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 /** Storage Class */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary system files. */
25
26 #define UX_SOURCE_CODE
27
28 #include "ux_api.h"
29 #include "ux_host_class_storage.h"
30 #include "ux_host_stack.h"
31
32
33 #if defined(UX_HOST_STANDALONE)
34
35
36 static inline VOID _ux_host_class_storage_inst_tasks_run(UX_HOST_CLASS_STORAGE *storage);
37
38 static inline UINT _ux_host_class_storage_lun_is_removable(UX_HOST_CLASS_STORAGE *storage);
39 static inline UINT _ux_host_class_storage_lun_type_is_known(UX_HOST_CLASS_STORAGE *storage);
40
41 static inline VOID _ux_host_class_storage_max_lun_save(UX_HOST_CLASS_STORAGE *storage);
42 static inline UINT _ux_host_class_storage_inquiry_save(UX_HOST_CLASS_STORAGE *storage);
43 static inline VOID _ux_host_class_storage_format_cap_save(UX_HOST_CLASS_STORAGE *storage);
44 static inline VOID _ux_host_class_storage_capacity_save(UX_HOST_CLASS_STORAGE *storage);
45 static inline VOID _ux_host_class_storage_unit_ready_check(UX_HOST_CLASS_STORAGE *storage);
46
47 static inline VOID _ux_host_class_storage_lun_media_insert(UX_HOST_CLASS_STORAGE *storage);
48
49 static inline UINT _ux_host_class_storage_transport_sense_check(UX_HOST_CLASS_STORAGE *storage);
50
51 /**************************************************************************/
52 /* */
53 /* FUNCTION RELEASE */
54 /* */
55 /* _ux_host_class_storage_tasks_run PORTABLE C */
56 /* 6.2.0 */
57 /* AUTHOR */
58 /* */
59 /* Chaoqiong Xiao, Microsoft Corporation */
60 /* */
61 /* DESCRIPTION */
62 /* */
63 /* This function is awaken every 2 seconds to check if there was a */
64 /* device insertion on a specific media. This is the only way we can */
65 /* remount a media after the storage instance has opened the media to */
66 /* UX_MEDIA (default FileX) and the media is either not present */
67 /* or was removed and is being re-inserted. */
68 /* */
69 /* INPUT */
70 /* */
71 /* storage Pointer to storage instance */
72 /* */
73 /* OUTPUT */
74 /* */
75 /* None */
76 /* */
77 /* CALLS */
78 /* */
79 /* _ux_host_class_storage_device_reset Reset device */
80 /* _ux_host_class_storage_media_mount Mount the media */
81 /* _ux_host_class_storage_unit_ready_test */
82 /* Test for unit ready */
83 /* _ux_host_class_storage_media_characteristics_get */
84 /* Get media characteristics */
85 /* _ux_host_class_storage_media_format_capacity_get */
86 /* Get media format capacity */
87 /* _ux_utility_memory_free Free memory block */
88 /* */
89 /* CALLED BY */
90 /* */
91 /* USBX Host Stack */
92 /* */
93 /* RELEASE HISTORY */
94 /* */
95 /* DATE NAME DESCRIPTION */
96 /* */
97 /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */
98 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
99 /* fixed parameter/variable */
100 /* names conflict C++ keyword, */
101 /* resulting in version 6.1.12 */
102 /* 10-31-2022 Chaoqiong Xiao Modified comment(s), */
103 /* improved internal logic, */
104 /* resulting in version 6.2.0 */
105 /* */
106 /**************************************************************************/
_ux_host_class_storage_tasks_run(UX_HOST_CLASS * storage_class)107 UINT _ux_host_class_storage_tasks_run(UX_HOST_CLASS *storage_class)
108 {
109 UX_HOST_CLASS_STORAGE *storage;
110
111 /* Validate class entry. */
112 if (storage_class -> ux_host_class_status != UX_USED ||
113 storage_class -> ux_host_class_entry_function != _ux_host_class_storage_entry)
114 return(UX_STATE_IDLE);
115
116 /* Run for class instances. */
117 storage = (UX_HOST_CLASS_STORAGE *)storage_class -> ux_host_class_first_instance;
118 while(storage)
119 {
120
121 /* Run tasks for each storage instance. */
122 storage -> ux_host_class_storage_flags |= UX_HOST_CLASS_STORAGE_FLAG_PROTECT;
123 _ux_host_class_storage_inst_tasks_run(storage);
124 storage -> ux_host_class_storage_flags &= ~UX_HOST_CLASS_STORAGE_FLAG_PROTECT;
125 storage = storage -> ux_host_class_storage_next_instance;
126 }
127 return(UX_STATE_WAIT);
128 }
129
_ux_host_class_storage_inst_tasks_run(UX_HOST_CLASS_STORAGE * storage)130 static inline VOID _ux_host_class_storage_inst_tasks_run(UX_HOST_CLASS_STORAGE *storage)
131 {
132 UX_INTERRUPT_SAVE_AREA
133 UCHAR state;
134 ULONG tick_now, tick_elapsed;
135 UINT status;
136 UX_TRANSFER *trans;
137 UX_INTERFACE *interface_ptr;
138 INT immediate_state;
139
140 /* If storage not live, start initialize. */
141 if (storage -> ux_host_class_storage_state == UX_HOST_CLASS_INSTANCE_MOUNTING)
142 {
143 if (storage -> ux_host_class_storage_state_state == UX_STATE_RESET)
144 {
145
146 /* Start initialize sequence Delay() - GetMaxLUN() - Inquiry() - GetFormatCapacity(). */
147 storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_DELAY_WAIT;
148 storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_GET;
149 storage -> ux_host_class_storage_delay_start = _ux_utility_time_get();
150 storage -> ux_host_class_storage_delay_ms =
151 UX_MS_TO_TICK_NON_ZERO(UX_HOST_CLASS_STORAGE_DEVICE_INIT_DELAY);
152 return;
153 }
154
155 /* OK to process states. */
156 }
157 else if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE)
158 {
159
160 /* No need to process states. */
161 storage -> ux_host_class_storage_state_state = UX_STATE_RESET;
162 return;
163 }
164
165 /* Handle read/write states. */
166 if ((storage -> ux_host_class_storage_op_state == UX_STATE_WAIT) &&
167 (storage -> ux_host_class_storage_flags &
168 UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT) == 0)
169 {
170
171 /* Run transport. */
172 status = _ux_host_class_storage_transport_run(storage);
173
174 /* Fatal error. */
175 if (status < UX_STATE_IDLE)
176 {
177 storage -> ux_host_class_storage_op_state = UX_STATE_RESET;
178 return;
179 }
180
181 /* Done with/without error. */
182 if (status <= UX_STATE_NEXT)
183 {
184 storage -> ux_host_class_storage_op_state = UX_STATE_IDLE;
185 return;
186 }
187
188 /* Keep waiting. */
189 /* Main states are frozen in this case. */
190 return;
191 }
192
193 /* Handle main states. */
194 immediate_state = UX_TRUE;
195 while(immediate_state)
196 {
197
198 /* Get current state. */
199 /* Initial check: delay()-GetMaxLUN()-Inquiry()-GetFormatCap()
200 process break on any error. */
201 /* Regular check: delay()-TestReady()-Inquiry()-GetFormatCap()
202 process break on any error. */
203 state = storage -> ux_host_class_storage_state_state;
204 switch(state)
205 {
206 case UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_GET:
207
208 /* Issue GetMaxLun(). */
209 status = _ux_host_class_storage_max_lun_get(storage);
210 if (UX_SUCCESS != status)
211 {
212
213 /* This fails storage activation. */
214 interface_ptr = storage -> ux_host_class_storage_interface;
215 _ux_host_stack_class_instance_destroy(
216 storage -> ux_host_class_storage_class, (VOID *) storage);
217 interface_ptr -> ux_interface_class_instance = (VOID *) UX_NULL;
218 _ux_utility_memory_free(storage);
219 return;
220 }
221
222 /* Roll back to next state. */
223 /* By default TRANSFER -> MAX_LUN_SAVE -> TEST_READY. */
224 continue;
225
226 case UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_SAVE:
227 _ux_host_class_storage_max_lun_save(storage);
228
229 /* Continue to start LUN 0 check from TEST_READY any way. */
230 storage -> ux_host_class_storage_check_lun = 0;
231 storage -> ux_host_class_storage_state_state =
232 UX_HOST_CLASS_STORAGE_STATE_TEST_READY;
233
234 /* Fall through. */
235 case UX_HOST_CLASS_STORAGE_STATE_TEST_READY:
236
237 /* Save the LUN for the follwing sequence to use. */
238 storage -> ux_host_class_storage_lun =
239 storage -> ux_host_class_storage_check_lun;
240
241 /* If storage is not live, skip to do INQUIRY. */
242 if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE)
243 {
244 storage -> ux_host_class_storage_state_state =
245 UX_HOST_CLASS_STORAGE_STATE_INQUIRY;
246 continue;
247 }
248
249 /* If LUN is not removable nor known, skip it to check next LUN. */
250 if (!_ux_host_class_storage_lun_is_removable(storage) ||
251 !_ux_host_class_storage_lun_type_is_known(storage))
252 {
253 storage -> ux_host_class_storage_state_state =
254 UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN;
255 continue;
256 }
257
258 /* Prepare TestUnitReady(). */
259 _ux_host_class_storage_unit_ready_test(storage);
260
261 /* Roll back to next - TRANSPORT - TEST_CHECK. */
262 continue;
263
264 case UX_HOST_CLASS_STORAGE_STATE_TEST_CHECK:
265 _ux_host_class_storage_unit_ready_check(storage);
266
267 /* Roll back to next - possible NEXT_LUN/INQUIRY/TEST_READY. */
268 continue;
269
270 case UX_HOST_CLASS_STORAGE_STATE_INQUIRY:
271 status = _ux_host_class_storage_media_characteristics_get(storage);
272 if (status != UX_SUCCESS)
273 {
274
275 /* There is error, break the regular check round. */
276 storage -> ux_host_class_storage_status = status;
277 storage -> ux_host_class_storage_state_state =
278 UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE;
279 }
280
281 /* Roll back to normal next - TRANSPORT - INQUIRY_SAVE. */
282 continue;
283
284 case UX_HOST_CLASS_STORAGE_STATE_INQUIRY_SAVE:
285 status = _ux_host_class_storage_inquiry_save(storage);
286 if (status != UX_SUCCESS)
287 {
288
289 /* Check next LUN. */
290 storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN;
291 continue;
292 }
293
294 /* Next : GetFormatCapacity(). */
295 storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_GET;
296
297 /* Fall through. */
298 case UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_GET:
299 status = _ux_host_class_storage_media_format_capacity_get(storage);
300 if (status != UX_SUCCESS)
301 {
302
303 /* This error breaks regular check round. */
304 storage -> ux_host_class_storage_status = status;
305 storage -> ux_host_class_storage_state_state =
306 UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE;
307 }
308
309 /* Roll back to normal next - TRANSPORT - FORMAT_CAP_SAVE. */
310 continue;
311
312 case UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_SAVE:
313 _ux_host_class_storage_format_cap_save(storage);
314
315 /* Next : GetCapacity() */
316 storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_CAP_GET;
317
318 /* Fall through. */
319 case UX_HOST_CLASS_STORAGE_STATE_CAP_GET:
320 status = _ux_host_class_storage_media_capacity_get(storage);
321 if (status != UX_SUCCESS)
322 {
323
324 /* This error breaks the regular check round. */
325 storage -> ux_host_class_storage_status = status;
326 storage -> ux_host_class_storage_state_state =
327 UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE;
328 }
329
330 /* Roll back to normal next - TRANSPORT - CAP_SAVE. */
331 continue;
332
333 case UX_HOST_CLASS_STORAGE_STATE_CAP_SAVE:
334 _ux_host_class_storage_capacity_save(storage);
335
336 /* Final step for a single LUN check, going to next LUN. */
337 storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN;
338 continue;
339
340 case UX_HOST_CLASS_STORAGE_STATE_CHECK_START:
341
342 /* Get lock and start check sequence: ready - inquiry - formatCap - cap. */
343 storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_LOCK_WAIT;
344 storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_TEST_READY;
345
346 /* Fall through. */
347 case UX_HOST_CLASS_STORAGE_STATE_LOCK_WAIT:
348 UX_DISABLE
349 if (storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK)
350 {
351
352 /* Locked, keep state to wait. */
353 UX_RESTORE
354 return;
355 }
356
357 /* I'm locking it. */
358 storage -> ux_host_class_storage_flags |= UX_HOST_CLASS_STORAGE_FLAG_LOCK;
359 UX_RESTORE
360
361 /* Next state. */
362 storage -> ux_host_class_storage_state_state =
363 storage -> ux_host_class_storage_state_next;
364 continue;
365
366 case UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN:
367
368 /* If it's immediate check for current LUN, we are done. */
369 if (storage -> ux_host_class_storage_flags &
370 UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT)
371 {
372
373 /* Go back to idle state. */
374 storage -> ux_host_class_storage_flags &=
375 ~UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT;
376 storage -> ux_host_class_storage_state_state = UX_STATE_IDLE;
377 continue;
378 }
379
380 if (storage -> ux_host_class_storage_check_lun <
381 storage -> ux_host_class_storage_max_lun)
382 {
383
384 /* Check next LUN. */
385 storage -> ux_host_class_storage_check_lun ++;
386 storage -> ux_host_class_storage_state_state =
387 UX_HOST_CLASS_STORAGE_STATE_TEST_READY;
388 }
389 else
390 {
391
392 /* All LUN check is done. */
393 storage -> ux_host_class_storage_state_state =
394 UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE;
395 }
396
397 /* Roll back to next state. */
398 continue;
399
400 case UX_HOST_CLASS_STORAGE_STATE_TRANSPORT:
401 status = _ux_host_class_storage_transport_run(storage);
402
403 /* Errors. */
404 if (status < UX_STATE_NEXT)
405 {
406
407 /* Normal flow is broken, if there is data buffer, free it. */
408 if (storage -> ux_host_class_storage_trans_data)
409 _ux_utility_memory_free(storage -> ux_host_class_storage_trans_data);
410
411 /* No further operations, reset state machine. */
412 storage -> ux_host_class_storage_state_state = UX_STATE_RESET;
413 storage -> ux_host_class_storage_flags &= ~UX_HOST_CLASS_STORAGE_FLAG_LOCK;
414 return;
415 }
416
417 /* Next. */
418 if (status == UX_STATE_NEXT)
419 {
420
421 /* If there is sense handled, rollback to next state. */
422 if (_ux_host_class_storage_transport_sense_check(storage))
423 {
424
425 /* Normal flow is broken, if there is data buffer, free it. */
426 if (storage -> ux_host_class_storage_trans_data)
427 _ux_utility_memory_free(storage -> ux_host_class_storage_trans_data);
428 continue;
429 }
430
431 storage -> ux_host_class_storage_state_state =
432 storage -> ux_host_class_storage_state_next;
433 continue;
434 }
435
436 /* Wait, state no change. */
437 return;
438
439 case UX_HOST_CLASS_STORAGE_STATE_TRANSFER:
440 trans = storage -> ux_host_class_storage_trans;
441 status = _ux_host_stack_transfer_run(trans);
442
443 /* Keep waiting if not done. */
444 if (status > UX_STATE_NEXT)
445 return;
446
447 /* Check status in next state. */
448 storage -> ux_host_class_storage_state_state =
449 storage -> ux_host_class_storage_state_next;
450 continue;
451
452 case UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE:
453
454 /* If it's mounting, do immediate ready check again. */
455 if (storage -> ux_host_class_storage_state == UX_HOST_CLASS_INSTANCE_MOUNTING)
456 {
457 storage -> ux_host_class_storage_state = UX_HOST_CLASS_INSTANCE_LIVE;
458 storage -> ux_host_class_storage_check_lun = 0;
459 storage -> ux_host_class_storage_state_state =
460 UX_HOST_CLASS_STORAGE_STATE_TEST_READY;
461 continue;
462 }
463
464 /* Release the storage. */
465 storage -> ux_host_class_storage_flags &= ~UX_HOST_CLASS_STORAGE_FLAG_LOCK;
466
467 /* Main state idle. */
468 storage -> ux_host_class_storage_state_state = UX_STATE_IDLE;
469 continue;
470
471 case UX_HOST_CLASS_STORAGE_STATE_DELAY_WAIT:
472 tick_now = _ux_utility_time_get();
473 tick_elapsed = _ux_utility_time_elapsed(
474 storage -> ux_host_class_storage_delay_start, tick_now);
475
476 /* If no timeout, state no change, keep waiting. */
477 if (tick_elapsed < storage -> ux_host_class_storage_delay_ms)
478 return;
479
480 /* Roll back to do next state. */
481 storage -> ux_host_class_storage_state_state =
482 storage -> ux_host_class_storage_state_next;
483 continue;
484
485 case UX_STATE_IDLE:
486
487 /* If it's not locked, start delay for checking. */
488 UX_DISABLE
489 if ((storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK) == 0)
490 {
491
492 /* Just keep regular checking from LUN 0. */
493 storage -> ux_host_class_storage_check_lun = 0;
494 storage -> ux_host_class_storage_delay_start = _ux_utility_time_get();
495 storage -> ux_host_class_storage_state_state =
496 UX_HOST_CLASS_STORAGE_STATE_DELAY_WAIT;
497 storage -> ux_host_class_storage_state_next =
498 UX_HOST_CLASS_STORAGE_STATE_CHECK_START;
499 storage -> ux_host_class_storage_delay_ms = UX_MS_TO_TICK(
500 UX_HOST_CLASS_STORAGE_THREAD_SLEEP_TIME);
501 UX_RESTORE
502 continue;
503 }
504 UX_RESTORE
505
506 /* Fall through. */
507
508 case UX_STATE_RESET: /* Fall through. */
509 default:
510 break;
511 }
512
513 /* Break the loop. */
514 immediate_state = UX_FALSE;
515 }
516 }
517
_ux_host_class_storage_max_lun_save(UX_HOST_CLASS_STORAGE * storage)518 static inline VOID _ux_host_class_storage_max_lun_save(UX_HOST_CLASS_STORAGE *storage)
519 {
520 UX_TRANSFER *trans = storage -> ux_host_class_storage_trans;
521
522 /* By default max lun is 0. */
523 storage -> ux_host_class_storage_max_lun = 0;
524
525 /* MaxLuN can from success request. */
526 if (trans)
527 {
528
529 /* If success, save max LUN. */
530 if (trans -> ux_transfer_request_completion_code == UX_SUCCESS &&
531 trans -> ux_transfer_request_actual_length == 1)
532 {
533 storage -> ux_host_class_storage_max_lun =
534 *trans -> ux_transfer_request_data_pointer;
535
536 /* Is the max LUN index greater than our LUN array's? */
537 if (storage -> ux_host_class_storage_max_lun > UX_MAX_HOST_LUN - 1)
538 {
539
540 /* Cap it off. */
541 storage -> ux_host_class_storage_max_lun = UX_MAX_HOST_LUN - 1;
542
543 /* Notify application so it knows to increase UX_MAX_HOST_LUN. */
544 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEMORY_ERROR);
545
546 /* If trace is enabled, insert this event into the trace buffer. */
547 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_MEMORY_ERROR, storage, 0, 0, UX_TRACE_ERRORS, 0, 0)
548 }
549 }
550
551 /* Allocated buffer for request must be freed here. */
552 _ux_utility_memory_free(trans -> ux_transfer_request_data_pointer);
553 }
554 }
_ux_host_class_storage_inquiry_save(UX_HOST_CLASS_STORAGE * storage)555 static inline UINT _ux_host_class_storage_inquiry_save(UX_HOST_CLASS_STORAGE *storage)
556 {
557 UCHAR *inquiry_response = storage -> ux_host_class_storage_trans_data;
558 UINT lun_index = storage -> ux_host_class_storage_lun;
559 storage -> ux_host_class_storage_media_type = *(inquiry_response +
560 UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_PERIPHERAL_TYPE);
561 storage -> ux_host_class_storage_lun_types[lun_index] =
562 storage -> ux_host_class_storage_media_type;
563 storage -> ux_host_class_storage_lun_removable_media_flags[lun_index] =
564 *(inquiry_response +
565 UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_REMOVABLE_MEDIA);
566
567 /* Free response buffer. */
568 _ux_utility_memory_free(inquiry_response);
569
570 /* Set default sector size. */
571 switch(storage -> ux_host_class_storage_media_type)
572 {
573 case UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK:
574 case UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK:
575 storage -> ux_host_class_storage_sector_size = UX_HOST_CLASS_STORAGE_SECTOR_SIZE_FAT;
576 break;
577
578 case UX_HOST_CLASS_STORAGE_MEDIA_CDROM:
579 case UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK:
580 storage -> ux_host_class_storage_sector_size = UX_HOST_CLASS_STORAGE_SECTOR_SIZE_OTHER;
581 break;
582
583 default:
584
585 /* Notify application so it knows to increase UX_MAX_HOST_LUN. */
586 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED);
587
588 /* If trace is enabled, insert this event into the trace buffer. */
589 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED, storage, 0, 0, UX_TRACE_ERRORS, 0, 0)
590
591 return(UX_HOST_CLASS_MEDIA_NOT_SUPPORTED);
592 }
593 return(UX_SUCCESS);
594 }
_ux_host_class_storage_capacity_save(UX_HOST_CLASS_STORAGE * storage)595 static inline VOID _ux_host_class_storage_capacity_save(UX_HOST_CLASS_STORAGE *storage)
596 {
597 UCHAR *capacity_response = storage -> ux_host_class_storage_trans_data;
598
599 /* If capacity response OK, save last LBA and LB size. */
600 if (storage -> ux_host_class_storage_sense_code == 0)
601 {
602 storage -> ux_host_class_storage_last_sector_number =
603 _ux_utility_long_get_big_endian(capacity_response +
604 UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_LBA);
605 storage -> ux_host_class_storage_sector_size =
606 _ux_utility_long_get_big_endian(capacity_response +
607 UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_SECTOR_SIZE);
608
609 /* Media inserted to LUN. */
610 _ux_host_class_storage_lun_media_insert(storage);
611 }
612
613 /* Free allocated buffer. */
614 _ux_utility_memory_free(capacity_response);
615 }
_ux_host_class_storage_format_cap_save(UX_HOST_CLASS_STORAGE * storage)616 static inline VOID _ux_host_class_storage_format_cap_save(UX_HOST_CLASS_STORAGE *storage)
617 {
618 UCHAR *format_cap_response = storage -> ux_host_class_storage_trans_data;
619
620 /* There is nothing to save. */
621 /* Free allocated resource. */
622 _ux_utility_memory_free(format_cap_response);
623 }
624
_ux_host_class_storage_lun_scan(UX_HOST_CLASS_STORAGE * storage,ULONG do_unmount)625 static inline ULONG _ux_host_class_storage_lun_scan(UX_HOST_CLASS_STORAGE *storage,
626 ULONG do_unmount)
627 {
628 UX_HOST_CLASS *class_inst;
629 UX_HOST_CLASS_STORAGE_MEDIA *storage_media;
630 ULONG media_index;
631 ULONG n_found;
632
633 /* We may need to unmount this partition if it was mounted before.
634 To do so, we need to parse the existing media instance and find out
635 if this partition was already mounted. */
636 class_inst = storage -> ux_host_class_storage_class;
637 storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class_inst -> ux_host_class_media;
638
639 /* Scan all instances of media. */
640 for (media_index = 0, n_found = 0;
641 media_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA;
642 storage_media++, media_index++)
643 {
644
645 /* Check storage instance and lun number. */
646 if (storage_media -> ux_host_class_storage_media_status != UX_USED)
647 continue;
648 if (storage_media -> ux_host_class_storage_media_storage != storage)
649 continue;
650 if (storage_media -> ux_host_class_storage_media_lun !=
651 storage -> ux_host_class_storage_lun)
652 continue;
653
654 /* Found mounted media. */
655 n_found ++;
656
657 /* If no unmount, just check next media instance. */
658 if (do_unmount == UX_FALSE)
659 continue;
660
661 /* Free the storage media. */
662 storage_media -> ux_host_class_storage_media_status = UX_UNUSED;
663
664 /* Invoke callback for media removal. */
665 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
666 {
667
668 /* Call system change function. */
669 _ux_system_host -> ux_system_host_change_function(UX_STORAGE_MEDIA_REMOVAL,
670 storage -> ux_host_class_storage_class,
671 (VOID *) storage_media);
672 }
673 }
674
675 /* Return number of medias found and unmounted. */
676 return(n_found);
677 }
678
_ux_host_class_storage_unit_ready_check(UX_HOST_CLASS_STORAGE * storage)679 static inline VOID _ux_host_class_storage_unit_ready_check(UX_HOST_CLASS_STORAGE *storage)
680 {
681 ULONG n;
682
683 /* The LUN is ready. */
684 if (storage -> ux_host_class_storage_sense_code == 0)
685 {
686
687 /* Check if LUN is mounted. */
688 n = _ux_host_class_storage_lun_scan(storage, UX_FALSE);
689
690 /* If LUN is already mounted, check next LUN. */
691 if (n > 0)
692 {
693
694 /* LUN is mounted, just check next LUN. */
695 storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN;
696 return;
697 }
698
699 /* Next mounting steps : Inquiry() -> ReadFormatCapacity() -> mount(). */
700 storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_INQUIRY;
701 return;
702 }
703
704 /* The LUN not ready cases have been done before. */
705
706 /* Just check next LUN. */
707 storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN;
708 }
709
_ux_host_class_storage_lun_is_removable(UX_HOST_CLASS_STORAGE * storage)710 static inline UINT _ux_host_class_storage_lun_is_removable(UX_HOST_CLASS_STORAGE *storage)
711 {
712 UINT lun_index = storage -> ux_host_class_storage_lun;
713 UINT removable = storage -> ux_host_class_storage_lun_removable_media_flags[lun_index] &
714 UX_HOST_CLASS_STORAGE_MEDIA_REMOVABLE;
715 return(removable);
716 }
_ux_host_class_storage_lun_type_is_known(UX_HOST_CLASS_STORAGE * storage)717 static inline UINT _ux_host_class_storage_lun_type_is_known(UX_HOST_CLASS_STORAGE *storage)
718 {
719 UINT lun_index = storage -> ux_host_class_storage_lun;
720 UINT lun_type = storage -> ux_host_class_storage_lun_types[lun_index];
721 return((lun_type == UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK) ||
722 (lun_type == UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK) ||
723 (lun_type == UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK));
724 }
725
_ux_host_class_storage_lun_media_insert(UX_HOST_CLASS_STORAGE * storage)726 static inline VOID _ux_host_class_storage_lun_media_insert(UX_HOST_CLASS_STORAGE *storage)
727 {
728 UX_HOST_CLASS *class_inst;
729 UX_HOST_CLASS_STORAGE_MEDIA *storage_media;
730 INT media_index;
731
732 /* Get class. */
733 class_inst = storage -> ux_host_class_storage_class;
734
735 /* Find a free media slot for inserted media. */
736 storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class_inst -> ux_host_class_media;
737 for (media_index = 0; media_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA;
738 storage_media ++, media_index ++)
739 {
740
741 /* Skip used storage media slots. */
742 if (storage_media -> ux_host_class_storage_media_status != UX_USED)
743 {
744
745 /* Use this free storage media slot. */
746 storage_media -> ux_host_class_storage_media_status = UX_USED;
747 storage_media -> ux_host_class_storage_media_storage = storage;
748
749 /* Save media information. */
750 storage_media -> ux_host_class_storage_media_lun = (UCHAR)storage -> ux_host_class_storage_lun;
751 storage_media -> ux_host_class_storage_media_sector_size = (USHORT)storage -> ux_host_class_storage_sector_size;
752 storage_media -> ux_host_class_storage_media_number_sectors = storage -> ux_host_class_storage_last_sector_number + 1;
753
754 /* Invoke callback for media insertion. */
755 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
756 {
757
758 /* Call system change function. */
759 /* In standalone mode, no state running (read/write) expected in callback. */
760 _ux_system_host -> ux_system_host_change_function(UX_STORAGE_MEDIA_INSERTION,
761 storage -> ux_host_class_storage_class, (VOID *) storage_media);
762 }
763
764 /* Media saved OK. */
765 return;
766 }
767 }
768
769 /* No free slot. */
770 return;
771 }
772
_ux_host_class_storage_transport_sense_check(UX_HOST_CLASS_STORAGE * storage)773 static inline UINT _ux_host_class_storage_transport_sense_check(UX_HOST_CLASS_STORAGE *storage)
774 {
775 ULONG sense_key;
776
777 if (storage -> ux_host_class_storage_sense_code == 0)
778 return(UX_FALSE);
779
780 sense_key = UX_HOST_CLASS_STORAGE_SENSE_KEY(storage -> ux_host_class_storage_sense_code);
781 switch(sense_key)
782 {
783 case UX_HOST_CLASS_STORAGE_SENSE_KEY_NOT_READY:
784
785 /* Remove the mounted LUN media. */
786 _ux_host_class_storage_lun_scan(storage, UX_TRUE);
787
788 /* The LUN is not ready, check next any way. */
789 storage -> ux_host_class_storage_state_state =
790 UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN;
791
792 /* We have changed state. */
793 return(UX_TRUE);
794
795 case UX_HOST_CLASS_STORAGE_SENSE_KEY_UNIT_ATTENTION:
796
797 /* Remove the mounted LUN media. */
798 _ux_host_class_storage_lun_scan(storage, UX_TRUE);
799
800 /* Do immediate ready check again. */
801 storage -> ux_host_class_storage_state_state =
802 UX_HOST_CLASS_STORAGE_STATE_TEST_READY;
803
804 /* We have changed state. */
805 return(UX_TRUE);
806
807 case UX_HOST_CLASS_STORAGE_SENSE_KEY_DATA_PROTECT:
808
809 /* Fall through. */
810 default:
811
812 /* Nothing to do now. */
813 break;
814 }
815
816 /* State manated by others. */
817 return(UX_FALSE);
818 }
819 #endif
820