📄 cfiscs.c
字号:
/* * $Log: V:/cfiscs.c_v $ * * Rev 1.20 11 Nov 1997 15:26:00 ANDRY * get rid of compiler warnings * * Rev 1.19 06 Oct 1997 9:53:30 danig * VPP functions under #ifdef * * Rev 1.18 18 Sep 1997 10:05:40 danig * Warnings * * Rev 1.17 10 Sep 1997 16:31:16 danig * Got rid of generic names * * Rev 1.16 04 Sep 1997 18:19:34 danig * Debug messages * * Rev 1.15 31 Aug 1997 14:50:52 danig * Registration routine return status * * Rev 1.14 27 Jul 1997 15:00:38 danig * FAR -> FAR0 * * Rev 1.13 21 Jul 1997 19:58:24 danig * No watchDogTimer * * Rev 1.12 15 Jul 1997 19:18:32 danig * Ver 2.0 * * Rev 1.11 09 Jul 1997 10:58:52 danig * Fixed byte erase bug & changed identification routines * * Rev 1.10 20 May 1997 14:48:02 danig * Changed overwrite to mode in write routines * * Rev 1.9 18 May 1997 13:54:58 danig * JEDEC ID independent * * Rev 1.8 13 May 1997 16:43:10 danig * Added getMultiplier. * * Rev 1.7 08 May 1997 19:56:12 danig * Added cfiscsByteSize * * Rev 1.6 04 May 1997 14:01:16 danig * Changed cfiscsByteErase and added multiplier * * Rev 1.4 15 Apr 1997 11:38:52 danig * Changed word identification and IDs. * * Rev 1.3 15 Jan 1997 18:21:40 danig * Bigger ID string buffers and removed unused definitions. * * Rev 1.2 08 Jan 1997 14:54:06 danig * Changes in specification * * Rev 1.1 25 Dec 1996 18:21:44 danig * Initial revision *//************************************************************************//* *//* FAT-FTL Lite Software Development Kit *//* Copyright (C) M-Systems Ltd. 1995-1997 *//* *//************************************************************************//*----------------------------------------------------------------------*//* This MTD supports the SCS/CFI technology. *//*----------------------------------------------------------------------*/#include "flflash.h"#include "backgrnd.h"/* JEDEC-IDs */#define VOYAGER_ID 0x8915#define KING_COBRA_ID 0xb0d0/* command set IDs */#define INTEL_COMMAND_SET 0x0001#define AMDFUJ_COMMAND_SET 0x0002#define INTEL_ALT_COMMAND_SET 0x0001#define AMDFUJ_ALT_COMMAND_SET 0x0004#define ALT_NOT_SUPPORTED 0x0000/* CFI identification strings */#define ID_STR_LENGTH 3#define QUERY_ID_STR "QRY"#define PRIMARY_ID_STR "PRI"#define ALTERNATE_ID_STR "ALT"/* commands */#define CONFIRM_SET_LOCK_BIT 0x01#define SETUP_BLOCK_ERASE 0x20#define SETUP_QUEUE_ERASE 0x28#define SETUP_CHIP_ERASE 0x30#define CLEAR_STATUS 0x50#define SET_LOCK_BIT 0x60#define CLEAR_LOCK_BIT 0x60#define READ_STATUS 0x70#define READ_ID 0x90#define QUERY 0x98#define SUSPEND_WRITE 0xb0#define SUSPEND_ERASE 0xb0#define CONFIG 0xb8#define CONFIRM_WRITE 0xd0#define RESUME_WRITE 0xd0#define CONFIRM_ERASE 0xd0#define RESUME_ERASE 0xd0#define CONFIRM_CLEAR_LOCK_BIT 0xd0#define WRITE_TO_BUFFER 0xe8#define READ_ARRAY 0xff/* status register bits */#define WSM_ERROR 0x3a#define SR_BLOCK_LOCK 0x02#define SR_WRITE_SUSPEND 0x04#define SR_VPP_ERROR 0x08#define SR_WRITE_ERROR 0x10#define SR_LOCK_SET_ERROR 0x10#define SR_ERASE_ERROR 0x20#define SR_LOCK_RESET_ERROR 0x20#define SR_ERASE_SUSPEND 0x40#define SR_READY 0x80/* optional commands support */#define CHIP_ERASE_SUPPORT 0x0001#define SUSPEND_ERASE_SUPPORT 0x0002#define SUSPEND_WRITE_SUPPORT 0x0004#define LOCK_SUPPORT 0x0008#define QUEUED_ERASE_SUPPORT 0x0010/* supported functions after suspend */#define WRITE_AFTER_SUSPEND_SUPPORT 0x0001/* a structure that hold important CFI data. */typedef struct { unsigned commandSetId; /* id of a specific command set. */ unsigned altCommandSetId; /* id of alternate command set. */ FLBoolean wordMode; /* TRUE - word mode. */ /* FALSE - byte mode. */ int multiplier; /* the number of times each byte */ /* of data appears in READ_ID */ /* and QUERY commands. */ unsigned maxBytesWrite; /* maximum number of bytes */ /* in multi-byte write. */ FLBoolean vpp; /* if = TRUE, need vpp. */ long optionalCommands; /* optional commands supported */ /* (1 = yes, 0 = no): */ /* bit 0 - chip erase. */ /* bit 1 - suspend erase. */ /* bit 2 - suspend write */ /* bit 3 - lock/unlock. */ /* bit 4 - queued erase. */ unsigned afterSuspend; /* functions supported after */ /* suspend (1 = yes, 0 = no): */ /* bit 0 - write after erase */ /* suspend. */} CFI;static CFI mtdVars[DRIVES];#define thisCFI ((CFI *)vol.mtdVars)/*----------------------------------------------------------------------*//* c f i s c s B y t e S i z e *//* *//* Identify the card size for byte mode. *//* Sets the value of flash.noOfChips. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* amdCmdRoutine : Routine to read-id AMD/Fujitsu style at *//* a specific location. If null, Intel procedure *//* is used. *//* idOffset : Chip offset to use for identification *//* *//* Returns: *//* FLStatus : 0 = OK, otherwise failed (invalid Flash array)*//*----------------------------------------------------------------------*/static FLStatus cfiscsByteSize(FLFlash vol){ char queryIdStr[ID_STR_LENGTH + 1] = QUERY_ID_STR; FlashPTR flashPtr = (FlashPTR) flMap(vol.socket, 0); flashPtr[0x55 * vol.interleaving] = QUERY; /* We leave the first chip in QUERY mode, so that we can */ /* discover an address wraparound. */ for (vol.noOfChips = 0; /* Scan the chips */ vol.noOfChips < 2000; /* Big enough ? */ vol.noOfChips += vol.interleaving) { int i; flashPtr = (FlashPTR) flMap(vol.socket, vol.noOfChips * vol.chipSize); /* Check for address wraparound to the first chip */ if (vol.noOfChips > 0 && (queryIdStr[0] == flashPtr[0x10 * vol.interleaving * thisCFI->multiplier] && queryIdStr[1] == flashPtr[0x11 * vol.interleaving * thisCFI->multiplier] && queryIdStr[2] == flashPtr[0x12 * vol.interleaving * thisCFI->multiplier])) goto noMoreChips; /* wraparound */ /* Check if chip displays the "QRY" ID string */ for (i = (vol.noOfChips ? 0 : 1); i < vol.interleaving; i++) { flashPtr[i * 0x55] = QUERY; if (queryIdStr[0] != flashPtr[0x10 * vol.interleaving * thisCFI->multiplier] || queryIdStr[1] != flashPtr[0x11 * vol.interleaving * thisCFI->multiplier] || queryIdStr[2] != flashPtr[0x12 * vol.interleaving * thisCFI->multiplier]) goto noMoreChips; /* This "chip" doesn't respond correctly, so we're done */ flashPtr[i] = READ_ARRAY; } }noMoreChips: flashPtr = (FlashPTR) flMap(vol.socket, 0); flashPtr[0] = READ_ARRAY; /* reset the original chip */ return (vol.noOfChips == 0) ? flUnknownMedia : flOK;}/*----------------------------------------------------------------------*//* c f i s c s B y t e I d e n t i f y *//* *//* Identify the Flash type for cards in byte mode. *//* Sets the value of flash.type (JEDEC id) & flash.interleaving. *//* Calculate the number of times each byte of data appears in READ_ID *//* and QUERY commands. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* *//* Returns: *//* FLStatus : 0 = OK, otherwise failed (invalid Flash array)*//*----------------------------------------------------------------------*/static FLStatus cfiscsByteIdentify(FLFlash vol){ int inlv, mul; FlashPTR flashPtr = (FlashPTR) flMap(vol.socket, 0); for (inlv = 1; inlv <= 8; inlv++) /* let us assume that interleaving is 8 */ flashPtr[inlv] = READ_ARRAY; /* and reset all the interleaved chips */ for (inlv = 1; inlv <= 8; inlv++) { for (mul = 1; mul <= 8; mul++) { /* try all possibilities */ int letter; flashPtr[0x55 * inlv] = QUERY; for (letter = 0; letter < ID_STR_LENGTH; letter++) { /* look for "QRY" id string */ char idChar = '?'; int offset, counter; switch (letter) { case 0: idChar = 'Q'; break; case 1: idChar = 'R'; break; case 2: idChar = 'Y'; break; } for (counter = 0, offset = (0x10 + letter) * inlv * mul; counter < mul; counter++, offset += inlv) /* each character should appear mul times */ if (flashPtr[offset] != idChar) break; if (counter < mul) /* no match */ break; } flashPtr[0x55 * inlv] = READ_ARRAY; /* reset the chip */ if (letter >= ID_STR_LENGTH) goto checkInlv; } }checkInlv: if (inlv > 8) /* too much */ return flUnknownMedia; if (inlv & (inlv - 1)) return flUnknownMedia; /* not a power of 2, no way ! */ vol.interleaving = inlv; thisCFI->multiplier = mul; flashPtr[0x55 * inlv] = QUERY; vol.type = (FlashType) ((flashPtr[0] << 8) | flashPtr[inlv * thisCFI->multiplier]); flashPtr[inlv] = READ_ARRAY; return flOK;}/*----------------------------------------------------------------------*//* c f i s c s W o r d S i z e *//* *//* Identify the card size for a word-mode Flash array. *//* Sets the value of flash.noOfChips. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* *//* Returns: *//* FLStatus : 0 = OK, otherwise failed (invalid Flash array)*//*----------------------------------------------------------------------*/static FLStatus cfiscsWordSize(FLFlash vol){ char queryIdStr[ID_STR_LENGTH + 1] = QUERY_ID_STR; FlashWPTR flashPtr = (FlashWPTR) flMap(vol.socket, 0); flashPtr[0] = CLEAR_STATUS; flashPtr[0x55] = QUERY; /* We leave the first chip in QUERY mode, so that we can */ /* discover an address wraparound. */ for (vol.noOfChips = 1; /* Scan the chips */ vol.noOfChips < 2000; /* Big enough ? */ vol.noOfChips++) { flashPtr = (FlashWPTR) flMap(vol.socket, vol.noOfChips * vol.chipSize); if ((flashPtr[0x10] == (unsigned short)queryIdStr[0]) && (flashPtr[0x11] == (unsigned short)queryIdStr[1]) && (flashPtr[0x12] == (unsigned short)queryIdStr[2])) break; /* We've wrapped around to the first chip ! */ flashPtr[0x55] = QUERY; if ((flashPtr[0x10] != (unsigned short)queryIdStr[0]) || (flashPtr[0x11] != (unsigned short)queryIdStr[1]) || (flashPtr[0x12] != (unsigned short)queryIdStr[2])) break; flashPtr[0] = CLEAR_STATUS; flashPtr[0] = READ_ARRAY; } flashPtr = (FlashWPTR) flMap(vol.socket, 0); flashPtr[0] = READ_ARRAY; return flOK;}/*----------------------------------------------------------------------*//* g e t B y t e C F I *//* *//* Load important CFI data to the CFI structure in a byte-mode. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* *//* Returns: *//* FLStatus : 0 = OK, otherwise failed. *//*----------------------------------------------------------------------*/static FLStatus getByteCFI(FLFlash vol){ unsigned primaryTable, secondaryTable; char queryIdStr[ID_STR_LENGTH + 1] = QUERY_ID_STR; char priIdStr[ID_STR_LENGTH + 1] = PRIMARY_ID_STR; FlashPTR flashPtr;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: reading CFI for byte mode.\n");#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -