9cedc7be667feabeb5b32cbdda08fe083b5382d6
[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 // Capacity List Header
310 // [0] Reserved
311 // [1] Reserved
312 // [2] Reserved
313
314 hmsc->bot_data[3] = 0x08; // Capacity List Length (8 bytes, 1 descriptor)
315
316 // Number of blocks. MAXIMUM
317 // 0x400000 is 2TB worth of 512 blocks.
318 hmsc->bot_data[4] = 0x00;
319 hmsc->bot_data[5] = 0x3F;
320 hmsc->bot_data[6] = 0xFF;
321 hmsc->bot_data[7] = 0xFF;
322
323 hmsc->bot_data[8] = 0x03; // Descriptor code - No media.
324 hmsc->bot_data[9] = 0x00;
325 hmsc->bot_data[10] = 0x02; // 0x200 512 bytes
326 hmsc->bot_data[11] = 0x00;
327 }
328 else
329 {
330 hmsc->bot_data[3] = 0x08;
331 hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1) >> 24);
332 hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1) >> 16);
333 hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1) >> 8);
334 hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1);
335
336 hmsc->bot_data[8] = 0x02; // Descriptor code - Formatted media
337 hmsc->bot_data[9] = (uint8_t)(blk_size >> 16);
338 hmsc->bot_data[10] = (uint8_t)(blk_size >> 8);
339 hmsc->bot_data[11] = (uint8_t)(blk_size);
340 }
341
342 hmsc->bot_data_length = 12;
343 return 0;
344 }
345
346 /**
347 * @brief SCSI_ModeSense6
348 * Process Mode Sense6 command
349 * @param lun: Logical unit number
350 * @param params: Command parameters
351 * @retval status
352 */
353 static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
354 {
355 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
356 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
357
358 uint16_t len = 8 ;
359 hmsc->bot_data_length = len;
360
361 while (len)
362 {
363 len--;
364 hmsc->bot_data[len] = MSC_Mode_Sense6_data[len];
365 }
366 return 0;
367 }
368
369 /**
370 * @brief SCSI_ModeSense10
371 * Process Mode Sense10 command
372 * @param lun: Logical unit number
373 * @param params: Command parameters
374 * @retval status
375 */
376 static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
377 {
378 uint16_t len = 8;
379 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
380 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
381
382 hmsc->bot_data_length = len;
383
384 while (len)
385 {
386 len--;
387 hmsc->bot_data[len] = MSC_Mode_Sense10_data[len];
388 }
389 return 0;
390 }
391
392 /**
393 * @brief SCSI_RequestSense
394 * Process Request Sense command
395 * @param lun: Logical unit number
396 * @param params: Command parameters
397 * @retval status
398 */
399
400 static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
401 {
402 uint8_t i;
403 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
404 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
405
406 for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++)
407 {
408 hmsc->bot_data[i] = 0;
409 }
410
411 hmsc->bot_data[0] = 0x70;
412 hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6;
413
414 if((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) {
415
416 hmsc->bot_data[2] = hmsc->scsi_sense[hmsc->scsi_sense_head].Skey;
417 hmsc->bot_data[12] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ;
418 hmsc->bot_data[13] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC;
419 hmsc->scsi_sense_head++;
420
421 if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH)
422 {
423 hmsc->scsi_sense_head = 0;
424 }
425 }
426 hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN;
427
428 if (params[4] <= REQUEST_SENSE_DATA_LEN)
429 {
430 hmsc->bot_data_length = params[4];
431 }
432 return 0;
433 }
434
435 /**
436 * @brief SCSI_SenseCode
437 * Load the last error code in the error list
438 * @param lun: Logical unit number
439 * @param sKey: Sense Key
440 * @param ASC: Additional Sense Key
441 * @retval none
442
443 */
444 void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
445 {
446 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
447 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
448
449 hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey;
450 hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8;
451 hmsc->scsi_sense_tail++;
452 if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH)
453 {
454 hmsc->scsi_sense_tail = 0;
455 }
456 }
457 /**
458 * @brief SCSI_StartStopUnit
459 * Process Start Stop Unit command
460 * @param lun: Logical unit number
461 * @param params: Command parameters
462 * @retval status
463 */
464 static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
465 {
466 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
467 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
468
469 hmsc->bot_data_length = 0;
470 return 0;
471 }
472
473 /**
474 * @brief SCSI_Read10
475 * Process Read10 command
476 * @param lun: Logical unit number
477 * @param params: Command parameters
478 * @retval status
479 */
480 static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
481 {
482 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
483 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
484
485 if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
486 {
487
488 /* case 10 : Ho <> Di */
489
490 if ((hmsc->cbw.bmFlags & 0x80) != 0x80)
491 {
492 SCSI_SenseCode(pdev,
493 hmsc->cbw.bLUN,
494 ILLEGAL_REQUEST,
495 INVALID_CDB);
496 return -1;
497 }
498
499 if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
500 {
501 SCSI_SenseCode(pdev,
502 lun,
503 NOT_READY,
504 MEDIUM_NOT_PRESENT);
505 return -1;
506 }
507
508 hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | \
509 ((uint32_t)params[3] << 16) | \
510 ((uint32_t)params[4] << 8) | \
511 (uint32_t)params[5];
512
513 hmsc->scsi_blk_len = ((uint32_t)params[7] << 8) | \
514 (uint32_t)params[8];
515
516
517
518 if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)
519 {
520 return -1; /* error */
521 }
522
523 hmsc->bot_state = USBD_BOT_DATA_IN;
524
525 /* cases 4,5 : Hi <> Dn */
526 if (hmsc->cbw.dDataLength != (hmsc->scsi_blk_len * hmsc->scsi_blk_size))
527 {
528 SCSI_SenseCode(pdev,
529 hmsc->cbw.bLUN,
530 ILLEGAL_REQUEST,
531 INVALID_CDB);
532 return -1;
533 }
534 }
535 hmsc->bot_data_length = S2S_MSC_MEDIA_PACKET;
536
537 return SCSI_ProcessRead(pdev, lun);
538 }
539
540 /**
541 * @brief SCSI_Write10
542 * Process Write10 command
543 * @param lun: Logical unit number
544 * @param params: Command parameters
545 * @retval status
546 */
547
548 static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
549 {
550 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
551 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
552 uint32_t len;
553
554 if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
555 {
556 /* case 8 : Hi <> Do */
557
558 if ((hmsc->cbw.bmFlags & 0x80) == 0x80)
559 {
560 SCSI_SenseCode(pdev,
561 hmsc->cbw.bLUN,
562 ILLEGAL_REQUEST,
563 INVALID_CDB);
564 return -1;
565 }
566
567 /* Check whether Media is ready */
568 if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )
569 {
570 SCSI_SenseCode(pdev,
571 lun,
572 NOT_READY,
573 MEDIUM_NOT_PRESENT);
574 return -1;
575 }
576
577 /* Check If media is write-protected */
578 if(((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) !=0 )
579 {
580 SCSI_SenseCode(pdev,
581 lun,
582 NOT_READY,
583 WRITE_PROTECTED);
584 return -1;
585 }
586
587
588 hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | \
589 ((uint32_t)params[3] << 16) | \
590 ((uint32_t)params[4] << 8) | \
591 (uint32_t)params[5];
592 hmsc->scsi_blk_len = ((uint32_t)params[7] << 8) | \
593 (uint32_t)params[8];
594
595 /* check if LBA address is in the right range */
596 if(SCSI_CheckAddressRange(pdev,
597 lun,
598 hmsc->scsi_blk_addr,
599 hmsc->scsi_blk_len) < 0)
600 {
601 return -1; /* error */
602 }
603
604 len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
605
606 /* cases 3,11,13 : Hn,Ho <> D0 */
607 if (hmsc->cbw.dDataLength != len)
608 {
609 SCSI_SenseCode(pdev,
610 hmsc->cbw.bLUN,
611 ILLEGAL_REQUEST,
612 INVALID_CDB);
613 return -1;
614 }
615
616 len = MIN(len, S2S_MSC_MEDIA_PACKET);
617
618 /* Prepare EP to receive first data packet */
619 hmsc->bot_state = USBD_BOT_DATA_OUT;
620 USBD_LL_PrepareReceive (pdev,
621 MSC_EPOUT_ADDR,
622 hmsc->bot_data,
623 len);
624 }
625 else /* Write Process ongoing */
626 {
627 return SCSI_ProcessWrite(pdev, lun);
628 }
629 return 0;
630 }
631
632
633 /**
634 * @brief SCSI_Verify10
635 * Process Verify10 command
636 * @param lun: Logical unit number
637 * @param params: Command parameters
638 * @retval status
639 */
640
641 static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
642 {
643 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
644 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
645
646 if ((params[1]& 0x02) == 0x02)
647 {
648 SCSI_SenseCode (pdev,
649 lun,
650 ILLEGAL_REQUEST,
651 INVALID_FIELED_IN_COMMAND);
652 return -1; /* Error, Verify Mode Not supported*/
653 }
654
655 if(SCSI_CheckAddressRange(pdev,
656 lun,
657 hmsc->scsi_blk_addr,
658 hmsc->scsi_blk_len) < 0)
659 {
660 return -1; /* error */
661 }
662 hmsc->bot_data_length = 0;
663 return 0;
664 }
665
666 /**
667 * @brief SCSI_CheckAddressRange
668 * Check address range
669 * @param lun: Logical unit number
670 * @param blk_offset: first block address
671 * @param blk_nbr: number of block to be processed
672 * @retval status
673 */
674 static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr)
675 {
676 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
677 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
678
679 // michael@codesrc.com: Re-check block limits in cause we have different values
680 // for different LUN's.
681 uint32_t blkNbr;
682 uint16_t blkSize;
683 if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blkNbr, &blkSize) != 0)
684 {
685 SCSI_SenseCode(pdev,
686 lun,
687 NOT_READY,
688 MEDIUM_NOT_PRESENT);
689 return -1;
690 }
691 // global variables. wooo
692 hmsc->scsi_blk_size = blkSize;
693 hmsc->scsi_blk_nbr = blkNbr;
694
695 if ((blk_offset + blk_nbr) > blkNbr )
696 {
697 SCSI_SenseCode(pdev,
698 lun,
699 ILLEGAL_REQUEST,
700 ADDRESS_OUT_OF_RANGE);
701 return -1;
702 }
703 return 0;
704 }
705
706 /**
707 * @brief SCSI_ProcessRead
708 * Handle Read Process
709 * @param lun: Logical unit number
710 * @retval status
711 */
712 static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun)
713 {
714 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
715 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
716
717 uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
718
719 len = MIN(len, S2S_MSC_MEDIA_PACKET);
720
721 // TODO there is a dcache issue here.
722 // work out how, and when, to flush cashes between sdio dma and usb dma
723 memset (hmsc->bot_data, 0xAA, len);
724 if( ((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun ,
725 hmsc->bot_data,
726 hmsc->scsi_blk_addr,
727 len / hmsc->scsi_blk_size) < 0)
728 {
729
730 SCSI_SenseCode(pdev,
731 lun,
732 HARDWARE_ERROR,
733 UNRECOVERED_READ_ERROR);
734 return -1;
735 }
736
737
738 USBD_LL_Transmit (pdev,
739 MSC_EPIN_ADDR,
740 hmsc->bot_data,
741 len);
742
743 hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size);
744 hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size);
745
746 /* case 6 : Hi = Di */
747 hmsc->csw.dDataResidue -= len;
748
749 if (hmsc->scsi_blk_len == 0)
750 {
751 hmsc->bot_state = USBD_BOT_LAST_DATA_IN;
752 }
753 return 0;
754 }
755
756 /**
757 * @brief SCSI_ProcessWrite
758 * Handle Write Process
759 * @param lun: Logical unit number
760 * @retval status
761 */
762
763 static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun)
764 {
765 USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
766 USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
767
768 uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;
769
770 len = MIN(len, S2S_MSC_MEDIA_PACKET);
771
772 if(((USBD_StorageTypeDef *)pdev->pUserData)->Write(lun ,
773 hmsc->bot_data,
774 hmsc->scsi_blk_addr,
775 len / hmsc->scsi_blk_size) < 0)
776 {
777 SCSI_SenseCode(pdev,
778 lun,
779 HARDWARE_ERROR,
780 WRITE_FAULT);
781 return -1;
782 }
783
784
785 hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size);
786 hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size);
787
788 /* case 12 : Ho = Do */
789 hmsc->csw.dDataResidue -= len;
790
791 if (hmsc->scsi_blk_len == 0)
792 {
793 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
794 }
795 else
796 {
797 len = MIN((hmsc->scsi_blk_len * hmsc->scsi_blk_size), S2S_MSC_MEDIA_PACKET);
798 /* Prepare EP to Receive next packet */
799 USBD_LL_PrepareReceive (pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len);
800 }
801
802 return 0;
803 }
804 /**
805 * @}
806 */
807
808
809 /**
810 * @}
811 */
812
813
814 /**
815 * @}
816 */
817
818 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/