1433d6423SLionel Sambuc /*
2433d6423SLionel Sambuc * SCSI commands related implementation
3433d6423SLionel Sambuc */
4433d6423SLionel Sambuc
5433d6423SLionel Sambuc #include <minix/blockdriver.h> /* SECTOR_SIZE */
6433d6423SLionel Sambuc
7433d6423SLionel Sambuc #include <assert.h>
8433d6423SLionel Sambuc #include <string.h> /* strncpy */
9433d6423SLionel Sambuc
10433d6423SLionel Sambuc #include "common.h"
11433d6423SLionel Sambuc #include "scsi.h"
12433d6423SLionel Sambuc
13433d6423SLionel Sambuc /*---------------------------*
14433d6423SLionel Sambuc * declared functions *
15433d6423SLionel Sambuc *---------------------------*/
16433d6423SLionel Sambuc /* To work correctly cbw->CBWCB must be zeroed before calling these: */
17433d6423SLionel Sambuc static int create_inquiry_scsi_cmd(mass_storage_cbw *);
18433d6423SLionel Sambuc static int create_test_scsi_cmd(mass_storage_cbw *);
19433d6423SLionel Sambuc static int create_read_capacity_scsi_cmd(mass_storage_cbw *);
20433d6423SLionel Sambuc static int create_write_scsi_cmd(mass_storage_cbw *, scsi_transfer *);
21433d6423SLionel Sambuc static int create_read_scsi_cmd(mass_storage_cbw *, scsi_transfer *);
22433d6423SLionel Sambuc static int create_mode_sense_scsi_cmd(mass_storage_cbw *);
23*2d64210cSWojciech Zajac static int create_request_sense_scsi_cmd(mass_storage_cbw *);
24433d6423SLionel Sambuc
25433d6423SLionel Sambuc /*---------------------------*
26433d6423SLionel Sambuc * defined functions *
27433d6423SLionel Sambuc *---------------------------*/
28433d6423SLionel Sambuc /*===========================================================================*
29433d6423SLionel Sambuc * create_scsi_cmd *
30433d6423SLionel Sambuc *===========================================================================*/
31433d6423SLionel Sambuc int
create_scsi_cmd(mass_storage_cbw * cbw,int cmd,scsi_transfer * info)32433d6423SLionel Sambuc create_scsi_cmd(mass_storage_cbw * cbw, int cmd, scsi_transfer * info)
33433d6423SLionel Sambuc {
34433d6423SLionel Sambuc MASS_DEBUG_DUMP;
35433d6423SLionel Sambuc
36433d6423SLionel Sambuc assert(NULL != cbw);
37433d6423SLionel Sambuc
38433d6423SLionel Sambuc switch (cmd) {
39433d6423SLionel Sambuc case SCSI_INQUIRY:
40433d6423SLionel Sambuc return create_inquiry_scsi_cmd(cbw);
41433d6423SLionel Sambuc case SCSI_TEST_UNIT_READY:
42433d6423SLionel Sambuc return create_test_scsi_cmd(cbw);
43433d6423SLionel Sambuc case SCSI_READ_CAPACITY:
44433d6423SLionel Sambuc return create_read_capacity_scsi_cmd(cbw);
45433d6423SLionel Sambuc case SCSI_WRITE:
46433d6423SLionel Sambuc return create_write_scsi_cmd(cbw, info);
47433d6423SLionel Sambuc case SCSI_READ:
48433d6423SLionel Sambuc return create_read_scsi_cmd(cbw, info);
49433d6423SLionel Sambuc case SCSI_MODE_SENSE:
50433d6423SLionel Sambuc return create_mode_sense_scsi_cmd(cbw);
51*2d64210cSWojciech Zajac case SCSI_REQUEST_SENSE:
52*2d64210cSWojciech Zajac return create_request_sense_scsi_cmd(cbw);
53433d6423SLionel Sambuc default:
54433d6423SLionel Sambuc MASS_MSG("Invalid SCSI command!");
55433d6423SLionel Sambuc return EXIT_FAILURE;
56433d6423SLionel Sambuc }
57433d6423SLionel Sambuc }
58433d6423SLionel Sambuc
59433d6423SLionel Sambuc
60433d6423SLionel Sambuc /*===========================================================================*
61433d6423SLionel Sambuc * create_inquiry_scsi_cmd *
62433d6423SLionel Sambuc *===========================================================================*/
63433d6423SLionel Sambuc static int
create_inquiry_scsi_cmd(mass_storage_cbw * cbw)64433d6423SLionel Sambuc create_inquiry_scsi_cmd(mass_storage_cbw * cbw)
65433d6423SLionel Sambuc {
66433d6423SLionel Sambuc MASS_DEBUG_DUMP;
67433d6423SLionel Sambuc
68433d6423SLionel Sambuc cbw->dCBWDataTransferLength = SCSI_INQUIRY_DATA_LEN;
69433d6423SLionel Sambuc cbw->bCBWFlags = CBW_FLAGS_IN;
70433d6423SLionel Sambuc cbw->bCDBLength = SCSI_INQUIRY_CMD_LEN;
71433d6423SLionel Sambuc
72433d6423SLionel Sambuc SCSI_SET_INQUIRY_OP_CODE(cbw->CBWCB);
73433d6423SLionel Sambuc SCSI_SET_INQUIRY_PAGE_CODE(cbw->CBWCB, 0);
74433d6423SLionel Sambuc SCSI_SET_INQUIRY_ALLOC_LEN(cbw->CBWCB, SCSI_INQUIRY_DATA_LEN);
75433d6423SLionel Sambuc
76433d6423SLionel Sambuc return EXIT_SUCCESS;
77433d6423SLionel Sambuc }
78433d6423SLionel Sambuc
79433d6423SLionel Sambuc
80433d6423SLionel Sambuc /*===========================================================================*
81433d6423SLionel Sambuc * create_test_scsi_cmd *
82433d6423SLionel Sambuc *===========================================================================*/
83433d6423SLionel Sambuc static int
create_test_scsi_cmd(mass_storage_cbw * cbw)84433d6423SLionel Sambuc create_test_scsi_cmd(mass_storage_cbw * cbw)
85433d6423SLionel Sambuc {
86433d6423SLionel Sambuc MASS_DEBUG_DUMP;
87433d6423SLionel Sambuc
88433d6423SLionel Sambuc cbw->bCDBLength = SCSI_TEST_CMD_LEN;
89433d6423SLionel Sambuc
90433d6423SLionel Sambuc SCSI_SET_TEST_OP_CODE(cbw->CBWCB);
91433d6423SLionel Sambuc
92433d6423SLionel Sambuc return EXIT_SUCCESS;
93433d6423SLionel Sambuc }
94433d6423SLionel Sambuc
95433d6423SLionel Sambuc
96433d6423SLionel Sambuc /*===========================================================================*
97433d6423SLionel Sambuc * create_read_capacity_scsi_cmd *
98433d6423SLionel Sambuc *===========================================================================*/
99433d6423SLionel Sambuc static int
create_read_capacity_scsi_cmd(mass_storage_cbw * cbw)100433d6423SLionel Sambuc create_read_capacity_scsi_cmd(mass_storage_cbw * cbw)
101433d6423SLionel Sambuc {
102433d6423SLionel Sambuc MASS_DEBUG_DUMP;
103433d6423SLionel Sambuc
104433d6423SLionel Sambuc cbw->dCBWDataTransferLength = SCSI_READ_CAPACITY_DATA_LEN;
105433d6423SLionel Sambuc cbw->bCBWFlags = CBW_FLAGS_IN;
106433d6423SLionel Sambuc cbw->bCDBLength = SCSI_READ_CAPACITY_CMD_LEN;
107433d6423SLionel Sambuc
108433d6423SLionel Sambuc SCSI_SET_READ_CAPACITY_OP_CODE(cbw->CBWCB);
109433d6423SLionel Sambuc SCSI_SET_READ_CAPACITY_LBA(cbw->CBWCB, 0x00);
110433d6423SLionel Sambuc
111433d6423SLionel Sambuc return EXIT_SUCCESS;
112433d6423SLionel Sambuc }
113433d6423SLionel Sambuc
114433d6423SLionel Sambuc
115433d6423SLionel Sambuc /*===========================================================================*
116433d6423SLionel Sambuc * create_write_scsi_cmd *
117433d6423SLionel Sambuc *===========================================================================*/
118433d6423SLionel Sambuc static int
create_write_scsi_cmd(mass_storage_cbw * cbw,scsi_transfer * info)119433d6423SLionel Sambuc create_write_scsi_cmd(mass_storage_cbw * cbw, scsi_transfer * info)
120433d6423SLionel Sambuc {
121433d6423SLionel Sambuc MASS_DEBUG_DUMP;
122433d6423SLionel Sambuc
123433d6423SLionel Sambuc assert(NULL != info);
124433d6423SLionel Sambuc assert(0 == (info->length % SECTOR_SIZE));
125433d6423SLionel Sambuc
126433d6423SLionel Sambuc cbw->dCBWDataTransferLength = info->length;
127433d6423SLionel Sambuc cbw->bCBWFlags = CBW_FLAGS_OUT;
128433d6423SLionel Sambuc cbw->bCDBLength = SCSI_WRITE_CMD_LEN;
129433d6423SLionel Sambuc
130433d6423SLionel Sambuc SCSI_SET_WRITE_OP_CODE(cbw->CBWCB);
131433d6423SLionel Sambuc SCSI_SET_WRITE_LBA(cbw->CBWCB, info->lba);
132433d6423SLionel Sambuc SCSI_SET_WRITE_BLEN(cbw->CBWCB, info->length / SECTOR_SIZE);
133433d6423SLionel Sambuc
134433d6423SLionel Sambuc return EXIT_SUCCESS;
135433d6423SLionel Sambuc }
136433d6423SLionel Sambuc
137433d6423SLionel Sambuc
138433d6423SLionel Sambuc /*===========================================================================*
139433d6423SLionel Sambuc * create_read_scsi_cmd *
140433d6423SLionel Sambuc *===========================================================================*/
141433d6423SLionel Sambuc static int
create_read_scsi_cmd(mass_storage_cbw * cbw,scsi_transfer * info)142433d6423SLionel Sambuc create_read_scsi_cmd(mass_storage_cbw * cbw, scsi_transfer * info)
143433d6423SLionel Sambuc {
144433d6423SLionel Sambuc MASS_DEBUG_DUMP;
145433d6423SLionel Sambuc
146433d6423SLionel Sambuc assert(NULL != info);
147433d6423SLionel Sambuc assert(0 == (info->length % SECTOR_SIZE));
148433d6423SLionel Sambuc
149433d6423SLionel Sambuc cbw->dCBWDataTransferLength = info->length;
150433d6423SLionel Sambuc cbw->bCBWFlags = CBW_FLAGS_IN;
151433d6423SLionel Sambuc cbw->bCDBLength = SCSI_READ_CMD_LEN;
152433d6423SLionel Sambuc
153433d6423SLionel Sambuc SCSI_SET_READ_OP_CODE(cbw->CBWCB);
154433d6423SLionel Sambuc SCSI_SET_READ_LBA(cbw->CBWCB, info->lba);
155433d6423SLionel Sambuc SCSI_SET_READ_BLEN(cbw->CBWCB, info->length / SECTOR_SIZE);
156433d6423SLionel Sambuc
157433d6423SLionel Sambuc return EXIT_SUCCESS;
158433d6423SLionel Sambuc }
159433d6423SLionel Sambuc
160433d6423SLionel Sambuc
161433d6423SLionel Sambuc /*===========================================================================*
162433d6423SLionel Sambuc * create_mode_sense_scsi_cmd *
163433d6423SLionel Sambuc *===========================================================================*/
164433d6423SLionel Sambuc static int
create_mode_sense_scsi_cmd(mass_storage_cbw * cbw)165433d6423SLionel Sambuc create_mode_sense_scsi_cmd(mass_storage_cbw * cbw)
166433d6423SLionel Sambuc {
167433d6423SLionel Sambuc MASS_DEBUG_DUMP;
168433d6423SLionel Sambuc
169433d6423SLionel Sambuc cbw->dCBWDataTransferLength = SCSI_MODE_SENSE_FLEX_DATA_LEN;
170433d6423SLionel Sambuc cbw->bCBWFlags = CBW_FLAGS_IN;
171433d6423SLionel Sambuc cbw->bCDBLength = SCSI_MODE_SENSE_CMD_LEN;
172433d6423SLionel Sambuc
173433d6423SLionel Sambuc SCSI_SET_MODE_SENSE_OP_CODE(cbw->CBWCB);
174433d6423SLionel Sambuc SCSI_SET_MODE_SENSE_PAGE_CODE(cbw->CBWCB,
175433d6423SLionel Sambuc SCSI_MODE_SENSE_FLEXIBLE_DISK_PAGE);
176433d6423SLionel Sambuc
177433d6423SLionel Sambuc return EXIT_SUCCESS;
178433d6423SLionel Sambuc }
179433d6423SLionel Sambuc
180433d6423SLionel Sambuc
181433d6423SLionel Sambuc /*===========================================================================*
182*2d64210cSWojciech Zajac * create_request_sense_scsi_cmd *
183*2d64210cSWojciech Zajac *===========================================================================*/
184*2d64210cSWojciech Zajac static int
create_request_sense_scsi_cmd(mass_storage_cbw * cbw)185*2d64210cSWojciech Zajac create_request_sense_scsi_cmd(mass_storage_cbw * cbw)
186*2d64210cSWojciech Zajac {
187*2d64210cSWojciech Zajac MASS_DEBUG_DUMP;
188*2d64210cSWojciech Zajac
189*2d64210cSWojciech Zajac cbw->dCBWDataTransferLength = SCSI_REQUEST_SENSE_DATA_LEN;
190*2d64210cSWojciech Zajac cbw->bCBWFlags = CBW_FLAGS_IN;
191*2d64210cSWojciech Zajac cbw->bCDBLength = SCSI_REQUEST_SENSE_CMD_LEN;
192*2d64210cSWojciech Zajac
193*2d64210cSWojciech Zajac SCSI_SET_REQUEST_SENSE_OP_CODE(cbw->CBWCB);
194*2d64210cSWojciech Zajac SCSI_SET_REQUEST_SENSE_ALLOC(cbw->CBWCB, SCSI_REQUEST_SENSE_DATA_LEN);
195*2d64210cSWojciech Zajac
196*2d64210cSWojciech Zajac return EXIT_SUCCESS;
197*2d64210cSWojciech Zajac }
198*2d64210cSWojciech Zajac
199*2d64210cSWojciech Zajac
200*2d64210cSWojciech Zajac /*===========================================================================*
201433d6423SLionel Sambuc * check_inquiry_reply *
202433d6423SLionel Sambuc *===========================================================================*/
203433d6423SLionel Sambuc int
check_inquiry_reply(uint8_t * scsi_reply)204433d6423SLionel Sambuc check_inquiry_reply(uint8_t * scsi_reply)
205433d6423SLionel Sambuc {
206433d6423SLionel Sambuc char vendor_name[SCSI_INQUIRY_VENDOR_NAME_LEN + 1];
207433d6423SLionel Sambuc char product_name[SCSI_INQUIRY_PRODUCT_NAME_LEN + 1];
208433d6423SLionel Sambuc
209433d6423SLionel Sambuc MASS_DEBUG_DUMP;
210433d6423SLionel Sambuc
211433d6423SLionel Sambuc /* Stop condition for printing as strncpy() does not add it */
212433d6423SLionel Sambuc vendor_name[SCSI_INQUIRY_VENDOR_NAME_LEN] = '\0';
213433d6423SLionel Sambuc product_name[SCSI_INQUIRY_PRODUCT_NAME_LEN] = '\0';
214433d6423SLionel Sambuc
215433d6423SLionel Sambuc if (SCSI_GET_INQUIRY_PERIPH_QUALIF(scsi_reply)) {
216433d6423SLionel Sambuc MASS_MSG("Device not connected");
217433d6423SLionel Sambuc return EXIT_FAILURE;
218433d6423SLionel Sambuc }
219433d6423SLionel Sambuc
220433d6423SLionel Sambuc strncpy(vendor_name, SCSI_GET_INQUIRY_VENDOR_NAME(scsi_reply),
221433d6423SLionel Sambuc SCSI_INQUIRY_VENDOR_NAME_LEN);
222433d6423SLionel Sambuc strncpy(product_name, SCSI_GET_INQUIRY_PRODUCT_NAME(scsi_reply),
223433d6423SLionel Sambuc SCSI_INQUIRY_PRODUCT_NAME_LEN);
224433d6423SLionel Sambuc
225433d6423SLionel Sambuc MASS_DEBUG_MSG("Vendor name: %s", vendor_name);
226433d6423SLionel Sambuc MASS_DEBUG_MSG("Product name %s", product_name);
227433d6423SLionel Sambuc
228433d6423SLionel Sambuc return EXIT_SUCCESS;
229433d6423SLionel Sambuc }
230433d6423SLionel Sambuc
231433d6423SLionel Sambuc
232433d6423SLionel Sambuc /*===========================================================================*
233433d6423SLionel Sambuc * check_read_capacity_reply *
234433d6423SLionel Sambuc *===========================================================================*/
235433d6423SLionel Sambuc int
check_read_capacity_reply(uint8_t * scsi_reply,uint32_t * lba,uint32_t * blen)236433d6423SLionel Sambuc check_read_capacity_reply(uint8_t * scsi_reply, uint32_t * lba, uint32_t * blen)
237433d6423SLionel Sambuc {
238433d6423SLionel Sambuc MASS_DEBUG_DUMP;
239433d6423SLionel Sambuc
240433d6423SLionel Sambuc *lba = SCSI_GET_READ_CAPACITY_LBA(scsi_reply);
241433d6423SLionel Sambuc *blen = SCSI_GET_READ_CAPACITY_BLEN(scsi_reply);
242433d6423SLionel Sambuc
243433d6423SLionel Sambuc return EXIT_SUCCESS;
244433d6423SLionel Sambuc }
245433d6423SLionel Sambuc
246433d6423SLionel Sambuc
247433d6423SLionel Sambuc /*===========================================================================*
248433d6423SLionel Sambuc * check_mode_sense_reply *
249433d6423SLionel Sambuc *===========================================================================*/
250433d6423SLionel Sambuc int
check_mode_sense_reply(uint8_t * scsi_reply,unsigned * cyl,unsigned * head,unsigned * sect)251433d6423SLionel Sambuc check_mode_sense_reply(uint8_t * scsi_reply, unsigned * cyl,
252433d6423SLionel Sambuc unsigned * head, unsigned * sect)
253433d6423SLionel Sambuc {
254433d6423SLionel Sambuc MASS_DEBUG_DUMP;
255433d6423SLionel Sambuc
256433d6423SLionel Sambuc *cyl = SCSI_GET_MODE_SENSE_CYLINDERS(scsi_reply);
257433d6423SLionel Sambuc *head = SCSI_GET_MODE_SENSE_HEADS(scsi_reply);
258433d6423SLionel Sambuc *sect = SCSI_GET_MODE_SENSE_SECTORS(scsi_reply);
259433d6423SLionel Sambuc
260433d6423SLionel Sambuc return EXIT_SUCCESS;
261433d6423SLionel Sambuc }
262433d6423SLionel Sambuc
263433d6423SLionel Sambuc
264433d6423SLionel Sambuc /*===========================================================================*
265433d6423SLionel Sambuc * check_csw *
266433d6423SLionel Sambuc *===========================================================================*/
267433d6423SLionel Sambuc int
check_csw(mass_storage_csw * csw,unsigned int tag)268433d6423SLionel Sambuc check_csw(mass_storage_csw * csw, unsigned int tag)
269433d6423SLionel Sambuc {
270433d6423SLionel Sambuc MASS_DEBUG_DUMP;
271433d6423SLionel Sambuc
272433d6423SLionel Sambuc if (csw->dCSWTag != tag) {
273433d6423SLionel Sambuc MASS_MSG("CSW tag mismatch!");
274433d6423SLionel Sambuc return EXIT_FAILURE;
275433d6423SLionel Sambuc }
276433d6423SLionel Sambuc
277433d6423SLionel Sambuc if (CSW_SIGNATURE != csw->dCSWSignature) {
278433d6423SLionel Sambuc MASS_MSG("CSW signature mismatch!");
279433d6423SLionel Sambuc return EXIT_FAILURE;
280433d6423SLionel Sambuc }
281433d6423SLionel Sambuc
282433d6423SLionel Sambuc if (CSW_STATUS_GOOD != csw->bCSWStatus) {
283433d6423SLionel Sambuc MASS_MSG("CSW status error (0x%02X)!", csw->bCSWStatus);
284433d6423SLionel Sambuc return EXIT_FAILURE;
285433d6423SLionel Sambuc }
286433d6423SLionel Sambuc
287433d6423SLionel Sambuc return EXIT_SUCCESS;
288433d6423SLionel Sambuc }
289