1 /*
2 * SCSI commands related implementation
3 */
4
5 #include <minix/blockdriver.h> /* SECTOR_SIZE */
6
7 #include <assert.h>
8 #include <string.h> /* strncpy */
9
10 #include "common.h"
11 #include "scsi.h"
12
13 /*---------------------------*
14 * declared functions *
15 *---------------------------*/
16 /* To work correctly cbw->CBWCB must be zeroed before calling these: */
17 static int create_inquiry_scsi_cmd(mass_storage_cbw *);
18 static int create_test_scsi_cmd(mass_storage_cbw *);
19 static int create_read_capacity_scsi_cmd(mass_storage_cbw *);
20 static int create_write_scsi_cmd(mass_storage_cbw *, scsi_transfer *);
21 static int create_read_scsi_cmd(mass_storage_cbw *, scsi_transfer *);
22 static int create_mode_sense_scsi_cmd(mass_storage_cbw *);
23 static int create_request_sense_scsi_cmd(mass_storage_cbw *);
24
25 /*---------------------------*
26 * defined functions *
27 *---------------------------*/
28 /*===========================================================================*
29 * create_scsi_cmd *
30 *===========================================================================*/
31 int
create_scsi_cmd(mass_storage_cbw * cbw,int cmd,scsi_transfer * info)32 create_scsi_cmd(mass_storage_cbw * cbw, int cmd, scsi_transfer * info)
33 {
34 MASS_DEBUG_DUMP;
35
36 assert(NULL != cbw);
37
38 switch (cmd) {
39 case SCSI_INQUIRY:
40 return create_inquiry_scsi_cmd(cbw);
41 case SCSI_TEST_UNIT_READY:
42 return create_test_scsi_cmd(cbw);
43 case SCSI_READ_CAPACITY:
44 return create_read_capacity_scsi_cmd(cbw);
45 case SCSI_WRITE:
46 return create_write_scsi_cmd(cbw, info);
47 case SCSI_READ:
48 return create_read_scsi_cmd(cbw, info);
49 case SCSI_MODE_SENSE:
50 return create_mode_sense_scsi_cmd(cbw);
51 case SCSI_REQUEST_SENSE:
52 return create_request_sense_scsi_cmd(cbw);
53 default:
54 MASS_MSG("Invalid SCSI command!");
55 return EXIT_FAILURE;
56 }
57 }
58
59
60 /*===========================================================================*
61 * create_inquiry_scsi_cmd *
62 *===========================================================================*/
63 static int
create_inquiry_scsi_cmd(mass_storage_cbw * cbw)64 create_inquiry_scsi_cmd(mass_storage_cbw * cbw)
65 {
66 MASS_DEBUG_DUMP;
67
68 cbw->dCBWDataTransferLength = SCSI_INQUIRY_DATA_LEN;
69 cbw->bCBWFlags = CBW_FLAGS_IN;
70 cbw->bCDBLength = SCSI_INQUIRY_CMD_LEN;
71
72 SCSI_SET_INQUIRY_OP_CODE(cbw->CBWCB);
73 SCSI_SET_INQUIRY_PAGE_CODE(cbw->CBWCB, 0);
74 SCSI_SET_INQUIRY_ALLOC_LEN(cbw->CBWCB, SCSI_INQUIRY_DATA_LEN);
75
76 return EXIT_SUCCESS;
77 }
78
79
80 /*===========================================================================*
81 * create_test_scsi_cmd *
82 *===========================================================================*/
83 static int
create_test_scsi_cmd(mass_storage_cbw * cbw)84 create_test_scsi_cmd(mass_storage_cbw * cbw)
85 {
86 MASS_DEBUG_DUMP;
87
88 cbw->bCDBLength = SCSI_TEST_CMD_LEN;
89
90 SCSI_SET_TEST_OP_CODE(cbw->CBWCB);
91
92 return EXIT_SUCCESS;
93 }
94
95
96 /*===========================================================================*
97 * create_read_capacity_scsi_cmd *
98 *===========================================================================*/
99 static int
create_read_capacity_scsi_cmd(mass_storage_cbw * cbw)100 create_read_capacity_scsi_cmd(mass_storage_cbw * cbw)
101 {
102 MASS_DEBUG_DUMP;
103
104 cbw->dCBWDataTransferLength = SCSI_READ_CAPACITY_DATA_LEN;
105 cbw->bCBWFlags = CBW_FLAGS_IN;
106 cbw->bCDBLength = SCSI_READ_CAPACITY_CMD_LEN;
107
108 SCSI_SET_READ_CAPACITY_OP_CODE(cbw->CBWCB);
109 SCSI_SET_READ_CAPACITY_LBA(cbw->CBWCB, 0x00);
110
111 return EXIT_SUCCESS;
112 }
113
114
115 /*===========================================================================*
116 * create_write_scsi_cmd *
117 *===========================================================================*/
118 static int
create_write_scsi_cmd(mass_storage_cbw * cbw,scsi_transfer * info)119 create_write_scsi_cmd(mass_storage_cbw * cbw, scsi_transfer * info)
120 {
121 MASS_DEBUG_DUMP;
122
123 assert(NULL != info);
124 assert(0 == (info->length % SECTOR_SIZE));
125
126 cbw->dCBWDataTransferLength = info->length;
127 cbw->bCBWFlags = CBW_FLAGS_OUT;
128 cbw->bCDBLength = SCSI_WRITE_CMD_LEN;
129
130 SCSI_SET_WRITE_OP_CODE(cbw->CBWCB);
131 SCSI_SET_WRITE_LBA(cbw->CBWCB, info->lba);
132 SCSI_SET_WRITE_BLEN(cbw->CBWCB, info->length / SECTOR_SIZE);
133
134 return EXIT_SUCCESS;
135 }
136
137
138 /*===========================================================================*
139 * create_read_scsi_cmd *
140 *===========================================================================*/
141 static int
create_read_scsi_cmd(mass_storage_cbw * cbw,scsi_transfer * info)142 create_read_scsi_cmd(mass_storage_cbw * cbw, scsi_transfer * info)
143 {
144 MASS_DEBUG_DUMP;
145
146 assert(NULL != info);
147 assert(0 == (info->length % SECTOR_SIZE));
148
149 cbw->dCBWDataTransferLength = info->length;
150 cbw->bCBWFlags = CBW_FLAGS_IN;
151 cbw->bCDBLength = SCSI_READ_CMD_LEN;
152
153 SCSI_SET_READ_OP_CODE(cbw->CBWCB);
154 SCSI_SET_READ_LBA(cbw->CBWCB, info->lba);
155 SCSI_SET_READ_BLEN(cbw->CBWCB, info->length / SECTOR_SIZE);
156
157 return EXIT_SUCCESS;
158 }
159
160
161 /*===========================================================================*
162 * create_mode_sense_scsi_cmd *
163 *===========================================================================*/
164 static int
create_mode_sense_scsi_cmd(mass_storage_cbw * cbw)165 create_mode_sense_scsi_cmd(mass_storage_cbw * cbw)
166 {
167 MASS_DEBUG_DUMP;
168
169 cbw->dCBWDataTransferLength = SCSI_MODE_SENSE_FLEX_DATA_LEN;
170 cbw->bCBWFlags = CBW_FLAGS_IN;
171 cbw->bCDBLength = SCSI_MODE_SENSE_CMD_LEN;
172
173 SCSI_SET_MODE_SENSE_OP_CODE(cbw->CBWCB);
174 SCSI_SET_MODE_SENSE_PAGE_CODE(cbw->CBWCB,
175 SCSI_MODE_SENSE_FLEXIBLE_DISK_PAGE);
176
177 return EXIT_SUCCESS;
178 }
179
180
181 /*===========================================================================*
182 * create_request_sense_scsi_cmd *
183 *===========================================================================*/
184 static int
create_request_sense_scsi_cmd(mass_storage_cbw * cbw)185 create_request_sense_scsi_cmd(mass_storage_cbw * cbw)
186 {
187 MASS_DEBUG_DUMP;
188
189 cbw->dCBWDataTransferLength = SCSI_REQUEST_SENSE_DATA_LEN;
190 cbw->bCBWFlags = CBW_FLAGS_IN;
191 cbw->bCDBLength = SCSI_REQUEST_SENSE_CMD_LEN;
192
193 SCSI_SET_REQUEST_SENSE_OP_CODE(cbw->CBWCB);
194 SCSI_SET_REQUEST_SENSE_ALLOC(cbw->CBWCB, SCSI_REQUEST_SENSE_DATA_LEN);
195
196 return EXIT_SUCCESS;
197 }
198
199
200 /*===========================================================================*
201 * check_inquiry_reply *
202 *===========================================================================*/
203 int
check_inquiry_reply(uint8_t * scsi_reply)204 check_inquiry_reply(uint8_t * scsi_reply)
205 {
206 char vendor_name[SCSI_INQUIRY_VENDOR_NAME_LEN + 1];
207 char product_name[SCSI_INQUIRY_PRODUCT_NAME_LEN + 1];
208
209 MASS_DEBUG_DUMP;
210
211 /* Stop condition for printing as strncpy() does not add it */
212 vendor_name[SCSI_INQUIRY_VENDOR_NAME_LEN] = '\0';
213 product_name[SCSI_INQUIRY_PRODUCT_NAME_LEN] = '\0';
214
215 if (SCSI_GET_INQUIRY_PERIPH_QUALIF(scsi_reply)) {
216 MASS_MSG("Device not connected");
217 return EXIT_FAILURE;
218 }
219
220 strncpy(vendor_name, SCSI_GET_INQUIRY_VENDOR_NAME(scsi_reply),
221 SCSI_INQUIRY_VENDOR_NAME_LEN);
222 strncpy(product_name, SCSI_GET_INQUIRY_PRODUCT_NAME(scsi_reply),
223 SCSI_INQUIRY_PRODUCT_NAME_LEN);
224
225 MASS_DEBUG_MSG("Vendor name: %s", vendor_name);
226 MASS_DEBUG_MSG("Product name %s", product_name);
227
228 return EXIT_SUCCESS;
229 }
230
231
232 /*===========================================================================*
233 * check_read_capacity_reply *
234 *===========================================================================*/
235 int
check_read_capacity_reply(uint8_t * scsi_reply,uint32_t * lba,uint32_t * blen)236 check_read_capacity_reply(uint8_t * scsi_reply, uint32_t * lba, uint32_t * blen)
237 {
238 MASS_DEBUG_DUMP;
239
240 *lba = SCSI_GET_READ_CAPACITY_LBA(scsi_reply);
241 *blen = SCSI_GET_READ_CAPACITY_BLEN(scsi_reply);
242
243 return EXIT_SUCCESS;
244 }
245
246
247 /*===========================================================================*
248 * check_mode_sense_reply *
249 *===========================================================================*/
250 int
check_mode_sense_reply(uint8_t * scsi_reply,unsigned * cyl,unsigned * head,unsigned * sect)251 check_mode_sense_reply(uint8_t * scsi_reply, unsigned * cyl,
252 unsigned * head, unsigned * sect)
253 {
254 MASS_DEBUG_DUMP;
255
256 *cyl = SCSI_GET_MODE_SENSE_CYLINDERS(scsi_reply);
257 *head = SCSI_GET_MODE_SENSE_HEADS(scsi_reply);
258 *sect = SCSI_GET_MODE_SENSE_SECTORS(scsi_reply);
259
260 return EXIT_SUCCESS;
261 }
262
263
264 /*===========================================================================*
265 * check_csw *
266 *===========================================================================*/
267 int
check_csw(mass_storage_csw * csw,unsigned int tag)268 check_csw(mass_storage_csw * csw, unsigned int tag)
269 {
270 MASS_DEBUG_DUMP;
271
272 if (csw->dCSWTag != tag) {
273 MASS_MSG("CSW tag mismatch!");
274 return EXIT_FAILURE;
275 }
276
277 if (CSW_SIGNATURE != csw->dCSWSignature) {
278 MASS_MSG("CSW signature mismatch!");
279 return EXIT_FAILURE;
280 }
281
282 if (CSW_STATUS_GOOD != csw->bCSWStatus) {
283 MASS_MSG("CSW status error (0x%02X)!", csw->bCSWStatus);
284 return EXIT_FAILURE;
285 }
286
287 return EXIT_SUCCESS;
288 }
289