提交 cfdc1bb0 编写于 作者: P Paolo Bonzini

scsi: introduce SCSIBusOps

There are more operations than a SCSI bus can handle, besides completing
commands.  One example, which this series will introduce, is cleaning up
after a request is cancelled.

More long term, a "SCSI bus" can represent the LUNs attached to a
target; in this case, while all commands will ultimately reach a logical
unit, it is the target who is in charge of answering REPORT LUNs.
Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
上级 ab9adc88
...@@ -714,6 +714,10 @@ void esp_init(target_phys_addr_t espaddr, int it_shift, ...@@ -714,6 +714,10 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
*dma_enable = qdev_get_gpio_in(dev, 1); *dma_enable = qdev_get_gpio_in(dev, 1);
} }
static const struct SCSIBusOps esp_scsi_ops = {
.complete = esp_command_complete
};
static int esp_init1(SysBusDevice *dev) static int esp_init1(SysBusDevice *dev)
{ {
ESPState *s = FROM_SYSBUS(ESPState, dev); ESPState *s = FROM_SYSBUS(ESPState, dev);
...@@ -728,7 +732,7 @@ static int esp_init1(SysBusDevice *dev) ...@@ -728,7 +732,7 @@ static int esp_init1(SysBusDevice *dev)
qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2); qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete); scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, &esp_scsi_ops);
return scsi_bus_legacy_handle_cmdline(&s->bus); return scsi_bus_legacy_handle_cmdline(&s->bus);
} }
......
...@@ -2205,6 +2205,10 @@ static int lsi_scsi_uninit(PCIDevice *d) ...@@ -2205,6 +2205,10 @@ static int lsi_scsi_uninit(PCIDevice *d)
return 0; return 0;
} }
static const struct SCSIBusOps lsi_scsi_ops = {
.complete = lsi_command_complete
};
static int lsi_scsi_init(PCIDevice *dev) static int lsi_scsi_init(PCIDevice *dev)
{ {
LSIState *s = DO_UPCAST(LSIState, dev, dev); LSIState *s = DO_UPCAST(LSIState, dev, dev);
...@@ -2241,7 +2245,7 @@ static int lsi_scsi_init(PCIDevice *dev) ...@@ -2241,7 +2245,7 @@ static int lsi_scsi_init(PCIDevice *dev)
PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc); PCI_BASE_ADDRESS_SPACE_MEMORY, lsi_ram_mapfunc);
QTAILQ_INIT(&s->queue); QTAILQ_INIT(&s->queue);
scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, lsi_command_complete); scsi_bus_new(&s->bus, &dev->qdev, 1, LSI_MAX_DEVS, &lsi_scsi_ops);
if (!dev->qdev.hotplugged) { if (!dev->qdev.hotplugged) {
return scsi_bus_legacy_handle_cmdline(&s->bus); return scsi_bus_legacy_handle_cmdline(&s->bus);
} }
......
...@@ -21,13 +21,13 @@ static int next_scsi_bus; ...@@ -21,13 +21,13 @@ static int next_scsi_bus;
/* Create a scsi bus, and attach devices to it. */ /* Create a scsi bus, and attach devices to it. */
void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev, void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
scsi_completionfn complete) const SCSIBusOps *ops)
{ {
qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL); qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL);
bus->busnr = next_scsi_bus++; bus->busnr = next_scsi_bus++;
bus->tcq = tcq; bus->tcq = tcq;
bus->ndev = ndev; bus->ndev = ndev;
bus->complete = complete; bus->ops = ops;
bus->qbus.allow_hotplug = 1; bus->qbus.allow_hotplug = 1;
} }
...@@ -503,7 +503,7 @@ static const char *scsi_command_name(uint8_t cmd) ...@@ -503,7 +503,7 @@ static const char *scsi_command_name(uint8_t cmd)
void scsi_req_data(SCSIRequest *req, int len) void scsi_req_data(SCSIRequest *req, int len)
{ {
trace_scsi_req_data(req->dev->id, req->lun, req->tag, len); trace_scsi_req_data(req->dev->id, req->lun, req->tag, len);
req->bus->complete(req->bus, SCSI_REASON_DATA, req->tag, len); req->bus->ops->complete(req->bus, SCSI_REASON_DATA, req->tag, len);
} }
void scsi_req_print(SCSIRequest *req) void scsi_req_print(SCSIRequest *req)
...@@ -538,9 +538,9 @@ void scsi_req_complete(SCSIRequest *req) ...@@ -538,9 +538,9 @@ void scsi_req_complete(SCSIRequest *req)
{ {
assert(req->status != -1); assert(req->status != -1);
scsi_req_dequeue(req); scsi_req_dequeue(req);
req->bus->complete(req->bus, SCSI_REASON_DONE, req->bus->ops->complete(req->bus, SCSI_REASON_DONE,
req->tag, req->tag,
req->status); req->status);
} }
static char *scsibus_get_fw_dev_path(DeviceState *dev) static char *scsibus_get_fw_dev_path(DeviceState *dev)
......
...@@ -335,7 +335,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, ...@@ -335,7 +335,7 @@ static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
s->senselen = 7; s->senselen = 7;
s->driver_status = SG_ERR_DRIVER_SENSE; s->driver_status = SG_ERR_DRIVER_SENSE;
bus = scsi_bus_from_device(d); bus = scsi_bus_from_device(d);
bus->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION); bus->ops->complete(bus, SCSI_REASON_DONE, tag, CHECK_CONDITION);
return 0; return 0;
} }
......
...@@ -16,10 +16,9 @@ enum scsi_reason { ...@@ -16,10 +16,9 @@ enum scsi_reason {
}; };
typedef struct SCSIBus SCSIBus; typedef struct SCSIBus SCSIBus;
typedef struct SCSIBusOps SCSIBusOps;
typedef struct SCSIDevice SCSIDevice; typedef struct SCSIDevice SCSIDevice;
typedef struct SCSIDeviceInfo SCSIDeviceInfo; typedef struct SCSIDeviceInfo SCSIDeviceInfo;
typedef void (*scsi_completionfn)(SCSIBus *bus, int reason, uint32_t tag,
uint32_t arg);
enum SCSIXferMode { enum SCSIXferMode {
SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */ SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
...@@ -74,20 +73,22 @@ struct SCSIDeviceInfo { ...@@ -74,20 +73,22 @@ struct SCSIDeviceInfo {
uint8_t *(*get_buf)(SCSIDevice *s, uint32_t tag); uint8_t *(*get_buf)(SCSIDevice *s, uint32_t tag);
}; };
typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv, struct SCSIBusOps {
int unit); void (*complete)(SCSIBus *bus, int reason, uint32_t tag, uint32_t arg);
};
struct SCSIBus { struct SCSIBus {
BusState qbus; BusState qbus;
int busnr; int busnr;
int tcq, ndev; int tcq, ndev;
scsi_completionfn complete; const SCSIBusOps *ops;
SCSIDevice *devs[MAX_SCSI_DEVS]; SCSIDevice *devs[MAX_SCSI_DEVS];
}; };
void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev, void scsi_bus_new(SCSIBus *bus, DeviceState *host, int tcq, int ndev,
scsi_completionfn complete); const SCSIBusOps *ops);
void scsi_qdev_register(SCSIDeviceInfo *info); void scsi_qdev_register(SCSIDeviceInfo *info);
static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
......
...@@ -907,6 +907,10 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data) ...@@ -907,6 +907,10 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
return 0; return 0;
} }
static const struct SCSIBusOps vscsi_scsi_ops = {
.complete = vscsi_command_complete
};
static int spapr_vscsi_init(VIOsPAPRDevice *dev) static int spapr_vscsi_init(VIOsPAPRDevice *dev)
{ {
VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev); VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
...@@ -923,7 +927,7 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev) ...@@ -923,7 +927,7 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev)
dev->crq.SendFunc = vscsi_do_crq; dev->crq.SendFunc = vscsi_do_crq;
scsi_bus_new(&s->bus, &dev->qdev, 1, VSCSI_REQ_LIMIT, scsi_bus_new(&s->bus, &dev->qdev, 1, VSCSI_REQ_LIMIT,
vscsi_command_complete); &vscsi_scsi_ops);
if (!dev->qdev.hotplugged) { if (!dev->qdev.hotplugged) {
scsi_bus_legacy_handle_cmdline(&s->bus); scsi_bus_legacy_handle_cmdline(&s->bus);
} }
......
...@@ -487,6 +487,10 @@ static void usb_msd_password_cb(void *opaque, int err) ...@@ -487,6 +487,10 @@ static void usb_msd_password_cb(void *opaque, int err)
qdev_unplug(&s->dev.qdev); qdev_unplug(&s->dev.qdev);
} }
static const struct SCSIBusOps usb_msd_scsi_ops = {
.complete = usb_msd_command_complete
};
static int usb_msd_initfn(USBDevice *dev) static int usb_msd_initfn(USBDevice *dev)
{ {
MSDState *s = DO_UPCAST(MSDState, dev, dev); MSDState *s = DO_UPCAST(MSDState, dev, dev);
...@@ -516,7 +520,7 @@ static int usb_msd_initfn(USBDevice *dev) ...@@ -516,7 +520,7 @@ static int usb_msd_initfn(USBDevice *dev)
} }
usb_desc_init(dev); usb_desc_init(dev);
scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete); scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, &usb_msd_scsi_ops);
s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable); s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
if (!s->scsi_dev) { if (!s->scsi_dev) {
return -1; return -1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册