diff --git a/hw/esp.c b/hw/esp.c index 68e15dd814643995c291efef7fa9ef63c8fa86bf..908767943d4b24e8d8f7a5b7a3765cd463a6466b 100644 --- a/hw/esp.c +++ b/hw/esp.c @@ -55,6 +55,7 @@ struct ESPState { uint32_t ti_size; uint32_t ti_rptr, ti_wptr; uint8_t ti_buf[TI_BUFSZ]; + int sense; int dma; SCSIDevice *scsi_dev[MAX_DISKS]; SCSIDevice *current_dev; @@ -84,6 +85,7 @@ static void handle_satn(ESPState *s) uint32_t dmaptr, dmalen; int target; int32_t datalen; + int lun; dmalen = s->wregs[0] | (s->wregs[1] << 8); target = s->wregs[4] & 7; @@ -98,6 +100,8 @@ static void handle_satn(ESPState *s) memcpy(&buf[1], s->ti_buf, dmalen); dmalen++; } + DPRINTF("busid 0x%x\n", buf[0]); + lun = buf[0] & 7; s->ti_size = 0; s->ti_rptr = 0; @@ -113,7 +117,7 @@ static void handle_satn(ESPState *s) return; } s->current_dev = s->scsi_dev[target]; - datalen = scsi_send_command(s->current_dev, 0, &buf[1]); + datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun); if (datalen == 0) { s->ti_size = 0; } else { @@ -132,34 +136,33 @@ static void handle_satn(ESPState *s) pic_set_irq(s->irq, 1); } -static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len) +static void write_response(ESPState *s) { uint32_t dmaptr; - DPRINTF("Transfer status len %d\n", len); + DPRINTF("Transfer status (sense=%d)\n", s->sense); + s->ti_buf[0] = s->sense; + s->ti_buf[1] = 0; if (s->dma) { dmaptr = iommu_translate(s->espdmaregs[1]); DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r'); - cpu_physical_memory_write(dmaptr, buf, len); + cpu_physical_memory_write(dmaptr, s->ti_buf, 2); s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; s->rregs[5] = INTR_BS | INTR_FC; s->rregs[6] = SEQ_CD; } else { - memcpy(s->ti_buf, buf, len); - s->ti_size = len; + s->ti_size = 2; s->ti_rptr = 0; s->ti_wptr = 0; - s->rregs[7] = len; + s->rregs[7] = 2; } s->espdmaregs[0] |= DMA_INTR; pic_set_irq(s->irq, 1); } -static const uint8_t okbuf[] = {0, 0}; - -static void esp_command_complete(void *opaque, uint32_t tag, int fail) +static void esp_command_complete(void *opaque, uint32_t tag, int sense) { ESPState *s = (ESPState *)opaque; @@ -167,9 +170,9 @@ static void esp_command_complete(void *opaque, uint32_t tag, int fail) if (s->ti_size != 0) DPRINTF("SCSI command completed unexpectedly\n"); s->ti_size = 0; - /* ??? Report failures. */ - if (fail) + if (sense) DPRINTF("Command failed\n"); + s->sense = sense; s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; } @@ -333,11 +336,11 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) break; case 0x11: DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val); - dma_write(s, okbuf, 2); + write_response(s); break; case 0x12: DPRINTF("Message Accepted (%2.2x)\n", val); - dma_write(s, okbuf, 2); + write_response(s); s->rregs[5] = INTR_DC; s->rregs[6] = 0; break; diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 9285c18cea07fb957e88dbbba05f0b823559631e..c15486b2bf60f9b880c4ff5704ebf1152c777df0 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -53,7 +53,7 @@ struct SCSIDevice static void scsi_command_complete(SCSIDevice *s, int sense) { s->sense = sense; - s->completion(s->opaque, s->tag, sense != SENSE_NO_SENSE); + s->completion(s->opaque, s->tag, sense); } /* Read data from a scsi device. Returns nonzero on failure. */ @@ -175,7 +175,7 @@ int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len) (eg. disk reads), negative for transfers to the device (eg. disk writes), and zero if the command does not transfer any data. */ -int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf) +int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun) { int64_t nb_sectors; uint32_t lba; @@ -225,8 +225,9 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf) printf("\n"); } #endif - if (buf[1] >> 5) { + if (lun || buf[1] >> 5) { /* Only LUN 0 supported. */ + DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5); goto fail; } switch (s->command) { diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 6b4cb81eb9adcd6044a577e9312908326a054755..bcca6d4ed50f40769d18901d7a121242ba64af81 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -295,7 +295,7 @@ static int usb_msd_handle_data(USBDevice *dev, int pid, uint8_t devep, } DPRINTF("Command tag 0x%x flags %08x len %d data %d\n", s->tag, cbw.flags, cbw.cmd_len, s->data_len); - scsi_send_command(s->scsi_dev, s->tag, cbw.cmd); + scsi_send_command(s->scsi_dev, s->tag, cbw.cmd, 0); ret = len; break; diff --git a/vl.h b/vl.h index f8414ea3fd692df422c35ac20e3a1e74a45a7e9b..26e009fdc47f992f34d5a7327bcc061d78e077bf 100644 --- a/vl.h +++ b/vl.h @@ -1044,7 +1044,7 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, void *opaque); void scsi_disk_destroy(SCSIDevice *s); -int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf); +int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun); int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len); int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len);