aa0880c20a8c72d77dbf51cb0886517e48c52773
[SCSI2SD-V6.git] / src / firmware / usb_device / usbd_msc_scsi.c
1 /**
2   ******************************************************************************
3   * @file    usbd_msc_scsi.c
4   * @author  MCD Application Team
5   * @version V2.4.1
6   * @date    19-June-2015
7   * @brief   This file provides all the USBD SCSI layer functions.
8   ******************************************************************************
9   * @attention
10   *
11   * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
12   *
13   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
14   * You may not use this file except in compliance with the License.
15   * You may obtain a copy of the License at:
16   *
17   *        http://www.st.com/software_license_agreement_liberty_v2
18   *
19   * Unless required by applicable law or agreed to in writing, software 
20   * distributed under the License is distributed on an "AS IS" BASIS, 
21   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22   * See the License for the specific language governing permissions and
23   * limitations under the License.
24   *
25   ******************************************************************************
26   */ 
27
28 /* Includes ------------------------------------------------------------------*/
29 #include "usbd_composite.h"
30 #include "usbd_msc_bot.h"
31 #include "usbd_msc_scsi.h"
32 #include "usbd_msc.h"
33 #include "usbd_msc_data.h"
34
35
36
37 /** @addtogroup STM32_USB_DEVICE_LIBRARY
38   * @{
39   */
40
41
42 /** @defgroup MSC_SCSI 
43   * @brief Mass storage SCSI layer module
44   * @{
45   */ 
46
47 /** @defgroup MSC_SCSI_Private_TypesDefinitions
48   * @{
49   */ 
50 /**
51   * @}
52   */ 
53
54
55 /** @defgroup MSC_SCSI_Private_Defines
56   * @{
57   */ 
58
59 /**
60   * @}
61   */ 
62
63
64 /** @defgroup MSC_SCSI_Private_Macros
65   * @{
66   */ 
67 /**
68   * @}
69   */ 
70
71
72 /** @defgroup MSC_SCSI_Private_Variables
73   * @{
74   */ 
75
76 /**
77   * @}
78   */ 
79
80
81 /** @defgroup MSC_SCSI_Private_FunctionPrototypes
82   * @{
83   */ 
84 static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params);
85 static int8_t SCSI_Inquiry(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params);
86 static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params);
87 static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params);
88 static int8_t SCSI_RequestSense (USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params);
89 static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params);
90 static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params);
91 static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params);
92 static int8_t SCSI_Write10(USBD_HandleTypeDef  *pdev, uint8_t lun , uint8_t *params);
93 static int8_t SCSI_Read10(USBD_HandleTypeDef  *pdev, uint8_t lun , uint8_t *params);
94 static int8_t SCSI_Verify10(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params);
95 static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef  *pdev, 
96                                       uint8_t lun , 
97                                       uint32_t blk_offset , 
98                                       uint16_t blk_nbr);
99 static int8_t SCSI_ProcessRead (USBD_HandleTypeDef  *pdev,
100                                 uint8_t lun);
101
102 static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef  *pdev,
103                                  uint8_t lun);
104 /**
105   * @}
106   */ 
107
108
109 /** @defgroup MSC_SCSI_Private_Functions
110   * @{
111   */ 
112
113
114 /**
115 * @brief  SCSI_ProcessCmd
116 *         Process SCSI commands
117 * @param  pdev: device instance
118 * @param  lun: Logical unit number
119 * @param  params: Command parameters
120 * @retval status
121 */
122 int8_t SCSI_ProcessCmd(USBD_HandleTypeDef  *pdev,
123                            uint8_t lun, 
124                            uint8_t *params)
125 {
126   
127   switch (params[0])
128   {
129   case SCSI_TEST_UNIT_READY:
130     return SCSI_TestUnitReady(pdev, lun, params);
131     
132   case SCSI_REQUEST_SENSE:
133     return SCSI_RequestSense (pdev, lun, params);
134   case SCSI_INQUIRY:
135     return SCSI_Inquiry(pdev, lun, params);
136     
137   case SCSI_START_STOP_UNIT:
138     return SCSI_StartStopUnit(pdev, lun, params);
139     
140   case SCSI_ALLOW_MEDIUM_REMOVAL:
141     return SCSI_StartStopUnit(pdev, lun, params);
142     
143   case SCSI_MODE_SENSE6:
144     return SCSI_ModeSense6 (pdev, lun, params);
145     
146   case SCSI_MODE_SENSE10:
147     return SCSI_ModeSense10 (pdev, lun, params);
148     
149   case SCSI_READ_FORMAT_CAPACITIES:
150     return SCSI_ReadFormatCapacity(pdev, lun, params);
151     
152   case SCSI_READ_CAPACITY10:
153     return SCSI_ReadCapacity10(pdev, lun, params);
154     
155   case SCSI_READ10:
156     return SCSI_Read10(pdev, lun, params); 
157     
158   case SCSI_WRITE10:
159     return SCSI_Write10(pdev, lun, params);
160     
161   case SCSI_VERIFY10:
162     return SCSI_Verify10(pdev, lun, params);
163     
164   default:
165     SCSI_SenseCode(pdev, 
166                    lun,
167                    ILLEGAL_REQUEST, 
168                    INVALID_CDB);    
169     return -1;
170   }
171 }
172
173
174 /**
175 * @brief  SCSI_TestUnitReady
176 *         Process SCSI Test Unit Ready Command
177 * @param  lun: Logical unit number
178 * @param  params: Command parameters
179 * @retval status
180 */
181 static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params)
182 {
183         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
184         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
185     
186   /* case 9 : Hi > D0 */
187   if (hmsc->cbw.dDataLength != 0)
188   {
189     SCSI_SenseCode(pdev,
190                    hmsc->cbw.bLUN, 
191                    ILLEGAL_REQUEST, 
192                    INVALID_CDB);
193     return -1;
194   }  
195   
196   if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
197   {
198     SCSI_SenseCode(pdev,
199                    lun,
200                    NOT_READY, 
201                    MEDIUM_NOT_PRESENT);
202     
203     hmsc->bot_state = USBD_BOT_NO_DATA;
204     return -1;
205   } 
206   hmsc->bot_data_length = 0;
207   return 0;
208 }
209
210 /**
211 * @brief  SCSI_Inquiry
212 *         Process Inquiry command
213 * @param  lun: Logical unit number
214 * @param  params: Command parameters
215 * @retval status
216 */
217 static int8_t  SCSI_Inquiry(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params)
218 {
219   uint8_t* pPage;
220   uint16_t len;
221
222         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
223         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
224   
225   if (params[1] & 0x01)/*Evpd is set*/
226   {
227     pPage = (uint8_t *)MSC_Page00_Inquiry_Data;
228     len = LENGTH_INQUIRY_PAGE00;
229     if (params[4] <= len)
230     {
231       len = params[4];
232     }
233         memcpy(hmsc->bot_data, pPage, len);
234   }
235   else
236   {
237         len = ((USBD_StorageTypeDef *)pdev->pUserData)->Inquiry(lun, hmsc->bot_data, params[4]);
238     
239     if (params[4] <= len)
240     {
241       len = params[4];
242     }
243   }
244   hmsc->bot_data_length = len;
245
246   return 0;
247 }
248
249 /**
250 * @brief  SCSI_ReadCapacity10
251 *         Process Read Capacity 10 command
252 * @param  lun: Logical unit number
253 * @param  params: Command parameters
254 * @retval status
255 */
256 static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params)
257 {
258         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
259         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
260   
261   if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0)
262   {
263     SCSI_SenseCode(pdev,
264                    lun,
265                    NOT_READY, 
266                    MEDIUM_NOT_PRESENT);
267     return -1;
268   } 
269   else
270   {
271     
272     hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 24);
273     hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 16);
274     hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >>  8);
275     hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1);
276     
277     hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >>  24);
278     hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >>  16);
279     hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >>  8);
280     hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size);
281     
282     hmsc->bot_data_length = 8;
283     return 0;
284   }
285 }
286 /**
287 * @brief  SCSI_ReadFormatCapacity
288 *         Process Read Format Capacity command
289 * @param  lun: Logical unit number
290 * @param  params: Command parameters
291 * @retval status
292 */
293 static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params)
294 {
295         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
296         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
297   
298   uint16_t blk_size;
299   uint32_t blk_nbr;
300   uint16_t i;
301   
302   for(i=0 ; i < 12 ; i++) 
303   {
304     hmsc->bot_data[i] = 0;
305   }
306   
307   if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blk_nbr, &blk_size) != 0)
308   {
309     SCSI_SenseCode(pdev,
310                    lun,
311                    NOT_READY, 
312                    MEDIUM_NOT_PRESENT);
313     return -1;
314   } 
315   else
316   {
317     hmsc->bot_data[3] = 0x08;
318     hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1) >> 24);
319     hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1) >> 16);
320     hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1) >>  8);
321     hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1);
322     
323     hmsc->bot_data[8] = 0x02;
324     hmsc->bot_data[9] = (uint8_t)(blk_size >>  16);
325     hmsc->bot_data[10] = (uint8_t)(blk_size >>  8);
326     hmsc->bot_data[11] = (uint8_t)(blk_size);
327     
328     hmsc->bot_data_length = 12;
329     return 0;
330   }
331 }
332 /**
333 * @brief  SCSI_ModeSense6
334 *         Process Mode Sense6 command
335 * @param  lun: Logical unit number
336 * @param  params: Command parameters
337 * @retval status
338 */
339 static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params)
340 {
341         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
342         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
343
344   uint16_t len = 8 ;
345   hmsc->bot_data_length = len;
346   
347   while (len) 
348   {
349     len--;
350     hmsc->bot_data[len] = MSC_Mode_Sense6_data[len];
351   }
352   return 0;
353 }
354
355 /**
356 * @brief  SCSI_ModeSense10
357 *         Process Mode Sense10 command
358 * @param  lun: Logical unit number
359 * @param  params: Command parameters
360 * @retval status
361 */
362 static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params)
363 {
364   uint16_t len = 8;
365         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
366         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
367   
368   hmsc->bot_data_length = len;
369
370   while (len) 
371   {
372     len--;
373     hmsc->bot_data[len] = MSC_Mode_Sense10_data[len];
374   }
375   return 0;
376 }
377
378 /**
379 * @brief  SCSI_RequestSense
380 *         Process Request Sense command
381 * @param  lun: Logical unit number
382 * @param  params: Command parameters
383 * @retval status
384 */
385
386 static int8_t SCSI_RequestSense (USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params)
387 {
388   uint8_t i;
389         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
390         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
391   
392   for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++) 
393   {
394     hmsc->bot_data[i] = 0;
395   }
396   
397   hmsc->bot_data[0]     = 0x70;         
398   hmsc->bot_data[7]     = REQUEST_SENSE_DATA_LEN - 6;   
399   
400   if((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) {
401     
402     hmsc->bot_data[2]     = hmsc->scsi_sense[hmsc->scsi_sense_head].Skey;               
403     hmsc->bot_data[12]    = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ;   
404     hmsc->bot_data[13]    = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC;    
405     hmsc->scsi_sense_head++;
406     
407     if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH)
408     {
409       hmsc->scsi_sense_head = 0;
410     }
411   }
412   hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN;  
413   
414   if (params[4] <= REQUEST_SENSE_DATA_LEN)
415   {
416     hmsc->bot_data_length = params[4];
417   }
418   return 0;
419 }
420
421 /**
422 * @brief  SCSI_SenseCode
423 *         Load the last error code in the error list
424 * @param  lun: Logical unit number
425 * @param  sKey: Sense Key
426 * @param  ASC: Additional Sense Key
427 * @retval none
428
429 */
430 void SCSI_SenseCode(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
431 {
432         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
433         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
434   
435   hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey  = sKey;
436   hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8;
437   hmsc->scsi_sense_tail++;
438   if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH)
439   {
440     hmsc->scsi_sense_tail = 0;
441   }
442 }
443 /**
444 * @brief  SCSI_StartStopUnit
445 *         Process Start Stop Unit command
446 * @param  lun: Logical unit number
447 * @param  params: Command parameters
448 * @retval status
449 */
450 static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef  *pdev, uint8_t lun, uint8_t *params)
451 {
452         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
453         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
454
455   hmsc->bot_data_length = 0;
456   return 0;
457 }
458
459 /**
460 * @brief  SCSI_Read10
461 *         Process Read10 command
462 * @param  lun: Logical unit number
463 * @param  params: Command parameters
464 * @retval status
465 */
466 static int8_t SCSI_Read10(USBD_HandleTypeDef  *pdev, uint8_t lun , uint8_t *params)
467 {
468         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
469         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
470   
471   if(hmsc->bot_state == USBD_BOT_IDLE)  /* Idle */
472   {
473     
474     /* case 10 : Ho <> Di */
475     
476     if ((hmsc->cbw.bmFlags & 0x80) != 0x80)
477     {
478       SCSI_SenseCode(pdev,
479                      hmsc->cbw.bLUN, 
480                      ILLEGAL_REQUEST, 
481                      INVALID_CDB);
482       return -1;
483     }    
484     
485     if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
486     {
487       SCSI_SenseCode(pdev,
488                      lun,
489                      NOT_READY, 
490                      MEDIUM_NOT_PRESENT);
491       return -1;
492     } 
493     
494     hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | \
495       ((uint32_t)params[3] << 16) | \
496         ((uint32_t)params[4] <<  8) | \
497           (uint32_t)params[5];
498     
499     hmsc->scsi_blk_len =  ((uint32_t)params[7] <<  8) | \
500       (uint32_t)params[8];  
501     
502     
503     
504     if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)
505     {
506       return -1; /* error */
507     }
508     
509     hmsc->bot_state = USBD_BOT_DATA_IN;
510     
511     /* cases 4,5 : Hi <> Dn */
512     if (hmsc->cbw.dDataLength != (hmsc->scsi_blk_len * hmsc->scsi_blk_size))
513     {
514       SCSI_SenseCode(pdev,
515                      hmsc->cbw.bLUN, 
516                      ILLEGAL_REQUEST, 
517                      INVALID_CDB);
518       return -1;
519     }
520   }
521   hmsc->bot_data_length = S2S_MSC_MEDIA_PACKET;  
522   
523   return SCSI_ProcessRead(pdev, lun);
524 }
525
526 /**
527 * @brief  SCSI_Write10
528 *         Process Write10 command
529 * @param  lun: Logical unit number
530 * @param  params: Command parameters
531 * @retval status
532 */
533
534 static int8_t SCSI_Write10 (USBD_HandleTypeDef  *pdev, uint8_t lun , uint8_t *params)
535 {
536   USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
537   USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
538   uint32_t len;
539   
540   if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
541   {
542     /* case 8 : Hi <> Do */
543     
544     if ((hmsc->cbw.bmFlags & 0x80) == 0x80)
545     {
546       SCSI_SenseCode(pdev,
547                      hmsc->cbw.bLUN, 
548                      ILLEGAL_REQUEST, 
549                      INVALID_CDB);
550       return -1;
551     }
552     
553     /* Check whether Media is ready */
554     if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
555     {
556       SCSI_SenseCode(pdev,
557                      lun,
558                      NOT_READY, 
559                      MEDIUM_NOT_PRESENT);
560       return -1;
561     } 
562     
563     /* Check If media is write-protected */
564     if(((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) !=0 )
565     {
566       SCSI_SenseCode(pdev,
567                      lun,
568                      NOT_READY, 
569                      WRITE_PROTECTED);
570       return -1;
571     } 
572     
573     
574     hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | \
575       ((uint32_t)params[3] << 16) | \
576         ((uint32_t)params[4] <<  8) | \
577           (uint32_t)params[5];
578     hmsc->scsi_blk_len = ((uint32_t)params[7] <<  8) | \
579       (uint32_t)params[8];  
580     
581     /* check if LBA address is in the right range */
582     if(SCSI_CheckAddressRange(pdev,
583                               lun,
584                               hmsc->scsi_blk_addr,
585                               hmsc->scsi_blk_len) < 0)
586     {
587       return -1; /* error */      
588     }
589
590     len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
591     
592     /* cases 3,11,13 : Hn,Ho <> D0 */
593     if (hmsc->cbw.dDataLength != len)
594     {
595       SCSI_SenseCode(pdev,
596                      hmsc->cbw.bLUN, 
597                      ILLEGAL_REQUEST, 
598                      INVALID_CDB);
599       return -1;
600     }
601
602     len = MIN(len, S2S_MSC_MEDIA_PACKET);
603     
604     /* Prepare EP to receive first data packet */
605     hmsc->bot_state = USBD_BOT_DATA_OUT;  
606     USBD_LL_PrepareReceive (pdev,
607                       MSC_EPOUT_ADDR,
608                       hmsc->bot_data, 
609                       len);  
610   }
611   else /* Write Process ongoing */
612   {
613     return SCSI_ProcessWrite(pdev, lun);
614   }
615   return 0;
616 }
617
618
619 /**
620 * @brief  SCSI_Verify10
621 *         Process Verify10 command
622 * @param  lun: Logical unit number
623 * @param  params: Command parameters
624 * @retval status
625 */
626
627 static int8_t SCSI_Verify10(USBD_HandleTypeDef  *pdev, uint8_t lun , uint8_t *params)
628 {
629         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
630         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
631   
632   if ((params[1]& 0x02) == 0x02) 
633   {
634     SCSI_SenseCode (pdev,
635                     lun, 
636                     ILLEGAL_REQUEST, 
637                     INVALID_FIELED_IN_COMMAND);
638     return -1; /* Error, Verify Mode Not supported*/
639   }
640   
641   if(SCSI_CheckAddressRange(pdev,
642                             lun, 
643                             hmsc->scsi_blk_addr, 
644                             hmsc->scsi_blk_len) < 0)
645   {
646     return -1; /* error */      
647   }
648   hmsc->bot_data_length = 0;
649   return 0;
650 }
651
652 /**
653 * @brief  SCSI_CheckAddressRange
654 *         Check address range
655 * @param  lun: Logical unit number
656 * @param  blk_offset: first block address
657 * @param  blk_nbr: number of block to be processed
658 * @retval status
659 */
660 static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef  *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr)
661 {
662         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
663         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
664
665         // michael@codesrc.com: Re-check block limits in cause we have different values
666         // for different LUN's.
667     uint32_t blkNbr;
668         uint16_t blkSize;
669         if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blkNbr, &blkSize) != 0)
670         {
671     SCSI_SenseCode(pdev,
672                    lun,
673                    NOT_READY, 
674                    MEDIUM_NOT_PRESENT);
675     return -1;
676   } 
677         // global variables. wooo
678         hmsc->scsi_blk_size = blkSize;
679         hmsc->scsi_blk_nbr = blkNbr;
680
681   if ((blk_offset + blk_nbr) > blkNbr )
682   {
683     SCSI_SenseCode(pdev,
684                    lun, 
685                    ILLEGAL_REQUEST, 
686                    ADDRESS_OUT_OF_RANGE);
687     return -1;
688   }
689   return 0;
690 }
691
692 /**
693 * @brief  SCSI_ProcessRead
694 *         Handle Read Process
695 * @param  lun: Logical unit number
696 * @retval status
697 */
698 static int8_t SCSI_ProcessRead (USBD_HandleTypeDef  *pdev, uint8_t lun)
699 {
700   USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
701   USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
702
703   uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
704
705   len = MIN(len, S2S_MSC_MEDIA_PACKET);
706
707   // TODO there is a dcache issue here.
708   // work out how, and when, to flush cashes between sdio dma and usb dma
709   memset (hmsc->bot_data, 0xAA, len);
710   if( ((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun ,
711                               hmsc->bot_data, 
712                               hmsc->scsi_blk_addr, 
713                               len / hmsc->scsi_blk_size) < 0)
714   {
715     
716     SCSI_SenseCode(pdev,
717                    lun, 
718                    HARDWARE_ERROR, 
719                    UNRECOVERED_READ_ERROR);
720     return -1; 
721   }
722   
723   
724   USBD_LL_Transmit (pdev, 
725              MSC_EPIN_ADDR,
726              hmsc->bot_data,
727              len);
728   
729   hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size);
730   hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size);
731   
732   /* case 6 : Hi = Di */
733   hmsc->csw.dDataResidue -= len;
734   
735   if (hmsc->scsi_blk_len == 0)
736   {
737     hmsc->bot_state = USBD_BOT_LAST_DATA_IN;
738   }
739   return 0;
740 }
741
742 /**
743 * @brief  SCSI_ProcessWrite
744 *         Handle Write Process
745 * @param  lun: Logical unit number
746 * @retval status
747 */
748
749 static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef  *pdev, uint8_t lun)
750 {
751   USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
752   USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
753
754   uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
755
756   len = MIN(len, S2S_MSC_MEDIA_PACKET);
757   
758   if(((USBD_StorageTypeDef *)pdev->pUserData)->Write(lun ,
759                               hmsc->bot_data, 
760                               hmsc->scsi_blk_addr, 
761                               len / hmsc->scsi_blk_size) < 0)
762   {
763     SCSI_SenseCode(pdev,
764                    lun, 
765                    HARDWARE_ERROR, 
766                    WRITE_FAULT);     
767     return -1; 
768   }
769   
770   
771   hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size);
772   hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size);
773   
774   /* case 12 : Ho = Do */
775   hmsc->csw.dDataResidue -= len;
776   
777   if (hmsc->scsi_blk_len == 0)
778   {
779     MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
780   }
781   else
782   {
783     len = MIN((hmsc->scsi_blk_len * hmsc->scsi_blk_size), S2S_MSC_MEDIA_PACKET);
784     /* Prepare EP to Receive next packet */
785     USBD_LL_PrepareReceive (pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len);
786   }
787   
788   return 0;
789 }
790 /**
791   * @}
792   */ 
793
794
795 /**
796   * @}
797   */ 
798
799
800 /**
801   * @}
802   */ 
803
804 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/