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 /* Defined if FileX is not integrated in USBX
34 and it's used as external module for file system. */
35
36 /* #define UX_HOST_CLASS_STORAGE_EXT_FILEX */
37
38 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
39
40 #ifdef FX_API_H /* For test, confirm FX is not included before. */
41 #error fx_api.h should not be included in this mode
42 #endif
43
44 /* FX not integrated in UX, but used as external module. */
45 #if defined(UX_HOST_CLASS_STORAGE_EXT_FILEX)
46
47 /* FX related things needs define here. */
48 #include "fx_api.h"
49 #define UX_MEDIA FX_MEDIA
50 VOID _ux_host_class_storage_driver_entry(UX_MEDIA *media);
51
52 /* FX driver is available to support FX as external module. */
53 #ifndef UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
54 #define UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
55 #endif
56 #endif
57 #else
58
59 /* FX driver is used for RTOS mode by default. */
60 #ifndef UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
61 #define UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE
62 #endif
63 #endif
64
65
66 #if defined(UX_HOST_CLASS_STORAGE_DRIVER_ENTRY_ENABLE)
67 /**************************************************************************/
68 /* */
69 /* FUNCTION RELEASE */
70 /* */
71 /* _ux_host_class_storage_driver_entry PORTABLE C */
72 /* 6.1.12 */
73 /* AUTHOR */
74 /* */
75 /* Chaoqiong Xiao, Microsoft Corporation */
76 /* */
77 /* DESCRIPTION */
78 /* */
79 /* This function is the entry point for the FileX file system. All */
80 /* FileX driver I/O calls are are multiplexed here and rerouted to */
81 /* the proper USB storage class functions. */
82 /* */
83 /* When the entry is for storage with FX support (not in standalone */
84 /* mode, and with FileX), the FX media is openned in storage mount */
85 /* flow, and can be directly used in application after mounted. */
86 /* */
87 /* When the entry is for no FX mode (FX in external module, and USBX */
88 /* is compiled without FileX integration), it is an example with */
89 /* disk partition support. In this case the FX media does not operate */
90 /* inside the storage flow. Actions are taken when application mounts */
91 /* media to FX_MEDIA and then have access to media APIs. */
92 /* */
93 /* In no FX mode demo, it assumes media is managed with partition */
94 /* start from sector address of FX_MEDIA::fx_media_reserved_for_user. */
95 /* */
96 /* The following links are not initialized in no FX mode, they must be */
97 /* initialized before using the entry in no FX mode: */
98 /* - FX_MEDIA::fx_media_reserved_for_user */
99 /* Partition start sector inside */
100 /* the whole storage media, must */
101 /* set before media open */
102 /* - FX_MEDIA::fx_media_driver_info Pointer to storage media, */
103 /* assigned while calling media */
104 /* open (fx_media_open) */
105 /* */
106 /* INPUT */
107 /* */
108 /* media FileX media pointer */
109 /* */
110 /* OUTPUT */
111 /* */
112 /* None */
113 /* */
114 /* CALLS */
115 /* */
116 /* _ux_host_class_storage_sense_code_translate */
117 /* Translate error status codes */
118 /* _ux_host_class_storage_media_read Read sector(s) */
119 /* _ux_host_class_storage_media_write Write sector(s) */
120 /* _ux_host_semaphore_get Get protection semaphore */
121 /* _ux_host_semaphore_put Release protection semaphore */
122 /* */
123 /* CALLED BY */
124 /* */
125 /* FileX */
126 /* */
127 /* RELEASE HISTORY */
128 /* */
129 /* DATE NAME DESCRIPTION */
130 /* */
131 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
132 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
133 /* added option to disable FX */
134 /* media integration, */
135 /* resulting in version 6.1 */
136 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
137 /* resulting in version 6.1.10 */
138 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
139 /* added implement to support */
140 /* external FX mode, */
141 /* resulting in version 6.1.11 */
142 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
143 /* improved external FX mode, */
144 /* resulting in version 6.1.12 */
145 /* */
146 /**************************************************************************/
_ux_host_class_storage_driver_entry(FX_MEDIA * media)147 VOID _ux_host_class_storage_driver_entry(FX_MEDIA *media)
148 {
149
150 UINT status;
151 UX_HOST_CLASS_STORAGE *storage;
152 UX_HOST_CLASS_STORAGE_MEDIA *storage_media;
153 ULONG partition_start;
154
155
156 /* Get the pointers to the instances and partition start. */
157 #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
158 storage = (UX_HOST_CLASS_STORAGE *) media -> fx_media_driver_info;
159 storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) media -> fx_media_reserved_for_user;
160 partition_start = storage_media -> ux_host_class_storage_media_partition_start;
161 #else
162 storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) media -> fx_media_driver_info;
163 storage = storage_media -> ux_host_class_storage_media_storage;
164 partition_start = (ULONG) media -> fx_media_reserved_for_user;
165 #endif
166
167 /* Ensure the instance is valid. */
168 if ((storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE) &&
169 (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_MOUNTING))
170 {
171
172 /* Class instance is invalid. Return an error! */
173 media -> fx_media_driver_status = FX_PTR_ERROR;
174 return;
175 }
176
177 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
178
179 /* Ensure the media is valid. */
180 if ((storage_media -> ux_host_class_storage_media_storage != storage) ||
181 (storage_media -> ux_host_class_storage_media_status != UX_USED))
182 {
183
184 /* Media instance is invalid. */
185 media -> fx_media_driver_status = FX_PTR_ERROR;
186 return;
187 }
188 #endif
189
190 /* Protect Thread reentry to this instance. */
191 status = _ux_host_class_storage_lock(storage, UX_WAIT_FOREVER);
192 if (status != UX_SUCCESS)
193 {
194
195 /* Unable to lock, return an error. */
196 media -> fx_media_driver_status = FX_INVALID_STATE;
197 return;
198 }
199
200 /* Restore the LUN number from the media instance. */
201 storage -> ux_host_class_storage_lun = storage_media -> ux_host_class_storage_media_lun;
202
203 /* And the sector size. */
204 storage -> ux_host_class_storage_sector_size =
205 storage_media -> ux_host_class_storage_media_sector_size;
206
207 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
208
209 /* Restore current used last sector number. */
210 storage -> ux_host_class_storage_last_sector_number =
211 storage_media -> ux_host_class_storage_media_number_sectors - 1;
212 #endif
213
214 /* Look at the request specified by the FileX caller. */
215 switch (media -> fx_media_driver_request)
216 {
217
218 case FX_DRIVER_READ:
219
220 /* Read one or more sectors. */
221 status = _ux_host_class_storage_media_read(storage,
222 media -> fx_media_driver_logical_sector + partition_start,
223 media -> fx_media_driver_sectors,
224 media -> fx_media_driver_buffer);
225
226 /* Check completion status. */
227 if (status == UX_SUCCESS)
228 media -> fx_media_driver_status = FX_SUCCESS;
229 else
230 {
231
232 #if defined(UX_HOST_STANDALONE)
233
234 /* Poll status. */
235 _ux_host_class_storage_media_check(storage);
236 #endif
237
238 media -> fx_media_driver_status =
239 _ux_host_class_storage_sense_code_translate(storage, status);
240 }
241 break;
242
243
244 case FX_DRIVER_WRITE:
245
246 /* Write one or more sectors. */
247 status = _ux_host_class_storage_media_write(storage,
248 media -> fx_media_driver_logical_sector + partition_start,
249 media -> fx_media_driver_sectors,
250 media -> fx_media_driver_buffer);
251
252 /* Check completion status. */
253 if (status == UX_SUCCESS)
254 media -> fx_media_driver_status = FX_SUCCESS;
255 else
256 {
257
258 #if defined(UX_HOST_STANDALONE)
259
260 /* Poll status. */
261 _ux_host_class_storage_media_check(storage);
262 #endif
263
264 media -> fx_media_driver_status =
265 _ux_host_class_storage_sense_code_translate(storage,status);
266 }
267 break;
268
269
270 case FX_DRIVER_FLUSH:
271
272 /* Nothing to do. Just return a good status! */
273 media -> fx_media_driver_status = FX_SUCCESS;
274 break;
275
276
277 case FX_DRIVER_ABORT:
278
279 /* Nothing to do. Just return a good status! */
280 media -> fx_media_driver_status = FX_SUCCESS;
281 break;
282
283
284 case FX_DRIVER_INIT:
285
286 #if defined(UX_HOST_STANDALONE)
287
288 /* Poll status. */
289 _ux_host_class_storage_media_check(storage);
290 #endif
291
292 /* Check for media protection. We must do this operation here because FileX clears all the
293 media fields before init. */
294 if (storage -> ux_host_class_storage_write_protected_media == UX_TRUE)
295
296 /* The media is Write Protected. We tell FileX. */
297 media -> fx_media_driver_write_protect = UX_TRUE;
298
299 /* This function always succeeds. */
300 media -> fx_media_driver_status = FX_SUCCESS;
301 break;
302
303
304 case FX_DRIVER_UNINIT:
305
306 /* Nothing to do. Just return a good status! */
307 media -> fx_media_driver_status = FX_SUCCESS;
308 break;
309
310
311 case FX_DRIVER_BOOT_READ:
312
313 /* Read the media boot sector. */
314 status = _ux_host_class_storage_media_read(storage,
315 partition_start, 1, media -> fx_media_driver_buffer);
316
317 /* Check completion status. */
318 if (status == UX_SUCCESS)
319 media -> fx_media_driver_status = FX_SUCCESS;
320 else
321 {
322
323 #if defined(UX_HOST_STANDALONE)
324
325 /* Poll status. */
326 _ux_host_class_storage_media_check(storage);
327 #endif
328
329 media -> fx_media_driver_status =
330 _ux_host_class_storage_sense_code_translate(storage,status);
331 }
332 break;
333
334
335 case FX_DRIVER_BOOT_WRITE:
336
337 /* Write the boot sector. */
338 status = _ux_host_class_storage_media_write(storage,
339 partition_start, 1, media -> fx_media_driver_buffer);
340
341 /* Check completion status. */
342 if (status == UX_SUCCESS)
343 media -> fx_media_driver_status = FX_SUCCESS;
344 else
345 {
346
347 #if defined(UX_HOST_STANDALONE)
348
349 /* Poll status. */
350 _ux_host_class_storage_media_check(storage);
351 #endif
352
353 media -> fx_media_driver_status =
354 _ux_host_class_storage_sense_code_translate(storage,status);
355 }
356 break;
357
358
359 default:
360
361 /* Invalid request from FileX */
362 media -> fx_media_driver_status = FX_IO_ERROR;
363 break;
364 }
365
366 /* Unprotect thread reentry to this instance. */
367 _ux_host_class_storage_unlock(storage);
368 }
369 #endif
370