⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fmd.cpp

📁 微软提供的Flash驱动程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:

    //  Check the status
    status = GetStatus((DWORD) -1);

    if(status & STATUS_ERROR) {
        RETAILMSG(1, (TEXT("######## Error Programing page %d!\n"), sectorAddr));
        FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
        return FALSE;
    }

    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
    return TRUE;
}

/*-----------------------------------------------------------------------------
 *  FMD Interface functions
 *
 *----------------------------------------------------------------------------*/

//  FMD_Init
//  
//  Initialize the flash chip
//
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
    //  Issue a reset command here
    RETAILMSG(1,(TEXT("FMD_Init\r\n")));
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)0);    // enable chip
    if (IoAddr==0) {
#ifdef READFROMREG
        if (lpActiveReg!=NULL) {
            DDKWINDOWINFO dwi;
            HKEY hConfig;
            hConfig=OpenDeviceKey((LPCTSTR)lpActiveReg);
           
            if (hConfig==NULL) {
                RETAILMSG(1, (TEXT("FMD: OpenDeviceKey Fails\r\n")));
                FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
                return 0;
            }
            dwi.cbSize = sizeof(dwi);
            if (DDKReg_GetWindowInfo(hConfig, &dwi)!=ERROR_SUCCESS) {
                RETAILMSG(1, (_T("FMD: DDKReg_GetWindowInfo() failed \r\n")));
                FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
                return 0;
            }
            if (dwi.dwNumIoWindows>=2) { // second IO address.
                IoAddr=dwi.ioWindows[1].dwBase;
            }
        }
        else
#endif
            if (!ScanPCI((PPCI_REG_INFO)pRegIn,(PPCI_REG_INFO)pRegOut)) {
                FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
                return 0;
            }        
        RETAILMSG(1,(TEXT("Found PCI NAND IO=%x .\r\n"),IoAddr));
        if (IoAddr!=NULL) {
            DWORD inIoSpace=1;
            PHYSICAL_ADDRESS ioPhysicalBase;
            ioPhysicalBase.LowPart=IoAddr;
            ioPhysicalBase.HighPart=0;
            if (HalTranslateBusAddress(PCIBus, 0, ioPhysicalBase, &inIoSpace, &ioPhysicalBase)) {
                if (!inIoSpace) { // If it is memory mappes IO.
                    bIoMemMapped=TRUE;
                    if ((IoAddr = (DWORD)MmMapIoSpace(ioPhysicalBase, 0x40, FALSE)) == NULL) {
                        // We may as well not continue
                        RETAILMSG(1,(TEXT("FMD: Error mapping I/O Ports.\r\n")));
                        FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
                        return 0;
                    }
                }
                else {
                    bIoMemMapped=FALSE;
                    IoAddr=ioPhysicalBase.LowPart;
                }
            }
            else {
                RETAILMSG(1,(TEXT("FMD:HalTranslateBusAddress FAILS.\r\n")));
                IoAddr=0;
                FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
                return 0;
            }
        }
        else 
            ASSERT(FALSE);
    }
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_RESET);

    CheckStatus((DWORD) -1);    // check ready
    dwDeviceId=ReadFlashID();
    NEED_EXT_ADDR=TRUE;
    switch (dwDeviceId) {
    case 0x9875:
        g_wPagesPerBlock = 0x20;    // 32 pages per block
        NEED_EXT_ADDR=FALSE;
        break;
    case 0x9876: // SanDisk 512.NAND_1.5.pdf
        if (ReadFlashID2() == 0) {
            g_wPagesPerBlock = 0x20;    // 32 pages per block for Binary
        } else {
            g_wPagesPerBlock = 0x40;    // 64 pages per block for MLC
        }
        break;
    case 0x9879: // SanDisk 1024_MLC_1.0.pdf
        if (ReadFlashID2() == 0) {
            g_wPagesPerBlock = 0x20;    // 32 pages per block for Binary
        } else {
            g_wPagesPerBlock = 0x40;    // 64 pages per block for MLC
        }
        break;        
    default:
        g_wPagesPerBlock = 0;
        break;
    }
        RETAILMSG(1,(TEXT("NAND pages Per Block=%x .\r\n"),g_wPagesPerBlock));

    return (PVOID)IoAddr;
}

//  FMD_Deinit
//
//  De-initialize the flash chip
//
BOOL    FMD_Deinit(PVOID hFMD)
{
    ASSERT((DWORD)hFMD==IoAddr);
    if (bIoMemMapped && hFMD!=NULL && (DWORD)hFMD==IoAddr) {
        MmUnmapIoSpace ((PVOID)IoAddr,0);
        IoAddr=0;
    }
    return TRUE;
}

//  FMD_GetInfo
//
//  Return the Flash information 
//
BOOL    FMD_GetInfo(PFlashInfo pFlashInfo)
{
    pFlashInfo->flashType = NAND;

    //  OK, instead of reading it from the chip, we use the hardcoded
    //  numbers here.

    pFlashInfo->wDataBytesPerSector = SECTOR_SIZE;
    switch (dwDeviceId) {
    case 0x9876: // SanDisk 512.NAND_1.5.pdf
        pFlashInfo->dwNumBlocks         = 0x1000; //4K per page
        break;
    case 0x9879: // SanDisk 1024_MLC_1.0.pdf
        pFlashInfo->dwNumBlocks         = 0x1000; //4K per page.
        break;
    case 0x9875:
        pFlashInfo->dwNumBlocks         = 0x800; // 2K per page.
        break;
    default:
        pFlashInfo->dwNumBlocks         = 0;
        pFlashInfo->wSectorsPerBlock    = 0;
        pFlashInfo->dwBytesPerBlock     = 0;
        return FALSE;
    }

    pFlashInfo->wSectorsPerBlock        = g_wPagesPerBlock;
    pFlashInfo->dwBytesPerBlock         = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);

    return TRUE;
}

//  FMD_ReadSector
//
//  Read the content of the sector.
//
//  startSectorAddr: Starting page address
//  pSectorBuff  : Buffer for the data portion
//  pSectorInfoBuff: Buffer for Sector Info structure
//  dwNumSectors : Number of sectors
//
BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, 
                        PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
    UCHAR  addr1, addr2, addr3, wData;
    DWORD   i,count;

    //  BUGBUGBUG: I need to come back to support dwNumSectors > 1
    //
    //  Sanity check
    if (!pSectorBuff && !pSectorInfoBuff || dwNumSectors > 1) {
        RETAILMSG(1, (TEXT("Invalid parameters!\n")));
        return FALSE;
    }

    //  Now reset the chip to a known state
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)0);    // enable chip
    CheckStatus((DWORD) -1);    // check ready
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_READ);
    
    for (count=0;count<dwNumSectors;count++) {
        
        CheckStatus((DWORD) -1);

        if(!pSectorBuff) {
            //  We are reading spare only
            NAND_ReadSectorInfo(startSectorAddr, pSectorInfoBuff);
            pSectorInfoBuff ++;

        }
        else {

            //  Reading data from the flash
            addr1 = (UCHAR) ((startSectorAddr) & 0xff);
            addr2 = (UCHAR) ((startSectorAddr >> 8) & 0xff);
            addr3 = (UCHAR) ((startSectorAddr >> 16) & 0xff);

            //  Issue Read command 
            FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_READ);
            FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, 0x0);
            FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr1);
            FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr2);

            if(NEED_EXT_ADDR) {
                FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr3);
            }

            CheckStatus((DWORD) -1);

            //  Read only data portion of the sector.
            for(i=0; i<SECTOR_SIZE; i++)
            {            
                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);

                // Copy the bytes directly into pSectorBuff
                pSectorBuff[i] = wData;
            }


            // Read the SectorInfo data (we only need to read first 8 bytes) 
            // Read the SectorInfo data
            if(pSectorInfoBuff)
            {
                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);               // First reserved field (DWORD)
                pSectorInfoBuff->dwReserved1  = (wData);
                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);               
                pSectorInfoBuff->dwReserved1  |= (wData << 8);
                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);               
                pSectorInfoBuff->dwReserved1  |= (wData << 16);
                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);               
                pSectorInfoBuff->dwReserved1  |= (wData << 24);

                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);               // OEM byte
                pSectorInfoBuff->bOEMReserved = (wData);
                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);               // Bad block byte
                pSectorInfoBuff->bBadBlock    = (wData);

                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);               // Second reserved field (WORD)
                pSectorInfoBuff->wReserved2  = (wData);
                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);               
                pSectorInfoBuff->wReserved2   |= (wData << 8);
                pSectorInfoBuff ++;
            }else
            {
                // Make sure we advance the Flash's read pointer (even though we don't need the SectorInfo data).
                for(i=0; i<sizeof(SectorInfo); i++)
                {
                    FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
                }
            }

            // Read the ECC info
            for(i=0; i<ECC_SIZE; i++)
            {
                wData = FMD_READ_PORT_UCHAR((PUCHAR) NAND_DATA_PORT);
            
                //  Read out the ECC bits saved  
                ECC[i]   = wData;
            }

           //  Test the data integrity; if the data is invalid, attempt to fix it using ECC
            if(!ECC_IsDataValid(pSectorBuff, SECTOR_SIZE, ECC, ECC_BUFF_LEN))
            {
                //RETAILMSG(1, (TEXT("FMD: Sector data (sector 0x%x) is invalid.  Attempting ECC to fix it.\n"), startSectorAddr));

                if(!ECC_CorrectData(pSectorBuff, SECTOR_SIZE, ECC, ECC_BUFF_LEN))
                {
                    // NOTE: this is specifically a debug message because sometimes it's valid to try to read from a sector in a good
                    // block which might contain bogus data (ECC fails) - example: loader code that needs to save/restore non-block-aligned
                    // data and we don't want a bunch of warnings in a retail build.
                    DEBUGMSG(1, (TEXT("FMD: ERROR - Sector data (sector 0x%x) Unable to correct invalid data!\r\n"),startSectorAddr));
                    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
                    return FALSE;

                }else{
                    DEBUGMSG(1, (TEXT("FMD: Invalid data was corrected using ECC!\r\n")));
                }
            }
            pSectorBuff += SECTOR_SIZE;
        }
        startSectorAddr ++;
    }
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
    return TRUE;
}
                 
        
//  FMD_EraseBlock
//
//  Erase the given block
//
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
    UCHAR   addr1, addr2, addr3;
    UCHAR   status;
    DWORD   dwPageID = blockID*g_wPagesPerBlock;   //  Get the first page of the blcok

    addr1 = (UCHAR) ((dwPageID) & 0xff);
    addr2 = (UCHAR) ((dwPageID >> 8) & 0xff);
    addr3 = (UCHAR) ((dwPageID >> 16) & 0xff);

    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)0);    // enable chip
    CheckStatus((DWORD) -1);    // check ready
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_ERASE);
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr1);
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr2);

    if(NEED_EXT_ADDR) {
        FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_ADDR_PORT, addr3);
    }

    CheckStatus((DWORD) -1);    // check ready
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CMD_PORT, (UCHAR) CMD_ERASE2);

    status = GetStatus((DWORD) -1);

    if(status & STATUS_ERROR) {
        RETAILMSG(1, (TEXT("######## Error Erasing block %d!\n"), blockID));
        FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
        return FALSE;
    }
    FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
    return TRUE;
}


//  FMD_WriteSector
//
//  Write dwNumPages pages to the startSectorAddr
//
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -