📄 cfiscs.c
字号:
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. */ /* FIXME: This is suboptimal. 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) | 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; }/**************************************************************************** cfiscsDWordWrite - Write routine for devices on 32 bit bus.** This routine is instrumented specifically for the large detachable flash* module on the wrSbc85xx board. It contains implementation and* configuration specific code and is not meant for generic use.** RETURNS:** ERRNO:** \NOMANUAL*/LOCAL FLStatus cfiscsDWordWrite ( FLFlash vol, /* Pointer identifying drive */ CardAddress address, /* Card address to write to */ const void FAR1 *buffer, /* Address of data to write */ int length, /* Number of bytes to write */ int mode /* write mode (overwrite yes/no) */ ) { 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; int uaoffset = 0, padding = 0; void FAR1 *newBuff = 0, *orgBuff = 0; int newLength = 0, orgLength = 0; printf ("CFISCS: writing %d bytes to flash offset 0x%x\n", length, address); /* check for unaligned address and length */ flashPtr = (FlashPTR) flMap(vol.socket, address); if ((uaoffset = ((UINT32)flashPtr & 0x3)) || (length & 0x3)) { padding = 0x3 & (4 - ((uaoffset + length) & 0x3)); newLength = uaoffset + length + padding; newBuff = (void FAR1 *) malloc(newLength+8); memset((void*)newBuff, 'A', newLength+8);#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: flashPtr mapped to %x\n", (UINT32) flashPtr); DEBUG_PRINT("Debug: uaoffset = %d, padding = %d\n", uaoffset, padding); DEBUG_PRINT("Debug: newLength = %d, newBuff = 0x%x\n", newLength, newBuff);#endif flashPtr = (FlashPTR) ((int)flashPtr & ~0x3); *(FlashDPTR)flashPtr = (UINT32) ((READ_ARRAY << 24) | (READ_ARRAY << 16) | (READ_ARRAY << 8) | READ_ARRAY); memcpy ((void*)newBuff, (void*)flashPtr, newLength); memcpy ((void*)((int)newBuff+uaoffset), (void*)buffer, length); orgBuff = (void FAR1 *)buffer; orgLength = length; temp = newBuff; buffer = newBuff; length = newLength; } 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)) *(FlashDPTR)flashPtr = (UINT32) ((WRITE_TO_BUFFER << 24) | (WRITE_TO_BUFFER << 16) | (WRITE_TO_BUFFER << 8) | WRITE_TO_BUFFER); else *(FlashDPTR)flashPtr = (UINT32) ((PROGRAM << 24) | (PROGRAM << 16) | (PROGRAM << 8) | PROGRAM); } while (!(*(FlashDPTR)flashPtr & (SR_READY<<24|SR_READY<<16|SR_READY<<8|SR_READY)) && (flMsecCounter < writeTimeout)); if (!(*(FlashDPTR)flashPtr & (SR_READY<<24|SR_READY<<16|SR_READY<<8|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)) *(FlashDPTR)flashPtr = (thisLength << 24 | thisLength << 16 | thisLength << 8 | thisLength); tffscpyLongs(flashPtr,temp + from,thisLength);#if FALSE *(FlashDPTR)flashPtr = (UINT32) ((CONFIRM_WRITE << 24) | (CONFIRM_WRITE << 16) | (CONFIRM_WRITE << 8) | CONFIRM_WRITE); *(FlashDPTR)flashPtr = (UINT32) ((CONFIRM_WRITE << 24) | (CONFIRM_WRITE << 16) | (CONFIRM_WRITE << 8) | CONFIRM_WRITE);#endif while (!((*flashPtr & SR_READY) && (*(flashPtr+1) & SR_READY) && (*(flashPtr+2) & SR_READY) && (*(flashPtr+3) & SR_READY)) && (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; *(FlashDPTR)flashPtr = (UINT32) ((CLEAR_STATUS << 24) | (CLEAR_STATUS << 16) | (CLEAR_STATUS << 8) | CLEAR_STATUS); } *(FlashDPTR)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 dword write failed in verification.\n");#endif status = flWriteFault; } if ((uaoffset != 0) || (padding != 0)) { free (newBuff); buffer = orgBuff; length = orgLength;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -