Commit 0fc5c15a4fad2dac00126c802554d9ca33c4ccc7
1 parent
cac782d4
SCSI lun probing fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1945 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
23 additions
and
19 deletions
hw/esp.c
| ... | ... | @@ -55,6 +55,7 @@ struct ESPState { |
| 55 | 55 | uint32_t ti_size; |
| 56 | 56 | uint32_t ti_rptr, ti_wptr; |
| 57 | 57 | uint8_t ti_buf[TI_BUFSZ]; |
| 58 | + int sense; | |
| 58 | 59 | int dma; |
| 59 | 60 | SCSIDevice *scsi_dev[MAX_DISKS]; |
| 60 | 61 | SCSIDevice *current_dev; |
| ... | ... | @@ -84,6 +85,7 @@ static void handle_satn(ESPState *s) |
| 84 | 85 | uint32_t dmaptr, dmalen; |
| 85 | 86 | int target; |
| 86 | 87 | int32_t datalen; |
| 88 | + int lun; | |
| 87 | 89 | |
| 88 | 90 | dmalen = s->wregs[0] | (s->wregs[1] << 8); |
| 89 | 91 | target = s->wregs[4] & 7; |
| ... | ... | @@ -98,6 +100,8 @@ static void handle_satn(ESPState *s) |
| 98 | 100 | memcpy(&buf[1], s->ti_buf, dmalen); |
| 99 | 101 | dmalen++; |
| 100 | 102 | } |
| 103 | + DPRINTF("busid 0x%x\n", buf[0]); | |
| 104 | + lun = buf[0] & 7; | |
| 101 | 105 | |
| 102 | 106 | s->ti_size = 0; |
| 103 | 107 | s->ti_rptr = 0; |
| ... | ... | @@ -113,7 +117,7 @@ static void handle_satn(ESPState *s) |
| 113 | 117 | return; |
| 114 | 118 | } |
| 115 | 119 | s->current_dev = s->scsi_dev[target]; |
| 116 | - datalen = scsi_send_command(s->current_dev, 0, &buf[1]); | |
| 120 | + datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun); | |
| 117 | 121 | if (datalen == 0) { |
| 118 | 122 | s->ti_size = 0; |
| 119 | 123 | } else { |
| ... | ... | @@ -132,34 +136,33 @@ static void handle_satn(ESPState *s) |
| 132 | 136 | pic_set_irq(s->irq, 1); |
| 133 | 137 | } |
| 134 | 138 | |
| 135 | -static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len) | |
| 139 | +static void write_response(ESPState *s) | |
| 136 | 140 | { |
| 137 | 141 | uint32_t dmaptr; |
| 138 | 142 | |
| 139 | - DPRINTF("Transfer status len %d\n", len); | |
| 143 | + DPRINTF("Transfer status (sense=%d)\n", s->sense); | |
| 144 | + s->ti_buf[0] = s->sense; | |
| 145 | + s->ti_buf[1] = 0; | |
| 140 | 146 | if (s->dma) { |
| 141 | 147 | dmaptr = iommu_translate(s->espdmaregs[1]); |
| 142 | 148 | DPRINTF("DMA Direction: %c\n", |
| 143 | 149 | s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r'); |
| 144 | - cpu_physical_memory_write(dmaptr, buf, len); | |
| 150 | + cpu_physical_memory_write(dmaptr, s->ti_buf, 2); | |
| 145 | 151 | s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; |
| 146 | 152 | s->rregs[5] = INTR_BS | INTR_FC; |
| 147 | 153 | s->rregs[6] = SEQ_CD; |
| 148 | 154 | } else { |
| 149 | - memcpy(s->ti_buf, buf, len); | |
| 150 | - s->ti_size = len; | |
| 155 | + s->ti_size = 2; | |
| 151 | 156 | s->ti_rptr = 0; |
| 152 | 157 | s->ti_wptr = 0; |
| 153 | - s->rregs[7] = len; | |
| 158 | + s->rregs[7] = 2; | |
| 154 | 159 | } |
| 155 | 160 | s->espdmaregs[0] |= DMA_INTR; |
| 156 | 161 | pic_set_irq(s->irq, 1); |
| 157 | 162 | |
| 158 | 163 | } |
| 159 | 164 | |
| 160 | -static const uint8_t okbuf[] = {0, 0}; | |
| 161 | - | |
| 162 | -static void esp_command_complete(void *opaque, uint32_t tag, int fail) | |
| 165 | +static void esp_command_complete(void *opaque, uint32_t tag, int sense) | |
| 163 | 166 | { |
| 164 | 167 | ESPState *s = (ESPState *)opaque; |
| 165 | 168 | |
| ... | ... | @@ -167,9 +170,9 @@ static void esp_command_complete(void *opaque, uint32_t tag, int fail) |
| 167 | 170 | if (s->ti_size != 0) |
| 168 | 171 | DPRINTF("SCSI command completed unexpectedly\n"); |
| 169 | 172 | s->ti_size = 0; |
| 170 | - /* ??? Report failures. */ | |
| 171 | - if (fail) | |
| 173 | + if (sense) | |
| 172 | 174 | DPRINTF("Command failed\n"); |
| 175 | + s->sense = sense; | |
| 173 | 176 | s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; |
| 174 | 177 | } |
| 175 | 178 | |
| ... | ... | @@ -333,11 +336,11 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
| 333 | 336 | break; |
| 334 | 337 | case 0x11: |
| 335 | 338 | DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val); |
| 336 | - dma_write(s, okbuf, 2); | |
| 339 | + write_response(s); | |
| 337 | 340 | break; |
| 338 | 341 | case 0x12: |
| 339 | 342 | DPRINTF("Message Accepted (%2.2x)\n", val); |
| 340 | - dma_write(s, okbuf, 2); | |
| 343 | + write_response(s); | |
| 341 | 344 | s->rregs[5] = INTR_DC; |
| 342 | 345 | s->rregs[6] = 0; |
| 343 | 346 | break; | ... | ... |
hw/scsi-disk.c
| ... | ... | @@ -53,7 +53,7 @@ struct SCSIDevice |
| 53 | 53 | static void scsi_command_complete(SCSIDevice *s, int sense) |
| 54 | 54 | { |
| 55 | 55 | s->sense = sense; |
| 56 | - s->completion(s->opaque, s->tag, sense != SENSE_NO_SENSE); | |
| 56 | + s->completion(s->opaque, s->tag, sense); | |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | 59 | /* 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) |
| 175 | 175 | (eg. disk reads), negative for transfers to the device (eg. disk writes), |
| 176 | 176 | and zero if the command does not transfer any data. */ |
| 177 | 177 | |
| 178 | -int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf) | |
| 178 | +int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun) | |
| 179 | 179 | { |
| 180 | 180 | int64_t nb_sectors; |
| 181 | 181 | uint32_t lba; |
| ... | ... | @@ -225,8 +225,9 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf) |
| 225 | 225 | printf("\n"); |
| 226 | 226 | } |
| 227 | 227 | #endif |
| 228 | - if (buf[1] >> 5) { | |
| 228 | + if (lun || buf[1] >> 5) { | |
| 229 | 229 | /* Only LUN 0 supported. */ |
| 230 | + DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5); | |
| 230 | 231 | goto fail; |
| 231 | 232 | } |
| 232 | 233 | switch (s->command) { | ... | ... |
hw/usb-msd.c
| ... | ... | @@ -295,7 +295,7 @@ static int usb_msd_handle_data(USBDevice *dev, int pid, uint8_t devep, |
| 295 | 295 | } |
| 296 | 296 | DPRINTF("Command tag 0x%x flags %08x len %d data %d\n", |
| 297 | 297 | s->tag, cbw.flags, cbw.cmd_len, s->data_len); |
| 298 | - scsi_send_command(s->scsi_dev, s->tag, cbw.cmd); | |
| 298 | + scsi_send_command(s->scsi_dev, s->tag, cbw.cmd, 0); | |
| 299 | 299 | ret = len; |
| 300 | 300 | break; |
| 301 | 301 | ... | ... |
vl.h
| ... | ... | @@ -1044,7 +1044,7 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, |
| 1044 | 1044 | void *opaque); |
| 1045 | 1045 | void scsi_disk_destroy(SCSIDevice *s); |
| 1046 | 1046 | |
| 1047 | -int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf); | |
| 1047 | +int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun); | |
| 1048 | 1048 | int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len); |
| 1049 | 1049 | int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len); |
| 1050 | 1050 | ... | ... |