📄 cfiscs.c
字号:
| CONFIRM_WRITE); /* both parts */ /* Flow diagram says to check that status register says * everything is copacetic. */ while ( (!(CFI_WORD_READ(flashPtr) & SR_READY)) || (!(CFI_WORD_READ((flashPtr + 1)) & SR_READY)) ); /* Check to see if either part timed out: */ if ( (!(CFI_WORD_READ(flashPtr) & SR_READY)) || (!(CFI_WORD_READ((flashPtr + 1)) & SR_READY)) ) { /* Send read-array command to both parts, abort. */ CFI_LONG_WRITE(flashPtr, (ULONG)(READ_ARRAY<<16) | READ_ARRAY); return(flWriteFault); } else { CFI_LONG_WRITE(flashPtr, (ULONG)(READ_ARRAY<<16) | READ_ARRAY); } /* Now verify the write. */ if (tffscmpWords(&((long *)flashPtr)[wordsWritten/2], &((long *)buffer)[wordsWritten/2], wordsThisWrite*2)) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: mtd: Buffer write verification failed (interleaved word mode)\n");#endif return flWriteFault; } else {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: mtd: Buffer write verification passed (interleaved word mode) at addr 0x%lx\n", (ULONG) flashPtr);#endif } } wordsRemaining -= wordsThisWrite; /* That many fewer words * to go. */ wordsWritten += wordsThisWrite; /* That many more done. */ } } else /* Part cannot handle writes to buffer, must write one byte at a time. */ { } /* Put both devices back into read mode: */ CFI_LONG_WRITE(flashPtr, (ULONG) (READ_ARRAY<<16) | READ_ARRAY); return status; }#endif /* 0 *//**************************************************************************** cfiscsDWordWrite - Write routine for devices on 32 bit bus.** This code has not been tested since we have not had 32 bit devices we have* had to support. It is provided for consistency in the hope that it will* reduce the effort needed by the folks who have to support such devices. To* avoid endian-ness issues commands are written to all four bytes of the* double word. ** RETURNS:** ERRNO*/LOCAL FLStatus cfiscsDWordWrite ( FLFlash vol, CardAddress address, const void FAR1 *buffer, int length, int mode ) { FLStatus status = flOK; FlashPTR flashPtr; unsigned int from, eachWrite; const char FAR1 *temp = (const char FAR1 *)buffer; /* Set timeout to 5 seconds from now */ unsigned long writeTimeout = flMsecCounter + 5000; /* Check if address and length are double word aligned */ if ((address & 0x3) || (length & 0x3)) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: Unaligned data - addr 0x%x - len 0x%x\n",(UINT32) address, length);#endif return flBadParameter; }#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering CFISCS DWord write routine.\n");#endif 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 = 4; /* Max bus width */ for (from = 0; (int)from < length && status == flOK; from += eachWrite) { int thisLength = length - from; if (thisLength > (int)eachWrite) thisLength = eachWrite; flashPtr = (FlashPTR) flMap(vol.socket, address + from); do { if ((thisCFI->maxBytesWrite > 1) && ((thisCFI->maxBytesWrite & 0x3) == 0)) *(UINT32 *)flashPtr = (UINT32) ((WRITE_TO_BUFFER << 24) | (WRITE_TO_BUFFER << 16) | (WRITE_TO_BUFFER << 8) | WRITE_TO_BUFFER); else *(UINT32 *)flashPtr = (UINT32) ((PROGRAM_WORD << 24) | (PROGRAM_WORD << 16) | (PROGRAM_WORD << 8) | PROGRAM_WORD); } 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 we are using the WRITE_TO_BUFFER command then we must program * the buffer length */ if ((thisCFI->maxBytesWrite > 1) && ((thisCFI->maxBytesWrite & 0x3) == 0)) *flashPtr = (thisLength << 24 | thisLength << 16 | thisLength << 8 | thisLength); tffscpyLongs(flashPtr,temp + from,thisLength); *(UINT32 *)flashPtr = (UINT32) ((CONFIRM_WRITE << 24) | (CONFIRM_WRITE << 16) | (CONFIRM_WRITE << 8) | CONFIRM_WRITE); *(UINT32 *)flashPtr = (UINT32) ((CONFIRM_WRITE << 24) | (CONFIRM_WRITE << 16) | (CONFIRM_WRITE << 8) | CONFIRM_WRITE); while (!(*(FlashDPTR) flashPtr & (SR_READY << 24)) && (flMsecCounter < writeTimeout)) ; if (!(flMsecCounter < writeTimeout)) {#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: error in CFISCS write.\n");#endif status = (*flashPtr & SR_VPP_ERROR) ? flVppFailure : flWriteFault; *(UINT32 *)flashPtr = (UINT32) ((CLEAR_STATUS << 24) | (CLEAR_STATUS << 16) | (CLEAR_STATUS << 8) | CLEAR_STATUS); } *(UINT32 *)flashPtr = (UINT32) ((READ_ARRAY << 24) | (READ_ARRAY << 16) | (READ_ARRAY << 8) | 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 && tffscmpWords((void FAR0 *) flashPtr, (void FAR1 *) buffer,length)) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: CFISCS write failed in verification.\n");#endif status = flWriteFault; } return status; }#ifdef INTERLEAVED_MODE_REQUIRES_32BIT_WRITES/**************************************************************************** cfiscsInterleavedWordErase - Erase specified number of blocks** Given the first block and number of contiguous blocks to erase, this * routine will erase the content of the specified region. The routine does* not support features like "Suspend Erase" or "Queued Erase" so the device* stays busy until all specified blocks have been erased. These features need* to be supported by the TrueFFS core to be applicable here.** RETURNS:** ERRNO*/LOCAL FLStatus cfiscsInterleavedWordErase ( FLFlash vol, int firstEraseBlock, int numberOfEraseBlocks ) { FLStatus status = flOK; /* unless proven otherwise */ int iBlock;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering CFISCS Interleaved Word Erase routine.\n");#endif if (flWriteProtected(vol.socket)) return flWriteProtect;#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) checkStatus(flNeedVpp(vol.socket));#endif for (iBlock = firstEraseBlock; iBlock < firstEraseBlock + numberOfEraseBlocks && status == flOK; iBlock++) { FLBoolean finished; FlashWPTR flashPtr = (FlashWPTR) flMap(vol.socket, iBlock * vol.erasableBlockSize); CFI_LONG_WRITE(flashPtr, (ULONG) (SETUP_BLOCK_ERASE <<16)|SETUP_BLOCK_ERASE); CFI_LONG_WRITE(flashPtr, (ULONG) (CONFIRM_ERASE <<16)|CONFIRM_ERASE); /* while (flashPtr[ix * thisCFI->interleaveFactor] != 0x80); */ do { finished = FALSE; if ((flashPtr[0] == SR_READY) && (flashPtr[1] == SR_READY)) { finished = TRUE; if (CFI_WORD_READ(flashPtr) & WSM_ERROR) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: CFISCS erase error on device one\n");#endif status = (CFI_WORD_READ(flashPtr) & SR_VPP_ERROR) ? flVppFailure : flWriteFault; CFI_LONG_WRITE(flashPtr, (ULONG) CLEAR_STATUS); } else if (CFI_WORD_READ(&flashPtr[1]) & WSM_ERROR) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: CFISCS erase error on device two\n");#endif status = ((CFI_WORD_READ(&flashPtr[1])) & (SR_VPP_ERROR)) ? flVppFailure : flWriteFault; CFI_LONG_WRITE(flashPtr, (ULONG) (CLEAR_STATUS <<16) & 0xffff0000); } CFI_LONG_WRITE(flashPtr, (ULONG) (READ_ARRAY <<16)|READ_ARRAY); } } while (!finished); }#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) flDontNeedVpp(vol.socket);#endif return status; }#else /* !INTERLEAVED_MODE_REQUIRES_32BIT_WRITES */#if 0/**************************************************************************** cfiscsErase - Erase specified number of blocks** Given the first block and number of contiguous blocks to erase, this * routine will erase the content of the specified region. The routine does* not support features like "Suspend Erase" or "Queued Erase" so the device* stays busy until all specified blocks have been erased. These features need* to be supported by the TrueFFS core to be applicable here.** Each interleaved device is erased independently. The core does not* compensate for interleaving and expects interleaving to be handled here.** RETURNS:** ERRNO*/LOCAL FLStatus cfiscsErase ( FLFlash vol, int firstEraseBlock, int numberOfEraseBlocks ) { FLStatus status = flOK; /* unless proven otherwise */ int iBlock;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering CFISCS Erase routine.\n");#endif if (flWriteProtected(vol.socket)) return flWriteProtect;#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) checkStatus(flNeedVpp(vol.socket));#endif for (iBlock = firstEraseBlock; iBlock < firstEraseBlock + numberOfEraseBlocks && status == flOK; iBlock++) { int ix; FLBoolean finished; FlashPTR flashPtr = (FlashPTR) flMap(vol.socket, iBlock * vol.erasableBlockSize); for(ix=0; ix < vol.interleaving; ix++) { flashPtr[ix * thisCFI->interleaveFactor] = SETUP_BLOCK_ERASE; flashPtr[ix * thisCFI->interleaveFactor] = CONFIRM_ERASE; flashPtr[ix * thisCFI->interleaveFactor] = CONFIRM_ERASE; while (flashPtr[ix * thisCFI->interleaveFactor] != 0x80); do { finished = TRUE; if (!(flashPtr[ix * thisCFI->interleaveFactor] & SR_READY)) finished = FALSE; else { if (flashPtr[ix * thisCFI->interleaveFactor] & WSM_ERROR) {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: CFISCS erase error on device %d.\n", ix);#endif status = (flashPtr[ix * thisCFI->interleaveFactor] & SR_VPP_ERROR) ? flVppFailure : flWriteFault; flashPtr[ix * thisCFI->interleaveFactor] = CLEAR_STATUS; } flashPtr[ix * thisCFI->interleaveFactor] = READ_ARRAY; } } while (!finished); } }#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) flDontNeedVpp(vol.socket);#endif return status; }#endif /* 0 */LOCAL FLStatus cfiscsWordErase ( FLFlash vol, int firstEraseBlock, int numberOfEraseBlocks ) { FLStatus status = flOK; /* unless proven otherwise */ int iBlock;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering CFISCS Erase routine. 0x%x 0x%x\n",vol.socket,flMap(vol.socket,0));#endif if (flWriteProtected(vol.socket)) return flWriteProtect;#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) checkStatus(flNeedVpp(vol.socket));#endif for (iBlock = firstEraseBlock; iBlock < firstEraseBlock + numberOfEraseBlocks && status == flOK; iBlock++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -