?? nandfs.c
字號:
//****************************************************************************//// NANDFS.C - File system driver for the on-board NAND FLASH.//// Copyright (c) 1999,2000,2001 Cirrus Logic, Inc.////****************************************************************************#include "globals.h"#include "../hwport.h"#include "../hwdefs.h"//****************************************************************************//// The persistent state of the NAND file system.////****************************************************************************static struct{ // // A list of the bad blocks in the on-board NAND FLASH, in numerical order. // unsigned short usBadBlocks[64]; // // The number of bad blocks in the on-board NAND FLASH. // unsigned short usNumBadBlocks; // // The number of blocks in the on-board NAND FLASH. // unsigned short usNumBlocks; // // The number of pages per block of the on-board NAND FLASH. // unsigned char ucPagesPerBlock; // // Unused bytes to pad the next member to a word boundary. // unsigned char ucUnused1, ucUnused2, ucUnused3; // // The length of the one file in the on-board NAND FLASH. // unsigned long ulFileLength; // // A pointer to the function used to read a page from the on-board NAND // FLASH. // void (*pfnRead)(unsigned long ulNANDAddress, unsigned long ulPage, unsigned char *pucData, unsigned char *pucRedundant); // // A pointer to the function used to write a page to the on-board NAND // FLASH. // void (*pfnWrite)(unsigned long ulNANDAddress, unsigned long ulPage, unsigned char *pucData, unsigned char *pucRedundant); // // A pointer to the function used to erase a block of the on-board NAND // FLASH. // void (*pfnErase)(unsigned long ulNANDAddress, unsigned long ulBlock);} sNAND;//****************************************************************************//// The following structure contains the parameters of an opened file.////****************************************************************************typedef struct{ // // The next page of the file to be read. // unsigned long ulPage; // // The current byte offset into the file. // unsigned long ulFilePos;} tNANDFile;//****************************************************************************//// The following structure contains the parameters of an opened directory.////****************************************************************************typedef struct{ // // An indicator that is true when there have been no IOCTL_FS_READDIR // Ioctls after an IOCTL_FS_OPENDIR Ioctl. // unsigned long bIsFirstDirEntry;} tNANDDir;//****************************************************************************//// NextPage increments to the next valid page of the NAND FLASH. The next// valid page is "*pulPage++", unless this falls on an invalid block. The// current value of the page variable is returned, so that this function can// be used as a post-increment reference (i.e. NextPage(&x) is roughly// equivalent to x++).////****************************************************************************static unsigned longNextPage(unsigned long *pulPage){ unsigned long ulRet; int iIdx; // // Save the current page number. // ulRet = *pulPage; // // Increment the page number. // (*pulPage)++; // // If this is not the first page of a block, then it is not part of an // invalid block. // if((*pulPage & (sNAND.ucPagesPerBlock - 1)) != 0) { // // Return the previous page number. // return(ulRet); } // // Increment the page number until we reach a page in a valid block. // while(1) { // // See if this page lies in one of our invalid blocks. // for(iIdx = 0; iIdx < sNAND.usNumBadBlocks; iIdx++) { if((*pulPage / sNAND.ucPagesPerBlock) == sNAND.usBadBlocks[iIdx]) { break; } } // // If this page does not lie in one of the invalid blocks, then stop // incrementing the page number. // if(iIdx == sNAND.usNumBadBlocks) { break; } // // Skip to the first page of the next block. // *pulPage += sNAND.ucPagesPerBlock; } // // Return the previous page number. // return(ulRet);}//****************************************************************************//// CheckNAND determines if the NAND FLASH on the board has been "formatted"// and reads the bad block table if it has been formatted.////****************************************************************************static intCheckNAND(unsigned char *pucBuffer, unsigned char *pucWriteBuffer){ int iLoop; // // Read the first page of the NAND FLASH. // (sNAND.pfnRead)(HwNANDAddress, 0, pucBuffer, pucWriteBuffer); // // See if the NAND FLASH has been formatted by looking for the signature // at the beginning of the first page. // if((pucBuffer[0] != 'B') || (pucBuffer[1] != 'K') || (pucBuffer[2] != 'O') || (pucBuffer[3] != 'K')) { // // The signature does not exist, so the NAND FLASH has not been // formatted yet. // return(0); } // // Get the number of bad blocks. // sNAND.usNumBadBlocks = pucBuffer[4] | (pucBuffer[5] << 8); // // Make sure that the number of bad blocks is valid. // if(sNAND.usNumBadBlocks > 64) { sNAND.usNumBadBlocks = 0; return(0); } // // Read the bad block table. // for(iLoop = 0; iLoop < sNAND.usNumBadBlocks; iLoop++) { sNAND.usBadBlocks[iLoop] = pucBuffer[6 + (iLoop << 1)] | (pucBuffer[7 + (iLoop << 1)] << 8); } // // The media has been formatted. // return(1);}//****************************************************************************//// FormatNAND prepares the NAND FLASH for use to record/download file data.// It checks the NAND FLASH for bad blocks and builds a bad block table.////****************************************************************************static voidFormatNAND(unsigned char *pucBuffer, unsigned char *pucWriteBuffer){ unsigned long ulValue; int iBlock, iPage, iIdx; // // We only need to check for bad blocks if the NAND FLASH has not already // been formatted. // if(!CheckNAND(pucBuffer, pucWriteBuffer)) { // // Initially, there are no bad blocks in the NAND FLASH (until we find // bad blocks). // sNAND.usNumBadBlocks = 0; // // Loop through all the blocks in the on-board NAND FLASH. // for(iBlock = 1; iBlock < sNAND.usNumBlocks; iBlock++) { // // Read the first two pages of each block. The page will be all // 0xff if it is good, and will contain zeros if it is bad. // for(iPage = 0; iPage < 2; iPage++) { // // Read the page from NAND FLASH. // (sNAND.pfnRead)(HwNANDAddress, (iBlock * sNAND.ucPagesPerBlock) + iPage, pucBuffer, pucWriteBuffer); // // Verify that the page contains all 0xff. // for(iIdx = 0; iIdx < 512; iIdx++) { if(pucBuffer[iIdx] != 0xff) { break; } } // // If this page did not contain all 0xff, then break out of the // loop. // if(iIdx != 512) { break; } // // Verify that the spare area contains all 0xff. // for(iIdx = 0; iIdx < 16; iIdx++) { if(pucWriteBuffer[iIdx] != 0xff) { break; } } // // If the spare area did not contain all 0xff, then break out // of the loop. // if(iIdx != 16) { break; } } // // If both pages did not contain all 0xff, then this block is bad. // if(iPage != 2) { // // Save this block in the bad block table. // sNAND.usBadBlocks[sNAND.usNumBadBlocks++] = iBlock; // // Quit scanning if we've found too many bad blocks. This // ignores any following bad blocks, but what can you do (this // isn't exactly a "filesystem" and is certainly not product // worthy)? // if(sNAND.usNumBadBlocks == 64) { break; } } } // // Build the signature and bad block table for the first page of the // NAND FLASH. // pucBuffer[0] = 'B'; pucBuffer[1] = 'K'; pucBuffer[2] = 'O'; pucBuffer[3] = 'K'; // // Fill in the bad block table. // pucBuffer[4] = sNAND.usNumBadBlocks & 0xFF; pucBuffer[5] = (sNAND.usNumBadBlocks >> 8) & 0xFF; for(iIdx = 0; iIdx < sNAND.usNumBadBlocks; iIdx++) { pucBuffer[6 + (iIdx << 1)] = sNAND.usBadBlocks[iIdx] & 0xFF; pucBuffer[7 + (iIdx << 1)] = (sNAND.usBadBlocks[iIdx] >> 8) & 0xFF; } // // Write the bad block table to the beginning of the NAND FLASH. // (sNAND.pfnErase)(HwNANDAddress, 0); NANDWaitTilNotBusy(HwNANDAddress); (sNAND.pfnWrite)(HwNANDAddress, 0, pucBuffer, pucWriteBuffer); NANDWaitTilNotBusy(HwNANDAddress); } // // Set the file size to zero, so that we do not try to play the empty // contents of the NAND FLASH. // pucBuffer[0] = 0; pucBuffer[1] = 0; pucBuffer[2] = 0; pucBuffer[3] = 0; ulValue = sNAND.ucPagesPerBlock - 1; NextPage(&ulValue); (sNAND.pfnErase)(HwNANDAddress, ulValue / sNAND.ucPagesPerBlock); NANDWaitTilNotBusy(HwNANDAddress); (sNAND.pfnWrite)(HwNANDAddress, ulValue, pucBuffer, pucWriteBuffer); NANDWaitTilNotBusy(HwNANDAddress);}//****************************************************************************//// The file system entry point for the on-board NAND FLASH.////****************************************************************************unsigned longNANDIoctl(unsigned char *pucScratch, unsigned char *pucWriteBuffer, unsigned long ulIoctl, unsigned long ulInstance, unsigned long ulParam1, unsigned long ulParam2){ volatile unsigned long *pulGPIO = (unsigned long *)HwBaseAddress; // // If we are being initialized, then we need to setup our global variables. // if(ulIoctl == IOCTL_FS_INIT) { unsigned long ulDeviceID; // // Select the on-board NAND. // pulGPIO[HwPortABCD >> 2] &= ~HwPortABCD_NAND1_CS; // // Get the ID of the on-board NAND FLASH. // ulDeviceID = NANDGetID(HwNANDAddress); // // Determine the size and geometry of the on-board NAND FLASH. // switch(ulDeviceID) { // // The device capacity is 4MB. // case 0x6B: case 0xE3: case 0xE5: { // // There are 512 blocks in this device. // sNAND.usNumBlocks = 512; // // There are 16 pages per block in this device. // sNAND.ucPagesPerBlock = 16; // // Fill in the function pointers for accessing this FLASH // device. // sNAND.pfnRead = NANDRead_512_3; sNAND.pfnWrite = NANDWrite_512_3; sNAND.pfnErase = NANDErase_16; // // We've interpreted the device ID. // break; } // // The device capacity is 8MB. // case 0xE6: { // // There are 1024 blocks in this device. // sNAND.usNumBlocks = 1024; // // There are 16 pages per block in this device. // sNAND.ucPagesPerBlock = 16; // // Fill in the function pointers for accessing this FLASH // device. // sNAND.pfnRead = NANDRead_512_3; sNAND.pfnWrite = NANDWrite_512_3; sNAND.pfnErase = NANDErase_16; // // We've interpreted the device ID. // break; } // // The device capacity is 16MB. // case 0x73:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -