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