GD32F1x0: USB/GD32_USB_Device_Library/Class/msc/src/usbd_msc_scsi.c Source File

GD32F1x0

usbd_msc_scsi.c
Go to the documentation of this file.
1 
11 /* Includes ------------------------------------------------------------------*/
12 #include "usbd_msc_scsi.h"
13 
14 /* Private variables ---------------------------------------------------------*/
15 SCSI_Sense_TypeDef SCSI_Sense[SENSE_LIST_DEEPTH];
16 
17 uint8_t SCSI_Sense_Head;
18 uint8_t SCSI_Sense_Tail;
19 
20 uint32_t SCSI_blk_size;
21 uint32_t SCSI_blk_nbr;
22 
23 uint32_t SCSI_blk_addr;
24 uint32_t SCSI_blk_len;
25 
26 USB_DEVICE_HANDLE *cdev;
27 
28 /* Private function prototypes -----------------------------------------------*/
29 static int8_t SCSI_TestUnitReady (uint8_t Lun, uint8_t *params);
30 static int8_t SCSI_Inquiry (uint8_t Lun, uint8_t *params);
31 static int8_t SCSI_ReadFormatCapacity (uint8_t Lun, uint8_t *params);
32 static int8_t SCSI_ReadCapacity10 (uint8_t Lun, uint8_t *params);
33 static int8_t SCSI_RequestSense (uint8_t Lun, uint8_t *params);
34 static int8_t SCSI_StartStopUnit (uint8_t Lun, uint8_t *params);
35 static int8_t SCSI_AllowMediumRemoval (uint8_t Lun, uint8_t *params);
36 static int8_t SCSI_ModeSense6 (uint8_t Lun, uint8_t *params);
37 static int8_t SCSI_ModeSense10 (uint8_t Lun, uint8_t *params);
38 static int8_t SCSI_Write10 (uint8_t Lun, uint8_t *params);
39 static int8_t SCSI_Read10 (uint8_t Lun, uint8_t *params);
40 static int8_t SCSI_Verify10 (uint8_t Lun, uint8_t *params);
41 static int8_t SCSI_CheckAddressRange (uint8_t Lun,
42  uint32_t BlkOffset,
43  uint16_t BlkNbr);
44 //static int8_t SCSI_ProcessRead (uint8_t Lun);
45 //static int8_t SCSI_ProcessWrite (uint8_t Lun);
46 static int8_t SCSI_Format_Cmd (uint8_t Lun);
47 
48 /* Private function ----------------------------------------------------------*/
49 
58  uint8_t Lun,
59  uint8_t *params)
60 {
61  cdev = pudev;
62 
63  switch (params[0])
64  {
65  case SCSI_TEST_UNIT_READY:
66  return SCSI_TestUnitReady(Lun, params);
67 
68  case SCSI_REQUEST_SENSE:
69  return SCSI_RequestSense(Lun, params);
70 
71  case SCSI_INQUIRY:
72  return SCSI_Inquiry(Lun, params);
73 
74  case SCSI_START_STOP_UNIT:
75  return SCSI_StartStopUnit(Lun, params);
76 
77  case SCSI_ALLOW_MEDIUM_REMOVAL:
78  return SCSI_AllowMediumRemoval(Lun, params);
79 
80  case SCSI_MODE_SENSE6:
81  return SCSI_ModeSense6(Lun, params);
82 
83  case SCSI_MODE_SENSE10:
84  return SCSI_ModeSense10(Lun, params);
85 
86  case SCSI_READ_FORMAT_CAPACITIES:
87  return SCSI_ReadFormatCapacity(Lun, params);
88 
89  case SCSI_READ_CAPACITY10:
90  return SCSI_ReadCapacity10(Lun, params);
91 
92  case SCSI_READ10:
93  return SCSI_Read10(Lun, params);
94 
95  case SCSI_WRITE10:
96  return SCSI_Write10(Lun, params);
97 
98  case SCSI_VERIFY10:
99  return SCSI_Verify10(Lun, params);
100 
101  case SCSI_FORMAT_UNIT:
102  return SCSI_Format_Cmd(Lun);
103 
104  default:
105  SCSI_SenseCode(Lun,
106  ILLEGAL_REQUEST,
107  INVALID_CDB);
108  return -1;
109  }
110 }
111 
112 
119 static int8_t SCSI_TestUnitReady (uint8_t Lun, uint8_t *params)
120 {
121  /* case 9 : Hi > D0 */
122  if (MSC_BBB_cbw.dCBWDataTransferLength != 0)
123  {
124  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
125  ILLEGAL_REQUEST,
126  INVALID_CDB);
127  return -1;
128  }
129 
130  if(USBD_STORAGE_fops->IsReady(Lun) != 0)
131  {
132  SCSI_SenseCode(Lun,
133  NOT_READY,
134  MEDIUM_NOT_PRESENT);
135  return -1;
136  }
137 
138  MSC_BBB_DataLen = 0;
139 
140  return 0;
141 }
142 
149 static int8_t SCSI_Inquiry (uint8_t Lun, uint8_t *params)
150 {
151  uint8_t* pPage;
152  uint16_t Len;
153 
154  if (params[1] & 0x01)
155  {
156  /* Evpd is set */
157 
158  pPage = (uint8_t *)MSC_Page00_Inquiry_Data;
159  Len = INQUIRY_PAGE00_LENGTH;
160  }
161  else
162  {
163  /* Evpd is 0 */
164 
165  pPage = (uint8_t *)&USBD_STORAGE_fops->pInquiryData[Lun * USBD_STD_INQUIRY_LENGTH];
166  Len = pPage[4] + 5;
167 
168  if (params[4] <= Len)
169  {
170  Len = params[4];
171  }
172  }
173 
174  MSC_BBB_DataLen = Len;
175 
176  while (Len)
177  {
178  Len--;
179  MSC_BBB_Data[Len] = pPage[Len];
180  }
181 
182  return 0;
183 }
184 
191 static int8_t SCSI_ReadCapacity10 (uint8_t Lun, uint8_t *params)
192 {
193  if(USBD_STORAGE_fops->GetCapacity(Lun, &SCSI_blk_nbr, &SCSI_blk_size) != 0)
194  {
195  SCSI_SenseCode(Lun,
196  NOT_READY,
197  MEDIUM_NOT_PRESENT);
198 
199  return -1;
200  }
201  else
202  {
203  uint32_t BlkNum = SCSI_blk_nbr - 1;
204 
205  MSC_BBB_Data[0] = (uint8_t)(BlkNum >> 24);
206  MSC_BBB_Data[1] = (uint8_t)(BlkNum >> 16);
207  MSC_BBB_Data[2] = (uint8_t)(BlkNum >> 8);
208  MSC_BBB_Data[3] = (uint8_t)(BlkNum);
209 
210  MSC_BBB_Data[4] = (uint8_t)(SCSI_blk_size >> 24);
211  MSC_BBB_Data[5] = (uint8_t)(SCSI_blk_size >> 16);
212  MSC_BBB_Data[6] = (uint8_t)(SCSI_blk_size >> 8);
213  MSC_BBB_Data[7] = (uint8_t)(SCSI_blk_size);
214 
215  MSC_BBB_DataLen = 8;
216 
217  return 0;
218  }
219 }
226 static int8_t SCSI_ReadFormatCapacity (uint8_t Lun, uint8_t *params)
227 {
228  uint32_t BlkSize;
229  uint32_t BlkNum;
230  uint16_t i;
231 
232  for(i = 0; i < 12; i++)
233  {
234  MSC_BBB_Data[i] = 0;
235  }
236 
237  if(USBD_STORAGE_fops->GetCapacity(Lun, &BlkNum, &BlkSize) != 0)
238  {
239  SCSI_SenseCode(Lun,
240  NOT_READY,
241  MEDIUM_NOT_PRESENT);
242  return (-1);
243  }
244  else
245  {
246  uint32_t BlkNbr = BlkNum - 1;
247 
248  MSC_BBB_Data[3] = 0x08;
249  MSC_BBB_Data[4] = (uint8_t)(BlkNbr >> 24);
250  MSC_BBB_Data[5] = (uint8_t)(BlkNbr >> 16);
251  MSC_BBB_Data[6] = (uint8_t)(BlkNbr >> 8);
252  MSC_BBB_Data[7] = (uint8_t)(BlkNbr);
253 
254  MSC_BBB_Data[8] = 0x02;
255  MSC_BBB_Data[9] = (uint8_t)(BlkSize >> 16);
256  MSC_BBB_Data[10] = (uint8_t)(BlkSize >> 8);
257  MSC_BBB_Data[11] = (uint8_t)(BlkSize);
258 
259  MSC_BBB_DataLen = 12;
260 
261  return 0;
262  }
263 }
264 
271 static int8_t SCSI_ModeSense6 (uint8_t Lun, uint8_t *params)
272 {
273  uint16_t len = 8;
274 
275  MSC_BBB_DataLen = len;
276 
277  while (len)
278  {
279  len--;
280  MSC_BBB_Data[len] = MSC_Mode_Sense6_data[len];
281  }
282 
283  return 0;
284 }
285 
292 static int8_t SCSI_ModeSense10 (uint8_t Lun, uint8_t *params)
293 {
294  uint16_t Len = 8;
295 
296  MSC_BBB_DataLen = Len;
297 
298  while (Len)
299  {
300  Len--;
301  MSC_BBB_Data[Len] = MSC_Mode_Sense10_data[Len];
302  }
303 
304  return 0;
305 }
306 
313 static int8_t SCSI_RequestSense (uint8_t Lun, uint8_t *params)
314 {
315  uint8_t i;
316 
317  for(i = 0; i < REQUEST_SENSE_DATA_LEN; i++)
318  {
319  MSC_BBB_Data[i] = 0;
320  }
321 
322  MSC_BBB_Data[0] = 0x70;
323  MSC_BBB_Data[7] = REQUEST_SENSE_DATA_LEN - 6;
324 
325  if((SCSI_Sense_Head != SCSI_Sense_Tail))
326  {
327  MSC_BBB_Data[2] = SCSI_Sense[SCSI_Sense_Head].SenseKey;
328  MSC_BBB_Data[12] = SCSI_Sense[SCSI_Sense_Head].ASCQ;
329  MSC_BBB_Data[13] = SCSI_Sense[SCSI_Sense_Head].ASC;
330 
331  SCSI_Sense_Head++;
332 
333  if (SCSI_Sense_Head == SENSE_LIST_DEEPTH)
334  {
335  SCSI_Sense_Head = 0;
336  }
337  }
338 
339  MSC_BBB_DataLen = MIN(REQUEST_SENSE_DATA_LEN, params[4]);
340 
341  return 0;
342 }
343 
351 void SCSI_SenseCode (uint8_t Lun, uint8_t SKey, uint8_t ASC)
352 {
353  SCSI_Sense[SCSI_Sense_Tail].SenseKey = SKey;
354  SCSI_Sense[SCSI_Sense_Tail].ASC = ASC << 8;
355  SCSI_Sense_Tail++;
356 
357  if (SCSI_Sense_Tail == SENSE_LIST_DEEPTH)
358  {
359  SCSI_Sense_Tail = 0;
360  }
361 }
362 
369 static int8_t SCSI_StartStopUnit(uint8_t Lun, uint8_t *params)
370 {
371  MSC_BBB_DataLen = 0;
372 
373  return 0;
374 }
375 
382 static int8_t SCSI_AllowMediumRemoval(uint8_t Lun, uint8_t *params)
383 {
384  MSC_BBB_DataLen = 0;
385 
386  return 0;
387 }
388 
395 static int8_t SCSI_Read10(uint8_t Lun, uint8_t *params)
396 {
397  if(MSC_BBB_State == BBB_IDLE)
398  {
399  /* Direction is from device to host */
400  if ((MSC_BBB_cbw.bmCBWFlags & 0x80) != 0x80)
401  {
402  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
403  ILLEGAL_REQUEST,
404  INVALID_CDB);
405  return -1;
406  }
407 
408  if(USBD_STORAGE_fops->IsReady(Lun) != 0)
409  {
410  SCSI_SenseCode(Lun,
411  NOT_READY,
412  MEDIUM_NOT_PRESENT);
413  return -1;
414  }
415 
416  SCSI_blk_addr = (params[2] << 24) | (params[3] << 16) | \
417  (params[4] << 8) | params[5];
418 
419  SCSI_blk_len = (params[7] << 8) | params[8];
420 
421  if(SCSI_CheckAddressRange(Lun, SCSI_blk_addr, SCSI_blk_len) < 0)
422  {
423  return -1; /* error */
424  }
425 
426  MSC_BBB_State = BBB_DATA_IN;
427  SCSI_blk_addr *= SCSI_blk_size;
428  SCSI_blk_len *= SCSI_blk_size;
429 
430  /* cases 4,5 : Hi <> Dn */
431  if (MSC_BBB_cbw.dCBWDataTransferLength != SCSI_blk_len)
432  {
433  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
434  ILLEGAL_REQUEST,
435  INVALID_CDB);
436 
437  return -1;
438  }
439  }
440 
441  MSC_BBB_DataLen = MSC_MEDIA_PACKET_SIZE;
442 
443  return SCSI_ProcessRead(Lun);
444 }
445 
452 static int8_t SCSI_Write10 (uint8_t Lun, uint8_t *params)
453 {
454  if (MSC_BBB_State == BBB_IDLE) /* Idle */
455  {
456  /* case 8 : Hi <> Do */
457  if ((MSC_BBB_cbw.bmCBWFlags & 0x80) == 0x80)
458  {
459  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
460  ILLEGAL_REQUEST,
461  INVALID_CDB);
462 
463  return -1;
464  }
465 
466  /* Check whether Media is ready */
467  if(USBD_STORAGE_fops->IsReady(Lun) !=0)
468  {
469  SCSI_SenseCode(Lun,
470  NOT_READY,
471  MEDIUM_NOT_PRESENT);
472 
473  return -1;
474  }
475 
476  /* Check If media is write-protected */
477  if(USBD_STORAGE_fops->IsWriteProtected(Lun) !=0)
478  {
479  SCSI_SenseCode(Lun,
480  NOT_READY,
481  WRITE_PROTECTED);
482 
483  return -1;
484  }
485 
486  SCSI_blk_addr = (params[2] << 24) | (params[3] << 16) | \
487  (params[4] << 8) | params[5];
488 
489  SCSI_blk_len = (params[7] << 8) | params[8];
490 
491  /* check if LBA address is in the right range */
492  if(SCSI_CheckAddressRange(Lun, SCSI_blk_addr, SCSI_blk_len) < 0)
493  {
494  return -1; /* error */
495  }
496 
497  SCSI_blk_addr *= SCSI_blk_size;
498  SCSI_blk_len *= SCSI_blk_size;
499 
500  /* cases 3,11,13 : Hn,Ho <> D0 */
501  if (MSC_BBB_cbw.dCBWDataTransferLength != SCSI_blk_len)
502  {
503  SCSI_SenseCode(MSC_BBB_cbw.bCBWLUN,
504  ILLEGAL_REQUEST,
505  INVALID_CDB);
506 
507  return -1;
508  }
509 
510  /* Prepare EP to receive first data packet */
511  MSC_BBB_State = BBB_DATA_OUT;
512  USB_EP_Rx (cdev,
513  MSC_OUT_EP,
514  MSC_BBB_Data,
515  MIN (SCSI_blk_len, MSC_MEDIA_PACKET_SIZE));
516  }
517  else /* Write Process ongoing */
518  {
519  return SCSI_ProcessWrite(Lun);
520  }
521 
522  return 0;
523 }
524 
525 
532 static int8_t SCSI_Verify10 (uint8_t Lun, uint8_t *params)
533 {
534  if ((params[1] & 0x02) == 0x02)
535  {
536  SCSI_SenseCode(Lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
537 
538  return -1; /* Error, Verify Mode Not supported*/
539  }
540 
541  if(SCSI_CheckAddressRange(Lun, SCSI_blk_addr, SCSI_blk_len) < 0)
542  {
543  return -1; /* error */
544  }
545 
546  MSC_BBB_DataLen = 0;
547 
548  return 0;
549 }
550 
558 static int8_t SCSI_CheckAddressRange (uint8_t Lun, uint32_t BlkOffset, uint16_t BlkNbr)
559 {
560  if ((BlkOffset + BlkNbr) > SCSI_blk_nbr)
561  {
562  SCSI_SenseCode(Lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE);
563 
564  return -1;
565  }
566 
567  return 0;
568 }
569 
575 /* static */ int8_t SCSI_ProcessRead (uint8_t Lun)
576 {
577  uint32_t len;
578 
579  len = MIN(SCSI_blk_len, MSC_MEDIA_PACKET_SIZE);
580 
581  if(USBD_STORAGE_fops->Read(Lun,
582  MSC_BBB_Data,
583  SCSI_blk_addr,
584  len / SCSI_blk_size) < 0)
585  {
586  SCSI_SenseCode(Lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR);
587 
588  return -1;
589  }
590 
591  USB_EP_Tx (cdev,
592  MSC_IN_EP,
593  MSC_BBB_Data,
594  len);
595 
596  SCSI_blk_addr += len;
597  SCSI_blk_len -= len;
598 
599  /* case 6 : Hi = Di */
600  MSC_BBB_csw.dCSWDataResidue -= len;
601 
602  if (SCSI_blk_len == 0)
603  {
604  MSC_BBB_State = BBB_LAST_DATA_IN;
605  }
606 
607  return 0;
608 }
609 
615 /* static */ int8_t SCSI_ProcessWrite (uint8_t Lun)
616 {
617  uint32_t len = MIN(SCSI_blk_len, MSC_MEDIA_PACKET_SIZE);
618 
619  if(USBD_STORAGE_fops->Write(Lun,
620  MSC_BBB_Data,
621  SCSI_blk_addr,
622  len / SCSI_blk_size) < 0)
623  {
624  SCSI_SenseCode(Lun, HARDWARE_ERROR, WRITE_FAULT);
625 
626  return -1;
627  }
628 
629  SCSI_blk_addr += len;
630  SCSI_blk_len -= len;
631 
632  /* case 12 : Ho = Do */
633  MSC_BBB_csw.dCSWDataResidue -= len;
634 
635  if (SCSI_blk_len == 0)
636  {
637  MSC_BBB_SendCSW (cdev, CSW_CMD_PASSED);
638  }
639  else
640  {
641  /* Prepare EP to Receive next packet */
642  USB_EP_Rx (cdev,
643  MSC_OUT_EP,
644  MSC_BBB_Data,
645  MIN (SCSI_blk_len, MSC_MEDIA_PACKET_SIZE));
646  }
647 
648  return 0;
649 }
650 
656 static int8_t SCSI_Format_Cmd (uint8_t Lun)
657 {
658  return 0;
659 }
660 
661 /************************ (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:376
void MSC_BBB_SendCSW(USB_DEVICE_HANDLE *pudev, uint8_t CSW_Status)
Send the CSW(command status wrapper)
Definition: usbd_msc_bot.c:202
int8_t SCSI_ProcessRead(uint8_t Lun)
Handle Read Process.
int8_t SCSI_ProcessWrite(uint8_t Lun)
Handle write process.
Header file for the usbd_msc_scsi.c file.
void SCSI_SenseCode(uint8_t Lun, uint8_t SKey, uint8_t ASC)
Load the last error code in the error list.
int8_t SCSI_ProcessCmd(USB_DEVICE_HANDLE *pudev, uint8_t Lun, uint8_t *params)
Process SCSI commands.
Definition: usbd_msc_scsi.c:57
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:336
Generated by   doxygen 1.8.10