📄 am29lv64xdmtd.c
字号:
while ((wFlashPtr[0] != tmpWord.ushort) && (flMsecCounter < writeTimeout)) { if (((wFlashPtr[0] & AMD_D5) && ((wFlashPtr[0] ^ tmpWord.ushort) & 0xff))) { wFlashPtr[0] = read_array;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: write failed in AMD MTD.\n");#endif return flWriteFault; } } cAddr += cLength; buffer = (const void FAR1 *)((UINT32)buffer + cLength); flashPtr = flashPtr + cLength; cLength = 0; } /* cfiAmdLeftoverBytesWrite(&vol, buffer, flashPtr, cLength); */ } flashPtr -= length; buffer = (unsigned char *)buffer - length; /* bBuffer -= length; */ if (tffscmp((void FAR0 *) flashPtr,buffer,length)) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: write failed in AMD MTD on verification.\n");#endif return flWriteFault; } return flOK; }/******************************************************************************** cfiAmdErase - Erase one or more contiguous Flash erasable blocks * * This routine will be registered as the MTD vol.erase routine. Sector zero is * assumed to be the boot block anchor of the boot block on bottom boot devices,* while the first sector of size not equal to vol.erasableBlockSize is assumed * to be the anchor for top boot devices.* * RETURNS: * FLStatus : 0 on success, failed otherwise** ERRNO*/LOCAL FLStatus cfiAmdErase( FLFlash vol, /* Pointer identifying drive */ int firstErasableBlock, /* Number of first block to erase */ int numOfErasableBlocks /* Number of blocks to erase */ ) { int i; UINT32 unlock1 = 0; UINT32 unlock2 = 0; UINT32 erase_setup = 0; UINT32 erase_sector = 0; int thisSector = firstErasableBlock; int sectorsToErase = numOfErasableBlocks; UINT32 * unlockAddr1; UINT32 * unlockAddr2; if (flWriteProtected(vol.socket)) return flWriteProtect; /* Setup the commands first */ for (i = 0; i < thisCFI->multiplier; i++) { unlock1 |= AMD_UNLOCK_1 << (i * 8); unlock2 |= AMD_UNLOCK_2 << (i * 8); erase_setup |= AMD_SETUP_ERASE << (i * 8); erase_sector |= AMD_SECTOR_ERASE << (i * 8); } for ( ; thisSector < firstErasableBlock + sectorsToErase; thisSector++) { int i; FLBoolean finished; FlashPTR flashPtr;#ifdef DEBUG_PRINT DEBUG_PRINT("Clearing sector %d\n", thisSector);#endif /* we know we are on a unit boundary so mapBase is not necessary */ flashPtr = (FlashPTR) vol.map(&vol, thisCFI->secInfo[thisSector].sectorBaseAdrs, 0); unlockAddr1 = (UINT32 *)((long)flashPtr + (thisCFI->unlockAddr1 *thisCFI->multiplier)); unlockAddr2 = (UINT32 *)((long)flashPtr + (thisCFI->unlockAddr2 *thisCFI->multiplier)); *(UINT16 *)unlockAddr1 = unlock1; *(UINT16 *)unlockAddr2 = unlock2; *(UINT16 *)unlockAddr1 = erase_setup; *(UINT16 *)unlockAddr1 = unlock1; *(UINT16 *)unlockAddr2 = unlock2; *(UINT16 *)flashPtr = erase_sector; do { finished = TRUE; for (i = 0;i < thisCFI->multiplier;i += thisCFI->interleaveWidth) { if (flashPtr[i] != 0xff) { if ((flashPtr[i] & AMD_D5) && flashPtr[i] != 0xff) { int x; UINT32 c; for (x = 0, c = 0; x < thisCFI->multiplier; x++) c |= AMD_READ_ARRAY << (x * 8); flashPtr[i] = c;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: erase failed in AMD MTD.\n");#endif return flWriteFault; } finished = FALSE; } } } while (!finished); } return flOK; }/**************************************************************************** cfiscsIdentify - Identification routine for devices conforming to CFI/SC** Identifies media based on CFI and the AMD/Fujitsu command set and registers* as an MTD for such. This routine should be placed on the MTD list in * flcustom.h. It must be an extern routine. On successful identification, the* Flash structure is filled out and the write and erase routines registered. ** RETURNS:* FLStatus : 0 on positive identification, failed otherwise ** ERRNO** http://www.amd.com/us-en/FlashMemory/ProductInformation/0,,37_1447_1451_1780%5E1834%5E1955,00.html** \NOMANUAL*/FLStatus cfiAmdIdentify ( FLFlash vol /* Pointer identifying drive */ ) { FlashPTR flashPtr = (FlashPTR) flMap(vol.socket, 0); FlashWPTR flashWPtr = (FlashWPTR) flashPtr; unsigned primaryTable, secondaryTable; FLBoolean eightBitMode = FALSE; int thisSector = 0; /* running count of sectors for this CFI */ CardAddress sectorBaseAdrs = 0; /* base address of this sector */ int ix = 0;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering CFIAMD identification routine.\n"); DEBUG_PRINT("Debug: flash base addr = 0x%x\n", (UINT32)flashPtr);#endif flSetWindowBusWidth(vol.socket, 16);/* use 16-bits */ flSetWindowSpeed(vol.socket, 120); /* 120 nsec. */ flSetWindowSize(vol.socket, 2); /* 8 KBytes */ vol.mtdVars = &mtdVars[flSocketNoOf(vol.socket)]; thisCFI->bootBlockSectors = 0; /* Is this an 8 bit device */ flashPtr[0x55] = AMD_READ_ARRAY; flashPtr[0x55] = QUERY; if (flashPtr[0x10] == 0x51 && /* 'Q' */ flashPtr[0x11] == 0x52 && /* 'R' */ flashPtr[0x12] == 0x59) /* 'Y' */ {#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected single 8 bit device\n");#endif thisCFI->multiplier = 1; thisCFI->interleaveWidth = 1; vol.interleaving = 1; eightBitMode = TRUE; goto getCFI; } /* Reset to READ_ARRAY and retry. Maybe 16 bit addressing */ flashPtr[0x55] = AMD_READ_ARRAY; flashWPtr[0x55] = (USHORT) ((QUERY << 8) | QUERY); /* Check for two interleaved 8 bit parts */ if (flashPtr[0x20] == 0x51 && /* 'Q' */ flashPtr[0x21] == 0x51 && /* 'Q' */ flashPtr[0x22] == 0x52 && /* 'R' */ flashPtr[0x23] == 0x52 && /* 'R' */ flashPtr[0x24] == 0x59 && /* 'Y' */ flashPtr[0x25] == 0x59) /* 'Y' */ { /* Let's try turning one off */ CFI_WORD_WRITE((FlashWPTR)(&flashPtr[0x55]), AMD_READ_ARRAY); if (flashPtr[0x20] != 0x51) /* Turned off successfully */ { thisCFI->multiplier = 2; thisCFI->interleaveWidth = 1; vol.interleaving =2;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected two 8 bit devices\n");#endif eightBitMode = TRUE; goto getCFI; } } /* a 16 bit device in 16 bit mode */ if (flashWPtr[0x10] == 'Q' && flashWPtr[0x11] == 'R' && flashWPtr[0x12] == 'Y') { thisCFI->multiplier = 2; thisCFI->interleaveWidth = 1; vol.interleaving = 1;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected one 16 bit device\n");#endif goto getCFI; }#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: No flash media detected!\n");#endif return flUnknownMedia; getCFI: if (!eightBitMode) { thisCFI->wordMode = TRUE; /* limiting ourselves to 8 an 16 bit devs */ thisCFI->unlockAddr1 = AMD_WW_UNLOCK_ADDR1; thisCFI->unlockAddr2 = AMD_WW_UNLOCK_ADDR2;#ifdef DEBUG_PRINT DEBUG_PRINT("WORD MODE !!\n");#endif } else { thisCFI->wordMode = FALSE; thisCFI->unlockAddr1 = AMD_BW_UNLOCK_ADDR1; thisCFI->unlockAddr2 = AMD_BW_UNLOCK_ADDR2;#ifdef DEBUG_PRINT DEBUG_PRINT("WORD MODE !!\n");#endif } /* check the command set ID */ /* NOTE: Not swapped */ thisCFI->commandSetId = *(USHORT *)(&flashPtr[0x13 * thisCFI->multiplier]);#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: Commandset ID is 0x%x\n", thisCFI->commandSetId);#endif /* Only support the AMD/Fujitsu Command set */ if ( thisCFI->commandSetId != AMDFUJ_COMMAND_SET) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: did not recognize command set.\n");#endif return flUnknownMedia; } /* get address for primary algorithm extended table. */ primaryTable = CFI_WORD_READ(&flashPtr[0x15 * thisCFI->multiplier]); /* check alternate command set ID. */ /* NOTE: not swapped */ thisCFI->altCommandSetId = *(USHORT *) (&flashPtr[0x17 * thisCFI->multiplier]); if (thisCFI->altCommandSetId != AMDFUJ_ALT_COMMAND_SET && thisCFI->altCommandSetId != ALT_NOT_SUPPORTED) return flUnknownMedia; /* get address for secondary algorithm extended table. */ secondaryTable = CFI_WORD_READ(&flashPtr[0x19 * thisCFI->multiplier]); thisCFI->vpp = flashPtr[0x1d * thisCFI->multiplier]; /*Get the number of erase block descriptions for the CFI*/ if (eightBitMode) thisCFI->sectorDefs = (int) (*(UCHAR *) (&flashPtr[0x2c * thisCFI->multiplier])); else thisCFI->sectorDefs = (int) (*(USHORT *) (&flashPtr[0x2c * thisCFI->multiplier])); /* We should bail out if this is greater than 8 */#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: Number of erase block descriptions is 0x%x\n", thisCFI->sectorDefs);#endif vol.erasableBlockSize = 0; thisCFI->sectorsInCFI = 0; for ( ix = 0; ix < thisCFI->sectorDefs; ix++) { thisCFI->secDesc[ix].numSecs = (int) (*(USHORT *) (&flashPtr[(0x2d + (ix * 4)) * thisCFI->multiplier])); thisCFI->secDesc[ix].numSecs++;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: Num sectors in %d - %d\n", ix, thisCFI->secDesc[ix].numSecs);#endif thisCFI->secDesc[ix].secSize = (long) ((*(USHORT *) (&flashPtr[(0x2f + (ix * 4)) * thisCFI->multiplier])) + (*(USHORT *)(&flashPtr[(0x30 + (ix * 4)) * thisCFI->multiplier])) * 0x100L);#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: Sector size is 0x%x\n", (UINT32) thisCFI->secDesc[ix].secSize);#endif /* TrueFFS does not support the flexible sector architecture so we * take the largest sector size to be the erase block size. */ if (vol.erasableBlockSize < thisCFI->secDesc[ix].secSize) vol.erasableBlockSize = thisCFI->secDesc[ix].secSize; /* Also track the number of sector on this device */ thisCFI->sectorsInCFI += thisCFI->secDesc[ix].numSecs; } if (vol.erasableBlockSize == 0x00) vol.erasableBlockSize = 0x80L; else vol.erasableBlockSize *= 256; /* Get Device Size */ if (eightBitMode) vol.chipSize = (1L << flashPtr[0x27 * thisCFI->multiplier]); else vol.chipSize = (1L << *(USHORT*)(&flashPtr[0x27 * thisCFI->multiplier])); vol.erasableBlockSize *= vol.interleaving; vol.chipSize -= CDS85XX_FLASH_RESERVED_SIZE;#ifdef SAVE_NVRAM_REGION /* Top boot block devices will loose their entire boot block to NVRAM. Since * TrueFFS cares not about the subdivisions we reserve an entire erase block * on each of the interleaved devices. */ vol.chipSize -= vol.erasableBlockSize;#endif#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: %d sectors on device\n", thisCFI->sectorsInCFI); DEBUG_PRINT("Debug: Erasable block size is 0x%lx\n", vol.erasableBlockSize); DEBUG_PRINT("Debug: Chip size is 0x%lx\n", vol.chipSize);#endif thisCFI->bootBlockType = BOOTBLOCK_NONE; /* Simplest case is the uniform sector device. Has only one * sector desc. */ for (; thisSector < thisCFI->secDesc[0].numSecs; thisSector++) { thisCFI->secInfo[thisSector].sectorSize = vol.erasableBlockSize; thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs; sectorBaseAdrs += (CardAddress) vol.erasableBlockSize; }#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: Number of boot block sectors is %d\n", thisCFI->bootBlockSectors);#endif /* Make sure this comes at the end since the device is set to READ_ARRAY * mode prior to the return */ if (cfiAmdChipCountGet(&vol) != flOK) return flUnknownMedia;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: No of chips detected is %d\n", vol.noOfChips);#if 0 for (ix = 0; ix < thisCFI->sectorsInCFI; ix++) DEBUG_PRINT ("%2d:0x%x --- 0x%lx\n", ix, thisCFI->secInfo[ix].sectorBaseAdrs, thisCFI->secInfo[ix].sectorSize);#endif#endif vol.erase = cfiAmdErase; vol.write = cfiAmdWrite; /* Might have to do this on a bus width basis but for now it seems to * work with Intel devices. */ flashPtr[0] = AMD_READ_ARRAY; flashPtr[1] = AMD_READ_ARRAY; flashPtr[2] = AMD_READ_ARRAY; flashPtr[3] = AMD_READ_ARRAY; return flOK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -