| /* | 
 |  * Virtio SCSI HBA | 
 |  * | 
 |  * Copyright IBM, Corp. 2010 | 
 |  * | 
 |  * Authors: | 
 |  *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com> | 
 |  * | 
 |  * This work is licensed under the terms of the GNU GPL, version 2.  See | 
 |  * the COPYING file in the top-level directory. | 
 |  * | 
 |  */ | 
 |  | 
 | #ifndef _QEMU_VIRTIO_SCSI_H | 
 | #define _QEMU_VIRTIO_SCSI_H | 
 |  | 
 | /* Override CDB/sense data size: they are dynamic (guest controlled) in QEMU */ | 
 | #define VIRTIO_SCSI_CDB_SIZE 0 | 
 | #define VIRTIO_SCSI_SENSE_SIZE 0 | 
 | #include "standard-headers/linux/virtio_scsi.h" | 
 | #include "hw/virtio/virtio.h" | 
 | #include "hw/pci/pci.h" | 
 | #include "hw/scsi/scsi.h" | 
 | #include "sysemu/iothread.h" | 
 | #include "hw/virtio/dataplane/vring.h" | 
 |  | 
 | #define TYPE_VIRTIO_SCSI_COMMON "virtio-scsi-common" | 
 | #define VIRTIO_SCSI_COMMON(obj) \ | 
 |         OBJECT_CHECK(VirtIOSCSICommon, (obj), TYPE_VIRTIO_SCSI_COMMON) | 
 |  | 
 | #define TYPE_VIRTIO_SCSI "virtio-scsi-device" | 
 | #define VIRTIO_SCSI(obj) \ | 
 |         OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI) | 
 |  | 
 | #define VIRTIO_SCSI_VQ_SIZE     128 | 
 | #define VIRTIO_SCSI_MAX_CHANNEL 0 | 
 | #define VIRTIO_SCSI_MAX_TARGET  255 | 
 | #define VIRTIO_SCSI_MAX_LUN     16383 | 
 |  | 
 | typedef struct virtio_scsi_cmd_req VirtIOSCSICmdReq; | 
 | typedef struct virtio_scsi_cmd_resp VirtIOSCSICmdResp; | 
 | typedef struct virtio_scsi_ctrl_tmf_req VirtIOSCSICtrlTMFReq; | 
 | typedef struct virtio_scsi_ctrl_tmf_resp VirtIOSCSICtrlTMFResp; | 
 | typedef struct virtio_scsi_ctrl_an_req VirtIOSCSICtrlANReq; | 
 | typedef struct virtio_scsi_ctrl_an_resp VirtIOSCSICtrlANResp; | 
 | typedef struct virtio_scsi_event VirtIOSCSIEvent; | 
 | typedef struct virtio_scsi_config VirtIOSCSIConfig; | 
 |  | 
 | struct VirtIOSCSIConf { | 
 |     uint32_t num_queues; | 
 |     uint32_t max_sectors; | 
 |     uint32_t cmd_per_lun; | 
 |     char *vhostfd; | 
 |     char *wwpn; | 
 |     uint32_t boot_tpgt; | 
 |     IOThread *iothread; | 
 | }; | 
 |  | 
 | struct VirtIOSCSI; | 
 |  | 
 | typedef struct { | 
 |     struct VirtIOSCSI *parent; | 
 |     Vring vring; | 
 |     EventNotifier host_notifier; | 
 |     EventNotifier guest_notifier; | 
 | } VirtIOSCSIVring; | 
 |  | 
 | typedef struct VirtIOSCSICommon { | 
 |     VirtIODevice parent_obj; | 
 |     VirtIOSCSIConf conf; | 
 |  | 
 |     uint32_t sense_size; | 
 |     uint32_t cdb_size; | 
 |     VirtQueue *ctrl_vq; | 
 |     VirtQueue *event_vq; | 
 |     VirtQueue **cmd_vqs; | 
 | } VirtIOSCSICommon; | 
 |  | 
 | typedef struct VirtIOSCSI { | 
 |     VirtIOSCSICommon parent_obj; | 
 |  | 
 |     SCSIBus bus; | 
 |     int resetting; | 
 |     bool events_dropped; | 
 |  | 
 |     /* Fields for dataplane below */ | 
 |     AioContext *ctx; /* one iothread per virtio-scsi-pci for now */ | 
 |  | 
 |     /* Vring is used instead of vq in dataplane code, because of the underlying | 
 |      * memory layer thread safety */ | 
 |     VirtIOSCSIVring *ctrl_vring; | 
 |     VirtIOSCSIVring *event_vring; | 
 |     VirtIOSCSIVring **cmd_vrings; | 
 |     bool dataplane_started; | 
 |     bool dataplane_starting; | 
 |     bool dataplane_stopping; | 
 |     bool dataplane_disabled; | 
 |     bool dataplane_fenced; | 
 |     Error *blocker; | 
 |     Notifier migration_state_notifier; | 
 |     uint32_t host_features; | 
 | } VirtIOSCSI; | 
 |  | 
 | typedef struct VirtIOSCSIReq { | 
 |     VirtIOSCSI *dev; | 
 |     VirtQueue *vq; | 
 |     QEMUSGList qsgl; | 
 |     QEMUIOVector resp_iov; | 
 |  | 
 |     /* Note: | 
 |      * - fields before elem are initialized by virtio_scsi_init_req; | 
 |      * - elem is uninitialized at the time of allocation. | 
 |      * - fields after elem are zeroed by virtio_scsi_init_req. | 
 |      * */ | 
 |  | 
 |     VirtQueueElement elem; | 
 |     /* Set by dataplane code. */ | 
 |     VirtIOSCSIVring *vring; | 
 |  | 
 |     union { | 
 |         /* Used for two-stage request submission */ | 
 |         QTAILQ_ENTRY(VirtIOSCSIReq) next; | 
 |  | 
 |         /* Used for cancellation of request during TMFs */ | 
 |         int remaining; | 
 |     }; | 
 |  | 
 |     SCSIRequest *sreq; | 
 |     size_t resp_size; | 
 |     enum SCSIXferMode mode; | 
 |     union { | 
 |         VirtIOSCSICmdResp     cmd; | 
 |         VirtIOSCSICtrlTMFResp tmf; | 
 |         VirtIOSCSICtrlANResp  an; | 
 |         VirtIOSCSIEvent       event; | 
 |     } resp; | 
 |     union { | 
 |         VirtIOSCSICmdReq      cmd; | 
 |         VirtIOSCSICtrlTMFReq  tmf; | 
 |         VirtIOSCSICtrlANReq   an; | 
 |     } req; | 
 | } VirtIOSCSIReq; | 
 |  | 
 | typedef void (*HandleOutput)(VirtIODevice *, VirtQueue *); | 
 |  | 
 | void virtio_scsi_common_realize(DeviceState *dev, Error **errp, | 
 |                                 HandleOutput ctrl, HandleOutput evt, | 
 |                                 HandleOutput cmd); | 
 |  | 
 | void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp); | 
 | void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req); | 
 | bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req); | 
 | void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req); | 
 | VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq); | 
 | void virtio_scsi_free_req(VirtIOSCSIReq *req); | 
 | void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev, | 
 |                             uint32_t event, uint32_t reason); | 
 |  | 
 | void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread *iothread); | 
 | void virtio_scsi_dataplane_start(VirtIOSCSI *s); | 
 | void virtio_scsi_dataplane_stop(VirtIOSCSI *s); | 
 | void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req); | 
 | VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s, | 
 |                                          VirtIOSCSIVring *vring); | 
 |  | 
 | #endif /* _QEMU_VIRTIO_SCSI_H */ |