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