📄 cfiscs.c
字号:
flashPtr = (FlashPTR)flMap(vol.socket, 0); flashPtr[0x55 * vol.interleaving] = QUERY; vol.interleaving *= thisCFI->multiplier; /* jump over the copies of the same byte */ /* look for the query identification string "QRY" */ if (queryIdStr[0] != flashPtr[0x10 * vol.interleaving] || queryIdStr[1] != flashPtr[0x11 * vol.interleaving] || queryIdStr[2] != flashPtr[0x12 * vol.interleaving]) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: did not recognize CFI.\n"); #endif return flUnknownMedia; } /* check the command set ID */ thisCFI->commandSetId = flashPtr[0x13 * vol.interleaving] | ((unsigned)flashPtr[0x14 * vol.interleaving] << 8); 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 * vol.interleaving] | ((unsigned)flashPtr[0x16 * vol.interleaving] << 8); /* check alternate command set ID. */ thisCFI->altCommandSetId = flashPtr[0x17 * vol.interleaving] | ((unsigned)flashPtr[0x18 * vol.interleaving] << 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 * vol.interleaving] | ((unsigned)flashPtr[0x1a * vol.interleaving] << 8); thisCFI->vpp = flashPtr[0x1d * vol.interleaving]; vol.chipSize = 1L << flashPtr[0x27 * vol.interleaving]; thisCFI->maxBytesWrite = 1L << (flashPtr[0x2a * vol.interleaving] | ((unsigned)flashPtr[0x2b * vol.interleaving] << 8)); /* divide by multiplier because interleaving is multiplied by multiplier */ vol.erasableBlockSize = (flashPtr[0x2f * vol.interleaving] | ((unsigned)flashPtr[0x30 * vol.interleaving]) << 8) * 0x100L * vol.interleaving / thisCFI->multiplier; /* 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 * vol.interleaving] || priIdStr[1] != flashPtr[(primaryTable + 1) * vol.interleaving] || priIdStr[2] != flashPtr[(primaryTable + 2) * vol.interleaving]) return flUnknownMedia; thisCFI->optionalCommands = flashPtr[(primaryTable + 5) * vol.interleaving] | ((long)flashPtr[(primaryTable + 6) * vol.interleaving] << 8) | ((long)flashPtr[(primaryTable + 7) * vol.interleaving] << 16) | ((long)flashPtr[(primaryTable + 8) * vol.interleaving] << 24); thisCFI->afterSuspend = flashPtr[(primaryTable + 9) * vol.interleaving]; } else { thisCFI->optionalCommands = 0; thisCFI->afterSuspend = 0; } flashPtr[0] = READ_ARRAY; vol.interleaving /= thisCFI->multiplier; /* return to the real interleaving*/ return flOK;}/*----------------------------------------------------------------------*//* g e t W o r d C F I *//* *//* Load important CFI data to the CFI structure in a word-mode. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* *//* Returns: *//* FLStatus : 0 = OK, otherwise failed. *//*----------------------------------------------------------------------*/static FLStatus getWordCFI(FLFlash vol){ unsigned primaryTable, secondaryTable; char queryIdStr[ID_STR_LENGTH + 1] = QUERY_ID_STR; char priIdStr[ID_STR_LENGTH + 1] = PRIMARY_ID_STR; FlashWPTR flashPtr;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: reading CFI for word mode.\n");#endif flashPtr = (FlashWPTR)flMap(vol.socket, 0); flashPtr[0x55] = QUERY; /* look for the query identification string "QRY" */ if (queryIdStr[0] != (char)flashPtr[0x10] || queryIdStr[1] != (char)flashPtr[0x11] || queryIdStr[2] != (char)flashPtr[0x12]) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: did not recognize CFI.\n"); #endif return flUnknownMedia; } /* check the command set ID */ thisCFI->commandSetId = flashPtr[0x13] | (flashPtr[0x14] << 8); 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] | (flashPtr[0x16] << 8); /* check alternate command set ID. */ thisCFI->altCommandSetId = flashPtr[0x17] | (flashPtr[0x18] << 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] | (flashPtr[0x1a] << 8); thisCFI->vpp = flashPtr[0x1d]; vol.chipSize = 1L << flashPtr[0x27]; thisCFI->maxBytesWrite = 1L << (flashPtr[0x2a] | (flashPtr[0x2b] << 8)); vol.erasableBlockSize = (flashPtr[0x2f] | (flashPtr[0x30] << 8)) * 0x100L; /* 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] != (char)flashPtr[primaryTable] || priIdStr[1] != (char)flashPtr[primaryTable + 1] || priIdStr[2] != (char)flashPtr[primaryTable + 2]) return flUnknownMedia; thisCFI->optionalCommands = flashPtr[primaryTable + 5] | (flashPtr[primaryTable + 6] << 8) | ((long)flashPtr[primaryTable + 7] << 16) | ((long)flashPtr[primaryTable + 8] << 24); thisCFI->afterSuspend = flashPtr[primaryTable + 9]; } else { thisCFI->optionalCommands = 0; thisCFI->afterSuspend = 0; } flashPtr[0] = READ_ARRAY; return flOK;}/*----------------------------------------------------------------------*//* c f i s c s B y t e W r i t e *//* *//* Write a block of bytes to Flash in a byte-mode. *//* *//* This routine will be registered as the MTD flash.write routine *//* *//* Parameters: *//* vol : Pointer identifying drive *//* address : Card address to write to *//* buffer : Address of data to write *//* length : Number of bytes to write *//* mode : write mode (overwrite yes/no) *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus cfiscsByteWrite(FLFlash vol, CardAddress address, const void FAR1 *buffer, int length, int mode){ FLStatus status = flOK; FlashPTR flashPtr; unsigned int i, from, eachWrite; const char FAR1 *temp = (const char FAR1 *)buffer; /* Set timeout to 5 seconds from now */ unsigned long writeTimeout = flMsecCounter + 5000; if (flWriteProtected(vol.socket)) return flWriteProtect;#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) checkStatus(flNeedVpp(vol.socket));#endif if (thisCFI->maxBytesWrite > 1) /* multi-byte write supported */ eachWrite = thisCFI->maxBytesWrite * vol.interleaving; else eachWrite = vol.interleaving; for (from = 0; (int)from < length && status == flOK; from += eachWrite) { int thisLength = length - from; FlashPTR currPtr; unsigned tailBytes, lengthByte; if (thisLength > (int)eachWrite) thisLength = eachWrite; lengthByte = thisLength / vol.interleaving; tailBytes = thisLength % vol.interleaving; flashPtr = (FlashPTR) flMap(vol.socket, address + from); for (i = 0, currPtr = flashPtr; ((int)i < vol.interleaving) && ((int)i < thisLength); i++, currPtr++) { do { *currPtr = WRITE_TO_BUFFER; } while (!(*currPtr & SR_READY) && (flMsecCounter < writeTimeout)); if (!(*currPtr & SR_READY)) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: timeout error in CFISCS write.\n"); #endif status = flWriteFault; } *currPtr = i < tailBytes ? lengthByte : lengthByte - 1; } tffscpy((unsigned long FAR0 *) flashPtr,temp + from,thisLength); for (i = 0, currPtr = flashPtr; ((int)i < vol.interleaving) && ((int)i < thisLength); i++, currPtr++) *currPtr = CONFIRM_WRITE; for (i = 0, currPtr = flashPtr; ((int)i < vol.interleaving) && ((int)i < thisLength); i++, currPtr++) { while (!(*currPtr & SR_READY) && (flMsecCounter < writeTimeout)) ; if (!(*currPtr & SR_READY)) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: timeout error in CFISCS write.\n"); #endif status = flWriteFault; } if (*currPtr & WSM_ERROR) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: error in CFISCS write.\n"); #endif status = (*currPtr & SR_VPP_ERROR) ? flVppFailure : flWriteFault; *currPtr = CLEAR_STATUS; } *currPtr = READ_ARRAY; } }#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) flDontNeedVpp(vol.socket);#endif flashPtr = (FlashPTR) flMap(vol.socket, address); /* verify the data */ if (status == flOK && tffscmp((void FAR0 *) flashPtr,buffer,length)) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: CFISCS write failed in verification.\n"); #endif status = flWriteFault; } return status;}/*----------------------------------------------------------------------*//* c f i s c s W o r d W r i t e *//* *//* Write a block of bytes to Flash in a word-mode. *//* *//* This routine will be registered as the MTD flash.write routine *//* *//* Parameters: *//* vol : Pointer identifying drive *//* address : Card address to write to *//* buffer : Address of data to write *//* length : Number of bytes to write *//* mode : write mode (overwrite yes/no) *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus cfiscsWordWrite(FLFlash vol, CardAddress address, const void FAR1 *buffer, int length, int mode){ FLStatus status = flOK; FlashWPTR flashPtr; int from, eachWrite; const char FAR1 *temp = (const char FAR1 *)buffer; /* Set timeout to 5 seconds from now */ unsigned long writeTimeout = flMsecCounter + 5000; if (flWriteProtected(vol.socket)) return flWriteProtect; if ((length & 1) || (address & 1)) /* Only write words on word-boundary */ return flBadParameter;#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) checkStatus(flNeedVpp(vol.socket));#endif if (thisCFI->maxBytesWrite > 1) /* multi-byte write supported */ eachWrite = thisCFI->maxBytesWrite / 2; /* we are counting words */ else eachWrite = 1; /* we assume that the interleaving is 1. */ for (from = 0; (from < length / 2) && (status == flOK); from += eachWrite) { int thisLength = (length / 2) - from; if (thisLength > eachWrite) thisLength = eachWrite; flashPtr = (FlashWPTR)flMap(vol.socket, address + from * 2); if (thisLength == 1) { /* Work around for 28F640JS bug in write if count==1 (N==0) *flashPtr = WRITE_SINGLE ; */ *flashPtr = * ( (FlashWPTR) (temp + from * 2) ) ; } else { /* count > 1 so do a multiple write */ do { *flashPtr = WRITE_TO_BUFFER; } while (!(*flashPtr & SR_READY) && (flMsecCounter < writeTimeout)); if (!(*flashPtr & SR_READY)) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: timeout error in CFISCS write.\n"); #endif status = flWriteFault; } *flashPtr = thisLength - 1; tffscpyWords((unsigned long FAR0 *) flashPtr, temp + from * 2, thisLength * 2); *flashPtr = CONFIRM_WRITE; } while (!(*flashPtr & SR_READY) && (flMsecCounter < writeTimeout)) ; if (!(*flashPtr & SR_READY)) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: timeout error in CFISCS write.\n"); #endif status = flWriteFault; } if (*flashPtr & WSM_ERROR) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: CFISCS write error.\n"); #endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -