From patchwork Tue Jan 24 19:33:12 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony Liguori X-Patchwork-Id: 137617 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 94C69B6EE8 for ; Wed, 25 Jan 2012 06:34:54 +1100 (EST) Received: from localhost ([::1]:47593 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rpm8p-0002hL-3Y for incoming@patchwork.ozlabs.org; Tue, 24 Jan 2012 14:34:51 -0500 Received: from eggs.gnu.org ([140.186.70.92]:50026) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rpm8b-0002a1-Sp for qemu-devel@nongnu.org; Tue, 24 Jan 2012 14:34:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Rpm8W-0004bj-Nu for qemu-devel@nongnu.org; Tue, 24 Jan 2012 14:34:37 -0500 Received: from e37.co.us.ibm.com ([32.97.110.158]:39998) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rpm8W-0004bL-94 for qemu-devel@nongnu.org; Tue, 24 Jan 2012 14:34:32 -0500 Received: from /spool/local by e37.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 24 Jan 2012 12:34:30 -0700 Received: from d03dlp02.boulder.ibm.com (9.17.202.178) by e37.co.us.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 24 Jan 2012 12:34:00 -0700 Received: from d03relay04.boulder.ibm.com (d03relay04.boulder.ibm.com [9.17.195.106]) by d03dlp02.boulder.ibm.com (Postfix) with ESMTP id C17383E4004C for ; Tue, 24 Jan 2012 12:33:59 -0700 (MST) Received: from d03av01.boulder.ibm.com (d03av01.boulder.ibm.com [9.17.195.167]) by d03relay04.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q0OJXkQc073130 for ; Tue, 24 Jan 2012 12:33:48 -0700 Received: from d03av01.boulder.ibm.com (loopback [127.0.0.1]) by d03av01.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q0OJXkXl008910 for ; Tue, 24 Jan 2012 12:33:46 -0700 Received: from titi.austin.rr.com (sig-9-65-115-125.mts.ibm.com [9.65.115.125]) by d03av01.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q0OJXNdc006821; Tue, 24 Jan 2012 12:33:45 -0700 From: Anthony Liguori To: qemu-devel@nongnu.org Date: Tue, 24 Jan 2012 13:33:12 -0600 Message-Id: <1327433600-7403-21-git-send-email-aliguori@us.ibm.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1327433600-7403-1-git-send-email-aliguori@us.ibm.com> References: <1327433600-7403-1-git-send-email-aliguori@us.ibm.com> X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12012419-7408-0000-0000-00000222E664 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 32.97.110.158 Cc: Kevin Wolf , Anthony Liguori , Paul Brook Subject: [Qemu-devel] [PATCH 20/28] scsi: convert to QEMU Object Model X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Anthony Liguori --- hw/scsi-bus.c | 95 +++++++++++++++++++++++--------- hw/scsi-disk.c | 159 ++++++++++++++++++++++++++++++++--------------------- hw/scsi-generic.c | 29 ++++++---- hw/scsi.h | 31 ++++++---- 4 files changed, 201 insertions(+), 113 deletions(-) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 64e709e..d017ece 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -23,6 +23,42 @@ static struct BusInfo scsi_bus_info = { }; static int next_scsi_bus; +static int scsi_device_init(SCSIDevice *s) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); + if (sc->init) { + return sc->init(s); + } + return 0; +} + +static void scsi_device_destroy(SCSIDevice *s) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); + if (sc->destroy) { + sc->destroy(s); + } +} + +static SCSIRequest *scsi_device_alloc_req(SCSIDevice *s, uint32_t tag, uint32_t lun, + uint8_t *buf, void *hba_private) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); + if (sc->alloc_req) { + return sc->alloc_req(s, tag, lun, buf, hba_private); + } + + return NULL; +} + +static void scsi_device_unit_attention_reported(SCSIDevice *s) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); + if (sc->unit_attention_reported) { + sc->unit_attention_reported(s); + } +} + /* Create a scsi bus, and attach devices to it. */ void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info) { @@ -81,8 +117,7 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state) static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base) { - SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev); - SCSIDeviceInfo *info = DO_UPCAST(SCSIDeviceInfo, qdev, base); + SCSIDevice *dev = SCSI_DEVICE(qdev); SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); SCSIDevice *d; int rc = -1; @@ -126,9 +161,8 @@ static int scsi_qdev_init(DeviceState *qdev, DeviceInfo *base) } } - dev->info = info; QTAILQ_INIT(&dev->requests); - rc = dev->info->init(dev); + rc = scsi_device_init(dev); if (rc == 0) { dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb, dev); @@ -140,24 +174,22 @@ err: static int scsi_qdev_exit(DeviceState *qdev) { - SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev); + SCSIDevice *dev = SCSI_DEVICE(qdev); if (dev->vmsentry) { qemu_del_vm_change_state_handler(dev->vmsentry); } - if (dev->info->destroy) { - dev->info->destroy(dev); - } + scsi_device_destroy(dev); return 0; } -void scsi_qdev_register(SCSIDeviceInfo *info) +void scsi_qdev_register(DeviceInfo *info) { - info->qdev.bus_info = &scsi_bus_info; - info->qdev.init = scsi_qdev_init; - info->qdev.unplug = qdev_simple_unplug_cb; - info->qdev.exit = scsi_qdev_exit; - qdev_register(&info->qdev); + info->bus_info = &scsi_bus_info; + info->init = scsi_qdev_init; + info->unplug = qdev_simple_unplug_cb; + info->exit = scsi_qdev_exit; + qdev_register_subclass(info, TYPE_SCSI_DEVICE); } /* handle legacy '-drive if=scsi,...' cmd line args */ @@ -182,7 +214,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, } if (qdev_init(dev) < 0) return NULL; - return DO_UPCAST(SCSIDevice, qdev, dev); + return SCSI_DEVICE(dev); } int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) @@ -278,7 +310,7 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r) found_lun0 = false; n = 0; QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) { - SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev); + SCSIDevice *dev = SCSI_DEVICE(qdev); if (dev->channel == channel && dev->id == id) { if (dev->lun == 0) { @@ -300,7 +332,7 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r) stl_be_p(&r->buf, n); i = found_lun0 ? 8 : 16; QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) { - SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev); + SCSIDevice *dev = SCSI_DEVICE(qdev); if (dev->channel == channel && dev->id == id) { store_lun(&r->buf[i], dev->lun); @@ -398,9 +430,7 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf) MIN(req->cmd.xfer, sizeof r->buf), (req->cmd.buf[1] & 1) == 0); if (r->req.dev->sense_is_ua) { - if (r->req.dev->info->unit_attention_reported) { - r->req.dev->info->unit_attention_reported(req->dev); - } + scsi_device_unit_attention_reported(req->dev); r->req.dev->sense_len = 0; r->req.dev->sense_is_ua = false; } @@ -507,7 +537,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, req = scsi_req_alloc(&reqops_target_command, d, tag, lun, hba_private); } else { - req = d->info->alloc_req(d, tag, lun, buf, hba_private); + req = scsi_device_alloc_req(d, tag, lun, buf, hba_private); } } @@ -597,9 +627,7 @@ int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len) * Here we handle unit attention clearing for UA_INTLCK_CTRL == 00b. */ if (req->dev->sense_is_ua) { - if (req->dev->info->unit_attention_reported) { - req->dev->info->unit_attention_reported(req->dev); - } + scsi_device_unit_attention_reported(req->dev); req->dev->sense_len = 0; req->dev->sense_is_ua = false; } @@ -1367,7 +1395,7 @@ void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense) static char *scsibus_get_fw_dev_path(DeviceState *dev) { - SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev); + SCSIDevice *d = SCSI_DEVICE(dev); char path[100]; snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel, @@ -1382,7 +1410,7 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun) SCSIDevice *target_dev = NULL; QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) { - SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev); + SCSIDevice *dev = SCSI_DEVICE(qdev); if (dev->channel == channel && dev->id == id) { if (dev->lun == lun) { @@ -1393,3 +1421,18 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun) } return target_dev; } + +static TypeInfo scsi_device_type_info = { + .name = TYPE_SCSI_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(SCSIDevice), + .abstract = true, + .class_size = sizeof(SCSIDeviceClass), +}; + +static void scsi_register_devices(void) +{ + type_register_static(&scsi_device_type_info); +} + +device_init(scsi_register_devices); diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 5d8bf53..cb61d82 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1720,75 +1720,108 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag, DEFINE_PROP_STRING("ver", SCSIDiskState, version), \ DEFINE_PROP_STRING("serial", SCSIDiskState, serial) -static SCSIDeviceInfo scsi_disk_info[] = { - { - .qdev.name = "scsi-hd", - .qdev.fw_name = "disk", - .qdev.desc = "virtual SCSI disk", - .qdev.size = sizeof(SCSIDiskState), - .qdev.reset = scsi_disk_reset, - .init = scsi_hd_initfn, - .destroy = scsi_destroy, - .alloc_req = scsi_new_request, - .unit_attention_reported = scsi_disk_unit_attention_reported, - .qdev.props = (Property[]) { - DEFINE_SCSI_DISK_PROPERTIES(), - DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false), - DEFINE_PROP_END_OF_LIST(), - } - },{ - .qdev.name = "scsi-cd", - .qdev.fw_name = "disk", - .qdev.desc = "virtual SCSI CD-ROM", - .qdev.size = sizeof(SCSIDiskState), - .qdev.reset = scsi_disk_reset, - .init = scsi_cd_initfn, - .destroy = scsi_destroy, - .alloc_req = scsi_new_request, - .unit_attention_reported = scsi_disk_unit_attention_reported, - .qdev.props = (Property[]) { - DEFINE_SCSI_DISK_PROPERTIES(), - DEFINE_PROP_END_OF_LIST(), - }, +static void scsi_hd_class_initfn(ObjectClass *klass, void *data) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); + + sc->init = scsi_hd_initfn; + sc->destroy = scsi_destroy; + sc->alloc_req = scsi_new_request; + sc->unit_attention_reported = scsi_disk_unit_attention_reported; +} + +static DeviceInfo scsi_hd_info = { + .name = "scsi-hd", + .fw_name = "disk", + .desc = "virtual SCSI disk", + .size = sizeof(SCSIDiskState), + .reset = scsi_disk_reset, + .class_init = scsi_hd_class_initfn, + .props = (Property[]) { + DEFINE_SCSI_DISK_PROPERTIES(), + DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false), + DEFINE_PROP_END_OF_LIST(), + }, +}; + +static void scsi_cd_class_initfn(ObjectClass *klass, void *data) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); + + sc->init = scsi_cd_initfn; + sc->destroy = scsi_destroy; + sc->alloc_req = scsi_new_request; + sc->unit_attention_reported = scsi_disk_unit_attention_reported; +} + +static DeviceInfo scsi_cd_info = { + .name = "scsi-cd", + .fw_name = "disk", + .desc = "virtual SCSI CD-ROM", + .size = sizeof(SCSIDiskState), + .reset = scsi_disk_reset, + .class_init = scsi_cd_class_initfn, + .props = (Property[]) { + DEFINE_SCSI_DISK_PROPERTIES(), + DEFINE_PROP_END_OF_LIST(), + }, +}; + #ifdef __linux__ - },{ - .qdev.name = "scsi-block", - .qdev.fw_name = "disk", - .qdev.desc = "SCSI block device passthrough", - .qdev.size = sizeof(SCSIDiskState), - .qdev.reset = scsi_disk_reset, - .init = scsi_block_initfn, - .destroy = scsi_destroy, - .alloc_req = scsi_block_new_request, - .qdev.props = (Property[]) { - DEFINE_SCSI_DISK_PROPERTIES(), - DEFINE_PROP_END_OF_LIST(), - }, +static void scsi_block_class_initfn(ObjectClass *klass, void *data) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); + + sc->init = scsi_block_initfn; + sc->destroy = scsi_destroy; + sc->alloc_req = scsi_block_new_request; +} + +static DeviceInfo scsi_block_info = { + .name = "scsi-block", + .fw_name = "disk", + .desc = "SCSI block device passthrough", + .size = sizeof(SCSIDiskState), + .reset = scsi_disk_reset, + .class_init = scsi_block_class_initfn, + .props = (Property[]) { + DEFINE_SCSI_DISK_PROPERTIES(), + DEFINE_PROP_END_OF_LIST(), + }, +}; #endif - },{ - .qdev.name = "scsi-disk", /* legacy -device scsi-disk */ - .qdev.fw_name = "disk", - .qdev.desc = "virtual SCSI disk or CD-ROM (legacy)", - .qdev.size = sizeof(SCSIDiskState), - .qdev.reset = scsi_disk_reset, - .init = scsi_disk_initfn, - .destroy = scsi_destroy, - .alloc_req = scsi_new_request, - .unit_attention_reported = scsi_disk_unit_attention_reported, - .qdev.props = (Property[]) { - DEFINE_SCSI_DISK_PROPERTIES(), - DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false), - DEFINE_PROP_END_OF_LIST(), - } + +static void scsi_disk_class_initfn(ObjectClass *klass, void *data) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); + + sc->init = scsi_disk_initfn; + sc->destroy = scsi_destroy; + sc->alloc_req = scsi_new_request; + sc->unit_attention_reported = scsi_disk_unit_attention_reported; +} + +static DeviceInfo scsi_disk_info = { + .name = "scsi-disk", /* legacy -device scsi-disk */ + .fw_name = "disk", + .desc = "virtual SCSI disk or CD-ROM (legacy)", + .size = sizeof(SCSIDiskState), + .reset = scsi_disk_reset, + .class_init = scsi_disk_class_initfn, + .props = (Property[]) { + DEFINE_SCSI_DISK_PROPERTIES(), + DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false), + DEFINE_PROP_END_OF_LIST(), } }; static void scsi_disk_register_devices(void) { - int i; - - for (i = 0; i < ARRAY_SIZE(scsi_disk_info); i++) { - scsi_qdev_register(&scsi_disk_info[i]); - } + scsi_qdev_register(&scsi_hd_info); + scsi_qdev_register(&scsi_cd_info); +#ifdef __linux__ + scsi_qdev_register(&scsi_block_info); +#endif + scsi_qdev_register(&scsi_disk_info); } device_init(scsi_disk_register_devices) diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 0aebcdd..5cf4005 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -357,7 +357,7 @@ static int get_stream_blocksize(BlockDriverState *bdrv) static void scsi_generic_reset(DeviceState *dev) { - SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev); + SCSIDevice *s = SCSI_DEVICE(dev); scsi_device_purge_requests(s, SENSE_CODE(RESET)); } @@ -457,16 +457,23 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, return req; } -static SCSIDeviceInfo scsi_generic_info = { - .qdev.name = "scsi-generic", - .qdev.fw_name = "disk", - .qdev.desc = "pass through generic scsi device (/dev/sg*)", - .qdev.size = sizeof(SCSIDevice), - .qdev.reset = scsi_generic_reset, - .init = scsi_generic_initfn, - .destroy = scsi_destroy, - .alloc_req = scsi_new_request, - .qdev.props = (Property[]) { +static void scsi_generic_class_initfn(ObjectClass *klass, void *data) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); + + sc->init = scsi_generic_initfn; + sc->destroy = scsi_destroy; + sc->alloc_req = scsi_new_request; +} + +static DeviceInfo scsi_generic_info = { + .name = "scsi-generic", + .fw_name = "disk", + .desc = "pass through generic scsi device (/dev/sg*)", + .size = sizeof(SCSIDevice), + .reset = scsi_generic_reset, + .class_init = scsi_generic_class_initfn, + .props = (Property[]) { DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf), DEFINE_PROP_END_OF_LIST(), }, diff --git a/hw/scsi.h b/hw/scsi.h index ab6e952..4290b20 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -13,7 +13,6 @@ typedef struct SCSIBus SCSIBus; typedef struct SCSIBusInfo SCSIBusInfo; typedef struct SCSICommand SCSICommand; typedef struct SCSIDevice SCSIDevice; -typedef struct SCSIDeviceInfo SCSIDeviceInfo; typedef struct SCSIRequest SCSIRequest; typedef struct SCSIReqOps SCSIReqOps; @@ -58,6 +57,23 @@ struct SCSIRequest { QTAILQ_ENTRY(SCSIRequest) next; }; +#define TYPE_SCSI_DEVICE "scsi-device" +#define SCSI_DEVICE(obj) \ + OBJECT_CHECK(SCSIDevice, (obj), TYPE_SCSI_DEVICE) +#define SCSI_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(SCSIDeviceClass, (klass), TYPE_SCSI_DEVICE) +#define SCSI_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SCSIDeviceClass, (obj), TYPE_SCSI_DEVICE) + +typedef struct SCSIDeviceClass { + DeviceClass parent_class; + int (*init)(SCSIDevice *dev); + void (*destroy)(SCSIDevice *s); + SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun, + uint8_t *buf, void *hba_private); + void (*unit_attention_reported)(SCSIDevice *s); +} SCSIDeviceClass; + struct SCSIDevice { DeviceState qdev; @@ -65,7 +81,6 @@ struct SCSIDevice QEMUBH *bh; uint32_t id; BlockConf conf; - SCSIDeviceInfo *info; SCSISense unit_attention; bool sense_is_ua; uint8_t sense[SCSI_SENSE_BUF_SIZE]; @@ -93,16 +108,6 @@ struct SCSIReqOps { uint8_t *(*get_buf)(SCSIRequest *req); }; -typedef int (*scsi_qdev_initfn)(SCSIDevice *dev); -struct SCSIDeviceInfo { - DeviceInfo qdev; - scsi_qdev_initfn init; - void (*destroy)(SCSIDevice *s); - SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun, - uint8_t *buf, void *hba_private); - void (*unit_attention_reported)(SCSIDevice *s); -}; - struct SCSIBusInfo { int tcq; int max_channel, max_target, max_lun; @@ -120,7 +125,7 @@ struct SCSIBus { }; void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info); -void scsi_qdev_register(SCSIDeviceInfo *info); +void scsi_qdev_register(DeviceInfo *info); static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) {