]> git.proxmox.com Git - qemu.git/blob - hw/scsi.h
scsi: add channel to addressing
[qemu.git] / hw / scsi.h
1 #ifndef QEMU_HW_SCSI_H
2 #define QEMU_HW_SCSI_H
3
4 #include "qdev.h"
5 #include "block.h"
6
7 #define MAX_SCSI_DEVS 255
8
9 #define SCSI_CMD_BUF_SIZE 16
10
11 typedef struct SCSIBus SCSIBus;
12 typedef struct SCSIBusInfo SCSIBusInfo;
13 typedef struct SCSICommand SCSICommand;
14 typedef struct SCSIDevice SCSIDevice;
15 typedef struct SCSIDeviceInfo SCSIDeviceInfo;
16 typedef struct SCSIRequest SCSIRequest;
17 typedef struct SCSIReqOps SCSIReqOps;
18
19 enum SCSIXferMode {
20 SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
21 SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */
22 SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
23 };
24
25 typedef struct SCSISense {
26 uint8_t key;
27 uint8_t asc;
28 uint8_t ascq;
29 } SCSISense;
30
31 #define SCSI_SENSE_BUF_SIZE 96
32
33 struct SCSICommand {
34 uint8_t buf[SCSI_CMD_BUF_SIZE];
35 int len;
36 size_t xfer;
37 uint64_t lba;
38 enum SCSIXferMode mode;
39 };
40
41 struct SCSIRequest {
42 SCSIBus *bus;
43 SCSIDevice *dev;
44 SCSIReqOps *ops;
45 uint32_t refcount;
46 uint32_t tag;
47 uint32_t lun;
48 uint32_t status;
49 SCSICommand cmd;
50 BlockDriverAIOCB *aiocb;
51 uint8_t sense[SCSI_SENSE_BUF_SIZE];
52 uint32_t sense_len;
53 bool enqueued;
54 void *hba_private;
55 QTAILQ_ENTRY(SCSIRequest) next;
56 };
57
58 struct SCSIDevice
59 {
60 DeviceState qdev;
61 uint32_t id;
62 BlockConf conf;
63 SCSIDeviceInfo *info;
64 SCSISense unit_attention;
65 bool sense_is_ua;
66 uint8_t sense[SCSI_SENSE_BUF_SIZE];
67 uint32_t sense_len;
68 QTAILQ_HEAD(, SCSIRequest) requests;
69 uint32_t channel;
70 uint32_t lun;
71 int blocksize;
72 int type;
73 };
74
75 /* cdrom.c */
76 int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
77 int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
78
79 /* scsi-bus.c */
80 struct SCSIReqOps {
81 size_t size;
82 void (*free_req)(SCSIRequest *req);
83 int32_t (*send_command)(SCSIRequest *req, uint8_t *buf);
84 void (*read_data)(SCSIRequest *req);
85 void (*write_data)(SCSIRequest *req);
86 void (*cancel_io)(SCSIRequest *req);
87 uint8_t *(*get_buf)(SCSIRequest *req);
88 };
89
90 typedef int (*scsi_qdev_initfn)(SCSIDevice *dev);
91 struct SCSIDeviceInfo {
92 DeviceInfo qdev;
93 scsi_qdev_initfn init;
94 void (*destroy)(SCSIDevice *s);
95 SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
96 void *hba_private);
97 void (*unit_attention_reported)(SCSIDevice *s);
98 SCSIReqOps reqops;
99 };
100
101 struct SCSIBusInfo {
102 int tcq;
103 int max_channel, max_target, max_lun;
104 void (*transfer_data)(SCSIRequest *req, uint32_t arg);
105 void (*complete)(SCSIRequest *req, uint32_t arg);
106 void (*cancel)(SCSIRequest *req);
107 };
108
109 struct SCSIBus {
110 BusState qbus;
111 int busnr;
112
113 SCSISense unit_attention;
114 const SCSIBusInfo *info;
115 };
116
117 void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info);
118 void scsi_qdev_register(SCSIDeviceInfo *info);
119
120 static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
121 {
122 return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
123 }
124
125 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
126 int unit, bool removable);
127 int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
128
129 /*
130 * Predefined sense codes
131 */
132
133 /* No sense data available */
134 extern const struct SCSISense sense_code_NO_SENSE;
135 /* LUN not ready, Manual intervention required */
136 extern const struct SCSISense sense_code_LUN_NOT_READY;
137 /* LUN not ready, Medium not present */
138 extern const struct SCSISense sense_code_NO_MEDIUM;
139 /* LUN not ready, medium removal prevented */
140 extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED;
141 /* Hardware error, internal target failure */
142 extern const struct SCSISense sense_code_TARGET_FAILURE;
143 /* Illegal request, invalid command operation code */
144 extern const struct SCSISense sense_code_INVALID_OPCODE;
145 /* Illegal request, LBA out of range */
146 extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
147 /* Illegal request, Invalid field in CDB */
148 extern const struct SCSISense sense_code_INVALID_FIELD;
149 /* Illegal request, LUN not supported */
150 extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
151 /* Illegal request, Saving parameters not supported */
152 extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED;
153 /* Illegal request, Incompatible format */
154 extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT;
155 /* Illegal request, medium removal prevented */
156 extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED;
157 /* Command aborted, I/O process terminated */
158 extern const struct SCSISense sense_code_IO_ERROR;
159 /* Command aborted, I_T Nexus loss occurred */
160 extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
161 /* Command aborted, Logical Unit failure */
162 extern const struct SCSISense sense_code_LUN_FAILURE;
163 /* LUN not ready, Medium not present */
164 extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM;
165 /* Unit attention, Power on, reset or bus device reset occurred */
166 extern const struct SCSISense sense_code_RESET;
167 /* Unit attention, Medium may have changed*/
168 extern const struct SCSISense sense_code_MEDIUM_CHANGED;
169 /* Unit attention, Reported LUNs data has changed */
170 extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED;
171 /* Unit attention, Device internal reset */
172 extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
173
174 #define SENSE_CODE(x) sense_code_ ## x
175
176 int scsi_sense_valid(SCSISense sense);
177
178 SCSIRequest *scsi_req_alloc(SCSIReqOps *reqops, SCSIDevice *d, uint32_t tag,
179 uint32_t lun, void *hba_private);
180 SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
181 uint8_t *buf, void *hba_private);
182 int32_t scsi_req_enqueue(SCSIRequest *req);
183 void scsi_req_free(SCSIRequest *req);
184 SCSIRequest *scsi_req_ref(SCSIRequest *req);
185 void scsi_req_unref(SCSIRequest *req);
186
187 void scsi_req_build_sense(SCSIRequest *req, SCSISense sense);
188 void scsi_req_print(SCSIRequest *req);
189 void scsi_req_continue(SCSIRequest *req);
190 void scsi_req_data(SCSIRequest *req, int len);
191 void scsi_req_complete(SCSIRequest *req, int status);
192 uint8_t *scsi_req_get_buf(SCSIRequest *req);
193 int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
194 void scsi_req_abort(SCSIRequest *req, int status);
195 void scsi_req_cancel(SCSIRequest *req);
196 void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
197 int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
198 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
199
200 #endif