📄 nand.c
字号:
//****************************************************************************//// NAND.C - File system driver for the on-board NAND FLASH.//// Copyright (c) 2000,2001 Cirrus Logic, Inc.////****************************************************************************#include "globals.h"#include "../hwport.h"#include "../hwdefs.h"#include "fat/fat.h"#include "ftl/ftl.h"//****************************************************************************//// The name of this drive.////****************************************************************************static const unsigned short pusDriveName[] ={ 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', ' ', 'N', 'A', 'N', 'D', '\0'};//****************************************************************************//// The persistent state of the NAND driver.////****************************************************************************static struct{ // // The persistent state of the FTL layer used for the on-board NAND. // tFTL sFTL; // // The persistent state of the FAT layer used for the on-board NAND. // tFAT sFAT; // // Flags indicating the state of the NAND FLASH driver. // unsigned long ulFlags;} sNAND;//****************************************************************************//// The set of flags that indicate the state of the NAND FLASH driver.////****************************************************************************#define FLAG_ID_MASK 0x000000ff#define FLAG_IS_BUSY1 0x40000000#define FLAG_IS_BUSY2 0x80000000//****************************************************************************//// The FLASH driver IOCTL entry point for the on-board NAND.////****************************************************************************static unsigned longNANDFLASHIoctl(unsigned long ulIoctl, unsigned long ulParam1, unsigned long ulParam2, unsigned long ulParam3, unsigned long ulParam4){ volatile unsigned long *pulGPIO = (unsigned long *)HwBaseAddress; unsigned long ulCS, ulBusyFlag; // // If the first on-board NAND could be busy, then wait until it is not. // if(sNAND.ulFlags & FLAG_IS_BUSY1) { // // Select the first on-board NAND. // pulGPIO[HwPortABCD >> 2] &= ~HwPortABCD_NAND1_CS; // // Wait until the first on-board NAND is not busy. // NANDWaitTilNotBusy(HwNANDAddress); // // Indicate that the first on-board NAND is not busy. // sNAND.ulFlags &= ~FLAG_IS_BUSY1; // // Deselect the first on-board NAND. // pulGPIO[HwPortABCD >> 2] |= HwPortABCD_NAND1_CS; } // // If the second on-board NAND could be busy, then wait until it is not. //#ifdef HwPortABCD_NAND2_CS if(sNAND.ulFlags & FLAG_IS_BUSY2) { // // Select the second on-board NAND. // pulGPIO[HwPortABCD >> 2] &= ~HwPortABCD_NAND2_CS; // // Wait until the second on-board NAND is not busy. // NANDWaitTilNotBusy(HwNANDAddress); // // Indicate that the second on-board NAND is not busy. // sNAND.ulFlags &= ~FLAG_IS_BUSY2; // // Deselect the second on-board NAND. // pulGPIO[HwPortABCD >> 2] |= HwPortABCD_NAND2_CS; }#endif // // Determine which of the on-board NAND FLASH devices to select. //#ifdef HwPortABCD_NAND2_CS if(sNAND.ulFlags & FLAG_ID_MASK) { // // The on-board NAND FLASH device to select is dependent upon the // IOCTL being executed. // switch(ulIoctl) { // // Handle the IOCTLs which work on a page basis. // case IOCTL_FLASH_READ: case IOCTL_FLASH_WRITE: case IOCTL_FLASH_READ_REDT: case IOCTL_FLASH_WRITE_REDT: { unsigned long ulNumPages = 0; // // Determine the number of pages in each of the NAND FLASH // devices. // switch(sNAND.ulFlags & FLAG_ID_MASK) { // // A pair of 16MB NAND FLASH devices have 32768 pages in // each device. // case 0x75: { ulNumPages = 32768; break; } // // A pair of 32MB NAND FLASH devices have 65536 pages in // each device. Also, each individual device is accessed // with only three address cycles. // case 0x76: { ulNumPages = 65536; ulParam4 &= ~FLASH_ADDR_4_CYCLE; break; } // // A pair of 64MB NAND FLASH devices have 131072 pages in // each device. // case 0x79: { ulNumPages = 131072; break; } } // // Determine the NAND FLASH device to select based on the page // number being accessed. // if(ulParam1 < ulNumPages) { ulCS = HwPortABCD_NAND1_CS; ulBusyFlag = FLAG_IS_BUSY1; } else { ulParam1 -= ulNumPages; ulCS = HwPortABCD_NAND2_CS; ulBusyFlag = FLAG_IS_BUSY2; } // // We've determined the correct device. // break; } // // Handle the IOCTLs which work on a block basis. // case IOCTL_FLASH_ERASE: { unsigned long ulNumBlocks = 0; // // Determine the number of blocks in each of the NAND FLASH // devices. // switch(sNAND.ulFlags & FLAG_ID_MASK) { // // A pair of 16MB NAND FLASH devices have 1024 blocks in // each device. // case 0x75: { ulNumBlocks = 1024; break; } // // A pair of 32MB NAND FLASH devices have 2048 blocks in // each device. Also, each individual device is accessed // with only three address cycles. // case 0x76: { ulNumBlocks = 2048; ulParam4 &= ~FLASH_ADDR_4_CYCLE; break; } // // A pair of 64MB NAND FLASH devices have 4096 blocks in // each device. // case 0x79: { ulNumBlocks = 4096; break; } } // // Determine the NAND FLASH device to select based on the block // number being accessed. // if(ulParam1 < ulNumBlocks) { ulCS = HwPortABCD_NAND1_CS; ulBusyFlag = FLAG_IS_BUSY1; } else { ulParam1 -= ulNumBlocks; ulCS = HwPortABCD_NAND2_CS; ulBusyFlag = FLAG_IS_BUSY2; } // // We've determined the correct device. // break; } // // Handle all other IOCTLs. // default: { // // Do not assert a chip select for all other IOCTLs. // ulCS = 0; // // Not not set a busy flag for all other IOCTLs. // ulBusyFlag = 0; // // We've determined the correct device. // break; } } } else#endif { // // Get the chip select for the first on-board NAND. // ulCS = HwPortABCD_NAND1_CS; // // Get the busy flag for the first on-board NAND. // ulBusyFlag = FLAG_IS_BUSY1; } // // Select the on-board NAND. // pulGPIO[HwPortABCD >> 2] &= ~ulCS; // // Determine what to do based on the requested IOCTL. // switch(ulIoctl) { // // Get the ID of the on-board NAND. // case IOCTL_FLASH_GETID: { unsigned long *pulDeviceID = (unsigned long *)ulParam1; // // If we are faking a larger NAND FLASH, then return the faked ID. // if(sNAND.ulFlags & FLAG_ID_MASK) { // // Return the faked ID. // *pulDeviceID = sNAND.ulFlags & FLAG_ID_MASK; } else { // // Read the device ID from the on-board NAND. // *pulDeviceID = NANDGetID(HwNANDAddress); } // // We're done with this request. // break; } // // Read a page of data from the on-board NAND. // case IOCTL_FLASH_READ: { // // Read the page of data from the on-board NAND. //#ifdef SUPPORT_TINY_MEDIA if(ulParam4 & FLASH_PS256) { // // This NAND device has 256 bytes per page. // NANDRead_256(HwNANDAddress, ulParam1 << 1, (unsigned char *)ulParam2, (unsigned char *)ulParam3); } else#endif if(ulParam4 & FLASH_ADDR_4_CYCLE) { // // This NAND device has 512 bytes per page and requires 4 // address cycles. // NANDRead_512_4(HwNANDAddress, ulParam1, (unsigned char *)ulParam2, (unsigned char *)ulParam3); } else { // // This NAND device has 512 bytes per page and requires 3 // address cycles. // NANDRead_512_3(HwNANDAddress, ulParam1, (unsigned char *)ulParam2, (unsigned char *)ulParam3); } // // We're done with this request. // break; } // // Write a page of data to the on-board NAND. // case IOCTL_FLASH_WRITE: { // // Write the page of data to the on-board NAND. //#ifdef SUPPORT_TINY_MEDIA if(ulParam4 & FLASH_PS256)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -