1 /*******************************************************************************
2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * PolarFire SoC MSS USB Driver Stack
7 * USB Logical Layer (USB-LL)
8 * USBD-MSC class driver.
9 *
10 * USBD-MSC class driver implementation:
11 * This source file implements Mass storage class functionality.
12 * BoT with Transparent SCSI command set is implemented.
13 *
14 */
15
16 #include "mpfs_hal/mss_hal.h"
17 #include "mss_usb_device.h"
18 #include "mss_usb_device_msd.h"
19 #include "mss_usb_std_def.h"
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 #ifdef MSS_USB_DEVICE_ENABLED
26
27 #define MSC_CLASS_BULK_RX_EP MSS_USB_RX_EP_1
28 #define MSC_CLASS_BULK_TX_EP MSS_USB_TX_EP_1
29
30 #define MSC_CLASS_INTERFACE_NUM 0x00
31 /*HS Operation values*/
32 #define MSC_TX_EP_FIFO_SIZE_HS 512
33 #define MSC_RX_EP_FIFO_SIZE_HS 512
34
35 /*Values should be same as described in ep descriptors*/
36 #define MSC_TX_EP_MAX_PKT_SIZE_HS 512
37 #define MSC_RX_EP_MAX_PKT_SIZE_HS 512
38
39 /*LS Operation values*/
40 #define MSC_TX_EP_FIFO_SIZE_FS 64
41 #define MSC_RX_EP_FIFO_SIZE_FS 64
42
43 /*Values should be same as described in ep descriptors*/
44 #define MSC_TX_EP_MAX_PKT_SIZE_FS 64
45 #define MSC_RX_EP_MAX_PKT_SIZE_FS 64
46
47
48 #define G_BOT_CBW_INIT(); g_bot_cbw.signature = 0;\
49 g_bot_cbw.tag = 0;\
50 g_bot_cbw.xfr_length = 0;\
51 g_bot_cbw.flags = 0;\
52 g_bot_cbw.lun = 0;\
53 g_bot_cbw.cmd_length = 0;\
54 g_bot_cbw.cmd_block[0]=(uint8_t)0;\
55 g_bot_cbw.cmd_block[1]=(uint8_t)0;\
56 g_bot_cbw.cmd_block[2]=(uint8_t)0;\
57 g_bot_cbw.cmd_block[3]=(uint8_t)0;\
58 g_bot_cbw.cmd_block[4]=(uint8_t)0;\
59 g_bot_cbw.cmd_block[5]=(uint8_t)0;\
60 g_bot_cbw.cmd_block[6]=(uint8_t)0;\
61 g_bot_cbw.cmd_block[7]=(uint8_t)0;\
62 g_bot_cbw.cmd_block[8]=(uint8_t)0;\
63 g_bot_cbw.cmd_block[9]=(uint8_t)0;\
64 g_bot_cbw.cmd_block[10]=(uint8_t)0;\
65 g_bot_cbw.cmd_block[11]=(uint8_t)0;\
66 g_bot_cbw.cmd_block[12]=(uint8_t)0;\
67 g_bot_cbw.cmd_block[13]=(uint8_t)0;\
68 g_bot_cbw.cmd_block[14]=(uint8_t)0;\
69 g_bot_cbw.cmd_block[15]=(uint8_t)0;
70
71
72 #define CB_PASS 0x01u
73 #define CB_NOT_SUPPORTED 0x02u
74 #define CB_INTERNAL_ERROR 0x03u
75 #define CB_LENGTH_MISMATCH 0x04u
76 #define CB_DATA_DIR_MISMATCH 0x05u
77 #define CB_MOREDATA 0x06u
78 #define CB_LESSDATA 0x07u
79 #define CB_INVALID_LUN 0x08u
80 #define CB_INVALID_CDB_FIELD 0x09u
81 #define CB_INVALID_CBW 0x0Au
82 #define CB_DATAPHASE_ERROR 0x0Bu
83
84 #define MSCD_CONF_DESCR_DESCTYPE_IDX 1u
85
86
87 /***************************************************************************//**
88 Local functions used by USBD-MSC class driver.
89 */
90 static uint8_t usbd_msc_process_cbw(mss_usb_msc_cbw_t * cbw);
91 static void usbd_msc_prepare_sense_data(uint8_t lun, uint8_t skey, uint8_t asc);
92 static void usbd_msc_abort_cbw(uint8_t lun);
93 static void usbd_msc_bot_fsm(uint8_t status, uint32_t rx_count);
94 static void usbd_msc_send_data(uint8_t* buf, uint32_t len);
95 static void usbd_msc_receive_data(uint8_t* buf, uint32_t len);
96 static void usbd_msc_send_csw(void);
97 static void usbd_msc_stallin_sendstatus(void);
98 static void usbd_msc_stallout_sendstatus(void);
99 static uint8_t usbd_msc_process_read_10(void);
100 static uint8_t usbd_msc_process_write_10(void);
101 static uint8_t usbd_msc_process_inquiry(void);
102 static uint8_t usbd_msc_process_read_capacity_10(void);
103
104 /***************************************************************************//**
105 Implementations of Call-back functions used by USBD.
106 */
107 static uint8_t* usbd_msc_get_descriptor_cb(uint8_t recepient,
108 uint8_t type,
109 uint32_t* length,
110 mss_usb_device_speed_t musb_speed);
111
112 static uint8_t usbd_msc_init_cb(uint8_t cfgidx, mss_usb_device_speed_t musb_speed);
113 static uint8_t usbd_msc_release_cb(uint8_t cfgidx);
114 static uint8_t usbd_msc_tx_complete_cb(mss_usb_ep_num_t num, uint8_t status);
115
116 static uint8_t usbd_msc_rx_cb(mss_usb_ep_num_t num,
117 uint8_t status,
118 uint32_t rx_count);
119
120 static uint8_t usbd_msc_process_request_cb(mss_usbd_setup_pkt_t* setup_pkt,
121 uint8_t** buf_pp,
122 uint32_t* length);
123
124 /*******************************************************************************
125 Global variables used by USBD-MSC class driver.
126 */
127
128 /*Buffer for responding to GET_MAX_LUN*/
129 uint8_t get_max_lun_response[] __attribute__ ((aligned (4))) = {0x00u};
130
131 /*
132 Buffer for responding to READ_FORMAT CAPACITIES command. Values will be provided
133 by Apps.
134 Driver Does not store Values for All the LUNs.
135 Values of the The LUN on which last USB_MSC_SCSI_READ_FORMAT_CAPACITIES command
136 was executed will be there in this buffer.
137 */
138 uint8_t format_capacity_list[12] __attribute__ ((aligned (4))) = {0};
139 /*
140 Buffer for responding to READ_CAPACITY_10 command. Values will be provided by Apps.
141 Driver retains values for all the supported LUN and uses them to calculate valid
142 address range for that LUN.
143 */
144 mss_usbd_msc_lun_capacity_t lun_capacity[4] __attribute__ ((aligned (4)))= {{0},{0},{0},{0}};
145 /*
146 Buffer to respond to USB_MSC_SCSI_MODE_SENSE_6 command.
147 Values are generated by driver.Same values are returned for all supported LUNs.
148 */
149 uint8_t mode_sense_response[4] __attribute__ ((aligned (4))) = {0x03u, 0x00u, 0x00u, 0x00u};
150
151 /*
152 The g_sense_response is used to respond to REQUEST_SENSE request.
153 Value of this variable is changed depending on the type of failure while
154 responding to the host request.
155 */
156 mss_usbd_msc_scsi_sense_resp_t g_sense_response __attribute__ ((aligned (4))) = {0xF0,0,0,{0},0x0b,{0},0,{0}};
157
158 /*
159 The g_bot_cbw is used to store the current CBW sent by the the host as a
160 BOT request.
161 */
162 mss_usb_msc_cbw_t g_bot_cbw __attribute__ ((aligned (4)));
163
164 /*
165 The g_current_command_csw structure is used to provide the status of the command.
166 The Values of the elements of this structure are updated according to the state
167 of the driver,success/Failure of the command and type of failure.
168 */
169 mss_usbd_msc_csw_t g_current_command_csw __attribute__ ((aligned (4))) =
170 {USB_MSC_BOT_CSW_SIGNATURE,
171 0,
172 0,
173 SCSI_COMMAND_PASS};
174
175 /*****************************************************************************/
176
177 /* Definition for Flash drive application call-backs. */
178 mss_usbd_msc_media_t *g_usbd_msc_media_ops;
179
180 /* USB current Speed of operation selected by user*/
181 mss_usb_device_speed_t g_usbd_msc_user_speed;
182
183 /*
184 Global variables used for multi-transfer OUT transactions
185 */
186 uint8_t* g_xfr_buf_ptr = 0;
187 uint32_t g_xfr_buf_len = 0u;
188 uint32_t g_xfr_lba_addr = 0u;
189
190 typedef enum scsi_req_type {
191 SCSI_ZDR,
192 SCSI_IN,
193 SCSI_OUT
194 } scsi_req_type_t;
195 scsi_req_type_t g_req_type = SCSI_ZDR;
196 /*
197 The g_bot_state is used to store the current state of the driver during
198 Bulk-only Transport (BOT) transaction.
199 The drivers response to the host request depends on this state.
200 */
201 volatile mss_usbd_msc_bot_state_t g_bot_state;
202 /*
203 This variable tracks the current state of the USBD-MSC driver.
204 */
205 mss_usbd_msc_state_t g_usbd_msc_state = USBD_MSC_NOT_CONFIGURED;
206
207 /* The g_bot_events is used to know the current event in the BOT transfer */
208 volatile mss_usbd_msc_bot_events_t g_bottx_events = BOT_EVENT_IDLE;
209 volatile mss_usbd_msc_bot_events_t g_botrx_events = BOT_EVENT_IDLE;
210
211 mss_usbd_class_cb_t usb_msd_class_cb = {usbd_msc_init_cb,
212 usbd_msc_release_cb,
213 usbd_msc_get_descriptor_cb,
214 usbd_msc_process_request_cb,
215 usbd_msc_tx_complete_cb,
216 usbd_msc_rx_cb,
217 0,
218 0 };
219
220 uint8_t msc_fs_conf_descr[FULL_CONFIG_DESCR_LENGTH] =
221 {
222 /*----------------------- Configuration Descriptor -----------------------*/
223 USB_STD_CONFIG_DESCR_LEN, /* bLength */
224 USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
225 FULL_CONFIG_DESCR_LENGTH, /* wTotalLength LSB */
226 0x00u, /* wTotalLength MSB */
227 0x01u, /* bNumInterfaces */
228 0x01u, /* bConfigurationValue */
229 0x04u, /* iConfiguration */
230 0xC0u, /* bmAttributes */
231 0x32u, /* bMaxPower */
232 /*------------------------- Interface Descriptor -------------------------*/
233 USB_STD_INTERFACE_DESCR_LEN, /* bLength */
234 USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
235 MSC_CLASS_INTERFACE_NUM, /* bInterfaceNumber */
236 0x00u, /* bAlternateSetting */
237 0x02u, /* bNumEndpoints */
238 0x08u, /* bInterfaceClass */
239 0x06u, /* bInterfaceSubClass */
240 0x50u, /* bInterfaceProtocol */
241 0x05u, /* bInterface */
242 /*------------------------- IN Endpoint Descriptor --------------------------*/
243 USB_STD_ENDPOINT_DESCR_LEN, /* bLength */
244 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
245 (0x80u | MSC_CLASS_BULK_TX_EP), /* bEndpointAddress */
246 0x02u, /* bmAttributes */
247 0x40u, /* wMaxPacketSize LSB */ //22
248 0x00u, /* wMaxPacketSize MSB */ //23
249 0xFFu, /* bInterval */ //ignored by host for Bulk IN EP
250 /*------------------------- OUT Endpoint Descriptor --------------------------*/
251 USB_STD_ENDPOINT_DESCR_LEN, /* bLength */
252 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
253 MSC_CLASS_BULK_RX_EP, /* bEndpointAddress */
254 0x02u, /* bmAttributes */
255 0x40u, /* wMaxPacketSize LSB *///29
256 0x00u, /* wMaxPacketSize MSB *///30
257 0xFFu /* bInterval *//*Max NAK rate*/
258 };
259
260 /*
261 Configuration descriptor and sub-ordinate descriptors to enumerate the USB device
262 as Mass Storage class Device by host.
263 */
264 uint8_t msc_hs_conf_descr[FULL_CONFIG_DESCR_LENGTH] =
265 {
266 /*----------------------- Configuration Descriptor -----------------------*/
267 USB_STD_CONFIG_DESCR_LEN, /* bLength */
268 USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
269 FULL_CONFIG_DESCR_LENGTH, /* wTotalLength LSB */
270 0x00u, /* wTotalLength MSB */
271 0x01u, /* bNumInterfaces */
272 0x01u, /* bConfigurationValue */
273 0x04u, /* iConfiguration */
274 0xC0u, /* bmAttributes */
275 0x32u, /* bMaxPower */
276 /*------------------------- Interface Descriptor -------------------------*/
277 USB_STD_INTERFACE_DESCR_LEN, /* bLength */
278 USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
279 MSC_CLASS_INTERFACE_NUM, /* bInterfaceNumber */
280 0x00u, /* bAlternateSetting */
281 0x02u, /* bNumEndpoints */
282 0x08u, /* bInterfaceClass */
283 0x06u, /* bInterfaceSubClass */
284 0x50u, /* bInterfaceProtocol */
285 0x05u, /* bInterface */
286 /*------------------------- IN Endpoint Descriptor --------------------------*/
287 USB_STD_ENDPOINT_DESCR_LEN, /* bLength */
288 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
289 (0x80u | MSC_CLASS_BULK_TX_EP), /* bEndpointAddress */
290 0x02u, /* bmAttributes */
291 0x00u, /* wMaxPacketSize LSB */ //22
292 0x02u, /* wMaxPacketSize MSB */ //23
293 0xFFu, /* bInterval *///ignored by host for Bulk IN EP
294 /*------------------------- OUT Endpoint Descriptor --------------------------*/
295 USB_STD_ENDPOINT_DESCR_LEN, /* bLength */
296 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
297 MSC_CLASS_BULK_RX_EP, /* bEndpointAddress */
298 0x02u, /* bmAttributes */
299 0x00u, /* wMaxPacketSize LSB *///29
300 0x02u, /* wMaxPacketSize MSB *///30
301 0xFFu /* bInterval */ /*Max NAK rate*/
302 };
303
304 void
MSS_USBD_MSC_init(mss_usbd_msc_media_t * media_ops,mss_usb_device_speed_t speed)305 MSS_USBD_MSC_init
306 (
307 mss_usbd_msc_media_t* media_ops,
308 mss_usb_device_speed_t speed
309 )
310 {
311 g_usbd_msc_media_ops = media_ops;
312 g_usbd_msc_user_speed = speed;
313
314 MSS_USBD_set_class_cb_handler(&usb_msd_class_cb);
315 }
316
317 mss_usbd_msc_state_t
MSS_USBD_MSC_get_state(void)318 MSS_USBD_MSC_get_state
319 (
320 void
321 )
322 {
323 return g_usbd_msc_state;
324 }
325
326 /***************************************************************************//**
327 returns the configuration descriptor requested by Host.
328 */
329 static uint8_t*
usbd_msc_get_descriptor_cb(uint8_t recepient,uint8_t type,uint32_t * length,mss_usb_device_speed_t musb_speed)330 usbd_msc_get_descriptor_cb
331 (
332 uint8_t recepient,
333 uint8_t type,
334 uint32_t* length,
335 mss_usb_device_speed_t musb_speed
336 )
337 {
338 uint8_t* conf_desc = 0;
339 uint8_t* os_conf_desc = 0;
340 uint8_t conf_desc_len = 0u;
341 uint8_t os_conf_desc_len = 0u;
342
343 /*User Selected FS:
344 Operate only in FS
345 User Selected HS:
346 Device connected to 2.0 Host(musb_speed = HS):Operate in HS
347 Device connected to 1.x Host(musb_speed = FS):Operate in FS
348 */
349 if(MSS_USB_DEVICE_FS == g_usbd_msc_user_speed)
350 {
351 conf_desc = msc_fs_conf_descr;
352 conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_CONFIGURATION_DESCRIPTOR_TYPE;
353 conf_desc_len = sizeof(msc_fs_conf_descr);
354 os_conf_desc = 0u;
355 os_conf_desc_len = 0u;
356 }
357 else if(MSS_USB_DEVICE_HS == g_usbd_msc_user_speed)
358 {
359 if(MSS_USB_DEVICE_HS == musb_speed)
360 {
361 conf_desc = msc_hs_conf_descr;
362 conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_CONFIGURATION_DESCRIPTOR_TYPE;
363 conf_desc_len = sizeof(msc_hs_conf_descr);
364 os_conf_desc = msc_fs_conf_descr;
365 os_conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE;
366 os_conf_desc_len = sizeof(msc_fs_conf_descr);
367 }
368 else if(MSS_USB_DEVICE_FS == musb_speed)
369 {
370 conf_desc = msc_fs_conf_descr;
371 conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_CONFIGURATION_DESCRIPTOR_TYPE;
372 conf_desc_len = sizeof(msc_fs_conf_descr);
373 os_conf_desc = msc_hs_conf_descr;
374 os_conf_desc[MSCD_CONF_DESCR_DESCTYPE_IDX] = USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE;
375 os_conf_desc_len = sizeof(msc_hs_conf_descr);
376 }
377 }
378 else
379 {
380 ASSERT(0); //user must select FS or HS, nothing else.
381 }
382
383 if(USB_STD_REQ_RECIPIENT_DEVICE == recepient)
384 {
385 if(USB_CONFIGURATION_DESCRIPTOR_TYPE == type)
386 {
387 *length = conf_desc_len;
388 return(conf_desc);
389 }
390 else if(USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE == type)
391 {
392 ASSERT(os_conf_desc != 0u);
393 *length = os_conf_desc_len;
394
395 return(os_conf_desc);
396 }
397 }
398 else if(USB_STD_REQ_RECIPIENT_ENDPOINT == recepient) /*Need index(EP Num) here*/
399 {
400 /*Do nothing*/
401 }
402 else if(USB_STD_REQ_RECIPIENT_INTERFACE == recepient) /*Need index(interface number) here*/
403 {
404 /*Do nothing*/
405 }
406 else
407 {
408 /*Do nothing*/
409 }
410
411 return USB_FAIL;
412 }
413
414 /***************************************************************************//**
415 usbd_msc_init_cb() call-back is called by USB Device mode driver on receiving
416 SET_CONFIGURATION command. The MSC class specific configurations are performed
417 by this function.
418 */
419 static uint8_t
usbd_msc_init_cb(uint8_t cfgidx,mss_usb_device_speed_t musb_speed)420 usbd_msc_init_cb
421 (
422 uint8_t cfgidx,
423 mss_usb_device_speed_t musb_speed
424 )
425 {
426 uint16_t bulk_rxep_fifo_sz = 0u;
427 uint16_t bulk_rxep_maxpktsz = 0u;
428
429 uint16_t bulk_txep_fifo_sz = 0u;
430 uint16_t bulk_txep_maxpktsz = 0u;
431
432 g_bottx_events = BOT_EVENT_IDLE;
433 g_botrx_events = BOT_EVENT_IDLE;
434 g_bot_state = BOT_IDLE;
435 g_current_command_csw.data_residue = 0u;
436 g_current_command_csw.tag = 0u;
437 g_current_command_csw.status = SCSI_COMMAND_FAIL;
438 G_BOT_CBW_INIT();
439 g_xfr_buf_ptr = 0;
440 g_xfr_buf_len = 0u;
441 g_xfr_lba_addr = 0u;
442
443 /*
444 User Selected FS: Operate only in FS
445 User Selected HS:
446 Device connected to 2.0 Host(musb_speed = HS):Operate in HS
447 Device connected to 1.x Host(musb_speed = FS):Operate in FS
448 */
449 /*
450 We calculate the Bulk endpoint sizes and max_pkt_size based on the
451 respective endpoint speed. This is done so that the config descriptor change
452 reflects here and this function need not be updated for that.
453 */
454 if(MSS_USB_DEVICE_FS == musb_speed)
455 {
456 bulk_txep_fifo_sz = (uint16_t)((msc_fs_conf_descr[23u] << 8u) | (msc_fs_conf_descr[22u]));
457 bulk_txep_maxpktsz = (uint16_t)((msc_fs_conf_descr[23u] << 8u) | (msc_fs_conf_descr[22u]));
458 bulk_rxep_fifo_sz = (uint16_t)((msc_fs_conf_descr[30u] << 8u) | (msc_fs_conf_descr[29u]));
459 bulk_rxep_maxpktsz = (uint16_t)((msc_fs_conf_descr[30u] << 8u) | (msc_fs_conf_descr[29u]));
460 }
461 else if(MSS_USB_DEVICE_HS == musb_speed)
462 {
463 bulk_txep_fifo_sz = (uint16_t)((msc_hs_conf_descr[23u] << 8u) | (msc_hs_conf_descr[22u]));
464 bulk_txep_maxpktsz = (uint16_t)((msc_hs_conf_descr[23u] << 8u) | (msc_hs_conf_descr[22u]));
465 bulk_rxep_fifo_sz = (uint16_t)((msc_hs_conf_descr[30u] << 8u) | (msc_hs_conf_descr[29u]));
466 bulk_rxep_maxpktsz = (uint16_t)((msc_hs_conf_descr[30u] << 8u) | (msc_hs_conf_descr[29u]));
467 }
468 else
469 {
470 ASSERT(0); /*speed value can not be any other than FS or HS*/
471 }
472
473 MSS_USBD_rx_ep_configure(MSC_CLASS_BULK_RX_EP,
474 0x100u,
475 bulk_rxep_fifo_sz,
476 bulk_rxep_maxpktsz,
477 1u,
478 DMA_ENABLE,
479 MSS_USB_DMA_CHANNEL1,
480 MSS_USB_XFR_BULK,
481 NO_ZLP_TO_XFR);
482
483 MSS_USBD_rx_ep_read_prepare(MSC_CLASS_BULK_RX_EP,
484 (uint8_t*)&g_bot_cbw,
485 USBD_MSC_BOT_CBW_LENGTH);
486
487 MSS_USBD_tx_ep_configure(MSC_CLASS_BULK_TX_EP,
488 0x300u,
489 bulk_txep_fifo_sz,
490 bulk_txep_maxpktsz,
491 1u,
492 DMA_ENABLE,
493 MSS_USB_DMA_CHANNEL2,
494 MSS_USB_XFR_BULK,
495 NO_ZLP_TO_XFR);
496
497 g_usbd_msc_state = USBD_MSC_CONFIGURED;
498
499 if(0 != g_usbd_msc_media_ops->media_init)
500 {
501 g_usbd_msc_media_ops->media_init(0);/*Todo:Remove the lun parameter*/
502 }
503
504 return USB_SUCCESS;
505 }
506
507 /***************************************************************************//**
508 usbd_msc_release_cb() call-back is called by USB Device mode driver on receiving
509 a command to clear the configuration.
510 */
511 static uint8_t
usbd_msc_release_cb(uint8_t cfgidx)512 usbd_msc_release_cb
513 (
514 uint8_t cfgidx
515 )
516 {
517 g_usbd_msc_state = USBD_MSC_NOT_CONFIGURED;
518 MSS_USB_CIF_tx_ep_disable_irq(MSC_CLASS_BULK_TX_EP);
519 MSS_USB_CIF_tx_ep_clr_csrreg(MSC_CLASS_BULK_TX_EP);
520 MSS_USB_CIF_dma_clr_ctrlreg(MSS_USB_DMA_CHANNEL2);
521
522 MSS_USB_CIF_rx_ep_disable_irq(MSC_CLASS_BULK_RX_EP);
523 MSS_USB_CIF_rx_ep_clr_csrreg(MSC_CLASS_BULK_RX_EP);
524 MSS_USB_CIF_dma_clr_ctrlreg(MSS_USB_DMA_CHANNEL1);
525
526 if(0 != g_usbd_msc_media_ops->media_release)
527 {
528 g_usbd_msc_media_ops->media_release(cfgidx);
529 }
530
531 return USB_SUCCESS;
532 }
533
534 /***************************************************************************//**
535 usbd_msc_process_request_cb() call-back function Process the MSC class requests.
536 */
537 static uint8_t
usbd_msc_process_request_cb(mss_usbd_setup_pkt_t * setup_pkt,uint8_t ** buf_pp,uint32_t * length)538 usbd_msc_process_request_cb
539 (
540 mss_usbd_setup_pkt_t* setup_pkt,
541 uint8_t** buf_pp,
542 uint32_t* length
543 )
544 {
545 if((MSC_CLASS_INTERFACE_NUM == setup_pkt->index) && (0u == setup_pkt->value))
546 {
547 switch(setup_pkt->request)
548 {
549 case USB_MSC_BOT_REQ_GET_MAX_LUN:
550 /*Return the max LUN index, not the actual number of LUNs*/
551 ASSERT(g_usbd_msc_media_ops->media_get_max_lun !=0u);
552
553 if(0 != g_usbd_msc_media_ops->media_get_max_lun)
554 {
555 get_max_lun_response[0] = (g_usbd_msc_media_ops->media_get_max_lun() - 1u);
556 }
557
558 *length = sizeof(get_max_lun_response);
559 *buf_pp = (uint8_t*)&get_max_lun_response;
560
561 return USB_SUCCESS;
562
563 case USB_MSC_BOT_REQ_BMS_RESET:
564 if(0u == setup_pkt->length)
565 {
566 /*
567 LVp:62 - prepare for next CBW. Don't change the stall
568 and Data toggle bit on Bulk EPs.
569 */
570 g_bottx_events = BOT_EVENT_IDLE;
571 g_botrx_events = BOT_EVENT_IDLE;
572 g_bot_state = BOT_IDLE;
573 g_current_command_csw.data_residue = 0u;
574 g_current_command_csw.tag = 0u;
575 g_current_command_csw.status = SCSI_COMMAND_FAIL;
576 G_BOT_CBW_INIT();
577 g_xfr_buf_ptr = (uint8_t*)0;
578 g_xfr_buf_len = 0u;
579 g_xfr_lba_addr = 0u;
580 MSS_USBD_rx_ep_read_prepare(MSC_CLASS_BULK_RX_EP,
581 (uint8_t*)&g_bot_cbw,
582 USBD_MSC_BOT_CBW_LENGTH);
583
584 return USB_SUCCESS;
585 }
586 else
587 {
588 return USB_FAIL;
589 }
590
591 default:
592 length = 0u;
593
594 return USB_FAIL;
595 }
596 }
597 else
598 {
599 return USB_FAIL;
600 }
601 }
602
603 /***************************************************************************//**
604 usbd_msc_tx_complete_cb() call-back function is called by USB Device mode driver
605 on completion of the Current Data Transmissions (IN Transaction) which was
606 previously initiated using MSS_USBD_tx_ep_configure().
607 */
usbd_msc_tx_complete_cb(mss_usb_ep_num_t num,uint8_t status)608 static uint8_t usbd_msc_tx_complete_cb
609 (
610 mss_usb_ep_num_t num,
611 uint8_t status
612 )
613 {
614 /*Underrun error ignore, it only means we are slow and that is because of
615 the slow serial flash memory*/
616 if(status & (TX_EP_STALL_ERROR))
617 {
618 g_bottx_events = BOT_EVENT_TX_ERROR;
619 }
620 else
621 {
622 g_bottx_events = BOT_EVENT_TX;
623 }
624
625 usbd_msc_bot_fsm(status, 0u);
626
627 return USB_SUCCESS;
628 }
629
630 /***************************************************************************//**
631 usbd_msc_rx_cb() call-back function is called by USB Device mode driver
632 on completion of data reception. USB Device mode driver must have been
633 previously prepared for this data reception using
634 MSS_USBD_rx_ep_read_prepare()
635 */
636 static uint8_t
usbd_msc_rx_cb(mss_usb_ep_num_t num,uint8_t status,uint32_t rx_count)637 usbd_msc_rx_cb
638 (
639 mss_usb_ep_num_t num,
640 uint8_t status,
641 uint32_t rx_count
642 )
643 {
644 /*
645 4.3.5.6
646 xfr length > Allocation length field ==> Terminate with CHECK CONDITION status,
647 sense key = ILLEGAL_REQUEST, additional sense code = INVALID FIELD in CDB
648 when NACA bit = 0 ==> ACA condition is not set = command abort should be done
649 as per sam-5, 5.8.2
650 */
651 if(status & (RX_EP_OVER_RUN_ERROR | RX_EP_STALL_ERROR |
652 RX_EP_DATA_ERROR | RX_EP_PID_ERROR | RX_EP_ISO_INCOMP_ERROR))
653 {
654 g_botrx_events = BOT_EVENT_RX_ERROR;
655 }
656 else
657 {
658 g_botrx_events = BOT_EVENT_RX;
659 }
660
661 usbd_msc_bot_fsm(status, rx_count);
662
663 return USB_SUCCESS;
664 }
665
666 /***************************************************************************//**
667 usbd_msc_bot_fsm() function is the state machine for BOT transfers.
668 */
669 static void
usbd_msc_bot_fsm(uint8_t status,uint32_t rx_count)670 usbd_msc_bot_fsm
671 (
672 uint8_t status,
673 uint32_t rx_count
674 )
675 {
676 uint8_t cb_result = CB_INTERNAL_ERROR;
677 switch (g_bot_state)
678 {
679 case BOT_IDLE:
680 if(BOT_EVENT_RX == g_botrx_events)
681 {
682 if(rx_count != USBD_MSC_BOT_CBW_LENGTH )
683 {
684 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
685 usbd_msc_abort_cbw(0u);
686 }
687 else
688 {
689 cb_result = usbd_msc_process_cbw(&g_bot_cbw);
690 g_current_command_csw.data_residue = g_bot_cbw.xfr_length;
691
692
693 switch(cb_result)
694 {
695 case CB_PASS:
696 g_current_command_csw.status = SCSI_COMMAND_PASS;
697 if(g_req_type == SCSI_OUT)
698 {
699 //CASE:12 (Success)
700 usbd_msc_receive_data(g_xfr_buf_ptr, g_xfr_buf_len);
701 }
702 else if(g_req_type == SCSI_IN)
703 {
704 //CASE:6 (Success)
705 usbd_msc_send_data(g_xfr_buf_ptr, g_xfr_buf_len);
706 }
707 else if(g_req_type == SCSI_ZDR)
708 {
709 //CASE:1 (Success)
710 usbd_msc_send_csw();
711 }
712 else
713 {
714 ASSERT(0); /*invalid req_type value*/
715 }
716 break;
717
718 case CB_LESSDATA:
719 g_current_command_csw.status = SCSI_COMMAND_LESSDATAPASS;
720
721 if(SCSI_OUT == g_req_type)
722 {
723 if(g_xfr_buf_len)
724 {
725 //CASE11(lvr:dont stall this)
726 usbd_msc_receive_data(g_xfr_buf_ptr, g_xfr_buf_len);
727 }
728 else
729 {
730 //CASE9-This needs to be cross-checked
731 usbd_msc_stallin_sendstatus();
732 }
733 }
734 else if(SCSI_IN == g_req_type)
735 {
736 if(g_xfr_buf_len)
737 {
738 //CASE5: send a stall and status after dataPhase.
739 usbd_msc_send_data(g_xfr_buf_ptr, g_xfr_buf_len);
740 }
741 else
742 {
743 //CASE4
744 usbd_msc_stallin_sendstatus();
745 }
746 }
747 else
748 {
749 ASSERT(0);/*invalid req_type value*/
750 }
751 break;
752
753 case CB_MOREDATA:
754 if(SCSI_OUT == g_req_type )
755 {
756 if(g_xfr_buf_len)
757 {
758 //CASE13
759 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
760 usbd_msc_stallout_sendstatus();
761 }
762 else
763 {
764 ASSERT(0); //shouldn't happen
765 }
766 }
767 else if(SCSI_IN == g_req_type)
768 {
769 //CASE7 stall then send status
770 g_current_command_csw.status = SCSI_COMMAND_FAIL;
771 usbd_msc_stallin_sendstatus();
772 }
773 else
774 {
775 ASSERT(0);
776 }
777 break;
778
779 case CB_INVALID_CDB_FIELD:
780 /*No data, only stall*/
781 g_current_command_csw.status = SCSI_COMMAND_FAIL;
782 usbd_msc_stallin_sendstatus();
783 break;
784
785 case CB_NOT_SUPPORTED:
786 /*Command Not supported.*/
787 g_current_command_csw.status = SCSI_COMMAND_FAIL;
788
789 if(0 == g_bot_cbw.xfr_length)
790 {
791 usbd_msc_stallin_sendstatus();
792 }
793 else
794 {
795 if(g_bot_cbw.flags & 0x80u) //IN D2H
796 {
797 usbd_msc_stallin_sendstatus();
798 }
799 else //OUT H2D
800 {
801 usbd_msc_stallout_sendstatus();
802 usbd_msc_stallin_sendstatus();
803 }
804 }
805 break;
806
807 case CB_INTERNAL_ERROR:
808 /*Dont respond till reset recovery*/
809 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
810 usbd_msc_abort_cbw(0u);
811 break;
812
813 case CB_LENGTH_MISMATCH:
814 if(SCSI_OUT == g_req_type)
815 {
816 if(0u == g_xfr_buf_len)
817 {
818 g_current_command_csw.status = SCSI_COMMAND_FAIL;
819 usbd_msc_stallout_sendstatus();
820 }
821 else if(g_xfr_buf_len > g_bot_cbw.xfr_length)
822 {
823 //CASE13
824 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
825 usbd_msc_stallout_sendstatus();
826 }
827 else
828 {
829 //CASE11(lvr:dont stall this)
830 g_current_command_csw.status = SCSI_COMMAND_FAIL;
831 usbd_msc_receive_data(g_xfr_buf_ptr, g_xfr_buf_len);
832 }
833 }
834 else if(SCSI_IN == g_req_type)
835 {
836 if(0u == g_xfr_buf_len)
837 {
838 g_current_command_csw.status = SCSI_COMMAND_FAIL;
839 usbd_msc_stallout_sendstatus();
840 }
841 else if(g_xfr_buf_len > g_bot_cbw.xfr_length)
842 {
843 //CASE7 stall then send status
844 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
845 usbd_msc_stallin_sendstatus();
846 }
847 else
848 {
849 g_current_command_csw.status = SCSI_COMMAND_FAIL;
850 usbd_msc_send_data(g_xfr_buf_ptr, g_xfr_buf_len);
851 }
852 }
853 else
854 {
855 g_current_command_csw.status = SCSI_COMMAND_FAIL;
856
857 if(g_bot_cbw.flags & 0x80u)
858 {
859 usbd_msc_stallin_sendstatus();
860 }
861 else
862 {
863 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
864 usbd_msc_abort_cbw(0u);
865 }
866 }
867 break;
868
869 case CB_DATA_DIR_MISMATCH:
870 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
871 usbd_msc_stallin_sendstatus();
872 break;
873
874 case CB_INVALID_CBW:
875 /*Don't respond till reset recovery*/
876 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
877 usbd_msc_abort_cbw(0u);
878 break;
879
880 default:
881 /*Don't respond till reset recovery*/
882 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
883 usbd_msc_abort_cbw(0u); //Internal Error
884 break;
885 }
886 }
887 }
888 else
889 {
890 ASSERT(0);
891 }
892
893 break;
894 case BOT_DATA_TX:
895 if(BOT_EVENT_TX == g_bottx_events) /* Data TX from Device*/
896 {
897 if(SCSI_COMMAND_LESSDATAPASS == g_current_command_csw.status)
898 {
899 g_xfr_buf_ptr = (uint8_t*)0;
900 g_xfr_buf_len = 0u;
901 g_xfr_lba_addr = 0u;
902 g_current_command_csw.status = SCSI_COMMAND_PASS;
903 usbd_msc_stallin_sendstatus();
904 }
905 else if(SCSI_COMMAND_PASS == g_current_command_csw.status)
906 {
907 if(g_current_command_csw.data_residue >= g_xfr_buf_len)
908 {
909 g_current_command_csw.data_residue -= g_xfr_buf_len;
910 }
911 else
912 {
913 ASSERT(0);/*corrupt/invalid data_residue value*/
914 }
915
916 if(0u == g_current_command_csw.data_residue)
917 {
918 g_xfr_buf_ptr = (uint8_t*)0;
919 g_xfr_buf_len = 0u;
920 g_xfr_lba_addr = 0u;
921 g_current_command_csw.status = SCSI_COMMAND_PASS;
922 usbd_msc_send_csw();
923 }
924 else
925 {
926 /*
927 Control reaches here because previous App read operation
928 returned less Data than requested by host.Read rest
929 of the data now.
930 */
931 uint32_t actual_read_len;
932 uint8_t* buf;
933
934 if(0 != g_usbd_msc_media_ops->media_read)
935 {
936 g_xfr_lba_addr += g_xfr_buf_len;
937 actual_read_len = g_usbd_msc_media_ops->media_read(g_bot_cbw.lun,
938 &buf,
939 g_xfr_lba_addr,
940 g_current_command_csw.data_residue);
941 if (actual_read_len > g_current_command_csw.data_residue)
942 {
943 ASSERT(0);/*App should not read more data than asked for*/
944 }
945 else
946 {
947 g_xfr_buf_ptr = buf;
948 g_xfr_buf_len = actual_read_len;
949 g_current_command_csw.status = SCSI_COMMAND_PASS;
950 usbd_msc_send_data(buf, g_xfr_buf_len);
951 }
952 }
953 else
954 {
955 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
956 usbd_msc_abort_cbw(0u); //Internal Error
957 }
958 }
959 }
960 else if(SCSI_COMMAND_FAIL == g_current_command_csw.status)
961 {
962 g_xfr_buf_ptr = (uint8_t*)0;
963 g_xfr_buf_len = 0u;
964 g_xfr_lba_addr = 0u;
965 usbd_msc_stallin_sendstatus();
966 }
967 else
968 {
969 ASSERT(0); //should never come there with Phase Error status
970 }
971 }
972 else if(BOT_EVENT_TX_ERROR == g_bottx_events)
973 {
974 /* Stall Error*/
975 if(status & TX_EP_STALL_ERROR)
976 {
977 ASSERT(0); //should never get a stall in this state
978 }
979 }
980 else
981 {
982 ASSERT(0);/*corrupt g_bottx_events value*/
983 }
984 break;
985
986 case BOT_DATA_RX:
987 if(BOT_EVENT_RX == g_botrx_events)
988 {
989 if(SCSI_COMMAND_LESSDATAPASS == g_current_command_csw.status)
990 {
991 g_xfr_buf_ptr = (uint8_t*)0;
992 g_xfr_buf_len = 0u;
993 g_xfr_lba_addr = 0u;
994 g_current_command_csw.status = SCSI_COMMAND_PASS;
995 usbd_msc_stallin_sendstatus();
996 }
997 else if(SCSI_COMMAND_PASS == g_current_command_csw.status)
998 {
999 uint8_t result = CB_DATAPHASE_ERROR;
1000
1001 if(g_current_command_csw.data_residue >= g_xfr_buf_len)
1002 {
1003 g_current_command_csw.data_residue -= g_xfr_buf_len;
1004 }
1005 else
1006 {
1007 ASSERT(0);/*corrupt/invalid data_residue value*/
1008 }
1009
1010 /*Write the received data on flash*/
1011 if(rx_count == g_xfr_buf_len)
1012 {
1013 result = CB_PASS;
1014 }
1015 else
1016 {
1017 result = CB_DATAPHASE_ERROR;
1018 }
1019
1020 if(0 != g_usbd_msc_media_ops->media_write_ready)
1021 {
1022 g_usbd_msc_media_ops->media_write_ready(g_bot_cbw.lun,
1023 g_xfr_lba_addr,
1024 g_xfr_buf_len);
1025 result = CB_PASS;
1026 }
1027 else
1028 {
1029 result = CB_DATAPHASE_ERROR;
1030 }
1031
1032 if(CB_PASS == result)
1033 {
1034 /*
1035 data_residue == 0 means we are done with current Data
1036 phase of OUT transaction, send the status.
1037 */
1038 if(0u == g_current_command_csw.data_residue)
1039 {
1040 g_xfr_buf_ptr = 0; // Data end.
1041 g_xfr_buf_len = 0u;
1042 g_xfr_lba_addr = 0u;
1043 g_current_command_csw.status = SCSI_COMMAND_PASS;
1044 usbd_msc_send_csw();
1045 }
1046 else
1047 {
1048 uint32_t app_write_len;
1049 uint8_t* write_buf = (uint8_t*) 0;
1050
1051 /*
1052 Data phase of current OUT transaction is still in
1053 progress.
1054 Prepare to write more data on flash
1055 */
1056 g_xfr_lba_addr += g_xfr_buf_len;
1057
1058 if(0 != g_usbd_msc_media_ops->media_acquire_write_buf)
1059 write_buf = g_usbd_msc_media_ops->media_acquire_write_buf(g_bot_cbw.lun,
1060 g_xfr_lba_addr,
1061 &app_write_len);
1062
1063 /*
1064 If application buffer is not big enough to handle all
1065 requested data from Host,then read amount of data
1066 that the application can handle at the moment.
1067 */
1068 if(app_write_len < g_current_command_csw.data_residue)
1069 {
1070 g_xfr_buf_len = app_write_len;
1071 }
1072 else
1073 {
1074 g_xfr_buf_len = g_current_command_csw.data_residue;
1075 }
1076
1077 g_xfr_buf_ptr = write_buf;
1078 g_current_command_csw.status = SCSI_COMMAND_PASS;
1079 usbd_msc_receive_data(g_xfr_buf_ptr, g_xfr_buf_len);
1080 }
1081 }
1082 else
1083 {
1084 g_current_command_csw.status = SCSI_COMMAND_PHASE_ERR;
1085 usbd_msc_abort_cbw(0u); //Internal Error
1086 }
1087 }
1088 else if(SCSI_COMMAND_FAIL == g_current_command_csw.status)
1089 {
1090 g_xfr_buf_ptr = 0;
1091 g_xfr_buf_len = 0u;
1092 g_xfr_lba_addr = 0u;
1093 usbd_msc_send_csw();
1094 }
1095 }
1096 else if(BOT_EVENT_RX_ERROR == g_botrx_events)
1097 {
1098 /* Stall Error*/
1099 if(status & 0x02u)
1100 {
1101 ASSERT(0); //should never get a stall in this state
1102 }
1103 }
1104 else
1105 {
1106 ASSERT(0); //invalid g_botrx_events
1107 }
1108 break;
1109
1110 case BOT_SEND_STATUS:
1111
1112 if(BOT_EVENT_TX == g_bottx_events)
1113 {
1114 G_BOT_CBW_INIT();
1115 g_current_command_csw.data_residue = 0u;
1116 g_current_command_csw.tag = 0u;
1117 g_current_command_csw.status = SCSI_COMMAND_FAIL;
1118 g_xfr_buf_ptr = (uint8_t*)0;
1119 g_xfr_buf_len = 0u;
1120 g_xfr_lba_addr = 0u;
1121
1122 g_bot_state = BOT_IDLE;
1123 /*Prepare to receive next command*/
1124 MSS_USBD_rx_ep_read_prepare(MSC_CLASS_BULK_RX_EP,
1125 (uint8_t*)&g_bot_cbw,
1126 USBD_MSC_BOT_CBW_LENGTH);
1127 }
1128 else if(BOT_EVENT_TX_ERROR == g_bottx_events)
1129 {
1130 /* Stall Error*/
1131 if(status & TX_EP_STALL_ERROR)
1132 {
1133 if(g_current_command_csw.status == SCSI_COMMAND_LESSDATAPASS)
1134 {
1135 g_current_command_csw.status = SCSI_COMMAND_PASS;
1136 }
1137 usbd_msc_send_csw();
1138 }
1139 }
1140 break;
1141
1142 case BOT_ABORTED:
1143 {
1144 g_bot_state = BOT_ABORTED;
1145 usbd_msc_abort_cbw(0u);
1146 }
1147 break;
1148
1149 default:
1150 {
1151 ASSERT(0); //invalid BOT state
1152 }
1153 break;
1154 }
1155
1156 g_bottx_events = BOT_EVENT_IDLE;
1157 g_botrx_events = BOT_EVENT_IDLE;
1158 }
1159
1160 /***************************************************************************//**
1161 usbd_msc_process_cbw() function decodes current command sent by host in CBW,
1162 and Processes the command. If the command was valid and meaningful, it asks for
1163 required information from application and returns the status. If the Command
1164 was invalid or is not processed by this driver, it returns the Failure status.
1165 */
1166
1167
1168 static uint8_t
usbd_msc_process_cbw(mss_usb_msc_cbw_t * cbw)1169 usbd_msc_process_cbw
1170 (
1171 mss_usb_msc_cbw_t * cbw
1172 )
1173 {
1174 uint8_t cbw_command = cbw->cmd_block[0];
1175 uint8_t result = CB_PASS;
1176 g_current_command_csw.tag = cbw->tag;
1177
1178 /*
1179 Check for valid cbw
1180 1) CBW received after csw or reset
1181 2) cbw is 32 bytes
1182 3) Signature is correct
1183
1184 CBW is meaningful if all reserved bytes are zero
1185 Lun value is supported
1186 CBWCBLength and cbwcb are valid for the interface subclass.
1187 No. Max LUN index provided by App in get_max_lun request.
1188 */
1189
1190 if((cbw->signature != USB_MSC_BOT_CBW_SIGNATURE) ||
1191 (cbw->lun > get_max_lun_response[0]) ||
1192 (cbw->cmd_length < 1) ||
1193 (cbw->cmd_length > 16))
1194 {
1195 result = CB_INVALID_CBW;
1196 }
1197 else
1198 {
1199 if(g_current_command_csw.data_residue != 0u)
1200 {
1201 ASSERT(0);
1202 }
1203
1204
1205 switch(cbw_command)
1206 {
1207 case USB_MSC_SCSI_INQUIRY:
1208 result = usbd_msc_process_inquiry();
1209 break;
1210
1211 case USB_MSC_SCSI_READ_CAPACITY_10:/*returns last LBA and block size*/
1212 result = usbd_msc_process_read_capacity_10();
1213 break;
1214
1215 case USB_MSC_SCSI_READ_FORMAT_CAPACITIES:/*Returns no. of blocks and block size*/
1216 {
1217 uint32_t no_of_blocks, block_size;
1218 uint32_t dev_data_len = 0;
1219
1220 dev_data_len = ((g_bot_cbw.cmd_block[7u] << 8u) | g_bot_cbw.cmd_block[8u]);
1221
1222 if(0 != g_usbd_msc_media_ops->media_get_capacity)
1223 {
1224 g_usbd_msc_media_ops->media_get_capacity(cbw->lun,
1225 (uint32_t*)&no_of_blocks,
1226 (uint32_t*)&block_size);
1227 }
1228
1229 format_capacity_list [4u] = (uint8_t)(no_of_blocks >> 24u);
1230 format_capacity_list [5u] = (uint8_t)(no_of_blocks >> 16u);
1231 format_capacity_list [6u] = (uint8_t)(no_of_blocks >> 8u);
1232 format_capacity_list [7u] = (uint8_t)(no_of_blocks);
1233
1234 /* format_capacity_list [8] = Descriptor Code*/
1235 format_capacity_list [9u] = (uint8_t)(block_size >> 16u);
1236 format_capacity_list [10u] = (uint8_t)(block_size >> 8u);
1237 format_capacity_list [11u] = (uint8_t)(block_size);
1238
1239 g_req_type = SCSI_IN;
1240 g_xfr_buf_ptr = (uint8_t*)format_capacity_list;
1241 g_xfr_buf_len = sizeof(format_capacity_list);
1242
1243 usbd_msc_prepare_sense_data(cbw->lun,
1244 SC_ILLEGAL_REQUEST,
1245 ASC_INVALID_CDB);
1246
1247 if(g_xfr_buf_len < dev_data_len)
1248 {
1249 result = CB_LESSDATA;
1250 }
1251 else if(g_xfr_buf_len > dev_data_len)
1252 {
1253 result = CB_LESSDATA;
1254 }
1255 else
1256 {
1257 result = CB_PASS;
1258 }
1259 }
1260 break;
1261
1262 case USB_MSC_SCSI_READ_10:
1263 result = usbd_msc_process_read_10();
1264 break;
1265
1266 case USB_MSC_SCSI_MODE_SENSE_6:
1267 {
1268 uint32_t dev_data_len =0;
1269 dev_data_len = g_bot_cbw.cmd_block[4u];
1270
1271 g_req_type = SCSI_IN;
1272 g_xfr_buf_ptr = mode_sense_response;
1273 g_xfr_buf_len = sizeof(mode_sense_response);
1274
1275 if(dev_data_len > g_xfr_buf_len)
1276 {
1277 result = CB_LESSDATA;
1278 }
1279 else if(dev_data_len < g_xfr_buf_len)
1280 {
1281 result = CB_MOREDATA;
1282 }
1283 else
1284 {
1285 result = CB_PASS;
1286 }
1287 }
1288 break;
1289
1290 case USB_MSC_SCSI_REQUEST_SENSE:
1291 {
1292 uint32_t dev_data_len =0;
1293 dev_data_len = g_bot_cbw.cmd_block[4u];
1294
1295 if(g_bot_cbw.cmd_block[1u] & 0x01u)//DESC bit 0 - only fixed format is supported
1296 {
1297 return(CB_INVALID_CDB_FIELD);
1298 }
1299
1300 /*SPC-4, table 39*/
1301 g_req_type = SCSI_IN;
1302 g_xfr_buf_ptr = (uint8_t*)&g_sense_response;
1303
1304 if(0 == dev_data_len)
1305 {
1306 result = CB_LESSDATA;
1307 g_xfr_buf_len = dev_data_len;
1308 }
1309 else if(dev_data_len > (sizeof(g_sense_response)))
1310 {
1311 g_xfr_buf_len = dev_data_len;
1312 result = CB_MOREDATA;
1313 }
1314 else
1315 {
1316 g_xfr_buf_len = dev_data_len;
1317 result = CB_PASS;
1318 }
1319 }
1320 break;
1321
1322 case USB_MSC_SCSI_WRITE_10:
1323 result = usbd_msc_process_write_10();
1324 break;
1325
1326 case USB_MSC_SCSI_TEST_UNIT_READY:
1327 g_req_type = SCSI_ZDR;
1328 g_xfr_buf_ptr = (uint8_t*)0;
1329 g_xfr_buf_len = 0u;
1330
1331 /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1332 if(0 != g_bot_cbw.xfr_length)
1333 {
1334 result = CB_LENGTH_MISMATCH;
1335 }
1336 else
1337 {
1338 result = CB_PASS;
1339 }
1340
1341 break;
1342 case USB_MSC_SCSI_VERIFY_10:
1343 g_req_type = SCSI_ZDR;
1344 g_xfr_buf_ptr = (uint8_t*)0;
1345 g_xfr_buf_len = 0u;
1346
1347 /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1348 if(0 != g_bot_cbw.xfr_length)
1349 {
1350 result = CB_LENGTH_MISMATCH;
1351 }
1352 else
1353 {
1354 result = CB_PASS;
1355 }
1356
1357 break;
1358
1359 default:
1360 result = CB_NOT_SUPPORTED;
1361 g_req_type = SCSI_IN;
1362 g_xfr_buf_ptr = (uint8_t*)0;
1363 g_xfr_buf_len = 0u;
1364 usbd_msc_prepare_sense_data(cbw->lun,
1365 SC_ILLEGAL_REQUEST,
1366 ASC_INVALID_FIELED_IN_COMMAND);
1367 break;
1368 }
1369 }
1370 return result;
1371 }
1372
1373 /***************************************************************************//**
1374 usbd_msc_prepare_sense_data() function prepares sense information required
1375 by the host in case there was an error in processing CBW. This information is
1376 sent as response to REQUEST_SENSE command.
1377 */
1378 static void
usbd_msc_prepare_sense_data(uint8_t lun,uint8_t skey,uint8_t asc)1379 usbd_msc_prepare_sense_data
1380 (
1381 uint8_t lun,
1382 uint8_t skey,
1383 uint8_t asc
1384 )
1385 {
1386 g_sense_response.sense_key = skey;
1387 g_sense_response.asc = asc;
1388 }
1389
1390 /***************************************************************************//**
1391 usbd_msc_abort_cbw() function aborts the current command CBW.and prepares
1392 the driver to receive new CBW from HOST.
1393 */
1394 static void
usbd_msc_abort_cbw(uint8_t lun)1395 usbd_msc_abort_cbw
1396 (
1397 uint8_t lun
1398 )
1399 {
1400 g_bot_state = BOT_ABORTED;
1401
1402 /*
1403 Don't respond to anything from host on Bulk IN or OUT Endpoint.
1404 Reset Recovery request is mandatory now.
1405 */
1406
1407 MSS_USBD_tx_ep_stall(MSC_CLASS_BULK_TX_EP);
1408 MSS_USBD_rx_ep_stall(MSC_CLASS_BULK_RX_EP);
1409 }
1410
1411 /***************************************************************************//**
1412 usbd_msc_send_data() function send data to the host (DATA phase of IN transactions)
1413 in response to current CBW command.
1414 */
1415 static void
usbd_msc_send_data(uint8_t * buf,uint32_t len)1416 usbd_msc_send_data
1417 (
1418 uint8_t* buf,
1419 uint32_t len
1420 )
1421 {
1422 /*TODO: check if the length can be accommodated in EP buffer*/
1423 g_bot_state = BOT_DATA_TX;
1424 MSS_USBD_tx_ep_write(MSC_CLASS_BULK_TX_EP, buf, len);
1425 }
1426
1427 static void
usbd_msc_stallin_sendstatus(void)1428 usbd_msc_stallin_sendstatus
1429 (
1430 void
1431 )
1432 {
1433 g_bot_state = BOT_SEND_STATUS;
1434 MSS_USBD_tx_ep_stall(MSC_CLASS_BULK_TX_EP);
1435 }
1436
1437 static void
usbd_msc_stallout_sendstatus(void)1438 usbd_msc_stallout_sendstatus
1439 (
1440 void
1441 )
1442 {
1443 g_bot_state = BOT_SEND_STATUS;
1444 MSS_USBD_rx_ep_stall(MSC_CLASS_BULK_RX_EP);
1445 }
1446
1447 /***************************************************************************//**
1448 usbd_msc_receive_data() function prepares the driver to receive data
1449 from USB host (DATA phase of OUT transactions) in response to the current CBW
1450 command.
1451 */
1452 static void
usbd_msc_receive_data(uint8_t * buf,uint32_t len)1453 usbd_msc_receive_data
1454 (
1455 uint8_t* buf,
1456 uint32_t len
1457 )
1458 {
1459 g_bot_state = BOT_DATA_RX;
1460 MSS_USBD_rx_ep_read_prepare(MSC_CLASS_BULK_RX_EP, g_xfr_buf_ptr, len);
1461 }
1462
1463 /***************************************************************************//**
1464 usbd_msc_send_csw() function sends status information to USB host
1465 (DATA phase of IN transactions), indicating the Success/Failure status of the
1466 current CBW command.
1467 */
1468 static void
usbd_msc_send_csw(void)1469 usbd_msc_send_csw
1470 (
1471 void
1472 )
1473 {
1474 g_bot_state = BOT_SEND_STATUS;
1475 MSS_USBD_tx_ep_write(MSC_CLASS_BULK_TX_EP,
1476 (uint8_t*)&g_current_command_csw,
1477 USBD_MSC_BOT_CSW_LENGTH);
1478 }
1479
1480 /***************************************************************************//**
1481 usbd_msc_process_read_10() function processes read command and calls application
1482 call-back function to read data from media.
1483 */
1484 static uint8_t
usbd_msc_process_read_10(void)1485 usbd_msc_process_read_10
1486 (
1487 void
1488 )
1489 {
1490 uint32_t app_read_len = 0u;
1491 uint32_t lba = 0u;
1492 uint32_t lba_addr = 0u;
1493 uint8_t* buf = 0;
1494 uint32_t dev_data_len = 0u;
1495 uint8_t cb_res = CB_PASS;
1496
1497 g_req_type = SCSI_IN;
1498 /*Lba address is in command block byte 2 to 4 with MSB first.*/
1499 lba = (g_bot_cbw.cmd_block[2u] << 24u) |
1500 (g_bot_cbw.cmd_block[3u] << 16u) |
1501 (g_bot_cbw.cmd_block[4u] << 8u) |
1502 g_bot_cbw.cmd_block[5u];
1503
1504 /*Block size was received in USB_MSC_SCSI_READ_CAPACITY_10 command*/
1505 lba_addr = (lba * lun_capacity[g_bot_cbw.lun].blk_sz_len);
1506
1507 /*
1508 Number of LBAs to be read is provided in command block byte 7 to 8,
1509 calculate the total size to be read
1510 */
1511 dev_data_len = ((g_bot_cbw.cmd_block[7u] << 8u) | g_bot_cbw.cmd_block[8u]) *
1512 lun_capacity[g_bot_cbw.lun].blk_sz_len;
1513
1514 /*Data Direction must be D2H (IN)*/
1515 if(!(g_bot_cbw.flags & 0x80u))
1516 {
1517 g_xfr_buf_len = dev_data_len;
1518 cb_res = CB_DATA_DIR_MISMATCH;
1519 }
1520 /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1521 if(dev_data_len != g_bot_cbw.xfr_length)
1522 {
1523 cb_res = CB_LENGTH_MISMATCH;
1524 }
1525
1526 if(0 == g_usbd_msc_media_ops->media_read)
1527 {
1528 cb_res = CB_INTERNAL_ERROR;
1529 }
1530
1531 if(CB_PASS == cb_res)
1532 {
1533 if(0 != g_usbd_msc_media_ops->media_read)
1534 {
1535 app_read_len = g_usbd_msc_media_ops->media_read(g_bot_cbw.lun,
1536 &buf,
1537 lba_addr,
1538 dev_data_len);
1539 }
1540
1541 if((uint8_t*)0 == buf)
1542 {
1543 cb_res = CB_INTERNAL_ERROR;
1544 }
1545 else
1546 {
1547 cb_res = CB_PASS;
1548 g_xfr_buf_ptr = buf;
1549
1550 if(app_read_len < dev_data_len)
1551 {
1552 g_xfr_buf_len = app_read_len;
1553 }
1554 else
1555 {
1556 g_xfr_buf_len = dev_data_len;
1557 }
1558 /*
1559 Store the current LBA address so that it will be used to calculate
1560 new LBA address when remaining data is read from flash.
1561 */
1562 g_xfr_lba_addr = lba_addr;
1563 }
1564 }
1565
1566 if(CB_PASS != cb_res)
1567 {
1568 g_xfr_buf_ptr = (uint8_t*)0;
1569 g_xfr_buf_len = 0u;
1570 g_xfr_lba_addr = 0u;
1571 }
1572
1573 return (cb_res);
1574 }
1575
1576 /***************************************************************************//**
1577 usbd_msc_process_write_10() function processes Write command and calls application
1578 call-back function to acquire a buffer where the data will be receive.
1579 */
1580 static uint8_t
usbd_msc_process_write_10(void)1581 usbd_msc_process_write_10
1582 (
1583 void
1584 )
1585 {
1586 uint32_t lba = 0u;
1587 uint32_t lba_addr = 0u;
1588 uint8_t* write_buf;
1589 uint32_t app_write_len = 0u;
1590 uint32_t dev_data_len = 0u;
1591 uint8_t cb_res = CB_PASS;
1592
1593 g_req_type = SCSI_OUT;
1594 g_xfr_buf_ptr = (uint8_t*)0;
1595 g_xfr_buf_len = 0u;
1596 g_xfr_lba_addr = 0u;
1597
1598 /*Lba address is in command block byte 2 to 4 with MSB first.*/
1599 lba = (g_bot_cbw.cmd_block[2u] << 24u) |
1600 (g_bot_cbw.cmd_block[3u] << 16u) |
1601 (g_bot_cbw.cmd_block[4u] << 8u) |
1602 g_bot_cbw.cmd_block[5u];
1603
1604 /*Block size was received in USB_MSC_SCSI_READ_CAPACITY_10 command*/
1605 lba_addr = (lba * lun_capacity[g_bot_cbw.lun].blk_sz_len);
1606
1607 /*
1608 Number of LBA to be written is provided in command block byte 7 to 8,
1609 calculate the total size to be written
1610 */
1611 dev_data_len = ((g_bot_cbw.cmd_block[7] << 8u) | g_bot_cbw.cmd_block[8u]) *
1612 lun_capacity[g_bot_cbw.lun].blk_sz_len;
1613
1614 /*Data Direction must be H2D (OUT)*/
1615 if(g_bot_cbw.flags & 0x80u)
1616 {
1617 g_xfr_buf_len = dev_data_len;
1618 cb_res = CB_DATA_DIR_MISMATCH;
1619 }
1620 /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1621 if(dev_data_len != g_bot_cbw.xfr_length)
1622 {
1623 cb_res = CB_LENGTH_MISMATCH;
1624 }
1625
1626 if(0 == g_usbd_msc_media_ops->media_acquire_write_buf)
1627 {
1628 cb_res = CB_INTERNAL_ERROR;
1629 }
1630
1631 if(CB_PASS == cb_res)
1632 {
1633 write_buf = g_usbd_msc_media_ops->media_acquire_write_buf(g_bot_cbw.lun,
1634 lba_addr,
1635 &app_write_len);
1636 if(write_buf == (uint8_t*)0)
1637 {
1638 cb_res = CB_INTERNAL_ERROR;
1639 }
1640 else
1641 {
1642 cb_res = CB_PASS;
1643 /*
1644 Since App is not capable of handling all data at the moment.
1645 Store the current LBA address so that it will be used to calculate
1646 new LBA address when remaining data is received.
1647 */
1648 g_xfr_lba_addr = lba_addr;
1649 g_xfr_buf_ptr = write_buf;
1650 /*
1651 If application buffer is not big enough to handle all requested data
1652 from Host, then read the amount of data that the application can
1653 handle at the moment
1654 */
1655 if(app_write_len < dev_data_len)
1656 {
1657 g_xfr_buf_len = app_write_len;
1658 }
1659 else
1660 {
1661 g_xfr_buf_len = dev_data_len;
1662 }
1663 }
1664 }
1665
1666 if(CB_PASS != cb_res)
1667 {
1668 g_xfr_buf_ptr = (uint8_t*)0;
1669 g_xfr_buf_len = 0u;
1670 g_xfr_lba_addr = 0u;
1671 }
1672
1673 return (cb_res);
1674 }
1675
usbd_msc_process_inquiry(void)1676 static uint8_t usbd_msc_process_inquiry(void)
1677 {
1678 uint32_t dev_data_len = 0u;
1679 uint8_t* buf = (uint8_t*)0;
1680 uint32_t app_data_len;
1681
1682 g_req_type = SCSI_IN;
1683 g_xfr_buf_ptr = (uint8_t*)0;
1684 g_xfr_buf_len = 0u;
1685
1686 dev_data_len = ((g_bot_cbw.cmd_block[3u] << 8u) | g_bot_cbw.cmd_block[4u]);
1687
1688 /*Data Direction must be D2H (IN)*/
1689 if(!(g_bot_cbw.flags & 0x80u))
1690 {
1691 g_xfr_buf_len = dev_data_len;
1692 return(CB_DATA_DIR_MISMATCH);
1693 }
1694
1695 /*Fail if DataTransferLength and Allocation length in CBW are mismatched*/
1696 if(dev_data_len != g_bot_cbw.xfr_length)
1697 {
1698 return(CB_LENGTH_MISMATCH);
1699 }
1700
1701 /*If EVPD is zero then Page code must be zero*/
1702 if((!(g_bot_cbw.cmd_block[1u] & 0x01u)) && (g_bot_cbw.cmd_block[1u]))
1703 {
1704 return(CB_INVALID_CDB_FIELD);
1705 }
1706
1707 if(0 == g_usbd_msc_media_ops->media_inquiry)
1708 {
1709 return(CB_INTERNAL_ERROR);
1710 }
1711
1712 if(0 != g_usbd_msc_media_ops->media_inquiry)
1713 {
1714 buf = g_usbd_msc_media_ops->media_inquiry(g_bot_cbw.lun, &app_data_len);
1715 }
1716
1717 if((uint8_t*)0 == buf)
1718 {
1719 return(CB_INTERNAL_ERROR);
1720 }
1721 else
1722 {
1723 g_xfr_buf_ptr = buf;
1724
1725 if(dev_data_len <= app_data_len)
1726 {
1727 g_xfr_buf_len = dev_data_len;
1728 return(CB_PASS);
1729 }
1730 else
1731 {
1732 g_xfr_buf_len = app_data_len;
1733 return(CB_LESSDATA);
1734 }
1735 }
1736 }
1737
usbd_msc_process_read_capacity_10(void)1738 static uint8_t usbd_msc_process_read_capacity_10(void)
1739 {
1740 uint32_t no_of_blocks, block_size;
1741
1742 /*
1743 Returns last block address and block size
1744 Last_blk_lba = no_of_blocks-1
1745 */
1746 g_xfr_buf_ptr = (uint8_t*)0;
1747 g_xfr_buf_len = 0u;
1748 g_req_type = SCSI_IN;
1749
1750 /*Data Direction must be D2H (IN)*/
1751 if(!(g_bot_cbw.flags & 0x80u))
1752 {
1753 g_xfr_buf_len = 8u;
1754 return(CB_DATA_DIR_MISMATCH);
1755 }
1756
1757 /*PMI bit set to one is not supported*/
1758 if(g_bot_cbw.cmd_block[8u] & 0x01u)
1759 {
1760 return(CB_INVALID_CDB_FIELD);
1761 }
1762
1763 if(0 == g_usbd_msc_media_ops->media_get_capacity)
1764 {
1765 return(CB_INTERNAL_ERROR);
1766 }
1767
1768 if(0 != g_usbd_msc_media_ops->media_get_capacity)
1769 {
1770 g_usbd_msc_media_ops->media_get_capacity(g_bot_cbw.lun,
1771 (uint32_t*)&no_of_blocks,
1772 (uint32_t*)&block_size);
1773 }
1774
1775 lun_capacity[g_bot_cbw.lun].last_lba_msb = (uint8_t)((no_of_blocks - 1u) >> 24u);
1776 lun_capacity[g_bot_cbw.lun].last_lba_2 = (uint8_t)((no_of_blocks - 1u) >> 16u);
1777 lun_capacity[g_bot_cbw.lun].last_lba_1 = (uint8_t)((no_of_blocks - 1u) >> 8u);
1778 lun_capacity[g_bot_cbw.lun].last_lba_lsb = (uint8_t)((no_of_blocks - 1u));
1779
1780 lun_capacity[g_bot_cbw.lun].blk_sz_len = block_size;
1781 lun_capacity[g_bot_cbw.lun].block_size_msb = (uint8_t)(block_size >> 24u);
1782 lun_capacity[g_bot_cbw.lun].block_size_2 = (uint8_t)(block_size >> 16u);
1783 lun_capacity[g_bot_cbw.lun].block_size_1 = (uint8_t)(block_size >> 8u);
1784 lun_capacity[g_bot_cbw.lun].block_size_lsb = (uint8_t)(block_size);
1785
1786 g_xfr_buf_ptr = (uint8_t*)&lun_capacity[g_bot_cbw.lun];
1787 g_xfr_buf_len = 8u;
1788
1789 return(CB_PASS);
1790 }
1791
1792 #endif //MSS_USB_DEVICE_ENABLED
1793
1794 #ifdef __cplusplus
1795 }
1796 #endif
1797