Commit 8ccc2ace5628720347017c98a43b47b2ba23cf15
1 parent
cf6d9118
SCSI cleanup, by Laurent Vivier.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3797 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
95 additions
and
67 deletions
hw/esp.c
| @@ -165,7 +165,7 @@ static int get_cmd(ESPState *s, uint8_t *buf) | @@ -165,7 +165,7 @@ static int get_cmd(ESPState *s, uint8_t *buf) | ||
| 165 | 165 | ||
| 166 | if (s->current_dev) { | 166 | if (s->current_dev) { |
| 167 | /* Started a new command before the old one finished. Cancel it. */ | 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 | s->async_len = 0; | 169 | s->async_len = 0; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| @@ -188,7 +188,7 @@ static void do_cmd(ESPState *s, uint8_t *buf) | @@ -188,7 +188,7 @@ static void do_cmd(ESPState *s, uint8_t *buf) | ||
| 188 | 188 | ||
| 189 | DPRINTF("do_cmd: busid 0x%x\n", buf[0]); | 189 | DPRINTF("do_cmd: busid 0x%x\n", buf[0]); |
| 190 | lun = buf[0] & 7; | 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 | s->ti_size = datalen; | 192 | s->ti_size = datalen; |
| 193 | if (datalen != 0) { | 193 | if (datalen != 0) { |
| 194 | s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC; | 194 | s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC; |
| @@ -196,10 +196,10 @@ static void do_cmd(ESPState *s, uint8_t *buf) | @@ -196,10 +196,10 @@ static void do_cmd(ESPState *s, uint8_t *buf) | ||
| 196 | s->dma_counter = 0; | 196 | s->dma_counter = 0; |
| 197 | if (datalen > 0) { | 197 | if (datalen > 0) { |
| 198 | s->rregs[ESP_RSTAT] |= STAT_DI; | 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 | } else { | 200 | } else { |
| 201 | s->rregs[ESP_RSTAT] |= STAT_DO; | 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 | s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; | 205 | s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; |
| @@ -298,9 +298,9 @@ static void esp_do_dma(ESPState *s) | @@ -298,9 +298,9 @@ static void esp_do_dma(ESPState *s) | ||
| 298 | if (s->async_len == 0) { | 298 | if (s->async_len == 0) { |
| 299 | if (to_device) { | 299 | if (to_device) { |
| 300 | // ti_size is negative | 300 | // ti_size is negative |
| 301 | - scsi_write_data(s->current_dev, 0); | 301 | + s->current_dev->write_data(s->current_dev, 0); |
| 302 | } else { | 302 | } else { |
| 303 | - scsi_read_data(s->current_dev, 0); | 303 | + s->current_dev->read_data(s->current_dev, 0); |
| 304 | /* If there is still data to be read from the device then | 304 | /* If there is still data to be read from the device then |
| 305 | complete the DMA operation immeriately. Otherwise defer | 305 | complete the DMA operation immeriately. Otherwise defer |
| 306 | until the scsi layer has completed. */ | 306 | until the scsi layer has completed. */ |
| @@ -335,7 +335,7 @@ static void esp_command_complete(void *opaque, int reason, uint32_t tag, | @@ -335,7 +335,7 @@ static void esp_command_complete(void *opaque, int reason, uint32_t tag, | ||
| 335 | } else { | 335 | } else { |
| 336 | DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size); | 336 | DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size); |
| 337 | s->async_len = arg; | 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 | if (s->dma_left) { | 339 | if (s->dma_left) { |
| 340 | esp_do_dma(s); | 340 | esp_do_dma(s); |
| 341 | } else if (s->dma_counter != 0 && s->ti_size <= 0) { | 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,7 +611,7 @@ void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id) | ||
| 611 | } | 611 | } |
| 612 | if (s->scsi_dev[id]) { | 612 | if (s->scsi_dev[id]) { |
| 613 | DPRINTF("Destroying device %d\n", id); | 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 | DPRINTF("Attaching block device %d\n", id); | 616 | DPRINTF("Attaching block device %d\n", id); |
| 617 | /* Command queueing is not implemented. */ | 617 | /* Command queueing is not implemented. */ |
hw/lsi53c895a.c
| @@ -187,6 +187,7 @@ typedef struct { | @@ -187,6 +187,7 @@ typedef struct { | ||
| 187 | /* The tag is a combination of the device ID and the SCSI tag. */ | 187 | /* The tag is a combination of the device ID and the SCSI tag. */ |
| 188 | uint32_t current_tag; | 188 | uint32_t current_tag; |
| 189 | uint32_t current_dma_len; | 189 | uint32_t current_dma_len; |
| 190 | + int command_complete; | ||
| 190 | uint8_t *dma_buf; | 191 | uint8_t *dma_buf; |
| 191 | lsi_queue *queue; | 192 | lsi_queue *queue; |
| 192 | int queue_len; | 193 | int queue_len; |
| @@ -465,7 +466,8 @@ static void lsi_do_dma(LSIState *s, int out) | @@ -465,7 +466,8 @@ static void lsi_do_dma(LSIState *s, int out) | ||
| 465 | s->dbc -= count; | 466 | s->dbc -= count; |
| 466 | 467 | ||
| 467 | if (s->dma_buf == NULL) { | 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 | /* ??? Set SFBR to first data byte. */ | 473 | /* ??? Set SFBR to first data byte. */ |
| @@ -479,10 +481,10 @@ static void lsi_do_dma(LSIState *s, int out) | @@ -479,10 +481,10 @@ static void lsi_do_dma(LSIState *s, int out) | ||
| 479 | s->dma_buf = NULL; | 481 | s->dma_buf = NULL; |
| 480 | if (out) { | 482 | if (out) { |
| 481 | /* Write the data. */ | 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 | } else { | 485 | } else { |
| 484 | /* Request any remaining data. */ | 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 | } else { | 489 | } else { |
| 488 | s->dma_buf += count; | 490 | s->dma_buf += count; |
| @@ -596,6 +598,7 @@ static void lsi_command_complete(void *opaque, int reason, uint32_t tag, | @@ -596,6 +598,7 @@ static void lsi_command_complete(void *opaque, int reason, uint32_t tag, | ||
| 596 | if (reason == SCSI_REASON_DONE) { | 598 | if (reason == SCSI_REASON_DONE) { |
| 597 | DPRINTF("Command complete sense=%d\n", (int)arg); | 599 | DPRINTF("Command complete sense=%d\n", (int)arg); |
| 598 | s->sense = arg; | 600 | s->sense = arg; |
| 601 | + s->command_complete = 2; | ||
| 599 | if (s->waiting && s->dbc != 0) { | 602 | if (s->waiting && s->dbc != 0) { |
| 600 | /* Raise phase mismatch for short transfers. */ | 603 | /* Raise phase mismatch for short transfers. */ |
| 601 | lsi_bad_phase(s, out, PHASE_ST); | 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,6 +615,7 @@ static void lsi_command_complete(void *opaque, int reason, uint32_t tag, | ||
| 612 | } | 615 | } |
| 613 | DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg); | 616 | DPRINTF("Data ready tag=0x%x len=%d\n", tag, arg); |
| 614 | s->current_dma_len = arg; | 617 | s->current_dma_len = arg; |
| 618 | + s->command_complete = 1; | ||
| 615 | if (!s->waiting) | 619 | if (!s->waiting) |
| 616 | return; | 620 | return; |
| 617 | if (s->waiting == 1 || s->dbc == 0) { | 621 | if (s->waiting == 1 || s->dbc == 0) { |
| @@ -631,21 +635,30 @@ static void lsi_do_command(LSIState *s) | @@ -631,21 +635,30 @@ static void lsi_do_command(LSIState *s) | ||
| 631 | s->dbc = 16; | 635 | s->dbc = 16; |
| 632 | cpu_physical_memory_read(s->dnad, buf, s->dbc); | 636 | cpu_physical_memory_read(s->dnad, buf, s->dbc); |
| 633 | s->sfbr = buf[0]; | 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 | if (n > 0) { | 641 | if (n > 0) { |
| 636 | lsi_set_phase(s, PHASE_DI); | 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 | } else if (n < 0) { | 644 | } else if (n < 0) { |
| 639 | lsi_set_phase(s, PHASE_DO); | 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,7 +1835,7 @@ void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id) | ||
| 1822 | } | 1835 | } |
| 1823 | if (s->scsi_dev[id]) { | 1836 | if (s->scsi_dev[id]) { |
| 1824 | DPRINTF("Destroying device %d\n", id); | 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 | DPRINTF("Attaching block device %d\n", id); | 1840 | DPRINTF("Attaching block device %d\n", id); |
| 1828 | s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s); | 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, "scsi-disk: " fmt , ##args); } while (0) | @@ -37,7 +37,7 @@ do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0) | ||
| 37 | #define SCSI_DMA_BUF_SIZE 65536 | 37 | #define SCSI_DMA_BUF_SIZE 65536 |
| 38 | 38 | ||
| 39 | typedef struct SCSIRequest { | 39 | typedef struct SCSIRequest { |
| 40 | - SCSIDevice *dev; | 40 | + SCSIDeviceState *dev; |
| 41 | uint32_t tag; | 41 | uint32_t tag; |
| 42 | /* ??? We should probably keep track of whether the data trasfer is | 42 | /* ??? We should probably keep track of whether the data trasfer is |
| 43 | a read or a write. Currently we rely on the host getting it right. */ | 43 | a read or a write. Currently we rely on the host getting it right. */ |
| @@ -51,7 +51,7 @@ typedef struct SCSIRequest { | @@ -51,7 +51,7 @@ typedef struct SCSIRequest { | ||
| 51 | struct SCSIRequest *next; | 51 | struct SCSIRequest *next; |
| 52 | } SCSIRequest; | 52 | } SCSIRequest; |
| 53 | 53 | ||
| 54 | -struct SCSIDevice | 54 | +struct SCSIDeviceState |
| 55 | { | 55 | { |
| 56 | BlockDriverState *bdrv; | 56 | BlockDriverState *bdrv; |
| 57 | SCSIRequest *requests; | 57 | SCSIRequest *requests; |
| @@ -69,7 +69,7 @@ struct SCSIDevice | @@ -69,7 +69,7 @@ struct SCSIDevice | ||
| 69 | /* Global pool of SCSIRequest structures. */ | 69 | /* Global pool of SCSIRequest structures. */ |
| 70 | static SCSIRequest *free_requests = NULL; | 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 | SCSIRequest *r; | 74 | SCSIRequest *r; |
| 75 | 75 | ||
| @@ -93,7 +93,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag) | @@ -93,7 +93,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag) | ||
| 93 | static void scsi_remove_request(SCSIRequest *r) | 93 | static void scsi_remove_request(SCSIRequest *r) |
| 94 | { | 94 | { |
| 95 | SCSIRequest *last; | 95 | SCSIRequest *last; |
| 96 | - SCSIDevice *s = r->dev; | 96 | + SCSIDeviceState *s = r->dev; |
| 97 | 97 | ||
| 98 | if (s->requests == r) { | 98 | if (s->requests == r) { |
| 99 | s->requests = r->next; | 99 | s->requests = r->next; |
| @@ -111,7 +111,7 @@ static void scsi_remove_request(SCSIRequest *r) | @@ -111,7 +111,7 @@ static void scsi_remove_request(SCSIRequest *r) | ||
| 111 | free_requests = r; | 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 | SCSIRequest *r; | 116 | SCSIRequest *r; |
| 117 | 117 | ||
| @@ -125,7 +125,7 @@ static SCSIRequest *scsi_find_request(SCSIDevice *s, uint32_t tag) | @@ -125,7 +125,7 @@ static SCSIRequest *scsi_find_request(SCSIDevice *s, uint32_t tag) | ||
| 125 | /* Helper function for command completion. */ | 125 | /* Helper function for command completion. */ |
| 126 | static void scsi_command_complete(SCSIRequest *r, int sense) | 126 | static void scsi_command_complete(SCSIRequest *r, int sense) |
| 127 | { | 127 | { |
| 128 | - SCSIDevice *s = r->dev; | 128 | + SCSIDeviceState *s = r->dev; |
| 129 | uint32_t tag; | 129 | uint32_t tag; |
| 130 | DPRINTF("Command complete tag=0x%x sense=%d\n", r->tag, sense); | 130 | DPRINTF("Command complete tag=0x%x sense=%d\n", r->tag, sense); |
| 131 | s->sense = sense; | 131 | s->sense = sense; |
| @@ -135,8 +135,9 @@ static void scsi_command_complete(SCSIRequest *r, int sense) | @@ -135,8 +135,9 @@ static void scsi_command_complete(SCSIRequest *r, int sense) | ||
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | /* Cancel a pending data transfer. */ | 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 | SCSIRequest *r; | 141 | SCSIRequest *r; |
| 141 | DPRINTF("Cancel tag=0x%x\n", tag); | 142 | DPRINTF("Cancel tag=0x%x\n", tag); |
| 142 | r = scsi_find_request(s, tag); | 143 | r = scsi_find_request(s, tag); |
| @@ -151,7 +152,7 @@ void scsi_cancel_io(SCSIDevice *s, uint32_t tag) | @@ -151,7 +152,7 @@ void scsi_cancel_io(SCSIDevice *s, uint32_t tag) | ||
| 151 | static void scsi_read_complete(void * opaque, int ret) | 152 | static void scsi_read_complete(void * opaque, int ret) |
| 152 | { | 153 | { |
| 153 | SCSIRequest *r = (SCSIRequest *)opaque; | 154 | SCSIRequest *r = (SCSIRequest *)opaque; |
| 154 | - SCSIDevice *s = r->dev; | 155 | + SCSIDeviceState *s = r->dev; |
| 155 | 156 | ||
| 156 | if (ret) { | 157 | if (ret) { |
| 157 | DPRINTF("IO error\n"); | 158 | DPRINTF("IO error\n"); |
| @@ -164,8 +165,9 @@ static void scsi_read_complete(void * opaque, int ret) | @@ -164,8 +165,9 @@ static void scsi_read_complete(void * opaque, int ret) | ||
| 164 | } | 165 | } |
| 165 | 166 | ||
| 166 | /* Read more data from scsi device into buffer. */ | 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 | SCSIRequest *r; | 171 | SCSIRequest *r; |
| 170 | uint32_t n; | 172 | uint32_t n; |
| 171 | 173 | ||
| @@ -204,7 +206,7 @@ void scsi_read_data(SCSIDevice *s, uint32_t tag) | @@ -204,7 +206,7 @@ void scsi_read_data(SCSIDevice *s, uint32_t tag) | ||
| 204 | static void scsi_write_complete(void * opaque, int ret) | 206 | static void scsi_write_complete(void * opaque, int ret) |
| 205 | { | 207 | { |
| 206 | SCSIRequest *r = (SCSIRequest *)opaque; | 208 | SCSIRequest *r = (SCSIRequest *)opaque; |
| 207 | - SCSIDevice *s = r->dev; | 209 | + SCSIDeviceState *s = r->dev; |
| 208 | uint32_t len; | 210 | uint32_t len; |
| 209 | 211 | ||
| 210 | if (ret) { | 212 | if (ret) { |
| @@ -228,8 +230,9 @@ static void scsi_write_complete(void * opaque, int ret) | @@ -228,8 +230,9 @@ static void scsi_write_complete(void * opaque, int ret) | ||
| 228 | 230 | ||
| 229 | /* Write data to a scsi device. Returns nonzero on failure. | 231 | /* Write data to a scsi device. Returns nonzero on failure. |
| 230 | The transfer may complete asynchronously. */ | 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 | SCSIRequest *r; | 236 | SCSIRequest *r; |
| 234 | uint32_t n; | 237 | uint32_t n; |
| 235 | 238 | ||
| @@ -259,8 +262,9 @@ int scsi_write_data(SCSIDevice *s, uint32_t tag) | @@ -259,8 +262,9 @@ int scsi_write_data(SCSIDevice *s, uint32_t tag) | ||
| 259 | } | 262 | } |
| 260 | 263 | ||
| 261 | /* Return a pointer to the data buffer. */ | 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 | SCSIRequest *r; | 268 | SCSIRequest *r; |
| 265 | 269 | ||
| 266 | r = scsi_find_request(s, tag); | 270 | r = scsi_find_request(s, tag); |
| @@ -276,8 +280,10 @@ uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag) | @@ -276,8 +280,10 @@ uint8_t *scsi_get_buf(SCSIDevice *s, uint32_t tag) | ||
| 276 | (eg. disk reads), negative for transfers to the device (eg. disk writes), | 280 | (eg. disk reads), negative for transfers to the device (eg. disk writes), |
| 277 | and zero if the command does not transfer any data. */ | 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 | int64_t nb_sectors; | 287 | int64_t nb_sectors; |
| 282 | uint32_t lba; | 288 | uint32_t lba; |
| 283 | uint32_t len; | 289 | uint32_t len; |
| @@ -291,7 +297,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun) | @@ -291,7 +297,7 @@ int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun) | ||
| 291 | r = scsi_find_request(s, tag); | 297 | r = scsi_find_request(s, tag); |
| 292 | if (r) { | 298 | if (r) { |
| 293 | BADF("Tag 0x%x already in use\n", tag); | 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 | /* ??? Tags are not unique for different luns. We only implement a | 302 | /* ??? Tags are not unique for different luns. We only implement a |
| 297 | single lun, so this should not matter. */ | 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,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 | s->bdrv = bdrv; | 598 | s->bdrv = bdrv; |
| 593 | s->tcq = tcq; | 599 | s->tcq = tcq; |
| 594 | s->completion = completion; | 600 | s->completion = completion; |
| @@ -599,6 +605,14 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, | @@ -599,6 +605,14 @@ SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, | ||
| 599 | s->cluster_size = 1; | 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,24 +7,25 @@ enum scsi_reason { | ||
| 7 | SCSI_REASON_DATA /* Transfer complete, more data required. */ | 7 | SCSI_REASON_DATA /* Transfer complete, more data required. */ |
| 8 | }; | 8 | }; |
| 9 | 9 | ||
| 10 | +typedef struct SCSIDeviceState SCSIDeviceState; | ||
| 10 | typedef struct SCSIDevice SCSIDevice; | 11 | typedef struct SCSIDevice SCSIDevice; |
| 11 | typedef void (*scsi_completionfn)(void *opaque, int reason, uint32_t tag, | 12 | typedef void (*scsi_completionfn)(void *opaque, int reason, uint32_t tag, |
| 12 | uint32_t arg); | 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 | /* cdrom.c */ | 30 | /* cdrom.c */ |
| 30 | int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track); | 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,9 +149,9 @@ static void usb_msd_copy_data(MSDState *s) | ||
| 149 | s->data_len -= len; | 149 | s->data_len -= len; |
| 150 | if (s->scsi_len == 0) { | 150 | if (s->scsi_len == 0) { |
| 151 | if (s->mode == USB_MSDM_DATAIN) { | 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 | } else if (s->mode == USB_MSDM_DATAOUT) { | 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,7 +204,7 @@ static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag, | ||
| 204 | return; | 204 | return; |
| 205 | } | 205 | } |
| 206 | s->scsi_len = arg; | 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 | if (p) { | 208 | if (p) { |
| 209 | usb_msd_copy_data(s); | 209 | usb_msd_copy_data(s); |
| 210 | if (s->usb_len == 0) { | 210 | if (s->usb_len == 0) { |
| @@ -342,7 +342,7 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value, | @@ -342,7 +342,7 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value, | ||
| 342 | static void usb_msd_cancel_io(USBPacket *p, void *opaque) | 342 | static void usb_msd_cancel_io(USBPacket *p, void *opaque) |
| 343 | { | 343 | { |
| 344 | MSDState *s = opaque; | 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 | s->packet = NULL; | 346 | s->packet = NULL; |
| 347 | s->scsi_len = 0; | 347 | s->scsi_len = 0; |
| 348 | } | 348 | } |
| @@ -390,14 +390,14 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) | @@ -390,14 +390,14 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) | ||
| 390 | DPRINTF("Command tag 0x%x flags %08x len %d data %d\n", | 390 | DPRINTF("Command tag 0x%x flags %08x len %d data %d\n", |
| 391 | s->tag, cbw.flags, cbw.cmd_len, s->data_len); | 391 | s->tag, cbw.flags, cbw.cmd_len, s->data_len); |
| 392 | s->residue = 0; | 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 | /* ??? Should check that USB and SCSI data transfer | 394 | /* ??? Should check that USB and SCSI data transfer |
| 395 | directions match. */ | 395 | directions match. */ |
| 396 | if (s->residue == 0) { | 396 | if (s->residue == 0) { |
| 397 | if (s->mode == USB_MSDM_DATAIN) { | 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 | } else if (s->mode == USB_MSDM_DATAOUT) { | 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 | ret = len; | 403 | ret = len; |
| @@ -508,7 +508,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) | @@ -508,7 +508,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) | ||
| 508 | { | 508 | { |
| 509 | MSDState *s = (MSDState *)dev; | 509 | MSDState *s = (MSDState *)dev; |
| 510 | 510 | ||
| 511 | - scsi_disk_destroy(s->scsi_dev); | 511 | + s->scsi_dev->destroy(s->scsi_dev); |
| 512 | bdrv_delete(s->bs); | 512 | bdrv_delete(s->bs); |
| 513 | qemu_free(s); | 513 | qemu_free(s); |
| 514 | } | 514 | } |