xref: /openbmc/qemu/include/hw/scsi/scsi.h (revision e2beaf7bad96c7e458f08eee033351e6b83032b2)
10d09e41aSPaolo Bonzini #ifndef QEMU_HW_SCSI_H
20d09e41aSPaolo Bonzini #define QEMU_HW_SCSI_H
30d09e41aSPaolo Bonzini 
4db725815SMarkus Armbruster #include "block/aio.h"
50d09e41aSPaolo Bonzini #include "hw/block/block.h"
6a27bd6c7SMarkus Armbruster #include "hw/qdev-core.h"
7e5b5728cSPaolo Bonzini #include "scsi/utils.h"
88e0a9320SFam Zheng #include "qemu/notify.h"
9db1015e9SEduardo Habkost #include "qom/object.h"
100d09e41aSPaolo Bonzini 
110d09e41aSPaolo Bonzini #define MAX_SCSI_DEVS 255
120d09e41aSPaolo Bonzini 
130d09e41aSPaolo Bonzini typedef struct SCSIBus SCSIBus;
140d09e41aSPaolo Bonzini typedef struct SCSIBusInfo SCSIBusInfo;
150d09e41aSPaolo Bonzini typedef struct SCSIDevice SCSIDevice;
160d09e41aSPaolo Bonzini typedef struct SCSIRequest SCSIRequest;
170d09e41aSPaolo Bonzini typedef struct SCSIReqOps SCSIReqOps;
180d09e41aSPaolo Bonzini 
192e323f03SFam Zheng #define SCSI_SENSE_BUF_SIZE_OLD 96
20c5f52875SFam Zheng #define SCSI_SENSE_BUF_SIZE 252
21c9b6609bSHannes Reinecke #define DEFAULT_IO_TIMEOUT 30
220d09e41aSPaolo Bonzini 
230d09e41aSPaolo Bonzini struct SCSIRequest {
240d09e41aSPaolo Bonzini     SCSIBus           *bus;
250d09e41aSPaolo Bonzini     SCSIDevice        *dev;
260d09e41aSPaolo Bonzini     const SCSIReqOps  *ops;
270d09e41aSPaolo Bonzini     uint32_t          refcount;
280d09e41aSPaolo Bonzini     uint32_t          tag;
290d09e41aSPaolo Bonzini     uint32_t          lun;
30f3126d65SHannes Reinecke     int16_t           status;
31f3126d65SHannes Reinecke     int16_t           host_status;
3261e68b3fSFam Zheng     void              *hba_private;
33f02b664aSPhilippe Mathieu-Daudé     uint64_t          residual;
340d09e41aSPaolo Bonzini     SCSICommand       cmd;
358e0a9320SFam Zheng     NotifierList      cancel_notifiers;
3661e68b3fSFam Zheng 
3761e68b3fSFam Zheng     /* Note:
3861e68b3fSFam Zheng      * - fields before sense are initialized by scsi_req_alloc;
3961e68b3fSFam Zheng      * - sense[] is uninitialized;
4061e68b3fSFam Zheng      * - fields after sense are memset to 0 by scsi_req_alloc.
4161e68b3fSFam Zheng      * */
4261e68b3fSFam Zheng 
430d09e41aSPaolo Bonzini     uint8_t           sense[SCSI_SENSE_BUF_SIZE];
440d09e41aSPaolo Bonzini     uint32_t          sense_len;
450d09e41aSPaolo Bonzini     bool              enqueued;
460d09e41aSPaolo Bonzini     bool              io_canceled;
470d09e41aSPaolo Bonzini     bool              retry;
4861e68b3fSFam Zheng     bool              dma_started;
497c84b1b8SMarkus Armbruster     BlockAIOCB        *aiocb;
5061e68b3fSFam Zheng     QEMUSGList        *sg;
510d09e41aSPaolo Bonzini     QTAILQ_ENTRY(SCSIRequest) next;
520d09e41aSPaolo Bonzini };
530d09e41aSPaolo Bonzini 
540d09e41aSPaolo Bonzini #define TYPE_SCSI_DEVICE "scsi-device"
55a489d195SEduardo Habkost OBJECT_DECLARE_TYPE(SCSIDevice, SCSIDeviceClass, SCSI_DEVICE)
560d09e41aSPaolo Bonzini 
57db1015e9SEduardo Habkost struct SCSIDeviceClass {
580d09e41aSPaolo Bonzini     DeviceClass parent_class;
59a818a4b6SFam Zheng     void (*realize)(SCSIDevice *dev, Error **errp);
60b69c3c21SMarkus Armbruster     void (*unrealize)(SCSIDevice *dev);
61ff34c32cSPaolo Bonzini     int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
62fe9d8927SJohn Millikin                      size_t buf_len, void *hba_private);
630d09e41aSPaolo Bonzini     SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
640d09e41aSPaolo Bonzini                               uint8_t *buf, void *hba_private);
650d09e41aSPaolo Bonzini     void (*unit_attention_reported)(SCSIDevice *s);
66db1015e9SEduardo Habkost };
670d09e41aSPaolo Bonzini 
680d09e41aSPaolo Bonzini struct SCSIDevice
690d09e41aSPaolo Bonzini {
700d09e41aSPaolo Bonzini     DeviceState qdev;
710d09e41aSPaolo Bonzini     VMChangeStateEntry *vmsentry;
720d09e41aSPaolo Bonzini     uint32_t id;
730d09e41aSPaolo Bonzini     BlockConf conf;
740d09e41aSPaolo Bonzini     SCSISense unit_attention;
750d09e41aSPaolo Bonzini     bool sense_is_ua;
760d09e41aSPaolo Bonzini     uint8_t sense[SCSI_SENSE_BUF_SIZE];
770d09e41aSPaolo Bonzini     uint32_t sense_len;
78eaad0fe2SStefan Hajnoczi 
79eaad0fe2SStefan Hajnoczi     /*
80eaad0fe2SStefan Hajnoczi      * The requests list is only accessed from the AioContext that executes
81eaad0fe2SStefan Hajnoczi      * requests or from the main loop when IOThread processing is stopped.
82eaad0fe2SStefan Hajnoczi      */
830d09e41aSPaolo Bonzini     QTAILQ_HEAD(, SCSIRequest) requests;
84eaad0fe2SStefan Hajnoczi 
850d09e41aSPaolo Bonzini     uint32_t channel;
860d09e41aSPaolo Bonzini     uint32_t lun;
870d09e41aSPaolo Bonzini     int blocksize;
880d09e41aSPaolo Bonzini     int type;
890d09e41aSPaolo Bonzini     uint64_t max_lba;
902ecab408SPaolo Bonzini     uint64_t wwn;
912ecab408SPaolo Bonzini     uint64_t port_wwn;
922343be0dSPaolo Bonzini     int scsi_version;
932343be0dSPaolo Bonzini     int default_scsi_version;
94c9b6609bSHannes Reinecke     uint32_t io_timeout;
95a71c775bSDaniel Henrique Barboza     bool needs_vpd_bl_emulation;
964f71fb43SKevin Wolf     bool hba_supports_iothread;
970d09e41aSPaolo Bonzini };
980d09e41aSPaolo Bonzini 
990d09e41aSPaolo Bonzini extern const VMStateDescription vmstate_scsi_device;
1000d09e41aSPaolo Bonzini 
1010d09e41aSPaolo Bonzini #define VMSTATE_SCSI_DEVICE(_field, _state) {                        \
1020d09e41aSPaolo Bonzini     .name       = (stringify(_field)),                               \
1030d09e41aSPaolo Bonzini     .size       = sizeof(SCSIDevice),                                \
1040d09e41aSPaolo Bonzini     .vmsd       = &vmstate_scsi_device,                              \
1050d09e41aSPaolo Bonzini     .flags      = VMS_STRUCT,                                        \
1060d09e41aSPaolo Bonzini     .offset     = vmstate_offset_value(_state, _field, SCSIDevice),  \
1070d09e41aSPaolo Bonzini }
1080d09e41aSPaolo Bonzini 
1090d09e41aSPaolo Bonzini /* cdrom.c */
1100d09e41aSPaolo Bonzini int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
1110d09e41aSPaolo Bonzini int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
1120d09e41aSPaolo Bonzini 
1130d09e41aSPaolo Bonzini /* scsi-bus.c */
1140d09e41aSPaolo Bonzini struct SCSIReqOps {
1150d09e41aSPaolo Bonzini     size_t size;
1169472083eSStefano Garzarella     void (*init_req)(SCSIRequest *req);
1170d09e41aSPaolo Bonzini     void (*free_req)(SCSIRequest *req);
1180d09e41aSPaolo Bonzini     int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
1190d09e41aSPaolo Bonzini     void (*read_data)(SCSIRequest *req);
1200d09e41aSPaolo Bonzini     void (*write_data)(SCSIRequest *req);
1210d09e41aSPaolo Bonzini     uint8_t *(*get_buf)(SCSIRequest *req);
1220d09e41aSPaolo Bonzini 
1230d09e41aSPaolo Bonzini     void (*save_request)(QEMUFile *f, SCSIRequest *req);
1240d09e41aSPaolo Bonzini     void (*load_request)(QEMUFile *f, SCSIRequest *req);
1250d09e41aSPaolo Bonzini };
1260d09e41aSPaolo Bonzini 
1270d09e41aSPaolo Bonzini struct SCSIBusInfo {
1280d09e41aSPaolo Bonzini     int tcq;
1290d09e41aSPaolo Bonzini     int max_channel, max_target, max_lun;
130ff34c32cSPaolo Bonzini     int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
131fe9d8927SJohn Millikin                      size_t buf_len, void *hba_private);
1320d09e41aSPaolo Bonzini     void (*transfer_data)(SCSIRequest *req, uint32_t arg);
133f3126d65SHannes Reinecke     void (*fail)(SCSIRequest *req);
1345f412602SPhilippe Mathieu-Daudé     void (*complete)(SCSIRequest *req, size_t residual);
1350d09e41aSPaolo Bonzini     void (*cancel)(SCSIRequest *req);
1360d09e41aSPaolo Bonzini     void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
1370d09e41aSPaolo Bonzini     QEMUSGList *(*get_sg_list)(SCSIRequest *req);
1380d09e41aSPaolo Bonzini 
1390d09e41aSPaolo Bonzini     void (*save_request)(QEMUFile *f, SCSIRequest *req);
1400d09e41aSPaolo Bonzini     void *(*load_request)(QEMUFile *f, SCSIRequest *req);
1410d09e41aSPaolo Bonzini     void (*free_request)(SCSIBus *bus, void *priv);
142766aa2deSStefan Hajnoczi 
143766aa2deSStefan Hajnoczi     /*
144766aa2deSStefan Hajnoczi      * Temporarily stop submitting new requests between drained_begin() and
145766aa2deSStefan Hajnoczi      * drained_end(). Called from the main loop thread with the BQL held.
146766aa2deSStefan Hajnoczi      *
147766aa2deSStefan Hajnoczi      * Implement these callbacks if request processing is triggered by a file
148766aa2deSStefan Hajnoczi      * descriptor like an EventNotifier. Otherwise set them to NULL.
149766aa2deSStefan Hajnoczi      */
150766aa2deSStefan Hajnoczi     void (*drained_begin)(SCSIBus *bus);
151766aa2deSStefan Hajnoczi     void (*drained_end)(SCSIBus *bus);
1520d09e41aSPaolo Bonzini };
1530d09e41aSPaolo Bonzini 
1540d09e41aSPaolo Bonzini #define TYPE_SCSI_BUS "SCSI"
1558063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(SCSIBus, SCSI_BUS)
1560d09e41aSPaolo Bonzini 
1570d09e41aSPaolo Bonzini struct SCSIBus {
1580d09e41aSPaolo Bonzini     BusState qbus;
1590d09e41aSPaolo Bonzini     int busnr;
1600d09e41aSPaolo Bonzini 
1610d09e41aSPaolo Bonzini     SCSISense unit_attention;
1620d09e41aSPaolo Bonzini     const SCSIBusInfo *info;
163766aa2deSStefan Hajnoczi 
164766aa2deSStefan Hajnoczi     int drain_count; /* protected by BQL */
1650d09e41aSPaolo Bonzini };
1660d09e41aSPaolo Bonzini 
167739e95f5SPeter Maydell /**
168739e95f5SPeter Maydell  * scsi_bus_init_named: Initialize a SCSI bus with the specified name
169739e95f5SPeter Maydell  * @bus: SCSIBus object to initialize
170739e95f5SPeter Maydell  * @bus_size: size of @bus object
171739e95f5SPeter Maydell  * @host: Device which owns the bus (generally the SCSI controller)
172739e95f5SPeter Maydell  * @info: structure defining callbacks etc for the controller
173739e95f5SPeter Maydell  * @bus_name: Name to use for this bus
174739e95f5SPeter Maydell  *
175739e95f5SPeter Maydell  * This in-place initializes @bus as a new SCSI bus with a name
176739e95f5SPeter Maydell  * provided by the caller. It is the caller's responsibility to make
177739e95f5SPeter Maydell  * sure that name does not clash with the name of any other bus in the
178739e95f5SPeter Maydell  * system. Unless you need the new bus to have a specific name, you
1797a3ce79cSPhilippe Mathieu-Daudé  * should use scsi_bus_init() instead.
180739e95f5SPeter Maydell  */
181739e95f5SPeter Maydell void scsi_bus_init_named(SCSIBus *bus, size_t bus_size, DeviceState *host,
182b1187b51SAndreas Färber                          const SCSIBusInfo *info, const char *bus_name);
1830d09e41aSPaolo Bonzini 
184739e95f5SPeter Maydell /**
185739e95f5SPeter Maydell  * scsi_bus_init: Initialize a SCSI bus
186739e95f5SPeter Maydell  *
187739e95f5SPeter Maydell  * This in-place-initializes @bus as a new SCSI bus and gives it
188739e95f5SPeter Maydell  * an automatically generated unique name.
189739e95f5SPeter Maydell  */
scsi_bus_init(SCSIBus * bus,size_t bus_size,DeviceState * host,const SCSIBusInfo * info)190739e95f5SPeter Maydell static inline void scsi_bus_init(SCSIBus *bus, size_t bus_size,
191739e95f5SPeter Maydell                                  DeviceState *host, const SCSIBusInfo *info)
192739e95f5SPeter Maydell {
193739e95f5SPeter Maydell     scsi_bus_init_named(bus, bus_size, host, info, NULL);
194739e95f5SPeter Maydell }
195739e95f5SPeter Maydell 
scsi_bus_from_device(SCSIDevice * d)1960d09e41aSPaolo Bonzini static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
1970d09e41aSPaolo Bonzini {
1980d09e41aSPaolo Bonzini     return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
1990d09e41aSPaolo Bonzini }
2000d09e41aSPaolo Bonzini 
2014be74634SMarkus Armbruster SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
202*30896374SKevin Wolf                                       int unit, bool removable, BlockConf *conf,
203caad4eb3SAndreas Färber                                       const char *serial, Error **errp);
2048cc5583aSVenu Busireddy void scsi_bus_set_ua(SCSIBus *bus, SCSISense sense);
20514545097SThomas Huth void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
2060d09e41aSPaolo Bonzini 
2070d09e41aSPaolo Bonzini SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
2080d09e41aSPaolo Bonzini                             uint32_t tag, uint32_t lun, void *hba_private);
2090d09e41aSPaolo Bonzini SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
210fe9d8927SJohn Millikin                           uint8_t *buf, size_t buf_len, void *hba_private);
2110d09e41aSPaolo Bonzini int32_t scsi_req_enqueue(SCSIRequest *req);
2120d09e41aSPaolo Bonzini SCSIRequest *scsi_req_ref(SCSIRequest *req);
2130d09e41aSPaolo Bonzini void scsi_req_unref(SCSIRequest *req);
2140d09e41aSPaolo Bonzini 
215ff34c32cSPaolo Bonzini int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
216fe9d8927SJohn Millikin                        size_t buf_len, void *hba_private);
217fe9d8927SJohn Millikin int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
218fe9d8927SJohn Millikin                        size_t buf_len);
2190d09e41aSPaolo Bonzini void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
2200d09e41aSPaolo Bonzini void scsi_req_print(SCSIRequest *req);
2210d09e41aSPaolo Bonzini void scsi_req_continue(SCSIRequest *req);
2220d09e41aSPaolo Bonzini void scsi_req_data(SCSIRequest *req, int len);
2230d09e41aSPaolo Bonzini void scsi_req_complete(SCSIRequest *req, int status);
224f3126d65SHannes Reinecke void scsi_req_complete_failed(SCSIRequest *req, int host_status);
2250d09e41aSPaolo Bonzini uint8_t *scsi_req_get_buf(SCSIRequest *req);
2260d09e41aSPaolo Bonzini int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
227d5776465SFam Zheng void scsi_req_cancel_complete(SCSIRequest *req);
2280d09e41aSPaolo Bonzini void scsi_req_cancel(SCSIRequest *req);
2298e0a9320SFam Zheng void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier);
2300d09e41aSPaolo Bonzini void scsi_req_retry(SCSIRequest *req);
231766aa2deSStefan Hajnoczi void scsi_device_drained_begin(SCSIDevice *sdev);
232766aa2deSStefan Hajnoczi void scsi_device_drained_end(SCSIDevice *sdev);
2330d09e41aSPaolo Bonzini void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
2340d09e41aSPaolo Bonzini void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
2350d09e41aSPaolo Bonzini void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
2368d72db68SHannes Reinecke void scsi_device_unit_attention_reported(SCSIDevice *dev);
237a71c775bSDaniel Henrique Barboza void scsi_generic_read_device_inquiry(SCSIDevice *dev);
2380d09e41aSPaolo Bonzini int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
239a0c7e35bSDaniel Henrique Barboza int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
240c9b6609bSHannes Reinecke                         uint8_t *buf, uint8_t buf_size, uint32_t timeout);
2410d09e41aSPaolo Bonzini SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
2428ff34495SMaxim Levitsky SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun);
2430d09e41aSPaolo Bonzini 
2440d09e41aSPaolo Bonzini /* scsi-generic.c. */
2450d09e41aSPaolo Bonzini extern const SCSIReqOps scsi_generic_req_ops;
2460d09e41aSPaolo Bonzini 
24709d37867SMark Cave-Ayland /* scsi-disk.c */
24809d37867SMark Cave-Ayland #define SCSI_DISK_QUIRK_MODE_PAGE_APPLE_VENDOR             0
249f43c2b94SMark Cave-Ayland #define SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD             1
25009274de1SMark Cave-Ayland #define SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE    2
251389e18ebSMark Cave-Ayland #define SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED                3
25209d37867SMark Cave-Ayland 
2530d09e41aSPaolo Bonzini #endif
254