📄 cfiscs.c
字号:
{ int ix; FLBoolean finished; FlashWPTR flashWPtr = (FlashWPTR) flMap(vol.socket, iBlock * vol.erasableBlockSize); for (ix=0; ix < vol.interleaving; ix++) { flashWPtr[ix * thisCFI->interleaveFactor] = (SETUP_BLOCK_ERASE <<8) | SETUP_BLOCK_ERASE; flashWPtr[ix * thisCFI->interleaveFactor] = (CONFIRM_ERASE<<8) | CONFIRM_ERASE; flashWPtr[ix * thisCFI->interleaveFactor] = (CONFIRM_ERASE<<8) | CONFIRM_ERASE; while (flashWPtr[ix * thisCFI->interleaveFactor] != 0x80); do { finished = TRUE; if (!(flashWPtr[ix * thisCFI->interleaveFactor] & SR_READY)) finished = FALSE; else { if (flashWPtr[ix * thisCFI->interleaveFactor] & WSM_ERROR) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: CFISCS erase error on device %d.\n", ix);#endif status = (flashWPtr[ix * thisCFI->interleaveFactor] & SR_VPP_ERROR) ? flVppFailure : flWriteFault; flashWPtr[ix * thisCFI->interleaveFactor] = (CLEAR_STATUS<<8)|CLEAR_STATUS; } flashWPtr[ix * thisCFI->interleaveFactor] = (READ_ARRAY<<8)|READ_ARRAY; } } while (!finished); } }#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) flDontNeedVpp(vol.socket);#endif return status; }#endif /* INTERLEAVED_MODE_REQUIRES_32BIT_WRITES *//**************************************************************************** cfiscsIdentify - Identification routine for devices conforming to CFI/SC** Identifies media based on SCS/CFI and registers as an MTD for such.* This routine will be placed on the MTD list in custom.h. It must be an * extern routine. On successful identification, the Flash structure is filled * out and the write and erase routines registered. ** Parameters:* vol : Pointer identifying drive ** RETURNS:* FLStatus : 0 on positive identification, failed otherwise ** ERRNO** URL:http://developer.intel.com/design/flcomp/applnots/29220404.pdf ** \NOMANUAL*/FLStatus cfiscsIdentify ( FLFlash vol ) { FlashPTR flashPtr = (FlashPTR) flMap(vol.socket,0); FlashWPTR flashWPtr = (FlashWPTR) flashPtr; FlashDPTR flashDPtr = (FlashDPTR) flashPtr; unsigned primaryTable, secondaryTable; char priIdStr[ID_STR_LENGTH + 1] = PRIMARY_ID_STR;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering CFISCS identification routine.\n");#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)]; /* Is this an 8 bit device */ flashPtr[0x55] = 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->interleaveFactor = 1; vol.interleaving = 1; vol.type = (FlashType) ((flashPtr[0] << 8) | flashWPtr[1]); vol.write = cfiscsByteWrite; goto getCFI; } /* Reset to READ_ARRAY and retry. Maybe 16 bit addressing */ flashPtr[0x55] = 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]), READ_ARRAY); if (flashPtr[0x20] != 0x51) /* Turned off successfully */ { thisCFI->multiplier = 2; thisCFI->interleaveFactor = 1; vol.interleaving =2; vol.type = (FlashType) ((flashWPtr[0] << 8) | flashWPtr[1]); vol.write = cfiscsByteWrite;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected two 8 bit devices\n");#endif goto getCFI; } } /* a 16 bit device in 16 bit mode */ if (flashWPtr[0x10] == 'Q' && flashWPtr[0x11] == 'R' && flashWPtr[0x12] == 'Y') { thisCFI->multiplier = 2; thisCFI->interleaveFactor = 1; vol.interleaving = 1; vol.write = cfiscsWordWrite; vol.erase = cfiscsWordErase;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected one 16 bit device\n");#endif goto getCFI; } /* a 16 bit device in 16 bit mode */ if (flashPtr[0x20] == 0x51 && /* 'Q' */ flashPtr[0x21] == 0x00 && /* NUL */ flashPtr[0x22] == 0x52 && /* 'R' */ flashPtr[0x23] == 0x00 && /* NUL */ flashPtr[0x24] == 0x59 && /* 'Y' */ flashPtr[0x25] == 0x00) /* NUL */ { thisCFI->multiplier = 2; thisCFI->interleaveFactor = 1; vol.interleaving = 1; vol.type = (FlashType) ((flashWPtr[0] << 8) | (flashWPtr[1])); vol.write = cfiscsWordWrite;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected one 16 bit device\n");#endif goto getCFI; } /* If we have a 16 bit device in 8 bit mode it should ID correctly */ 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' */ { thisCFI->multiplier = 2;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected a 16 bit device in 8 bit mode\n");#endif vol.interleaving =1; thisCFI->interleaveFactor = 1; vol.type = (FlashType) ((flashWPtr[0] << 8) | flashWPtr[1]); vol.write = cfiscsByteWrite; goto getCFI; } /* Reset to READ_ARRAY and retry. Maybe 32 bit addressing */ flashWPtr[0x55] = (USHORT) ((READ_ARRAY << 8) | READ_ARRAY); flashDPtr[0x55] = (ULONG) (QUERY << 24| QUERY <<16 | QUERY << 8 | QUERY); /* A 32 bit device in 8 bit mode and two 16 bit device in 8 bit mode will * appear the same to the querying process. The only way to make the * distinction is to try and set one device back to read array mode while * the other remains in query mode */ if (flashPtr[0x40] == 0x51 && /* 'Q' */ flashPtr[0x41] == 0x51 && /* 'Q' */ flashPtr[0x42] == 0x51 && /* 'Q' */ flashPtr[0x43] == 0x51 && /* 'Q' */ flashPtr[0x44] == 0x52 && /* 'R' */ flashPtr[0x45] == 0x52 && /* 'R' */ flashPtr[0x46] == 0x52 && /* 'R' */ flashPtr[0x47] == 0x52 && /* 'R' */ flashPtr[0x48] == 0x59 && /* 'Y' */ flashPtr[0x49] == 0x59 && /* 'Y' */ flashPtr[0x4a] == 0x59 && /* 'Y' */ flashPtr[0x4b] == 0x59) /* 'Y' */ { /* See if we can turn one off */ flashPtr[0x154] = READ_ARRAY; if ((flashPtr[0x40] != 0x51) && (flashPtr[0x41] == 0x51)) { /* Turned one device off successfully */ flashPtr[0x154] = QUERY; /* turn it back on to query mode */ vol.interleaving = 2; vol.type = (FlashType) ((flashWPtr[0] << 8) | (flashWPtr[4]));#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected two 16 bit device, 8 bit interleaved(2)\n");#endif } else { vol.interleaving =1;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected a 32 bit device in 8 bit mode\n");#endif vol.type = (FlashType) ((flashDPtr[0] << 8) | flashDPtr[1]); } thisCFI->multiplier = 4; thisCFI->interleaveFactor = 1; vol.write = cfiscsByteWrite; goto getCFI; } /* Is it a single 32 bit device */ if (flashPtr[0x40] == 0x51 && /* 'Q' */ flashPtr[0x41] == 0x00 && /* NUL */ flashPtr[0x42] == 0x00 && /* NUL */ flashPtr[0x43] == 0x00 && /* NUL */ flashPtr[0x44] == 0x52 && /* 'R' */ flashPtr[0x45] == 0x00 && /* NUL */ flashPtr[0x46] == 0x00 && /* NUL */ flashPtr[0x47] == 0x00 && /* NUL */ flashPtr[0x48] == 0x59 && /* 'Y' */ flashPtr[0x49] == 0x00 && /* NUL */ flashPtr[0x4a] == 0x00 && /* NUL */ flashPtr[0x4b] == 0x00) /* NUL */ {#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: detected a 32 bit device in 32 bit mode\n");#endif thisCFI->multiplier = 4; thisCFI->interleaveFactor = 1; vol.interleaving = 1; vol.type = (FlashType) ((flashDPtr[0] << 8) | flashDPtr[1]); vol.write = cfiscsDWordWrite; goto getCFI; } /* Two 16 bit devices in 16 bit mode */ if (flashPtr[0x41] == 0x51 && /* 'Q' */ flashPtr[0x40] == 0x00 && /* NUL */ flashPtr[0x43] == 0x51 && /* 'Q' */ flashPtr[0x42] == 0x00 && /* NUL */ flashPtr[0x45] == 0x52 && /* 'R' */ flashPtr[0x44] == 0x00 && /* NUL */ flashPtr[0x47] == 0x52 && /* 'R' */ flashPtr[0x46] == 0x00 && /* NUL */ flashPtr[0x49] == 0x59 && /* 'Y' */ flashPtr[0x48] == 0x00 && /* NUL */ flashPtr[0x4b] == 0x59 && /* 'Y' */ flashPtr[0x4a] == 0x00) /* NUL */ {#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: Detected two 16 bit devices in 16 bit mode(3)\n");#endif thisCFI->multiplier = 4; thisCFI->interleaveFactor = 1; vol.interleaving = 2; vol.type = (FlashType) (flashPtr[0] << 8 | flashPtr[thisCFI->multiplier]); vol.write = cfiscsWordWrite; 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) (READ_ARRAY << 24| READ_ARRAY <<16 | READ_ARRAY << 8 | READ_ARRAY); return flUnknownMedia; getCFI: /* check the command set ID */ thisCFI->commandSetId = *(USHORT *)(&flashPtr[0x13 * thisCFI->multiplier]); if (thisCFI->commandSetId != INTEL_COMMAND_SET && 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 = flashPtr[(0x15 * thisCFI->multiplier) + 1] | ((unsigned)flashPtr[(0x16 * thisCFI->multiplier)+1] << 8); /* check alternate command set ID. */ thisCFI->altCommandSetId = flashPtr[(0x17 * thisCFI->multiplier)+1] | ((unsigned)flashPtr[(0x18 * thisCFI->multiplier)+1] << 8); if (thisCFI->altCommandSetId != INTEL_ALT_COMMAND_SET && thisCFI->altCommandSetId != AMDFUJ_ALT_COMMAND_SET && thisCFI->altCommandSetId != ALT_NOT_SUPPORTED) return flUnknownMedia; /* get address for secondary algorithm extended table. */ secondaryTable = flashPtr[(0x19 * thisCFI->multiplier)+1] | ((unsigned)flashPtr[(0x1a * thisCFI->multiplier)+1] << 8); thisCFI->vpp = flashPtr[(0x1d * thisCFI->multiplier)+1]; vol.erasableBlockSize = (flashPtr[(0x2f * thisCFI->multiplier)+1] | ((unsigned)flashPtr[(0x30 * thisCFI->multiplier)+1] << 8)) * 0x100L; /* we reserve one erase block for NVRAM usage */#ifdef SAVE_NVRAM_REGION vol.chipSize = 0x400000 - vol.erasableBlockSize;#else vol.chipSize = 0x400000;#endif vol.erasableBlockSize *= vol.interleaving;#ifdef BUFFERED_WRITE_BROKEN thisCFI->maxBytesWrite = 2;#else thisCFI->maxBytesWrite = 1L << (flashPtr[(0x2a * thisCFI->multiplier)+1] | ((unsigned)flashPtr[(0x2b * thisCFI->multiplier)+1] << 8));#endif /* BUFFERED_WRITE_BROKEN */ /* In this part we access the primary extended table implemented by Intel. * If the device uses a different extended table, it should be accessed * according to the vendor specifications. */ if ((primaryTable) && (thisCFI->commandSetId == INTEL_COMMAND_SET)) { /* look for the primary table identification string "PRI" */ if (priIdStr[0] != flashPtr[(primaryTable * thisCFI->multiplier)+1] || priIdStr[1] != flashPtr[((primaryTable + 1) * thisCFI->multiplier)+1] || priIdStr[2] != flashPtr[((primaryTable + 2) * thisCFI->multiplier)+1]) {#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: No primary ID @ offset 0x%x\n", primaryTable);#endif return flUnknownMedia; } thisCFI->optionalCommands = flashPtr[((primaryTable + 5) * thisCFI->multiplier)+1] | ((long)flashPtr[((primaryTable + 6) * thisCFI->multiplier)+1] << 8) | ((long)flashPtr[((primaryTable + 7) * thisCFI->multiplier)+1] << 16) | ((long)flashPtr[((primaryTable + 8) * thisCFI->multiplier)+1] << 24); thisCFI->afterSuspend = flashPtr[((primaryTable + 9) * thisCFI->multiplier)+1]; } else { thisCFI->optionalCommands = 0; thisCFI->afterSuspend = 0; } /* Make sure this comes at the end since the device is set to READ_ARRAY * mode prior to the return */ if (cfiscsGetChipCount(&vol) != flOK) return flUnknownMedia;#ifdef DEBUG_PRINT DEBUG_PRINT ("Debug: No of chips detected is %d\n", vol.noOfChips);#endif#ifdef INTERLEAVED_MODE_REQUIRES_32BIT_WRITES vol.erase = cfiscsInterleavedWordErase;#else /* !INTERLEAVED_MODE_REQUIRES_32BIT_WRITES */ vol.erase = cfiscsWordErase;#endif /* INTERLEAVED_MODE_REQUIRES_32BIT_WRITES */ /* Might have to do this on a bus width basis but for now it seems to * work with Intel devices. */ *(UINT16*)(&flashPtr[0]) = (READ_ARRAY<<8)|READ_ARRAY; return flOK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -