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