qemu/hw/scsi.h
<<
>>
Prefs
   1#ifndef QEMU_HW_SCSI_H
   2#define QEMU_HW_SCSI_H
   3
   4#include "qdev.h"
   5#include "block.h"
   6#include "hw/block-common.h"
   7#include "sysemu.h"
   8
   9#define MAX_SCSI_DEVS   255
  10
  11#define SCSI_CMD_BUF_SIZE     16
  12
  13typedef struct SCSIBus SCSIBus;
  14typedef struct SCSIBusInfo SCSIBusInfo;
  15typedef struct SCSICommand SCSICommand;
  16typedef struct SCSIDevice SCSIDevice;
  17typedef struct SCSIRequest SCSIRequest;
  18typedef struct SCSIReqOps SCSIReqOps;
  19
  20enum SCSIXferMode {
  21    SCSI_XFER_NONE,      /*  TEST_UNIT_READY, ...            */
  22    SCSI_XFER_FROM_DEV,  /*  READ, INQUIRY, MODE_SENSE, ...  */
  23    SCSI_XFER_TO_DEV,    /*  WRITE, MODE_SELECT, ...         */
  24};
  25
  26typedef struct SCSISense {
  27    uint8_t key;
  28    uint8_t asc;
  29    uint8_t ascq;
  30} SCSISense;
  31
  32#define SCSI_SENSE_BUF_SIZE 96
  33
  34struct SCSICommand {
  35    uint8_t buf[SCSI_CMD_BUF_SIZE];
  36    int len;
  37    size_t xfer;
  38    uint64_t lba;
  39    enum SCSIXferMode mode;
  40};
  41
  42struct SCSIRequest {
  43    SCSIBus           *bus;
  44    SCSIDevice        *dev;
  45    const SCSIReqOps  *ops;
  46    uint32_t          refcount;
  47    uint32_t          tag;
  48    uint32_t          lun;
  49    uint32_t          status;
  50    size_t            resid;
  51    SCSICommand       cmd;
  52    BlockDriverAIOCB  *aiocb;
  53    QEMUSGList        *sg;
  54    bool              dma_started;
  55    uint8_t sense[SCSI_SENSE_BUF_SIZE];
  56    uint32_t sense_len;
  57    bool enqueued;
  58    bool io_canceled;
  59    bool retry;
  60    void *hba_private;
  61    QTAILQ_ENTRY(SCSIRequest) next;
  62};
  63
  64#define TYPE_SCSI_DEVICE "scsi-device"
  65#define SCSI_DEVICE(obj) \
  66     OBJECT_CHECK(SCSIDevice, (obj), TYPE_SCSI_DEVICE)
  67#define SCSI_DEVICE_CLASS(klass) \
  68     OBJECT_CLASS_CHECK(SCSIDeviceClass, (klass), TYPE_SCSI_DEVICE)
  69#define SCSI_DEVICE_GET_CLASS(obj) \
  70     OBJECT_GET_CLASS(SCSIDeviceClass, (obj), TYPE_SCSI_DEVICE)
  71
  72typedef struct SCSIDeviceClass {
  73    DeviceClass parent_class;
  74    int (*init)(SCSIDevice *dev);
  75    void (*destroy)(SCSIDevice *s);
  76    SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
  77                              uint8_t *buf, void *hba_private);
  78    void (*unit_attention_reported)(SCSIDevice *s);
  79} SCSIDeviceClass;
  80
  81struct SCSIDevice
  82{
  83    DeviceState qdev;
  84    VMChangeStateEntry *vmsentry;
  85    QEMUBH *bh;
  86    uint32_t id;
  87    BlockConf conf;
  88    SCSISense unit_attention;
  89    bool sense_is_ua;
  90    uint8_t sense[SCSI_SENSE_BUF_SIZE];
  91    uint32_t sense_len;
  92    QTAILQ_HEAD(, SCSIRequest) requests;
  93    uint32_t channel;
  94    uint32_t lun;
  95    int blocksize;
  96    int type;
  97    uint64_t max_lba;
  98};
  99
 100extern const VMStateDescription vmstate_scsi_device;
 101
 102#define VMSTATE_SCSI_DEVICE(_field, _state) {                        \
 103    .name       = (stringify(_field)),                               \
 104    .size       = sizeof(SCSIDevice),                                \
 105    .vmsd       = &vmstate_scsi_device,                              \
 106    .flags      = VMS_STRUCT,                                        \
 107    .offset     = vmstate_offset_value(_state, _field, SCSIDevice),  \
 108}
 109
 110/* cdrom.c */
 111int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
 112int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
 113
 114/* scsi-bus.c */
 115struct SCSIReqOps {
 116    size_t size;
 117    void (*free_req)(SCSIRequest *req);
 118    int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
 119    void (*read_data)(SCSIRequest *req);
 120    void (*write_data)(SCSIRequest *req);
 121    void (*cancel_io)(SCSIRequest *req);
 122    uint8_t *(*get_buf)(SCSIRequest *req);
 123
 124    void (*save_request)(QEMUFile *f, SCSIRequest *req);
 125    void (*load_request)(QEMUFile *f, SCSIRequest *req);
 126};
 127
 128struct SCSIBusInfo {
 129    int tcq;
 130    int max_channel, max_target, max_lun;
 131    void (*transfer_data)(SCSIRequest *req, uint32_t arg);
 132    void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid);
 133    void (*cancel)(SCSIRequest *req);
 134    void (*hotplug)(SCSIBus *bus, SCSIDevice *dev);
 135    void (*hot_unplug)(SCSIBus *bus, SCSIDevice *dev);
 136    void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
 137    QEMUSGList *(*get_sg_list)(SCSIRequest *req);
 138
 139    void (*save_request)(QEMUFile *f, SCSIRequest *req);
 140    void *(*load_request)(QEMUFile *f, SCSIRequest *req);
 141    void (*free_request)(SCSIBus *bus, void *priv);
 142};
 143
 144#define TYPE_SCSI_BUS "SCSI"
 145#define SCSI_BUS(obj) OBJECT_CHECK(SCSIBus, (obj), TYPE_SCSI_BUS)
 146
 147struct SCSIBus {
 148    BusState qbus;
 149    int busnr;
 150
 151    SCSISense unit_attention;
 152    const SCSIBusInfo *info;
 153};
 154
 155void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
 156
 157static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
 158{
 159    return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
 160}
 161
 162SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
 163                                      int unit, bool removable, int bootindex);
 164int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
 165
 166/*
 167 * Predefined sense codes
 168 */
 169
 170/* No sense data available */
 171extern const struct SCSISense sense_code_NO_SENSE;
 172/* LUN not ready, Manual intervention required */
 173extern const struct SCSISense sense_code_LUN_NOT_READY;
 174/* LUN not ready, Medium not present */
 175extern const struct SCSISense sense_code_NO_MEDIUM;
 176/* LUN not ready, medium removal prevented */
 177extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED;
 178/* Hardware error, internal target failure */
 179extern const struct SCSISense sense_code_TARGET_FAILURE;
 180/* Illegal request, invalid command operation code */
 181extern const struct SCSISense sense_code_INVALID_OPCODE;
 182/* Illegal request, LBA out of range */
 183extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
 184/* Illegal request, Invalid field in CDB */
 185extern const struct SCSISense sense_code_INVALID_FIELD;
 186/* Illegal request, Invalid field in parameter list */
 187extern const struct SCSISense sense_code_INVALID_PARAM;
 188/* Illegal request, Parameter list length error */
 189extern const struct SCSISense sense_code_INVALID_PARAM_LEN;
 190/* Illegal request, LUN not supported */
 191extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
 192/* Illegal request, Saving parameters not supported */
 193extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED;
 194/* Illegal request, Incompatible format */
 195extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT;
 196/* Illegal request, medium removal prevented */
 197extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED;
 198/* Command aborted, I/O process terminated */
 199extern const struct SCSISense sense_code_IO_ERROR;
 200/* Command aborted, I_T Nexus loss occurred */
 201extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
 202/* Command aborted, Logical Unit failure */
 203extern const struct SCSISense sense_code_LUN_FAILURE;
 204/* LUN not ready, Capacity data has changed */
 205extern const struct SCSISense sense_code_CAPACITY_CHANGED;
 206/* LUN not ready, Medium not present */
 207extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM;
 208/* Unit attention, Power on, reset or bus device reset occurred */
 209extern const struct SCSISense sense_code_RESET;
 210/* Unit attention, Medium may have changed*/
 211extern const struct SCSISense sense_code_MEDIUM_CHANGED;
 212/* Unit attention, Reported LUNs data has changed */
 213extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED;
 214/* Unit attention, Device internal reset */
 215extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
 216/* Data Protection, Write Protected */
 217extern const struct SCSISense sense_code_WRITE_PROTECTED;
 218
 219#define SENSE_CODE(x) sense_code_ ## x
 220
 221uint32_t scsi_data_cdb_length(uint8_t *buf);
 222uint32_t scsi_cdb_length(uint8_t *buf);
 223int scsi_sense_valid(SCSISense sense);
 224int scsi_build_sense(uint8_t *in_buf, int in_len,
 225                     uint8_t *buf, int len, bool fixed);
 226
 227SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
 228                            uint32_t tag, uint32_t lun, void *hba_private);
 229SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
 230                          uint8_t *buf, void *hba_private);
 231int32_t scsi_req_enqueue(SCSIRequest *req);
 232void scsi_req_free(SCSIRequest *req);
 233SCSIRequest *scsi_req_ref(SCSIRequest *req);
 234void scsi_req_unref(SCSIRequest *req);
 235
 236void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
 237void scsi_req_print(SCSIRequest *req);
 238void scsi_req_continue(SCSIRequest *req);
 239void scsi_req_data(SCSIRequest *req, int len);
 240void scsi_req_complete(SCSIRequest *req, int status);
 241uint8_t *scsi_req_get_buf(SCSIRequest *req);
 242int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
 243void scsi_req_abort(SCSIRequest *req, int status);
 244void scsi_req_cancel(SCSIRequest *req);
 245void scsi_req_retry(SCSIRequest *req);
 246void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
 247void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
 248void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
 249int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
 250SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
 251
 252/* scsi-generic.c. */
 253extern const SCSIReqOps scsi_generic_req_ops;
 254
 255#endif
 256