2 * SCSI commands related implementation
5 #include <minix/blockdriver.h> /* SECTOR_SIZE */
8 #include <string.h> /* strncpy */
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
*);
25 /*---------------------------*
27 *---------------------------*/
28 /*===========================================================================*
30 *===========================================================================*/
32 create_scsi_cmd(mass_storage_cbw
* cbw
, int cmd
, scsi_transfer
* info
)
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
);
46 return create_write_scsi_cmd(cbw
, info
);
48 return create_read_scsi_cmd(cbw
, info
);
50 return create_mode_sense_scsi_cmd(cbw
);
51 case SCSI_REQUEST_SENSE
:
52 return create_request_sense_scsi_cmd(cbw
);
54 MASS_MSG("Invalid SCSI command!");
60 /*===========================================================================*
61 * create_inquiry_scsi_cmd *
62 *===========================================================================*/
64 create_inquiry_scsi_cmd(mass_storage_cbw
* cbw
)
68 cbw
->dCBWDataTransferLength
= SCSI_INQUIRY_DATA_LEN
;
69 cbw
->bCBWFlags
= CBW_FLAGS_IN
;
70 cbw
->bCDBLength
= SCSI_INQUIRY_CMD_LEN
;
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
);
80 /*===========================================================================*
81 * create_test_scsi_cmd *
82 *===========================================================================*/
84 create_test_scsi_cmd(mass_storage_cbw
* cbw
)
88 cbw
->bCDBLength
= SCSI_TEST_CMD_LEN
;
90 SCSI_SET_TEST_OP_CODE(cbw
->CBWCB
);
96 /*===========================================================================*
97 * create_read_capacity_scsi_cmd *
98 *===========================================================================*/
100 create_read_capacity_scsi_cmd(mass_storage_cbw
* cbw
)
104 cbw
->dCBWDataTransferLength
= SCSI_READ_CAPACITY_DATA_LEN
;
105 cbw
->bCBWFlags
= CBW_FLAGS_IN
;
106 cbw
->bCDBLength
= SCSI_READ_CAPACITY_CMD_LEN
;
108 SCSI_SET_READ_CAPACITY_OP_CODE(cbw
->CBWCB
);
109 SCSI_SET_READ_CAPACITY_LBA(cbw
->CBWCB
, 0x00);
115 /*===========================================================================*
116 * create_write_scsi_cmd *
117 *===========================================================================*/
119 create_write_scsi_cmd(mass_storage_cbw
* cbw
, scsi_transfer
* info
)
123 assert(NULL
!= info
);
124 assert(0 == (info
->length
% SECTOR_SIZE
));
126 cbw
->dCBWDataTransferLength
= info
->length
;
127 cbw
->bCBWFlags
= CBW_FLAGS_OUT
;
128 cbw
->bCDBLength
= SCSI_WRITE_CMD_LEN
;
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
);
138 /*===========================================================================*
139 * create_read_scsi_cmd *
140 *===========================================================================*/
142 create_read_scsi_cmd(mass_storage_cbw
* cbw
, scsi_transfer
* info
)
146 assert(NULL
!= info
);
147 assert(0 == (info
->length
% SECTOR_SIZE
));
149 cbw
->dCBWDataTransferLength
= info
->length
;
150 cbw
->bCBWFlags
= CBW_FLAGS_IN
;
151 cbw
->bCDBLength
= SCSI_READ_CMD_LEN
;
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
);
161 /*===========================================================================*
162 * create_mode_sense_scsi_cmd *
163 *===========================================================================*/
165 create_mode_sense_scsi_cmd(mass_storage_cbw
* cbw
)
169 cbw
->dCBWDataTransferLength
= SCSI_MODE_SENSE_FLEX_DATA_LEN
;
170 cbw
->bCBWFlags
= CBW_FLAGS_IN
;
171 cbw
->bCDBLength
= SCSI_MODE_SENSE_CMD_LEN
;
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
);
181 /*===========================================================================*
182 * create_request_sense_scsi_cmd *
183 *===========================================================================*/
185 create_request_sense_scsi_cmd(mass_storage_cbw
* cbw
)
189 cbw
->dCBWDataTransferLength
= SCSI_REQUEST_SENSE_DATA_LEN
;
190 cbw
->bCBWFlags
= CBW_FLAGS_IN
;
191 cbw
->bCDBLength
= SCSI_REQUEST_SENSE_CMD_LEN
;
193 SCSI_SET_REQUEST_SENSE_OP_CODE(cbw
->CBWCB
);
194 SCSI_SET_REQUEST_SENSE_ALLOC(cbw
->CBWCB
, SCSI_REQUEST_SENSE_DATA_LEN
);
200 /*===========================================================================*
201 * check_inquiry_reply *
202 *===========================================================================*/
204 check_inquiry_reply(uint8_t * scsi_reply
)
206 char vendor_name
[SCSI_INQUIRY_VENDOR_NAME_LEN
+ 1];
207 char product_name
[SCSI_INQUIRY_PRODUCT_NAME_LEN
+ 1];
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';
215 if (SCSI_GET_INQUIRY_PERIPH_QUALIF(scsi_reply
)) {
216 MASS_MSG("Device not connected");
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
);
225 MASS_DEBUG_MSG("Vendor name: %s", vendor_name
);
226 MASS_DEBUG_MSG("Product name %s", product_name
);
232 /*===========================================================================*
233 * check_read_capacity_reply *
234 *===========================================================================*/
236 check_read_capacity_reply(uint8_t * scsi_reply
, uint32_t * lba
, uint32_t * blen
)
240 *lba
= SCSI_GET_READ_CAPACITY_LBA(scsi_reply
);
241 *blen
= SCSI_GET_READ_CAPACITY_BLEN(scsi_reply
);
247 /*===========================================================================*
248 * check_mode_sense_reply *
249 *===========================================================================*/
251 check_mode_sense_reply(uint8_t * scsi_reply
, unsigned * cyl
,
252 unsigned * head
, unsigned * sect
)
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
);
264 /*===========================================================================*
266 *===========================================================================*/
268 check_csw(mass_storage_csw
* csw
, unsigned int tag
)
272 if (csw
->dCSWTag
!= tag
) {
273 MASS_MSG("CSW tag mismatch!");
277 if (CSW_SIGNATURE
!= csw
->dCSWSignature
) {
278 MASS_MSG("CSW signature mismatch!");
282 if (CSW_STATUS_GOOD
!= csw
->bCSWStatus
) {
283 MASS_MSG("CSW status error (0x%02X)!", csw
->bCSWStatus
);