📄 s29jl064h.c
字号:
#endif return flWriteFault; } #endif return flOK;}/*----------------------------------------------------------------------*//* e r a s e F i r s t B l o c k L V 0 0 8 *//* *//* Erase the first block in LV008 chip. This block is devided into four *//* subblocks 16, 8, 8, and 32 kbytes in size. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* firstErasableBlock : Number of block to erase *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus eraseFirstBlockLV008(FLFlash vol, int firstErasableBlock){ int iSubBlock; long subBlockSize = 0; for (iSubBlock = 0; iSubBlock < 4; iSubBlock++) { int i; FlashPTR flashPtr; FLBoolean finished; switch (iSubBlock) { case 1: subBlockSize = 0x4000; break; case 2: case 3: subBlockSize = 0x2000; break; } flashPtr = (FlashPTR) vol.map(&vol, firstErasableBlock + subBlockSize * vol.interleaving, vol.interleaving); for (i = 0; i < vol.interleaving; i++) { amdCommand(&vol, i,SETUP_ERASE, flashPtr); *((FlashPTR) flAddLongToFarPointer((void FAR0 *)flashPtr, i + thisVars->unlockAddr1)) = UNLOCK_1; *((FlashPTR) flAddLongToFarPointer((void FAR0 *)flashPtr, i + thisVars->unlockAddr2)) = UNLOCK_2; flashPtr[i] = SECTOR_ERASE; } do {#ifdef BACKGROUND while (flForeground(1) == BG_SUSPEND) { /* suspend */ for (i = 0; i < vol.interleaving; i++) { flashPtr[i] = SUSPEND_ERASE; /* Wait for D6 to stop toggling */ while ((flashPtr[i] ^ flashPtr[i]) & D6) ; } }#endif finished = TRUE; for (i = 0; i < vol.interleaving; i++) { flashPtr[i] = RESUME_ERASE; if (flashPtr[i] != 0xff) { if ((flashPtr[i] & D5) && flashPtr[i] != 0xff) { flashPtr[i] = READ_ARRAY; return flWriteFault; } finished = FALSE; } } } while (!finished); } return flOK;}/*----------------------------------------------------------------------*//* a m d M T D E r a s e *//* *//* Erase one or more contiguous Flash erasable blocks *//* *//* This routine will be registered as the MTD vol.erase routine *//* *//* Parameters: *//* vol : Pointer identifying drive *//* firstErasableBlock : Number of first block to erase *//* numOfErasableBlocks: Number of blocks to erase *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus amdMTDErase(FLFlash vol, int firstErasableBlock, int numOfErasableBlocks){ int iBlock; if (flWriteProtected(vol.socket)) return flWriteProtect; for (iBlock = 0; iBlock < numOfErasableBlocks; iBlock++) { int i; FLBoolean finished; FlashPTR flashPtr; /* The first block in an LV008 chip requires special care.*/ if ((vol.type == Am29LV008_FLASH) || (vol.type == Fuj29LV008_FLASH)) if ((firstErasableBlock + iBlock) % (vol.chipSize / 0x10000l) == 0) { checkStatus(eraseFirstBlockLV008(&vol, firstErasableBlock + iBlock)); continue; } /* No need to call mapBase because we know we are on a unit boundary */ flashPtr = (FlashPTR) vol.map(&vol, (firstErasableBlock + iBlock) * vol.erasableBlockSize, vol.interleaving); for (i = 0; i < vol.interleaving; i++) { amdCommand(&vol, i,SETUP_ERASE, flashPtr); *((FlashPTR) flAddLongToFarPointer((void FAR0 *)flashPtr, i + thisVars->unlockAddr1)) = UNLOCK_1; *((FlashPTR) flAddLongToFarPointer((void FAR0 *)flashPtr, i + thisVars->unlockAddr2)) = UNLOCK_2; flashPtr[i] = SECTOR_ERASE; } do {#ifdef BACKGROUND FLBoolean eraseSuspended = FALSE; while (flForeground(1) == BG_SUSPEND) { /* suspend */ eraseSuspended = TRUE; for (i = 0; i < vol.interleaving; i++) { flashPtr[i] = SUSPEND_ERASE; /* Wait for D6 to stop toggling */ while ((flashPtr[i] ^ flashPtr[i]) & D6) ; } } if (eraseSuspended) { /* resume */ eraseSuspended = FALSE; for(i = 0; i < vol.interleaving; i++) flashPtr[i] = RESUME_ERASE; }#endif finished = TRUE; for (i = 0; i < vol.interleaving; i++) { if (flashPtr[i] != 0xff) { if ((flashPtr[i] & D5) && flashPtr[i] != 0xff) { flashPtr[i] = READ_ARRAY; #if 0 #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: erase failed in AMD MTD.\n"); #endif #endif return flWriteFault; } finished = FALSE; } } } while (!finished); } return flOK;}/*----------------------------------------------------------------------*//* a m d M T D I d e n t i f y *//* *//* Identifies AMD and Fujitsu flash media and registers as an MTD for *//* such. *//* *//* 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 identificaion, failed otherwise *//*----------------------------------------------------------------------*/FLStatus amdMTDIdentify(FLFlash vol){ int inlv; #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering AMD MTD 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)]; thisVars->unlockAddr1 = NO_UNLOCK_ADDR; /* try different interleavings */ for (inlv = 4; inlv > 0; inlv >>= 1) { if (inlv == 1) flSetWindowBusWidth(vol.socket,8); /* use 8-bits */ vol.interleaving = inlv; flIntelIdentify(&vol, amdCommand,0); if (vol.type == Am29F016_FLASH || vol.type == Fuj29F016_FLASH || vol.type == Am29F016C_FLASH || vol.type == Fuj29F016C_FLASH || vol.type == Am29F080_FLASH || vol.type == Fuj29F080_FLASH || vol.type == Am29LV080_FLASH || vol.type == Fuj29LV080_FLASH || vol.type == Am29LV008_FLASH || vol.type == Fuj29LV008_FLASH || vol.type == Am29F040_FLASH || vol.type == Fuj29F040_FLASH || vol.type == Am29LV017_FLASH || vol.type == Fuj29LV017_FLASH) break; } if (vol.type == Am29F016_FLASH || vol.type == Fuj29F016_FLASH || vol.type == Am29F016C_FLASH || vol.type == Fuj29F016C_FLASH || vol.type == Am29LV017_FLASH || vol.type == Fuj29LV017_FLASH) vol.chipSize = 0x200000l; else if (vol.type == Fuj29F080_FLASH || vol.type == Am29F080_FLASH || vol.type == Fuj29LV080_FLASH || vol.type == Am29LV080_FLASH || vol.type == Fuj29LV008_FLASH || vol.type == Am29LV008_FLASH) vol.chipSize = 0x100000l; else if (vol.type == Fuj29F040_FLASH || vol.type == Am29F040_FLASH) vol.chipSize = 0x80000l; else { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: did not identify AMD or Fujitsu flash media.\n"); #endif return flUnknownMedia; } if ((vol.type == Am29F016C_FLASH) || (vol.type == Fuj29F016C_FLASH)) { thisVars->unlockAddr1 = thisVars->unlockAddr2 = 0L; thisVars->baseMask = 0xfffff800L * vol.interleaving; } else if ((vol.type == Am29F040_FLASH) || (vol.type == Fuj29F040_FLASH)){ flSetWindowSize(vol.socket,8 * vol.interleaving); thisVars->unlockAddr1 = 0x5555u * vol.interleaving; thisVars->unlockAddr2 = 0x2aaau * vol.interleaving; thisVars->baseMask = 0xffff8000L * vol.interleaving; } else { thisVars->unlockAddr1 = 0x555 * vol.interleaving; thisVars->unlockAddr2 = 0x2aa * vol.interleaving; thisVars->baseMask = 0xfffff800L * vol.interleaving; } checkStatus(flIntelSize(&vol,amdCommand,0)); vol.erasableBlockSize = 0x10000l * vol.interleaving; vol.flags |= SUSPEND_FOR_WRITE; /* Register our flash handlers */ vol.write = amdMTDWrite; vol.erase = amdMTDErase; #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: Identified AMD or Fujitsu flash media.\n");#endif return flOK;}#if FALSE/*----------------------------------------------------------------------*//* f l R e g i s t e r A M D M T D *//* *//* Registers this MTD for use *//* *//* Parameters: *//* None *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failure *//*----------------------------------------------------------------------*/FLStatus flRegisterAMDMTD(void){ if (noOfMTDs >= MTDS) return flTooManyComponents; mtdTable[noOfMTDs++] = amdMTDIdentify; return flOK;}#endif /* FALSE *//*----------------------------------------------------------------------*//* amd29lv160dMTDIdentify *//* *//* Identifies AMD and Fujitsu flash media and registers as an MTD for *//* such. *//* *//* 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 identificaion, failed otherwise *//*----------------------------------------------------------------------*/FLStatus amd29lv160dMTDIdentify(FLFlash vol){ #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: entering AMD MTD identification routine.\n"); #endif flSetWindowBusWidth(vol.socket,16);/* use 16-bits */ flSetWindowSpeed(vol.socket,120); /* 120 nsec. */ flSetWindowSize(vol.socket, (FLASH_TFFS_SIZE) >> 12); /* 8 KBytes */ vol.interleaving = 1; vol.type = Am29LV160D_FLASH; vol.chipSize = (FLASH_TFFS_SIZE); vol.erasableBlockSize = 0x10000; vol.flags |= SUSPEND_FOR_WRITE; vol.noOfChips = 1; /* Register our flash handlers */ vol.write = am29lv160dMTDWrite; vol.erase = am29lv160dMTDErase; vol.map = am29lv160dMap; #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: Leaving AMD MTD identification routine.\n"); #endif return flOK;}/*----------------------------------------------------------------------*//* am29lv160dMap *//* *//* Maps the window to a specified card address and returns a pointer to *//* that location (some offset within the window). *//* *//* NOTE: Addresses over 128M are attribute memory. On PCMCIA adapters, *//* subtract 128M from the address and map to attribute memory. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* address : Byte-address on card. NOT necessarily on a *//* full-window boundary. *//* If above 128MB, address is in attribute space.*//* *//* Returns: *//* Pointer to a location within the window mapping the address. *//*----------------------------------------------------------------------*/void FAR0 *am29lv160dMap(FLFlash vol, CardAddress address, int length){ UINT32 mapaddr; mapaddr = FLASH_TFFS_BASE + address; return (void FAR0 *)mapaddr;}/*----------------------------------------------------------------------*//* a m d M T D W r i t e *//* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -