📄 cfiscs.c
字号:
return flOK; }/******************************************************************************* cfiscsByteWrite - byte write routine** This routine is intended to be registered as the write routine in systems* that have byte wide devices interleaved or devices that are in byte mode.** RETURNS:** ERRNO*/LOCAL 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;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering CFISCS byte 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 = 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; }/****************************************************************************** cfiscsWordWrite - write routine for 16 bit devices * * 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 ** ERRNO*/LOCAL FLStatus cfiscsWordWrite ( FLFlash vol, CardAddress address, const void FAR1 *buffer, int length, int mode ) { FLStatus status = flOK; FlashWPTR flashPtr; int from, eachWrite,test; const char FAR1 *temp = (const char FAR1 *)buffer; /* Set timeout to 5 seconds from now */ unsigned long writeTimeout = flMsecCounter + 5000;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering CFISCS Word Write routine.\n");#endif 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; test=0; /* 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) { *flashPtr = (PROGRAM << 8) | PROGRAM; *flashPtr = (* ( (FlashWPTR) (temp + from * 2) )) ; } 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 status = (*flashPtr & SR_VPP_ERROR) ? flVppFailure : flWriteFault; *flashPtr = CLEAR_STATUS; } *flashPtr = (READ_ARRAY<<8)|READ_ARRAY; WRS_ASM("eieio"); if (*flashPtr != (* ( (FlashWPTR) (temp + from * 2) ))) { from-=eachWrite; test++; } if (test>100) { from+=eachWrite; test=0; } }#ifdef SOCKET_12_VOLTS if (thisCFI->vpp) flDontNeedVpp(vol.socket);#endif flashPtr = (FlashWPTR) 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; }#if 0/******************************************************************************* cfiscsInterleavedWordWrite - write routine 16 bit interleaved devices* * 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 ** ERRNO*/LOCAL FLStatus cfiscsInterleavedWordWrite ( FLFlash vol, CardAddress address, const void FAR1 *buffer, int length, int mode ) { FLStatus status = flOK; FlashWPTR flashPtr; unsigned long maxWordsPerWrite, /* Number of words per WRITE/WRITE_BUFFER command. */ wordsWritten, /* total written so far */ wordsRemaining, /* number of words left to go */ wordsThisWrite; /* number of words */ #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering CFISCS Interleaved Word Write routine.\n");#endif if (flWriteProtected(vol.socket)) return flWriteProtect; if ((length & 1) || (address & 1)) /* Only write whole words, only 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? */ maxWordsPerWrite = thisCFI->maxBytesWrite; else maxWordsPerWrite = 1; /* Part can only handle single-byte writes. */ flashPtr = (FlashWPTR)flMap(vol.socket, address); /* Now program the part: */ if (maxWordsPerWrite > 1) /* Part can handle writes of multiple words to buffer */ { wordsWritten = 0; wordsRemaining = length / 2; /* Number of words left to program into a part, convert bytes to words. */ while (wordsRemaining > 0) { /* Figure out how many words we need to write. This will either * be the max allowed (maxWordsPerWrite), or what's left over at * the end (wordsRemaining). Make it extra-cryptic with the * ?: operator. */ wordsThisWrite = (wordsRemaining > maxWordsPerWrite) ? maxWordsPerWrite : wordsRemaining; /* if we don't have enough aligned data to use a buffered write * we just use a normal write */ if ( (wordsThisWrite <2 ) && (wordsThisWrite > 0)) { /* data is a 1's mask, so we only try overwriting the * bytes we desire ie. written a 1 should not change * the state of an erase bit */ int byteCount; ULONG data = 0xffffffff; /* clear out the bytes we are going to overwrite */ for (byteCount = 0; byteCount<length; byteCount++) data &= ~(0xff << (byteCount*8)); /* set the bits we don't want to clear in our data */ data |= CFI_LONGSWAP(* (ULONG *) buffer); CFI_LONG_WRITE(flashPtr, (ULONG) (PROGRAM<<16) |PROGRAM); CFI_LONG_WRITE(flashPtr, (ULONG) data); /* 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)) ); CFI_LONG_WRITE(flashPtr, (ULONG) (READ_ARRAY<<16) |READ_ARRAY); #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: mtd: Using NON-buffered write to program %ld words at addr 0x%lx\n", wordsThisWrite, (ULONG) flashPtr);#endif } else { CFI_LONG_WRITE(flashPtr, (ULONG) ((CLEAR_STATUS<<16) |CLEAR_STATUS)); CFI_LONG_WRITE(flashPtr, (ULONG) (WRITE_TO_BUFFER<<16) |WRITE_TO_BUFFER); /* both parts */ /* At this point, we must wait for XSR to indicate a buffer is * available. We will spin on this, but only for a maximum of 5 * seconds. We do the timing by taking advantage of the * ever-incrementing flMsecCounter. */ while ((!(CFI_WORD_READ((FlashWPTR)(flashPtr)) & SR_READY)) || (!(CFI_WORD_READ((FlashWPTR)(flashPtr + 1)) & SR_READY))) ; /* Check to see if either part timed out: */ if ( (!(CFI_WORD_READ(&flashPtr[0x0]) & SR_READY)) || (!(CFI_WORD_READ((&flashPtr[0x1])) & SR_READY)) ) { /* Send read-array command to both parts, abort. */ CFI_LONG_WRITE(flashPtr, (ULONG) (READ_ARRAY<<16) |READ_ARRAY); return(flWriteFault); } /* Now we must write the count value (zero-based, so 0 => 1 word, * 1 => 2 words, etc.) for the number of words we intend to * write. Note that this code always assumes an even number of * words > 0. Half the words go in the even part, half go in the * odd part. */ CFI_LONG_WRITE(flashPtr, (ULONG)(((wordsThisWrite / 2) - 1) <<16) | ((wordsThisWrite / 2) - 1)); /* both parts */ /* Finally, write the data. This is easy, because now the * flash parts are seen as memory addresses. */ /* This is not optimal. It is only writing half the * maximum words that could be written to each part in buffered * write mode. If we double the assignments for wordsWritten & * wordsThisWrite, and halve the assignment for wordsRemaining * each iteration, we can probably make this work optimally. * Then we should probably rename some of the variables to * "longsxxx". */ /* last argument is expected in bytes */ tffscpyLongs(&((long *)flashPtr)[wordsWritten/2], &((long *)buffer)[wordsWritten/2], wordsThisWrite*2); /* Now send CONFIRM_WRITE command. */ CFI_LONG_WRITE(flashPtr, (ULONG) (CONFIRM_WRITE<<16)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -