1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** USBX Component */
17 /** */
18 /** Device Storage Class */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define UX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "ux_api.h"
29 #include "ux_device_class_storage.h"
30 #include "ux_device_stack.h"
31
32 #if defined(UX_DEVICE_STANDALONE)
33
34 /* Internal static inline implements. */
35
36
37 static inline UINT _ux_device_class_storage_task_usb(UX_SLAVE_CLASS_STORAGE *storage);
38
39 static inline UINT _ux_device_class_storage_reset_wait(UX_SLAVE_CLASS_STORAGE *storage);
40 static inline VOID _ux_device_class_storage_cbw_receive(UX_SLAVE_CLASS_STORAGE *storage);
41 static inline VOID _ux_device_class_storage_cbw_process(UX_SLAVE_CLASS_STORAGE *storage);
42 static inline VOID _ux_device_class_storage_cmd_process(UX_SLAVE_CLASS_STORAGE *storage, UCHAR *cbw);
43 static inline VOID _ux_device_class_storage_data_cases_check(UX_SLAVE_CLASS_STORAGE *storage);
44 static inline VOID _ux_device_class_storage_trans_start(UX_SLAVE_CLASS_STORAGE *storage);
45 static inline UINT _ux_device_class_storage_trans_wait(UX_SLAVE_CLASS_STORAGE *storage);
46 static inline VOID _ux_device_class_storage_trans_error(UX_SLAVE_CLASS_STORAGE *storage);
47 static inline UINT _ux_device_class_storage_data_next(UX_SLAVE_CLASS_STORAGE *storage);
48
49 static inline VOID _ux_device_class_storage_halt_out(UX_SLAVE_CLASS_STORAGE *storage);
50 static inline VOID _ux_device_class_storage_halt_in(UX_SLAVE_CLASS_STORAGE *storage);
51 static inline VOID _ux_device_class_storage_halt_trans(UX_SLAVE_CLASS_STORAGE *storage);
52
53 static inline VOID _ux_device_class_storage_task_disk(UX_SLAVE_CLASS_STORAGE *storage);
54
55 static inline VOID _ux_device_class_storage_disk_start(UX_SLAVE_CLASS_STORAGE *storage);
56 static inline UINT _ux_device_class_storage_disk_wait(UX_SLAVE_CLASS_STORAGE *storage);
57 static inline VOID _ux_device_class_storage_disk_next(UX_SLAVE_CLASS_STORAGE *storage);
58 static inline VOID _ux_device_class_storage_disk_read_next(UX_SLAVE_CLASS_STORAGE *storage);
59 static inline VOID _ux_device_class_storage_disk_write_next(UX_SLAVE_CLASS_STORAGE *storage);
60 static inline VOID _ux_device_class_storage_disk_error(UX_SLAVE_CLASS_STORAGE *storage);
61
62
63 /**************************************************************************/
64 /* */
65 /* FUNCTION RELEASE */
66 /* */
67 /* _ux_device_class_storage_tasks_run PORTABLE C */
68 /* 6.2.0 */
69 /* AUTHOR */
70 /* */
71 /* Chaoqiong Xiao, Microsoft Corporation */
72 /* */
73 /* DESCRIPTION */
74 /* */
75 /* This function runs tasks of the storage class. */
76 /* E.g., CBW-DATA-CSW state machine. */
77 /* */
78 /* It's for standalone mode. */
79 /* */
80 /* INPUT */
81 /* */
82 /* instance Address of storage instance */
83 /* */
84 /* OUTPUT */
85 /* */
86 /* UX_STATE_RESET Tasks suspended */
87 /* UX_STATE_IDLE Activated but no task ran */
88 /* (others > UX_STATE_IDLE) Tasks running */
89 /* */
90 /* CALLS */
91 /* */
92 /* _ux_device_class_storage_format Storage class format */
93 /* _ux_device_class_storage_inquiry Storage class inquiry */
94 /* _ux_device_class_storage_mode_select Mode select */
95 /* _ux_device_class_storage_mode_sense Mode sense */
96 /* _ux_device_class_storage_prevent_allow_media_removal */
97 /* Prevent media removal */
98 /* _ux_device_class_storage_read Read */
99 /* _ux_device_class_storage_read_capacity */
100 /* Read capacity */
101 /* _ux_device_class_storage_read_format_capacity */
102 /* Read format capacity */
103 /* _ux_device_class_storage_request_sense */
104 /* Sense request */
105 /* _ux_device_class_storage_start_stop Start/Stop */
106 /* _ux_device_class_storage_synchronize_cache */
107 /* Synchronize cache */
108 /* _ux_device_class_storage_test_ready Ready test */
109 /* _ux_device_class_storage_verify Verify */
110 /* _ux_device_class_storage_write Write */
111 /* _ux_device_stack_endpoint_stall Endpoint stall */
112 /* _ux_device_stack_interface_delete Interface delete */
113 /* _ux_device_stack_transfer_request Transfer request */
114 /* _ux_utility_long_get Get 32-bit value */
115 /* _ux_utility_memory_allocate Allocate memory */
116 /* _ux_utility_semaphore_create Create semaphore */
117 /* _ux_utility_thread_suspend Suspend thread */
118 /* */
119 /* CALLED BY */
120 /* */
121 /* Device Stack */
122 /* */
123 /* RELEASE HISTORY */
124 /* */
125 /* DATE NAME DESCRIPTION */
126 /* */
127 /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */
128 /* 10-31-2022 Chaoqiong Xiao Modified comment(s), */
129 /* improved internal logic, */
130 /* resulting in version 6.2.0 */
131 /* */
132 /**************************************************************************/
_ux_device_class_storage_tasks_run(VOID * instance)133 UINT _ux_device_class_storage_tasks_run(VOID *instance)
134 {
135
136 UX_SLAVE_CLASS_STORAGE *storage;
137 UINT status;
138
139
140 /* Get storage instance. */
141 storage = (UX_SLAVE_CLASS_STORAGE *) instance;
142
143 /* Run USB and disk tasks. */
144 status = _ux_device_class_storage_task_usb(storage);
145 _ux_device_class_storage_task_disk(storage);
146 return(status);
147 }
148
_ux_device_class_storage_task_usb(UX_SLAVE_CLASS_STORAGE * storage)149 static inline UINT _ux_device_class_storage_task_usb(UX_SLAVE_CLASS_STORAGE *storage)
150 {
151 UX_SLAVE_DEVICE *device;
152 UCHAR state;
153 UINT status;
154 INT immediate_state = UX_TRUE;
155
156
157 /* Get pointer to the device. */
158 device = &_ux_system_slave -> ux_system_slave_device;
159
160 /* Run states once. */
161 while(immediate_state)
162 {
163
164 /* General check for MSC ready. */
165 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED ||
166 storage -> ux_device_class_storage_ep_in == UX_NULL ||
167 storage -> ux_device_class_storage_ep_out == UX_NULL)
168 {
169 storage -> ux_device_class_storage_state = UX_STATE_RESET;
170 return(UX_STATE_EXIT);
171 }
172
173 /* Get current state. */
174 state = storage -> ux_device_class_storage_state;
175
176 /* Handle different state. */
177 switch(state)
178 {
179
180 case UX_STATE_RESET: /* Initial, reset. */
181 _ux_device_class_storage_cbw_receive(storage);
182
183 /* Roll back to next state directly. */
184 continue;
185
186 case UX_DEVICE_CLASS_STORAGE_STATE_RESET:
187 _ux_device_class_storage_halt_in(storage);
188 _ux_device_class_storage_halt_out(storage);
189 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_RESET_WAIT;
190
191 /* Fall through. */
192 case UX_DEVICE_CLASS_STORAGE_STATE_RESET_WAIT: /* Wait reset recovery. */
193 return _ux_device_class_storage_reset_wait(storage);
194
195 case UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START:
196 _ux_device_class_storage_trans_start(storage);
197
198 /* Fall through. */
199 case UX_DEVICE_CLASS_STORAGE_STATE_TRANS_WAIT:
200 status = _ux_device_class_storage_trans_wait(storage);
201
202 /* Fatal case. */
203 if (status < UX_STATE_ERROR)
204 {
205
206 /* USB idle. */
207 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_IDLE;
208
209 /* Disk notified with USB error. */
210 if (storage -> ux_device_class_storage_disk_state !=
211 UX_DEVICE_CLASS_STORAGE_DISK_IDLE)
212 {
213 storage -> ux_device_class_storage_disk_state =
214 UX_DEVICE_CLASS_STORAGE_DISK_USB_ERROR;
215 }
216 return(UX_STATE_WAIT);
217 }
218
219 /* Error case. */
220 if (status == UX_STATE_ERROR)
221 {
222
223 /* Stall. */
224 _ux_device_class_storage_halt_trans(storage);
225
226 /* Disk notified with USB error. */
227 if (storage -> ux_device_class_storage_disk_state !=
228 UX_DEVICE_CLASS_STORAGE_DISK_IDLE)
229 {
230 storage -> ux_device_class_storage_disk_state =
231 UX_DEVICE_CLASS_STORAGE_DISK_USB_ERROR;
232 }
233
234 /* Update residue. */
235 storage -> ux_slave_class_storage_csw_residue =
236 storage -> ux_slave_class_storage_host_length -
237 storage -> ux_device_class_storage_data_count;
238
239 /* Update the REQUEST_SENSE codes. */
240 storage -> ux_slave_class_storage_lun[
241 storage -> ux_slave_class_storage_cbw_lun].
242 ux_slave_class_storage_request_sense_status =
243 UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(0x02,0x54,0x00);
244
245 /* Issue CSW. */
246 _ux_device_class_storage_csw_send(storage,
247 storage -> ux_slave_class_storage_cbw_lun,
248 storage -> ux_device_class_storage_ep_in, 0);
249
250 return(UX_STATE_WAIT);
251 }
252
253 /* Success case. */
254 if (status == UX_STATE_NEXT)
255 {
256
257 /* Update data count. */
258 storage -> ux_device_class_storage_data_count +=
259 storage -> ux_device_class_storage_transfer ->
260 ux_slave_transfer_request_actual_length;
261
262 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_NEXT;
263 }
264
265 /* Other cases, keep waiting. */
266 return(UX_STATE_WAIT);
267
268 case UX_DEVICE_CLASS_STORAGE_STATE_TRANS_NEXT:
269
270 /* CBW received: -> CBW handle. */
271 if (storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_CBW)
272 {
273 _ux_device_class_storage_cbw_process(storage);
274
275 /* Apply command in next call anyway. */
276 return(UX_STATE_WAIT);
277 }
278
279 /* CSW sent: -> CSW done - CBW start. */
280 if (storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_CSW)
281 {
282 if (storage -> ux_slave_class_storage_csw_status == UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR)
283 {
284 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_RESET;
285 }
286 else
287 {
288 _ux_device_class_storage_cbw_receive(storage);
289 }
290 continue;
291 }
292
293 /* DATA done: -> process data. */
294 return _ux_device_class_storage_data_next(storage);
295
296 case UX_DEVICE_CLASS_STORAGE_STATE_DISK_ERROR:
297 _ux_device_class_storage_trans_error(storage);
298 continue;
299
300 case UX_DEVICE_CLASS_STORAGE_STATE_IDLE: /* Nothing to do, fall through. */
301
302 case UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT: /* Nothing to do, fall through. */
303
304 default: /* Do nothing. */
305 break;
306 }
307
308 /* Unhandled, just break the loop and do again by app call. */
309 immediate_state = UX_FALSE;
310 }
311
312 /* Unhandled state. */
313 return(UX_STATE_EXIT);
314 }
315
_ux_device_class_storage_cbw_receive(UX_SLAVE_CLASS_STORAGE * storage)316 static inline VOID _ux_device_class_storage_cbw_receive(UX_SLAVE_CLASS_STORAGE *storage)
317 {
318 UX_SLAVE_ENDPOINT *endpoint;
319 UX_SLAVE_TRANSFER *transfer;
320 ULONG max_packet_size;
321
322
323 /* Command state: CBW. */
324 storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_CBW;
325 storage -> ux_device_class_storage_data_buffer = UX_NULL;
326
327 /* Transfer state: START: OUT 31. */
328 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START;
329
330 endpoint = storage -> ux_device_class_storage_ep_out;
331 max_packet_size = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize;
332 transfer = &endpoint -> ux_slave_endpoint_transfer_request;
333
334 storage -> ux_device_class_storage_transfer = transfer;
335 storage -> ux_device_class_storage_data_length = max_packet_size;
336 storage -> ux_device_class_storage_data_count = 0;
337 }
338
_ux_device_class_storage_cbw_process(UX_SLAVE_CLASS_STORAGE * storage)339 static inline VOID _ux_device_class_storage_cbw_process(UX_SLAVE_CLASS_STORAGE *storage)
340 {
341 UX_SLAVE_TRANSFER *cbw_trans;
342 ULONG cbw_length;
343 UCHAR *cbw;
344
345
346 /* Get transfer. */
347 cbw_trans = storage -> ux_device_class_storage_transfer;
348
349 /* If CBW is stalled, just retry. */
350 if (cbw_trans -> ux_slave_transfer_request_completion_code == UX_TRANSFER_STALLED)
351 {
352 _ux_device_class_storage_cbw_receive(storage);
353 return;
354 }
355
356 /* Get CBW and length. */
357 cbw_length = cbw_trans -> ux_slave_transfer_request_actual_length;
358 cbw = cbw_trans -> ux_slave_transfer_request_data_pointer;
359 if (cbw_length != UX_SLAVE_CLASS_STORAGE_CBW_LENGTH)
360 {
361 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
362 }
363 else
364 {
365 _ux_device_class_storage_cmd_process(storage, cbw);
366 }
367
368 /* If still in CBW phase, there must be CBW structure error, wait reset. */
369 if (storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_CBW)
370 {
371 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
372 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_RESET;
373 return;
374 }
375
376 /* If no error, error cases need check. */
377 if (storage -> ux_slave_class_storage_csw_status == UX_SLAVE_CLASS_STORAGE_CSW_PASSED)
378 {
379 _ux_device_class_storage_data_cases_check(storage);
380 }
381
382 /* Error, stall and send CSW. */
383 if (storage -> ux_slave_class_storage_csw_status)
384 {
385
386 /* There will not be any disk operation in this case. */
387 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE;
388
389 if (storage -> ux_slave_class_storage_host_length &&
390 (storage -> ux_slave_class_storage_cbw_flags &
391 UX_DEVICE_CLASS_STORAGE_CBW_FLAG_DIR) == 0)
392 {
393 _ux_device_class_storage_halt_out(storage);
394 }
395 else
396 {
397 _ux_device_class_storage_halt_in(storage);
398 }
399
400 /* Still need CSW phase. */
401 if (storage -> ux_device_class_storage_cmd_state != UX_DEVICE_CLASS_STORAGE_CMD_CBW)
402 storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_ERR;
403 }
404
405 /* No error, state not changed. */
406
407 /* Start CSW if there is no data. */
408 if (storage -> ux_device_class_storage_cmd_state < UX_DEVICE_CLASS_STORAGE_CMD_WRITE)
409 {
410 _ux_device_class_storage_csw_send(storage,
411 storage -> ux_slave_class_storage_cbw_lun,
412 storage -> ux_device_class_storage_ep_in, 0);
413 }
414 }
_ux_device_class_storage_cmd_process(UX_SLAVE_CLASS_STORAGE * storage,UCHAR * cbw)415 static inline VOID _ux_device_class_storage_cmd_process(UX_SLAVE_CLASS_STORAGE *storage, UCHAR *cbw)
416 {
417
418 UX_SLAVE_ENDPOINT *endpoint_in, *endpoint_out;
419 ULONG cbwcb_length;
420 UCHAR *cbwcb;
421 UCHAR lun;
422
423
424 /* Get bCBWLUN. */
425 lun = *(cbw + UX_SLAVE_CLASS_STORAGE_CBW_LUN);
426 storage -> ux_slave_class_storage_cbw_lun = lun;
427
428 /* Get bmCBWFlags. */
429 storage -> ux_slave_class_storage_cbw_flags = *(cbw + UX_SLAVE_CLASS_STORAGE_CBW_FLAGS);
430
431 /* Get dCBWTag. */
432 storage -> ux_slave_class_storage_scsi_tag =
433 _ux_utility_long_get(cbw + UX_SLAVE_CLASS_STORAGE_CBW_TAG);
434
435 /* Get dCBWDataTransferLength: number of bytes to transfer. */
436 storage -> ux_slave_class_storage_host_length = _ux_utility_long_get(cbw + UX_SLAVE_CLASS_STORAGE_CBW_DATA_LENGTH);
437
438 /* Reset CSW status. */
439 storage -> ux_slave_class_storage_csw_residue = 0;
440 storage -> ux_slave_class_storage_csw_status = 0;
441
442 /* Check LUN error. */
443 if (lun >= storage -> ux_slave_class_storage_number_lun)
444 {
445
446 /* Phase error! */
447 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
448 return;
449 }
450
451 /* Check Signature error. */
452 if (_ux_utility_long_get(cbw) != UX_SLAVE_CLASS_STORAGE_CBW_SIGNATURE_MASK)
453 {
454
455 /* Phase error! */
456 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
457 return;
458 }
459
460 /* Get CBWCB length. */
461 cbwcb_length = (ULONG)*(cbw + UX_SLAVE_CLASS_STORAGE_CBW_CB_LENGTH);
462
463 /* Check CBWCB length. */
464 if (cbwcb_length == 0)
465 {
466
467 /* Phase error! */
468 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
469 return;
470 }
471
472 /* Get endpoints. */
473 endpoint_in = storage -> ux_device_class_storage_ep_in;
474 endpoint_out = storage -> ux_device_class_storage_ep_out;
475
476 /* By default set next command state to CSW (no DATA). */
477 storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_CSW;
478 storage -> ux_device_class_storage_device_length = 0;
479 storage -> ux_device_class_storage_data_length = 0;
480 storage -> ux_device_class_storage_data_count = 0;
481
482 /* Reset disk access state. */
483 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE;
484
485 /* Analyze the CBWCB command. */
486 cbwcb = cbw + UX_SLAVE_CLASS_STORAGE_CBW_CB;
487 storage -> ux_device_class_storage_cmd = *cbwcb;
488 switch(storage -> ux_device_class_storage_cmd)
489 {
490
491 case UX_SLAVE_CLASS_STORAGE_SCSI_TEST_READY:
492
493 _ux_device_class_storage_test_ready(storage, lun, endpoint_in, endpoint_out, cbwcb);
494 break;
495
496 case UX_SLAVE_CLASS_STORAGE_SCSI_REQUEST_SENSE:
497
498 _ux_device_class_storage_request_sense(storage, lun, endpoint_in, endpoint_out, cbwcb);
499 break;
500
501 case UX_SLAVE_CLASS_STORAGE_SCSI_FORMAT:
502
503 _ux_device_class_storage_format(storage, lun, endpoint_in, endpoint_out, cbwcb);
504 break;
505
506 case UX_SLAVE_CLASS_STORAGE_SCSI_INQUIRY:
507
508 _ux_device_class_storage_inquiry(storage, lun, endpoint_in, endpoint_out, cbwcb);
509 break;
510
511 case UX_SLAVE_CLASS_STORAGE_SCSI_START_STOP:
512
513 _ux_device_class_storage_start_stop(storage, lun, endpoint_in, endpoint_out, cbwcb);
514 break;
515
516 case UX_SLAVE_CLASS_STORAGE_SCSI_PREVENT_ALLOW_MEDIA_REMOVAL:
517
518 _ux_device_class_storage_prevent_allow_media_removal(storage, lun, endpoint_in, endpoint_out, cbwcb);
519 break;
520
521 case UX_SLAVE_CLASS_STORAGE_SCSI_READ_FORMAT_CAPACITY:
522
523 _ux_device_class_storage_read_format_capacity(storage, lun, endpoint_in, endpoint_out, cbwcb);
524 break;
525
526 case UX_SLAVE_CLASS_STORAGE_SCSI_READ_CAPACITY:
527
528 _ux_device_class_storage_read_capacity(storage, lun, endpoint_in, endpoint_out, cbwcb);
529 break;
530
531 case UX_SLAVE_CLASS_STORAGE_SCSI_VERIFY:
532
533 _ux_device_class_storage_verify(storage, lun, endpoint_in, endpoint_out, cbwcb);
534 break;
535
536 case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SELECT:
537
538 _ux_device_class_storage_mode_select(storage, lun, endpoint_in, endpoint_out, cbwcb);
539 break;
540
541 case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT:
542 case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE:
543
544 _ux_device_class_storage_mode_sense(storage, lun, endpoint_in, endpoint_out, cbwcb);
545 break;
546
547 case UX_SLAVE_CLASS_STORAGE_SCSI_READ32:
548
549 _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, cbwcb,
550 UX_SLAVE_CLASS_STORAGE_SCSI_READ32);
551 break;
552
553 case UX_SLAVE_CLASS_STORAGE_SCSI_READ16:
554
555 _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, cbwcb,
556 UX_SLAVE_CLASS_STORAGE_SCSI_READ16);
557 break;
558
559 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32:
560
561 _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, cbwcb,
562 UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32);
563 break;
564
565 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16:
566
567 _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, cbwcb,
568 UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16);
569 break;
570
571 case UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE:
572
573 _ux_device_class_storage_synchronize_cache(storage, lun, endpoint_in, endpoint_out, cbwcb, *(cbwcb));
574 break;
575
576 #ifdef UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC
577 case UX_SLAVE_CLASS_STORAGE_SCSI_GET_STATUS_NOTIFICATION:
578
579 _ux_device_class_storage_get_status_notification(storage, lun, endpoint_in, endpoint_out, cbwcb);
580 break;
581
582 case UX_SLAVE_CLASS_STORAGE_SCSI_GET_CONFIGURATION:
583
584 _ux_device_class_storage_get_configuration(storage, lun, endpoint_in, endpoint_out, cbwcb);
585 break;
586
587 case UX_SLAVE_CLASS_STORAGE_SCSI_READ_DISK_INFORMATION:
588
589 _ux_device_class_storage_read_disk_information(storage, lun, endpoint_in, endpoint_out, cbwcb);
590 break;
591
592 case UX_SLAVE_CLASS_STORAGE_SCSI_REPORT_KEY:
593
594 _ux_device_class_storage_report_key(storage, lun, endpoint_in, endpoint_out, cbwcb);
595 break;
596
597 case UX_SLAVE_CLASS_STORAGE_SCSI_GET_PERFORMANCE:
598
599 _ux_device_class_storage_get_performance(storage, lun, endpoint_in, endpoint_out, cbwcb);
600 break;
601
602 case UX_SLAVE_CLASS_STORAGE_SCSI_READ_DVD_STRUCTURE:
603
604 _ux_device_class_storage_read_dvd_structure(storage, lun, endpoint_in, endpoint_out, cbwcb);
605 break;
606
607 case UX_SLAVE_CLASS_STORAGE_SCSI_READ_TOC:
608
609 _ux_device_class_storage_read_toc(storage, lun, endpoint_in, endpoint_out, cbwcb);
610 break;
611
612 #endif
613
614 default:
615
616 /* The command is unknown or unsupported, fail. */
617 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED;
618
619 /* Initialize the request sense keys. */
620 storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status =
621 UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(UX_SLAVE_CLASS_STORAGE_SENSE_KEY_ILLEGAL_REQUEST,
622 UX_SLAVE_CLASS_STORAGE_ASC_KEY_INVALID_COMMAND,0);
623 }
624 }
_ux_device_class_storage_data_cases_check(UX_SLAVE_CLASS_STORAGE * storage)625 static inline VOID _ux_device_class_storage_data_cases_check(UX_SLAVE_CLASS_STORAGE *storage)
626 {
627
628 /* ============ 13 cases check. */
629 /* (1)Hn=Dn, (2)Hn<Di, (3)Hn<Do : CBW */
630 /* (4)Hi>Dn, (5)Hi>Di, (6)Hi=Di, (7)Hi<Di, (8)Hi<>Do : DATA */
631 /* (9)Ho>Dn, (10)Ho<>Di, (11)Ho>Do, (12)Ho=Do, (13)Ho<Do : DATA */
632 /* Hn ----------------------------- */
633 /* Case (1) : Success/Error */
634 /* Case (2)(3) : STALL(IN/OUT), PhaseError. */
635 /* Hi ------------------------------------------------- */
636 /* Case (6) : Send DeviceLength, Success/Error. */
637 /* Case (4)(5) : Send DeviceLength, STALL(IN), Success/Error, dCSWDataResidue. */
638 /* Case (7)(8) : (Send HostLength), STALL(IN), PhaseError. */
639 /* Ho ----------------------------------------------------------- */
640 /* Case (12) : Receive, Success/Error. */
641 /* Case (9)(11) : STALL(OUT), Success/Error, dCSWDataResidue. */
642 /* Case (10)(13) : STALL(OUT), PhaseError. */
643 if (storage -> ux_slave_class_storage_cbw_flags & UX_DEVICE_CLASS_STORAGE_CBW_FLAG_DIR)
644 {
645
646 /* Hi. */
647 /* Case (2), (8). */
648 if (storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_WRITE ||
649 storage -> ux_slave_class_storage_host_length == 0)
650 {
651
652 /* Phase error. */
653 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
654 return;
655 }
656
657 /* Case (7). */
658 if (storage -> ux_slave_class_storage_host_length <
659 storage -> ux_device_class_storage_data_length)
660 {
661
662 /* Part of data will be sent. */
663 storage -> ux_device_class_storage_data_length =
664 storage -> ux_slave_class_storage_host_length;
665 }
666
667 /* Case (4), (5), (6), (7). */
668 /* No touch for prepared transfer. */
669 }
670 else
671 {
672
673 /* Ho. */
674 /* Case (3), (10), (13). */
675 if (storage -> ux_slave_class_storage_host_length <
676 storage -> ux_device_class_storage_device_length ||
677 storage -> ux_device_class_storage_cmd_state ==
678 UX_DEVICE_CLASS_STORAGE_CMD_READ)
679 {
680
681 /* Phase error. */
682 storage -> ux_slave_class_storage_csw_status =
683 UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
684 return;
685 }
686
687 /* Case (9), (11). */
688 if (storage -> ux_slave_class_storage_host_length !=
689 storage -> ux_device_class_storage_device_length)
690 {
691
692 /* Update dCSWDataResidue. */
693 storage -> ux_slave_class_storage_csw_residue =
694 storage -> ux_slave_class_storage_host_length -
695 storage -> ux_device_class_storage_device_length;
696
697 /* Failed. */
698 storage -> ux_slave_class_storage_csw_status =
699 UX_SLAVE_CLASS_STORAGE_CSW_FAILED;
700 return;
701 }
702 }
703 }
_ux_device_class_storage_reset_wait(UX_SLAVE_CLASS_STORAGE * storage)704 static inline UINT _ux_device_class_storage_reset_wait(UX_SLAVE_CLASS_STORAGE *storage)
705 {
706
707 /* Check PhaseError. */
708 if ((UCHAR)storage -> ux_slave_class_storage_csw_status !=
709 UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR)
710 {
711
712 /* Reset states. */
713 storage -> ux_device_class_storage_state = UX_STATE_RESET;
714 }
715 else
716 {
717
718 /* Keep CBW endpoints halted until status is reset. */
719 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_RESET;
720 }
721
722 return(UX_STATE_WAIT);
723 }
_ux_device_class_storage_data_next(UX_SLAVE_CLASS_STORAGE * storage)724 static inline UINT _ux_device_class_storage_data_next(UX_SLAVE_CLASS_STORAGE *storage)
725 {
726 switch(storage -> ux_device_class_storage_cmd)
727 {
728
729 /* Disk read. */
730 case UX_SLAVE_CLASS_STORAGE_SCSI_READ16:
731 /* Fall through. */
732 case UX_SLAVE_CLASS_STORAGE_SCSI_READ32:
733
734 /* Check if all data is done. */
735 if (storage -> ux_device_class_storage_data_count >=
736 storage -> ux_device_class_storage_data_length)
737 {
738
739 /* Stall if host expects more data. */
740 if (storage -> ux_slave_class_storage_host_length >
741 storage -> ux_device_class_storage_data_length)
742 {
743 _ux_device_class_storage_halt_in(storage);
744
745 /* Update dCSWDataResidue. */
746 storage -> ux_slave_class_storage_csw_residue =
747 storage -> ux_slave_class_storage_host_length -
748 storage -> ux_device_class_storage_data_length;
749 }
750
751 /* Set to fail if device expects more data. */
752 if (storage -> ux_device_class_storage_device_length >
753 storage -> ux_device_class_storage_data_count)
754 {
755
756 /* Update bCSWStatus. */
757 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED;
758 }
759
760 /* Issue CSW. */
761 _ux_device_class_storage_csw_send(storage,
762 storage -> ux_slave_class_storage_cbw_lun,
763 storage -> ux_device_class_storage_ep_in,
764 0 /* Not used. */);
765 }
766 else
767 {
768
769 /* Buffer sent, update buffer states. */
770 storage -> ux_device_class_storage_buffer_state[storage -> ux_device_class_storage_buffer_usb] =
771 UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY;
772 storage -> ux_device_class_storage_buffer_usb = !storage -> ux_device_class_storage_buffer_usb;
773 storage -> ux_device_class_storage_transfer -> ux_slave_transfer_request_data_pointer =
774 storage -> ux_device_class_storage_buffer[storage -> ux_device_class_storage_buffer_usb];
775
776 /* If disk read not started (waiting free buffer), start it. */
777 if (storage -> ux_device_class_storage_disk_state == UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT)
778 {
779 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_START;
780 }
781
782 /* If there is buffer ready, send next. */
783 if (storage -> ux_device_class_storage_buffer_state[storage->ux_device_class_storage_buffer_usb] ==
784 UX_DEVICE_CLASS_STORAGE_BUFFER_FULL)
785 {
786 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START;
787 }
788 else
789 {
790
791 /* Wait disk operation to fill buffer. */
792 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT;
793 }
794 }
795 break;
796
797 /* Disk write. */
798 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16:
799 /* Fall through. */
800 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32:
801
802 /* Buffer received, update buffer state. */
803 storage -> ux_device_class_storage_buffer_state[
804 storage -> ux_device_class_storage_buffer_usb] =
805 UX_DEVICE_CLASS_STORAGE_BUFFER_FULL;
806
807 /* If disk waiting data, Start disk write. */
808 if (storage -> ux_device_class_storage_disk_state ==
809 UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT)
810 {
811 storage -> ux_device_class_storage_disk_state =
812 UX_DEVICE_CLASS_STORAGE_DISK_OP_START;
813 }
814
815 /* Check if all data is done. */
816 if (storage -> ux_device_class_storage_data_count >=
817 storage -> ux_device_class_storage_data_length)
818 {
819
820 /* Wait disk operation done. */
821 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT;
822 }
823 else
824 {
825
826 /* Buffer received, update buffer states. */
827 storage -> ux_device_class_storage_buffer_usb =
828 !storage -> ux_device_class_storage_buffer_usb;
829 storage -> ux_device_class_storage_transfer ->
830 ux_slave_transfer_request_data_pointer =
831 storage -> ux_device_class_storage_buffer[
832 storage -> ux_device_class_storage_buffer_usb];
833
834 /* If there is buffer empty, start it. */
835 if (storage -> ux_device_class_storage_buffer_state[
836 storage -> ux_device_class_storage_buffer_usb] ==
837 UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY)
838 {
839 storage -> ux_device_class_storage_state =
840 UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START;
841 }
842 else
843 {
844
845 /* No buffer available, wait disk operation done. */
846 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT;
847 }
848 }
849 break;
850
851 /* No further data to send. */
852 default:
853
854 /* Stall if host expects more data. */
855 if (storage -> ux_slave_class_storage_host_length >
856 storage -> ux_device_class_storage_data_count)
857 {
858 _ux_device_class_storage_halt_trans(storage);
859
860 /* Update dCSWDataResidue. */
861 storage -> ux_slave_class_storage_csw_residue =
862 storage -> ux_slave_class_storage_host_length -
863 storage -> ux_device_class_storage_data_length;
864 }
865
866 /* Set to fail if device expects more data. */
867 if (storage -> ux_device_class_storage_device_length >
868 storage -> ux_device_class_storage_data_count)
869 {
870
871 /* Update bCSWStatus. */
872 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED;
873 }
874
875 /* Issue CSW. */
876 _ux_device_class_storage_csw_send(storage,
877 storage -> ux_slave_class_storage_cbw_lun,
878 storage -> ux_device_class_storage_ep_in,
879 0 /* Not used. */);
880 }
881
882 /* Next task state. */
883 return(UX_STATE_NEXT);
884 }
_ux_device_class_storage_trans_start(UX_SLAVE_CLASS_STORAGE * storage)885 static inline VOID _ux_device_class_storage_trans_start(UX_SLAVE_CLASS_STORAGE *storage)
886 {
887 ULONG remaining, host_length, device_length;
888
889
890 /* Get remaining transfer length. */
891 remaining = storage -> ux_device_class_storage_data_length - storage -> ux_device_class_storage_data_count;
892
893 /* Check if data exceeds buffer length. */
894 if (remaining > UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE)
895 {
896
897 /* Send full packets, without ZLP. */
898 host_length = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE;
899 device_length = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE;
900 }
901 else
902 {
903
904 /* Send packets sliced based on host length and device length. */
905 device_length = remaining;
906
907 /* USB CV test expecting stall but not ZLP, so host length is same, but not remaining. */
908 host_length = remaining;
909 }
910
911 /* Prepare data if necessary. */
912 if (storage -> ux_device_class_storage_data_buffer && device_length &&
913 storage -> ux_device_class_storage_cmd_state == UX_DEVICE_CLASS_STORAGE_CMD_READ)
914 {
915 _ux_utility_memory_copy(storage -> ux_device_class_storage_transfer ->
916 ux_slave_transfer_request_data_pointer,
917 storage -> ux_device_class_storage_data_buffer +
918 storage -> ux_device_class_storage_data_count,
919 device_length); /* Use case of memcpy is verified. */
920 }
921
922 /* Save host length and device length for task states. */
923 storage -> ux_device_class_storage_trans_device_length = device_length;
924 storage -> ux_device_class_storage_trans_host_length = host_length;
925
926 /* To TRANS_WAIT. */
927 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_WAIT;
928
929 /* Reset transfer state. */
930 UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer);
931 }
_ux_device_class_storage_trans_wait(UX_SLAVE_CLASS_STORAGE * storage)932 static inline UINT _ux_device_class_storage_trans_wait(UX_SLAVE_CLASS_STORAGE *storage)
933 {
934 return _ux_device_stack_transfer_run(storage -> ux_device_class_storage_transfer,
935 storage -> ux_device_class_storage_trans_device_length,
936 storage -> ux_device_class_storage_trans_host_length);
937 }
_ux_device_class_storage_trans_error(UX_SLAVE_CLASS_STORAGE * storage)938 static inline VOID _ux_device_class_storage_trans_error(UX_SLAVE_CLASS_STORAGE *storage)
939 {
940
941 /* Abort USB operation if transfer not done. */
942 if (storage -> ux_device_class_storage_data_count < storage -> ux_device_class_storage_data_length)
943 {
944 if (storage -> ux_slave_class_storage_cbw_flags & UX_DEVICE_CLASS_STORAGE_CBW_FLAG_IN)
945 {
946 _ux_device_class_storage_halt_in(storage);
947 }
948 else
949 {
950 _ux_device_class_storage_halt_out(storage);
951 }
952
953 /* Update dCSWDataResidue. */
954 storage -> ux_slave_class_storage_csw_residue =
955 storage -> ux_slave_class_storage_host_length -
956 storage -> ux_device_class_storage_data_count;
957 }
958 else
959 {
960 _ux_device_class_storage_halt_in(storage);
961 }
962
963 /* Issue CSW. */
964 _ux_device_class_storage_csw_send(storage,
965 storage -> ux_slave_class_storage_cbw_lun,
966 storage -> ux_device_class_storage_ep_in,
967 0 /* Not used. */);
968 }
_ux_device_class_storage_halt_out(UX_SLAVE_CLASS_STORAGE * storage)969 static inline VOID _ux_device_class_storage_halt_out(UX_SLAVE_CLASS_STORAGE *storage)
970 {
971 _ux_device_stack_endpoint_stall(storage -> ux_device_class_storage_ep_out);
972 }
_ux_device_class_storage_halt_in(UX_SLAVE_CLASS_STORAGE * storage)973 static inline VOID _ux_device_class_storage_halt_in(UX_SLAVE_CLASS_STORAGE *storage)
974 {
975 _ux_device_stack_endpoint_stall(storage -> ux_device_class_storage_ep_in);
976 }
_ux_device_class_storage_halt_trans(UX_SLAVE_CLASS_STORAGE * storage)977 static inline VOID _ux_device_class_storage_halt_trans(UX_SLAVE_CLASS_STORAGE *storage)
978 {
979 UX_SLAVE_TRANSFER *trans = storage -> ux_device_class_storage_transfer;
980 UX_SLAVE_ENDPOINT *endp = trans -> ux_slave_transfer_request_endpoint;
981 _ux_device_stack_endpoint_stall(endp);
982 }
983
984
_ux_device_class_storage_task_disk(UX_SLAVE_CLASS_STORAGE * storage)985 static inline VOID _ux_device_class_storage_task_disk(UX_SLAVE_CLASS_STORAGE *storage)
986 {
987 UCHAR state = storage -> ux_device_class_storage_disk_state;
988 UINT status;
989 INT immediate_state = UX_TRUE;
990
991 /* Run states once. */
992 while(immediate_state)
993 {
994
995 /* Update state. */
996 state = storage -> ux_device_class_storage_disk_state;
997 switch(state)
998 {
999
1000 case UX_DEVICE_CLASS_STORAGE_DISK_OP_START:
1001 _ux_device_class_storage_disk_start(storage);
1002 storage -> ux_device_class_storage_disk_state =
1003 UX_DEVICE_CLASS_STORAGE_DISK_OP_WAIT;
1004
1005 /* Fall through. */
1006 case UX_DEVICE_CLASS_STORAGE_DISK_OP_WAIT:
1007 status = _ux_device_class_storage_disk_wait(storage);
1008
1009 /* Error case. */
1010 if (status < UX_STATE_NEXT)
1011 {
1012
1013 /* Disk idle. */
1014 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE;
1015
1016 /* USB notified with disk error. */
1017 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_DISK_ERROR;
1018 }
1019
1020 /* Success case. */
1021 if (status == UX_STATE_NEXT)
1022 {
1023
1024 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_NEXT;
1025 }
1026
1027 /* Other cases, keep waiting. */
1028 return;
1029
1030 case UX_DEVICE_CLASS_STORAGE_DISK_OP_NEXT:
1031 _ux_device_class_storage_disk_next(storage);
1032 return;
1033
1034 case UX_DEVICE_CLASS_STORAGE_DISK_USB_ERROR:
1035 _ux_device_class_storage_disk_error(storage);
1036 break;
1037
1038 case UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT: /* Nothing to do, fall through. */
1039
1040 case UX_DEVICE_CLASS_STORAGE_DISK_IDLE: /* Nothing to do, fall through. */
1041
1042 default: /* Nothing to do. */
1043 break;
1044 }
1045
1046 /* Task run once, break the loop. */
1047 immediate_state = UX_FALSE;
1048 }
1049 }
_ux_device_class_storage_disk_start(UX_SLAVE_CLASS_STORAGE * storage)1050 static inline VOID _ux_device_class_storage_disk_start(UX_SLAVE_CLASS_STORAGE *storage)
1051 {
1052 ULONG block_size;
1053 ULONG max_n_blocks;
1054
1055
1056 if (storage -> ux_device_class_storage_cmd == UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE)
1057 {
1058
1059 /* All things sync in one call. */
1060 storage -> ux_device_class_storage_disk_n_lb = storage -> ux_device_class_storage_cmd_n_lb;
1061 return;
1062 }
1063
1064 /* Read/write, split the operation by buffer sizes. */
1065
1066 /* Max blocks for one buffer. */
1067 block_size = storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun].
1068 ux_slave_class_storage_media_block_length;
1069 if (block_size == 0)
1070 UX_ASSERT(UX_FALSE);
1071 max_n_blocks = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE / block_size;
1072
1073 /* Prepare next disk read. */
1074 if (storage -> ux_device_class_storage_cmd_n_lb > max_n_blocks)
1075 {
1076 storage -> ux_device_class_storage_disk_n_lb = max_n_blocks;
1077 }
1078 else
1079 {
1080 storage -> ux_device_class_storage_disk_n_lb = storage -> ux_device_class_storage_cmd_n_lb;
1081 }
1082 }
_ux_device_class_storage_disk_wait(UX_SLAVE_CLASS_STORAGE * storage)1083 static inline UINT _ux_device_class_storage_disk_wait(UX_SLAVE_CLASS_STORAGE *storage)
1084 {
1085 switch (storage -> ux_device_class_storage_cmd)
1086 {
1087 case UX_SLAVE_CLASS_STORAGE_SCSI_READ16:
1088 case UX_SLAVE_CLASS_STORAGE_SCSI_READ32:
1089 return storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun].
1090 ux_slave_class_storage_media_read(storage,
1091 storage -> ux_slave_class_storage_cbw_lun,
1092 storage -> ux_device_class_storage_buffer[
1093 storage -> ux_device_class_storage_buffer_disk],
1094 storage -> ux_device_class_storage_disk_n_lb,
1095 storage -> ux_device_class_storage_cmd_lba,
1096 &storage -> ux_device_class_storage_media_status);
1097
1098 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16:
1099 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32:
1100 return storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun].
1101 ux_slave_class_storage_media_write(storage,
1102 storage -> ux_slave_class_storage_cbw_lun,
1103 storage -> ux_device_class_storage_buffer[
1104 storage -> ux_device_class_storage_buffer_disk],
1105 storage -> ux_device_class_storage_disk_n_lb,
1106 storage -> ux_device_class_storage_cmd_lba,
1107 &storage -> ux_device_class_storage_media_status);
1108
1109 case UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE:
1110 return storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun].
1111 ux_slave_class_storage_media_flush(storage,
1112 storage -> ux_slave_class_storage_cbw_lun,
1113 storage -> ux_device_class_storage_disk_n_lb,
1114 storage -> ux_device_class_storage_cmd_lba,
1115 &storage -> ux_device_class_storage_media_status);
1116
1117 case UX_SLAVE_CLASS_STORAGE_SCSI_VERIFY: /* No nothing for now. */
1118 default:
1119 break;
1120 }
1121 return(UX_STATE_NEXT);
1122 }
_ux_device_class_storage_disk_next(UX_SLAVE_CLASS_STORAGE * storage)1123 static inline VOID _ux_device_class_storage_disk_next(UX_SLAVE_CLASS_STORAGE *storage)
1124 {
1125
1126 /* Update disk operation status. */
1127 storage -> ux_device_class_storage_cmd_lba += storage -> ux_device_class_storage_disk_n_lb;
1128 storage -> ux_device_class_storage_cmd_n_lb -= storage -> ux_device_class_storage_disk_n_lb;
1129
1130 /* Next check is different for read/write. */
1131 switch (storage -> ux_device_class_storage_cmd)
1132 {
1133 case UX_SLAVE_CLASS_STORAGE_SCSI_READ16:
1134 case UX_SLAVE_CLASS_STORAGE_SCSI_READ32:
1135 _ux_device_class_storage_disk_read_next(storage);
1136 return;
1137
1138 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16:
1139 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32:
1140 _ux_device_class_storage_disk_write_next(storage);
1141 return;
1142
1143 case UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE:
1144
1145 /* Disk is idle now. */
1146 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE;
1147
1148 /* Send CSW if not sent yet. */
1149 if (storage -> ux_device_class_storage_state == UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT)
1150 {
1151 _ux_device_class_storage_csw_send(storage,
1152 storage -> ux_slave_class_storage_cbw_lun,
1153 storage -> ux_device_class_storage_ep_in,
1154 0 /* Not used. */);
1155 }
1156 return;
1157
1158 default:
1159 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE;
1160 break;
1161 }
1162 }
_ux_device_class_storage_disk_read_next(UX_SLAVE_CLASS_STORAGE * storage)1163 static inline VOID _ux_device_class_storage_disk_read_next(UX_SLAVE_CLASS_STORAGE *storage)
1164 {
1165
1166 /* Update buffer state : full. */
1167 storage -> ux_device_class_storage_buffer_state[
1168 storage -> ux_device_class_storage_buffer_disk] =
1169 UX_DEVICE_CLASS_STORAGE_BUFFER_FULL;
1170
1171 /* Check if all disk operation is done. */
1172 if (storage -> ux_device_class_storage_cmd_n_lb == 0)
1173 {
1174 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE;
1175 }
1176 else
1177 {
1178
1179 /* Update buffer index. */
1180 storage -> ux_device_class_storage_buffer_disk =
1181 !storage -> ux_device_class_storage_buffer_disk;
1182
1183 /* If buffer is free, start next read. */
1184 if (UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY ==
1185 storage -> ux_device_class_storage_buffer_state[
1186 storage -> ux_device_class_storage_buffer_disk])
1187 {
1188
1189 /* Start next read. */
1190 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_START;
1191 }
1192 else
1193 {
1194
1195 /* Wait until buffer sent by USB. */
1196 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT;
1197 }
1198 }
1199
1200 /* Start USB transfer. */
1201 if (storage -> ux_device_class_storage_state ==
1202 UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT &&
1203 UX_DEVICE_CLASS_STORAGE_BUFFER_FULL ==
1204 storage -> ux_device_class_storage_buffer_state[
1205 storage -> ux_device_class_storage_buffer_usb])
1206 {
1207 storage -> ux_device_class_storage_state =
1208 UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START;
1209 }
1210 }
_ux_device_class_storage_disk_write_next(UX_SLAVE_CLASS_STORAGE * storage)1211 static inline VOID _ux_device_class_storage_disk_write_next(UX_SLAVE_CLASS_STORAGE *storage)
1212 {
1213
1214 /* Update buffer state : empty. */
1215 storage -> ux_device_class_storage_buffer_state[
1216 storage -> ux_device_class_storage_buffer_disk] =
1217 UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY;
1218
1219 /* Check if all disk operation is done. */
1220 if (storage -> ux_device_class_storage_cmd_n_lb == 0)
1221 {
1222
1223 /* Disk is idle now. */
1224 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE;
1225
1226 /* Issue CSW. */
1227 _ux_device_class_storage_csw_send(storage,
1228 storage -> ux_slave_class_storage_cbw_lun,
1229 storage -> ux_device_class_storage_ep_in,
1230 0 /* Not used. */);
1231 }
1232 else
1233 {
1234
1235 /* Update buffer index. */
1236 storage -> ux_device_class_storage_buffer_disk =
1237 !storage -> ux_device_class_storage_buffer_disk;
1238
1239 /* If buffer is full, start next write. */
1240 if (UX_DEVICE_CLASS_STORAGE_BUFFER_FULL ==
1241 storage -> ux_device_class_storage_buffer_state[
1242 storage -> ux_device_class_storage_buffer_disk])
1243 {
1244
1245 /* Start next write. */
1246 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_OP_START;
1247 }
1248 else
1249 {
1250
1251 /* Wait until buffer filled by USB. */
1252 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_USB_WAIT;
1253 }
1254
1255 /* Start USB transfer. */
1256 if (storage -> ux_device_class_storage_state ==
1257 UX_DEVICE_CLASS_STORAGE_STATE_DISK_WAIT &&
1258 UX_DEVICE_CLASS_STORAGE_BUFFER_EMPTY ==
1259 storage -> ux_device_class_storage_buffer_state[
1260 storage -> ux_device_class_storage_buffer_usb])
1261 {
1262 storage -> ux_device_class_storage_state =
1263 UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START;
1264 }
1265 }
1266 }
_ux_device_class_storage_disk_error(UX_SLAVE_CLASS_STORAGE * storage)1267 static inline VOID _ux_device_class_storage_disk_error(UX_SLAVE_CLASS_STORAGE *storage)
1268 {
1269 /* Abort disk operation: read or write with NULL! */
1270 switch (storage -> ux_device_class_storage_cmd)
1271 {
1272 case UX_SLAVE_CLASS_STORAGE_SCSI_READ16:
1273 case UX_SLAVE_CLASS_STORAGE_SCSI_READ32:
1274 storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun].
1275 ux_slave_class_storage_media_read(storage,
1276 storage -> ux_slave_class_storage_cbw_lun, UX_NULL, 0, 0, UX_NULL);
1277 break;
1278 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16:
1279 case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32:
1280 storage -> ux_slave_class_storage_lun[storage -> ux_slave_class_storage_cbw_lun].
1281 ux_slave_class_storage_media_write(storage,
1282 storage -> ux_slave_class_storage_cbw_lun, UX_NULL, 0, 0, UX_NULL);
1283 break;
1284 default:
1285 break;
1286 }
1287
1288 /* Change disk state to IDLE. */
1289 storage -> ux_device_class_storage_disk_state = UX_DEVICE_CLASS_STORAGE_DISK_IDLE;
1290 }
1291
1292 #endif
1293