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,460 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 NOR FLASH Simulator Driver */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "fx_api.h"
|
||||
#include "lx_api.h"
|
||||
|
||||
|
||||
/* Create a NOR flash control block. */
|
||||
|
||||
LX_NOR_FLASH nor_flash;
|
||||
|
||||
|
||||
/* The simulated NOR driver relies on the fx_media_format call to be made prior to
|
||||
the fx_media_open call.
|
||||
|
||||
fx_media_format(&ram_disk,
|
||||
_fx_nor_sim_driver, // Driver entry
|
||||
FX_NULL, // Unused
|
||||
media_memory, // Media buffer pointer
|
||||
sizeof(media_memory), // Media buffer size
|
||||
"MY_NOR_DISK", // Volume Name
|
||||
1, // Number of FATs
|
||||
32, // Directory Entries
|
||||
0, // Hidden sectors
|
||||
120, // Total sectors
|
||||
512, // Sector size
|
||||
1, // Sectors per cluster
|
||||
1, // Heads
|
||||
1); // Sectors per track
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Define prototypes. */
|
||||
|
||||
UINT _lx_nor_flash_simulator_initialize(LX_NOR_FLASH *nor_flash);
|
||||
VOID _fx_nor_flash_simulator_driver(FX_MEDIA *media_ptr);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _fx_nor_flash_simulator_driver PORTABLE C */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is the entry point to the generic NOR simulated */
|
||||
/* disk driver that is delivered with the flash wear leveling product */
|
||||
/* LevelX. */
|
||||
/* */
|
||||
/* This driver also serves as a template for developing other LevelX */
|
||||
/* NOR 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 NOR 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_nor_flash_close Close NOR flash manager */
|
||||
/* lx_nor_flash_open Open NOR flash manager */
|
||||
/* lx_nor_flash_sector_read Read a NOR sector */
|
||||
/* lx_nor_flash_sector_release Release a NOR sector */
|
||||
/* lx_nor_flash_sector_write Write a NOR sector */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* FileX System Functions */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _fx_nor_flash_simulator_driver(FX_MEDIA *media_ptr)
|
||||
{
|
||||
|
||||
UCHAR *source_buffer;
|
||||
UCHAR *destination_buffer;
|
||||
ULONG logical_sector;
|
||||
ULONG i;
|
||||
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:
|
||||
{
|
||||
|
||||
/* Setup the destination buffer and logical sector. */
|
||||
logical_sector = media_ptr -> fx_media_driver_logical_sector;
|
||||
destination_buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
|
||||
|
||||
/* Loop to read sectors from flash. */
|
||||
for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
|
||||
{
|
||||
|
||||
/* Read a sector from NOR flash. */
|
||||
status = lx_nor_flash_sector_read(&nor_flash, logical_sector, destination_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;
|
||||
}
|
||||
|
||||
/* Move to the next entries. */
|
||||
logical_sector++;
|
||||
destination_buffer = destination_buffer + 512;
|
||||
}
|
||||
|
||||
/* Successful driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_WRITE:
|
||||
{
|
||||
|
||||
/* Setup the source buffer and logical sector. */
|
||||
logical_sector = media_ptr -> fx_media_driver_logical_sector;
|
||||
source_buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
|
||||
|
||||
/* Loop to write sectors to flash. */
|
||||
for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
|
||||
{
|
||||
|
||||
/* Write a sector to NOR flash. */
|
||||
status = lx_nor_flash_sector_write(&nor_flash, logical_sector, source_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;
|
||||
}
|
||||
|
||||
/* Move to the next entries. */
|
||||
logical_sector++;
|
||||
source_buffer = source_buffer + 512;
|
||||
}
|
||||
|
||||
/* Successful driver request. */
|
||||
media_ptr -> fx_media_driver_status = FX_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
case FX_DRIVER_RELEASE_SECTORS:
|
||||
{
|
||||
|
||||
/* Setup the logical sector. */
|
||||
logical_sector = media_ptr -> fx_media_driver_logical_sector;
|
||||
|
||||
/* Release sectors. */
|
||||
for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
|
||||
{
|
||||
|
||||
/* Release NOR flash sector. */
|
||||
status = lx_nor_flash_sector_release(&nor_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;
|
||||
}
|
||||
|
||||
/* Move to the next entries. */
|
||||
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 NOR flash simulation. */
|
||||
status = lx_nor_flash_open(&nor_flash, "sim nor flash", _lx_nor_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 NOR flash simulation. */
|
||||
status = lx_nor_flash_close(&nor_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. */
|
||||
|
||||
/* Setup the destination buffer. */
|
||||
destination_buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
|
||||
|
||||
/* Read boot sector from NOR flash. */
|
||||
status = lx_nor_flash_sector_read(&nor_flash, 0, destination_buffer);
|
||||
|
||||
/* For NOR driver, determine if the boot record is valid. */
|
||||
if ((destination_buffer[0] != (UCHAR) 0xEB) ||
|
||||
(destination_buffer[1] != (UCHAR) 0x34) ||
|
||||
(destination_buffer[2] != (UCHAR) 0x90))
|
||||
{
|
||||
|
||||
/* Invalid boot record, return an error! */
|
||||
media_ptr -> fx_media_driver_status = FX_MEDIA_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine if the boot 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. */
|
||||
|
||||
/* Setup the source buffer. */
|
||||
source_buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
|
||||
|
||||
/* Write boot sector to NOR flash. */
|
||||
status = lx_nor_flash_sector_write(&nor_flash, 0, source_buffer);
|
||||
|
||||
/* Determine if the boot 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