aboutsummaryrefslogtreecommitdiff
path: root/hw/lsi53c895a.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2009-08-31 14:24:04 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-09-09 14:57:19 -0500
commitd52affa7f6b9df3c7d44da0effbdfc8339c43914 (patch)
treef846e1baed7d228519ba95bfd3d915529e7172f9 /hw/lsi53c895a.c
parent5b19d9a247c47fe52c4f3d3e844009a689ee6b28 (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/lsi53c895a.c')
-rw-r--r--hw/lsi53c895a.c65
1 files changed, 21 insertions, 44 deletions
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index bf9f072fe9..62bdca8032 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -14,6 +14,7 @@
#include "hw.h"
#include "pci.h"
+#include "scsi.h"
#include "scsi-disk.h"
#include "block_int.h"
@@ -192,7 +193,7 @@ typedef struct {
* 2 if processing DMA from lsi_execute_script.
* 3 if a DMA operation is in progress. */
int waiting;
- SCSIDevice *scsi_dev[LSI_MAX_DEVS];
+ SCSIBus *bus;
SCSIDevice *current_dev;
int current_lun;
/* The tag is a combination of the device ID and the SCSI tag. */
@@ -510,8 +511,8 @@ static void lsi_do_dma(LSIState *s, int out)
s->dbc -= count;
if (s->dma_buf == NULL) {
- s->dma_buf = s->current_dev->get_buf(s->current_dev,
- s->current_tag);
+ s->dma_buf = s->current_dev->info->get_buf(s->current_dev,
+ s->current_tag);
}
/* ??? Set SFBR to first data byte. */
@@ -525,10 +526,10 @@ static void lsi_do_dma(LSIState *s, int out)
s->dma_buf = NULL;
if (out) {
/* Write the data. */
- s->current_dev->write_data(s->current_dev, s->current_tag);
+ s->current_dev->info->write_data(s->current_dev, s->current_tag);
} else {
/* Request any remaining data. */
- s->current_dev->read_data(s->current_dev, s->current_tag);
+ s->current_dev->info->read_data(s->current_dev, s->current_tag);
}
} else {
s->dma_buf += count;
@@ -584,7 +585,7 @@ static void lsi_reselect(LSIState *s, uint32_t tag)
id = (tag >> 8) & 0xf;
s->ssid = id | 0x80;
DPRINTF("Reselected target %d\n", id);
- s->current_dev = s->scsi_dev[id];
+ s->current_dev = s->bus->devs[id];
s->current_tag = tag;
s->scntl1 |= LSI_SCNTL1_CON;
lsi_set_phase(s, PHASE_MI);
@@ -632,10 +633,10 @@ static int lsi_queue_tag(LSIState *s, uint32_t tag, uint32_t arg)
}
/* Callback to indicate that the SCSI layer has completed a transfer. */
-static void lsi_command_complete(void *opaque, int reason, uint32_t tag,
+static void lsi_command_complete(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg)
{
- LSIState *s = opaque;
+ LSIState *s = DO_UPCAST(LSIState, dev.qdev, bus->qbus.parent);
int out;
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
@@ -680,14 +681,14 @@ static void lsi_do_command(LSIState *s)
cpu_physical_memory_read(s->dnad, buf, s->dbc);
s->sfbr = buf[0];
s->command_complete = 0;
- n = s->current_dev->send_command(s->current_dev, s->current_tag, buf,
- s->current_lun);
+ n = s->current_dev->info->send_command(s->current_dev, s->current_tag, buf,
+ s->current_lun);
if (n > 0) {
lsi_set_phase(s, PHASE_DI);
- s->current_dev->read_data(s->current_dev, s->current_tag);
+ s->current_dev->info->read_data(s->current_dev, s->current_tag);
} else if (n < 0) {
lsi_set_phase(s, PHASE_DO);
- s->current_dev->write_data(s->current_dev, s->current_tag);
+ s->current_dev->info->write_data(s->current_dev, s->current_tag);
}
if (!s->command_complete) {
@@ -1040,7 +1041,7 @@ again:
}
s->sstat0 |= LSI_SSTAT0_WOA;
s->scntl1 &= ~LSI_SCNTL1_IARB;
- if (id >= LSI_MAX_DEVS || !s->scsi_dev[id]) {
+ if (id >= LSI_MAX_DEVS || !s->bus->devs[id]) {
DPRINTF("Selected absent target %d\n", id);
lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
lsi_disconnect(s);
@@ -1051,7 +1052,7 @@ again:
/* ??? Linux drivers compain when this is set. Maybe
it only applies in low-level mode (unimplemented).
lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
- s->current_dev = s->scsi_dev[id];
+ s->current_dev = s->bus->devs[id];
s->current_tag = id << 8;
s->scntl1 |= LSI_SCNTL1_CON;
if (insn & (1 << 3)) {
@@ -1958,31 +1959,6 @@ static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
cpu_register_physical_memory(addr + 0, 0x400, s->mmio_io_addr);
}
-void lsi_scsi_attach(DeviceState *host, BlockDriverState *bd, int id)
-{
- LSIState *s = DO_UPCAST(LSIState, dev.qdev, host);
-
- if (id < 0) {
- for (id = 0; id < LSI_MAX_DEVS; id++) {
- if (s->scsi_dev[id] == NULL)
- break;
- }
- }
- if (id >= LSI_MAX_DEVS) {
- BADF("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);
- s->scsi_dev[id] = scsi_generic_init(bd, 1, lsi_command_complete, s);
- if (s->scsi_dev[id] == NULL)
- s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
- bd->private = &s->dev;
-}
-
static void lsi_scsi_save(QEMUFile *f, void *opaque)
{
LSIState *s = opaque;
@@ -2202,16 +2178,17 @@ static int lsi_scsi_init(PCIDevice *dev)
lsi_soft_reset(s);
- scsi_bus_new(&dev->qdev, lsi_scsi_attach);
-
+ s->bus = scsi_bus_new(&dev->qdev, 1, LSI_MAX_DEVS, lsi_command_complete);
+ scsi_bus_legacy_handle_cmdline(s->bus);
register_savevm("lsiscsi", -1, 0, lsi_scsi_save, lsi_scsi_load, s);
return 0;
}
static PCIDeviceInfo lsi_info = {
- .qdev.name = "lsi53c895a",
- .qdev.size = sizeof(LSIState),
- .init = lsi_scsi_init,
+ .qdev.name = "lsi53c895a",
+ .qdev.alias = "lsi",
+ .qdev.size = sizeof(LSIState),
+ .init = lsi_scsi_init,
};
static void lsi53c895a_register_devices(void)