GD32F10x USB-Device: E:/USB Libraries/GD32_USB_Device_Library/Class/msc/src/usbd_msc_scsi.c Source File

GD32F103 Firmware

usbd_msc_scsi.c
Go to the documentation of this file.
1 
11 /* Includes ------------------------------------------------------------------*/
12 #include "usbd_msc_scsi.h"
13 
33 SCSI_Sense_TypeDef SCSI_Sense[SENSE_LIST_DEEPTH];
34 
35 uint8_t SCSI_Sense_Head;
36 uint8_t SCSI_Sense_Tail;
37 
38 uint32_t SCSI_blk_size;
39 uint32_t SCSI_blk_nbr;
40 
41 uint32_t SCSI_blk_addr;
42 uint32_t SCSI_blk_len;
43 
44 USB_DEVICE_HANDLE *cdev;
45 
53 static int8_t SCSI_TestUnitReady (uint8_t Lun, uint8_t *params);
54 static int8_t SCSI_Inquiry (uint8_t Lun, uint8_t *params);
55 static int8_t SCSI_ReadFormatCapacity (uint8_t Lun, uint8_t *params);
56 static int8_t SCSI_ReadCapacity10 (uint8_t Lun, uint8_t *params);
57 static int8_t SCSI_RequestSense (uint8_t Lun, uint8_t *params);
58 static int8_t SCSI_StartStopUnit (uint8_t Lun, uint8_t *params);
59 static int8_t SCSI_AllowMediumRemoval (uint8_t Lun, uint8_t *params);
60 static int8_t SCSI_ModeSense6 (uint8_t Lun, uint8_t *params);
61 static int8_t SCSI_ModeSense10 (uint8_t Lun, uint8_t *params);
62 static int8_t SCSI_Write10 (uint8_t Lun, uint8_t *params);
63 static int8_t SCSI_Read10 (uint8_t Lun, uint8_t *params);
64 static int8_t SCSI_Verify10 (uint8_t Lun, uint8_t *params);
65 static int8_t SCSI_CheckAddressRange (uint8_t Lun,
66  uint32_t BlkOffset,
67  uint16_t BlkNbr);
68 //static int8_t SCSI_ProcessRead (uint8_t Lun);
69 //static int8_t SCSI_ProcessWrite (uint8_t Lun);
70 static int8_t SCSI_Format_Cmd (uint8_t Lun);
71 
88  uint8_t Lun,
89  uint8_t *params)
90 {
91  cdev = pudev;
92 
93  switch (params[0])
94  {
95  case SCSI_TEST_UNIT_READY:
96  return SCSI_TestUnitReady(Lun, params);
97 
98  case SCSI_REQUEST_SENSE:
99  return SCSI_RequestSense(Lun, params);
100 
101  case SCSI_INQUIRY:
102  return SCSI_Inquiry(Lun, params);
103 
104  case SCSI_START_STOP_UNIT:
105  return SCSI_StartStopUnit(Lun, params);
106 
107  case SCSI_ALLOW_MEDIUM_REMOVAL:
108  return SCSI_AllowMediumRemoval(Lun, params);
109 
110  case SCSI_MODE_SENSE6:
111  return SCSI_ModeSense6(Lun, params);
112 
113  case SCSI_MODE_SENSE10:
114  return SCSI_ModeSense10(Lun, params);
115 
116  case SCSI_READ_FORMAT_CAPACITIES:
117  return SCSI_ReadFormatCapacity(Lun, params);
118 
119  case SCSI_READ_CAPACITY10:
120  return SCSI_ReadCapacity10(Lun, params);
121 
122  case SCSI_READ10:
123  return SCSI_Read10(Lun, params);
124 
125  case SCSI_WRITE10:
126  return SCSI_Write10(Lun, params);
127 
128  case SCSI_VERIFY10:
129  return SCSI_Verify10(Lun, params);
130 
131  case SCSI_FORMAT_UNIT:
132  return SCSI_Format_Cmd(Lun);
133 
134  default:
135  SCSI_SenseCode(Lun,
136  ILLEGAL_REQUEST,
137  INVALID_CDB);
138  return -1;
139  }
140 }
141 
142 
149 static int8_t SCSI_TestUnitReady (uint8_t Lun, uint8_t *params)
150 {
151  /* case 9 : Hi > D0 */
152  if (MSC_BBB_cbw.dCBWDataTransferLength != 0)
153  {
154  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
155  ILLEGAL_REQUEST,
156  INVALID_CDB);
157  return -1;
158  }
159 
160  if(USBD_STORAGE_fops->IsReady(Lun) != 0)
161  {
162  SCSI_SenseCode(Lun,
163  NOT_READY,
164  MEDIUM_NOT_PRESENT);
165  return -1;
166  }
167 
168  MSC_BBB_DataLen = 0;
169 
170  return 0;
171 }
172 
179 static int8_t SCSI_Inquiry (uint8_t Lun, uint8_t *params)
180 {
181  uint8_t* pPage;
182  uint16_t Len;
183 
184  if (params[1] & 0x01)
185  {
186  /* Evpd is set */
187 
188  pPage = (uint8_t *)MSC_Page00_Inquiry_Data;
189  Len = INQUIRY_PAGE00_LENGTH;
190  }
191  else
192  {
193  /* Evpd is 0 */
194 
195  pPage = (uint8_t *)&USBD_STORAGE_fops->pInquiryData[Lun * USBD_STD_INQUIRY_LENGTH];
196  Len = pPage[4] + 5;
197  }
198 
199  MSC_BBB_DataLen = MIN(Len, params[4]);
200 
201  while (Len)
202  {
203  Len--;
204  MSC_BBB_Data[Len] = pPage[Len];
205  }
206 
207  return 0;
208 }
209 
216 static int8_t SCSI_ReadCapacity10 (uint8_t Lun, uint8_t *params)
217 {
218  if(USBD_STORAGE_fops->GetCapacity(Lun, &SCSI_blk_nbr, &SCSI_blk_size) != 0)
219  {
220  SCSI_SenseCode(Lun,
221  NOT_READY,
222  MEDIUM_NOT_PRESENT);
223 
224  return -1;
225  }
226  else
227  {
228  uint32_t BlkNum = SCSI_blk_nbr - 1;
229 
230  MSC_BBB_Data[0] = (uint8_t)(BlkNum >> 24);
231  MSC_BBB_Data[1] = (uint8_t)(BlkNum >> 16);
232  MSC_BBB_Data[2] = (uint8_t)(BlkNum >> 8);
233  MSC_BBB_Data[3] = (uint8_t)(BlkNum);
234 
235  MSC_BBB_Data[4] = (uint8_t)(SCSI_blk_size >> 24);
236  MSC_BBB_Data[5] = (uint8_t)(SCSI_blk_size >> 16);
237  MSC_BBB_Data[6] = (uint8_t)(SCSI_blk_size >> 8);
238  MSC_BBB_Data[7] = (uint8_t)(SCSI_blk_size);
239 
240  MSC_BBB_DataLen = 8;
241 
242  return 0;
243  }
244 }
251 static int8_t SCSI_ReadFormatCapacity (uint8_t Lun, uint8_t *params)
252 {
253  uint32_t BlkSize;
254  uint32_t BlkNum;
255  uint16_t i;
256 
257  for(i = 0; i < 12; i++)
258  {
259  MSC_BBB_Data[i] = 0;
260  }
261 
262  if(USBD_STORAGE_fops->GetCapacity(Lun, &BlkNum, &BlkSize) != 0)
263  {
264  SCSI_SenseCode(Lun,
265  NOT_READY,
266  MEDIUM_NOT_PRESENT);
267  return (-1);
268  }
269  else
270  {
271  uint32_t BlkNbr = BlkNum - 1;
272 
273  MSC_BBB_Data[3] = 0x08;
274  MSC_BBB_Data[4] = (uint8_t)(BlkNbr >> 24);
275  MSC_BBB_Data[5] = (uint8_t)(BlkNbr >> 16);
276  MSC_BBB_Data[6] = (uint8_t)(BlkNbr >> 8);
277  MSC_BBB_Data[7] = (uint8_t)(BlkNbr);
278 
279  MSC_BBB_Data[8] = 0x02;
280  MSC_BBB_Data[9] = (uint8_t)(BlkSize >> 16);
281  MSC_BBB_Data[10] = (uint8_t)(BlkSize >> 8);
282  MSC_BBB_Data[11] = (uint8_t)(BlkSize);
283 
284  MSC_BBB_DataLen = 12;
285 
286  return 0;
287  }
288 }
289 
296 static int8_t SCSI_ModeSense6 (uint8_t Lun, uint8_t *params)
297 {
298  uint16_t len = 8;
299 
300  MSC_BBB_DataLen = len;
301 
302  while (len)
303  {
304  len--;
305  MSC_BBB_Data[len] = MSC_Mode_Sense6_data[len];
306  }
307 
308  return 0;
309 }
310 
317 static int8_t SCSI_ModeSense10 (uint8_t Lun, uint8_t *params)
318 {
319  uint16_t Len = 8;
320 
321  MSC_BBB_DataLen = Len;
322 
323  while (Len)
324  {
325  Len--;
326  MSC_BBB_Data[Len] = MSC_Mode_Sense10_data[Len];
327  }
328 
329  return 0;
330 }
331 
338 static int8_t SCSI_RequestSense (uint8_t Lun, uint8_t *params)
339 {
340  uint8_t i;
341 
342  for(i = 0; i < REQUEST_SENSE_DATA_LEN; i++)
343  {
344  MSC_BBB_Data[i] = 0;
345  }
346 
347  MSC_BBB_Data[0] = 0x70;
348  MSC_BBB_Data[7] = REQUEST_SENSE_DATA_LEN - 6;
349 
350  if((SCSI_Sense_Head != SCSI_Sense_Tail))
351  {
352  MSC_BBB_Data[2] = SCSI_Sense[SCSI_Sense_Head].SenseKey;
353  MSC_BBB_Data[12] = SCSI_Sense[SCSI_Sense_Head].ASCQ;
354  MSC_BBB_Data[13] = SCSI_Sense[SCSI_Sense_Head].ASC;
355 
356  SCSI_Sense_Head++;
357 
358  if (SCSI_Sense_Head == SENSE_LIST_DEEPTH)
359  {
360  SCSI_Sense_Head = 0;
361  }
362  }
363 
364  MSC_BBB_DataLen = MIN(REQUEST_SENSE_DATA_LEN, params[4]);
365 
366  return 0;
367 }
368 
376 void SCSI_SenseCode (uint8_t Lun, uint8_t SKey, uint8_t ASC)
377 {
378  SCSI_Sense[SCSI_Sense_Tail].SenseKey = SKey;
379  SCSI_Sense[SCSI_Sense_Tail].ASC = ASC << 8;
380  SCSI_Sense_Tail++;
381 
382  if (SCSI_Sense_Tail == SENSE_LIST_DEEPTH)
383  {
384  SCSI_Sense_Tail = 0;
385  }
386 }
387 
394 static int8_t SCSI_StartStopUnit(uint8_t Lun, uint8_t *params)
395 {
396  MSC_BBB_DataLen = 0;
397 
398  return 0;
399 }
400 
407 static int8_t SCSI_AllowMediumRemoval(uint8_t Lun, uint8_t *params)
408 {
409  MSC_BBB_DataLen = 0;
410 
411  return 0;
412 }
413 
420 static int8_t SCSI_Read10(uint8_t Lun , uint8_t *params)
421 {
422  if(MSC_BBB_State == BBB_IDLE)
423  {
424  /* Direction is from device to host */
425  if ((MSC_BBB_cbw.bmCBWFlags & 0x80) != 0x80)
426  {
427  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
428  ILLEGAL_REQUEST,
429  INVALID_CDB);
430  return -1;
431  }
432 
433  if(USBD_STORAGE_fops->IsReady(Lun) != 0)
434  {
435  SCSI_SenseCode(Lun,
436  NOT_READY,
437  MEDIUM_NOT_PRESENT);
438  return -1;
439  }
440 
441  SCSI_blk_addr = (params[2] << 24) | (params[3] << 16) | \
442  (params[4] << 8) | params[5];
443 
444  SCSI_blk_len = (params[7] << 8) | params[8];
445 
446  if(SCSI_CheckAddressRange(Lun, SCSI_blk_addr, SCSI_blk_len) < 0)
447  {
448  return -1; /* error */
449  }
450 
451  MSC_BBB_State = BBB_DATA_IN;
452  SCSI_blk_addr *= SCSI_blk_size;
453  SCSI_blk_len *= SCSI_blk_size;
454 
455  /* cases 4,5 : Hi <> Dn */
456  if (MSC_BBB_cbw.dCBWDataTransferLength != SCSI_blk_len)
457  {
458  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
459  ILLEGAL_REQUEST,
460  INVALID_CDB);
461 
462  return -1;
463  }
464  }
465 
466  MSC_BBB_DataLen = MSC_MEDIA_PACKET_SIZE;
467 
468  return SCSI_ProcessRead(Lun);
469 }
470 
477 static int8_t SCSI_Write10 (uint8_t Lun, uint8_t *params)
478 {
479  if (MSC_BBB_State == BBB_IDLE) /* Idle */
480  {
481  /* case 8 : Hi <> Do */
482  if ((MSC_BBB_cbw.bmCBWFlags & 0x80) == 0x80)
483  {
484  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
485  ILLEGAL_REQUEST,
486  INVALID_CDB);
487 
488  return -1;
489  }
490 
491  /* Check whether Media is ready */
492  if(USBD_STORAGE_fops->IsReady(Lun) !=0 )
493  {
494  SCSI_SenseCode(Lun,
495  NOT_READY,
496  MEDIUM_NOT_PRESENT);
497 
498  return -1;
499  }
500 
501  /* Check If media is write-protected */
502  if(USBD_STORAGE_fops->IsWriteProtected(Lun) !=0)
503  {
504  SCSI_SenseCode(Lun,
505  NOT_READY,
506  WRITE_PROTECTED);
507 
508  return -1;
509  }
510 
511  SCSI_blk_addr = (params[2] << 24) | (params[3] << 16) | \
512  (params[4] << 8) | params[5];
513 
514  SCSI_blk_len = (params[7] << 8) | params[8];
515 
516  /* check if LBA address is in the right range */
517  if(SCSI_CheckAddressRange(Lun, SCSI_blk_addr, SCSI_blk_len) < 0)
518  {
519  return -1; /* error */
520  }
521 
522  SCSI_blk_addr *= SCSI_blk_size;
523  SCSI_blk_len *= SCSI_blk_size;
524 
525  /* cases 3,11,13 : Hn,Ho <> D0 */
526  if (MSC_BBB_cbw.dCBWDataTransferLength != SCSI_blk_len)
527  {
528  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
529  ILLEGAL_REQUEST,
530  INVALID_CDB);
531 
532  return -1;
533  }
534 
535  /* Prepare EP to receive first data packet */
536  MSC_BBB_State = BBB_DATA_OUT;
537  USB_EP_Rx (cdev,
538  MSC_OUT_EP,
539  MSC_BBB_Data,
540  MIN (SCSI_blk_len, MSC_MEDIA_PACKET_SIZE));
541  }
542  else /* Write Process ongoing */
543  {
544  return SCSI_ProcessWrite(Lun);
545  }
546 
547  return 0;
548 }
549 
556 static int8_t SCSI_Verify10 (uint8_t Lun, uint8_t *params)
557 {
558  if ((params[1] & 0x02) == 0x02)
559  {
560  SCSI_SenseCode(Lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
561 
562  return -1; /* Error, Verify Mode Not supported*/
563  }
564 
565  if(SCSI_CheckAddressRange(Lun, SCSI_blk_addr, SCSI_blk_len) < 0)
566  {
567  return -1; /* error */
568  }
569 
570  MSC_BBB_DataLen = 0;
571 
572  return 0;
573 }
574 
582 static int8_t SCSI_CheckAddressRange (uint8_t Lun, uint32_t BlkOffset, uint16_t BlkNbr)
583 {
584  if ((BlkOffset + BlkNbr) > SCSI_blk_nbr)
585  {
586  SCSI_SenseCode(Lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE);
587 
588  return -1;
589  }
590 
591  return 0;
592 }
593 
599 /* static */ int8_t SCSI_ProcessRead (uint8_t Lun)
600 {
601  uint32_t len;
602 
603  len = MIN(SCSI_blk_len, MSC_MEDIA_PACKET_SIZE);
604 
605  if(USBD_STORAGE_fops->Read(Lun,
606  MSC_BBB_Data,
607  SCSI_blk_addr,
608  len / SCSI_blk_size) < 0)
609  {
610  SCSI_SenseCode(Lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR);
611 
612  return -1;
613  }
614 
615  USB_EP_Tx (cdev,
616  MSC_IN_EP,
617  MSC_BBB_Data,
618  len);
619 
620  SCSI_blk_addr += len;
621  SCSI_blk_len -= len;
622 
623  /* case 6 : Hi = Di */
624  MSC_BBB_csw.dCSWDataResidue -= len;
625 
626  if (SCSI_blk_len == 0)
627  {
628  MSC_BBB_State = BBB_LAST_DATA_IN;
629  }
630 
631  return 0;
632 }
633 
639 /* static */ int8_t SCSI_ProcessWrite (uint8_t Lun)
640 {
641  uint32_t len = MIN(SCSI_blk_len, MSC_MEDIA_PACKET_SIZE);
642 
643  if(USBD_STORAGE_fops->Write(Lun,
644  MSC_BBB_Data,
645  SCSI_blk_addr,
646  len / SCSI_blk_size) < 0)
647  {
648  SCSI_SenseCode(Lun, HARDWARE_ERROR, WRITE_FAULT);
649 
650  return -1;
651  }
652 
653  SCSI_blk_addr += len;
654  SCSI_blk_len -= len;
655 
656  /* case 12 : Ho = Do */
657  MSC_BBB_csw.dCSWDataResidue -= len;
658 
659  if (SCSI_blk_len == 0)
660  {
661 // printf("write success ");
662 
663  MSC_BBB_SendCSW (cdev, CSW_CMD_PASSED);
664  }
665  else
666  {
667  /* Prepare EP to Receive next packet */
668  USB_EP_Rx (cdev,
669  MSC_OUT_EP,
670  MSC_BBB_Data,
671  MIN (SCSI_blk_len, MSC_MEDIA_PACKET_SIZE));
672  }
673 
674  return 0;
675 }
676 
682 static int8_t SCSI_Format_Cmd (uint8_t Lun)
683 {
684  return 0;
685 }
686 
707 /************************ (C) COPYRIGHT 2014 GIGADEVICE *****END OF FILE****/
void USB_EP_Tx(USB_CORE_HANDLE *pudev, uint8_t EpAddr, uint8_t *pbuf, uint16_t BufLen)
Endpoint prepare to transmit data.
Definition: usb_core.c:346
int8_t SCSI_ProcessCmd(USB_DEVICE_HANDLE *pudev, uint8_t Lun, uint8_t *params)
Process SCSI commands.
Definition: usbd_msc_scsi.c:87
int8_t SCSI_ProcessRead(uint8_t Lun)
Handle Read Process.
void SCSI_SenseCode(uint8_t Lun, uint8_t SKey, uint8_t ASC)
Load the last error code in the error list.
int8_t SCSI_ProcessWrite(uint8_t Lun)
Handle write process.
void MSC_BBB_SendCSW(USB_DEVICE_HANDLE *pudev, uint8_t CSW_Status)
Send the CSW(command status wrapper)
Definition: usbd_msc_bot.c:242
Header file for the usbd_msc_scsi.c file.
void USB_EP_Rx(USB_CORE_HANDLE *pudev, uint8_t EpAddr, uint8_t *pbuf, uint16_t BufLen)
Endpoint prepare to receive data.
Definition: usb_core.c:309
Generated on Fri Feb 6 2015 14:56:35 for GD32F10x USB-Device by   doxygen 1.8.8