1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** USBX Component */
16 /** */
17 /** Storage Class */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Include necessary system files. */
24
25 #define UX_SOURCE_CODE
26
27 #include "ux_api.h"
28 #include "ux_host_class_storage.h"
29 #include "ux_host_stack.h"
30
31 #if defined(UX_HOST_STANDALONE)
32
33 extern VOID _ux_host_class_storage_read_initialize(UX_HOST_CLASS_STORAGE *storage,
34 ULONG sector_start, ULONG sector_count);
35
36 extern VOID _ux_host_class_storage_write_initialize(UX_HOST_CLASS_STORAGE *storage,
37 ULONG sector_start, ULONG sector_count);
38
39
40 /**************************************************************************/
41 /* */
42 /* FUNCTION RELEASE */
43 /* */
44 /* _ux_host_class_storage_read_write_run PORTABLE C */
45 /* 6.2.1 */
46 /* AUTHOR */
47 /* */
48 /* Chaoqiong Xiao, Microsoft Corporation */
49 /* */
50 /* DESCRIPTION */
51 /* */
52 /* This function runs state machine to read or write one or more */
53 /* logical sector on a selected media of a storage function. */
54 /* */
55 /* It's valid only in standalone mode. */
56 /* */
57 /* Note it must be used in case following conditions are true: */
58 /* - storage insstance is live */
59 /* - storage is locked for specific LUN */
60 /* - the main storage state must be idle */
61 /* */
62 /* INPUT */
63 /* */
64 /* storage Pointer to storage class */
65 /* read_write Set to UX_TRUE to read */
66 /* sector_start Starting sector */
67 /* sector_count Number of sectors to read */
68 /* data_pointer Pointer to data to read */
69 /* */
70 /* OUTPUT */
71 /* */
72 /* Completion Status */
73 /* UX_STATE_WAIT States started/in progress */
74 /* UX_STATE_NEXT Read/write is done, next call */
75 /* starts read/write again. */
76 /* */
77 /* CALLS */
78 /* */
79 /* _ux_host_class_storage_read_initialize */
80 /* Initialize the CBW */
81 /* _ux_host_class_storage_write_initialize */
82 /* Initialize the CBW */
83 /* _ux_system_error_handler The error trap */
84 /* _ux_system_tasks_run Run USB system tasks */
85 /* */
86 /* CALLED BY */
87 /* */
88 /* Storage Class */
89 /* */
90 /* RELEASE HISTORY */
91 /* */
92 /* DATE NAME DESCRIPTION */
93 /* */
94 /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */
95 /* 03-08-2023 Chaoqiong Xiao Modified comment(s), */
96 /* checked device state, */
97 /* resulting in version 6.2.1 */
98 /* */
99 /**************************************************************************/
_ux_host_class_storage_read_write_run(UX_HOST_CLASS_STORAGE * storage,ULONG read_write,ULONG sector_start,ULONG sector_count,UCHAR * data_pointer)100 UINT _ux_host_class_storage_read_write_run(UX_HOST_CLASS_STORAGE *storage,
101 ULONG read_write,
102 ULONG sector_start, ULONG sector_count, UCHAR *data_pointer)
103 {
104
105 UX_DEVICE *device;
106
107 #if defined UX_HOST_CLASS_STORAGE_STATE_CHECK_ENABLE
108 UX_INTERRUPT_SAVE_AREA
109
110 /* Check states - storage must be live, locked and main state machine idle. */
111 UX_DISABLE
112 if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE ||
113 (storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK) == 0 ||
114 storage -> ux_host_class_storage_state_state != UX_STATE_IDLE)
115 {
116 UX_RESTORE
117
118 /* Error trap. */
119 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NOT_READY);
120
121 /* The state is not ready for read. */
122 storage -> ux_host_class_storage_status = UX_TRANSFER_NOT_READY;
123 storage -> ux_host_class_storage_op_state = UX_STATE_RESET;
124 return(UX_STATE_ERROR);
125 }
126 UX_RESTORE
127 #endif
128
129 /* If trace is enabled, insert this event into the trace buffer. */
130 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_READ, storage, sector_start, sector_count, data_pointer, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
131
132 /* Get device. */
133 device = storage -> ux_host_class_storage_device;
134
135 switch(storage -> ux_host_class_storage_op_state)
136 {
137 case UX_STATE_IDLE: /* Fall through. */
138 case UX_STATE_ERROR: /* Fall through. */
139 case UX_STATE_RESET:
140
141 /* Initialize CBW. */
142 if (read_write)
143 _ux_host_class_storage_read_initialize(storage, sector_start, sector_count);
144 else
145 _ux_host_class_storage_write_initialize(storage, sector_start, sector_count);
146
147 /* Initialize for transport. */
148 UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(storage);
149 storage -> ux_host_class_storage_trans_data = data_pointer;
150
151 /* Next : wait */
152 storage -> ux_host_class_storage_op_state = UX_STATE_WAIT;
153
154 /* Fall through. */
155 case UX_STATE_WAIT:
156
157 /* Run tasks, including transport task. */
158 _ux_system_host_tasks_run();
159
160 /* Check if device is still available. */
161 if (device -> ux_device_state != UX_DEVICE_CONFIGURED)
162 {
163
164 /* Instance should have been destroyed, just return. */
165 return(UX_STATE_EXIT);
166 }
167
168 /* Fatal error. */
169 if (storage -> ux_host_class_storage_op_state < UX_STATE_IDLE)
170 return(UX_STATE_EXIT);
171
172 /* It's done with/without error. */
173 if (storage -> ux_host_class_storage_op_state <= UX_STATE_NEXT)
174 return(UX_STATE_NEXT);
175
176 /* Wait. */
177 return(UX_STATE_WAIT);
178
179 /* Unexpected states. */
180 default:
181 storage -> ux_host_class_storage_op_state = UX_STATE_RESET;
182 break;
183 }
184
185 /* Return fatal exit state status. */
186 return(UX_STATE_EXIT);
187 }
188 #endif
189