1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/sys/util.h>
8 
9 #ifndef ZEPHYR_INCLUDE_USBD_MSC_SCSI_H_
10 #define ZEPHYR_INCLUDE_USBD_MSC_SCSI_H_
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 /* SAM-6 5.3.1 Status codes
17  * Table 44 – Status codes
18  */
19 enum scsi_status_code {
20 	GOOD = 0x00,
21 	CHECK_CONDITION = 0x02,
22 	CONDITION_MET = 0x04,
23 	BUSY = 0x08,
24 	RESERVATION_CONFLICT = 0x18,
25 	TASK_SET_FULL = 0x28,
26 	ACA_ACTIVE = 0x30,
27 	TASK_ABORTED = 0x40,
28 };
29 
30 /* SPC-5 4.4.8 Sense key and additional sense code definitions
31  * Table 49 — Sense key descriptions
32  */
33 enum scsi_sense_key {
34 	NO_SENSE = 0x0,
35 	RECOVERED_ERROR = 0x1,
36 	NOT_READY = 0x2,
37 	MEDIUM_ERROR = 0x3,
38 	HARDWARE_ERROR = 0x4,
39 	ILLEGAL_REQUEST = 0x5,
40 	UNIT_ATTENTION = 0x6,
41 	DATA_PROTECT = 0x7,
42 	BLANK_CHECK = 0x8,
43 	VENDOR_SPECIFIC = 0x9,
44 	COPY_ABORTED = 0xA,
45 	ABORTED_COMMAND = 0xB,
46 	/* 0xC is Reserved */
47 	VOLUME_OVERFLOW = 0xD,
48 	MISCOMPARE = 0xE,
49 	COMPLETED = 0xF,
50 };
51 
52 /* SPC-5 Table F.1 — ASC and ASCQ assignments
53  * ASC is upper 8 bits, ASCQ on lower 8 bits
54  */
55 enum scsi_additional_sense_code {
56 	NO_ADDITIONAL_SENSE_INFORMATION = 0x0000,
57 	LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE = 0x2100,
58 	INVALID_FIELD_IN_CDB = 0x2400,
59 	MEDIUM_NOT_PRESENT = 0x3A00,
60 	MEDIUM_REMOVAL_PREVENTED = 0x5302,
61 	WRITE_ERROR = 0x0C00,
62 };
63 
64 struct scsi_ctx {
65 	const char *disk;
66 	const char *vendor;
67 	const char *product;
68 	const char *revision;
69 	size_t (*read_cb)(struct scsi_ctx *ctx,
70 			  uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE]);
71 	size_t (*write_cb)(struct scsi_ctx *ctx, const uint8_t *buf, size_t length);
72 	size_t remaining_data;
73 	uint32_t lba;
74 	uint32_t sector_count;
75 	uint32_t sector_size;
76 	enum scsi_status_code status;
77 	enum scsi_sense_key sense_key;
78 	enum scsi_additional_sense_code asc;
79 	bool prevent_removal : 1;
80 	bool medium_loaded : 1;
81 	bool cmd_is_data_read : 1;
82 	bool cmd_is_data_write : 1;
83 };
84 
85 void scsi_init(struct scsi_ctx *ctx, const char *disk, const char *vendor,
86 	       const char *product, const char *revision);
87 void scsi_reset(struct scsi_ctx *ctx);
88 int scsi_usb_boot_cmd_len(const uint8_t *cb, int len);
89 size_t scsi_cmd(struct scsi_ctx *ctx, const uint8_t *cb, int len,
90 		uint8_t data_in_buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE]);
91 
92 bool scsi_cmd_is_data_read(struct scsi_ctx *ctx);
93 bool scsi_cmd_is_data_write(struct scsi_ctx *ctx);
94 size_t scsi_cmd_remaining_data_len(struct scsi_ctx *ctx);
95 size_t scsi_read_data(struct scsi_ctx *ctx,
96 		      uint8_t data_in_buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE]);
97 size_t scsi_write_data(struct scsi_ctx *ctx, const uint8_t *buf, size_t length);
98 
99 enum scsi_status_code scsi_cmd_get_status(struct scsi_ctx *ctx);
100 
101 #ifdef __cplusplus
102 }
103 #endif
104 
105 #endif /* ZEPHYR_INCLUDE_USBD_MSC_SCSI_H_ */
106