fmd_tyax.cpp

来自「该BSP是基于PXA270+WINCE的BSP」· C++ 代码 · 共 1,678 行 · 第 1/5 页

CPP
1,678
字号
                    if (pBytesReturned)
                        *pBytesReturned = 0;
                    return(FALSE);
                } else
                {
                    if (pBytesReturned)
                        *pBytesReturned = dwTableSize;
                    if (g_pReservedTable)
                        memcpy (pOutBuf, g_pReservedTable, dwTableSize);
                    return(TRUE);
                }
            }
            break;

        case IOCTL_FMD_SET_SECTORSIZE:
            if (!pInBuf || nInBufSize < sizeof(DWORD))
            {
                LOGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_SET_SECTORSIZE bad parameter(s).\r\n")));
                return(FALSE);
            }
            g_FMDInfo.SectorSize = *(LPDWORD)pInBuf;
            break;
        case IOCTL_FMD_RAW_WRITE_BLOCKS:
            if (!pInBuf || nInBufSize < sizeof(RawWriteBlocksReq))
            {
                LOGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_RAW_WRITE_BLOCKS bad parameter(s).\r\n")));
                return(FALSE);
            }
            return(RawWriteBlocks ((PRawWriteBlocksReq)pInBuf));

        case IOCTL_FMD_GET_RAW_BLOCK_SIZE:
            if (!pOutBuf || nOutBufSize < sizeof(DWORD))
            {
                LOGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_RAW_BLOCK_SIZE bad parameter(s).\r\n")));
                return(FALSE);
            }
            *((PDWORD)pOutBuf) = g_FMDInfo.BlockSize;
            return(TRUE);
        case IOCTL_FMDHAL_FLASH_CMD:

            if (FMDHAL_IOControl( *pInBuf,pOutBuf, pInBuf ) )
            {
                DBGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMDHAL_FLASH_CMD OK\r\n")));
                return(TRUE);
            } else
            {
                LOGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMDHAL_FLASH_CMD failed\r\n")));
                return(FALSE);
            }

        default:
            LOGMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x)\r\n"), dwIoControlCode));
            return(FALSE);
    }

    return(TRUE);
}

/*
    @func   BOOLEAN | UnlockBlock | Unlocks the specified flash block.
    @rdesc  TRUE returned on success, FALSE on failure.
    @comm
    @xref
*/
BOOLEAN SetBlockLock(BLOCK_ID blockID, ULONG NumBlocks, BOOL bLock)
{
    volatile ULONG ulBlockAddress = 0;
#ifndef UNDER_BOOTLOADER
    BOOL bLastMode = SetKMode(TRUE);
#endif
    struct FMDHAL_CmdStruct CurrCmd;

    if (bLock) {
        DBGMSG(1, (TEXT("FMD:SetBlockLock: lock 0x%x-0x%x\r\n"), blockID, blockID+(NumBlocks-1)));
    }
    else {
        DBGMSG(1, (TEXT("FMD:SetBlockLock: unlock 0x%x-0x%x\r\n"), blockID, blockID+(NumBlocks-1)));
    }

    ulBlockAddress  =  g_FMDInfo.BaseAddress + (blockID * g_FMDInfo.BlockSize);
    CurrCmd.pTargetAddress = (ULONG *)ulBlockAddress;
    CurrCmd.ulNumBlocks = NumBlocks;
    CurrCmd.uCmd = bLock?FMDHAL_CMD_LOCK_BLOCK:FMDHAL_CMD_UNLOCK_BLOCK;

    // Grab the flash mutex
    WAIT_FMD_FLASH_MUTEX(ghFlashMutex);

    if (!FMD_OEMIoControl(IOCTL_FMDHAL_FLASH_CMD, (PBYTE) &CurrCmd, sizeof(struct FMDHAL_CmdStruct),
                          NULL, NULL, NULL))
    {
#ifndef UNDER_BOOTLOADER
        SetKMode(bLastMode);
#endif
        // If failed, release Mutex
        RELEASE_FMD_FLASH_MUTEX(ghFlashMutex);
        return(FALSE);
    }

#ifndef UNDER_BOOTLOADER
    SetKMode(bLastMode);
#endif

    // Release Mutex after SetBlockLock completes
    RELEASE_FMD_FLASH_MUTEX(ghFlashMutex);

    return(TRUE);
}


BOOL ReadWriteReserved (PReservedReq pReq, BOOL fRead)
{

    PCSTR szName = pReq->szName;
    LPBYTE pBuffer = pReq->pBuffer;
#ifndef UNDER_BOOTLOADER
    BOOL bLastMode = SetKMode(TRUE);
#endif

#ifndef UNDER_BOOTLOADER
    if ((pBuffer = (LPBYTE)MapCallerPtr((LPVOID)(pReq->pBuffer), pReq->dwLen)) == NULL)
    {
        LOGMSG(1, (TEXT("ReadWriteReserved() - MapCallerPtr() failed, couldn't obtain pointer to buffer.\r\n")));
        goto Error;
    }
#endif

    for (DWORD i = 0; i < g_dwNumReserved; i++)
    {
#ifndef UNDER_BOOTLOADER
        if (_strnicmp(szName, g_pReservedTable[i].szName, RESERVED_NAME_LEN) == 0)
#else
        if (0)
#endif
        {
            //
            // Found a region name match
            //

            // Verify the request is in the valid range
            DWORD dwRegionSize = g_pReservedTable[i].dwNumBlocks * g_FMDInfo.BlockSize;
            if ((pReq->dwStart >= dwRegionSize) || (pReq->dwStart + pReq->dwLen > dwRegionSize))
            {
                LOGMSG(1, (TEXT("ReadWriteReserved: Invalid request.  Start: 0x%x.  Len: 0x%x\r\n"), pReq->dwStart, pReq->dwLen));
                goto Error;
            }

            if (fRead)
            {
                PVOID pStartAddress = (PVOID)(g_FMDInfo.BaseAddress + g_pReservedTable[i].dwStartBlock * g_FMDInfo.BlockSize + pReq->dwStart);
                memcpy (pBuffer, pStartAddress, pReq->dwLen);
            } else
            {
                //
                // Write flash case
                //

                DWORD dwBusWidth = g_bPairedFlash ? sizeof(ULONG) : sizeof(USHORT);

                if (pReq->dwStart % g_FMDInfo.SectorSize)
                {
                    LOGMSG(1, (TEXT("ReadWriteReserved: Invalid write request.  Start: 0x%x is not sector aligned.\r\n"), pReq->dwStart));
                    goto Error;
                }

                if ((DWORD)pBuffer & (dwBusWidth - 1))
                {
                    LOGMSG(1, (TEXT("ReadWriteReserved: Unaligned pointer 0x%x.\r\n"), pBuffer));
                    goto Error;
                }

                DWORD dwStartBlock = pReq->dwStart / g_FMDInfo.BlockSize + g_pReservedTable[i].dwStartBlock;
                DWORD dwEndBlock = (pReq->dwStart + pReq->dwLen - 1) / g_FMDInfo.BlockSize + g_pReservedTable[i].dwStartBlock;
                DWORD iBlock;
                DWORD dwWriteRemain = pReq->dwLen;

                for (iBlock = dwStartBlock; iBlock <= dwEndBlock; iBlock++)
                {
                    DWORD dwBlockWriteLen = MIN (g_FMDInfo.BlockSize, dwWriteRemain);
                    DWORD dwBlockOffset = 0;

                    // If this is the first block, then start at the appropriate offset within the block
                    if (iBlock == dwStartBlock)
                    {
                        dwBlockOffset = pReq->dwStart % g_FMDInfo.BlockSize;
                        dwBlockWriteLen = MIN (dwBlockWriteLen, g_FMDInfo.BlockSize - dwBlockOffset);
                    }

                    if (!WriteBlock (iBlock, pBuffer, dwBlockOffset, dwBlockWriteLen))
                    {
                        LOGMSG(1, (TEXT("ReadWriteReserved: WriteBlock failed (0x%x).\r\n"), iBlock));
                        goto Error;
                    }

                    pBuffer += dwBlockWriteLen;
                    dwWriteRemain -= dwBlockWriteLen;

                }
            }

#ifndef UNDER_BOOTLOADER
            SetKMode(bLastMode);
#endif
            return(TRUE);
        }
    }

    Error:
#ifndef UNDER_BOOTLOADER
    SetKMode(bLastMode);
#endif
    return(FALSE);
}



BOOL RawWriteBlocks (PRawWriteBlocksReq pReq)
{
    DWORD dwEndBlock = pReq->dwStartBlock + pReq->dwNumBlocks - 1;
    LPBYTE pBuffer = pReq->pBuffer;
#ifndef UNDER_BOOTLOADER
    BOOL bLastMode = SetKMode(TRUE);
#endif
    BOOL fRet = FALSE;

    if (pReq->dwStartBlock >= g_FMDInfo.TotalFlashBlocks ||
        dwEndBlock >= g_FMDInfo.TotalFlashBlocks ||
        dwEndBlock < pReq->dwStartBlock)
    {
        LOGMSG(1, (TEXT("FMD:RawWriteBlocks: Invalid request: (0x%x, 0x%x)\r\n"), pReq->dwStartBlock, pReq->dwNumBlocks));
        goto Error;
    }

    if (pReq->cbBuffer < (pReq->dwNumBlocks * g_FMDInfo.BlockSize))
    {
        LOGMSG(1, (TEXT("FMD:RawWriteBlocks: Insufficient buffer: (0x%x)\r\n"), pReq->cbBuffer));
        goto Error;
    }

    DBGMSG(1, (TEXT("FMD:RawWriteBlocks: (0x%x,0x%x)\r\n"), pReq->dwStartBlock, pReq->dwNumBlocks));

    for (DWORD dwBlock = pReq->dwStartBlock; dwBlock <= dwEndBlock; dwBlock++)
    {
        if (!WriteBlock (dwBlock, pBuffer, 0, g_FMDInfo.BlockSize))
        {
            LOGMSG(1, (TEXT("FMD:RawWriteBlocks: WriteBlock failed (0x%x)\r\n"), dwBlock));
            goto Error;
        }

        pBuffer += g_FMDInfo.BlockSize;
    }

    fRet = TRUE;

    Error:
#ifndef UNDER_BOOTLOADER
    SetKMode(bLastMode);
#endif
    return(fRet);
}



BOOL IsReservedTableBlock (BLOCK_ID dwBlock)
{
    for (DWORD i = 0; i < g_dwNumReserved; i++)
    {
        if (dwBlock >= g_pReservedTable[i].dwStartBlock &&
            dwBlock <= (g_pReservedTable[i].dwStartBlock + g_pReservedTable[i].dwNumBlocks - 1))
        {
            return(TRUE);
        }
    }

    return(FALSE);
}


/////////////
/* ******* */
/////////////
DWORD GetRegion (DWORD dwBlock)
{
    for (DWORD i = 0; i < g_dwNumRegions; i++)
    {
        if (dwBlock >= g_pRegionTable[i].dwStartPhysBlock &&
            dwBlock < (g_pRegionTable[i].dwStartPhysBlock + g_pRegionTable[i].dwNumPhysBlocks))
        {
            //DBGMSG(1, (TEXT("GetRegion: BlockID[%d] is in Region[%d]\r\n"), dwBlock, i));
            return(i);
        }
    }

    LOGMSG(1, (TEXT("GetRegion: Could not find region for block 0x%x.\r\n"), dwBlock));
    ASSERT(0);
    return(INVALID_BLOCK_ID);
}


SECTOR_ADDR GetStartSectorInBlock (DWORD dwBlock)
{
    DWORD i = GetRegion(dwBlock);
    if (i == INVALID_BLOCK_ID)
        return(INVALID_SECTOR_ADDR);

    // The starting sector in the block is the starting physical sector
    // of the region plus the block offset into the region times
    // the sectors per block

    //DBGMSG(1, (TEXT("GetStartSectorInBlock: The start sector for block[%d] = %d.\r\n"), dwBlock, (g_pStartSectorTable[i] + (dwBlock - g_pRegionTable[i].dwStartPhysBlock) * g_pRegionTable[i].dwSectorsPerBlock)));
    return(g_pStartSectorTable[i] + (dwBlock - g_pRegionTable[i].dwStartPhysBlock) * g_pRegionTable[i].dwSectorsPerBlock);
}


// bman: this routine seems ok
//
VOID GetPhysicalSectorAddress (DWORD dwSector, PSECTOR_ADDR pStartSectorAddr, PSECTOR_ADDR pStartSectorInfoAddr, BLOCK_ID *pBlockID)
{
    for (DWORD i = 0; i < g_dwNumRegions; i++)
    {
        // Determine the region this physical sector resides in
        if (dwSector >= g_pStartSectorTable[i] &&
            ((i == g_dwNumRegions - 1) || (dwSector < g_pStartSectorTable[i+1])))
        {
            DWORD dwSectorOffsetInRegion = dwSector - g_pStartSectorTable[i];
            DWORD dwBlockID = dwSectorOffsetInRegion / g_pRegionTable[i].dwSectorsPerBlock + g_pRegionTable[i].dwStartPhysBlock;
            DWORD dwSectorOffsetInBlock = dwSectorOffsetInRegion % g_pRegionTable[i].dwSectorsPerBlock;

            // Determine physical address of the block
            SECTOR_ADDR BlockAddr = g_FMDInfo.BaseAddress + (dwBlockID * g_FMDInfo.BlockSize);

            // Determine the physical address of the sector
            *pStartSectorAddr = BlockAddr + (dwSectorOffsetInBlock * g_FMDInfo.SectorSize);

            //DBGMSG(1, (TEXT("GetPhysicalSector

⌨️ 快捷键说明

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