]> Git Repo - qemu.git/blame - hw/scsi-disk.c
scsi: add read/write 16 commands.
[qemu.git] / hw / scsi-disk.c
CommitLineData
2e5d83bb
PB
1/*
2 * SCSI Device emulation
3 *
4 * Copyright (c) 2006 CodeSourcery.
5 * Based on code by Fabrice Bellard
6 *
7 * Written by Paul Brook
8 *
9 * This code is licenced under the LGPL.
a917d384
PB
10 *
11 * Note that this file only handles the SCSI architecture model and device
1d4db89c
AZ
12 * commands. Emulation of interface/link layer protocols is handled by
13 * the host adapter emulator.
2e5d83bb
PB
14 */
15
fa879c64
AL
16#include <qemu-common.h>
17#include <sysemu.h>
2e5d83bb
PB
18//#define DEBUG_SCSI
19
20#ifdef DEBUG_SCSI
001faf32
BS
21#define DPRINTF(fmt, ...) \
22do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
2e5d83bb 23#else
001faf32 24#define DPRINTF(fmt, ...) do {} while(0)
2e5d83bb
PB
25#endif
26
001faf32
BS
27#define BADF(fmt, ...) \
28do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
2e5d83bb 29
87ecb68b
PB
30#include "qemu-common.h"
31#include "block.h"
43b443b6 32#include "scsi.h"
0d65e1f8 33#include "scsi-defs.h"
22864256 34
f0f72ffe 35#define SCSI_DMA_BUF_SIZE 131072
57575058 36#define SCSI_MAX_INQUIRY_LEN 256
a917d384 37
ea8a5d7f
AL
38#define SCSI_REQ_STATUS_RETRY 0x01
39
d52affa7
GH
40typedef struct SCSIDiskState SCSIDiskState;
41
4c41d2ef
GH
42typedef struct SCSIDiskReq {
43 SCSIRequest req;
e035b43d 44 /* ??? We should probably keep track of whether the data transfer is
2e5d83bb 45 a read or a write. Currently we rely on the host getting it right. */
a917d384 46 /* Both sector and sector_count are in terms of qemu 512 byte blocks. */
e035b43d
AL
47 uint64_t sector;
48 uint32_t sector_count;
c87c0672
AL
49 struct iovec iov;
50 QEMUIOVector qiov;
ea8a5d7f 51 uint32_t status;
4c41d2ef 52} SCSIDiskReq;
a917d384 53
d52affa7 54struct SCSIDiskState
a917d384 55{
d52affa7 56 SCSIDevice qdev;
a917d384
PB
57 /* The qemu block layer uses a fixed 512 byte sector size.
58 This is the number of 512 byte blocks in a single scsi sector. */
59 int cluster_size;
274fb0e1 60 uint64_t max_lba;
213189ab 61 QEMUBH *bh;
2e5d83bb
PB
62};
63
89b08ae1 64static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
2e5d83bb 65{
89b08ae1 66 SCSIRequest *req;
4c41d2ef 67 SCSIDiskReq *r;
a917d384 68
89b08ae1
GH
69 req = scsi_req_alloc(sizeof(SCSIDiskReq), d, tag, lun);
70 r = DO_UPCAST(SCSIDiskReq, req, req);
9af99d98 71 r->iov.iov_base = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
a917d384 72 return r;
2e5d83bb
PB
73}
74
4c41d2ef 75static void scsi_remove_request(SCSIDiskReq *r)
4d611c9a 76{
9af99d98 77 qemu_free(r->iov.iov_base);
89b08ae1 78 scsi_req_free(&r->req);
4d611c9a
PB
79}
80
4c41d2ef 81static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag)
4d611c9a 82{
89b08ae1 83 return DO_UPCAST(SCSIDiskReq, req, scsi_req_find(&s->qdev, tag));
a917d384
PB
84}
85
ed3a34a3
GH
86static void scsi_req_set_status(SCSIRequest *req, int status, int sense_code)
87{
88 req->status = status;
89 scsi_dev_set_sense(req->dev, sense_code);
90}
91
a917d384 92/* Helper function for command completion. */
4c41d2ef 93static void scsi_command_complete(SCSIDiskReq *r, int status, int sense)
a917d384 94{
4c41d2ef
GH
95 DPRINTF("Command complete tag=0x%x status=%d sense=%d\n",
96 r->req.tag, status, sense);
ed3a34a3
GH
97 scsi_req_set_status(&r->req, status, sense);
98 scsi_req_complete(&r->req);
89b08ae1 99 scsi_remove_request(r);
4d611c9a
PB
100}
101
102/* Cancel a pending data transfer. */
8ccc2ace 103static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
4d611c9a 104{
d52affa7 105 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 106 SCSIDiskReq *r;
a917d384
PB
107 DPRINTF("Cancel tag=0x%x\n", tag);
108 r = scsi_find_request(s, tag);
109 if (r) {
4c41d2ef
GH
110 if (r->req.aiocb)
111 bdrv_aio_cancel(r->req.aiocb);
112 r->req.aiocb = NULL;
a917d384
PB
113 scsi_remove_request(r);
114 }
115}
116
117static void scsi_read_complete(void * opaque, int ret)
118{
4c41d2ef 119 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
a917d384
PB
120
121 if (ret) {
122 DPRINTF("IO error\n");
4c41d2ef 123 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, 0);
0d65e1f8 124 scsi_command_complete(r, CHECK_CONDITION, NO_SENSE);
4d611c9a
PB
125 return;
126 }
4c41d2ef 127 DPRINTF("Data ready tag=0x%x len=%" PRId64 "\n", r->req.tag, r->iov.iov_len);
a917d384 128
4c41d2ef 129 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
4d611c9a
PB
130}
131
a917d384 132/* Read more data from scsi device into buffer. */
8ccc2ace 133static void scsi_read_data(SCSIDevice *d, uint32_t tag)
2e5d83bb 134{
d52affa7 135 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 136 SCSIDiskReq *r;
2e5d83bb
PB
137 uint32_t n;
138
a917d384
PB
139 r = scsi_find_request(s, tag);
140 if (!r) {
141 BADF("Bad read tag 0x%x\n", tag);
b1fa7164 142 /* ??? This is the wrong error. */
0d65e1f8 143 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
a917d384 144 return;
2e5d83bb 145 }
a917d384 146 if (r->sector_count == (uint32_t)-1) {
0bf9e31a 147 DPRINTF("Read buf_len=%" PRId64 "\n", r->iov.iov_len);
a917d384 148 r->sector_count = 0;
4c41d2ef 149 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, r->iov.iov_len);
a917d384 150 return;
2e5d83bb 151 }
a917d384
PB
152 DPRINTF("Read sector_count=%d\n", r->sector_count);
153 if (r->sector_count == 0) {
0d65e1f8 154 scsi_command_complete(r, GOOD, NO_SENSE);
a917d384 155 return;
2e5d83bb
PB
156 }
157
a917d384
PB
158 n = r->sector_count;
159 if (n > SCSI_DMA_BUF_SIZE / 512)
160 n = SCSI_DMA_BUF_SIZE / 512;
161
c87c0672
AL
162 r->iov.iov_len = n * 512;
163 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
251882b7 164 r->req.aiocb = bdrv_aio_readv(s->qdev.dinfo->bdrv, r->sector, &r->qiov, n,
c87c0672 165 scsi_read_complete, r);
4c41d2ef 166 if (r->req.aiocb == NULL)
0d65e1f8 167 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
a917d384
PB
168 r->sector += n;
169 r->sector_count -= n;
2e5d83bb
PB
170}
171
4c41d2ef 172static int scsi_handle_write_error(SCSIDiskReq *r, int error)
ea8a5d7f 173{
4c41d2ef 174 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
251882b7 175 BlockInterfaceErrorAction action = drive_get_onerror(s->qdev.dinfo->bdrv);
ea8a5d7f
AL
176
177 if (action == BLOCK_ERR_IGNORE)
178 return 0;
179
180 if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
181 || action == BLOCK_ERR_STOP_ANY) {
182 r->status |= SCSI_REQ_STATUS_RETRY;
183 vm_stop(0);
184 } else {
0d65e1f8
GH
185 scsi_command_complete(r, CHECK_CONDITION,
186 HARDWARE_ERROR);
ea8a5d7f
AL
187 }
188
189 return 1;
190}
191
4d611c9a
PB
192static void scsi_write_complete(void * opaque, int ret)
193{
4c41d2ef 194 SCSIDiskReq *r = (SCSIDiskReq *)opaque;
a917d384 195 uint32_t len;
ea8a5d7f
AL
196 uint32_t n;
197
4c41d2ef 198 r->req.aiocb = NULL;
4d611c9a
PB
199
200 if (ret) {
ea8a5d7f
AL
201 if (scsi_handle_write_error(r, -ret))
202 return;
4d611c9a
PB
203 }
204
c87c0672 205 n = r->iov.iov_len / 512;
ea8a5d7f
AL
206 r->sector += n;
207 r->sector_count -= n;
a917d384 208 if (r->sector_count == 0) {
0d65e1f8 209 scsi_command_complete(r, GOOD, NO_SENSE);
a917d384
PB
210 } else {
211 len = r->sector_count * 512;
212 if (len > SCSI_DMA_BUF_SIZE) {
213 len = SCSI_DMA_BUF_SIZE;
214 }
c87c0672 215 r->iov.iov_len = len;
4c41d2ef
GH
216 DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, len);
217 r->req.bus->complete(r->req.bus, SCSI_REASON_DATA, r->req.tag, len);
4d611c9a 218 }
4d611c9a
PB
219}
220
4c41d2ef 221static void scsi_write_request(SCSIDiskReq *r)
ea8a5d7f 222{
4c41d2ef 223 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
ea8a5d7f
AL
224 uint32_t n;
225
c87c0672 226 n = r->iov.iov_len / 512;
ea8a5d7f 227 if (n) {
c87c0672 228 qemu_iovec_init_external(&r->qiov, &r->iov, 1);
251882b7 229 r->req.aiocb = bdrv_aio_writev(s->qdev.dinfo->bdrv, r->sector, &r->qiov, n,
c87c0672 230 scsi_write_complete, r);
4c41d2ef 231 if (r->req.aiocb == NULL)
0d65e1f8
GH
232 scsi_command_complete(r, CHECK_CONDITION,
233 HARDWARE_ERROR);
ea8a5d7f
AL
234 } else {
235 /* Invoke completion routine to fetch data from host. */
236 scsi_write_complete(r, 0);
237 }
238}
239
4d611c9a
PB
240/* Write data to a scsi device. Returns nonzero on failure.
241 The transfer may complete asynchronously. */
8ccc2ace 242static int scsi_write_data(SCSIDevice *d, uint32_t tag)
2e5d83bb 243{
d52affa7 244 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 245 SCSIDiskReq *r;
2e5d83bb 246
a917d384
PB
247 DPRINTF("Write data tag=0x%x\n", tag);
248 r = scsi_find_request(s, tag);
249 if (!r) {
250 BADF("Bad write tag 0x%x\n", tag);
0d65e1f8 251 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
2e5d83bb
PB
252 return 1;
253 }
ea8a5d7f 254
4c41d2ef 255 if (r->req.aiocb)
a917d384 256 BADF("Data transfer already in progress\n");
ea8a5d7f
AL
257
258 scsi_write_request(r);
2e5d83bb 259
a917d384
PB
260 return 0;
261}
2e5d83bb 262
213189ab 263static void scsi_dma_restart_bh(void *opaque)
ea8a5d7f 264{
d52affa7 265 SCSIDiskState *s = opaque;
9af99d98
GH
266 SCSIRequest *req;
267 SCSIDiskReq *r;
213189ab
MA
268
269 qemu_bh_delete(s->bh);
270 s->bh = NULL;
ea8a5d7f 271
9af99d98
GH
272 QTAILQ_FOREACH(req, &s->qdev.requests, next) {
273 r = DO_UPCAST(SCSIDiskReq, req, req);
ea8a5d7f
AL
274 if (r->status & SCSI_REQ_STATUS_RETRY) {
275 r->status &= ~SCSI_REQ_STATUS_RETRY;
276 scsi_write_request(r);
277 }
ea8a5d7f
AL
278 }
279}
280
213189ab
MA
281static void scsi_dma_restart_cb(void *opaque, int running, int reason)
282{
d52affa7 283 SCSIDiskState *s = opaque;
213189ab
MA
284
285 if (!running)
286 return;
287
288 if (!s->bh) {
289 s->bh = qemu_bh_new(scsi_dma_restart_bh, s);
290 qemu_bh_schedule(s->bh);
291 }
292}
293
a917d384 294/* Return a pointer to the data buffer. */
8ccc2ace 295static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
a917d384 296{
d52affa7 297 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
4c41d2ef 298 SCSIDiskReq *r;
2e5d83bb 299
a917d384
PB
300 r = scsi_find_request(s, tag);
301 if (!r) {
302 BADF("Bad buffer tag 0x%x\n", tag);
303 return NULL;
4d611c9a 304 }
3f4cb3d3 305 return (uint8_t *)r->iov.iov_base;
2e5d83bb
PB
306}
307
0b06c059
GH
308static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
309{
310 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
311 int buflen = 0;
312
313 if (req->cmd.buf[1] & 0x2) {
314 /* Command support data - optional, not implemented */
315 BADF("optional INQUIRY command support request not implemented\n");
316 return -1;
317 }
318
319 if (req->cmd.buf[1] & 0x1) {
320 /* Vital product data */
321 uint8_t page_code = req->cmd.buf[2];
322 if (req->cmd.xfer < 4) {
323 BADF("Error: Inquiry (EVPD[%02X]) buffer size %zd is "
324 "less than 4\n", page_code, req->cmd.xfer);
325 return -1;
326 }
327
328 if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM) {
329 outbuf[buflen++] = 5;
330 } else {
331 outbuf[buflen++] = 0;
332 }
333 outbuf[buflen++] = page_code ; // this page
334 outbuf[buflen++] = 0x00;
335
336 switch (page_code) {
337 case 0x00: /* Supported page codes, mandatory */
338 DPRINTF("Inquiry EVPD[Supported pages] "
339 "buffer size %zd\n", req->cmd.xfer);
340 outbuf[buflen++] = 3; // number of pages
341 outbuf[buflen++] = 0x00; // list of supported pages (this page)
342 outbuf[buflen++] = 0x80; // unit serial number
343 outbuf[buflen++] = 0x83; // device identification
344 break;
345
346 case 0x80: /* Device serial number, optional */
347 {
348 const char *serial = req->dev->dinfo->serial ?: "0";
349 int l = strlen(serial);
350
351 if (l > req->cmd.xfer)
352 l = req->cmd.xfer;
353 if (l > 20)
354 l = 20;
355
356 DPRINTF("Inquiry EVPD[Serial number] "
357 "buffer size %zd\n", req->cmd.xfer);
358 outbuf[buflen++] = l;
359 memcpy(outbuf+buflen, serial, l);
360 buflen += l;
361 break;
362 }
363
364 case 0x83: /* Device identification page, mandatory */
365 {
366 int max_len = 255 - 8;
367 int id_len = strlen(bdrv_get_device_name(bdrv));
368
369 if (id_len > max_len)
370 id_len = max_len;
371 DPRINTF("Inquiry EVPD[Device identification] "
372 "buffer size %zd\n", req->cmd.xfer);
373
374 outbuf[buflen++] = 3 + id_len;
375 outbuf[buflen++] = 0x2; // ASCII
376 outbuf[buflen++] = 0; // not officially assigned
377 outbuf[buflen++] = 0; // reserved
378 outbuf[buflen++] = id_len; // length of data following
379
380 memcpy(outbuf+buflen, bdrv_get_device_name(bdrv), id_len);
381 buflen += id_len;
382 break;
383 }
384 default:
385 BADF("Error: unsupported Inquiry (EVPD[%02X]) "
386 "buffer size %zd\n", page_code, req->cmd.xfer);
387 return -1;
388 }
389 /* done with EVPD */
390 return buflen;
391 }
392
393 /* Standard INQUIRY data */
394 if (req->cmd.buf[2] != 0) {
395 BADF("Error: Inquiry (STANDARD) page or code "
396 "is non-zero [%02X]\n", req->cmd.buf[2]);
397 return -1;
398 }
399
400 /* PAGE CODE == 0 */
401 if (req->cmd.xfer < 5) {
402 BADF("Error: Inquiry (STANDARD) buffer size %zd "
403 "is less than 5\n", req->cmd.xfer);
404 return -1;
405 }
406
407 if (req->cmd.xfer < 36) {
408 BADF("Error: Inquiry (STANDARD) buffer size %zd "
409 "is less than 36 (TODO: only 5 required)\n", req->cmd.xfer);
410 }
411
412 buflen = req->cmd.xfer;
413 if (buflen > SCSI_MAX_INQUIRY_LEN)
414 buflen = SCSI_MAX_INQUIRY_LEN;
415
416 memset(outbuf, 0, buflen);
417
418 if (req->lun || req->cmd.buf[1] >> 5) {
419 outbuf[0] = 0x7f; /* LUN not supported */
420 return buflen;
421 }
422
423 if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM) {
424 outbuf[0] = 5;
425 outbuf[1] = 0x80;
426 memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
427 } else {
428 outbuf[0] = 0;
429 memcpy(&outbuf[16], "QEMU HARDDISK ", 16);
430 }
431 memcpy(&outbuf[8], "QEMU ", 8);
432 memcpy(&outbuf[32], QEMU_VERSION, 4);
433 /* Identify device as SCSI-3 rev 1.
434 Some later commands are also implemented. */
435 outbuf[2] = 3;
436 outbuf[3] = 2; /* Format 2 */
437 outbuf[4] = buflen - 5; /* Additional Length = (Len - 1) - 4 */
438 /* Sync data transfer and TCQ. */
439 outbuf[7] = 0x10 | (req->bus->tcq ? 0x02 : 0);
440 return buflen;
441}
442
ebddfcbe
GH
443static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
444{
445 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
446 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
447 int cylinders, heads, secs;
448
449 switch (page) {
450 case 4: /* Rigid disk device geometry page. */
451 p[0] = 4;
452 p[1] = 0x16;
453 /* if a geometry hint is available, use it */
454 bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
455 p[2] = (cylinders >> 16) & 0xff;
456 p[3] = (cylinders >> 8) & 0xff;
457 p[4] = cylinders & 0xff;
458 p[5] = heads & 0xff;
459 /* Write precomp start cylinder, disabled */
460 p[6] = (cylinders >> 16) & 0xff;
461 p[7] = (cylinders >> 8) & 0xff;
462 p[8] = cylinders & 0xff;
463 /* Reduced current start cylinder, disabled */
464 p[9] = (cylinders >> 16) & 0xff;
465 p[10] = (cylinders >> 8) & 0xff;
466 p[11] = cylinders & 0xff;
467 /* Device step rate [ns], 200ns */
468 p[12] = 0;
469 p[13] = 200;
470 /* Landing zone cylinder */
471 p[14] = 0xff;
472 p[15] = 0xff;
473 p[16] = 0xff;
474 /* Medium rotation rate [rpm], 5400 rpm */
475 p[20] = (5400 >> 8) & 0xff;
476 p[21] = 5400 & 0xff;
477 return 0x16;
478
479 case 5: /* Flexible disk device geometry page. */
480 p[0] = 5;
481 p[1] = 0x1e;
482 /* Transfer rate [kbit/s], 5Mbit/s */
483 p[2] = 5000 >> 8;
484 p[3] = 5000 & 0xff;
485 /* if a geometry hint is available, use it */
486 bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
487 p[4] = heads & 0xff;
488 p[5] = secs & 0xff;
489 p[6] = s->cluster_size * 2;
490 p[8] = (cylinders >> 8) & 0xff;
491 p[9] = cylinders & 0xff;
492 /* Write precomp start cylinder, disabled */
493 p[10] = (cylinders >> 8) & 0xff;
494 p[11] = cylinders & 0xff;
495 /* Reduced current start cylinder, disabled */
496 p[12] = (cylinders >> 8) & 0xff;
497 p[13] = cylinders & 0xff;
498 /* Device step rate [100us], 100us */
499 p[14] = 0;
500 p[15] = 1;
501 /* Device step pulse width [us], 1us */
502 p[16] = 1;
503 /* Device head settle delay [100us], 100us */
504 p[17] = 0;
505 p[18] = 1;
506 /* Motor on delay [0.1s], 0.1s */
507 p[19] = 1;
508 /* Motor off delay [0.1s], 0.1s */
509 p[20] = 1;
510 /* Medium rotation rate [rpm], 5400 rpm */
511 p[28] = (5400 >> 8) & 0xff;
512 p[29] = 5400 & 0xff;
513 return 0x1e;
514
515 case 8: /* Caching page. */
516 p[0] = 8;
517 p[1] = 0x12;
518 if (bdrv_enable_write_cache(s->qdev.dinfo->bdrv)) {
519 p[2] = 4; /* WCE */
520 }
521 return 20;
522
523 case 0x2a: /* CD Capabilities and Mechanical Status page. */
524 if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM)
525 return 0;
526 p[0] = 0x2a;
527 p[1] = 0x14;
528 p[2] = 3; // CD-R & CD-RW read
529 p[3] = 0; // Writing not supported
530 p[4] = 0x7f; /* Audio, composite, digital out,
531 mode 2 form 1&2, multi session */
532 p[5] = 0xff; /* CD DA, DA accurate, RW supported,
533 RW corrected, C2 errors, ISRC,
534 UPC, Bar code */
535 p[6] = 0x2d | (bdrv_is_locked(s->qdev.dinfo->bdrv)? 2 : 0);
536 /* Locking supported, jumper present, eject, tray */
537 p[7] = 0; /* no volume & mute control, no
538 changer */
539 p[8] = (50 * 176) >> 8; // 50x read speed
540 p[9] = (50 * 176) & 0xff;
541 p[10] = 0 >> 8; // No volume
542 p[11] = 0 & 0xff;
543 p[12] = 2048 >> 8; // 2M buffer
544 p[13] = 2048 & 0xff;
545 p[14] = (16 * 176) >> 8; // 16x read speed current
546 p[15] = (16 * 176) & 0xff;
547 p[18] = (16 * 176) >> 8; // 16x write speed
548 p[19] = (16 * 176) & 0xff;
549 p[20] = (16 * 176) >> 8; // 16x write speed current
550 p[21] = (16 * 176) & 0xff;
551 return 22;
552
553 default:
554 return 0;
555 }
556}
557
558static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
559{
560 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
561 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
562 uint64_t nb_sectors;
563 int page, dbd, buflen;
564 uint8_t *p;
565
566 dbd = req->cmd.buf[1] & 0x8;
567 page = req->cmd.buf[2] & 0x3f;
568 DPRINTF("Mode Sense (page %d, len %zd)\n", page, req->cmd.xfer);
569 memset(outbuf, 0, req->cmd.xfer);
570 p = outbuf;
571
572 p[1] = 0; /* Default media type. */
573 p[3] = 0; /* Block descriptor length. */
574 if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM ||
575 bdrv_is_read_only(bdrv)) {
576 p[2] = 0x80; /* Readonly. */
577 }
578 p += 4;
579
580 bdrv_get_geometry(bdrv, &nb_sectors);
581 if ((~dbd) & nb_sectors) {
582 outbuf[3] = 8; /* Block descriptor length */
583 nb_sectors /= s->cluster_size;
584 nb_sectors--;
585 if (nb_sectors > 0xffffff)
586 nb_sectors = 0xffffff;
587 p[0] = 0; /* media density code */
588 p[1] = (nb_sectors >> 16) & 0xff;
589 p[2] = (nb_sectors >> 8) & 0xff;
590 p[3] = nb_sectors & 0xff;
591 p[4] = 0; /* reserved */
592 p[5] = 0; /* bytes 5-7 are the sector size in bytes */
593 p[6] = s->cluster_size * 2;
594 p[7] = 0;
595 p += 8;
596 }
597
598 switch (page) {
599 case 0x04:
600 case 0x05:
601 case 0x08:
602 case 0x2a:
603 p += mode_sense_page(req, page, p);
604 break;
605 case 0x3f:
606 p += mode_sense_page(req, 0x08, p);
607 p += mode_sense_page(req, 0x2a, p);
608 break;
609 }
610
611 buflen = p - outbuf;
612 outbuf[0] = buflen - 4;
613 if (buflen > req->cmd.xfer)
614 buflen = req->cmd.xfer;
615 return buflen;
616}
617
02880f43
GH
618static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
619{
620 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
621 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
622 int start_track, format, msf, toclen;
623 uint64_t nb_sectors;
624
625 msf = req->cmd.buf[1] & 2;
626 format = req->cmd.buf[2] & 0xf;
627 start_track = req->cmd.buf[6];
628 bdrv_get_geometry(bdrv, &nb_sectors);
629 DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
630 nb_sectors /= s->cluster_size;
631 switch (format) {
632 case 0:
633 toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track);
634 break;
635 case 1:
636 /* multi session : only a single session defined */
637 toclen = 12;
638 memset(outbuf, 0, 12);
639 outbuf[1] = 0x0a;
640 outbuf[2] = 0x01;
641 outbuf[3] = 0x01;
642 break;
643 case 2:
644 toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track);
645 break;
646 default:
647 return -1;
648 }
649 if (toclen > req->cmd.xfer)
650 toclen = req->cmd.xfer;
651 return toclen;
652}
653
aa5dbdc1
GH
654static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
655{
e7e25e32 656 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
aa5dbdc1 657 BlockDriverState *bdrv = req->dev->dinfo->bdrv;
e7e25e32 658 uint64_t nb_sectors;
aa5dbdc1
GH
659 int buflen = 0;
660
661 switch (req->cmd.buf[0]) {
662 case TEST_UNIT_READY:
663 if (!bdrv_is_inserted(bdrv))
664 goto not_ready;
665 break;
51ad87c9
GH
666 case REQUEST_SENSE:
667 if (req->cmd.xfer < 4)
668 goto illegal_request;
669 memset(outbuf, 0, 4);
670 buflen = 4;
671 if (req->dev->sense.key == NOT_READY && req->cmd.xfer >= 18) {
672 memset(outbuf, 0, 18);
673 buflen = 18;
674 outbuf[7] = 10;
675 /* asc 0x3a, ascq 0: Medium not present */
676 outbuf[12] = 0x3a;
677 outbuf[13] = 0;
678 }
679 outbuf[0] = 0xf0;
680 outbuf[1] = 0;
681 outbuf[2] = req->dev->sense.key;
682 scsi_dev_clear_sense(req->dev);
683 break;
0b06c059
GH
684 case INQUIRY:
685 buflen = scsi_disk_emulate_inquiry(req, outbuf);
686 if (buflen < 0)
687 goto illegal_request;
688 break;
ebddfcbe
GH
689 case MODE_SENSE:
690 case MODE_SENSE_10:
691 buflen = scsi_disk_emulate_mode_sense(req, outbuf);
692 if (buflen < 0)
693 goto illegal_request;
694 break;
02880f43
GH
695 case READ_TOC:
696 buflen = scsi_disk_emulate_read_toc(req, outbuf);
697 if (buflen < 0)
698 goto illegal_request;
699 break;
3d53ba18
GH
700 case RESERVE:
701 if (req->cmd.buf[1] & 1)
702 goto illegal_request;
703 break;
704 case RESERVE_10:
705 if (req->cmd.buf[1] & 3)
706 goto illegal_request;
707 break;
708 case RELEASE:
709 if (req->cmd.buf[1] & 1)
710 goto illegal_request;
711 break;
712 case RELEASE_10:
713 if (req->cmd.buf[1] & 3)
714 goto illegal_request;
715 break;
8d3628ff
GH
716 case START_STOP:
717 if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM && (req->cmd.buf[4] & 2)) {
718 /* load/eject medium */
719 bdrv_eject(bdrv, !(req->cmd.buf[4] & 1));
720 }
721 break;
c68b9f34
GH
722 case ALLOW_MEDIUM_REMOVAL:
723 bdrv_set_locked(bdrv, req->cmd.buf[4] & 1);
724 break;
e7e25e32
GH
725 case READ_CAPACITY:
726 /* The normal LEN field for this command is zero. */
727 memset(outbuf, 0, 8);
728 bdrv_get_geometry(bdrv, &nb_sectors);
729 if (!nb_sectors)
730 goto not_ready;
731 nb_sectors /= s->cluster_size;
732 /* Returned value is the address of the last sector. */
733 nb_sectors--;
734 /* Remember the new size for read/write sanity checking. */
735 s->max_lba = nb_sectors;
736 /* Clip to 2TB, instead of returning capacity modulo 2TB. */
737 if (nb_sectors > UINT32_MAX)
738 nb_sectors = UINT32_MAX;
739 outbuf[0] = (nb_sectors >> 24) & 0xff;
740 outbuf[1] = (nb_sectors >> 16) & 0xff;
741 outbuf[2] = (nb_sectors >> 8) & 0xff;
742 outbuf[3] = nb_sectors & 0xff;
743 outbuf[4] = 0;
744 outbuf[5] = 0;
745 outbuf[6] = s->cluster_size * 2;
746 outbuf[7] = 0;
747 buflen = 8;
748 break;
fc903943
GH
749 case SYNCHRONIZE_CACHE:
750 bdrv_flush(bdrv);
751 break;
38215553
GH
752 case GET_CONFIGURATION:
753 memset(outbuf, 0, 8);
754 /* ??? This should probably return much more information. For now
755 just return the basic header indicating the CD-ROM profile. */
756 outbuf[7] = 8; // CD-ROM
757 buflen = 8;
758 break;
5dd90e2a
GH
759 case SERVICE_ACTION_IN:
760 /* Service Action In subcommands. */
761 if ((req->cmd.buf[1] & 31) == 0x10) {
762 DPRINTF("SAI READ CAPACITY(16)\n");
763 memset(outbuf, 0, req->cmd.xfer);
764 bdrv_get_geometry(bdrv, &nb_sectors);
765 if (!nb_sectors)
766 goto not_ready;
767 nb_sectors /= s->cluster_size;
768 /* Returned value is the address of the last sector. */
769 nb_sectors--;
770 /* Remember the new size for read/write sanity checking. */
771 s->max_lba = nb_sectors;
772 outbuf[0] = (nb_sectors >> 56) & 0xff;
773 outbuf[1] = (nb_sectors >> 48) & 0xff;
774 outbuf[2] = (nb_sectors >> 40) & 0xff;
775 outbuf[3] = (nb_sectors >> 32) & 0xff;
776 outbuf[4] = (nb_sectors >> 24) & 0xff;
777 outbuf[5] = (nb_sectors >> 16) & 0xff;
778 outbuf[6] = (nb_sectors >> 8) & 0xff;
779 outbuf[7] = nb_sectors & 0xff;
780 outbuf[8] = 0;
781 outbuf[9] = 0;
782 outbuf[10] = s->cluster_size * 2;
783 outbuf[11] = 0;
784 /* Protection, exponent and lowest lba field left blank. */
785 buflen = req->cmd.xfer;
786 break;
787 }
788 DPRINTF("Unsupported Service Action In\n");
789 goto illegal_request;
39ec9a50
GH
790 case REPORT_LUNS:
791 if (req->cmd.xfer < 16)
792 goto illegal_request;
793 memset(outbuf, 0, 16);
794 outbuf[3] = 8;
795 buflen = 16;
796 break;
88f8a5ed
GH
797 case VERIFY:
798 break;
aa5dbdc1
GH
799 default:
800 goto illegal_request;
801 }
802 scsi_req_set_status(req, GOOD, NO_SENSE);
803 return buflen;
804
805not_ready:
806 scsi_req_set_status(req, CHECK_CONDITION, NOT_READY);
807 return 0;
808
809illegal_request:
810 scsi_req_set_status(req, CHECK_CONDITION, ILLEGAL_REQUEST);
811 return 0;
812}
813
2e5d83bb
PB
814/* Execute a scsi command. Returns the length of the data expected by the
815 command. This will be Positive for data transfers from the device
816 (eg. disk reads), negative for transfers to the device (eg. disk writes),
817 and zero if the command does not transfer any data. */
818
8ccc2ace
TS
819static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
820 uint8_t *buf, int lun)
2e5d83bb 821{
d52affa7 822 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
86106e59 823 uint64_t lba;
2e5d83bb
PB
824 uint32_t len;
825 int cmdlen;
826 int is_write;
a917d384
PB
827 uint8_t command;
828 uint8_t *outbuf;
4c41d2ef 829 SCSIDiskReq *r;
aa5dbdc1 830 int rc;
a917d384
PB
831
832 command = buf[0];
833 r = scsi_find_request(s, tag);
834 if (r) {
835 BADF("Tag 0x%x already in use\n", tag);
8ccc2ace 836 scsi_cancel_io(d, tag);
a917d384
PB
837 }
838 /* ??? Tags are not unique for different luns. We only implement a
839 single lun, so this should not matter. */
89b08ae1 840 r = scsi_new_request(d, tag, lun);
3f4cb3d3 841 outbuf = (uint8_t *)r->iov.iov_base;
2e5d83bb 842 is_write = 0;
a917d384
PB
843 DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
844 switch (command >> 5) {
2e5d83bb 845 case 0:
86106e59
AL
846 lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
847 (((uint64_t) buf[1] & 0x1f) << 16);
2e5d83bb
PB
848 len = buf[4];
849 cmdlen = 6;
850 break;
851 case 1:
852 case 2:
86106e59
AL
853 lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
854 ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
2e5d83bb
PB
855 len = buf[8] | (buf[7] << 8);
856 cmdlen = 10;
857 break;
858 case 4:
86106e59
AL
859 lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
860 ((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
861 ((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
862 ((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
2e5d83bb
PB
863 len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
864 cmdlen = 16;
865 break;
866 case 5:
86106e59
AL
867 lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
868 ((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
2e5d83bb
PB
869 len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
870 cmdlen = 12;
871 break;
872 default:
a917d384 873 BADF("Unsupported command length, command %x\n", command);
2e5d83bb
PB
874 goto fail;
875 }
876#ifdef DEBUG_SCSI
877 {
878 int i;
879 for (i = 1; i < cmdlen; i++) {
880 printf(" 0x%02x", buf[i]);
881 }
882 printf("\n");
883 }
884#endif
aa5dbdc1
GH
885
886 if (scsi_req_parse(&r->req, buf) != 0) {
887 BADF("Unsupported command length, command %x\n", command);
888 goto fail;
889 }
890 assert(r->req.cmd.len == cmdlen);
891 assert(r->req.cmd.lba == lba);
892
0fc5c15a 893 if (lun || buf[1] >> 5) {
2e5d83bb 894 /* Only LUN 0 supported. */
0fc5c15a 895 DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
ebf46023 896 if (command != REQUEST_SENSE && command != INQUIRY)
22864256 897 goto fail;
2e5d83bb 898 }
a917d384 899 switch (command) {
ebf46023 900 case TEST_UNIT_READY:
51ad87c9 901 case REQUEST_SENSE:
0b06c059 902 case INQUIRY:
ebddfcbe
GH
903 case MODE_SENSE:
904 case MODE_SENSE_10:
3d53ba18
GH
905 case RESERVE:
906 case RESERVE_10:
907 case RELEASE:
908 case RELEASE_10:
8d3628ff 909 case START_STOP:
c68b9f34 910 case ALLOW_MEDIUM_REMOVAL:
e7e25e32 911 case READ_CAPACITY:
fc903943 912 case SYNCHRONIZE_CACHE:
02880f43 913 case READ_TOC:
38215553 914 case GET_CONFIGURATION:
5dd90e2a 915 case SERVICE_ACTION_IN:
39ec9a50 916 case REPORT_LUNS:
88f8a5ed 917 case VERIFY:
aa5dbdc1
GH
918 rc = scsi_disk_emulate_command(&r->req, outbuf);
919 if (rc > 0) {
920 r->iov.iov_len = rc;
921 } else {
922 scsi_req_complete(&r->req);
923 scsi_remove_request(r);
0b06c059 924 return 0;
aa5dbdc1 925 }
0b06c059 926 break;
ebf46023
GH
927 case READ_6:
928 case READ_10:
bd536cf3
GH
929 case READ_12:
930 case READ_16:
0bf9e31a 931 DPRINTF("Read (sector %" PRId64 ", count %d)\n", lba, len);
274fb0e1
AL
932 if (lba > s->max_lba)
933 goto illegal_lba;
a917d384
PB
934 r->sector = lba * s->cluster_size;
935 r->sector_count = len * s->cluster_size;
2e5d83bb 936 break;
ebf46023
GH
937 case WRITE_6:
938 case WRITE_10:
bd536cf3
GH
939 case WRITE_12:
940 case WRITE_16:
0bf9e31a 941 DPRINTF("Write (sector %" PRId64 ", count %d)\n", lba, len);
274fb0e1
AL
942 if (lba > s->max_lba)
943 goto illegal_lba;
a917d384
PB
944 r->sector = lba * s->cluster_size;
945 r->sector_count = len * s->cluster_size;
2e5d83bb
PB
946 is_write = 1;
947 break;
2e5d83bb
PB
948 default:
949 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
950 fail:
0d65e1f8 951 scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST);
2e5d83bb 952 return 0;
274fb0e1 953 illegal_lba:
0d65e1f8 954 scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
274fb0e1 955 return 0;
2e5d83bb 956 }
c87c0672 957 if (r->sector_count == 0 && r->iov.iov_len == 0) {
0d65e1f8 958 scsi_command_complete(r, GOOD, NO_SENSE);
a917d384 959 }
c87c0672 960 len = r->sector_count * 512 + r->iov.iov_len;
a917d384
PB
961 if (is_write) {
962 return -len;
963 } else {
964 if (!r->sector_count)
965 r->sector_count = -1;
966 return len;
2e5d83bb 967 }
2e5d83bb
PB
968}
969
56a14938
GH
970static void scsi_destroy(SCSIDevice *dev)
971{
972 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
9af99d98 973 SCSIDiskReq *r;
56a14938 974
9af99d98
GH
975 while (!QTAILQ_EMPTY(&s->qdev.requests)) {
976 r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests));
977 scsi_remove_request(r);
978 }
251882b7 979 drive_uninit(s->qdev.dinfo);
56a14938
GH
980}
981
d52affa7 982static int scsi_disk_initfn(SCSIDevice *dev)
2e5d83bb 983{
d52affa7 984 SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
274fb0e1 985 uint64_t nb_sectors;
2e5d83bb 986
251882b7 987 if (!s->qdev.dinfo || !s->qdev.dinfo->bdrv) {
d52affa7
GH
988 qemu_error("scsi-disk: drive property not set\n");
989 return -1;
990 }
991
251882b7 992 if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
7c22dd52 993 s->cluster_size = 4;
2e5d83bb 994 } else {
7c22dd52 995 s->cluster_size = 1;
2e5d83bb 996 }
b07995e3 997 s->qdev.blocksize = 512 * s->cluster_size;
91376656 998 s->qdev.type = TYPE_DISK;
251882b7 999 bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
274fb0e1
AL
1000 nb_sectors /= s->cluster_size;
1001 if (nb_sectors)
1002 nb_sectors--;
1003 s->max_lba = nb_sectors;
ea8a5d7f 1004 qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
d52affa7
GH
1005 return 0;
1006}
1007
1008static SCSIDeviceInfo scsi_disk_info = {
1009 .qdev.name = "scsi-disk",
1010 .qdev.desc = "virtual scsi disk or cdrom",
1011 .qdev.size = sizeof(SCSIDiskState),
1012 .init = scsi_disk_initfn,
56a14938 1013 .destroy = scsi_destroy,
d52affa7
GH
1014 .send_command = scsi_send_command,
1015 .read_data = scsi_read_data,
1016 .write_data = scsi_write_data,
1017 .cancel_io = scsi_cancel_io,
1018 .get_buf = scsi_get_buf,
1019 .qdev.props = (Property[]) {
251882b7 1020 DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.dinfo),
d52affa7
GH
1021 DEFINE_PROP_END_OF_LIST(),
1022 },
1023};
1024
1025static void scsi_disk_register_devices(void)
1026{
1027 scsi_qdev_register(&scsi_disk_info);
8ccc2ace 1028}
d52affa7 1029device_init(scsi_disk_register_devices)
This page took 0.52686 seconds and 4 git commands to generate.