1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-02-25 GuEe-GUI the first version
9 */
10
11 #ifndef __SCSI_H__
12 #define __SCSI_H__
13
14 #include <rthw.h>
15 #include <rtthread.h>
16 #include <drivers/byteorder.h>
17
18 #define RT_SCSI_LUN_SHIFT 5
19
20 rt_packed(struct rt_scsi_unknow
21 {
22 rt_uint8_t opcode;
23 });
24
25 rt_packed(struct rt_scsi_test_unit_ready
26 {
27 rt_uint8_t opcode;
28 rt_uint8_t reserved[4];
29 rt_uint8_t control;
30 rt_uint8_t pad[6]; /* To be ATAPI compatible */
31 });
32
33 rt_packed(struct rt_scsi_inquiry
34 {
35 rt_uint8_t opcode;
36 rt_uint8_t config; /* 7-2 Reserved, 1 Obsolete Formerly CMDDT, 0 EVPD */
37 rt_uint8_t page; /* Page code if EVPD=1 */
38 rt_uint8_t reserved;
39 rt_uint8_t alloc_length;
40 rt_uint8_t control;
41 rt_uint8_t pad[6]; /* To be ATAPI compatible */
42 });
43
44 rt_packed(struct rt_scsi_inquiry_data
45 {
46 #define RT_SCSI_DEVTYPE_MASK 31
47 rt_uint8_t devtype;
48 #define RT_SCSI_REMOVABLE_BIT 7
49 rt_uint8_t rmb;
50 rt_uint8_t reserved[2];
51 rt_uint8_t length;
52 rt_uint8_t reserved1[3];
53 char vendor[8];
54 char prodid[16];
55 char prodrev[4];
56 });
57
58 rt_packed(struct rt_scsi_request_sense
59 {
60 rt_uint8_t opcode;
61 rt_uint8_t config; /* 7-2 Reserved, 1 Obsolete, 0 SP */
62 rt_uint8_t reserved[2];
63 rt_uint8_t alloc_length;
64 rt_uint8_t control;
65 rt_uint8_t pad[6]; /* To be ATAPI compatible */
66 });
67
68 rt_packed(struct rt_scsi_request_sense_data
69 {
70 rt_uint8_t error_code; /* 7 Valid, 6-0 Err. code */
71 rt_uint8_t segment_number;
72 rt_uint8_t sense_key; /* 7 FileMark, 6 EndOfMedia, 5 ILI, 4-0 sense key */
73 rt_be32_t information;
74 rt_uint8_t additional_sense_length;
75 rt_be32_t cmd_specific_info;
76 rt_uint8_t additional_sense_code;
77 rt_uint8_t additional_sense_code_qualifier;
78 rt_uint8_t field_replaceable_unit_code;
79 rt_uint8_t sense_key_specific[3];
80 });
81
82 rt_packed(struct rt_scsi_read_capacity10
83 {
84 rt_uint8_t opcode;
85 rt_uint8_t config; /* 7-1 Reserved, 0 Obsolete */
86 rt_be32_t logical_block_addr; /* only if PMI=1 */
87 rt_uint8_t reserved[2];
88 rt_uint8_t pmi;
89 rt_uint8_t control;
90 rt_be16_t pad; /* To be ATAPI compatible */
91 });
92
93 rt_packed(struct rt_scsi_read_capacity10_data
94 {
95 rt_be32_t last_block;
96 rt_be32_t block_size;
97 });
98
99 rt_packed(struct rt_scsi_read_capacity16
100 {
101 rt_uint8_t opcode;
102 rt_uint8_t config; /* 7-5 Reserved, 4-0 SERVICE ACTION 0x10 */
103 rt_be64_t logical_block_addr; /* only if PMI=1 */
104 rt_be32_t alloc_len;
105 rt_uint8_t pmi;
106 rt_uint8_t control;
107 });
108
109 rt_packed(struct rt_scsi_read_capacity16_data
110 {
111 rt_be64_t last_block;
112 rt_be32_t block_size;
113 rt_uint8_t pad[20];
114 });
115
116 rt_packed(struct rt_scsi_read10
117 {
118 rt_uint8_t opcode;
119 rt_uint8_t config; /* 7-5 RDPROTECT, 4 DPO, 3 FUA, 2 RARC, 1 Obsolete, 0 Obsolete */
120 rt_be32_t lba;
121 rt_uint8_t reserved;
122 rt_be16_t size;
123 rt_uint8_t reserved2;
124 rt_be16_t pad;
125 });
126
127 rt_packed(struct rt_scsi_read12
128 {
129 rt_uint8_t opcode;
130 rt_uint8_t config; /* 7-5 RDPROTECT, 4 DPO, 3 FUA, 2 RARC, 1 Obsolete, 0 Obsolete */
131 rt_be32_t lba;
132 rt_be32_t size;
133 rt_uint8_t reserved;
134 rt_uint8_t control;
135 });
136
137 rt_packed(struct rt_scsi_read16
138 {
139 rt_uint8_t opcode;
140 rt_uint8_t config; /* 7-5 RDPROTECT, 4 DPO, 3 FUA, 2 RARC, 1 Obsolete, 0 DLD2 */
141 rt_be64_t lba;
142 rt_be32_t size;
143 rt_uint8_t reserved;
144 rt_uint8_t control;
145 });
146
147 rt_packed(struct rt_scsi_write10
148 {
149 rt_uint8_t opcode;
150 rt_uint8_t config; /* 7-5 WRPROTECT, 4 DPO, 3 FUA, 2 Reserved, 1 Obsolete, 0 Obsolete */
151 rt_be32_t lba;
152 rt_uint8_t reserved;
153 rt_be16_t size;
154 rt_uint8_t reserved2;
155 rt_be16_t pad;
156 });
157
158 rt_packed(struct rt_scsi_write12
159 {
160 rt_uint8_t opcode;
161 rt_uint8_t config; /* 7-5 WRPROTECT, 4 DPO, 3 FUA, 2 Reserved, 1 Obsolete, 0 Obsolete */
162 rt_be32_t lba;
163 rt_be32_t size;
164 rt_uint8_t reserved;
165 rt_uint8_t control;
166 });
167
168 rt_packed(struct rt_scsi_write16
169 {
170 rt_uint8_t opcode;
171 rt_uint8_t config; /* 7-5 WRPROTECT, 4 DPO, 3 FUA, 2 Reserved, 1 Obsolete, 0 DLD2 */
172 rt_be64_t lba;
173 rt_be32_t size;
174 rt_uint8_t reserved;
175 rt_uint8_t control;
176 });
177
178 rt_packed(struct rt_scsi_synchronize_cache10
179 {
180 rt_uint8_t opcode;
181 rt_uint8_t config; /* 7-3 Reserved, 2 Obsolete, 1 IMMED, 0 Obsolete */
182 rt_be32_t lba;
183 rt_uint8_t reserved;
184 rt_be16_t size;
185 rt_uint8_t control;
186 });
187
188 rt_packed(struct rt_scsi_synchronize_cache16
189 {
190 rt_uint8_t opcode;
191 rt_uint8_t config; /* 7-3 Reserved, 2 Obsolete, 1 IMMED, 0 Obsolete */
192 rt_be64_t lba;
193 rt_be32_t size;
194 rt_uint8_t reserved;
195 rt_uint8_t control;
196 });
197
198 #define RT_SCSI_UNMAP_SHIFT 3
199
200 rt_packed(struct rt_scsi_write_same10
201 {
202 rt_uint8_t opcode;
203 rt_uint8_t config; /* 7-5 WRPROTECT, 4 ANCHOR, 3 UNMAP, 2 Obsolete, 1 Obsolete, 0 Obsolete */
204 rt_be32_t lba;
205 rt_uint8_t reserved;
206 rt_be16_t size;
207 rt_uint8_t control;
208 });
209
210 rt_packed(struct rt_scsi_write_same16
211 {
212 rt_uint8_t opcode;
213 rt_uint8_t config; /* 7-5 WRPROTECT, 4 ANCHOR, 3 UNMAP, 2 Obsolete, 1 Obsolete, 0 NDOB */
214 rt_be64_t lba;
215 rt_be32_t size;
216 rt_uint8_t reserved;
217 rt_uint8_t control;
218 });
219
220 #define RT_SCSI_PF_SHIFT 4
221 #define RT_SCSI_RTD_SHIFT 1
222 #define RT_SCSI_SP_SHIFT 0
223
224 rt_packed(struct rt_scsi_mode_select6
225 {
226 rt_uint8_t opcode;
227 rt_uint8_t config; /* 7-5 Reserved, 4 PF, 3-2 Reserved, 1 RTD, 0 SP */
228 rt_uint8_t reserved[2];
229 rt_uint8_t param_list_len;
230 rt_uint8_t control;
231 });
232
233 rt_packed(struct rt_scsi_mode_select10
234 {
235 rt_uint8_t opcode;
236 rt_uint8_t config; /* 7-5 Reserved, 4 PF, 3-1 Reserved, 0 SP */
237 rt_uint8_t reserved[5];
238 rt_be16_t param_list_len;
239 rt_uint8_t control;
240 });
241
242 struct rt_scsi_mode_select_data
243 {
244 rt_uint32_t length;
245 rt_uint16_t block_descriptor_length;
246 rt_uint8_t medium_type;
247 rt_uint8_t device_specific;
248 rt_uint8_t header_length;
249 rt_uint8_t longlba:1;
250 };
251
252 #define RT_SCSI_DBD_SHIFT 3
253 #define RT_SCSI_LLBAA_SHIFT 4
254 #define RT_SCSI_PC_SHIFT 6
255 #define RT_SCSI_PAGE_CODE_SHIFT 0
256
257 rt_packed(struct rt_scsi_mode_sense6
258 {
259 rt_uint8_t opcode;
260 rt_uint8_t config; /* 7-4 Reserved, 3 DBD, 2-0 Reserved */
261 rt_uint8_t page_control_code;
262 rt_uint8_t subpage_code;
263 rt_uint8_t allocation_len;
264 rt_uint8_t control;
265 });
266
267 rt_packed(struct rt_scsi_mode_sense10
268 {
269 rt_uint8_t opcode;
270 rt_uint8_t config; /* 7-5 Reserved, 4 LLBAA, 3 DBD, 2-0 Reserved */
271 rt_uint8_t page_control_code;
272 rt_uint8_t subpage_code;
273 rt_uint8_t reserved[3];
274 rt_be16_t allocation_len;
275 rt_uint8_t control;
276 });
277
278 #define RT_SCSI_CMD_TEST_UNIT_READY 0x00
279 #define RT_SCSI_CMD_REQUEST_SENSE 0x03
280 #define RT_SCSI_CMD_INQUIRY 0x12
281 #define RT_SCSI_CMD_MODE_SELECT 0x15
282 #define RT_SCSI_CMD_MODE_SENSE 0x1a
283 #define RT_SCSI_CMD_READ_CAPACITY10 0x25
284 #define RT_SCSI_CMD_READ10 0x28
285 #define RT_SCSI_CMD_WRITE10 0x2a
286 #define RT_SCSI_CMD_SYNCHRONIZE_CACHE10 0x35
287 #define RT_SCSI_CMD_WRITE_SAME10 0x41
288 #define RT_SCSI_CMD_MODE_SELECT10 0x55
289 #define RT_SCSI_CMD_MODE_SENSE10 0x5a
290 #define RT_SCSI_CMD_READ16 0x88
291 #define RT_SCSI_CMD_WRITE16 0x8a
292 #define RT_SCSI_CMD_SYNCHRONIZE_CACHE16 0x91
293 #define RT_SCSI_CMD_WRITE_SAME16 0x93
294 #define RT_SCSI_CMD_READ_CAPACITY16 0x9e
295 #define RT_SCSI_CMD_READ12 0xa8
296 #define RT_SCSI_CMD_WRITE12 0xaa
297
298 struct rt_scsi_cmd
299 {
300 union
301 {
302 struct rt_scsi_unknow unknow;
303 struct rt_scsi_test_unit_ready test_unit_ready;
304 struct rt_scsi_inquiry inquiry;
305 struct rt_scsi_request_sense request_sense;
306 struct rt_scsi_read_capacity10 read_capacity10;
307 struct rt_scsi_read_capacity16 read_capacity16;
308 struct rt_scsi_read10 read10;
309 struct rt_scsi_read12 read12;
310 struct rt_scsi_read16 read16;
311 struct rt_scsi_write10 write10;
312 struct rt_scsi_write12 write12;
313 struct rt_scsi_write16 write16;
314 struct rt_scsi_synchronize_cache10 synchronize_cache10;
315 struct rt_scsi_synchronize_cache16 synchronize_cache16;
316 struct rt_scsi_write_same10 write_same10;
317 struct rt_scsi_write_same16 write_same16;
318 struct rt_scsi_mode_select6 mode_select6;
319 struct rt_scsi_mode_select10 mode_select10;
320 struct rt_scsi_mode_sense6 mode_sense6;
321 struct rt_scsi_mode_sense10 mode_sense10;
322 } op;
323 rt_size_t op_size;
324
325 union
326 {
327 struct
328 {
329 struct rt_scsi_inquiry_data inquiry;
330 struct rt_scsi_request_sense_data request_sense;
331 struct rt_scsi_read_capacity10_data read_capacity10;
332 struct rt_scsi_read_capacity16_data read_capacity16;
333 };
334 struct
335 {
336 void *ptr;
337 rt_size_t size;
338 };
339 } data;
340 };
341
342 enum
343 {
344 SCSI_DEVICE_TYPE_DIRECT = 0x00, /* DiskPeripheral (GenDisk) */
345 SCSI_DEVICE_TYPE_SEQUENTIAL = 0x01, /* TapePeripheral */
346 SCSI_DEVICE_TYPE_PRINTER = 0x02, /* PrinterPeripheral (GenPrinter) */
347 SCSI_DEVICE_TYPE_PROCESSOR = 0x03, /* OtherPeripheral */
348 SCSI_DEVICE_TYPE_WRITE_ONCE_READ_MULTIPLE = 0x04, /* WormPeripheral (GenWorm) */
349 SCSI_DEVICE_TYPE_CDROM = 0x05, /* CdRomPeripheral (GenCdRom) */
350 SCSI_DEVICE_TYPE_SCANNER = 0x06, /* ScannerPeripheral (GenScanner) */
351 SCSI_DEVICE_TYPE_OPTICAL = 0x07, /* OpticalDiskPeripheral (GenOptical) */
352 SCSI_DEVICE_TYPE_MEDIUM_CHANGER = 0x08, /* MediumChangerPeripheral (ScsiChanger) */
353 SCSI_DEVICE_TYPE_COMMUNICATION = 0x09, /* CommunicationsPeripheral (ScsiNet) */
354 SCSI_DEVICE_TYPE_ASC_PREPRESS_GRAPHICS10 = 0x0a, /* ASCPrePressGraphicsPeripheral (ScsiASCIT8) */
355 SCSI_DEVICE_TYPE_ASC_PREPRESS_GRAPHICS11 = 0x0b, /* ASCPrePressGraphicsPeripheral (ScsiASCIT8) */
356 SCSI_DEVICE_TYPE_ARRAY = 0x0c, /* ArrayPeripheral (ScsiArray) */
357 SCSI_DEVICE_TYPE_ENCLOSURE = 0x0d, /* EnclosurePeripheral (ScsiEnclosure) */
358 SCSI_DEVICE_TYPE_RBC = 0x0e, /* RBCPeripheral (ScsiRBC) */
359 SCSI_DEVICE_TYPE_CARDREADER = 0x0f, /* CardReaderPeripheral (ScsiCardReader) */
360 SCSI_DEVICE_TYPE_BRIDGE = 0x10, /* BridgePeripheral (ScsiBridge) */
361 SCSI_DEVICE_TYPE_OTHER = 0x11, /* OtherPeripheral (ScsiOther) */
362 SCSI_DEVICE_TYPE_MAX,
363 };
364
365 struct rt_scsi_ops;
366
367 struct rt_scsi_host
368 {
369 struct rt_device *dev;
370
371 const struct rt_scsi_ops *ops;
372
373 rt_size_t max_id;
374 rt_size_t max_lun;
375
376 rt_list_t lun_nodes;
377 };
378
379 struct rt_scsi_device
380 {
381 struct rt_scsi_host *host;
382
383 rt_list_t list;
384
385 rt_size_t id;
386 rt_size_t lun;
387 rt_uint32_t devtype;
388 rt_uint32_t removable;
389 rt_size_t last_block;
390 rt_size_t block_size;
391
392 void *priv;
393 };
394
395 struct rt_scsi_ops
396 {
397 rt_err_t (*reset)(struct rt_scsi_device *sdev);
398 rt_err_t (*transfer)(struct rt_scsi_device *sdev, struct rt_scsi_cmd *cmd);
399 };
400
401 rt_err_t rt_scsi_host_register(struct rt_scsi_host *scsi);
402 rt_err_t rt_scsi_host_unregister(struct rt_scsi_host *scsi);
403
rt_scsi_cmd_is_write(struct rt_scsi_cmd * cmd)404 rt_inline rt_bool_t rt_scsi_cmd_is_write(struct rt_scsi_cmd *cmd)
405 {
406 return cmd->op.write10.opcode == RT_SCSI_CMD_WRITE10 ||
407 cmd->op.write12.opcode == RT_SCSI_CMD_WRITE16 ||
408 cmd->op.write16.opcode == RT_SCSI_CMD_WRITE12;
409 }
410
411 rt_err_t rt_scsi_request_sense(struct rt_scsi_device *sdev,
412 struct rt_scsi_request_sense_data *out_data);
413
414 rt_err_t rt_scsi_test_unit_ready(struct rt_scsi_device *sdev);
415 rt_err_t rt_scsi_inquiry(struct rt_scsi_device *sdev,
416 struct rt_scsi_inquiry_data *out_data);
417
418 rt_err_t rt_scsi_read_capacity10(struct rt_scsi_device *sdev,
419 struct rt_scsi_read_capacity10_data *out_data);
420 rt_err_t rt_scsi_read_capacity16(struct rt_scsi_device *sdev,
421 struct rt_scsi_read_capacity16_data *out_data);
422
423 rt_err_t rt_scsi_read10(struct rt_scsi_device *sdev,
424 rt_off_t lba, void *buffer, rt_size_t size);
425 rt_err_t rt_scsi_read12(struct rt_scsi_device *sdev,
426 rt_off_t lba, void *buffer, rt_size_t size);
427 rt_err_t rt_scsi_read16(struct rt_scsi_device *sdev,
428 rt_off_t lba, void *buffer, rt_size_t size);
429
430 rt_err_t rt_scsi_write10(struct rt_scsi_device *sdev,
431 rt_off_t lba, const void *buffer, rt_size_t size);
432 rt_err_t rt_scsi_write12(struct rt_scsi_device *sdev,
433 rt_off_t lba, const void *buffer, rt_size_t size);
434 rt_err_t rt_scsi_write16(struct rt_scsi_device *sdev,
435 rt_off_t lba, const void *buffer, rt_size_t size);
436
437 rt_err_t rt_scsi_synchronize_cache10(struct rt_scsi_device *sdev,
438 rt_off_t lba, rt_size_t size);
439 rt_err_t rt_scsi_synchronize_cache16(struct rt_scsi_device *sdev,
440 rt_off_t lba, rt_size_t size);
441
442 rt_err_t rt_scsi_write_same10(struct rt_scsi_device *sdev,
443 rt_off_t lba, rt_size_t size);
444 rt_err_t rt_scsi_write_same16(struct rt_scsi_device *sdev,
445 rt_off_t lba, rt_size_t size);
446
447 rt_err_t rt_scsi_mode_select6(struct rt_scsi_device *sdev,
448 rt_uint8_t pf, rt_uint8_t sp, void *buffer, rt_size_t size,
449 struct rt_scsi_mode_select_data *data);
450 rt_err_t rt_scsi_mode_select10(struct rt_scsi_device *sdev,
451 rt_uint8_t pf, rt_uint8_t sp, void *buffer, rt_size_t size,
452 struct rt_scsi_mode_select_data *data);
453
454 rt_err_t rt_scsi_mode_sense6(struct rt_scsi_device *sdev,
455 rt_uint8_t dbd, rt_uint8_t modepage, rt_uint8_t subpage, void *buffer, rt_size_t size,
456 struct rt_scsi_mode_select_data *data);
457 rt_err_t rt_scsi_mode_sense10(struct rt_scsi_device *sdev,
458 rt_uint8_t dbd, rt_uint8_t modepage, rt_uint8_t subpage, void *buffer, rt_size_t size,
459 struct rt_scsi_mode_select_data *data);
460
461 #endif /* __SCSI_H__ */
462