Revision 0fc5c15a
b/hw/esp.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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; |
b/hw/scsi-disk.c | ||
---|---|---|
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 | 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 | 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) { |
b/hw/usb-msd.c | ||
---|---|---|
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 |
|
b/vl.h | ||
---|---|---|
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 |
|
Also available in: Unified diff