mirror of
https://github.com/eclipse-threadx/levelx.git
synced 2026-09-14 12:37:01 +08:00
Initial commit
This commit is contained in:
@@ -0,0 +1,441 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** FileX Component */
|
||||
/** */
|
||||
/** FileX NAND FLASH Simulator Driver */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "fx_api.h"
|
||||
#include "lx_api.h"
|
||||
|
||||
|
||||
/* Create a NAND flash control block. */
|
||||
|
||||
LX_NAND_FLASH nand_flash;
|
||||
|
||||
|
||||
/* Define the NAND flash simulation initialization function. */
|
||||
|
||||
UINT _lx_nand_flash_simulator_initialize(LX_NAND_FLASH *nand_flash);
|
||||
VOID _fx_nand_flash_read_sectors(ULONG logical_sector, ULONG sectors, UCHAR *destination_buffer);
|
||||
VOID _fx_nand_flash_write_sectors(ULONG logical_sector, ULONG sectors, UCHAR *source_buffer);
|
||||
|
||||
|
||||
/* The simulated NAND driver relies on the fx_media_format call to be made prior to
|
||||
the fx_media_open call.
|
||||
|
||||
fx_media_format(&ram_disk,
|
||||
_fx_nand_sim_driver, // Driver entry
|
||||
FX_NULL, // Unused
|
||||
media_memory, // Media buffer pointer
|
||||
sizeof(media_memory), // Media buffer size
|
||||
"MY_NAND_DISK", // Volume Name
|
||||
1, // Number of FATs
|
||||
32, // Directory Entries
|
||||
0, // Hidden sectors
|
||||
120, // Total sectors
|
||||
2048, // Sector size
|
||||
1, // Sectors per cluster
|
||||
1, // Heads
|
||||
1); // Sectors per track
|
||||
|
||||
*/
|
||||
|
||||
|
||||
VOID _fx_nand_flash_simulator_driver(FX_MEDIA *media_ptr);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_nand_simulator_driver PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is the entry point to the generic NAND simulated */
|
||||
/* disk driver that is delivered with the flash wear leveling product */
|
||||
/* LevelX. */
|
||||
/* */
|
||||
/* This driver also serves as a template for developing other LevelX */
|
||||
/* NAND flash drivers for actual flash devices. Simply replace the */
|
||||
/* read/write sector logic with calls to read/write from the */
|
||||
/* appropriate physical device access functions. */
|
||||
/* */
|
||||
/* FileX NAND FLASH structures look like the following: */
|
||||
/* */
|
||||
/* Logical Sector Contents */
|
||||
/* */
|
||||
/* 0 Boot record */
|
||||
/* 1 FAT Area Start */
|
||||
/* +FAT Sectors Root Directory Start */
|
||||
/* +Directory Sectors Data Sector Start */
|
||||
/* */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* media_ptr Media control block pointer */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _lx_nand_flash_close Close NAND flash manager */
|
||||
/* _lx_nand_flash_open Open NAND flash manager */
|
||||
/* _lx_nand_flash_sector_read Read a NAND sector */
|
||||
/* _lx_nand_flash_sector_release Release a NAND sector */
|
||||
/* _lx_nand_flash_sector_write Write a NAND sector */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _fx_nand_flash_simulator_driver(FX_MEDIA *media_ptr)
|
||||
{
|
||||
|
||||
ULONG logical_sector;
|
||||
ULONG count;
|
||||
UCHAR *buffer;
|
||||
UINT status;
|
||||
|
||||
|
||||
/* There are several useful/important pieces of information contained in the media
|
||||
structure, some of which are supplied by FileX and others are for the driver to
|
||||
setup. The following is a summary of the necessary FX_MEDIA structure members:
|
||||
|
||||
FX_MEDIA Member Meaning
|
||||
|
||||
fx_media_driver_request FileX request type. Valid requests from FileX are
|
||||
as follows:
|
||||
|
||||
FX_DRIVER_READ
|
||||
FX_DRIVER_WRITE
|
||||
FX_DRIVER_FLUSH
|
||||
FX_DRIVER_ABORT
|
||||
FX_DRIVER_INIT
|
||||
FX_DRIVER_BOOT_READ
|
||||
FX_DRIVER_RELEASE_SECTORS
|
||||
FX_DRIVER_BOOT_WRITE
|
||||
FX_DRIVER_UNINIT
|
||||
|
||||
fx_media_driver_status This value is RETURNED by the driver. If the
|
||||
operation is successful, this field should be
|
||||
set to FX_SUCCESS for before returning. Otherwise,
|
||||
if an error occurred, this field should be set
|
||||
to FX_IO_ERROR.
|
||||
|
||||
fx_media_driver_buffer Pointer to buffer to read or write sector data.
|
||||
This is supplied by FileX.
|
||||
|
||||
fx_media_driver_logical_sector Logical sector FileX is requesting.
|
||||
|
||||
fx_media_driver_sectors Number of sectors FileX is requesting.
|
||||
|
||||
|
||||
The following is a summary of the optional FX_MEDIA structure members:
|
||||
|
||||
FX_MEDIA Member Meaning
|
||||
|
||||
fx_media_driver_info Pointer to any additional information or memory.
|
||||
This is optional for the driver use and is setup
|
||||
from the fx_media_open call. The RAM disk uses
|
||||
this pointer for the RAM disk memory itself.
|
||||
|
||||
fx_media_driver_write_protect The DRIVER sets this to FX_TRUE when media is write
|
||||
protected. This is typically done in initialization,
|
||||
but can be done anytime.
|
||||
|
||||
fx_media_driver_free_sector_update The DRIVER sets this to FX_TRUE when it needs to
|
||||
know when clusters are released. This is important
|
||||
for FLASH wear-leveling drivers.
|
||||
|
||||
fx_media_driver_system_write FileX sets this flag to FX_TRUE if the sector being
|
||||
written is a system sector, e.g., a boot, FAT, or
|
||||
directory sector. The driver may choose to use this
|
||||
to initiate error recovery logic for greater fault
|
||||
tolerance.
|
||||
|
||||
fx_media_driver_data_sector_read FileX sets this flag to FX_TRUE if the sector(s) being
|
||||
read are file data sectors, i.e., NOT system sectors.
|
||||
|
||||
fx_media_driver_sector_type FileX sets this variable to the specific type of
|
||||
sector being read or written. The following sector
|
||||
types are identified:
|
||||
|
||||
FX_UNKNOWN_SECTOR
|
||||
FX_BOOT_SECTOR
|
||||
FX_FAT_SECTOR
|
||||
FX_DIRECTORY_SECTOR
|
||||
FX_DATA_SECTOR
|
||||
*/
|
||||
|
||||
/* Process the driver request specified in the media control block. */
|
||||
switch(media_ptr -> fx_media_driver_request)
|
||||
{
|
||||
|
||||
case FX_DRIVER_READ:
|
||||
{
|
||||
|
||||
/* Read sector(s) from NAND flash. */
|
||||
logical_sector = media_ptr -> fx_media_driver_logical_sector;
|
||||
count = media_ptr -> fx_media_driver_sectors;
|
||||
buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
|
||||
while (count)
|
||||
{
|
||||
|
||||
/* Call LevelX to read one flash sector. */
|
||||
status = _lx_nand_flash_sector_read(&nand_flash, logical_sector, buffer);
|
||||
|
||||
/* Determine if the read was successful. */
|
||||
if (status != LX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return an I/O error to FileX. */
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Successful sector read. */
|
||||
count--;
|
||||
logical_sector++;
|
||||
buffer += media_ptr -> fx_media_bytes_per_sector;
|
||||
}
|
||||
/* Successful driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_WRITE:
|
||||
{
|
||||
|
||||
/* Write sector(s) to NAND flash. */
|
||||
logical_sector = media_ptr -> fx_media_driver_logical_sector;
|
||||
count = media_ptr -> fx_media_driver_sectors;
|
||||
buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
|
||||
while (count)
|
||||
{
|
||||
|
||||
/* Call LevelX to write a sector. */
|
||||
status = _lx_nand_flash_sector_write(&nand_flash, logical_sector, buffer);
|
||||
|
||||
/* Determine if the write was successful. */
|
||||
if (status != LX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return an I/O error to FileX. */
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Successful sector write. */
|
||||
count--;
|
||||
logical_sector++;
|
||||
buffer += media_ptr -> fx_media_bytes_per_sector;
|
||||
}
|
||||
|
||||
/* Successful driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_RELEASE_SECTORS:
|
||||
{
|
||||
|
||||
/* Release the mapping of this sector. */
|
||||
logical_sector = media_ptr -> fx_media_driver_logical_sector;
|
||||
count = media_ptr -> fx_media_driver_sectors;
|
||||
while (count)
|
||||
{
|
||||
|
||||
/* Call LevelX to release a sector mapping. */
|
||||
status = _lx_nand_flash_sector_release(&nand_flash, logical_sector);
|
||||
|
||||
/* Determine if the sector release was successful. */
|
||||
if (status != LX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return an I/O error to FileX. */
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Successful sector release. */
|
||||
count--;
|
||||
logical_sector++;
|
||||
}
|
||||
|
||||
/* Successful driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_FLUSH:
|
||||
{
|
||||
|
||||
/* Return driver success. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_ABORT:
|
||||
{
|
||||
|
||||
/* Return driver success. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_INIT:
|
||||
{
|
||||
|
||||
/* FLASH drivers are responsible for setting several fields in the
|
||||
media structure, as follows:
|
||||
|
||||
media_ptr -> fx_media_driver_free_sector_update
|
||||
media_ptr -> fx_media_driver_write_protect
|
||||
|
||||
The fx_media_driver_free_sector_update flag is used to instruct
|
||||
FileX to inform the driver whenever sectors are not being used.
|
||||
This is especially useful for FLASH managers so they don't have
|
||||
maintain mapping for sectors no longer in use.
|
||||
|
||||
The fx_media_driver_write_protect flag can be set anytime by the
|
||||
driver to indicate the media is not writable. Write attempts made
|
||||
when this flag is set are returned as errors. */
|
||||
|
||||
/* Perform basic initialization here... since the boot record is going
|
||||
to be read subsequently and again for volume name requests. */
|
||||
|
||||
/* With flash wear leveling, FileX should tell wear leveling when sectors
|
||||
are no longer in use. */
|
||||
media_ptr -> fx_media_driver_free_sector_update = FX_TRUE;
|
||||
|
||||
/* Open the NAND flash simulation. */
|
||||
status = _lx_nand_flash_open(&nand_flash, "sim nand flash", _lx_nand_flash_simulator_initialize);
|
||||
|
||||
/* Determine if the flash open was successful. */
|
||||
if (status != LX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return an I/O error to FileX. */
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Successful driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_UNINIT:
|
||||
{
|
||||
|
||||
/* There is nothing to do in this case for the RAM driver. For actual
|
||||
devices some shutdown processing may be necessary. */
|
||||
|
||||
/* Close the NAND flash simulation. */
|
||||
status = _lx_nand_flash_close(&nand_flash);
|
||||
|
||||
/* Determine if the flash close was successful. */
|
||||
if (status != LX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return an I/O error to FileX. */
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Successful driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_BOOT_READ:
|
||||
{
|
||||
|
||||
/* Read the boot record and return to the caller. */
|
||||
status = _lx_nand_flash_sector_read(&nand_flash, 0, (UCHAR *) media_ptr -> fx_media_driver_buffer);
|
||||
|
||||
/* Determine if the read was successful. */
|
||||
if (status != LX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return an I/O error to FileX. */
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Successful driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_BOOT_WRITE:
|
||||
{
|
||||
|
||||
/* Write the boot record and return to the caller. */
|
||||
status = _lx_nand_flash_sector_write(&nand_flash, 0, (UCHAR *) media_ptr -> fx_media_driver_buffer);
|
||||
|
||||
/* Determine if the write was successful. */
|
||||
if (status != LX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Return an I/O error to FileX. */
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Successful driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break ;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
/* Invalid driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_IO_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user