Commit 22864256db67a1f85b7f09436612bd9633474dac

Authored by blueswir1
1 parent 71fb2348

Correct SCSI error reporting (Laurent Vivier)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5455 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 27 additions and 15 deletions
hw/scsi-disk.c
... ... @@ -34,6 +34,9 @@ do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
34 34 #define SENSE_HARDWARE_ERROR 4
35 35 #define SENSE_ILLEGAL_REQUEST 5
36 36  
  37 +#define STATUS_GOOD 0
  38 +#define STATUS_CHECK_CONDITION 2
  39 +
37 40 #define SCSI_DMA_BUF_SIZE 131072
38 41  
39 42 typedef struct SCSIRequest {
... ... @@ -124,15 +127,15 @@ static SCSIRequest *scsi_find_request(SCSIDeviceState *s, uint32_t tag)
124 127 }
125 128  
126 129 /* Helper function for command completion. */
127   -static void scsi_command_complete(SCSIRequest *r, int sense)
  130 +static void scsi_command_complete(SCSIRequest *r, int status, int sense)
128 131 {
129 132 SCSIDeviceState *s = r->dev;
130 133 uint32_t tag;
131   - DPRINTF("Command complete tag=0x%x sense=%d\n", r->tag, sense);
  134 + DPRINTF("Command complete tag=0x%x status=%d sense=%d\n", r->tag, status, sense);
132 135 s->sense = sense;
133 136 tag = r->tag;
134 137 scsi_remove_request(r);
135   - s->completion(s->opaque, SCSI_REASON_DONE, tag, sense);
  138 + s->completion(s->opaque, SCSI_REASON_DONE, tag, status);
136 139 }
137 140  
138 141 /* Cancel a pending data transfer. */
... ... @@ -157,7 +160,8 @@ static void scsi_read_complete(void * opaque, int ret)
157 160  
158 161 if (ret) {
159 162 DPRINTF("IO error\n");
160   - scsi_command_complete(r, SENSE_HARDWARE_ERROR);
  163 + s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 0);
  164 + scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NO_SENSE);
161 165 return;
162 166 }
163 167 DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->buf_len);
... ... @@ -176,7 +180,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
176 180 if (!r) {
177 181 BADF("Bad read tag 0x%x\n", tag);
178 182 /* ??? This is the wrong error. */
179   - scsi_command_complete(r, SENSE_HARDWARE_ERROR);
  183 + scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
180 184 return;
181 185 }
182 186 if (r->sector_count == (uint32_t)-1) {
... ... @@ -187,7 +191,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
187 191 }
188 192 DPRINTF("Read sector_count=%d\n", r->sector_count);
189 193 if (r->sector_count == 0) {
190   - scsi_command_complete(r, SENSE_NO_SENSE);
  194 + scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
191 195 return;
192 196 }
193 197  
... ... @@ -199,7 +203,7 @@ static void scsi_read_data(SCSIDevice *d, uint32_t tag)
199 203 r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n,
200 204 scsi_read_complete, r);
201 205 if (r->aiocb == NULL)
202   - scsi_command_complete(r, SENSE_HARDWARE_ERROR);
  206 + scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
203 207 r->sector += n;
204 208 r->sector_count -= n;
205 209 }
... ... @@ -217,7 +221,7 @@ static void scsi_write_complete(void * opaque, int ret)
217 221  
218 222 r->aiocb = NULL;
219 223 if (r->sector_count == 0) {
220   - scsi_command_complete(r, SENSE_NO_SENSE);
  224 + scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
221 225 } else {
222 226 len = r->sector_count * 512;
223 227 if (len > SCSI_DMA_BUF_SIZE) {
... ... @@ -241,7 +245,7 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
241 245 r = scsi_find_request(s, tag);
242 246 if (!r) {
243 247 BADF("Bad write tag 0x%x\n", tag);
244   - scsi_command_complete(r, SENSE_HARDWARE_ERROR);
  248 + scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR);
245 249 return 1;
246 250 }
247 251 if (r->aiocb)
... ... @@ -251,7 +255,8 @@ static int scsi_write_data(SCSIDevice *d, uint32_t tag)
251 255 r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n,
252 256 scsi_write_complete, r);
253 257 if (r->aiocb == NULL)
254   - scsi_command_complete(r, SENSE_HARDWARE_ERROR);
  258 + scsi_command_complete(r, STATUS_CHECK_CONDITION,
  259 + SENSE_HARDWARE_ERROR);
255 260 r->sector += n;
256 261 r->sector_count -= n;
257 262 } else {
... ... @@ -344,7 +349,8 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
344 349 if (lun || buf[1] >> 5) {
345 350 /* Only LUN 0 supported. */
346 351 DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
347   - goto fail;
  352 + if (command != 0x03 && command != 0x12) /* REQUEST SENSE and INQUIRY */
  353 + goto fail;
348 354 }
349 355 switch (command) {
350 356 case 0x0:
... ... @@ -487,7 +493,10 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
487 493 }
488 494 }
489 495 memset(outbuf, 0, 36);
490   - if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
  496 +
  497 + if (lun || buf[1] >> 5) {
  498 + outbuf[0] = 0x7f; /* LUN not supported */
  499 + } else if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
491 500 outbuf[0] = 5;
492 501 outbuf[1] = 0x80;
493 502 memcpy(&outbuf[16], "QEMU CD-ROM ", 16);
... ... @@ -670,7 +679,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
670 679 outbuf[7] = 0;
671 680 r->buf_len = 8;
672 681 } else {
673   - scsi_command_complete(r, SENSE_NOT_READY);
  682 + scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY);
674 683 return 0;
675 684 }
676 685 break;
... ... @@ -754,14 +763,17 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
754 763 outbuf[3] = 8;
755 764 r->buf_len = 16;
756 765 break;
  766 + case 0x2f:
  767 + DPRINTF("Verify (sector %d, count %d)\n", lba, len);
  768 + break;
757 769 default:
758 770 DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
759 771 fail:
760   - scsi_command_complete(r, SENSE_ILLEGAL_REQUEST);
  772 + scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_ILLEGAL_REQUEST);
761 773 return 0;
762 774 }
763 775 if (r->sector_count == 0 && r->buf_len == 0) {
764   - scsi_command_complete(r, SENSE_NO_SENSE);
  776 + scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE);
765 777 }
766 778 len = r->sector_count * 512 + r->buf_len;
767 779 if (is_write) {
... ...