📄 flash.c
字号:
//------------------------------------------------------------------------------
static BOOL ReadIdent1(UINT32 base, UINT32 block, OAL_FLASH_INFO *pInfo, BYTE* pId, UINT32 count)
{
UINT32 offset = 0x81;
UINT32 i = 0;
// Start read device identification command
WriteCommand(base, 0, 0x90, pInfo->width, pInfo->parallel);
// Now read count bytes into the pId buffer
// bytes are contiguous, so don't read every other byte
while (i < count)
{
// read a width at the following offset
UINT32 Ident = ReadIdentification(block, offset, pInfo->width);
memcpy(pId, &Ident, pInfo->width);
// read a width at a time
pId += pInfo->width;
i+= pInfo->width;
// each width == 1 offset (ie reading 0x81-0x88 with a width = 2 will get 16 bytes)
offset++;
}
// Switch back to read mode
WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);
return TRUE;
}
//------------------------------------------------------------------------------
BOOL OALFlashInfo(VOID *pBase, OAL_FLASH_INFO *pInfo)
{
BOOL rc = FALSE;
UINT32 base, code1, code2, code3, i;
OALMSG(OAL_FUNC, (L"+OALFlashInfo(0x%08x, ...)\r\n", pBase));
// Just to avoid possible problems
memset(pInfo, 0, sizeof(*pInfo));
// Make sure that we talk to uncached address
base = (UINT32)OALCAtoUA(pBase);
// Try 32-bit geometry
//OUTREG32((UINT32*)(base + 4 * 0x5555), 0xAAAAAAAA);
//OUTREG32((UINT32*)(base + 4 * 0x2AAA), 0x55555555);
OUTREG32((UINT32*)(base + 4 * 0x5555), 0x98989898);
code1 = INREG32((UINT32*)(base + 4 * 0x10));
code2 = INREG32((UINT32*)(base + 4 * 0x11));
code3 = INREG32((UINT32*)(base + 4 * 0x12));
if (code1 == 'QQQQ' && code2 == 'RRRR' && code3 == 'YYYY') {
pInfo->width = 4;
pInfo->parallel = 4;
} else if (code1 == 'Q\0Q\0' && code2 == 'R\0R\0' && code3 == 'Y\0Y\0') {
pInfo->width = 4;
pInfo->parallel = 2;
} else if (code1 == 'Q\0\0\0' && code2 == 'R\0\0\0' && code3 == 'Y\0\0\0') {
pInfo->width = 4;
pInfo->parallel = 1;
} else {
// Now try luck with 16-bit geometry
//OUTREG16((UINT16*)(base + 2 * 0x5555), 0xAAAA);
//OUTREG16((UINT16*)(base + 2 * 0x2AAA), 0x5555);
OUTREG16((UINT16*)(base + 2 * 0x5555), 0x9898);
code1 = INREG16((UINT16*)(base + 2 * 0x10));
code2 = INREG16((UINT16*)(base + 2 * 0x11));
code3 = INREG16((UINT16*)(base + 2 * 0x12));
if (code1 == 'QQ' && code2 == 'RR' && code3 == 'YY') {
pInfo->width = 2;
pInfo->parallel = 2;
} else if (code1 == '\0Q' && code2 == '\0R' && code3 == '\0Y') {
pInfo->width = 2;
pInfo->parallel = 1;
} else {
// So last oppurtinity is 8-bit mode
//OUTREG8((UINT8*)(base + 0x5555), 0xAA);
//OUTREG8((UINT8*)(base + 0x2AAA), 0x55);
OUTREG8((UINT8*)(base + 0x5555), 0x98);
code1 = INREG8((UINT8*)(base + 0x10));
code2 = INREG8((UINT8*)(base + 0x11));
code3 = INREG8((UINT8*)(base + 0x12));
if (code1 == 'Q' && code2 == 'R' && code3 == 'Y') {
pInfo->width = 1;
pInfo->parallel = 1;
} else {
goto cleanUp;
}
}
}
// Read primary command set, size, burst size and number of regions
pInfo->set = ReadInfo(base, 0x13, 2, pInfo->width);
pInfo->size = 1 << ReadInfo(base, 0x27, 1, pInfo->width);
pInfo->burst = 1 << ReadInfo(base, 0x2A, 1, pInfo->width);
pInfo->regions = ReadInfo(base, 0x2C, 1, pInfo->width);
// If there is more regions than expected
if (pInfo->regions > 8) goto cleanUp;
// Read region info
for (i = 0; i < pInfo->regions; i++) {
code1 = ReadInfo(base, 0x2d + (i << 2), 4, pInfo->width);
pInfo->aBlocks[i] = (code1 & 0xFFFF) + 1;
pInfo->aBlockSize[i] = (code1 >> 8) & 0x00FFFF00;
if (pInfo->aBlockSize[i] == 0) pInfo->aBlockSize[i] = 128;
}
// Switch back to read mode
switch (pInfo->set) {
case 1: // Intel/Sharp
case 3: // New Intel parts
WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);
break;
case 2: // AMD/Fujitsu
case 0x0701: // SST
WriteCommand(base, 0, 0xF0, pInfo->width, pInfo->parallel);
break;
}
rc = TRUE;
cleanUp:
OALMSG(OAL_FUNC, (L"-OALFlashInfo(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
BOOL OALFlashErase(VOID *pBase, VOID *pStart, UINT32 size)
{
BOOL rc = FALSE;
OAL_FLASH_INFO info;
UINT32 base, start, end, chip, block;
UINT32 ixReg, ixBlock;
OALMSG(OAL_FUNC, (
L"+OALFlashErase(0x%08x, 0x%08x, 0x%08x)\r\n", pBase, pStart, size
));
// Erase must work from uncached memory
base = (UINT32)OALCAtoUA(pBase);
start = (UINT32)OALCAtoUA(pStart);
// First get end address
end = start + size;
// Ther read first chip info
if (!OALFlashInfo((VOID*)base, &info)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALFlashErase failed get flash memory info\r\n"
));
goto cleanUp;
}
ixReg = ixBlock = 0;
block = chip = base;
while (block < end) {
// Should block be erased?
if (
start < (block + info.aBlockSize[ixReg] * info.parallel) &&
end >= block
) {
switch (info.set) {
case 1: // Intel/Sharp
case 3: // New Intel parts
if (!UnlockBlock1(chip, block, &info)) {
goto cleanUp;
}
if (!EraseBlock1(chip, block, &info)) {
goto cleanUp;
}
break;
case 2: // AMD
case 0x0701: // SST
if (!EraseBlock2(chip, block, &info)) {
goto cleanUp;
}
break;
default:
OALMSG(OAL_ERROR, (
L"ERROR: Flash type %d isn't supported\r\n", info.set
));
goto cleanUp;
}
}
// Move to next block
block += info.aBlockSize[ixReg] * info.parallel;
if (block >= end) break;
if (++ixBlock >= info.aBlocks[ixReg]) {
ixBlock = 0;
if (++ixReg >= info.regions) {
// Try read next chip info
if (!OALFlashInfo((VOID*)block, &info)) break;
ixReg = 0;
chip = block;
}
}
}
rc = TRUE;
cleanUp:
OALMSG(OAL_FUNC, (L"-OALFlashErase(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
BOOL OALFlashWrite(VOID *pBase, VOID *pStart, UINT32 size, VOID *pBuffer)
{
BOOL rc = FALSE;
OAL_FLASH_INFO info;
UINT32 base, start, end, chip, pos, count;
UINT8 *pPos;
OALMSG(OAL_FUNC, (
L"+OALFlashWrite(0x%08x, 0x%08x, 0x%08x, 0x%08x)\r\n",
pBase, pStart, size, pBuffer
));
// Flash must work from uncached memory
base = (UINT32)OALCAtoUA(pBase);
start = (UINT32)OALCAtoUA(pStart);
// First get end address
end = start + size;
chip = base;
pPos = (UINT8*)pBuffer;
// First read first chip info
while (TRUE) {
if (!OALFlashInfo((VOID*)chip, &info)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALFlashWrite - failed get flash info at 0x%08x\r\n",
chip
));
goto cleanUp;
}
// Is start address on this chip
if (start >= chip && start < (chip + info.size * info.parallel)) break;
// Move to next chip
chip += info.size * info.parallel;
}
pos = start;
while (pos < end) {
// Program data chunk
switch (info.set) {
case 1:
case 3:
count = WriteData1(chip, pos, &info, pPos);
break;
case 2:
case 0x0701: // SST
count = WriteData2(chip, pos, &info, pPos);
break;
default:
OALMSG(OAL_ERROR, (
L"ERROR: Flash type %d isn't supported\r\n", info.set
));
goto cleanUp;
}
// If we write nothing some problem happen
if (count == 0) {
rc = FALSE;
OALMSG(OAL_ERROR, (
L"ERROR: Flash write at 0x%08x failed\r\n", pos
));
goto cleanUp;
}
// Move position
pos += count;
pPos += count;
// If we run out of chip move to next one
if (pos > (chip + info.size * info.parallel)) {
switch (info.set) {
case 1:
case 3:
WriteCommand(chip, 0, 0xFF, info.width, info.parallel);
break;
case 2:
WriteCommand(chip, 0, 0xF0, info.width, info.parallel);
break;
}
chip += info.size * info.parallel;
if (!OALFlashInfo((VOID*)chip, &info)) break;
}
}
switch (info.set) {
case 1:
case 3:
WriteCommand(chip, 0, 0xFF, info.width, info.parallel);
break;
case 2:
case 0x0701: // SST
WriteCommand(chip, 0, 0xF0, info.width, info.parallel);
break;
}
// Do final check
pPos = (UINT8*)pBuffer;
for (pos = start; pos < end - sizeof(UINT32) + 1; pos += sizeof(UINT32)) {
if (*(UINT32*)pPos != *(UINT32*)pos) break;
pPos += sizeof(UINT32);
}
// If we reach end, all is ok
rc = (pos >= end - sizeof(UINT32) + 1);
OALMSG(!rc&&OAL_ERROR, (
L"ERROR: Flash failed at 0x%08x -- write 0x%08x, but read 0x%08x\r\n",
pos, *(UINT32*)pPos, *(UINT32*)pos
));
cleanUp:
OALMSG(OAL_FUNC, (L"-OALFlashWrite(rc = %d)", rc));
return rc;
}
//------------------------------------------------------------------------------
BOOL OALFlashIdentifier(VOID *pBase, BYTE* pIdent, DWORD* pdwSize)
{
BOOL rc = FALSE;
OAL_FLASH_INFO info;
UINT32 base;
OALMSG(OAL_FUNC, (L"+OALFlashIdentifier(0x%08x, ...)\r\n", pBase));
if (pdwSize == NULL || *pdwSize == 0)
{
goto cleanUp;
}
// Make sure that we talk to uncached address
base = (UINT32)OALCAtoUA(pBase);
if (pIdent == NULL)
goto cleanUp;
if (!OALFlashInfo((VOID*)base, &info)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALFlashIdentifier - failed get flash info at 0x%08x\r\n",
base
));
goto cleanUp;
}
// TODO: This works for Intel parts. How about others?
switch (info.set) {
case 1:
case 3:
if (*pdwSize < 8 * info.parallel)
goto cleanUp;
*pdwSize = 8 * info.parallel;
// read 8 bytes of protection register from each chip into pIdent buffer
rc = ReadIdent1(base, base, &info, pIdent, *pdwSize);
break;
case 2:
*pdwSize = 0; // I'm unaware of any chips with set=2 which have an ident
break;
default:
rc = FALSE;
}
cleanUp:
OALMSG(OAL_FUNC, (L"-OALFlashIdentifier(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -