blob: 0b726bc78c631c2e236ccdf442ac30e4aac7e05e [file] [log] [blame]
Gerd Hoffmann1e376072009-11-26 15:33:47 +01001#ifndef QEMU_HW_SCSI_H
2#define QEMU_HW_SCSI_H
Gerd Hoffmann43b443b2009-10-30 09:54:00 +01003
Markus Armbrusterdb725812019-08-12 07:23:50 +02004#include "block/aio.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +01005#include "hw/block/block.h"
Markus Armbrustera27bd6c2019-08-12 07:23:51 +02006#include "hw/qdev-core.h"
Paolo Bonzinie5b57282017-08-22 07:08:27 +02007#include "scsi/utils.h"
Fam Zheng8e0a9322014-09-28 09:48:00 +08008#include "qemu/notify.h"
Eduardo Habkostdb1015e2020-09-03 16:43:22 -04009#include "qom/object.h"
Gerd Hoffmann43b443b2009-10-30 09:54:00 +010010
Markus Armbruster27d6bf42011-01-28 11:21:40 +010011#define MAX_SCSI_DEVS 255
12
Gerd Hoffmann43b443b2009-10-30 09:54:00 +010013typedef struct SCSIBus SCSIBus;
Paolo Bonziniafd40302011-08-13 15:44:45 +020014typedef struct SCSIBusInfo SCSIBusInfo;
Gerd Hoffmann43b443b2009-10-30 09:54:00 +010015typedef struct SCSIDevice SCSIDevice;
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +020016typedef struct SCSIRequest SCSIRequest;
Paolo Bonzini8dbd4572011-08-03 10:49:08 +020017typedef struct SCSIReqOps SCSIReqOps;
Gerd Hoffmann43b443b2009-10-30 09:54:00 +010018
Fam Zheng2e323f02014-03-06 16:26:02 +080019#define SCSI_SENSE_BUF_SIZE_OLD 96
Fam Zhengc5f52872014-01-24 15:02:24 +080020#define SCSI_SENSE_BUF_SIZE 252
Hannes Reineckec9b66092020-11-16 19:31:13 +010021#define DEFAULT_IO_TIMEOUT 30
Paolo Bonzinib45ef672011-08-03 10:49:07 +020022
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +020023struct SCSIRequest {
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010024 SCSIBus *bus;
25 SCSIDevice *dev;
Paolo Bonziniadcf2752011-10-12 12:57:59 +020026 const SCSIReqOps *ops;
Paolo Bonziniad2d30f2011-04-18 16:01:56 +020027 uint32_t refcount;
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010028 uint32_t tag;
Gerd Hoffmann89b08ae2009-11-26 15:33:50 +010029 uint32_t lun;
Hannes Reineckef3126d62021-02-24 19:14:50 +010030 int16_t status;
31 int16_t host_status;
Fam Zheng61e68b32014-09-16 15:20:17 +080032 void *hba_private;
Paolo Bonzini01e95452011-07-06 11:55:37 +020033 size_t resid;
Paolo Bonzini2599aec2011-08-03 10:49:11 +020034 SCSICommand cmd;
Fam Zheng8e0a9322014-09-28 09:48:00 +080035 NotifierList cancel_notifiers;
Fam Zheng61e68b32014-09-16 15:20:17 +080036
37 /* Note:
38 * - fields before sense are initialized by scsi_req_alloc;
39 * - sense[] is uninitialized;
40 * - fields after sense are memset to 0 by scsi_req_alloc.
41 * */
42
43 uint8_t sense[SCSI_SENSE_BUF_SIZE];
44 uint32_t sense_len;
45 bool enqueued;
46 bool io_canceled;
47 bool retry;
48 bool dma_started;
Markus Armbruster7c84b1b2014-10-07 13:59:14 +020049 BlockAIOCB *aiocb;
Paolo Bonzini3d5aba92011-07-06 11:26:47 +020050 QEMUSGList *sg;
Gerd Hoffmann9af99d92009-11-26 15:33:49 +010051 QTAILQ_ENTRY(SCSIRequest) next;
Hannes Reinecke5c6c0e52011-04-18 12:35:39 +020052};
Gerd Hoffmann4c41d2e2009-11-26 15:33:48 +010053
Anthony Liguorib9eea3e2011-12-15 14:50:08 -060054#define TYPE_SCSI_DEVICE "scsi-device"
Eduardo Habkosta489d192020-09-16 14:25:18 -040055OBJECT_DECLARE_TYPE(SCSIDevice, SCSIDeviceClass, SCSI_DEVICE)
Anthony Liguorib9eea3e2011-12-15 14:50:08 -060056
Eduardo Habkostdb1015e2020-09-03 16:43:22 -040057struct SCSIDeviceClass {
Anthony Liguorib9eea3e2011-12-15 14:50:08 -060058 DeviceClass parent_class;
Fam Zhenga818a4b2014-08-12 10:12:55 +080059 void (*realize)(SCSIDevice *dev, Error **errp);
Markus Armbrusterb69c3c22020-05-05 17:29:24 +020060 void (*unrealize)(SCSIDevice *dev);
Paolo Bonziniff34c322014-07-16 10:39:05 +020061 int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
62 void *hba_private);
Anthony Liguorib9eea3e2011-12-15 14:50:08 -060063 SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
64 uint8_t *buf, void *hba_private);
65 void (*unit_attention_reported)(SCSIDevice *s);
Eduardo Habkostdb1015e2020-09-03 16:43:22 -040066};
Anthony Liguorib9eea3e2011-12-15 14:50:08 -060067
Gerd Hoffmann43b443b2009-10-30 09:54:00 +010068struct SCSIDevice
69{
70 DeviceState qdev;
Paolo Bonzini71544d32011-10-25 12:53:36 +020071 VMChangeStateEntry *vmsentry;
72 QEMUBH *bh;
Gerd Hoffmann43b443b2009-10-30 09:54:00 +010073 uint32_t id;
Christoph Hellwig428c1492010-02-10 23:37:09 +010074 BlockConf conf;
Paolo Bonzini6dc06f02011-08-03 10:49:17 +020075 SCSISense unit_attention;
Paolo Bonzini3653d8c2011-09-13 16:19:53 +020076 bool sense_is_ua;
Paolo Bonzinib45ef672011-08-03 10:49:07 +020077 uint8_t sense[SCSI_SENSE_BUF_SIZE];
78 uint32_t sense_len;
Gerd Hoffmann9af99d92009-11-26 15:33:49 +010079 QTAILQ_HEAD(, SCSIRequest) requests;
Paolo Bonzini0d3545e2011-07-27 23:24:50 +020080 uint32_t channel;
Paolo Bonzini87dcd1b2011-08-03 10:49:12 +020081 uint32_t lun;
Gerd Hoffmannb07995e2009-11-26 15:33:52 +010082 int blocksize;
Gerd Hoffmann91376652009-11-26 15:33:54 +010083 int type;
Paolo Bonzini78779032011-10-13 10:39:50 +020084 uint64_t max_lba;
Paolo Bonzini2ecab402016-01-12 11:47:00 +010085 uint64_t wwn;
86 uint64_t port_wwn;
Paolo Bonzini2343be02018-04-05 18:09:51 +020087 int scsi_version;
88 int default_scsi_version;
Hannes Reineckec9b66092020-11-16 19:31:13 +010089 uint32_t io_timeout;
Daniel Henrique Barbozaa71c7752018-06-27 14:24:32 -030090 bool needs_vpd_bl_emulation;
Kevin Wolf4f71fb42019-04-26 19:29:47 +020091 bool hba_supports_iothread;
Gerd Hoffmann43b443b2009-10-30 09:54:00 +010092};
93
Paolo Bonzini63f740d2011-12-02 16:27:02 +010094extern const VMStateDescription vmstate_scsi_device;
95
96#define VMSTATE_SCSI_DEVICE(_field, _state) { \
97 .name = (stringify(_field)), \
98 .size = sizeof(SCSIDevice), \
99 .vmsd = &vmstate_scsi_device, \
100 .flags = VMS_STRUCT, \
101 .offset = vmstate_offset_value(_state, _field, SCSIDevice), \
102}
103
Gerd Hoffmann43b443b2009-10-30 09:54:00 +0100104/* cdrom.c */
105int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
106int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
107
108/* scsi-bus.c */
Paolo Bonzini8dbd4572011-08-03 10:49:08 +0200109struct SCSIReqOps {
110 size_t size;
Paolo Bonzini12010e72011-08-03 10:49:09 +0200111 void (*free_req)(SCSIRequest *req);
112 int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
113 void (*read_data)(SCSIRequest *req);
114 void (*write_data)(SCSIRequest *req);
Paolo Bonzini12010e72011-08-03 10:49:09 +0200115 uint8_t *(*get_buf)(SCSIRequest *req);
Paolo Bonzini63f740d2011-12-02 16:27:02 +0100116
117 void (*save_request)(QEMUFile *f, SCSIRequest *req);
118 void (*load_request)(QEMUFile *f, SCSIRequest *req);
Paolo Bonzini8dbd4572011-08-03 10:49:08 +0200119};
120
Paolo Bonziniafd40302011-08-13 15:44:45 +0200121struct SCSIBusInfo {
Paolo Bonzini7e0380b2011-08-13 18:55:17 +0200122 int tcq;
Paolo Bonzini0d3545e2011-07-27 23:24:50 +0200123 int max_channel, max_target, max_lun;
Paolo Bonziniff34c322014-07-16 10:39:05 +0200124 int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
125 void *hba_private);
Paolo Bonzinic6df7102011-04-22 12:27:30 +0200126 void (*transfer_data)(SCSIRequest *req, uint32_t arg);
Hannes Reineckef3126d62021-02-24 19:14:50 +0100127 void (*fail)(SCSIRequest *req);
Hannes Reinecke17ea26c22020-11-16 19:40:36 +0100128 void (*complete)(SCSIRequest *req, size_t resid);
Paolo Bonzini94d3f982011-04-18 22:53:08 +0200129 void (*cancel)(SCSIRequest *req);
Paolo Bonzini53200fa2012-07-16 14:22:36 +0200130 void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
Paolo Bonzini3d5aba92011-07-06 11:26:47 +0200131 QEMUSGList *(*get_sg_list)(SCSIRequest *req);
Paolo Bonzini63f740d2011-12-02 16:27:02 +0100132
133 void (*save_request)(QEMUFile *f, SCSIRequest *req);
134 void *(*load_request)(QEMUFile *f, SCSIRequest *req);
Paolo Bonzini8e86b932012-07-09 12:06:28 +0200135 void (*free_request)(SCSIBus *bus, void *priv);
Paolo Bonzinicfdc1bb2011-04-18 17:11:14 +0200136};
137
Anthony Liguori0d936922012-05-02 09:00:20 +0200138#define TYPE_SCSI_BUS "SCSI"
Eduardo Habkost80633962020-09-16 14:25:19 -0400139OBJECT_DECLARE_SIMPLE_TYPE(SCSIBus, SCSI_BUS)
Anthony Liguori0d936922012-05-02 09:00:20 +0200140
Gerd Hoffmann43b443b2009-10-30 09:54:00 +0100141struct SCSIBus {
142 BusState qbus;
143 int busnr;
144
Paolo Bonzini6dc06f02011-08-03 10:49:17 +0200145 SCSISense unit_attention;
Paolo Bonziniafd40302011-08-13 15:44:45 +0200146 const SCSIBusInfo *info;
Gerd Hoffmann43b443b2009-10-30 09:54:00 +0100147};
148
Andreas Färberb1187b52013-08-23 20:30:03 +0200149void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host,
150 const SCSIBusInfo *info, const char *bus_name);
Gerd Hoffmann43b443b2009-10-30 09:54:00 +0100151
152static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
153{
154 return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
155}
156
Markus Armbruster4be74632014-10-07 13:59:18 +0200157SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
Kevin Wolf76534da2013-04-03 12:41:46 +0200158 int unit, bool removable, int bootindex,
Fam Zheng395b9532018-01-17 08:52:22 +0800159 bool share_rw,
Kevin Wolfb8efb362018-06-25 18:39:00 +0200160 BlockdevOnError rerror,
161 BlockdevOnError werror,
Andreas Färbercaad4eb2013-07-21 12:16:34 +0200162 const char *serial, Error **errp);
Thomas Huth14545092018-02-20 11:42:37 +0100163void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
Markus Armbrusterfb8b6602017-02-15 13:18:54 +0100164void scsi_legacy_handle_cmdline(void);
Gerd Hoffmann43b443b2009-10-30 09:54:00 +0100165
Paolo Bonziniadcf2752011-10-12 12:57:59 +0200166SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
167 uint32_t tag, uint32_t lun, void *hba_private);
Hannes Reineckec5bf71a2011-07-11 15:02:24 +0200168SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
Paolo Bonzinic39ce112011-08-03 10:49:10 +0200169 uint8_t *buf, void *hba_private);
170int32_t scsi_req_enqueue(SCSIRequest *req);
Paolo Bonziniad2d30f2011-04-18 16:01:56 +0200171SCSIRequest *scsi_req_ref(SCSIRequest *req);
172void scsi_req_unref(SCSIRequest *req);
Gerd Hoffmann37659e52009-11-26 15:33:58 +0100173
Paolo Bonziniff34c322014-07-16 10:39:05 +0200174int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
175 void *hba_private);
Paolo Bonzini3e7e1802014-07-16 12:22:26 +0200176int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf);
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200177void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
Gerd Hoffmannec766862009-11-26 15:34:01 +0100178void scsi_req_print(SCSIRequest *req);
Paolo Bonziniad3376c2011-04-18 15:28:11 +0200179void scsi_req_continue(SCSIRequest *req);
Paolo Bonziniab9adc82011-04-18 14:59:13 +0200180void scsi_req_data(SCSIRequest *req, int len);
Paolo Bonzini682a9b22011-08-03 10:49:06 +0200181void scsi_req_complete(SCSIRequest *req, int status);
Hannes Reineckef3126d62021-02-24 19:14:50 +0100182void scsi_req_complete_failed(SCSIRequest *req, int host_status);
Paolo Bonzini0c344592011-04-21 13:21:02 +0200183uint8_t *scsi_req_get_buf(SCSIRequest *req);
Hannes Reinecke74382212011-04-18 13:36:02 +0200184int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
Fam Zhengd5776462014-09-25 10:20:47 +0800185void scsi_req_cancel_complete(SCSIRequest *req);
Paolo Bonzini94d3f982011-04-18 22:53:08 +0200186void scsi_req_cancel(SCSIRequest *req);
Fam Zheng8e0a9322014-09-28 09:48:00 +0800187void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier);
Paolo Bonzini71544d32011-10-25 12:53:36 +0200188void scsi_req_retry(SCSIRequest *req);
Paolo Bonzinic7b48872011-08-03 10:49:18 +0200189void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
Paolo Bonzinie48e84e2012-07-16 14:18:58 +0200190void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
Paolo Bonzini53200fa2012-07-16 14:22:36 +0200191void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
Hannes Reinecke8d72db62014-10-29 13:00:11 +0100192void scsi_device_unit_attention_reported(SCSIDevice *dev);
Daniel Henrique Barbozaa71c7752018-06-27 14:24:32 -0300193void scsi_generic_read_device_inquiry(SCSIDevice *dev);
Paolo Bonzinib45ef672011-08-03 10:49:07 +0200194int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
Daniel Henrique Barbozaa0c7e352018-06-27 14:24:31 -0300195int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
Hannes Reineckec9b66092020-11-16 19:31:13 +0100196 uint8_t *buf, uint8_t buf_size, uint32_t timeout);
Paolo Bonzini0d3545e2011-07-27 23:24:50 +0200197SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
Maxim Levitsky8ff34492020-10-06 15:39:02 +0300198SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun);
Gerd Hoffmann89b08ae2009-11-26 15:33:50 +0100199
Paolo Bonzini765d1522011-10-12 12:54:31 +0200200/* scsi-generic.c. */
201extern const SCSIReqOps scsi_generic_req_ops;
202
Gerd Hoffmann43b443b2009-10-30 09:54:00 +0100203#endif