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