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 /** FileX Component                                                       */
17 /**                                                                       */
18 /**   FileX NAND FLASH Simulator Driver                                   */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #include "fx_api.h"
27 #include "lx_api.h"
28 
29 
30 /* Create a NAND flash control block.  */
31 
32 LX_NAND_FLASH       nand_flash;
33 
34 /* Memory buffer size should be at least 7 * total block count + 2 * page size,
35    that is 7 * 1024 + 2 * 528 = 8224 bytes */
36 ULONG               lx_memory_buffer[8224 / sizeof (ULONG)];
37 
38 /* Define the NAND flash simulation initialization function.  */
39 
40 UINT  _lx_nand_flash_simulator_initialize(LX_NAND_FLASH *nand_flash);
41 VOID  _fx_nand_flash_read_sectors(ULONG logical_sector, ULONG sectors, UCHAR *destination_buffer);
42 VOID  _fx_nand_flash_write_sectors(ULONG logical_sector, ULONG sectors, UCHAR *source_buffer);
43 
44 
45 /* The simulated NAND driver relies on the fx_media_format call to be made prior to
46    the fx_media_open call.
47 
48         fx_media_format(&ram_disk,
49                             _fx_nand_sim_driver,    // Driver entry
50                             FX_NULL,                // Unused
51                             media_memory,           // Media buffer pointer
52                             sizeof(media_memory),   // Media buffer size
53                             "MY_NAND_DISK",         // Volume Name
54                             1,                      // Number of FATs
55                             32,                     // Directory Entries
56                             0,                      // Hidden sectors
57                             120,                    // Total sectors
58                             2048,                   // Sector size
59                             1,                      // Sectors per cluster
60                             1,                      // Heads
61                             1);                     // Sectors per track
62 
63 */
64 
65 
66 VOID  _fx_nand_flash_simulator_driver(FX_MEDIA *media_ptr);
67 
68 
69 /**************************************************************************/
70 /*                                                                        */
71 /*  FUNCTION                                               RELEASE        */
72 /*                                                                        */
73 /*    _fx_nand_simulator_driver                           PORTABLE C      */
74 /*                                                           6.2.1       */
75 /*  AUTHOR                                                                */
76 /*                                                                        */
77 /*    William E. Lamie, Microsoft Corporation                             */
78 /*                                                                        */
79 /*  DESCRIPTION                                                           */
80 /*                                                                        */
81 /*    This function is the entry point to the generic NAND simulated      */
82 /*    disk driver that is delivered with the flash wear leveling product  */
83 /*    LevelX.                                                             */
84 /*                                                                        */
85 /*    This driver also serves as a template for developing other LevelX   */
86 /*    NAND flash drivers for actual flash devices. Simply replace the     */
87 /*    read/write sector logic with calls to read/write from the           */
88 /*    appropriate physical device access functions.                       */
89 /*                                                                        */
90 /*    FileX NAND FLASH structures look like the following:                */
91 /*                                                                        */
92 /*          Logical Sector                  Contents                      */
93 /*                                                                        */
94 /*              0                       Boot record                       */
95 /*              1                       FAT Area Start                    */
96 /*              +FAT Sectors            Root Directory Start              */
97 /*              +Directory Sectors      Data Sector Start                 */
98 /*                                                                        */
99 /*                                                                        */
100 /*  INPUT                                                                 */
101 /*                                                                        */
102 /*    media_ptr                             Media control block pointer   */
103 /*                                                                        */
104 /*  OUTPUT                                                                */
105 /*                                                                        */
106 /*    None                                                                */
107 /*                                                                        */
108 /*  CALLS                                                                 */
109 /*                                                                        */
110 /*    _lx_nand_flash_close                  Close NAND flash manager      */
111 /*    _lx_nand_flash_open                   Open NAND flash manager       */
112 /*    _lx_nand_flash_sector_read            Read a NAND sector            */
113 /*    _lx_nand_flash_sector_release         Release a NAND sector         */
114 /*    _lx_nand_flash_sector_write           Write a NAND sector           */
115 /*                                                                        */
116 /*  CALLED BY                                                             */
117 /*                                                                        */
118 /*    FileX System Functions                                              */
119 /*                                                                        */
120 /*  RELEASE HISTORY                                                       */
121 /*                                                                        */
122 /*    DATE              NAME                      DESCRIPTION             */
123 /*                                                                        */
124 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
125 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
126 /*                                            resulting in version 6.1    */
127 /*  06-02-2021     Bhupendra Naphade        Modified comment(s),          */
128 /*                                            resulting in version 6.1.7  */
129 /*  03-08-2023     Xiuwen Cai               Modified comment(s),          */
130 /*                                            changed to use new API,     */
131 /*                                            resulting in version 6.2.1 */
132 /*                                                                        */
133 /**************************************************************************/
_fx_nand_flash_simulator_driver(FX_MEDIA * media_ptr)134 VOID  _fx_nand_flash_simulator_driver(FX_MEDIA *media_ptr)
135 {
136 
137 ULONG   logical_sector;
138 ULONG   count;
139 UCHAR   *buffer;
140 UINT    status;
141 
142 
143     /* There are several useful/important pieces of information contained in the media
144        structure, some of which are supplied by FileX and others are for the driver to
145        setup. The following is a summary of the necessary FX_MEDIA structure members:
146 
147             FX_MEDIA Member                              Meaning
148 
149         fx_media_driver_request             FileX request type. Valid requests from FileX are
150                                             as follows:
151 
152                                                     FX_DRIVER_READ
153                                                     FX_DRIVER_WRITE
154                                                     FX_DRIVER_FLUSH
155                                                     FX_DRIVER_ABORT
156                                                     FX_DRIVER_INIT
157                                                     FX_DRIVER_BOOT_READ
158                                                     FX_DRIVER_RELEASE_SECTORS
159                                                     FX_DRIVER_BOOT_WRITE
160                                                     FX_DRIVER_UNINIT
161 
162         fx_media_driver_status              This value is RETURNED by the driver. If the
163                                             operation is successful, this field should be
164                                             set to FX_SUCCESS for before returning. Otherwise,
165                                             if an error occurred, this field should be set
166                                             to FX_IO_ERROR.
167 
168         fx_media_driver_buffer              Pointer to buffer to read or write sector data.
169                                             This is supplied by FileX.
170 
171         fx_media_driver_logical_sector      Logical sector FileX is requesting.
172 
173         fx_media_driver_sectors             Number of sectors FileX is requesting.
174 
175 
176        The following is a summary of the optional FX_MEDIA structure members:
177 
178             FX_MEDIA Member                              Meaning
179 
180         fx_media_driver_info                Pointer to any additional information or memory.
181                                             This is optional for the driver use and is setup
182                                             from the fx_media_open call. The RAM disk uses
183                                             this pointer for the RAM disk memory itself.
184 
185         fx_media_driver_write_protect       The DRIVER sets this to FX_TRUE when media is write
186                                             protected. This is typically done in initialization,
187                                             but can be done anytime.
188 
189         fx_media_driver_free_sector_update  The DRIVER sets this to FX_TRUE when it needs to
190                                             know when clusters are released. This is important
191                                             for FLASH wear-leveling drivers.
192 
193         fx_media_driver_system_write        FileX sets this flag to FX_TRUE if the sector being
194                                             written is a system sector, e.g., a boot, FAT, or
195                                             directory sector. The driver may choose to use this
196                                             to initiate error recovery logic for greater fault
197                                             tolerance.
198 
199         fx_media_driver_data_sector_read    FileX sets this flag to FX_TRUE if the sector(s) being
200                                             read are file data sectors, i.e., NOT system sectors.
201 
202         fx_media_driver_sector_type         FileX sets this variable to the specific type of
203                                             sector being read or written. The following sector
204                                             types are identified:
205 
206                                                     FX_UNKNOWN_SECTOR
207                                                     FX_BOOT_SECTOR
208                                                     FX_FAT_SECTOR
209                                                     FX_DIRECTORY_SECTOR
210                                                     FX_DATA_SECTOR
211     */
212 
213     /* Process the driver request specified in the media control block.  */
214     switch(media_ptr -> fx_media_driver_request)
215     {
216 
217         case FX_DRIVER_READ:
218         {
219 
220             /* Read sector(s) from NAND flash.  */
221             logical_sector =  media_ptr -> fx_media_driver_logical_sector;
222             count =  media_ptr -> fx_media_driver_sectors;
223             buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
224             while (count)
225             {
226 
227                 /* Call LevelX to read one flash sector.  */
228                 status =  _lx_nand_flash_sector_read(&nand_flash, logical_sector, buffer);
229 
230                 /* Determine if the read was successful.  */
231                 if (status != LX_SUCCESS)
232                 {
233 
234                     /* Return an I/O error to FileX.  */
235                     media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
236 
237                     return;
238                 }
239 
240                 /* Successful sector read.  */
241                 count--;
242                 logical_sector++;
243                 buffer += media_ptr -> fx_media_bytes_per_sector;
244             }
245             /* Successful driver request.  */
246             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
247             break;
248         }
249 
250         case FX_DRIVER_WRITE:
251         {
252 
253             /* Write sector(s) to NAND flash.  */
254             logical_sector =  media_ptr -> fx_media_driver_logical_sector;
255             count =  media_ptr -> fx_media_driver_sectors;
256             buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
257             while (count)
258             {
259 
260                 /* Call LevelX to write a sector.  */
261                 status =  _lx_nand_flash_sector_write(&nand_flash, logical_sector, buffer);
262 
263                 /* Determine if the write was successful.  */
264                 if (status != LX_SUCCESS)
265                 {
266 
267                     /* Return an I/O error to FileX.  */
268                     media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
269 
270                     return;
271                 }
272 
273                 /* Successful sector write.  */
274                 count--;
275                 logical_sector++;
276                 buffer += media_ptr -> fx_media_bytes_per_sector;
277             }
278 
279             /* Successful driver request.  */
280             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
281             break;
282         }
283 
284         case FX_DRIVER_RELEASE_SECTORS:
285         {
286 
287             /* Release the mapping of this sector.  */
288             logical_sector =  media_ptr -> fx_media_driver_logical_sector;
289             count =  media_ptr -> fx_media_driver_sectors;
290             while (count)
291             {
292 
293                 /* Call LevelX to release a sector mapping.  */
294                 status =  _lx_nand_flash_sector_release(&nand_flash, logical_sector);
295 
296                 /* Determine if the sector release was successful.  */
297                 if (status != LX_SUCCESS)
298                 {
299 
300                     /* Return an I/O error to FileX.  */
301                     media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
302 
303                     return;
304                 }
305 
306                 /* Successful sector release.  */
307                 count--;
308                 logical_sector++;
309             }
310 
311             /* Successful driver request.  */
312             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
313             break;
314         }
315 
316         case FX_DRIVER_FLUSH:
317         {
318 
319             /* Return driver success.  */
320             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
321             break;
322         }
323 
324         case FX_DRIVER_ABORT:
325         {
326 
327             /* Return driver success.  */
328             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
329             break;
330         }
331 
332         case FX_DRIVER_INIT:
333         {
334 
335             /* FLASH drivers are responsible for setting several fields in the
336                media structure, as follows:
337 
338                     media_ptr -> fx_media_driver_free_sector_update
339                     media_ptr -> fx_media_driver_write_protect
340 
341                The fx_media_driver_free_sector_update flag is used to instruct
342                FileX to inform the driver whenever sectors are not being used.
343                This is especially useful for FLASH managers so they don't have
344                maintain mapping for sectors no longer in use.
345 
346                The fx_media_driver_write_protect flag can be set anytime by the
347                driver to indicate the media is not writable.  Write attempts made
348                when this flag is set are returned as errors.  */
349 
350             /* Perform basic initialization here... since the boot record is going
351                to be read subsequently and again for volume name requests.  */
352 
353             /* With flash wear leveling, FileX should tell wear leveling when sectors
354                are no longer in use.  */
355             media_ptr -> fx_media_driver_free_sector_update =  FX_TRUE;
356 
357             /* Open the NAND flash simulation.  */
358             status =  _lx_nand_flash_open(&nand_flash, "sim nand flash", _lx_nand_flash_simulator_initialize, lx_memory_buffer, sizeof(lx_memory_buffer));
359 
360             /* Determine if the flash open was successful.  */
361             if (status != LX_SUCCESS)
362             {
363 
364                 /* Return an I/O error to FileX.  */
365                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
366 
367                 return;
368             }
369 
370             /* Successful driver request.  */
371             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
372             break;
373         }
374 
375         case FX_DRIVER_UNINIT:
376         {
377 
378             /* There is nothing to do in this case for the RAM driver.  For actual
379                devices some shutdown processing may be necessary.  */
380 
381             /* Close the NAND flash simulation.  */
382             status =  _lx_nand_flash_close(&nand_flash);
383 
384             /* Determine if the flash close was successful.  */
385             if (status != LX_SUCCESS)
386             {
387 
388                 /* Return an I/O error to FileX.  */
389                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
390 
391                 return;
392             }
393 
394             /* Successful driver request.  */
395             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
396             break;
397         }
398 
399         case FX_DRIVER_BOOT_READ:
400         {
401 
402             /* Read the boot record and return to the caller.  */
403             status =  _lx_nand_flash_sector_read(&nand_flash, 0, (UCHAR *) media_ptr -> fx_media_driver_buffer);
404 
405             /* Determine if the read was successful.  */
406             if (status != LX_SUCCESS)
407             {
408 
409                 /* Return an I/O error to FileX.  */
410                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
411 
412                 return;
413             }
414 
415             /* Successful driver request.  */
416             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
417             break;
418         }
419 
420         case FX_DRIVER_BOOT_WRITE:
421         {
422 
423             /* Write the boot record and return to the caller.  */
424             status =  _lx_nand_flash_sector_write(&nand_flash, 0, (UCHAR *) media_ptr -> fx_media_driver_buffer);
425 
426             /* Determine if the write was successful.  */
427             if (status != LX_SUCCESS)
428             {
429 
430                 /* Return an I/O error to FileX.  */
431                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
432 
433                 return;
434             }
435 
436             /* Successful driver request.  */
437             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
438             break ;
439         }
440 
441         default:
442         {
443 
444             /* Invalid driver request.  */
445             media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
446             break;
447         }
448     }
449 }
450 
451