Commit 8ccc2ace5628720347017c98a43b47b2ba23cf15

Authored by ths
1 parent cf6d9118

SCSI cleanup, by Laurent Vivier.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3797 c046a42c-6fe2-441c-8c8c-71466251a162
hw/esp.c
... ... @@ -165,7 +165,7 @@ static int get_cmd(ESPState *s, uint8_t *buf)
165 165  
166 166 if (s->current_dev) {
167 167 /* Started a new command before the old one finished. Cancel it. */
168   - scsi_cancel_io(s->current_dev, 0);
  168 + s->current_dev->cancel_io(s->current_dev, 0);
169 169 s->async_len = 0;
170 170 }
171 171  
... ... @@ -188,7 +188,7 @@ static void do_cmd(ESPState *s, uint8_t *buf)
188 188  
189 189 DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
190 190 lun = buf[0] & 7;
191   - datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
  191 + datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
192 192 s->ti_size = datalen;
193 193 if (datalen != 0) {
194 194 s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC;
... ... @@ -196,10 +196,10 @@ static void do_cmd(ESPState *s, uint8_t *buf)
196 196 s->dma_counter = 0;
197 197 if (datalen > 0) {
198 198 s->rregs[ESP_RSTAT] |= STAT_DI;
199   - scsi_read_data(s->current_dev, 0);
  199 + s->current_dev->read_data(s->current_dev, 0);
200 200 } else {
201 201 s->rregs[ESP_RSTAT] |= STAT_DO;
202   - scsi_write_data(s->current_dev, 0);
  202 + s->current_dev->write_data(s->current_dev, 0);
203 203 }
204 204 }
205 205 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
... ... @@ -298,9 +298,9 @@ static void esp_do_dma(ESPState *s)
298 298 if (s->async_len == 0) {
299 299 if (to_device) {
300 300 // ti_size is negative
301   - scsi_write_data(s->current_dev, 0);
  301 + s->current_dev->write_data(s->current_dev, 0);
302 302 } else {
303   - scsi_read_data(s->current_dev, 0);
  303 + s->current_dev->read_data(s->current_dev, 0);
304 304 /* If there is still data to be read from the device then
305 305 complete the DMA operation immeriately. Otherwise defer
306 306 until the scsi layer has completed. */
... ... @@ -335,7 +335,7 @@ static void esp_command_complete(void *opaque, int reason, uint32_t tag,
335 335 } else {
336 336 DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
337 337 s->async_len = arg;
338   - s->async_buf = scsi_get_buf(s->current_dev, 0);
  338 + s->async_buf = s->current_dev->get_buf(s->current_dev, 0);
339 339 if (s->dma_left) {
340 340 esp_do_dma(s);
341 341 } else if (s->dma_counter != 0 && s->ti_size <= 0) {
... ... @@ -611,7 +611,7 @@ void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id)
611 611 }
612 612 if (s->scsi_dev[id]) {
613 613 DPRINTF("Destroying device %d\n", id);
614   - scsi_disk_destroy(s->scsi_dev[id]);
  614 + s->scsi_dev[id]->destroy(s->scsi_dev[id]);
615 615 }
616 616 DPRINTF("Attaching block device %d\n", id);
617 617 /* Command queueing is not implemented. */
... ...
hw/lsi53c895a.c
... ... @@ -187,6 +187,7 @@ typedef struct {
187 187 /* The tag is a combination of the device ID and the SCSI tag. */
188 188 uint32_t current_tag;
189 189 uint32_t current_dma_len;
  190 + int command_complete;
190 191 uint8_t *dma_buf;
191 192 lsi_queue *queue;
192 193 int queue_len;
... ... @@ -465,7 +466,8 @@ static void lsi_do_dma(LSIState *s, int out)
465 466 s->dbc -= count;
466 467  
467 468 if (s->dma_buf == NULL) {
468   - s->dma_buf = scsi_get_buf(s->current_dev, s->current_tag);
  469 + s->dma_buf = s->current_dev->get_buf(s->current_dev,
  470 + s->current_tag);
469 471 }
470 472  
471 473 /* ??? Set SFBR to first data byte. */
... ... @@ -479,10 +481,10 @@ static void lsi_do_dma(LSIState *s, int out)
479 481 s->dma_buf = NULL;
480 482 if (out) {
481 483 /* Write the data. */
482   - scsi_write_data(s->current_dev, s->current_tag);
  484 + s->current_dev->write_data(s->current_dev, s->current_tag);
483 485 } else {
484 486 /* Request any remaining data. */
485   - scsi_read_data(s->current_dev, s->current_tag);
  487 + s->current_dev->read_data(s->current_dev, s->current_tag);
486 488 }
487 489 } else {
488 490 s->dma_buf += count;
... ... @@ -596,6 +598,7 @@ static void lsi_command_complete(void *opaque, int reason, uint32_t tag,
596 598 if (reason == SCSI_REASON_DONE) {
597 599 DPRINTF("Command complete sense=%d\n", (int)arg);
598 600 s->sense = arg;
  601 + s->command_complete = 2;
599 602 if (s->waiting && s->dbc != 0) {
600 603 /* Raise phase mismatch for short transfers. */
601 604 lsi_bad_phase(s, out, PHASE_ST);
... ... @@ -612,6 +615,7 @@ static void lsi_command_complete(void *opaque, int reason, uint32_t tag,
612 615 }
613 616 DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg);
614 617 s->current_dma_len = arg;
  618 + s->command_complete = 1;
615 619 if (!s->waiting)
616 620 return;
617 621 if (s->waiting == 1 || s->dbc == 0) {
... ... @@ -631,21 +635,30 @@ static void lsi_do_command(LSIState *s)
631 635 s->dbc = 16;
632 636 cpu_physical_memory_read(s->dnad, buf, s->dbc);
633 637 s->sfbr = buf[0];
634   - n = scsi_send_command(s->current_dev, s->current_tag, buf, s->current_lun);
  638 + s->command_complete = 0;
  639 + n = s->current_dev->send_command(s->current_dev, s->current_tag, buf,
  640 + s->current_lun);
635 641 if (n > 0) {
636 642 lsi_set_phase(s, PHASE_DI);
637   - scsi_read_data(s->current_dev, s->current_tag);
  643 + s->current_dev->read_data(s->current_dev, s->current_tag);
638 644 } else if (n < 0) {
639 645 lsi_set_phase(s, PHASE_DO);
640   - scsi_write_data(s->current_dev, s->current_tag);
  646 + s->current_dev->write_data(s->current_dev, s->current_tag);
641 647 }
642   - if (n && s->current_dma_len == 0) {
643   - /* Command did not complete immediately so disconnect. */
644   - lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */
645   - lsi_add_msg_byte(s, 4); /* DISCONNECT */
646   - lsi_set_phase(s, PHASE_MI);
647   - s->msg_action = 1;
648   - lsi_queue_command(s);
  648 +
  649 + if (!s->command_complete) {
  650 + if (n) {
  651 + /* Command did not complete immediately so disconnect. */
  652 + lsi_add_msg_byte(s, 2); /* SAVE DATA POINTER */
  653 + lsi_add_msg_byte(s, 4); /* DISCONNECT */
  654 + /* wait data */
  655 + lsi_set_phase(s, PHASE_MI);
  656 + s->msg_action = 1;
  657 + lsi_queue_command(s);
  658 + } else {
  659 + /* wait command complete */
  660 + lsi_set_phase(s, PHASE_DI);
  661 + }
649 662 }
650 663 }
651 664  
... ... @@ -1822,7 +1835,7 @@ void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id)
1822 1835 }
1823 1836 if (s->scsi_dev[id]) {
1824 1837 DPRINTF("Destroying device %d\n", id);
1825   - scsi_disk_destroy(s->scsi_dev[id]);
  1838 + s->scsi_dev[id]->destroy(s->scsi_dev[id]);
1826 1839 }
1827 1840 DPRINTF("Attaching block device %d\n", id);
1828 1841 s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
... ...
hw/scsi-disk.c
... ... @@ -37,7 +37,7 @@ do { fprintf(stderr, &quot;scsi-disk: &quot; fmt , ##args); } while (0)
37 37 #define SCSI_DMA_BUF_SIZE 65536
38 38  
39 39 typedef struct SCSIRequest {
40   - SCSIDevice *dev;
  40 + SCSIDeviceState *dev;
41 41 uint32_t tag;
42 42 /* ??? We should probably keep track of whether the data trasfer is
43 43 a read or a write. Currently we rely on the host getting it right. */
... ... @@ -51,7 +51,7 @@ typedef struct SCSIRequest {
51 51 struct SCSIRequest *next;
52 52 } SCSIRequest;
53 53  
54   -struct SCSIDevice
  54 +struct SCSIDeviceState
55 55 {
56 56 BlockDriverState *bdrv;
57 57 SCSIRequest *requests;
... ... @@ -69,7 +69,7 @@ struct SCSIDevice
69 69 /* Global pool of SCSIRequest structures. */
70 70 static SCSIRequest *free_requests = NULL;
71 71  
72   -static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag)
  72 +static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
73 73 {
74 74 SCSIRequest *r;
75 75  
... ... @@ -93,7 +93,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag)
93 93 static void scsi_remove_request(SCSIRequest *r)
94 94 {
95 95 SCSIRequest *last;
96   - SCSIDevice *s = r->dev;
  96 + SCSIDeviceState *s = r->dev;
97 97  
98 98 if (s->requests == r) {
99 99 s->requests = r->next;
... ... @@ -111,7 +111,7 @@ static void scsi_remove_request(SCSIRequest *r)
111 111 free_requests = r;
112 112 }
113 113  
114   -static SCSIRequest *scsi_find_request(SCSIDevice *s, uint32_t tag)
  114 +static SCSIRequest *scsi_find_request(SCSIDeviceState *s, uint32_t tag)
115 115 {
116 116 SCSIRequest *r;
117 117  
... ... @@ -125,7 +125,7 @@ static SCSIRequest *scsi_find_request(SCSIDevice *s, uint32_t tag)
125 125 /* Helper function for command completion. */
126 126 static void scsi_command_complete(SCSIRequest *r, int sense)
127 127 {
128   - SCSIDevice *s = r->dev;
  128 + SCSIDeviceState *s = r->dev;
129 129 uint32_t tag;
130 130 DPRINTF("Command complete tag=0x%x sense=%d\n", r->tag, sense);
131 131 s->sense = sense;
... ... @@ -135,8 +135,9 @@ static void scsi_command_complete(SCSIRequest *r, int sense)
135 135 }
136 136  
137 137 /* Cancel a pending data transfer. */
138   -void scsi_cancel_io(SCSIDevice *s, uint32_t tag)
  138 +static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
139 139 {
  140 + SCSIDeviceState *s = d->state;
140 141 SCSIRequest *r;
141 142 DPRINTF("Cancel tag=0x%x\n", tag);
142 143 r = scsi_find_request(s, tag);
... ... @@ -151,7 +152,7 @@ void scsi_cancel_io(SCSIDevice *s, uint32_t tag)
151 152 static void scsi_read_complete(void * opaque, int ret)
152 153 {
153 154 SCSIRequest *r = (SCSIRequest *)opaque;
154   - SCSIDevice *s = r->dev;
  155 + SCSIDeviceState *s = r->dev;
155 156  
156 157 if (ret) {
157 158 DPRINTF("IO error\n");
... ... @@ -164,8 +165,9 @@ static void scsi_read_complete(void * opaque, int ret)
164 165 }
165 166  
166 167 /* Read more data from scsi device into buffer. */
167   -void scsi_read_data(SCSIDevice *s, uint32_t tag)
  168 +static void scsi_read_data(SCSIDevice *d, uint32_t tag)
168 169 {
  170 + SCSIDeviceState *s = d->state;
169 171 SCSIRequest *r;
170 172 uint32_t n;
171 173  
... ... @@ -204,7 +206,7 @@ void scsi_read_data(SCSIDevice *s, uint32_t tag)
204 206 static void scsi_write_complete(void * opaque, int ret)
205 207 {
206 208 SCSIRequest *r = (SCSIRequest *)opaque;
207   - SCSIDevice *s = r->dev;
  209 + SCSIDeviceState *s = r->dev;
208 210 uint32_t len;
209 211  
210 212 if (ret) {
... ... @@ -228,8 +230,9 @@ static void scsi_write_complete(void * opaque, int ret)
228 230  
229 231 /* Write data to a scsi device. Returns nonzero on failure.
230 232 The transfer may complete asynchronously. */
231   -int scsi_write_data(SCSIDevice *s, uint32_t tag)
  233 +static int scsi_write_data(SCSIDevice *d, uint32_t tag)
232 234 {
  235 + SCSIDeviceState *s = d->state;
233 236 SCSIRequest *r;
234 237 uint32_t n;
235 238  
... ... @@ -259,8 +262,9 @@ int scsi_write_data(SCSIDevice *s, uint32_t tag)
259 262 }
260 263  
261 264 /* Return a pointer to the data buffer. */
262   -uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag)
  265 +static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
263 266 {
  267 + SCSIDeviceState *s = d->state;
264 268 SCSIRequest *r;
265 269  
266 270 r = scsi_find_request(s, tag);
... ... @@ -276,8 +280,10 @@ uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag)
276 280 (eg. disk reads), negative for transfers to the device (eg. disk writes),
277 281 and zero if the command does not transfer any data. */
278 282  
279   -int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
  283 +static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
  284 + uint8_t *buf, int lun)
280 285 {
  286 + SCSIDeviceState *s = d->state;
281 287 int64_t nb_sectors;
282 288 uint32_t lba;
283 289 uint32_t len;
... ... @@ -291,7 +297,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
291 297 r = scsi_find_request(s, tag);
292 298 if (r) {
293 299 BADF("Tag 0x%x already in use\n", tag);
294   - scsi_cancel_io(s, tag);
  300 + scsi_cancel_io(d, tag);
295 301 }
296 302 /* ??? Tags are not unique for different luns. We only implement a
297 303 single lun, so this should not matter. */
... ... @@ -576,19 +582,19 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
576 582 }
577 583 }
578 584  
579   -void scsi_disk_destroy(SCSIDevice *s)
  585 +static void scsi_destroy(SCSIDevice *d)
580 586 {
581   - qemu_free(s);
  587 + qemu_free(d->state);
  588 + qemu_free(d);
582 589 }
583 590  
584   -SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
585   - int tcq,
586   - scsi_completionfn completion,
587   - void *opaque)
  591 +SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
  592 + scsi_completionfn completion, void *opaque)
588 593 {
589   - SCSIDevice *s;
  594 + SCSIDevice *d;
  595 + SCSIDeviceState *s;
590 596  
591   - s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
  597 + s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
592 598 s->bdrv = bdrv;
593 599 s->tcq = tcq;
594 600 s->completion = completion;
... ... @@ -599,6 +605,14 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
599 605 s->cluster_size = 1;
600 606 }
601 607  
602   - return s;
603   -}
  608 + d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
  609 + d->state = s;
  610 + d->destroy = scsi_destroy;
  611 + d->send_command = scsi_send_command;
  612 + d->read_data = scsi_read_data;
  613 + d->write_data = scsi_write_data;
  614 + d->cancel_io = scsi_cancel_io;
  615 + d->get_buf = scsi_get_buf;
604 616  
  617 + return d;
  618 +}
... ...
hw/scsi-disk.h
... ... @@ -7,24 +7,25 @@ enum scsi_reason {
7 7 SCSI_REASON_DATA /* Transfer complete, more data required. */
8 8 };
9 9  
  10 +typedef struct SCSIDeviceState SCSIDeviceState;
10 11 typedef struct SCSIDevice SCSIDevice;
11 12 typedef void (*scsi_completionfn)(void *opaque, int reason, uint32_t tag,
12 13 uint32_t arg);
13 14  
14   -SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
15   - int tcq,
16   - scsi_completionfn completion,
17   - void *opaque);
18   -void scsi_disk_destroy(SCSIDevice *s);
  15 +struct SCSIDevice
  16 +{
  17 + SCSIDeviceState *state;
  18 + void (*destroy)(SCSIDevice *s);
  19 + int32_t (*send_command)(SCSIDevice *s, uint32_t tag, uint8_t *buf,
  20 + int lun);
  21 + void (*read_data)(SCSIDevice *s, uint32_t tag);
  22 + int (*write_data)(SCSIDevice *s, uint32_t tag);
  23 + void (*cancel_io)(SCSIDevice *s, uint32_t tag);
  24 + uint8_t *(*get_buf)(SCSIDevice *s, uint32_t tag);
  25 +};
19 26  
20   -int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun);
21   -/* SCSI data transfers are asynchrnonous. However, unlike the block IO
22   - layer the completion routine may be called directly by
23   - scsi_{read,write}_data. */
24   -void scsi_read_data(SCSIDevice *s, uint32_t tag);
25   -int scsi_write_data(SCSIDevice *s, uint32_t tag);
26   -void scsi_cancel_io(SCSIDevice *s, uint32_t tag);
27   -uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag);
  27 +SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
  28 + scsi_completionfn completion, void *opaque);
28 29  
29 30 /* cdrom.c */
30 31 int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
... ...
hw/usb-msd.c
... ... @@ -149,9 +149,9 @@ static void usb_msd_copy_data(MSDState *s)
149 149 s->data_len -= len;
150 150 if (s->scsi_len == 0) {
151 151 if (s->mode == USB_MSDM_DATAIN) {
152   - scsi_read_data(s->scsi_dev, s->tag);
  152 + s->scsi_dev->read_data(s->scsi_dev, s->tag);
153 153 } else if (s->mode == USB_MSDM_DATAOUT) {
154   - scsi_write_data(s->scsi_dev, s->tag);
  154 + s->scsi_dev->write_data(s->scsi_dev, s->tag);
155 155 }
156 156 }
157 157 }
... ... @@ -204,7 +204,7 @@ static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag,
204 204 return;
205 205 }
206 206 s->scsi_len = arg;
207   - s->scsi_buf = scsi_get_buf(s->scsi_dev, tag);
  207 + s->scsi_buf = s->scsi_dev->get_buf(s->scsi_dev, tag);
208 208 if (p) {
209 209 usb_msd_copy_data(s);
210 210 if (s->usb_len == 0) {
... ... @@ -342,7 +342,7 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
342 342 static void usb_msd_cancel_io(USBPacket *p, void *opaque)
343 343 {
344 344 MSDState *s = opaque;
345   - scsi_cancel_io(s->scsi_dev, s->tag);
  345 + s->scsi_dev->cancel_io(s->scsi_dev, s->tag);
346 346 s->packet = NULL;
347 347 s->scsi_len = 0;
348 348 }
... ... @@ -390,14 +390,14 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
390 390 DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
391 391 s->tag, cbw.flags, cbw.cmd_len, s->data_len);
392 392 s->residue = 0;
393   - scsi_send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
  393 + s->scsi_dev->send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
394 394 /* ??? Should check that USB and SCSI data transfer
395 395 directions match. */
396 396 if (s->residue == 0) {
397 397 if (s->mode == USB_MSDM_DATAIN) {
398   - scsi_read_data(s->scsi_dev, s->tag);
  398 + s->scsi_dev->read_data(s->scsi_dev, s->tag);
399 399 } else if (s->mode == USB_MSDM_DATAOUT) {
400   - scsi_write_data(s->scsi_dev, s->tag);
  400 + s->scsi_dev->write_data(s->scsi_dev, s->tag);
401 401 }
402 402 }
403 403 ret = len;
... ... @@ -508,7 +508,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
508 508 {
509 509 MSDState *s = (MSDState *)dev;
510 510  
511   - scsi_disk_destroy(s->scsi_dev);
  511 + s->scsi_dev->destroy(s->scsi_dev);
512 512 bdrv_delete(s->bs);
513 513 qemu_free(s);
514 514 }
... ...