usbd_msc_scsi.c
Go to the documentation of this file.
1 
28 /* Includes ------------------------------------------------------------------*/
29 #include "usbd_msc_bot.h"
30 #include "usbd_msc_scsi.h"
31 #include "usbd_msc_mem.h"
32 #include "usbd_msc_data.h"
33 
34 #define UNUSED(x) (void)(x)
35 
36 
37 
80 
81 uint32_t SCSI_blk_size;
82 uint32_t SCSI_blk_nbr;
83 
84 uint32_t SCSI_blk_addr;
85 uint32_t SCSI_blk_len;
86 
96 static int8_t SCSI_TestUnitReady(uint8_t lun, uint8_t *params);
97 static int8_t SCSI_Inquiry(uint8_t lun, uint8_t *params);
98 static int8_t SCSI_ReadFormatCapacity(uint8_t lun, uint8_t *params);
99 static int8_t SCSI_ReadCapacity10(uint8_t lun, uint8_t *params);
100 static int8_t SCSI_RequestSense (uint8_t lun, uint8_t *params);
101 static int8_t SCSI_StartStopUnit(uint8_t lun, uint8_t *params);
102 static int8_t SCSI_ModeSense6 (uint8_t lun, uint8_t *params);
103 static int8_t SCSI_ModeSense10 (uint8_t lun, uint8_t *params);
104 static int8_t SCSI_Write10(uint8_t lun , uint8_t *params);
105 static int8_t SCSI_Read10(uint8_t lun , uint8_t *params);
106 static int8_t SCSI_Verify10(uint8_t lun, uint8_t *params);
107 static int8_t SCSI_CheckAddressRange (uint8_t lun ,
108  uint32_t blk_offset ,
109  uint16_t blk_nbr);
110 static int8_t SCSI_ProcessRead (uint8_t lun);
111 
112 static int8_t SCSI_ProcessWrite (uint8_t lun);
132  uint8_t lun,
133  uint8_t *params)
134 {
135  cdev = pdev;
136 
137  switch (params[0])
138  {
140  return SCSI_TestUnitReady(lun, params);
141 
142  case SCSI_REQUEST_SENSE:
143  return SCSI_RequestSense (lun, params);
144  case SCSI_INQUIRY:
145  return SCSI_Inquiry(lun, params);
146 
148  return SCSI_StartStopUnit(lun, params);
149 
151  return SCSI_StartStopUnit(lun, params);
152 
153  case SCSI_MODE_SENSE6:
154  return SCSI_ModeSense6 (lun, params);
155 
156  case SCSI_MODE_SENSE10:
157  return SCSI_ModeSense10 (lun, params);
158 
160  return SCSI_ReadFormatCapacity(lun, params);
161 
163  return SCSI_ReadCapacity10(lun, params);
164 
165  case SCSI_READ10:
166  return SCSI_Read10(lun, params);
167 
168  case SCSI_WRITE10:
169  return SCSI_Write10(lun, params);
170 
171  case SCSI_VERIFY10:
172  return SCSI_Verify10(lun, params);
173 
174  default:
175  SCSI_SenseCode(lun,
177  INVALID_CDB);
178  return -1;
179  }
180 }
181 
182 
190 static int8_t SCSI_TestUnitReady(uint8_t lun, uint8_t *params)
191 {
192  UNUSED(params);
193  /* case 9 : Hi > D0 */
194  if (MSC_BOT_cbw.dDataLength != 0)
195  {
198  INVALID_CDB);
199  return -1;
200  }
201 
202  if(USBD_STORAGE_fops->IsReady(lun) !=0 )
203  {
204  SCSI_SenseCode(lun,
205  NOT_READY,
207  return -1;
208  }
209  MSC_BOT_DataLen = 0;
210  return 0;
211 }
212 
220 static int8_t SCSI_Inquiry(uint8_t lun, uint8_t *params)
221 {
222  uint8_t* pPage;
223  uint16_t len;
224 
225  if (params[1] & 0x01)/*Evpd is set*/
226  {
227  pPage = (uint8_t *)MSC_Page00_Inquiry_Data;
228  len = LENGTH_INQUIRY_PAGE00;
229  }
230  else
231  {
232 
233  pPage = (uint8_t *)&USBD_STORAGE_fops->pInquiry[lun * USBD_STD_INQUIRY_LENGTH];
234  len = pPage[4] + 5;
235 
236  if (params[4] <= len)
237  {
238  len = params[4];
239  }
240  }
241  MSC_BOT_DataLen = len;
242 
243  while (len)
244  {
245  len--;
246  MSC_BOT_Data[len] = pPage[len];
247  }
248  return 0;
249 }
250 
258 static int8_t SCSI_ReadCapacity10(uint8_t lun, uint8_t *params)
259 {
260  UNUSED(params);
262  {
263  SCSI_SenseCode(lun,
264  NOT_READY,
266  return -1;
267  }
268  else
269  {
270 
271  MSC_BOT_Data[0] = (uint8_t)((SCSI_blk_nbr - 1) >> 24);
272  MSC_BOT_Data[1] = (uint8_t)((SCSI_blk_nbr - 1) >> 16);
273  MSC_BOT_Data[2] = (uint8_t)((SCSI_blk_nbr - 1) >> 8);
274  MSC_BOT_Data[3] = (uint8_t)(SCSI_blk_nbr - 1);
275 
276  MSC_BOT_Data[4] = (uint8_t)(SCSI_blk_size >> 24);
277  MSC_BOT_Data[5] = (uint8_t)(SCSI_blk_size >> 16);
278  MSC_BOT_Data[6] = (uint8_t)(SCSI_blk_size >> 8);
279  MSC_BOT_Data[7] = (uint8_t)(SCSI_blk_size);
280 
281  MSC_BOT_DataLen = 8;
282  return 0;
283  }
284 }
292 static int8_t SCSI_ReadFormatCapacity(uint8_t lun, uint8_t *params)
293 {
294  UNUSED(params);
295  uint32_t blk_size;
296  uint32_t blk_nbr;
297  uint16_t i;
298 
299  for(i=0 ; i < 12 ; i++)
300  {
301  MSC_BOT_Data[i] = 0;
302  }
303 
304  if(USBD_STORAGE_fops->GetCapacity(lun, &blk_nbr, &blk_size) != 0)
305  {
306  SCSI_SenseCode(lun,
307  NOT_READY,
309  return -1;
310  }
311  else
312  {
313  MSC_BOT_Data[3] = 0x08;
314  MSC_BOT_Data[4] = (uint8_t)((blk_nbr - 1) >> 24);
315  MSC_BOT_Data[5] = (uint8_t)((blk_nbr - 1) >> 16);
316  MSC_BOT_Data[6] = (uint8_t)((blk_nbr - 1) >> 8);
317  MSC_BOT_Data[7] = (uint8_t)(blk_nbr - 1);
318 
319  MSC_BOT_Data[8] = 0x02;
320  MSC_BOT_Data[9] = (uint8_t)(blk_size >> 16);
321  MSC_BOT_Data[10] = (uint8_t)(blk_size >> 8);
322  MSC_BOT_Data[11] = (uint8_t)(blk_size);
323 
324  MSC_BOT_DataLen = 12;
325  return 0;
326  }
327 }
335 static int8_t SCSI_ModeSense6 (uint8_t lun, uint8_t *params)
336 {
337  UNUSED(params);
338  UNUSED(lun);
339  uint16_t len = 8 ;
340  MSC_BOT_DataLen = len;
341 
342  while (len)
343  {
344  len--;
346  }
347  return 0;
348 }
349 
357 static int8_t SCSI_ModeSense10 (uint8_t lun, uint8_t *params)
358 {
359  UNUSED(params);
360  UNUSED(lun);
361  uint16_t len = 8;
362 
363  MSC_BOT_DataLen = len;
364 
365  while (len)
366  {
367  len--;
369  }
370  return 0;
371 }
372 
381 static int8_t SCSI_RequestSense (uint8_t lun, uint8_t *params)
382 {
383  UNUSED(lun);
384  uint8_t i;
385 
386  for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++)
387  {
388  MSC_BOT_Data[i] = 0;
389  }
390 
391  MSC_BOT_Data[0] = 0x70;
392  MSC_BOT_Data[7] = REQUEST_SENSE_DATA_LEN - 6;
393 
395 
396  MSC_BOT_Data[2] = SCSI_Sense[SCSI_Sense_Head].Skey;
397  MSC_BOT_Data[12] = SCSI_Sense[SCSI_Sense_Head].w.b.ASCQ;
398  MSC_BOT_Data[13] = SCSI_Sense[SCSI_Sense_Head].w.b.ASC;
399  SCSI_Sense_Head++;
400 
402  {
403  SCSI_Sense_Head = 0;
404  }
405  }
407 
408  if (params[4] <= REQUEST_SENSE_DATA_LEN)
409  {
410  MSC_BOT_DataLen = params[4];
411  }
412  return 0;
413 }
414 
424 void SCSI_SenseCode(uint8_t lun, uint8_t sKey, uint8_t ASC)
425 {
426  UNUSED(lun);
427  SCSI_Sense[SCSI_Sense_Tail].Skey = sKey;
428  SCSI_Sense[SCSI_Sense_Tail].w.ASC = ASC << 8;
429  SCSI_Sense_Tail++;
431  {
432  SCSI_Sense_Tail = 0;
433  }
434 }
442 static int8_t SCSI_StartStopUnit(uint8_t lun, uint8_t *params)
443 {
444  UNUSED(params);
445  UNUSED(lun);
446  MSC_BOT_DataLen = 0;
447  return 0;
448 }
449 
457 static int8_t SCSI_Read10(uint8_t lun , uint8_t *params)
458 {
459  if(MSC_BOT_State == BOT_IDLE) /* Idle */
460  {
461 
462  /* case 10 : Ho <> Di */
463 
464  if ((MSC_BOT_cbw.bmFlags & 0x80) != 0x80)
465  {
468  INVALID_CDB);
469  return -1;
470  }
471 
472  if(USBD_STORAGE_fops->IsReady(lun) !=0 )
473  {
474  SCSI_SenseCode(lun,
475  NOT_READY,
477  return -1;
478  }
479 
480  SCSI_blk_addr = (params[2] << 24) | \
481  (params[3] << 16) | \
482  (params[4] << 8) | \
483  params[5];
484 
485  SCSI_blk_len = (params[7] << 8) | \
486  params[8];
487 
488 
489 
491  {
492  return -1; /* error */
493  }
494 
498 
499  /* cases 4,5 : Hi <> Dn */
501  {
504  INVALID_CDB);
505  return -1;
506  }
507  }
509 
510  return SCSI_ProcessRead(lun);
511 }
512 
521 static int8_t SCSI_Write10 (uint8_t lun , uint8_t *params)
522 {
523  if (MSC_BOT_State == BOT_IDLE) /* Idle */
524  {
525 
526  /* case 8 : Hi <> Do */
527 
528  if ((MSC_BOT_cbw.bmFlags & 0x80) == 0x80)
529  {
532  INVALID_CDB);
533  return -1;
534  }
535 
536  /* Check whether Media is ready */
537  if(USBD_STORAGE_fops->IsReady(lun) !=0 )
538  {
539  SCSI_SenseCode(lun,
540  NOT_READY,
542  return -1;
543  }
544 
545  /* Check If media is write-protected */
546  if(USBD_STORAGE_fops->IsWriteProtected(lun) !=0 )
547  {
548  SCSI_SenseCode(lun,
549  NOT_READY,
551  return -1;
552  }
553 
554 
555  SCSI_blk_addr = (params[2] << 24) | \
556  (params[3] << 16) | \
557  (params[4] << 8) | \
558  params[5];
559  SCSI_blk_len = (params[7] << 8) | \
560  params[8];
561 
562  /* check if LBA address is in the right range */
564  {
565  return -1; /* error */
566  }
567 
570 
571  /* cases 3,11,13 : Hn,Ho <> D0 */
573  {
576  INVALID_CDB);
577  return -1;
578  }
579 
580  /* Prepare EP to receive first data packet */
582  DCD_EP_PrepareRx (cdev,
583  MSC_OUT_EP,
584  MSC_BOT_Data,
586  }
587  else /* Write Process ongoing */
588  {
589  return SCSI_ProcessWrite(lun);
590  }
591  return 0;
592 }
593 
594 
603 static int8_t SCSI_Verify10(uint8_t lun , uint8_t *params){
604  if ((params[1]& 0x02) == 0x02)
605  {
607  return -1; /* Error, Verify Mode Not supported*/
608  }
609 
610  SCSI_blk_addr = (params[2] << 24) | \
611  (params[3] << 16) | \
612  (params[4] << 8) | \
613  params[5];
614  SCSI_blk_len = (params[7] << 8) | \
615  params[8];
616 
618  {
619  return -1; /* error */
620  }
621  MSC_BOT_DataLen = 0;
622  return 0;
623 }
624 
633 static int8_t SCSI_CheckAddressRange (uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr)
634 {
635 
636  if ((blk_offset + blk_nbr) > SCSI_blk_nbr )
637  {
639  return -1;
640  }
641  return 0;
642 }
643 
650 static int8_t SCSI_ProcessRead (uint8_t lun)
651 {
652  uint32_t len;
653 
655 
656  if( USBD_STORAGE_fops->Read(lun ,
657  MSC_BOT_Data,
659  len / SCSI_blk_size) < 0)
660  {
661 
663  return -1;
664  }
665 
666 
667  DCD_EP_Tx (cdev,
668  MSC_IN_EP,
669  MSC_BOT_Data,
670  len);
671 
672 
673  SCSI_blk_addr += len;
674  SCSI_blk_len -= len;
675 
676  /* case 6 : Hi = Di */
677  MSC_BOT_csw.dDataResidue -= len;
678 
679  if (SCSI_blk_len == 0)
680  {
682  }
683  return 0;
684 }
685 
693 static int8_t SCSI_ProcessWrite (uint8_t lun)
694 {
695  uint32_t len;
696 
698 
699  if(USBD_STORAGE_fops->Write(lun ,
700  MSC_BOT_Data,
702  len / SCSI_blk_size) < 0)
703  {
705  return -1;
706  }
707 
708 
709  SCSI_blk_addr += len;
710  SCSI_blk_len -= len;
711 
712  /* case 12 : Ho = Do */
713  MSC_BOT_csw.dDataResidue -= len;
714 
715  if (SCSI_blk_len == 0)
716  {
718  }
719  else
720  {
721  /* Prapare EP to Receive next packet */
722  DCD_EP_PrepareRx (cdev,
723  MSC_OUT_EP,
724  MSC_BOT_Data,
726  }
727 
728  return 0;
729 }
744 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
static int8_t SCSI_ProcessRead(uint8_t lun)
SCSI_ProcessRead Handle Read Process.
#define SCSI_START_STOP_UNIT
Definition: usbd_msc_scsi.h:67
#define SCSI_REQUEST_SENSE
Definition: usbd_msc_scsi.h:66
uint32_t dDataResidue
Definition: usbd_msc_bot.h:100
#define SCSI_READ10
Definition: usbd_msc_scsi.h:59
#define MSC_IN_EP
Definition: usbd_conf.h:66
#define INVALID_FIELED_IN_COMMAND
Definition: usbd_msc_scsi.h:98
struct _SENSE_ITEM::@58::_ASCs b
uint32_t DCD_EP_Tx(USB_OTG_CORE_HANDLE *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len)
Transmit data over USB.
Definition: usb_dcd.c:271
SCSI_Sense_TypeDef SCSI_Sense[SENSE_LIST_DEEPTH]
Definition: usbd_msc_scsi.c:77
#define UNRECOVERED_READ_ERROR
uint8_t SCSI_Sense_Tail
Definition: usbd_msc_scsi.c:79
uint8_t MSC_BOT_Data[]
int8_t(* GetCapacity)(uint8_t lun, uint32_t *block_num, uint32_t *block_size)
Definition: usbd_msc_mem.h:61
const uint8_t MSC_Page00_Inquiry_Data[]
Definition: usbd_msc_data.c:72
#define SCSI_TEST_UNIT_READY
Definition: usbd_msc_scsi.h:68
#define INVALID_CDB
Definition: usbd_msc_scsi.h:97
#define MEDIUM_NOT_PRESENT
uint32_t SCSI_blk_nbr
Definition: usbd_msc_scsi.c:82
#define BOT_IDLE
Definition: usbd_msc_bot.h:49
static int8_t SCSI_StartStopUnit(uint8_t lun, uint8_t *params)
SCSI_StartStopUnit Process Start Stop Unit command.
uint8_t bmFlags
Definition: usbd_msc_bot.h:88
#define REQUEST_SENSE_DATA_LEN
header for the STORAGE DISK file file
static int8_t SCSI_Inquiry(uint8_t lun, uint8_t *params)
SCSI_Inquiry Process Inquiry command.
int8_t(* IsReady)(uint8_t lun)
Definition: usbd_msc_mem.h:62
#define LENGTH_INQUIRY_PAGE00
Definition: usbd_msc_data.h:50
uint32_t SCSI_blk_addr
Definition: usbd_msc_scsi.c:84
#define BOT_DATA_IN
Definition: usbd_msc_bot.h:51
#define SCSI_INQUIRY
Definition: usbd_msc_scsi.h:52
static int8_t SCSI_ProcessWrite(uint8_t lun)
SCSI_ProcessWrite Handle Write Process.
void MSC_BOT_SendCSW(USB_OTG_CORE_HANDLE *pdev, uint8_t CSW_Status)
MSC_BOT_SendCSW Send the Command Status Wrapper.
Definition: usbd_msc_bot.c:322
#define SCSI_MODE_SENSE10
Definition: usbd_msc_scsi.h:56
#define MIN(a, b)
Definition: usb_defines.h:178
#define UNUSED(x)
Definition: usbd_msc_scsi.c:34
#define NOT_READY
Definition: usbd_msc_scsi.h:83
#define SCSI_MODE_SENSE6
Definition: usbd_msc_scsi.h:55
uint32_t dDataLength
Definition: usbd_msc_bot.h:87
#define USBD_STD_INQUIRY_LENGTH
Definition: usbd_msc_mem.h:48
int8_t SCSI_ProcessCmd(USB_OTG_CORE_HANDLE *pdev, uint8_t lun, uint8_t *params)
SCSI_ProcessCmd Process SCSI commands.
header for the usbd_msc_data.c file
int8_t * pInquiry
Definition: usbd_msc_mem.h:67
const uint8_t MSC_Mode_Sense6_data[]
Definition: usbd_msc_data.c:82
static int8_t SCSI_TestUnitReady(uint8_t lun, uint8_t *params)
SCSI_TestUnitReady Process SCSI Test Unit Ready Command.
#define SCSI_READ_FORMAT_CAPACITIES
Definition: usbd_msc_scsi.h:79
#define MSC_MEDIA_PACKET
Definition: usbd_conf.h:79
#define ADDRESS_OUT_OF_RANGE
header for the usbd_msc_scsi.c file
#define SCSI_VERIFY10
Definition: usbd_msc_scsi.h:74
int8_t(* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
Definition: usbd_msc_mem.h:65
#define HARDWARE_ERROR
Definition: usbd_msc_scsi.h:85
uint32_t DCD_EP_PrepareRx(USB_OTG_CORE_HANDLE *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len)
DCD_EP_PrepareRx.
Definition: usb_dcd.c:231
static int8_t SCSI_RequestSense(uint8_t lun, uint8_t *params)
SCSI_RequestSense Process Request Sense command.
#define SENSE_LIST_DEEPTH
Definition: usbd_msc_scsi.h:48
#define MSC_OUT_EP
Definition: usbd_conf.h:67
#define SCSI_WRITE10
Definition: usbd_msc_scsi.h:70
static int8_t SCSI_Write10(uint8_t lun, uint8_t *params)
SCSI_Write10 Process Write10 command.
#define ILLEGAL_REQUEST
Definition: usbd_msc_scsi.h:86
static int8_t SCSI_Read10(uint8_t lun, uint8_t *params)
SCSI_Read10 Process Read10 command.
#define SCSI_READ_CAPACITY10
Definition: usbd_msc_scsi.h:63
#define BOT_LAST_DATA_IN
Definition: usbd_msc_bot.h:52
USBD_STORAGE_cb_TypeDef * USBD_STORAGE_fops
MSC_BOT_CBW_TypeDef MSC_BOT_cbw
#define CSW_CMD_PASSED
Definition: usbd_msc_bot.h:61
static int8_t SCSI_ReadFormatCapacity(uint8_t lun, uint8_t *params)
SCSI_ReadFormatCapacity Process Read Format Capacity command.
uint8_t MSC_BOT_State
Definition: usbd_msc_bot.c:75
int8_t(* IsWriteProtected)(uint8_t lun)
Definition: usbd_msc_mem.h:63
USB_OTG_CORE_HANDLE * cdev
Definition: usbd_msc_scsi.c:87
void SCSI_SenseCode(uint8_t lun, uint8_t sKey, uint8_t ASC)
SCSI_SenseCode Load the last error code in the error list.
#define WRITE_FAULT
static int8_t SCSI_CheckAddressRange(uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr)
SCSI_CheckAddressRange Check address range.
MSC_BOT_CSW_TypeDef MSC_BOT_csw
#define BOT_DATA_OUT
Definition: usbd_msc_bot.h:50
uint32_t SCSI_blk_size
Definition: usbd_msc_scsi.c:81
uint16_t MSC_BOT_DataLen
Definition: usbd_msc_bot.c:74
uint32_t SCSI_blk_len
Definition: usbd_msc_scsi.c:85
uint8_t bLUN
Definition: usbd_msc_bot.h:89
static int8_t SCSI_ModeSense6(uint8_t lun, uint8_t *params)
SCSI_ModeSense6 Process Mode Sense6 command.
uint8_t SCSI_Sense_Head
Definition: usbd_msc_scsi.c:78
union _SENSE_ITEM::@58 w
#define SCSI_ALLOW_MEDIUM_REMOVAL
Definition: usbd_msc_scsi.h:57
header for the usbd_msc_bot.c file
int8_t(* Read)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
Definition: usbd_msc_mem.h:64
static int8_t SCSI_ReadCapacity10(uint8_t lun, uint8_t *params)
SCSI_ReadCapacity10 Process Read Capacity 10 command.
const uint8_t MSC_Mode_Sense10_data[]
Definition: usbd_msc_data.c:93
#define WRITE_PROTECTED
static int8_t SCSI_Verify10(uint8_t lun, uint8_t *params)
SCSI_Verify10 Process Verify10 command.
static int8_t SCSI_ModeSense10(uint8_t lun, uint8_t *params)
SCSI_ModeSense10 Process Mode Sense10 command.


rosflight_firmware
Author(s): Daniel Koch , James Jackson
autogenerated on Wed Jul 3 2019 19:59:26