typedef struct SCSIBus SCSIBus;
typedef struct SCSIBusOps SCSIBusOps;
+typedef struct SCSICommand SCSICommand;
typedef struct SCSIDevice SCSIDevice;
typedef struct SCSIDeviceInfo SCSIDeviceInfo;
typedef struct SCSIRequest SCSIRequest;
+typedef struct SCSIReqOps SCSIReqOps;
enum SCSIXferMode {
SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
uint8_t ascq;
} SCSISense;
+#define SCSI_SENSE_BUF_SIZE 96
+
+struct SCSICommand {
+ uint8_t buf[SCSI_CMD_BUF_SIZE];
+ int len;
+ size_t xfer;
+ uint64_t lba;
+ enum SCSIXferMode mode;
+};
+
struct SCSIRequest {
SCSIBus *bus;
SCSIDevice *dev;
+ SCSIReqOps *ops;
uint32_t refcount;
uint32_t tag;
uint32_t lun;
uint32_t status;
- struct {
- uint8_t buf[SCSI_CMD_BUF_SIZE];
- int len;
- size_t xfer;
- uint64_t lba;
- enum SCSIXferMode mode;
- } cmd;
+ SCSICommand cmd;
BlockDriverAIOCB *aiocb;
+ uint8_t sense[SCSI_SENSE_BUF_SIZE];
+ uint32_t sense_len;
bool enqueued;
void *hba_private;
QTAILQ_ENTRY(SCSIRequest) next;
uint32_t id;
BlockConf conf;
SCSIDeviceInfo *info;
+ uint8_t sense[SCSI_SENSE_BUF_SIZE];
+ uint32_t sense_len;
QTAILQ_HEAD(, SCSIRequest) requests;
+ uint32_t lun;
int blocksize;
int type;
};
int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
/* scsi-bus.c */
+struct SCSIReqOps {
+ size_t size;
+ void (*free_req)(SCSIRequest *req);
+ int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
+ void (*read_data)(SCSIRequest *req);
+ void (*write_data)(SCSIRequest *req);
+ void (*cancel_io)(SCSIRequest *req);
+ uint8_t *(*get_buf)(SCSIRequest *req);
+};
+
typedef int (*scsi_qdev_initfn)(SCSIDevice *dev);
struct SCSIDeviceInfo {
DeviceInfo qdev;
void (*destroy)(SCSIDevice *s);
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
void *hba_private);
- void (*free_req)(SCSIRequest *req);
- int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
- void (*read_data)(SCSIRequest *req);
- void (*write_data)(SCSIRequest *req);
- void (*cancel_io)(SCSIRequest *req);
- uint8_t *(*get_buf)(SCSIRequest *req);
- int (*get_sense)(SCSIRequest *req, uint8_t *buf, int len);
+ SCSIReqOps reqops;
};
struct SCSIBusOps {
#define SENSE_CODE(x) sense_code_ ## x
-int scsi_build_sense(SCSISense sense, uint8_t *buf, int len, int fixed);
int scsi_sense_valid(SCSISense sense);
-SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag,
+SCSIRequest *scsi_req_alloc(SCSIReqOps *reqops, SCSIDevice *d, uint32_t tag,
uint32_t lun, void *hba_private);
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
- void *hba_private);
-int32_t scsi_req_enqueue(SCSIRequest *req, uint8_t *buf);
+ uint8_t *buf, void *hba_private);
+int32_t scsi_req_enqueue(SCSIRequest *req);
void scsi_req_free(SCSIRequest *req);
SCSIRequest *scsi_req_ref(SCSIRequest *req);
void scsi_req_unref(SCSIRequest *req);
+void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
void scsi_req_print(SCSIRequest *req);
void scsi_req_continue(SCSIRequest *req);
void scsi_req_data(SCSIRequest *req, int len);
-void scsi_req_complete(SCSIRequest *req);
+void scsi_req_complete(SCSIRequest *req, int status);
uint8_t *scsi_req_get_buf(SCSIRequest *req);
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
void scsi_req_abort(SCSIRequest *req, int status);
void scsi_req_cancel(SCSIRequest *req);
void scsi_device_purge_requests(SCSIDevice *sdev);
+int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
#endif