diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2009-08-31 14:24:04 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2009-09-09 14:57:19 -0500 |
commit | d52affa7f6b9df3c7d44da0effbdfc8339c43914 (patch) | |
tree | f846e1baed7d228519ba95bfd3d915529e7172f9 /hw/esp.c | |
parent | 5b19d9a247c47fe52c4f3d3e844009a689ee6b28 (diff) |
qdev/scsi: add scsi bus support to qdev, convert drivers.
* Add SCSIBus.
* Add SCSIDeviceInfo, move device callbacks here.
* add qdev/scsi helper functions.
* convert drivers.
Adding scsi disks via -device works now, i.e. you can do:
-drive id=sda,if=none,...
-device lsi
-device scsi-disk,drive=sda
legacy command lines (-drive if=scsi,...) continue to work.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/esp.c')
-rw-r--r-- | hw/esp.c | 54 |
1 files changed, 14 insertions, 40 deletions
@@ -63,7 +63,7 @@ struct ESPState { uint8_t ti_buf[TI_BUFSZ]; uint32_t sense; uint32_t dma; - SCSIDevice *scsi_dev[ESP_MAX_DEVS]; + SCSIBus *bus; SCSIDevice *current_dev; uint8_t cmdbuf[TI_BUFSZ]; uint32_t cmdlen; @@ -187,11 +187,11 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf) if (s->current_dev) { /* Started a new command before the old one finished. Cancel it. */ - s->current_dev->cancel_io(s->current_dev, 0); + s->current_dev->info->cancel_io(s->current_dev, 0); s->async_len = 0; } - if (target >= ESP_MAX_DEVS || !s->scsi_dev[target]) { + if (target >= ESP_MAX_DEVS || !s->bus->devs[target]) { // No such drive s->rregs[ESP_RSTAT] = 0; s->rregs[ESP_RINTR] = INTR_DC; @@ -199,7 +199,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf) esp_raise_irq(s); return 0; } - s->current_dev = s->scsi_dev[target]; + s->current_dev = s->bus->devs[target]; return dmalen; } @@ -210,7 +210,7 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid) DPRINTF("do_busid_cmd: busid 0x%x\n", busid); lun = busid & 7; - datalen = s->current_dev->send_command(s->current_dev, 0, buf, lun); + datalen = s->current_dev->info->send_command(s->current_dev, 0, buf, lun); s->ti_size = datalen; if (datalen != 0) { s->rregs[ESP_RSTAT] = STAT_TC; @@ -218,10 +218,10 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid) s->dma_counter = 0; if (datalen > 0) { s->rregs[ESP_RSTAT] |= STAT_DI; - s->current_dev->read_data(s->current_dev, 0); + s->current_dev->info->read_data(s->current_dev, 0); } else { s->rregs[ESP_RSTAT] |= STAT_DO; - s->current_dev->write_data(s->current_dev, 0); + s->current_dev->info->write_data(s->current_dev, 0); } } s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; @@ -338,9 +338,9 @@ static void esp_do_dma(ESPState *s) if (s->async_len == 0) { if (to_device) { // ti_size is negative - s->current_dev->write_data(s->current_dev, 0); + s->current_dev->info->write_data(s->current_dev, 0); } else { - s->current_dev->read_data(s->current_dev, 0); + s->current_dev->info->read_data(s->current_dev, 0); /* If there is still data to be read from the device then complete the DMA operation immediately. Otherwise defer until the scsi layer has completed. */ @@ -354,10 +354,10 @@ static void esp_do_dma(ESPState *s) } } -static void esp_command_complete(void *opaque, int reason, uint32_t tag, +static void esp_command_complete(SCSIBus *bus, int reason, uint32_t tag, uint32_t arg) { - ESPState *s = (ESPState *)opaque; + ESPState *s = DO_UPCAST(ESPState, busdev.qdev, bus->qbus.parent); if (reason == SCSI_REASON_DONE) { DPRINTF("SCSI Command complete\n"); @@ -375,7 +375,7 @@ static void esp_command_complete(void *opaque, int reason, uint32_t tag, } else { DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size); s->async_len = arg; - s->async_buf = s->current_dev->get_buf(s->current_dev, 0); + s->async_buf = s->current_dev->info->get_buf(s->current_dev, 0); if (s->dma_left) { esp_do_dma(s); } else if (s->dma_counter != 0 && s->ti_size <= 0) { @@ -652,33 +652,6 @@ static int esp_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void esp_scsi_attach(DeviceState *host, BlockDriverState *bd, int id) -{ - ESPState *s = FROM_SYSBUS(ESPState, sysbus_from_qdev(host)); - - if (id < 0) { - for (id = 0; id < ESP_MAX_DEVS; id++) { - if (id == (s->rregs[ESP_CFG1] & 0x7)) - continue; - if (s->scsi_dev[id] == NULL) - break; - } - } - if (id >= ESP_MAX_DEVS) { - DPRINTF("Bad Device ID %d\n", id); - return; - } - if (s->scsi_dev[id]) { - DPRINTF("Destroying device %d\n", id); - s->scsi_dev[id]->destroy(s->scsi_dev[id]); - } - DPRINTF("Attaching block device %d\n", id); - /* Command queueing is not implemented. */ - s->scsi_dev[id] = scsi_generic_init(bd, 0, esp_command_complete, s); - if (s->scsi_dev[id] == NULL) - s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s); -} - void esp_init(target_phys_addr_t espaddr, int it_shift, espdma_memory_read_write dma_memory_read, espdma_memory_read_write dma_memory_write, @@ -719,7 +692,8 @@ static int esp_init1(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1); - scsi_bus_new(&dev->qdev, esp_scsi_attach); + s->bus = scsi_bus_new(&dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete); + scsi_bus_legacy_handle_cmdline(s->bus); return 0; } |