📄 cfiamd.c
字号:
if (flashWPtr[0x20] == 'Q' && flashWPtr[0x21] == 'Q' && flashWPtr[0x22] == 'R' && flashWPtr[0x23] == 'R' && flashWPtr[0x24] == 'Y' && flashWPtr[0x25] == 'Y') {#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: Detected two 16 bit devices in 16 bit mode(3)\n");#endif thisCFI->multiplier = 4; thisCFI->interleaveWidth = 2; vol.interleaving = 2; goto getCFI; } /* If we get here the device is probably not CFI */ #ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: Failed to identify CFI... \n Exiting \n");#endif flashDPtr[0x55] = (ULONG) (AMD_READ_ARRAY << 24| AMD_READ_ARRAY <<16 | AMD_READ_ARRAY << 8 | AMD_READ_ARRAY); return flUnknownMedia;getCFI: if (!eightBitMode) { thisCFI->wordMode = TRUE; /* limitting 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 thei 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; #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 /* Since boot blocks happen to be subdevided erase blocks and TrueFFS does * not support the sub devision of erase blocks the MTD needs to be able * to detect the "sectors" that are sub devisions and erase all of them * (assuming that they are contiguous) together. Since the boot block can * appear either at the top or the bottom, the only way to keep track of * them is to read all sector descriptions and remember them for cross * reference. The size of the largest erase block is registered as the * eraseBlockSize for the volume. */ /* Setup the commands first */ for (i = 0; i < thisCFI->multiplier; i++) { unlock1 |= AMD_UNLOCK_1 << (i * 8); unlock2 |= AMD_UNLOCK_2 << (i * 8); readID |= AMD_READ_ID << (i * 8); readArray |= AMD_READ_ARRAY << (i * 8); } /* Get JEDEC ID so we know if this is a top or bottom boot device */ *(UINT32 *)(flashPtr + (thisCFI->unlockAddr1 * thisCFI->multiplier)) = unlock1; *(UINT32 *)(flashPtr + (thisCFI->unlockAddr2 * thisCFI->multiplier)) = unlock2; *(UINT32 *)(flashPtr + (thisCFI->unlockAddr1 * thisCFI->multiplier)) = readID; if (eightBitMode) vol.type = flashPtr[0] << 8 | flashPtr[thisCFI->interleaveWidth]; else vol.type = (*(USHORT *)(&flashPtr[0]) << 8) | (*(USHORT *)(&flashPtr[thisCFI->multiplier]) & 0x00ff); /* Determine boot block type */ if ((vol.type == Am29DS163DT_FLASH) || (vol.type == Am29DS323DT_FLASH) || (vol.type == Am29PDS322DT_FLASH)|| (vol.type == Am29SL160CT_FLASH) || (vol.type == Am29DL161DT_FLASH) || (vol.type == Am29DL162DT_FLASH) || (vol.type == Am29DL163DT_FLASH) || (vol.type == Am29DL164DT_FLASH) || (vol.type == Am29LV320DT_FLASH) || (vol.type == Am29DL322DT_FLASH) || (vol.type == Am29DL323DT_FLASH) || (vol.type == Am29DL324DT_FLASH) || (vol.type == Am29LV116DT_FLASH) || (vol.type == Am29F160DT_FLASH) || (vol.type == Fuj29LV160TE_FLASH)) thisCFI->bootBlockType = BOOTBLOCK_TOP; else if ((vol.type == Am29DS163DT_FLASH) || (vol.type == Am29DS323DB_FLASH) || (vol.type == Am29PDS322DB_FLASH) || (vol.type == Am29SL160CB_FLASH) || (vol.type == Am29DL161DB_FLASH) || (vol.type == Am29DL162DB_FLASH) || (vol.type == Am29DL163DB_FLASH) || (vol.type == Am29DL164DB_FLASH) || (vol.type == Am29LV320DB_FLASH) || (vol.type == Am29DL322DB_FLASH) || (vol.type == Am29DL323DB_FLASH) || (vol.type == Am29DL324DB_FLASH) || (vol.type == Am29LV116DB_FLASH) || (vol.type == Am29F160DB_FLASH) || (vol.type == Fuj29LV160BE_FLASH)) thisCFI->bootBlockType = BOOTBLOCK_BOTTOM; else if ((vol.type == Am29LV017D_FLASH) || (vol.type == Am29LV033C_FLASH) || (vol.type == Am29LV065D_FLASH) || (vol.type == Am29LV640D_FLASH) || (vol.type == Am29F016D_FLASH) || (vol.type == Am29F017D_FLASH)) thisCFI->bootBlockType = BOOTBLOCK_NONE; else { /* Probably an unregistered device that needs to be added here */#ifdef DEBUG_PRINT DEBUG_PRINT ("Unknown device of type 0x%x \n", vol.type);#endif /* set device back to read array */ *(UINT32 *) flashPtr = AMD_READ_ARRAY; return flUnknownMedia; } /* We now have all of the CFI info that we need. Now lets build up * the sector map and register the erase block sizes. */ if (thisCFI->bootBlockType == BOOTBLOCK_NONE) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: Uniform device, no boot block\n");#endif /* 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; } } else if (thisCFI->bootBlockType == BOOTBLOCK_BOTTOM) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: Bottom boot block device\n");#endif /* This is a hack but when looking at the data sheets for all of * these devices what comes across is that the CFI data always * describes a botom boot device. There for we read the sector * info in the exact order that it is provided in. */ for ( ix = 0; ix < thisCFI->sectorDefs; ix++) { int iy; for (iy = 0; iy < thisCFI->secDesc[ix].numSecs; iy++, thisSector++) { if (thisCFI->secDesc[ix].secSize != 0x00) thisCFI->secInfo[thisSector].sectorSize = thisCFI->secDesc[ix].secSize * 0x100L; else thisCFI->secInfo[thisSector].sectorSize = 0x80L; /* count boot blocks */ if (thisCFI->secInfo[thisSector].sectorSize != vol.erasableBlockSize) thisCFI->bootBlockSectors++; thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs; sectorBaseAdrs += (CardAddress) thisCFI->secInfo[thisSector].sectorSize; } } } else /* Top boot device */ { int secCount;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: Top boot block device\n");#endif /* First load the descriptions of the uniform sectors and * then add the sub divisions */ for ( ix = 0; ix < thisCFI->sectorDefs; ix++) { int iy; /* We assume that the unform sectors will never be of the * variety 128 bytes */ if (vol.erasableBlockSize == thisCFI->secDesc[ix].secSize * 0x100L * vol.interleaving) { for (iy = 0; iy < thisCFI->secDesc[ix].numSecs; iy++, thisSector++) { thisCFI->secInfo[thisSector].sectorSize = vol.erasableBlockSize; thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs; sectorBaseAdrs += (CardAddress) thisCFI->secInfo[thisSector].sectorSize; } break; } } for ( ix = 0, secCount = 0; thisCFI->secDesc[ix].secSize * 0x100L * vol.interleaving != vol.erasableBlockSize; ix++) { int iy; for (iy = 0; iy < thisCFI->secDesc[ix].numSecs; iy++, secCount++) { thisCFI->secInfo[(thisCFI->sectorsInCFI - 1) - secCount].sectorSize = thisCFI->secDesc[ix].secSize * 0x100L * vol.interleaving; } } for (; thisSector <= (thisCFI->sectorsInCFI -1); thisSector++) { thisCFI->secInfo[thisSector].sectorBaseAdrs = sectorBaseAdrs; sectorBaseAdrs += (CardAddress) thisCFI->secInfo[thisSector].sectorSize; thisCFI->bootBlockSectors++; } }#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 + -