diff options
author | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
---|---|---|
committer | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
commit | 709c4d66e0b107ca606941b988bad717c0b45d9b (patch) | |
tree | 37ee08b1eb308f3b2b6426d5793545c38396b838 /packages/linux/linux-titan-sh4 | |
parent | fa6cd5a3b993f16c27de4ff82b42684516d433ba (diff) |
rename packages/ to recipes/ per earlier agreement
See links below for more details:
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816
Signed-off-by: Denys Dmytriyenko <denis@denix.org>
Acked-by: Mike Westerhof <mwester@dls.net>
Acked-by: Philip Balister <philip@balister.org>
Acked-by: Khem Raj <raj.khem@gmail.com>
Acked-by: Marcin Juszkiewicz <hrw@openembedded.org>
Acked-by: Koen Kooi <koen@openembedded.org>
Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'packages/linux/linux-titan-sh4')
-rw-r--r-- | packages/linux/linux-titan-sh4/titan-flash.patch | 3153 | ||||
-rw-r--r-- | packages/linux/linux-titan-sh4/titan-pcibios-scan-update.patch | 22 |
2 files changed, 0 insertions, 3175 deletions
diff --git a/packages/linux/linux-titan-sh4/titan-flash.patch b/packages/linux/linux-titan-sh4/titan-flash.patch deleted file mode 100644 index c84adcdb8c..0000000000 --- a/packages/linux/linux-titan-sh4/titan-flash.patch +++ /dev/null @@ -1,3153 +0,0 @@ -Add the driver for onboard flash. -The quality of this driver means that it has not been included in the -upstream kernel sources. -This implements a block device translation layer to match what the -onboard firmware implements. - -diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig -index 58c1deb..9668ac7 100644 ---- a/drivers/block/Kconfig -+++ b/drivers/block/Kconfig -@@ -186,6 +186,13 @@ config BLK_DEV_DAC960 - To compile this driver as a module, choose M here: the - module will be called DAC960. - -+config BLK_SSFDC -+ tristate "SmartMedia(TM) Driver (sm)" -+ depends on SH_TITAN -+ help -+ Say Y here if you want the SmartMedia chip enabled. -+ Otherwise say N. -+ - config BLK_DEV_UMEM - tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL -diff --git a/drivers/block/Makefile b/drivers/block/Makefile -index dd88e33..37fc9e8 100644 ---- a/drivers/block/Makefile -+++ b/drivers/block/Makefile -@@ -19,6 +19,7 @@ obj-$(CONFIG_BLK_DEV_XD) += xd.o - obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o - obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o - obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o -+obj-$(CONFIG_BLK_SSFDC) += ssfdc.o - obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o - - obj-$(CONFIG_BLK_DEV_UMEM) += umem.o -diff --git a/drivers/block/ssfdc.c b/drivers/block/ssfdc.c -new file mode 100644 -index 0000000..482d617 ---- /dev/null -+++ b/drivers/block/ssfdc.c -@@ -0,0 +1,2733 @@ -+/* $id: $ -+ssfdc.c - Solid State Flopyy Disk Card -+ -+Original source curtesy of Toshiba Corporation. -+ -+Modification for use by Linux provided by Nimble Microsystems Inc. -+ -+TODO: -+ -+Modification History: -+ -+ March 2001 - Initial port of Toshiba sources by Bill Mann -+ May 2001 - Debug of staticly linked ssfdc driver, Bill Mann -+ Nov 2001 - Reimplementation using tasklets and timers. -+ May 2002 - Partition support added. -+ Oct 2003 - Port to kernel 2.6.0 -+ Mar 2004 - Stabilization refinements... -+ -+Overview: The kernel interfaces to the device via the "block_device_operations -+ ssfdc_fops", the device's request handling function -+ "do_ssfdc_request(request_queue_t * q)", or by the ioctl interface ssfdc_ioctl(). -+ -+ do_ssfdc_request() purpose is to kickstart ssfdc_thread via a wake_up call. ssfdc_thread -+ then processes requests from the queue. -+ -+ Blocks are mapped logically. So a sector read/write results in the determination -+ of the logical block address of the block containing the desired sector and the -+ corresponding physical block being accessed. Note the use of ReadBlock, WriteBlock, -+ and PhyBlock, Log2Phy[] etc. -+ -+ This driver implements a wear leveling strategy where sector writes to the -+ SmartMedia causes the block which is the target of the write to be copied into a -+ new block, the new data written and the old block erased. This makes the driver -+ more complicated than a straightforward sector read/write. -+ -+*/ -+ -+/* Section device headers */ -+#define DEBUG_SSFDC 0 -+#define DEBUG_SSFDC_STRUCT 0 -+#define DEBUG_SSFDC_REQUEST 0 -+#define DEBUG_SSFDC_READREDT 0 -+#define DEBUG_SSFDC_WRITE 0 -+#define DEBUG_SSFDC_WRITESECT 0 -+#define DEBUG_SSFDC_WRITEBLKS 0 -+#define DEBUG_SSFDC_READ 0 -+#define DEBUG_SSFDC_ADDR 0 -+#define DEBUG_SSFDC_ASSIGNRELEASE 0 -+#define SSFDC_READINGTASKLET 0 -+/* Edition Compilation Mode */ -+ -+#include <linux/module.h> -+ -+#include <asm/delay.h> -+#include <linux/sched.h> -+#include <linux/interrupt.h> -+ -+#include <linux/fs.h> -+#include <linux/hdreg.h> -+#include <linux/file.h> -+#include <linux/stat.h> -+#include <linux/time.h> -+#include <linux/errno.h> -+#include <linux/major.h> -+#include <linux/init.h> -+#include <asm/uaccess.h> -+#include <asm/hardirq.h> -+#include <linux/bio.h> -+#include <linux/blkdev.h> -+#include <linux/slab.h> -+#include <linux/highmem.h> -+ -+#include "ssfdc.h" -+ -+#define SSFDC_MAJOR 240 -+ -+static int static_ssfdc_debug = 0; -+ -+static DECLARE_WAIT_QUEUE_HEAD(ssfdc_wait); -+ -+static struct gendisk *disks[MAX_SSFDC]; -+static ssfdc_dev *ssfdc[MAX_SSFDC]; -+ -+static int ssfdc_open(struct inode *i_node, struct file *fptr); -+static int ssfdc_release(struct inode *i_node, struct file *fptr); -+static int ssfdc_ioctl(struct inode *i_node, struct file *fptr, unsigned cmd, unsigned long arg); -+static int ssfdc_revalidate(struct gendisk *disk); -+void do_ssfdc_request(request_queue_t * q); -+ -+static struct block_device_operations ssfdc_fops = { -+ .owner = THIS_MODULE, -+ .open = ssfdc_open, -+ .release = ssfdc_release, -+ .ioctl = ssfdc_ioctl, -+ // bjm out .revalidate_disk = ssfdc_revalidate, -+}; -+ -+ -+/*************************************************************************** -+ BIT Control Macro -+ ***************************************************************************/ -+static char BitData[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 }; -+#define SetBit(a,b) (a[(unsigned char)((b)/8)]|= BitData[(b)%8]) -+#define ClrBit(a,b) (a[(unsigned char)((b)/8)]&=~BitData[(b)%8]) -+#define ChkBit(a,b) (a[(unsigned char)((b)/8)] & BitData[(b)%8]) -+ -+/***************************************************************************/ -+static int MediaReadSector(ssfdc_dev *, struct request *, char *, long,int); -+static int MediaWriteSector(ssfdc_dev *, struct request *, char *, long,int); -+ -+/***************************************************************************/ -+static int CheckLogCHS(ssfdc_dev *,unsigned int *,unsigned char *,unsigned char *); -+static int CheckMediaWP(ssfdc_dev *); -+static int ConvMediaAddr(ssfdc_dev *,long); -+static int IncMediaAddr(ssfdc_dev *); -+static int WriteReqInCurrBlk(ssfdc_dev *, long, int *); -+/******************************************/ -+/******************************************/ -+static int AssignWriteBlock(ssfdc_dev *, int); -+/******************************************/ -+/******************************************/ -+static int SetPhyFmtValue(ssfdc_dev *); -+static int SearchCIS(ssfdc_dev *,unsigned int *); -+static int MakeLogTable(ssfdc_dev *,unsigned int); -+/******************************************/ -+static int MarkFailPhyOneBlock(ssfdc_dev *); -+ -+static void _ReadSsfdcBuf(ssfdc_dev *, unsigned char *databuf,unsigned char *redundant); -+static void _WriteSsfdcBuf(ssfdc_dev *,unsigned char *,unsigned char *); -+static void _ReadSsfdcWord(ssfdc_dev *,unsigned int *); -+static void _ReadRedtSsfdcBuf(ssfdc_dev *, unsigned char *redundant); -+static void _WriteRedtSsfdcBuf(ssfdc_dev*, unsigned char *redundant); -+ -+/***************************************************************************/ -+static void _SetSsfdcCmd(ssfdc_dev *, unsigned char); -+static void _SetSsfdcAddr(ssfdc_dev *, unsigned char); -+static void _SetSsfdcBlock(ssfdc_dev *); -+static void _SetSsfdcChip(ssfdc_dev *); -+static void _SetSsfdcStandby(ssfdc_dev *); -+static int _CheckSsfdcBusy(ssfdc_dev *, unsigned int); -+static int _CheckSsfdcStatus(ssfdc_dev *); -+static void _ResetSsfdcErr(ssfdc_dev *psm); -+static unsigned char _CheckDevCode(unsigned char); -+void SsfdcReset(ssfdc_dev *); -+void CntReset(ssfdc_dev *); -+ -+static char BitCount(unsigned char); -+static char BitCountWord(unsigned int); -+ -+static void _WaitTimer(long int); -+typedef void (*timeout_fn)(unsigned long); -+static void ssfdc_rw_request(ssfdc_dev *psm, struct request *req); -+static int ssfdc_end_request(ssfdc_dev *psm, struct request *req, int status); -+static void ssfdc_terminate_request(ssfdc_dev *psm, struct request *req); -+static struct request *ssfdc_get_request(ssfdc_dev *psm); -+ -+/* debugging utils etc. */ -+ -+#if DEBUG_SSFDC -+static void dump_ssfdc_state(ssfdc_dev * psm); -+#endif -+ -+/* end of debugging utils etc. */ -+ -+/* our tasklets */ -+/* top level R/W initiation tasklet */ -+static void initxfer(unsigned long); -+#if 0 // use thread and not a tasklet -+DECLARE_TASKLET(initxfer_tasklet0, initxfer, 0); -+#ifdef CONFIG_SH_NIMBLE_MINI -+DECLARE_TASKLET(initxfer_tasklet1, initxfer, 1); -+#endif -+#endif -+ -+/* Sector Write Tasklets, This group includes a readcopy tasklet for block copies...*/ -+ -+/* Tasklet to read a sector into a temporary buffer for later write */ -+ -+/* power is turned on, and then left on for TIMER_ON_TIMEOUT */ -+// bjm debug struct timer_list mediachange_timer; -+// bjm debug static void mediachangetest(unsigned long); -+ -+// bjm out -+// bjm out struct timer_list waiting_timer; -+static void waiting_timeout(unsigned long); -+ -+/******************************************************************************/ -+static void trans_result \ -+ (unsigned char,unsigned char,unsigned char *,unsigned char *); -+static void calculate_ecc \ -+ (unsigned char *,unsigned char *,unsigned char *,unsigned char *,unsigned char *); -+static unsigned char correct_data \ -+ (unsigned char *,unsigned char *,unsigned char,unsigned char,unsigned char); -+ -+ /* CP0-CP5 code table */ -+static unsigned char ecctable[256] = { -+ 0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00, -+ 0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65, -+ 0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66, -+ 0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03, -+ 0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69, -+ 0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C, -+ 0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F, -+ 0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A, -+ 0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A, -+ 0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F, -+ 0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C, -+ 0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69, -+ 0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03, -+ 0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66, -+ 0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65, -+ 0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00 -+}; -+ -+#define BIT7 0x80 -+#define BIT6 0x40 -+#define BIT5 0x20 -+#define BIT4 0x10 -+#define BIT3 0x08 -+#define BIT2 0x04 -+#define BIT1 0x02 -+#define BIT0 0x01 -+ -+#define BIT1BIT0 0x03 -+#define BIT23 0x00800000L -+#define MASK_CPS 0x3f -+#define CORRECTABLE 0x00555554L -+ -+/* -+ Transfer result -+ LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,.. -+*/ -+static void trans_result(reg2,reg3,ecc1,ecc2) -+unsigned char reg2; /* LP14,LP12,LP10,... */ -+unsigned char reg3; /* LP15,LP13,LP11,... */ -+unsigned char *ecc1; /* LP15,LP14,LP13,... */ -+unsigned char *ecc2; /* LP07,LP06,LP05,... */ -+{ -+ unsigned char a; /* Working for reg2,reg3 */ -+ unsigned char b; /* Working for ecc1,ecc2 */ -+ unsigned char i; /* For counting */ -+ -+ a=BIT7; b=BIT7; /* 80h=10000000b */ -+ *ecc1=*ecc2=0; /* Clear ecc1,ecc2 */ -+ for(i=0; i<4; ++i) { -+ if ((reg3&a)!=0) *ecc1|=b; /* LP15,13,11,9 -> ecc1 */ -+ b=b>>1; /* Right shift */ -+ if ((reg2&a)!=0) *ecc1|=b; /* LP14,12,10,8 -> ecc1 */ -+ b=b>>1; /* Right shift */ -+ a=a>>1; /* Right shift */ -+ } -+ b=BIT7; /* 80h=10000000b */ -+ for(i=0; i<4; ++i) { -+ if ((reg3&a)!=0) *ecc2|=b; /* LP7,5,3,1 -> ecc2 */ -+ b=b>>1; /* Right shift */ -+ if ((reg2&a)!=0) *ecc2|=b; /* LP6,4,2,0 -> ecc2 */ -+ b=b>>1; /* Right shift */ -+ a=a>>1; /* Right shift */ -+ } -+} -+ -+ -+/* -+ Calculating ECC -+ data[0-255] -> ecc1,ecc2,ecc3 using CP0-CP5 code table[0-255] -+*/ -+static void calculate_ecc(table,data,ecc1,ecc2,ecc3) -+unsigned char *table; /* CP0-CP5 code table */ -+unsigned char *data; /* DATA */ -+unsigned char *ecc1; /* LP15,LP14,LP13,... */ -+unsigned char *ecc2; /* LP07,LP06,LP05,... */ -+unsigned char *ecc3; /* CP5,CP4,CP3,...,"1","1" */ -+{ -+ unsigned int i; /* For counting */ -+ unsigned char a; /* Working for table */ -+ unsigned char reg1; /* D-all,CP5,CP4,CP3,... */ -+ unsigned char reg2; /* LP14,LP12,L10,... */ -+ unsigned char reg3; /* LP15,LP13,L11,... */ -+ -+ reg1=reg2=reg3=0; /* Clear parameter */ -+ -+ for(i=0; i<256; ++i) { -+ a=table[data[i]]; /* Get CP0-CP5 code from table */ -+ reg1^=(a&MASK_CPS); /* XOR with a */ -+ if ((a&BIT6)!=0) { /* If D_all(all bit XOR) = 1 */ -+ reg3^=(unsigned char)i; /* XOR with counter */ -+ reg2^=~((unsigned char)i); /* XOR with inv. of counter */ -+ } -+ } -+ -+ /* Trans LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,.. */ -+ trans_result(reg2,reg3,ecc1,ecc2); -+ -+ *ecc1=~(*ecc1); *ecc2=~(*ecc2); /* Inv. ecc2 & ecc3 */ -+ *ecc3=((~reg1)<<2)|BIT1BIT0; /* Make TEL format */ -+} -+ -+static unsigned char correct_data(data,eccdata,ecc1,ecc2,ecc3) -+unsigned char *data; /* DATA */ -+unsigned char *eccdata; /* ECC DATA */ -+unsigned char ecc1; /* LP15,LP14,LP13,... */ -+unsigned char ecc2; /* LP07,LP06,LP05,... */ -+unsigned char ecc3; /* CP5,CP4,CP3,...,"1","1" */ -+{ -+ unsigned long l; /* Working to check d */ -+ unsigned long d; /* Result of comparison */ -+ unsigned int i; /* For counting */ -+ unsigned char d1,d2,d3; /* Result of comparison */ -+ unsigned char a; /* Working for add */ -+ unsigned char add; /* Byte address of cor. DATA */ -+ unsigned char b; /* Working for bit */ -+ unsigned char bit; /* Bit address of cor. DATA */ -+ -+ d1=ecc1^eccdata[1]; d2=ecc2^eccdata[0]; /* Compare LP's */ -+ d3=ecc3^eccdata[2]; /* Comapre CP's */ -+ d=((unsigned long)d1<<16) /* Result of comparison */ -+ +((unsigned long)d2<<8) -+ +(unsigned long)d3; -+ -+ if (d==0) return(0); /* If No error, return */ -+ if (((d^(d>>1))&CORRECTABLE)==CORRECTABLE) { /* If correctable */ -+ l=BIT23; -+ add=0; /* Clear parameter */ -+ a=BIT7; -+ for(i=0; i<8; ++i) { /* Checking 8 bit */ -+ if ((d&l)!=0) add|=a; /* Make byte address from LP's */ -+ l>>=2; a>>=1; /* Right Shift */ -+ } -+ bit=0; /* Clear parameter */ -+ b=BIT2; -+ for(i=0; i<3; ++i) { /* Checking 3 bit */ -+ if ((d&l)!=0) bit|=b; /* Make bit address from CP's */ -+ l>>=2; b>>=1; /* Right shift */ -+ } -+ b=BIT0; -+ data[add]^=(b<<bit); /* Put corrected data */ -+ return(1); -+ } -+ i=0; /* Clear count */ -+ d&=0x00ffffffL; /* Masking */ -+ while(d) { /* If d=0 finish counting */ -+ if (d&BIT0) ++i; /* Count number of 1 bit */ -+ d>>=1; /* Right shift */ -+ } -+ if (i==1) { /* If ECC error */ -+ eccdata[1]=ecc1; eccdata[0]=ecc2; /* Put right ECC code */ -+ eccdata[2]=ecc3; -+ return(2); -+ } -+ return(3); /* Uncorrectable error */ -+} -+/*************************************************************************** -+ Common Subroutine -+ ***************************************************************************/ -+char BitCount(unsigned char cdata) -+{ -+ char bitcount=0; -+ while(cdata) { -+ bitcount+=(cdata &0x01); -+ cdata /=2; -+ } -+ return(bitcount); -+} -+ -+char BitCountWord(unsigned int cdata) -+{ -+ char bitcount=0; -+ while(cdata) { -+ bitcount+=(cdata &0x01); -+ cdata /=2; -+ } -+ return(bitcount); -+} -+ -+/***************************************************************************/ -+void StringCopy(char *stringA, char *stringB, int count) -+{ -+ int i; -+ for(i=0; i<count; i++) -+ *stringA++ = *stringB++; -+} -+ -+int StringCmp(char *stringA, char *stringB, int count) -+{ -+ int i; -+ for (i=0;i<count;i++) -+ if (*stringA++ != *stringB++) return(ERROR); -+ return(SUCCESS); -+} -+/***************************************************************************/ -+int CheckDataBlank(unsigned char *redundant) -+{ -+ char i; -+ for(i=0; i<REDTSIZE; i++) -+ if(*redundant++!=0xFF) return(ERROR); -+ return(SUCCESS); -+} -+ -+int CheckFailBlock(unsigned char *redundant) -+{ -+ redundant+=REDT_BLOCK; -+ if(*redundant==0xFF) return(SUCCESS); -+ if(! *redundant) return(ERROR); -+ if(BitCount(*redundant)<7) return(ERROR); -+ return(SUCCESS); -+} -+ -+int CheckCisBlock(unsigned char *redundant) -+{ -+ if(! (*(redundant+REDT_ADDR1H)|*(redundant+REDT_ADDR1L))) -+ return(SUCCESS); -+ if(! (*(redundant+REDT_ADDR2H)|*(redundant+REDT_ADDR2L))) -+ return(SUCCESS); -+ return(ERROR); -+} -+ -+int CheckDataStatus(unsigned char *redundant) -+{ -+ redundant+=REDT_DATA; -+ if(*redundant==0xFF) return(SUCCESS); -+ if(! *redundant) return(ERROR); -+ if(BitCount(*redundant)<5) return(ERROR); -+ return(SUCCESS); -+} -+ -+int LoadLogBlockAddr(ssfdc_dev *psm) -+{ -+ unsigned int addr1,addr2; -+ addr1=*(psm->Redundant+REDT_ADDR1H)*0x100+*(psm->Redundant+REDT_ADDR1L); -+ addr2=*(psm->Redundant+REDT_ADDR2H)*0x100+*(psm->Redundant+REDT_ADDR2L); -+ if(addr1==addr2) -+ if((addr1 &0xF000)==0x1000) -+ { psm->LogBlock=(addr1 &0x0FFF)/2; return(SUCCESS); } -+ if(BitCountWord(addr1^addr2)>1) return(ERROR); -+ if((addr1 &0xF000)==0x1000) -+ if(! (BitCountWord(addr1) &0x0001)) -+ { psm->LogBlock=(addr1 &0x0FFF)/2; return(SUCCESS); } -+ if((addr2 &0xF000)==0x1000) -+ if(! (BitCountWord(addr2) &0x0001)) -+ { psm->LogBlock=(addr2 &0x0FFF)/2; return(SUCCESS); } -+ return(ERROR); -+} -+/***************************************************************************/ -+void ClrRedundantData(unsigned char *redundant) -+{ -+ char i; -+ for(i=0; i<REDTSIZE; i++) *(redundant+i)=0xFF; -+} -+ -+/***************************************************************************/ -+void SetLogBlockAddr(ssfdc_dev *psm, unsigned char *redundant) -+{ -+ unsigned int addr; -+ *(redundant+REDT_BLOCK)=0xFF; -+ *(redundant+REDT_DATA) =0xFF; -+ addr=psm->LogBlock*2+0x1000; -+ if((BitCountWord(addr)%2)) addr++; -+ *(redundant+REDT_ADDR1H)=*(redundant+REDT_ADDR2H)=addr/0x100; -+ *(redundant+REDT_ADDR1L)=*(redundant+REDT_ADDR2L)=(unsigned char)addr; -+} -+ -+void SetFailBlock(unsigned char *redundant) -+{ -+ char i; -+ for(i=0; i<REDTSIZE; i++) -+ *redundant++=((i==REDT_BLOCK)?0xF0:0xFF); -+} -+ -+void SetDataStatus(unsigned char *redundant) -+{ -+ redundant+=REDT_DATA; -+ *redundant=0x00; -+} -+ -+ -+/*************************************************************************** -+ NAND Memory (SmartMedia) Control Subroutine -+ ***************************************************************************/ -+static void _SetSsfdcCmd(ssfdc_dev *psm, unsigned char cmd) -+{ -+ _HwSetCmd(psm); -+ _HwOutData(psm,cmd); -+ _HwSetData(psm); -+} -+ -+static void _SetSsfdcAddr(ssfdc_dev *psm, unsigned char add) -+{ -+ unsigned int addr; -+ -+#if DEBUG_SSFDC_ADDR -+ printk(KERN_DEBUG "_SetSsfdcAddr() Zone %d LogBlock %d PhyBlock %d Sector %d\n", -+ psm->Zone,psm->LogBlock,psm->PhyBlock,psm->Sector); -+#endif -+ addr=(unsigned int)psm->Zone*psm->MaxBlocks+psm->PhyBlock; -+ addr=addr*(unsigned int)psm->MaxSectors+psm->Sector; -+ if((psm->Attribute &MPS)==PS256) /* for 256byte/page */ -+ addr=addr*2+(unsigned int)add; -+/*-----------------------------------------------*/ -+ _HwSetAddr(psm); -+ _HwOutData(psm,0x00); -+ _HwOutData(psm,(unsigned char)addr); -+ _HwOutData(psm,(unsigned char)(addr/0x0100)); -+ if((psm->Attribute &MADC)==AD4CYC) -+ _HwOutData(psm,(unsigned char)(psm->Zone/2)); /* Patch */ -+ _HwSetData(psm); -+} -+ -+static void _SetSsfdcBlock(ssfdc_dev *psm) -+{ -+ unsigned int addr; -+#if DEBUG_SSFDC_ASSIGNRELEASE -+ printk(KERN_DEBUG "_SetSsfdcBlock() set card addr to PhyBlock %d\n", psm->PhyBlock); -+#endif -+ addr=(unsigned int)psm->Zone*psm->MaxBlocks+psm->PhyBlock; -+ addr=addr*(unsigned int)psm->MaxSectors; -+ if((psm->Attribute &MPS)==PS256) /* for 256byte/page */ -+ addr=addr*2; -+/*-----------------------------------------------*/ -+ _HwSetAddr(psm); -+ _HwOutData(psm,(unsigned char)addr); -+ _HwOutData(psm,(unsigned char)(addr/0x0100)); -+ if((psm->Attribute &MADC)==AD4CYC) -+ _HwOutData(psm,(unsigned char)(psm->Zone/2)); /* Patch */ -+ _HwSetData(psm); -+} -+ -+static inline void _SetSsfdcStandby(ssfdc_dev *psm) -+{ -+ _HwSetStandby(psm); -+} -+ -+static int _CheckSsfdcStatus(ssfdc_dev *psm) -+{ -+ int status; -+ if((status=_HwInData(psm)) & WR_FAIL) { -+ printk(KERN_DEBUG "_CheckSsfdcStatus() error %x\n", status); -+ return(ERROR); -+ } -+ return(SUCCESS); -+} -+ -+static void _ResetSsfdcErr(ssfdc_dev *psm) -+{ -+ _HwSetCmd(psm); -+ _HwOutData(psm,SSFDC_RST_CHIP); -+ _HwSetData(psm); -+ while(1) { -+ udelay(30); -+ if(! _HwChkBusy(psm)) break; -+ } -+ _HwSetStandby(psm); -+} -+ -+static void waiting_timeout(unsigned long psm) -+{ -+ // enable the wakeup signal! -+ wake_up(&((ssfdc_dev *)psm)->thread_wq); -+} -+ -+/* -+ _CheckSsfdcBusy() -+ -+ set a timer in jiffies from int time x .1ms -+*/ -+ -+static int _CheckSsfdcBusy(ssfdc_dev *psm, unsigned int time) -+{ -+ unsigned long incr_div = 4; -+ unsigned long incr_us = time / incr_div, -+ jticks=time/(MSEC * JIFFY_TICK_MS); -+ unsigned long tick_retried=0, wrap_flag, expires; -+ -+ if (!jticks) { -+ // small delay first to test completion -+ do { -+ udelay(incr_us); -+ if (!_HwChkBusy(psm)) -+ return(SUCCESS); -+ } while (incr_div--); -+ return(ERROR); -+ } -+ -+ // Block the wakeup signal? -+ -+one_more_time: -+ expires = jiffies + jticks; -+ wrap_flag = ( expires < jiffies); -+ -+ do { -+ wait_event_interruptible_timeout(psm->thread_wq, 0, jticks); -+ if (!_HwChkBusy(psm)) { -+ return(SUCCESS); -+ } -+ } while (wrap_flag ? expires <= jiffies : expires >= jiffies); -+ -+#if 1 -+ // Is the chip not busy? If so its an ERROR -+ if (!_HwChkBusy(psm)) { -+ return(SUCCESS); -+ } -+ else { -+ // if we came back, give us one more tick/time -+ if (! tick_retried ) { -+ tick_retried = 1; -+ jticks = 0; -+ printk("."); -+ goto one_more_time; -+ } -+ return(ERROR); -+ } -+#endif -+} -+ -+static void _SetSsfdcChip(ssfdc_dev *psm) -+{ -+ _HwSetAddr(psm); -+ _HwOutData(psm,0x00); -+ _HwSetData(psm); -+} -+/*************************************************************************** -+ NAND Memory (SmartMedia) Buffer Data Xfer Subroutine -+ ***************************************************************************/ -+static void _ReadSsfdcBuf(ssfdc_dev *psm,unsigned char *databuf,unsigned char *redundant) -+{ -+ int i; -+ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x100:0x200);i++) -+ *databuf++ =_HwInData(psm); -+ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x08:0x10);i++) -+ *redundant++ =_HwInData(psm); -+} -+ -+static void _WriteSsfdcBuf(ssfdc_dev *psm, unsigned char *databuf,unsigned char *redundant) -+{ -+ int i; -+ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x100:0x200);i++) -+ _HwOutData(psm,*databuf++); -+ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x08:0x10);i++) -+ _HwOutData(psm,*redundant++); -+} -+ -+static void _ReadSsfdcWord(ssfdc_dev *psm, unsigned int *pdata) -+{ -+ *pdata =_HwInData(psm)*0x100; -+ *pdata|=(unsigned char)_HwInData(psm); -+} -+ -+static void _ReadRedtSsfdcBuf(ssfdc_dev *psm,unsigned char *redundant) -+{ -+ int i; -+ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x08:0x10);i++) -+ redundant[i] =_HwInData(psm); -+} -+ -+static void _WriteRedtSsfdcBuf(ssfdc_dev *psm, unsigned char *redundant) -+{ -+ char i; -+ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x08:0x10);i++) -+ _HwOutData(psm,*redundant++); -+} -+ -+/*************************************************************************** -+ Timer Control Subroutine -+ ***************************************************************************/ -+#define SHORT_DELAY 1 -+ -+ -+ -+ -+void _GetDateTime(char *date) -+{ -+} -+ -+/* -+_WaitTimer(long time) time is in ticks. -+*/ -+ -+static inline void _WaitTimer(long time) -+{ -+} -+ -+/*************************************************************************** -+ SmartMedia Function Command Subroutine -+ ***************************************************************************/ -+void SsfdcReset(ssfdc_dev *psm) -+{ -+ _SetSsfdcCmd(psm, SSFDC_RST_CHIP); -+ _CheckSsfdcBusy(psm,BUSY_RESET); -+ _SetSsfdcCmd(psm,SSFDC_READ); -+ _CheckSsfdcBusy(psm,BUSY_READ); -+ _SetSsfdcStandby(psm); -+} -+ -+void SsfdcWriteRedtMode(ssfdc_dev *psm) -+{ -+ _SetSsfdcCmd(psm,SSFDC_RST_CHIP); -+ _CheckSsfdcBusy(psm,BUSY_RESET); -+ _SetSsfdcCmd(psm,SSFDC_READ_REDT); -+ _CheckSsfdcBusy(psm,BUSY_READ); -+ _SetSsfdcStandby(psm); -+} -+ -+void SsfdcReadID(ssfdc_dev *psm, unsigned int *pid) -+{ -+ _SetSsfdcCmd(psm,SSFDC_READ_ID); -+ _SetSsfdcChip(psm); -+ _ReadSsfdcWord(psm,pid); -+ _SetSsfdcStandby(psm); -+} -+ -+int SsfdcCheckStatus(ssfdc_dev *psm) -+{ -+ _SetSsfdcCmd(psm,SSFDC_RDSTATUS); -+ if(_CheckSsfdcStatus(psm)) -+ { _SetSsfdcStandby(psm); return(ERROR); } -+ _SetSsfdcStandby(psm); -+ return(SUCCESS); -+} -+ -+int SsfdcReadSect(ssfdc_dev *psm, unsigned char *buf,unsigned char *redundant) -+{ -+#if DEBUG_SSFDC_READ -+ printk(KERN_DEBUG "SsfdcReadSect() - Zone %d LogBlock %d, PhyBlock %d, Sector %d\n", -+ psm->Zone, psm->LogBlock, psm->PhyBlock, psm->Sector); -+#endif -+ _SetSsfdcCmd(psm,SSFDC_READ); -+ _SetSsfdcAddr(psm, EVEN); -+ if(_CheckSsfdcBusy(psm,BUSY_READ)) -+ { _ResetSsfdcErr(psm); return(ERROR); } -+ _ReadSsfdcBuf(psm,buf,redundant); -+ if(_CheckSsfdcBusy(psm,BUSY_READ)) -+ { _ResetSsfdcErr(psm); return(ERROR); } -+ if((psm->Attribute &MPS)==PS256) { -+ _SetSsfdcCmd(psm,SSFDC_READ); -+ _SetSsfdcAddr(psm, ODD); -+ if(_CheckSsfdcBusy(psm,BUSY_READ)) -+ { _ResetSsfdcErr(psm); return(ERROR); } -+ _ReadSsfdcBuf(psm,buf+0x100,redundant+0x08); -+ if(_CheckSsfdcBusy(psm,BUSY_READ)) -+ { _ResetSsfdcErr(psm); return(ERROR); } -+ } -+ _SetSsfdcStandby(psm); -+ return(SUCCESS); -+} -+ -+int SsfdcWriteSect(ssfdc_dev *psm, unsigned char *buf, unsigned char *redundant) -+{ -+#if DEBUG_SSFDC_WRITESECT -+ printk(KERN_DEBUG "SsfdcWriteSect() - Zone %d LogBlock %d, PhyBlock %d, Sector %d\n", \ -+ psm->Zone, psm->LogBlock, psm->PhyBlock, psm->Sector); -+#endif -+ _SetSsfdcCmd(psm,SSFDC_WRDATA); -+ _SetSsfdcAddr(psm,EVEN); -+ _WriteSsfdcBuf(psm,buf,redundant); -+ _SetSsfdcCmd(psm,SSFDC_WRITE); -+ if(_CheckSsfdcBusy(psm,BUSY_PROG)) -+ { _ResetSsfdcErr(psm); -+#if DEBUG_SSFDC_WRITESECT -+ printk(KERN_DEBUG "SsfdcWriteSect() e 1\n"); -+#endif -+ return(ERROR); } -+ if((psm->Attribute &MPS)==PS256) { -+ _SetSsfdcCmd(psm,SSFDC_RDSTATUS); -+ if(_CheckSsfdcStatus(psm)) -+ { _SetSsfdcStandby(psm); return(SUCCESS); } -+ _SetSsfdcCmd(psm,SSFDC_WRDATA); -+ _SetSsfdcAddr(psm,ODD); -+ _WriteSsfdcBuf(psm,buf+0x100,redundant+0x08); -+ _SetSsfdcCmd(psm,SSFDC_WRITE); -+ if(_CheckSsfdcBusy(psm,BUSY_PROG)) -+ { _ResetSsfdcErr(psm); -+#if DEBUG_SSFDC_WRITESECT -+ printk(KERN_DEBUG "SsfdcWriteSect() e 2\n"); -+#endif -+ return(ERROR); } -+ } -+ _SetSsfdcStandby(psm); -+ return(SUCCESS); -+} -+ -+int SsfdcEraseBlock(ssfdc_dev *psm) -+{ -+ _SetSsfdcCmd(psm,SSFDC_ERASE1); -+ _SetSsfdcBlock(psm); -+ _SetSsfdcCmd(psm,SSFDC_ERASE2); -+ if(_CheckSsfdcBusy(psm,BUSY_ERASE) || SsfdcCheckStatus(psm)) { -+ _ResetSsfdcErr(psm); -+ return(ERROR); -+ } -+ _SetSsfdcStandby(psm); -+ return(SUCCESS); -+} -+ -+int SsfdcReadRedtData(ssfdc_dev *psm, unsigned char *redundant) -+{ -+#if DEBUG_SSFDC_READREDT -+ printk(KERN_DEBUG " +"); -+#endif -+ _SetSsfdcCmd(psm,SSFDC_READ_REDT); -+ _SetSsfdcAddr(psm,EVEN); -+ if(_CheckSsfdcBusy(psm,BUSY_READ)) -+ { _ResetSsfdcErr(psm); -+#if DEBUG_SSFDC_READREDT -+ printk(KERN_DEBUG " e 1\n"); -+#endif -+ return(ERROR); } -+ _ReadRedtSsfdcBuf(psm, redundant); -+ if(_CheckSsfdcBusy(psm,BUSY_READ)) -+ { _ResetSsfdcErr(psm); -+#if DEBUG_SSFDC_READREDT -+ printk(KERN_DEBUG " e 2\n"); -+#endif -+ return(ERROR); } -+ if((psm->Attribute &MPS)==PS256) { -+ _SetSsfdcCmd(psm,SSFDC_READ_REDT); -+ _SetSsfdcAddr(psm,ODD); -+ if(_CheckSsfdcBusy(psm,BUSY_READ)) -+ { _ResetSsfdcErr(psm); -+#if DEBUG_SSFDC_READREDT -+ printk(KERN_DEBUG " e 3\n"); -+#endif -+ -+ return(ERROR); } -+ _ReadRedtSsfdcBuf(psm, redundant+0x08); -+ if(_CheckSsfdcBusy(psm,BUSY_READ)) -+ { _ResetSsfdcErr(psm); -+#if DEBUG_SSFDC_READREDT -+ printk(KERN_DEBUG " e 4\n"); -+#endif -+ return(ERROR); } -+ } -+ _SetSsfdcStandby(psm); -+#if DEBUG_SSFDC_READREDT -+ printk(KERN_DEBUG " -\n"); -+#endif -+ return(SUCCESS); -+} -+ -+int SsfdcWriteRedtData(ssfdc_dev *psm, unsigned char *redundant) -+{ -+ _SetSsfdcCmd(psm,SSFDC_WRDATA); -+ _SetSsfdcAddr(psm,EVEN); -+ _WriteRedtSsfdcBuf(psm,redundant); -+ _SetSsfdcCmd(psm,SSFDC_WRITE); -+ if(_CheckSsfdcBusy(psm,BUSY_PROG)) -+ { _ResetSsfdcErr(psm); return(ERROR); } -+ if((psm->Attribute &MPS)==PS256) { -+ _SetSsfdcCmd(psm,SSFDC_RDSTATUS); -+ if(_CheckSsfdcStatus(psm)) -+ { _SetSsfdcStandby(psm); return(SUCCESS); } -+ _SetSsfdcCmd(psm,SSFDC_WRDATA); -+ _SetSsfdcAddr(psm,ODD); -+ _WriteRedtSsfdcBuf(psm,redundant+0x08); -+ _SetSsfdcCmd(psm,SSFDC_WRITE); -+ if(_CheckSsfdcBusy(psm,BUSY_PROG)) -+ { _ResetSsfdcErr(psm); return(ERROR); } -+ } -+ _SetSsfdcStandby(psm); -+ return(SUCCESS); -+} -+ -+/*************************************************************************** -+ SmartMedia ID Code Check & Mode Set Subroutine -+ ***************************************************************************/ -+int SetSsfdcModel(ssfdc_dev *psm, unsigned char dcode) -+{ -+ switch(_CheckDevCode(dcode)) { -+ case SSFDC1MB: -+ psm->Model = SSFDC1MB; -+ psm->Attribute = FLASH | AD3CYC | BS16 | PS256; -+ psm->MaxZones = 1; -+ psm->MaxBlocks = 256; -+ psm->MaxLogBlocks = 250; -+ psm->MaxSectors = 8; -+ break; -+ case SSFDC2MB: -+ psm->Model = SSFDC2MB; -+ psm->Attribute = FLASH | AD3CYC | BS16 | PS256; -+ psm->MaxZones = 1; -+ psm->MaxBlocks = 512; -+ psm->MaxLogBlocks = 500; -+ psm->MaxSectors = 8; -+ break; -+ case SSFDC4MB: -+ psm->Model = SSFDC4MB; -+ psm->Attribute = FLASH | AD3CYC | BS16 | PS512; -+ psm->MaxZones = 1; -+ psm->MaxBlocks = 512; -+ psm->MaxLogBlocks = 500; -+ psm->MaxSectors = 16; -+ break; -+ case SSFDC8MB: -+ psm->Model = SSFDC8MB; -+ psm->Attribute = FLASH | AD3CYC | BS16 | PS512; -+ psm->MaxZones = 1; -+ psm->MaxBlocks = 1024; -+ psm->MaxLogBlocks = 1000; -+ psm->MaxSectors = 16; -+ break; -+ case SSFDC16MB: -+ psm->Model = SSFDC16MB; -+ psm->Attribute = FLASH | AD3CYC | BS32 | PS512; -+ psm->MaxZones = 1; -+ psm->MaxBlocks = 1024; -+ psm->MaxLogBlocks = 1000; -+ psm->MaxSectors = 32; -+ break; -+ case SSFDC32MB: -+ psm->Model = SSFDC32MB; -+ psm->Attribute = FLASH | AD3CYC | BS32 | PS512; -+ psm->MaxZones = 2; -+ psm->MaxBlocks = 1024; -+ psm->MaxLogBlocks = 1000; -+ psm->MaxSectors = 32; -+ break; -+ case SSFDC64MB: -+ psm->Model = SSFDC64MB; -+ psm->Attribute = FLASH | AD4CYC | BS32 | PS512; -+ psm->MaxZones = 4; -+ psm->MaxBlocks = 1024; -+ psm->MaxLogBlocks = 1000; -+ psm->MaxSectors = 32; -+ break; -+ case SSFDC128MB: -+ psm->Model = SSFDC128MB; -+ psm->Attribute = FLASH | AD4CYC | BS32 | PS512; -+ psm->MaxZones = 8; -+ psm->MaxBlocks = 1024; -+ psm->MaxLogBlocks = 1000; -+ psm->MaxSectors = 32; -+ break; -+ default: -+ psm->Model = NOSSFDC; -+ return(ERROR); -+ } -+ return(SUCCESS); -+} -+ -+/***************************************************************************/ -+static unsigned char _CheckDevCode(unsigned char dcode) -+{ -+ switch(dcode){ -+ case 0x6E: -+ case 0xE8: -+ case 0xEC: return(SSFDC1MB); /* 8Mbit (1M) NAND */ -+ case 0x64: -+ case 0xEA: return(SSFDC2MB); /* 16Mbit (2M) NAND */ -+ case 0x6B: -+ case 0xE3: -+ case 0xE5: return(SSFDC4MB); /* 32Mbit (4M) NAND */ -+ case 0xE6: return(SSFDC8MB); /* 64Mbit (8M) NAND */ -+ case 0x73: return(SSFDC16MB); /*128Mbit (16M)NAND */ -+ case 0x75: return(SSFDC32MB); /*256Mbit (32M)NAND */ -+ case 0x76: return(SSFDC64MB); /*512Mbit (64M)NAND */ -+ case 0x79: return(SSFDC128MB); /* 1Gbit(128M)NAND */ -+ default: return(ERROR); -+ } -+} -+/*************************************************************************** -+ SmartMedia Power Control Subroutine -+ ***************************************************************************/ -+void CntReset(ssfdc_dev *psm) -+{ -+ _HwSetStandby(psm); -+ _HwVccOff(psm); -+} -+ -+int CntPowerOn(ssfdc_dev *psm) -+{ -+ _HwVccOn(psm); -+ _WaitTimer(TIME_PON); -+ if(_HwChkPower(psm)) -+ return(SUCCESS); -+ _HwVccOff(psm); -+ return(ERROR); -+} -+ -+#if 0 // remove for now -+static void mediachangetest(unsigned long dev_idx) -+{ -+ ssfdc_dev *psm = ssfdc[dev_idx]; -+ unsigned int cardpresent; -+ unsigned long flags; -+ -+ spin_lock_irqsave( &psm->req_queue_lock, flags ); -+ // bjm spin_lock( &psm->req_queue_lock); -+ -+ del_timer(&mediachange_timer); -+ -+ // check current card presence -+ if ( ! (cardpresent = CntPowerOn(psm)) && psm->CardPresent ) { -+ psm->MediaChange = 1; -+ psm->DataBuf_Valid = 0; -+ } -+ psm->CardPresent = cardpresent; -+ -+ // set up to run again... -+ mediachange_timer.function = mediachangetest; -+ mediachange_timer.expires = jiffies + (HZ / 2); -+ mediachange_timer.data = dev_idx; -+ add_timer(&mediachange_timer); -+ -+ spin_unlock_irqrestore( &psm->req_queue_lock, flags ); -+ // bjm spin_unlock( &psm->req_queue_lock); -+} -+#endif -+ -+int CheckCardExist(ssfdc_dev *psm) -+{ -+ char i,j,k; -+ if(! _HwChkStatus(psm)) /***** Not Status Change *****/ -+ if(_HwChkCardIn(psm)) return(SUCCESS); /* Card exist in Slot */ -+ for(i=0,j=0,k=0; i<0x10; i++) { -+ if(_HwChkCardIn(psm)) /***** Status Change *****/ -+ { j++; k=0; } -+ else { j=0; k++; } -+ if(j>3) return(SUCCESS); /* Card exist in Slot */ -+ if(k>3) return(ERROR); /* NO Card exist in Slot */ -+ _WaitTimer(TIME_CDCHK); -+ } -+ return(ERROR); -+} -+ -+int CheckSsfdcWP(ssfdc_dev *psm) -+{ /* ERROR: WP, SUCCESS: Not WP */ -+ char i; -+ for(i=0; i<0x08; i++) { -+ if(_HwChkWP(psm)) -+ return(ERROR); -+ _WaitTimer(TIME_WPCHK); -+ } -+ return(SUCCESS); -+} -+ -+/******************************************/ -+int CheckCISdata(unsigned char *buf,unsigned char *redundant) -+{ -+ static unsigned char cis[]={ 0x01,0x03,0xD9,0x01,0xFF,0x18,0x02,0xDF,0x01,0x20 }; -+ unsigned char ecc1,ecc2,ecc3; -+ unsigned int err; -+ calculate_ecc(ecctable,buf,&ecc1,&ecc2,&ecc3); -+ err=correct_data(buf,redundant+0x0D,ecc1,ecc2,ecc3); -+ if(err==0 || err==1 || err==2) -+ return(StringCmp(buf,cis,10)); -+ buf+=0x100; -+ calculate_ecc(ecctable,buf,&ecc1,&ecc2,&ecc3); -+ err=correct_data(buf,redundant+0x08,ecc1,ecc2,ecc3); -+ if(err==0 || err==1 || err==2) -+ return(StringCmp(buf,cis,10)); -+ return(ERROR); -+} -+ -+int CheckECCdata(unsigned char *buf,unsigned char *redundant) -+{ -+ unsigned char ecc1,ecc2,ecc3; -+ unsigned int err, corr=SUCCESS; -+ calculate_ecc(ecctable,buf,&ecc1,&ecc2,&ecc3); -+ err=correct_data(buf,redundant+0x0D,ecc1,ecc2,ecc3); -+ if(err==1 || err==2) corr=CORRECT; -+ else if(err) return(ERROR); -+ buf+=0x100; -+ calculate_ecc(ecctable,buf,&ecc1,&ecc2,&ecc3); -+ err=correct_data(buf,redundant+0x08,ecc1,ecc2,ecc3); -+ if(err==1 || err==2) corr=CORRECT; -+ else if(err) return(ERROR); -+ return(corr); -+} -+ -+void SetECCdata(unsigned char *buf,unsigned char *redundant) -+{ -+ calculate_ecc(ecctable,buf,redundant+0x0E,redundant+0x0D,redundant+0x0F); -+ buf+=0x100; -+ calculate_ecc(ecctable,buf,redundant+0x09,redundant+0x08,redundant+0x0A); -+} -+ -+/*************************************************************************** -+ Power Control & Media Exist Check Function -+ ***************************************************************************/ -+ -+/*************************************************************************** -+ SmartMedia Read/Write/Erase Function -+ ***************************************************************************/ -+static int MediaReadSector(ssfdc_dev *psm, struct request *req, -+ char * bbuf, long start,int count) -+{ -+ char *buf; -+ int i, err, request_complete, -+ PrevBlock = NO_ASSIGN; -+ int read_status=0; -+ -+ if (ConvMediaAddr(psm, start)) { -+ printk(KERN_ERR "MediaReadSector() - bad address conversion\n"); -+ goto read_exit; -+ } -+ -+ psm->ReqSectorSize = count; -+ psm->BufIndex = 0; -+ psm->RetryCount = 0; -+ -+#if DEBUG_SSFDC_READ -+ printk(KERN_DEBUG "MediaReadSector() - read %d sectors @ %d\n", psm->ReqSectorSize, start); -+#endif -+ while (psm->ReqSectorSize) { -+ // if this PhyBlock is not assigned, fill with dummy data and return -+ // An assigned block results in a card access and readsector schedule... -+ if (psm->PhyBlock == NO_ASSIGN) { -+#if DEBUG_SSFDC_READ -+ printk(KERN_DEBUG "Read NO_ASSIGN block %x\n", psm->PhyBlock); -+#endif -+ buf = bbuf + psm->BufIndex; -+ for(i=0; i<SSFDC_SECTSIZE; i++) -+ *buf++=DUMMY_DATA; -+ } -+ else { -+ // send our command -+ if (PrevBlock != psm->PhyBlock) { -+#if DEBUG_SSFDC_READ -+ printk(KERN_DEBUG "Read block %x\n", psm->PhyBlock); -+#endif -+ PrevBlock = psm->PhyBlock; -+ _SetSsfdcCmd(psm,SSFDC_READ); -+ _SetSsfdcAddr(psm, EVEN); -+ for (i=0; i<5; ++i) { -+ if (!_HwChkBusy(psm)) -+ break; -+ udelay(10); -+ } -+ } -+ -+ -+ if ( _HwChkBusy(psm) ) { -+ ++psm->Sect_rd_errs_ttl; -+#if DEBUG_SSFDC_READ -+ printk(KERN_DEBUG "MediaReadSector() - Hardware busy!\n"); -+#endif -+ } -+ else { -+ ++psm->Sector_reads; -+ _ReadSsfdcBuf( psm, psm->SectBuf, psm->Redundant); -+ -+ // verify the integrity of what was read -+ if (CheckDataStatus(psm->Redundant)) { -+#if DEBUG_SSFDC_READ -+ printk(KERN_DEBUG "Bad Data Status\n"); -+#endif -+ goto error_state; -+ } -+ -+ switch (err = CheckECCdata(psm->SectBuf,psm->Redundant)) -+ { -+ case CORRECT: -+ // Correctable data, fix and copy like SUCCESS -+ SetECCdata(psm->SectBuf,psm->Redundant); -+ case SUCCESS: -+ memcpy(bbuf + psm->BufIndex, psm->SectBuf, SSFDC_SECTSIZE); -+ break; -+ -+ case ERROR: -+error_state: -+ ++psm->Sect_rd_errs_ttl; -+#if DEBUG_SSFDC_READ -+ printk(KERN_DEBUG "readsector() - err == ERROR\n"); -+#endif -+ _ResetSsfdcErr(psm); -+ if (++psm->RetryCount < RD_RETRY_LIMIT) { -+ continue; -+ } -+ break; -+ default: -+ ssfdc_terminate_request( psm, req); -+ break; -+ } -+ -+ } // if ( _HwChkBusy(psm) ) -+ } // if (psm->PhyBlock == NO_ASSIGN) -+ -+ // common req/buffer management code for either unassigned or assigned -+ // block from /dev/ssfdc -+ psm->RetryCount = 0; -+ psm->BufIndex += SSFDC_SECTSIZE; -+ request_complete = (--psm->ReqSectorSize == 0); -+ if (request_complete) { -+ // completed the read, req->buffer now has requested sector(s). -+ // End the request waking sleeping process and reschedule initxfer(). -+#if DEBUG_SSFDC_READ -+ printk(KERN_DEBUG "readsector() - req %x complete\n", req); -+#endif -+ read_status = 1; -+ } -+ else if (IncMediaAddr(psm)) { -+ printk(KERN_DEBUG "readsector() - IncMediaAddr() error.\n"); -+ goto read_exit; -+ } -+ } // while (psm->ReqSectorSize) -+ -+read_exit: -+ psm->XferState = xfer_idle; -+ -+ return read_status; -+ -+} -+ -+/* -+ ReadBlkCopy(ssfdc_dev *psm, unsigned char *buf) -+*/ -+int ReadBlkCopy(ssfdc_dev *psm, unsigned char *buf, char *rd_sector_status) -+{ -+ int err, read_error=0, rw_retry=0; -+ unsigned long PrevBlock=NO_ASSIGN; -+ -+ if ( ! buf ) { -+ printk(KERN_ERR "NULL buffer pointer\n"); -+ return ERROR; -+ } -+ -+ if (psm->PhyBlock == NO_ASSIGN) { -+ memset(buf, 0xff, psm->MaxSectors * SSFDC_SECTSIZE); -+ memset(rd_sector_status, 1, sizeof(char) * MAX_SECTNUM); -+ return SUCCESS; -+ } -+ -+#if 0 -+ printk(KERN_ERR "ReadBlkCopy() - LogBlk %d\n", psm->LogBlock); -+#endif -+ -+ for (psm->Sector = 0; -+ psm->PhyBlock != NO_ASSIGN && psm->Sector < psm->MaxSectors; -+ ++psm->Sector) -+ { -+ if (PrevBlock != psm->PhyBlock) { -+ _SetSsfdcCmd(psm,SSFDC_READ); -+ _SetSsfdcAddr(psm, EVEN); -+ PrevBlock = psm->PhyBlock; -+ _CheckSsfdcBusy(psm, BUSY_ADDR_SET); -+ } -+ -+ if ( _HwChkBusy(psm) ) { -+ printk(KERN_ERR "%s: HW busy during block copy!\n", MAJOR_NAME); -+ goto error_state; -+ } -+ -+ _ReadSsfdcBuf( psm, psm->SectBuf, psm->Redundant); -+ if (CheckDataStatus(psm->Redundant)) { -+ printk("KERN_ERR reading Block %d, sector %d\n", psm->PhyBlock, psm->Sector); -+ goto error_state; -+ } -+ -+ // Attempt to correct -+ switch (err = CheckECCdata(psm->SectBuf,psm->Redundant)) -+ { -+ case CORRECT: -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "ReadBlkCopy() - err == CORRECT\n"); -+#endif -+ SetECCdata(psm->SectBuf,psm->Redundant); -+ case SUCCESS: -+ read_error = 0; -+ rw_retry = 0; -+ memcpy(buf + (psm->Sector * SSFDC_SECTSIZE), psm->SectBuf, SSFDC_SECTSIZE); -+ rd_sector_status[psm->Sector] = 1; -+ read_error = 0; -+ break; -+ -+ case ERROR: -+error_state: -+/*bjm*/ printk("ERR - ECC error reading Block %d, Sector %d\n", psm->PhyBlock,psm->Sector); -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "ReadBlkCopy() - err == ERROR\n"); -+ printk("_ResetSsfdcErr(psm)\n"); -+#endif -+ _ResetSsfdcErr(psm); -+ PrevBlock = NO_ASSIGN; -+ if (++rw_retry < RD_RETRY_LIMIT) { -+ // retry current Sector/loop counter on next loop iteration. -+ --psm->Sector; -+ } -+ else { -+ // set sector data in copy buf to the unassigned value 0xFF -+ // next loop iteration will read next Sector, zero RetryCount -+ // for next sectors read -+ // map bad sector... -+ memset(buf + psm->Sector * SSFDC_SECTSIZE, 0xFF, SSFDC_SECTSIZE); -+ rw_retry = 0; -+ rd_sector_status[psm->Sector] = 0; -+ ++psm->Sect_rd_errs_ttl; -+ read_error = 1; -+ } -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "Unable to read Blk %d Sector %d\n", psm->PhyBlock, psm->Sector); -+#endif -+ break; -+ } -+ } -+ if (!read_error) { -+ if (SsfdcEraseBlock(psm)) { -+ MarkFailPhyOneBlock(psm); -+ ++psm->Bad_blks_erase; -+ } -+ else { -+ ClrBit(psm->Assign[psm->Zone], psm->PhyBlock); -+ } -+ } -+ else { -+ printk("Read error block %d\n", psm->PhyBlock); -+ MarkFailPhyOneBlock(psm); -+ } -+ psm->Sector = 0; -+ return read_error ? ERROR : SUCCESS; -+} -+ -+/* -+ WriteBlock() -+*/ -+int WriteBlock(ssfdc_dev *psm, char *buf, char *wr_sector_status) -+{ -+ int write_error=0, reassign_retry=0; -+ -+ for ( reassign_retry = 0; reassign_retry < REASSIGN_RETRY_LIMIT; ++reassign_retry) -+ { -+ /* -+ assign new write block for write req -+ - set new write address -+ - write buffer to new block -+ */ -+#if DEBUG_SSFDC_WRITE -+ if (AssignWriteBlock(psm,1)) { -+#else -+ if (AssignWriteBlock(psm,0)) { -+#endif -+ write_error = 1; -+ printk(KERN_ERR "sm%dd Unable to assign new write block.\n", psm->sm_minor); -+ memset(wr_sector_status, 1, sizeof(char) * MAX_SECTNUM); -+ // ssfdc_terminate_request(psm, req); -+ return ERROR; -+ } -+ -+#if 0 -+ printk(KERN_ERR "WriteBlock() - LogBlock %d\n", psm->LogBlock); -+#endif -+ -+ for (psm->Sector = 0; psm->Sector < psm->MaxSectors; ++psm->Sector) -+ { -+ memcpy(psm->SectBuf,buf+psm->Sector*SSFDC_SECTSIZE,SSFDC_SECTSIZE); -+ -+ _SetSsfdcCmd(psm,SSFDC_WRDATA); -+ _SetSsfdcAddr(psm,EVEN); -+ ClrRedundantData(psm->Redundant); -+ SetLogBlockAddr(psm,psm->Redundant); -+ SetECCdata(psm->SectBuf,psm->Redundant); -+ _WriteSsfdcBuf(psm,psm->SectBuf,psm->Redundant); -+ -+#if DEBUG_SSFDC_WRITE -+ printk("%d ", psm->Sector); -+#endif -+ -+ _SetSsfdcCmd(psm, SSFDC_WRITE); -+ if ( ! _CheckSsfdcBusy(psm, BUSY_PROG) && !SsfdcCheckStatus(psm)) { -+#if DEBUG_SSFDC_WRITE -+ printk("\nMulti-Sector write OK!\n"); -+#endif -+ _SetSsfdcStandby(psm); -+ // mark status a success -+ wr_sector_status[psm->Sector] = 1; -+ -+#if 0 // bjm removed -+ { unsigned char parbuf[SSFDC_SECTSIZE]; -+ unsigned char redtpar[REDTSIZE]; -+ -+ _SetSsfdcCmd(psm,SSFDC_READ); -+ _SetSsfdcAddr(psm, EVEN); -+ -+ udelay(30); -+ if ( _HwChkBusy(psm) ) { -+ _ResetSsfdcErr(psm); -+ printk("paranoid read failure\n"); -+ } -+ else { -+ _ReadSsfdcBuf(psm, parbuf, redtpar); -+ if (CheckDataStatus(redtpar)) { -+ printk("paranoid read, bad data status\n"); -+ } -+ else { -+ switch( err = CheckECCdata(parbuf,redtpar)) -+ { -+ case CORRECT: -+ printk("paranoid correctable\n"); -+ SetECCdata(parbuf,redtpar); -+ case SUCCESS: -+ if (memcmp(parbuf,psm->SectBuf, SSFDC_SECTSIZE)) -+ write_error = 1; -+ else -+ write_error = 0; -+ break; -+ case ERROR: -+ MarkFailPhyOneBlock(psm); -+ write_error=1; -+ break; -+ } -+ } -+ } -+ } // bjm end of paranoid read back test... -+#endif -+ } -+ else { -+#if DEBUG_SSFDC_WRITE -+ printk("\nMulti-Sector write FAILED!\n"); -+#endif -+ // mark status a failure -+ wr_sector_status[psm->Sector] = 0; -+ _ResetSsfdcErr(psm); -+ write_error = 1; -+ break; -+ } // for (psm->Sector ...) -+ if (write_error) -+ break; -+ } -+ if ( ! write_error ) { -+ psm->Log2Phy[psm->Zone][psm->LogBlock] = psm->WriteBlock; -+ break; -+ } -+ } -+ psm->Sector = 0; -+ return write_error ? ERROR : SUCCESS; -+} -+ -+/* -+ MediaWriteSector() -+ -+*/ -+static int MediaWriteSector(ssfdc_dev *psm, struct request *req, char * bbuf, long start, int count) -+{ -+ int write_error=0, unwritten_block=0; -+ char *buf; -+ unsigned long curr_sector, blksize, PrevBlock; -+ unsigned long writebuf_index, readbio_index; -+ int i, sector, rw_retry=0; -+ int sectors_in_block; -+ char rd_sector_status[MAX_SECTNUM]; -+ char wr_sector_status[MAX_SECTNUM]; -+ -+ // optimized write, new vars -+ int bio_endios=0; -+ int bio_bvecs=0; -+ struct bio *bio; -+ // optimized for write -+ -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "+MediaWriteSector()\n"); -+#endif -+ -+ if (!count) { -+ printk("MediaWriteSector() count == 0!\n"); -+ ssfdc_end_request(psm, req, 0); -+ return 1; -+ } -+ -+ if (CheckMediaWP(psm)) { -+ printk(KERN_DEBUG "%s: write protected media.\n", MAJOR_NAME); -+ ssfdc_terminate_request( psm, req); -+ psm->XferState = xfer_idle; -+ return -EIO; -+ } -+ -+ // allocate block size buffer -+ blksize = psm->MaxSectors * SSFDC_SECTSIZE; -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "%s: Allocate %d sized block.\n", MAJOR_NAME, blksize); -+#endif -+ if ((buf = kmalloc(blksize, GFP_ATOMIC)) == NULL) { -+ printk(KERN_ERR "%s: Null buffer allocated!\n", MAJOR_NAME); -+ ssfdc_terminate_request( psm, req); -+ goto the_exit; -+ } -+ -+ /* -+ Loop to handle a request at the curr_sector of count sectors. -+ The write operation my encompas more than one phys block. -+ */ -+ curr_sector = start; -+ sectors_in_block = 0; -+ // zero out our sector R/W status array -+ memset(rd_sector_status, 1, sizeof(char) * MAX_SECTNUM); -+ memset(wr_sector_status, 1, sizeof(char) * MAX_SECTNUM); -+ -+ // rangecheck this sector within the device. -+ if (ConvMediaAddr(psm, curr_sector)) { -+ ssfdc_terminate_request(psm, req); -+ printk(KERN_ERR "WriteSector: ConvMediaAddr() error\n"); -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "-MediaWriteSector()\n"); -+#endif -+ return 0; -+ } -+ -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "MediaWriteSector() Zone %d, LogBlock %d PhyBlock %d, Sector %d\n", -+ psm->Zone,psm->LogBlock, psm->PhyBlock,psm->Sector); -+#endif -+ -+ PrevBlock = NO_ASSIGN; -+ rw_retry = 0; -+ -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "Copy Zone %d, Phys %d\n", psm->Zone, psm->PhyBlock); -+#endif -+ // As a technique for wear leveling, a write to the SM results in the contents -+ // of the block to be copied into a blocksize buffer, the write data of the -+ // write request being overlayed onto the buffer containing the copied block, -+ // a new logical to physical mapping defined, and the buffer written into this -+ // newly mapped (logically) physical block. -+ -+ // read the physical block into the buffer. -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "ReadBlock = %d LogBlock %d\n", psm->PhyBlock, psm->LogBlock); -+#endif -+ if (ReadBlkCopy(psm, buf, rd_sector_status) != SUCCESS) { -+ printk(KERN_ERR "Unable to read block.\n"); -+ goto the_exit; -+ } -+ -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "Read from pending write request "); -+#endif -+ -+#if 0 -+ int bio_idx=0; -+#endif -+ rq_for_each_bio(bio, req) { -+ struct bio_vec *bvec; -+ int i, break_flag=0; -+#if 0 -+ int segment_idx; -+ printk(KERN_ERR "bio %d\n", bio_idx++); -+ -+ segment_idx = 0; -+#endif -+ // bio_bvecs = 0; -+ bio_for_each_segment(bvec, bio, i) { -+#if 0 -+ printk(KERN_ERR "segment %d\n", segment_idx++); -+#endif -+ // The conditions... -+ // bio fits within block -+ if (WriteReqInCurrBlk(psm,curr_sector + (bvec->bv_len >> 9) - 1,§or) -+ && WriteReqInCurrBlk(psm,curr_sector, §or)) -+ { -+#if 0 -+ printk(KERN_ERR "LogBlk %d: write at %d, %d sectors\n", -+ psm->LogBlock, curr_sector % psm->MaxSectors, bio_cur_sectors(bio)); -+#endif -+ // write bio into copied block -+ ++bio_bvecs; -+ writebuf_index = sector * SSFDC_SECTSIZE; -+#if 0 -+ printk(KERN_ERR "memcpy buf at 0x%x, 0x%x bytes\n", -+ writebuf_index, bvec->bv_len); -+#endif -+ memcpy(buf + writebuf_index, -+ page_address(bvec->bv_page) + bvec->bv_offset, bvec->bv_len); -+ unwritten_block = 1; -+ curr_sector += bvec->bv_len >> 9; -+ } -+ // bio fits partially within block -+ else if (WriteReqInCurrBlk(psm,curr_sector, §or)) -+ { -+ // put portion of bio in block -+ ++bio_bvecs; -+ writebuf_index = sector * SSFDC_SECTSIZE; -+ sectors_in_block = psm->MaxSectors - sector; -+ readbio_index = sectors_in_block * SSFDC_SECTSIZE; -+#if 0 -+ printk(KERN_ERR "memcpy buf at %x, %x bytes\n", -+ writebuf_index, readbio_index); -+#endif -+ memcpy(buf + writebuf_index, -+ page_address(bvec->bv_page) + bvec->bv_offset, readbio_index); -+#if 0 -+ printk(KERN_ERR "LogBlk %d: partial-write at %d, %d sectors first\n", -+ psm->LogBlock, curr_sector % psm->MaxSectors, sectors_in_block); -+#endif -+ // write block -+ unwritten_block = 0; -+ if (WriteBlock(psm, buf, wr_sector_status) != SUCCESS) { -+ printk(KERN_ERR "Unable to write block %d\n", psm->LogBlock); -+ // write_error - writing this block failed -+ break_flag = 1; -+ break; -+ } -+ // incr addr & read next block, -+ curr_sector += sectors_in_block; -+ if (ConvMediaAddr(psm,curr_sector) != SUCCESS) { -+ printk(KERN_ERR "MediaWriteSector() IncMediaAddr() error!\n"); -+ // write_error - address into next block is bogus -+ write_error = 1; -+ break_flag = 1; -+ break; -+ } -+ if (ReadBlkCopy(psm, buf, rd_sector_status) != SUCCESS) { -+ printk(KERN_ERR "MediaWriteSector() ReadBlkCopy() error!\n"); -+ // write error - next block read error -+ write_error = 1; -+ break_flag =1; -+ break; -+ } -+ // write remainder of bio into block -+#if 0 -+ printk(KERN_ERR "LogBlk %d: partial-write at %d, %d sectors, second write\n", -+ psm->LogBlock, curr_sector % psm->MaxSectors, (bvec->bv_len >> 9) - sectors_in_block); -+#endif -+#if 0 -+ printk(KERN_ERR "memcpy buf at 0x%x, from bio 0x%x, for 0x%x bytes\n", -+ 0, readbio_index, ((bvec->bv_len >> 9) - sectors_in_block) * SSFDC_SECTSIZE); -+#endif -+ memcpy(buf, (page_address(bvec->bv_page) + bvec->bv_offset) + readbio_index, -+ ((bvec->bv_len >> 9) - sectors_in_block) * SSFDC_SECTSIZE); -+ writebuf_index = ((bvec->bv_len >> 9) - sectors_in_block) * SSFDC_SECTSIZE; -+ unwritten_block = 1; -+ curr_sector += (bvec->bv_len >> 9) - sectors_in_block; -+ } -+ // bio is not in block at all. coplete unwritten block and exit loop. -+ else { -+ // write current block -+#if 0 -+ printk(KERN_ERR "bio no longer in block\n"); -+#endif -+ if (unwritten_block) { -+ if (WriteBlock(psm, buf, wr_sector_status) != SUCCESS) { -+ printk(KERN_ERR "MediaWriteSector() WriteBlock() error!\n"); -+ // write_error -+ } -+ unwritten_block = 0; -+ } -+ break_flag = 1; -+ break; -+ } -+ } -+ // bjm if (bio_bvecs) +bio_bvecs; -+ -+ if (break_flag) -+ break; -+ } -+ -+ if (unwritten_block) { -+ if (WriteBlock(psm, buf, wr_sector_status) != SUCCESS) { -+ printk(KERN_ERR "MediaWriteSector() WriteBlock() error!\n"); -+ write_error = 1; -+ } -+ } -+ -+ if (!(bio_endios=bio_bvecs)) { -+ if (static_ssfdc_debug) -+ printk("no bios from request!\n"); -+ ++bio_endios; -+ write_error = 0; -+ } -+ -+the_exit: -+ // log sector status for the copied/unmodified Sectors and flag any that have cpy errors -+ for (sector = 0; sector < psm->MaxSectors; ++sector) { -+ if ( ! rd_sector_status[sector] ) -+ printk(KERN_ERR "%s: READ sector %d invalid for block %d!\n", \ -+ MAJOR_NAME, sector, psm->LogBlock); -+ if ( ! wr_sector_status[sector]) -+ printk(KERN_ERR "%s: WRITTEN sector %d invalid for block %d!\n", \ -+ MAJOR_NAME, sector, psm->LogBlock); -+ } -+ -+ // free our prev allocated block for copy... -+ if (buf) -+ kfree(buf); -+ -+ psm->XferState = xfer_idle; -+ -+#if DEBUG_SSFDC_WRITE -+ printk(KERN_DEBUG "-MediaWriteSector()\n"); -+#endif -+ if (static_ssfdc_debug) -+ printk("end_request(%d) ", ! write_error); -+ for (i = 0; i < bio_endios; ++i) { -+ if (static_ssfdc_debug) -+ printk("%d ", i); -+ ssfdc_end_request(psm, req, ! write_error); -+ } -+ if (static_ssfdc_debug) -+ printk("\n"); -+ -+ return ! write_error; -+ -+} -+ -+ -+/*************************************************************************** -+ SmartMedia Logical Format Subroutine -+ ***************************************************************************/ -+int CheckLogCHS(ssfdc_dev *psm, unsigned int *c,unsigned char *h,unsigned char *s) -+{ -+ switch(psm->Model) { -+ case SSFDC1MB: *c=125; *h= 4; *s= 4; break; -+ case SSFDC2MB: *c=125; *h= 4; *s= 8; break; -+ case SSFDC4MB: *c=250; *h= 4; *s= 8; break; -+ case SSFDC8MB: *c=250; *h= 4; *s=16; break; -+ case SSFDC16MB: *c=500; *h= 4; *s=16; break; -+ case SSFDC32MB: *c=500; *h= 8; *s=16; break; -+ case SSFDC64MB: *c=500; *h= 8; *s=32; break; -+ case SSFDC128MB: *c=500; *h=16; *s=32; break; -+ default: -+ *c= 0; *h= 0; *s= 0; -+ psm->ErrCode=ERR_NoSmartMedia; -+ return(ERROR); -+ } -+ return(SUCCESS); -+} -+/*************************************************************************** -+ Power Control & Media Exist Check Subroutine -+ ***************************************************************************/ -+ -+int CheckMediaWP(ssfdc_dev *psm) -+{ -+ if(psm->Attribute &MWP) -+ { psm->ErrCode=ERR_WrtProtect; return(ERROR); } -+ return(SUCCESS); -+} -+ -+/*************************************************************************** -+ SmartMedia Physical Address Control Subroutine -+ ***************************************************************************/ -+int ConvMediaAddr(ssfdc_dev *psm, long addr) -+{ -+ long temp; -+ temp =addr/psm->MaxSectors; -+ psm->Sector =addr%psm->MaxSectors; -+ psm->LogBlock=temp%psm->MaxLogBlocks; -+ psm->Zone =temp/psm->MaxLogBlocks; -+ if(psm->Zone<psm->MaxZones) { -+ ClrRedundantData(psm->Redundant); -+ SetLogBlockAddr(psm,psm->Redundant); -+ psm->PhyBlock=psm->Log2Phy[psm->Zone][psm->LogBlock]; -+#if DEBUG_SSFDC_ASSIGNRELEASE -+ printk(KERN_DEBUG "ConvMediaAddr() LogBlock %d -> PhyBlock %d\n", -+ psm->LogBlock, psm->PhyBlock); -+#endif -+ return(SUCCESS); -+ } -+ psm->ErrCode=ERR_OutOfLBA; -+ return(ERROR); -+} -+ -+int IncMediaAddr(ssfdc_dev *psm) -+{ -+ if(++psm->Sector<psm->MaxSectors) -+ return(SUCCESS); -+ psm->Sector=0; -+ if(++psm->LogBlock<psm->MaxLogBlocks) { -+ ClrRedundantData(psm->Redundant); -+ SetLogBlockAddr(psm,psm->Redundant); -+ psm->PhyBlock=psm->Log2Phy[psm->Zone][psm->LogBlock]; -+#if DEBUG_SSFDC_ASSIGNRELEASE -+ printk(KERN_DEBUG "IncMediaAddr() PhyBlock %d <- LogBlock %d\n", -+ psm->PhyBlock, psm->LogBlock); -+#endif -+ return(SUCCESS); -+ } -+ psm->LogBlock=0; -+ if(++psm->Zone<psm->MaxZones) { -+ ClrRedundantData(psm->Redundant); -+ SetLogBlockAddr(psm,psm->Redundant); -+ psm->PhyBlock=psm->Log2Phy[psm->Zone][psm->LogBlock]; -+#if DEBUG_SSFDC_ASSIGNRELEASE -+ printk(KERN_DEBUG "IncMediaAddr() PhyBlock %d <- LogBlock %d\n", -+ psm->PhyBlock, psm->LogBlock); -+#endif -+ return(SUCCESS); -+ } -+ psm->Zone=0; -+ psm->ErrCode=ERR_OutOfLBA; -+ return(ERROR); -+} -+ -+/***************************************************************************/ -+ -+ -+static int WriteReqInCurrBlk(ssfdc_dev *psm, long sector, int *blksector) -+{ -+ long temp; -+ unsigned char Zone; /* Zone Number */ -+ unsigned int LogBlock; /* Logical Block Number of Zone */ -+ -+ if (!psm) -+ return 0; -+ -+ temp = sector / psm->MaxSectors; -+ *blksector = sector % psm->MaxSectors; -+ LogBlock = temp % psm->MaxLogBlocks; -+ Zone = temp / psm->MaxLogBlocks; -+ -+ return (psm->LogBlock == LogBlock && psm->Zone == Zone); -+} -+ -+/*************************************************************************** -+ SmartMedia Read/Write Subroutine with Retry -+ ***************************************************************************/ -+ -+/*************************************************************************** -+ SmartMedia Physical Block Assign/Release Subroutine -+ ***************************************************************************/ -+int AssignWriteBlock(ssfdc_dev *psm, int verbose_flag) -+{ -+ psm->ReadBlock=psm->PhyBlock; -+#if DEBUG_SSFDC_WRITE -+ int Zonesave=psm->Zone, ZoneIndex; -+#endif -+ -+#if DEBUG_SSFDC_WRITE -+ if (verbose_flag) { -+ printk("AssignWriteBlock() verbose mode. psm->Zone %d\n",psm->Zone); -+ for (psm->Zone = 0; psm->Zone < psm->MaxZones; psm->Zone++) { -+ int free_blk=0; -+ printk("\tZone %d, AssignStart %d and ", psm->Zone, psm->AssignStart[psm->Zone]); -+ for (psm->WriteBlock=0; psm->WriteBlock < psm->MaxLogBlocks; psm->WriteBlock++) -+ if (! ChkBit(psm->Assign[psm->Zone],psm->WriteBlock)) ++free_blk; -+ printk("%d free blocks.\n", free_blk); -+ } -+ psm->Zone = Zonesave; -+ } -+#endif -+ for(psm->WriteBlock=psm->AssignStart[psm->Zone]; psm->WriteBlock<psm->MaxBlocks; psm->WriteBlock++) -+ if(! ChkBit(psm->Assign[psm->Zone],psm->WriteBlock)) { -+ SetBit(psm->Assign[psm->Zone],psm->WriteBlock); -+ psm->AssignStart[psm->Zone]=psm->WriteBlock+1; -+ psm->PhyBlock=psm->WriteBlock; -+ psm->SectCopyMode=REQ_ERASE; -+#if DEBUG_SSFDC_ASSIGNRELEASE -+ printk(KERN_DEBUG "AssignWriteBlock() - WriteBlock %d ReadBlock %d LogBlock %d\n", -+ psm->WriteBlock, psm->ReadBlock, psm->LogBlock); -+#endif -+ return(SUCCESS); -+ } -+ for(psm->WriteBlock=0; psm->WriteBlock<psm->AssignStart[psm->Zone]; psm->WriteBlock++) -+ if(! ChkBit(psm->Assign[psm->Zone],psm->WriteBlock)) { -+ SetBit(psm->Assign[psm->Zone],psm->WriteBlock); -+ psm->AssignStart[psm->Zone]=psm->WriteBlock+1; -+ psm->PhyBlock=psm->WriteBlock; -+ psm->SectCopyMode=REQ_ERASE; -+#if DEBUG_SSFDC_ASSIGNRELEASE -+ printk(KERN_DEBUG "AssignWriteBlock() - WriteBlock %d PhyBlock %d LogBlock %d\n", -+ psm->WriteBlock, psm->PhyBlock, psm->LogBlock); -+#endif -+ return(SUCCESS); -+ } -+ psm->WriteBlock=NO_ASSIGN; -+ psm->ErrCode=ERR_WriteFault; -+ return(ERROR); -+} -+ -+/*************************************************************************** -+ SmartMedia Physical Format Check Local Subroutine -+ ***************************************************************************/ -+static int SetPhyFmtValue(ssfdc_dev *psm) -+{ -+ unsigned int idcode; -+ SsfdcReadID(psm, &idcode); -+ if(SetSsfdcModel(psm,(unsigned char)idcode)) -+ return(ERROR); -+ if(CheckSsfdcWP(psm)) -+ psm->Attribute|=WP; -+ return(SUCCESS); -+} -+ -+static int SearchCIS(ssfdc_dev *psm, unsigned int *pcis) -+{ -+ psm->Zone=0; psm->Sector=0; -+ for(psm->PhyBlock=0; psm->PhyBlock<(psm->MaxBlocks-psm->MaxLogBlocks-1); psm->PhyBlock++) { -+ if(SsfdcReadRedtData(psm, psm->Redundant)) -+ { SsfdcReset(psm); return(ERROR); } -+ if(! CheckFailBlock(psm->Redundant)) { -+ if(CheckCisBlock(psm->Redundant)) -+ { SsfdcReset(psm); return(ERROR); } -+ break; -+ } -+ } -+ while(psm->Sector<psm->MaxSectors) { -+ if(psm->Sector) -+ if(SsfdcReadRedtData(psm, psm->Redundant)) -+ { SsfdcReset(psm); return(ERROR); } -+ if(! CheckDataStatus(psm->Redundant)) { -+ if(SsfdcReadSect(psm,psm->WorkBuf,psm->Redundant)) -+ { SsfdcReset(psm); return(ERROR); } -+ if(CheckCISdata(psm->WorkBuf,psm->Redundant)) -+ { SsfdcReset(psm); return(ERROR); } -+ *pcis=psm->PhyBlock; -+ SsfdcReset(psm); -+ return(SUCCESS); -+ } -+ psm->Sector++; -+ } -+ SsfdcReset(psm); -+ return(ERROR); -+} -+ -+/***************************************************************************/ -+static int MakeLogTable(ssfdc_dev *psm, unsigned int start) -+{ -+ unsigned int block; -+ unsigned int blk_total=0, blk_blank=0, blk_nologaddr=0, -+ blk_fail=0, blk_assigned=0; -+ -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "MakeLogTable()\n"); -+#endif -+ psm->DataBuf_Valid = 1; -+ psm->Sector=0; -+ for(psm->Zone=0; psm->Zone<psm->MaxZones; psm->Zone++) { -+ /* set all LogBlocks to NO_ASSIGN */ -+ for(psm->LogBlock=0; psm->LogBlock<psm->MaxLogBlocks; psm->LogBlock++) -+ psm->Log2Phy[psm->Zone][psm->LogBlock]=NO_ASSIGN; -+ /* for all Assigns[zone][PhyBlock] = 0x00 */ -+ for(psm->PhyBlock=0; psm->PhyBlock<(MAX_BLOCKNUM/8); psm->PhyBlock++) -+ psm->Assign[psm->Zone][psm->PhyBlock]=0x00; -+ /*******************************************************************/ -+ for(psm->PhyBlock=0; psm->PhyBlock<psm->MaxBlocks; psm->PhyBlock++) { -+ if((! psm->Zone) && (psm->PhyBlock<start)) { -+ SetBit(psm->Assign[psm->Zone],psm->PhyBlock); -+ continue; -+ } -+ ++blk_total; -+ if(SsfdcReadRedtData(psm,psm->Redundant)) { -+ SsfdcReset(psm); -+#if 0 -+ printk(KERN_ERR "error 1 PhyBlock %d\n", psm->PhyBlock); -+#endif -+ return(ERROR); -+ } -+ if(! CheckDataBlank(psm->Redundant)) { -+ ++blk_blank; -+ continue; -+ } -+ SetBit(psm->Assign[psm->Zone],psm->PhyBlock); -+ if(CheckFailBlock(psm->Redundant)) { -+#if 0 -+ printk("Zone %d, Block %d failed\n", psm->Zone, psm->PhyBlock); -+#endif -+ ++blk_fail; -+ continue; -+ } -+ if(LoadLogBlockAddr(psm)) { -+ ++blk_nologaddr; -+ continue; -+ } -+ if(psm->LogBlock>=psm->MaxLogBlocks) -+ continue; -+ ++blk_assigned; -+ if(psm->Log2Phy[psm->Zone][psm->LogBlock]==NO_ASSIGN) { -+#if DEBUG_SSFDC_ASSIGNRELEASE -+ if (psm->LogBlock == 0) -+ printk(KERN_DEBUG "MakeLogTable() LogBlock %d = PhyBlock %d\n", -+ psm->LogBlock, psm->PhyBlock); -+#endif -+ psm->Log2Phy[psm->Zone][psm->LogBlock]=psm->PhyBlock; -+ continue; -+ } -+ psm->Sector=psm->MaxSectors-1; -+ if(SsfdcReadRedtData(psm,psm->Redundant)) { -+ SsfdcReset(psm); -+#if 0 -+ printk(KERN_ERR "error 2\n"); -+#endif -+ return(ERROR); -+ } -+ psm->Sector=0; -+ block=psm->LogBlock; -+ if(! LoadLogBlockAddr(psm)) -+ if(psm->LogBlock==block) { -+#ifdef L2P_ERR_ERASE /***************************************************/ -+ block=psm->Log2Phy[psm->Zone][psm->LogBlock]; -+ psm->Log2Phy[psm->Zone][psm->LogBlock]=psm->PhyBlock; -+ psm->PhyBlock=block; -+ if(!(psm->Attribute &MWP)) { -+ SsfdcReset(psm); -+ if(SsfdcEraseBlock(psm)) { -+ printk(KERN_ERR "error 3\n"); -+ return(ERROR); -+ } -+ if(SsfdcCheckStatus(psm)) { -+ if(MarkFailPhyOneBlock(psm)) { -+ printk(KERN_ERR "error 4\n"); -+ return(ERROR); -+ } -+ } -+ else ClrBit(psm->Assign[psm->Zone],psm->PhyBlock); -+ } -+ psm->PhyBlock=psm->Log2Phy[psm->Zone][psm->LogBlock]; -+#else /*******************************************************************/ -+ psm->Log2Phy[psm->Zone][psm->LogBlock]=psm->PhyBlock; -+#endif /*******************************************************************/ -+ continue; -+ } -+#ifdef L2P_ERR_ERASE /***************************************************/ -+ if(!(psm->Attribute &MWP)) { -+ SsfdcReset(psm); -+ if(SsfdcEraseBlock(psm)) { -+ printk(KERN_ERR "error 5\n"); -+ return(ERROR); -+ } -+ if(SsfdcCheckStatus(psm)) { -+ if(MarkFailPhyOneBlock(psm)) { -+ printk(KERN_ERR "error 6\n"); -+ return(ERROR); -+ } -+ } -+ else ClrBit(psm->Assign[psm->Zone],psm->PhyBlock); -+ } -+#endif /*******************************************************************/ -+ } -+ psm->AssignStart[psm->Zone]=0; -+ } -+ SsfdcReset(psm); -+#if 0 -+ printk("MakeLogTable()\n"); -+ printk("\t%d failed\n", blk_fail); -+ printk("\t%d blank\n", blk_blank); -+ printk("\t%d assigned\n", blk_assigned); -+ printk("\t%d no logical addr\n", blk_nologaddr); -+ printk("\n\t%d total\n", blk_total); -+ printk("\t%d sum total\n", blk_fail + blk_blank + blk_assigned + blk_nologaddr); -+#endif -+ return(SUCCESS); -+} -+ -+/***************************************************************************/ -+static int MarkFailPhyOneBlock(ssfdc_dev *psm) -+{ -+ unsigned char sect; -+ sect=psm->Sector; -+ SetFailBlock(psm->WorkRedund); -+ SsfdcWriteRedtMode(psm); -+ for(psm->Sector=0; psm->Sector<psm->MaxSectors; psm->Sector++) -+ if(SsfdcWriteRedtData(psm,psm->WorkRedund)) { -+ SsfdcReset(psm); -+ psm->Sector=sect; -+ psm->ErrCode=ERR_HwError; -+ return(ERROR); -+ } /* NO Status Check */ -+ SsfdcReset(psm); -+ psm->Sector=sect; -+ return(SUCCESS); -+} -+ -+/*************************************************************************** -+ SmartMedia Control subroutine -+ Rev 0.30('98-06-30) ***** BETA RELEASE ***** -+ Copyright (c) 1997-98, Toshiba Corporation. All rights reserved. -+ ***************************************************************************/ -+ -+ -+/* Linux Driver Modifications */ -+/* -+dump_ssfdc_state -+*/ -+#if DEBUG_SSFDC -+void dump_ssfdc_state(ssfdc_dev * psm) -+{ -+#if DEBUG_SSFDC_STRUCT -+ // misc structure dump information -+ printk(KERN_DEBUG "psm->\n"); -+ /* unsigned long */ printk(KERN_DEBUG "\t address %x\n", psm->address); -+ /* int */ printk(KERN_DEBUG "\t sm_minor %d\n",psm->sm_minor); -+ /* struct dentry printk(KERN_DEBUG "\t *sm_dentry %x\n",psm->sm_dentry );*/ -+ /* kdev_t */ printk(KERN_DEBUG "\t sm_device %x\n",psm->sm_device); -+ /* int */ printk(KERN_DEBUG "\t sm_flags %x\n",psm->sm_flags); -+ /* unsigned int */ printk(KERN_DEBUG "\t UseCount %d\n",psm->UseCount); -+ /* unsigned int */ printk(KERN_DEBUG "\t ErrCode %d\n",psm->ErrCode); -+ /* unsigned int */ printk(KERN_DEBUG "\t MediaChange %d\n",psm->MediaChange); -+ /* unsigned int */ printk(KERN_DEBUG "\t SectCopyMode %d\n",psm->SectCopyMode); -+ /* unsigned int */ printk(KERN_DEBUG "\t HostCyl %d\n",psm->HostCyl ); -+ /* unsigned char */ printk(KERN_DEBUG "\t HostHead %d\n",psm->HostHead ); -+ /* unsigned char */ printk(KERN_DEBUG "\t HostSect %d\n",psm->HostSect ); -+ /* unsigned int */ printk(KERN_DEBUG "\t ReadBlock %d\n",psm->ReadBlock ); -+ /* unsigned int */ printk(KERN_DEBUG "\t WriteBlock %d\n",psm->WriteBlock ); -+ -+ /* Card attributes */ -+ /* unsigned char */ printk(KERN_DEBUG "\t Model %d\n",psm->Model ); -+ /* unsigned char */ printk(KERN_DEBUG "\t Attribute %x\n",psm->Attribute ); -+ /* unsigned char */ printk(KERN_DEBUG "\t MaxZones %d\n",psm->MaxZones ); -+ /* unsigned char */ printk(KERN_DEBUG "\t MaxSectors %d\n",psm->MaxSectors ); -+ /* unsigned int */ printk(KERN_DEBUG "\t MaxBlocks %d\n",psm->MaxBlocks ); -+ /* unsigned int */ printk(KERN_DEBUG "\t MaxLogBlocks %d\n",psm->MaxLogBlocks ); -+ /* unsigned char */ printk(KERN_DEBUG "\t Zone %d\n",psm->Zone ); -+ /* unsigned char */ printk(KERN_DEBUG "\t Sector %d\n",psm->Sector ); -+ /* unsigned int */ printk(KERN_DEBUG "\t PhyBlock %d\n",psm->PhyBlock ); -+ /* unsigned int */ printk(KERN_DEBUG "\t LogBlock %d\n",psm->LogBlock ); -+#endif -+} -+#endif -+ -+typedef struct { -+ int sm_error; -+ int lnx_error; -+ char *smerrstr; -+} errmap; -+ -+static errmap error_map_table [] = { -+ { NO_ERROR, 0x0000, ""}, -+ { ERR_WriteFault, EIO, "Peripheral Device Write Fault "}, -+ { ERR_HwError, EIO, "Hardware Error"}, -+ { ERR_DataStatus, EIO, "DataStatus Error"}, -+ { ERR_EccReadErr, EIO, "Unrecovered Read Error" }, -+ { ERR_CorReadErr, EIO, "Recovered Read Data with ECC" }, -+ { ERR_OutOfLBA, EIO, "Illegal Logical Block Address" }, -+ { ERR_WrtProtect, EROFS, "Write Protected" }, -+ { ERR_ChangedMedia, EIO, "Medium Changed" }, -+ { ERR_UnknownMedia, EIO, "Incompatible Medium Installed" }, -+ { ERR_IllegalFmt, EIO, "Medium Format Corrupted" }, -+ { ERR_NoSmartMedia, EIO, "Medium Not Present" } -+}; -+ -+static int ssfdc_maperror(int ssfdc_error) { -+ int loopus=0; -+ -+ if (!ssfdc_error) return 0; -+ -+ do { -+ if (error_map_table[loopus].sm_error == ssfdc_error) { -+ printk("%s\n", error_map_table[loopus].smerrstr); -+ return -error_map_table[loopus].lnx_error; -+ } -+ } while (++loopus < (sizeof(error_map_table) / (sizeof(errmap)))); -+ -+ printk(KERN_ERR "%s: error code %d is not mapped, EIO\n", MAJOR_NAME, ssfdc_error); -+ return -EIO; -+} -+ -+static int ssfdc_thread(void * arg) -+{ -+ ssfdc_dev *psm = arg; -+ unsigned long flags; -+ -+ daemonize("sm%dd",psm->sm_minor); -+ -+ spin_lock_irqsave(¤t->sighand->siglock,flags); // _irq -+ sigfillset(¤t->blocked); -+ recalc_sigpending(); -+ spin_unlock_irqrestore(¤t->sighand->siglock,flags); // _irq -+ -+ while (!psm->exiting) { -+ if ( ssfdc_get_request(psm) ) -+ initxfer(psm->sm_minor); -+ -+ spin_lock_irqsave(&psm->req_queue_lock,flags); // _irq -+ // bjm spin_lock(&psm->req_queue_lock); // _irq -+ psm->waiting = 0; -+ spin_unlock_irqrestore(&psm->req_queue_lock,flags); // _irq -+ // bjm spin_unlock(&psm->req_queue_lock); // _irq -+ if (wait_event_interruptible(psm->thread_wq,ssfdc_get_request(psm))) -+ printk("ssfdc_thread() interrupted\n"); -+ // wait_event(psm->thread_wq,ssfdc_get_request(psm)); -+ spin_lock_irqsave(&psm->req_queue_lock,flags); // _irq -+ // bjm spin_lock(&psm->req_queue_lock); // _irq -+ psm->waiting = 1; -+ spin_unlock_irqrestore(&psm->req_queue_lock,flags); // _irq -+ // bjm spin_unlock(&psm->req_queue_lock); // _irq -+ } -+ -+ printk("ssfdcd Exiting!\n"); -+ -+ complete_and_exit(&psm->thread_dead, 0); -+ -+} -+ -+/* -+ssfdc_init_device(ssfdc_dev *, int minor, unsigned long baseaddr, int removable) -+ reset and initialize the ssfdc_dev structure -+*/ -+static int ssfdc_init_device(ssfdc_dev *psm, int minor, unsigned long baseaddr) -+{ -+ int pid; -+ -+ // Establish ssfdc state -+ psm->XferState = xfer_idle; -+ psm->ErrCode = NO_ERROR; -+ psm->MediaChange = SUCCESS; -+ psm->SectCopyMode = COMPLETED; -+ psm->UseCount = 0; -+ psm->DataBuf_Valid = 0; -+ -+ // set minor number -+ psm->sm_minor = minor; -+ // io address -+ psm->address = baseaddr; -+ if (!request_region(psm->address, 3, "sm")) { -+ printk(KERN_ERR "sm: memory already in use!\n"); -+ return ERROR; -+ } -+ spin_lock_init(&psm->req_queue_lock); -+ -+ // thread related inititializations... -+ init_completion(&psm->thread_dead); -+ init_waitqueue_head(&psm->thread_wq); -+ -+ pid = kernel_thread(ssfdc_thread, psm, CLONE_KERNEL); -+ if (pid < 0) -+ printk("ssfdc: ERROR starting thread!\n"); -+ else -+ printk("ssfdc: started kernel thread sm%dd pid %d\n", psm->sm_minor, pid); -+ -+ // switch on power to device, and set basic attributes of card (no logical to phys mapping) -+ if ( ! CntPowerOn(psm) && ! CheckCardExist(psm) ) { -+ SetPhyFmtValue(psm); -+ } -+ else { -+ printk(KERN_ERR "ssfdc_init_device() unable to SetPhyFmtValue()\n"); -+ } -+ -+#if DEBUG_SSFDC -+ dump_ssfdc_state(psm); -+#endif -+ -+ return SUCCESS; -+} -+ -+static int ssfdc_dev_blk_size(ssfdc_dev *psm) -+{ -+ if (!psm) -+ return 0; -+ -+ // because of the physical to logical block mapping, not as many blocks -+ // as expected... -+ switch(psm->Model) { -+ case SSFDC1MB: -+ return (250 * 8 * 512) / SSFDC_BLKSIZE; -+ case SSFDC2MB: -+ return (500 * 8 * 512) / SSFDC_BLKSIZE; -+ case SSFDC4MB: -+ return (500 * 16 * 512) / SSFDC_BLKSIZE; -+ case SSFDC8MB: -+ return (1000 * 16 * 512) / SSFDC_BLKSIZE; -+ case SSFDC16MB: -+ return (1000 * 32 * 512) / SSFDC_BLKSIZE; -+ case SSFDC32MB: -+ return (2000 * 32 * 512) / SSFDC_BLKSIZE; -+ case SSFDC64MB: -+ return (4000 * 32 * 512) / SSFDC_BLKSIZE; -+ case SSFDC128MB: -+ return (8000 * 32 * 512) / SSFDC_BLKSIZE; -+ default: -+ return 0; -+ } -+} -+ -+inline int ssfdc_dev_sectors(ssfdc_dev *psm) { -+ return ssfdc_dev_blk_size(psm) * (SSFDC_BLKSIZE/SSFDC_SECTSIZE); -+} -+ -+static int ssfdc_open(struct inode *in, struct file *fptr) -+{ -+ int error_code=NO_ERROR; -+ ssfdc_dev *psm = in->i_bdev->bd_disk->private_data; -+ unsigned long flags; -+ -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "+ssfdc_open()\n"); -+#endif -+ -+ if (!fptr) { -+ return -EIO; -+ } -+ -+ spin_lock_irqsave(&psm->req_queue_lock,flags); -+ // bjm spin_lock(&psm->req_queue_lock); -+ // Power up smartmedia device, check for card, check media -+ if ((error_code=CntPowerOn(psm))) { -+ printk(KERN_ERR "%s PowerUP error\n", MAJOR_NAME); -+ } -+ else if ((error_code=CheckCardExist(psm))) {// Check the existence of a card -+ printk(KERN_ERR "%s No Card!\n", MAJOR_NAME); -+ } -+ else if ( ! psm->UseCount++ ) { -+ spin_unlock_irqrestore(&psm->req_queue_lock,flags); -+ // bjm spin_unlock(&psm->req_queue_lock); -+ check_disk_change(in->i_bdev); -+ spin_lock_irqsave(&psm->req_queue_lock,flags); -+ // bjm spin_lock(&psm->req_queue_lock); -+ } -+ -+ if ( ! psm->ErrCode ) { -+ // check our open mode against that of removable media's -+ if (WRITE_PROTECTED(psm)) { -+ printk(KERN_ERR "mount read only detected.\n"); -+ } -+ } -+ -+#if DEBUG_SSFDC -+ dump_ssfdc_state(psm); -+ printk(KERN_DEBUG "-ssfdc_open() error_code %d\n", error_code); -+#endif -+ -+ spin_unlock_irqrestore(&psm->req_queue_lock,flags); -+ -+#if DEBUG_SSFDC -+ printk("-ssfdc_open()\n"); -+#endif -+ -+ return ssfdc_maperror(error_code); -+} -+ -+static int ssfdc_release(struct inode *i_node, struct file *fptr) -+{ -+ int drive; -+ ssfdc_dev *psm=NULL; -+ unsigned long flags; -+ -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "+ssfdc_release("); -+#endif -+ -+ psm = (ssfdc_dev *) i_node->i_bdev->bd_disk->private_data; -+ drive = psm->sm_minor; -+ -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "%d)\n", drive); -+#endif -+ if (drive < 0 || drive >= MAX_SSFDC) -+ return -ENODEV; -+ -+ spin_lock_irqsave(&psm->req_queue_lock,flags); -+ // bjm spin_lock(&psm->req_queue_lock); -+ -+ if (!psm->UseCount) -+ printk(KERN_ERR "sm: Zero use count!\n"); -+ else { -+ --psm->UseCount; -+ } -+ -+#if DEBUG_SSFDC -+ dump_ssfdc_state(psm); -+#endif -+ -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "-ssfdc_release()\n"); -+#endif -+ -+ spin_unlock_irqrestore(&psm->req_queue_lock,flags); -+ // bjm spin_unlock(&psm->req_queue_lock); -+ -+ return 0; -+} -+ -+static int ssfdc_ioctl(struct inode *i_node, struct file *fptr, unsigned cmd, unsigned long arg) -+{ -+ int err, drive, int_val; -+ unsigned char heads, sectors; -+ unsigned int cylinders; -+ struct hd_geometry geo; -+ ssfdc_dev *psm; -+ -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "ssfdc_ioctl(%d)", cmd); -+#endif -+ -+ if (i_node == NULL) -+ return -EINVAL; -+ -+ psm = (ssfdc_dev *) i_node->i_bdev->bd_disk->private_data; -+ drive = psm->sm_minor; -+ -+ if (drive < 0 || drive >= MAX_SSFDC) -+ return -ENODEV; -+ switch(cmd) { -+ case BLKROSET: /* set device read-only (0 = read-write) */ -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EACCES; -+ if (copy_from_user((void *) &int_val, (int *)arg, sizeof(int_val))) -+ return -EFAULT; -+ if (int_val) -+ psm->Attribute |= MWP; -+ else -+ psm->Attribute &= ~MWP; -+ return 0; -+ -+ case BLKROGET:/* get read-only status (0 = read_write) */ -+ int_val = psm->Attribute & MWP; -+ copy_to_user(arg, (void *) &int_val, sizeof(int_val)); -+ return 0; -+ -+ /* case BLKRRPART: */ /* re-read partition table */ -+ -+ case BLKGETSIZE: -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "BLKGETSIZE"); -+#else -+ printk(KERN_DEBUG "ssfdc_ioctl(BLKGETSIZE) not handled.\n"); -+#endif -+ break; -+ -+ case HDIO_GETGEO: -+ if ((void *) arg == NULL) return -EINVAL; -+ if (!access_ok(VERIFY_WRITE, (void __user *)arg, sizeof(geo))) -+ return -EFAULT; -+ if ((err=CheckLogCHS( psm, &cylinders, &heads, §ors))) -+ return ssfdc_maperror(err); -+ memset(&geo, 0, sizeof(geo)); -+ geo.cylinders = cylinders; -+ geo.heads = heads; -+ geo.sectors = sectors; -+ geo.start = get_start_sect(i_node->i_bdev); -+ if (copy_to_user((void *) arg, &geo, sizeof(geo))) -+ return -EFAULT; -+ if (copy_to_user((void *) arg, &geo, sizeof(geo))) -+ return -EFAULT; -+ return 0; -+ } -+ return -EINVAL; -+} -+ -+ -+ -+static int ssfdc_revalidate(struct gendisk *disk) -+{ -+ unsigned int cis; -+ ssfdc_dev *psm=NULL; -+ int error_code=NO_ERROR; -+ unsigned long flags; -+ -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "ssfdc_revalidate()\n"); -+#endif -+ -+ psm = disk->private_data; -+ -+ spin_lock_irqsave(&psm->req_queue_lock,flags); -+ // bjm spin_lock(&psm->req_queue_lock); -+ -+ if ( ! psm->DataBuf_Valid ) { -+ if ((error_code=SetPhyFmtValue(psm))) -+ printk(KERN_ERR "ssfdc_revalidate() SetPhyFmtValue error\n"); -+ else if ((error_code=SearchCIS(psm,&cis))) -+ printk(KERN_ERR "ssfdc_revalidate() SearchCIS error\n"); -+ else if ((error_code=MakeLogTable(psm,cis+1))) -+ printk(KERN_ERR "ssfdc_revalidate() MakeLogTable error\n"); -+ } -+ spin_unlock_irqrestore(&psm->req_queue_lock,flags); -+ // bjm spin_unlock(&psm->req_queue_lock); -+ -+ return ssfdc_maperror(error_code); -+} -+ -+int __init ssfdc_init(void) -+{ -+ int i; -+ int err = 0; -+ -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "+ssfdc_init()\n"); -+#endif -+ -+ memset(disks, 0, sizeof(struct gendisk *) * MAX_SSFDC); -+ memset(ssfdc, 0, sizeof(struct ssfdc_dev *) * MAX_SSFDC); -+ for (i=0; i<MAX_SSFDC; ++i) { -+ disks[i] = alloc_disk(1 << SSFDC_PARTN_BITS); -+ ssfdc[i] = kmalloc(sizeof(ssfdc_dev), GFP_KERNEL); -+ if (!disks[i] || !ssfdc[i]) { -+ err = -ENOMEM; -+ goto no_memory_error; -+ } -+ memset( ssfdc[i], 0, sizeof(ssfdc_dev)); -+ } -+ -+ if (register_blkdev(SSFDC_MAJOR, "smartmedia")) { -+ printk(KERN_ERR "Unable to get major number %d for ssfdc device\n", -+ SSFDC_MAJOR); -+ err = -EBUSY; -+ goto busy_error; -+ } -+ -+ for ( i=0; i < MAX_SSFDC; ++i) { -+ disks[i]->major = SSFDC_MAJOR; -+ disks[i]->first_minor = i << SSFDC_PARTN_BITS; -+ disks[i]->fops = &ssfdc_fops; -+ sprintf(disks[i]->disk_name, "sm%d", i); -+ disks[i]->private_data = ssfdc[i]; -+ ssfdc_init_device(ssfdc[i], i << SSFDC_PARTN_BITS, -+ CPLD_BASE_ADDRESS + SMART_MEDIA_ONE_OFFSET); -+ -+ disks[i]->queue = ssfdc[i]->req_queue = -+ blk_init_queue(do_ssfdc_request, &ssfdc[i]->req_queue_lock); -+ ssfdc[i]->req_queue->queuedata = ssfdc[i]; -+ -+ set_capacity(disks[i], ssfdc_dev_sectors(ssfdc[i])); -+ // bjm blk_queue_max_sectors(disks[i]->queue, 32); -+ // bjm blk_queue_max_phys_segments(disks[i]->queue, 4); -+ blk_queue_max_segment_size(disks[i]->queue, (ssfdc[i]->MaxSectors / 2) * K_BYTE); -+ add_disk(disks[i]); -+ } -+ -+#if 0 // bjm debug -+#ifndef CONFIG_SH_NIMBLE_MINI -+ mediachangetest(0L); -+#else -+ mediachangetest(1L); -+#endif -+#endif // bjm debug -+ -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "-ssfdc_init(0)\n"); -+#endif -+ return 0; -+ -+busy_error: -+no_memory_error: -+ for (i=0; i < MAX_SSFDC; ++i) { -+ if (disks[i] && disks[i]->queue) -+ kfree(disks[i]->queue); -+ put_disk(disks[i]); -+ if (ssfdc[i]) -+ kfree(ssfdc[i]); -+ } -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG "-ssfdc_init(%d)\n", -ENOMEM); -+#endif -+ return -ENOMEM; -+} -+ -+void __init ssfdc_clean(void) -+{ -+ int i; -+ -+ printk(KERN_DEBUG "SSFDC exit code\n"); -+ -+ for (i=0; i < MAX_SSFDC; ++i) { -+ if (disks[i] != NULL) { -+ blk_cleanup_queue(disks[i]->queue); -+ del_gendisk(disks[i]); -+ put_disk(disks[i]); -+ } -+ -+ if (ssfdc[i]) { -+ // signal thread to exit... -+ ssfdc[i]->exiting = 1; -+ wake_up(&ssfdc[i]->thread_wq); -+ wait_for_completion(&ssfdc[i]->thread_dead); -+ -+ if (ssfdc[i]->address) -+ release_region(ssfdc[i]->address, 3); -+ kfree(ssfdc[i]); -+ } -+ } -+ -+ if (unregister_blkdev(SSFDC_MAJOR, "smartmedia")) -+ printk(KERN_WARNING "smartmedia: cannot unregister blkdev\n"); -+} -+ -+#if DEBUG_SSFDC -+void dump_request(struct request *req) -+{ -+#if DEBUG_SSFDC_REQUEST && DEBUG_SSFDC_REQUEST -+ printk(KERN_DEBUG "req->\n"); -+ /* int */ printk(KERN_DEBUG "\t req->cmd %x\n", req->cmd); /* READ or WRITE */ -+ /* int errors */ printk(KERN_DEBUG "\t req->errors %d\n", req->errors); -+ /* unsigned long */ printk(KERN_DEBUG "\t req->sector %d\n", req->sector); -+ /* unsigned long */ printk(KERN_DEBUG "\t req->nr_sectors %d\n",req->nr_sectors); -+ /* unsigned long */ printk(KERN_DEBUG "\t req->hard_sector %d\n", req->hard_sector); -+ /* unsigned int */ printk(KERN_DEBUG "\t req->nr_hw_segments %d\n",req->nr_hw_segments); -+ /* unsigned long */ printk(KERN_DEBUG "\t req->current_nr_sectors %d\n",req->current_nr_sectors); -+ -+#endif -+} -+#endif -+ -+void do_ssfdc_request(request_queue_t * rq) -+{ -+ ssfdc_dev *psm = rq->queuedata; -+ -+ if ( ! psm->waiting ) -+ wake_up(&psm->thread_wq); -+} -+ -+static struct request * ssfdc_get_request(ssfdc_dev *psm) -+{ -+ struct request *treq; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&psm->req_queue_lock, flags); -+ // bjm spin_lock(&psm->req_queue_lock); -+ treq = elv_next_request(psm->req_queue); -+ spin_unlock_irqrestore(&psm->req_queue_lock, flags); -+ // bjm spin_unlock(&psm->req_queue_lock); -+ -+ return treq; -+} -+ -+static void ssfdc_terminate_request(ssfdc_dev *psm, struct request *req) -+{ -+ unsigned long flags; -+ -+ if (psm && req) { -+ spin_lock_irqsave(&psm->req_queue_lock, flags); -+ // bjm spin_lock(&psm->req_queue_lock); -+ end_request(req,0); -+ spin_unlock_irqrestore(&psm->req_queue_lock, flags); -+ // bjm spin_unlock(&psm->req_queue_lock); -+ } -+} -+ -+ -+static int ssfdc_end_request(ssfdc_dev *psm, struct request *req, int status) -+{ -+ unsigned long flags; -+ -+ if (!psm || !req) { -+ printk(KERN_DEBUG "ssfdc_end_request() NULL psm or req!\n"); -+ return 0; -+ } -+ -+#if DEBUG_SSFDC_REQUEST -+ printk("ssfdc_end_request(%p)\n", req); -+#endif -+ -+ spin_lock_irqsave(&psm->req_queue_lock,flags); -+ // bjm spin_lock(&psm->req_queue_lock); -+ end_request(req,status); -+ spin_unlock_irqrestore(&psm->req_queue_lock,flags); -+ // bjm spin_unlock(&psm->req_queue_lock); -+ return 0; -+} -+ -+void initxfer(unsigned long dev_idx) -+{ -+ ssfdc_dev *psm = ssfdc[dev_idx]; -+ struct request *req; -+ int error_code; -+ unsigned int cis; -+ -+#if DEBUG_SSFDC -+ // printk(KERN_DEBUG "+initxfer(%d)", dev_idx); -+#endif -+ // get device lock, and check idle flag, setting if not busy -+ -+ req = ssfdc_get_request(psm); -+ -+ // if the device is idle, setup a read or write operation -+ if (psm->XferState == xfer_idle) { -+ // get the current request from our device's request list. -+ if (!req) { -+#if DEBUG_SSFDC -+// printk(KERN_DEBUG "initxfer() terminate, no schedule.\n"); -+#endif -+ } -+ // Absence of power indicates absence of card. -+ // terminate request and exit... -+ if ( ! _HwChkPower(psm) ) { -+ printk(KERN_DEBUG "initxfer() - Media power NOT!\n"); -+ ssfdc_terminate_request(psm,req); -+ return; -+ } -+ -+ // We have a request and we have a card. Is the Log2Phys mapping still valid? -+ if ( ! psm->DataBuf_Valid ) { -+ if ((error_code = SetPhyFmtValue(psm))) -+ printk(KERN_DEBUG "%s SetPhyFmtValue error\n", MAJOR_NAME); -+ else if ((error_code = SearchCIS(psm,&cis))) -+ printk(KERN_DEBUG "%s SearchCIS error\n", MAJOR_NAME); -+ else if ((error_code = MakeLogTable(psm,cis+1))) -+ printk(KERN_DEBUG "%s MakeLogTable error\n", MAJOR_NAME); -+ if (error_code) { -+ printk(KERN_DEBUG "%s error %d\n", MAJOR_NAME, error_code); -+ ssfdc_terminate_request(psm,req); -+ return; -+ } -+ } -+ -+ psm->XferState = xfer_busy; -+#if DEBUG_SSFDC -+ printk(KERN_DEBUG " initxfer() - do the request %x\n", req); -+#endif -+ ssfdc_rw_request(psm, req); -+ } -+#if DEBUG_SSFDC -+ else { -+ printk(KERN_DEBUG "initxfer(%d) dev is busy, no reschedule.\n", dev_idx); -+ } -+#endif -+ -+} -+ -+ -+void ssfdc_rw_request(ssfdc_dev *psm, struct request *req) -+{ -+ int (*rwsector)(ssfdc_dev *, struct request *, char *, long, int); -+ unsigned sector, count; -+ int rw_return=1; -+ -+ if (rq_data_dir(req) == WRITE) -+ rwsector = MediaWriteSector; -+ else if (rq_data_dir(req) == READ) -+ rwsector = MediaReadSector; -+ else { -+ printk(KERN_DEBUG "%s: command %d not implemented!\n", MAJOR_NAME, (int) rq_data_dir(req)); -+ goto terminal_error; -+ } -+ -+ /* -+ */ -+ sector = req->sector; -+ count = req->nr_sectors; -+ -+ // check that the request does not extend past ssfdc's max size -+ if ( (sector + count) > ssfdc_dev_sectors(psm) ) { -+ printk(KERN_ERR "Attempt to read past end of device!"); -+ goto terminal_error; -+ } -+ else { -+ -+ // for each segment in each bio_vec R/W from/to device. -+ -+ count = req->current_nr_sectors; -+ rw_return = rwsector(psm, req, req->buffer, sector, count); -+ -+ if (rq_data_dir(req) == READ) -+ ssfdc_end_request(psm, req, rw_return); -+ } -+ -+ // things appear OK... -+ return; -+ -+terminal_error: -+ ssfdc_terminate_request( psm, req); -+ psm->XferState = xfer_idle; -+} -+ -+module_init(ssfdc_init); -+module_exit(ssfdc_clean); -+ -+MODULE_LICENSE("GPL"); -+ -+/* End of Linux Driver Modifications */ -diff --git a/drivers/block/ssfdc.h b/drivers/block/ssfdc.h -new file mode 100644 -index 0000000..06f4a3c ---- /dev/null -+++ b/drivers/block/ssfdc.h -@@ -0,0 +1,372 @@ -+/* $id: $ */ -+#ifndef _SSFDC_H -+#define _SSFDC_H -+ -+/* -+ Linux related defines -+*/ -+ -+#ifdef CONFIG_SH_NIMBLE_MINI -+#define MAX_SSFDC 2 /* two drives */ -+#else -+#define MAX_SSFDC 1 /* only one drive */ -+#endif -+ -+#define SSFDC_MAJOR_NAME "sm" -+#define MAJOR_NAME SSFDC_MAJOR_NAME -+#define SSFDC_PARTN_BITS 4 /* number of minor dev bits for partitions */ -+#define PARTN_MASK ((1<<SSFDC_PARTN_BITS)-1) /* a useful bit mask */ -+#define MAX_DRIVES MAX_SSFDC -+ -+/*************************************************************************** -+ SmartMedia Controll Header -+ Rev 0.30('98-06-30) ***** BETA RELEASE ***** -+ Copyright (c) 1997-98, Toshiba Corporation. All rights reserved. -+ ***************************************************************************/ -+ -+/*************************************************************************** -+ Define Difinetion -+ ***************************************************************************/ -+#define SUCCESS 0 /* SUCCESS */ -+#define ERROR -1 /* ERROR */ -+#define CORRECT 1 /* CORRECTABLE */ -+ -+/***************************************************************************/ -+#define NO_ERROR 0x0000 /* NO ERROR */ -+#define ERR_WriteFault 0x0003 /* Peripheral Device Write Fault */ -+#define ERR_HwError 0x0004 /* Hardware Error */ -+#define ERR_DataStatus 0x0010 /* DataStatus Error */ -+#define ERR_EccReadErr 0x0011 /* Unrecovered Read Error */ -+#define ERR_CorReadErr 0x0018 /* Recovered Read Data with ECC */ -+#define ERR_OutOfLBA 0x0021 /* Illegal Logical Block Address */ -+#define ERR_WrtProtect 0x0027 /* Write Protected */ -+#define ERR_ChangedMedia 0x0028 /* Medium Changed */ -+#define ERR_UnknownMedia 0x0030 /* Incompatible Medium Installed */ -+#define ERR_IllegalFmt 0x0031 /* Medium Format Corrupted */ -+#define ERR_NoSmartMedia 0x003A /* Medium Not Present */ -+ -+/*************************************************************************** -+ Common Controll Header -+ Rev 1.30('98-06-30) ***** BETA RELEASE ***** -+ Copyright (c) 1997-98, Toshiba Corporation. All rights reserved. -+ ***************************************************************************/ -+ -+/*************************************************************************** -+ SmartMedia Controller Definition -+ ***************************************************************************/ -+/* I/O Mode Address */ -+#define DATA(p) (p->address+0x00) /* R/W Data Reg */ -+#define STATUS(p) (p->address+0x02) /* R/- Status Reg */ -+#define MODE(p) (p->address+0x02) /* -/W Mode Reg */ -+ -+/* Controller Status Reg (Read Only) */ -+#define STS_BUSY 0x80 -+#define STS_VCC 0x10 -+#define STS_SCHG 0x08 -+#define STS_WP 0x01 -+#define STS_CENB 0x04 -+ -+#ifdef CONFIG_SH_TITAN -+/* Controller Mode Reg (Write Only) */ -+/* keep PCI clock running on bit 3 */ -+/* CE# on bit 2, CLE on bit 1 and ALE on bit 0 */ -+#define STANDBY (0x00 | 0x00 | 0x08) -+#define WR_DATA (0x00 | 0x04 | 0x08) -+#define WR_CMD (0x02 | 0x04 | 0x08) -+#define WR_ADR (0x01 | 0x04 | 0x08) -+#else -+/* Controller Mode Reg (Write Only) */ -+#define STANDBY 0x00 -+#define WR_DATA 0x10 -+#define WR_CMD 0x11 -+#define WR_ADR 0x12 -+#define PW_OFF 0x80 -+#define PW_ON 0x88 -+#endif -+ -+/***************************************************************************/ -+#define _HwSetData(p) ctrl_outb(WR_DATA,MODE(p)) -+#define _HwSetCmd(p) ctrl_outb(WR_CMD,MODE(p)) -+#define _HwSetAddr(p) ctrl_outb(WR_ADR,MODE(p)) -+#define _HwSetStandby(p) ctrl_outb(STANDBY,MODE(p)) -+ -+#define _HwInData(p) ctrl_inb(DATA(p)) -+#define _HwOutData(p,a) ctrl_outb((a),DATA(p)) -+ -+#ifdef CONFIG_SH_TITAN -+#define _HwVccOn(p) -+#define _HwVccOff(p) -+#else -+#define _HwVccOn(p) ctrl_outb(PW_ON,MODE(p)) -+#define _HwVccOff(p) ctrl_outb(PW_OFF,MODE(p)) -+#endif -+ -+#ifdef CONFIG_SH_TITAN -+#define _HwChkCardIn(p) (1) -+#define _HwChkStatus(p) (0) -+#define _HwChkWP(p) (0) -+#define _HwChkPower(p) (1) -+#define _HwChkBusy(p) (ctrl_inb(STATUS(p))&STS_BUSY) -+ -+#else -+ -+#define _HwChkCardIn(p) (ctrl_inb(STATUS(p))&STS_CENB) -+#define _HwChkStatus(p) (ctrl_inb(STATUS(p))&(STS_SCHG)) -+#define _HwChkWP(p) (ctrl_inb(STATUS(p))&(STS_WP)) -+#define _HwChkPower(p) (ctrl_inb(STATUS(p))&(STS_VCC)) -+#define _HwChkBusy(p) (ctrl_inb(STATUS(p))&STS_BUSY) -+ -+#endif -+ -+#define _HwRdStatus(p) (ctrl_inb(STATUS(p))) -+/***************************************************************************/ -+#ifdef CONFIG_SH_NIMBLE_MINI -+#define CPLD_BASE_ADDRESS 0xB4030000L -+#define SMART_MEDIA_ONE_OFFSET 0x08 // The "built-in" SmartMedia -+#define SMART_MEDIA_TWO_OFFSET 0x00 // The "removable" SmartMedia -+#elif CONFIG_SH_TITAN -+#define CPLD_BASE_ADDRESS 0xA4000000L -+#define SMART_MEDIA_ONE_OFFSET 0x00 -+#else -+#define CPLD_BASE_ADDRESS 0xB8030000L -+#define SMART_MEDIA_ONE_OFFSET 0x00 // The "built-in" SmartMedia -+#endif -+ -+/*************************************************************************** -+ Program & Macro for SmartMedia Controller -+ Rev 0.30('98-06-30) ***** BETA RELEASE ***** -+ Copyright (c) 1997-98, Toshiba Corporation. All rights reserved. -+ ***************************************************************************/ -+/*************************************************************************** -+ Define Definition -+ ***************************************************************************/ -+#define K_BYTE 1024 /* Kilo Byte */ -+#define SSFDC_SECTSIZE 512 /* Sector buffer size */ -+#define SSFDC_BLKSIZE (K_BYTE * 4) -+#define REDTSIZE 16 /* Redundant buffer size */ -+ -+/***************************************************************************/ -+#define DUMMY_DATA 0xFF /* No Assign Sector Read Data */ -+ -+/*************************************************************************** -+ Max Zone/Block/Sectors Data Definition -+ ***************************************************************************/ -+#define MAX_ZONENUM 0x08 /* Max Zone Numbers in a SmartMedia */ -+#define MAX_BLOCKNUM 0x0400 /* Max Block Numbers in a Zone */ -+#define MAX_SECTNUM 0x20 /* Max Sector Numbers in a Block */ -+#define MAX_LOGBLOCK 1000 /* Max Logical Block Numbers in a Zone */ -+ -+/*************************************************************************** -+ Logical to Physical Block Table Data Definition -+ ***************************************************************************/ -+#define NO_ASSIGN 0xFFFF /* No Assign Logical Block Address */ -+ -+/*************************************************************************** -+ 'SectCopyMode' Data -+ ***************************************************************************/ -+#define COMPLETED 0 /* Sector Copy Completed */ -+#define REQ_ERASE 1 /* Request Read Block Erase */ -+#define REQ_FAIL 2 /* Request Read Block Failed */ -+ -+/*************************************************************************** -+ Retry Counter Definition -+ ***************************************************************************/ -+#define RDERR_REASSIGN 1 /* Reassign with Read Error */ -+#define L2P_ERR_ERASE 1 /* BlockErase for Contradicted L2P Table */ -+ -+/*************************************************************************** -+ SmartMedia Command & Status Definition -+ ***************************************************************************/ -+/* SmartMedia Command */ -+#define SSFDC_WRDATA 0x80 -+#define SSFDC_READ 0x00 -+#define SSFDC_READ_REDT 0x50 -+#define SSFDC_READ1 0x00 -+#define SSFDC_READ2 0x01 -+#define SSFDC_READ3 0x50 -+#define SSFDC_RST_CHIP 0xFF -+#define SSFDC_WRITE 0x10 -+#define SSFDC_DUMMY_WRITE 0x11 -+#define SSFDC_MULTI_WRITE 0x15 -+#define SSFDC_ERASE1 0x60 -+#define SSFDC_ERASE2 0xD0 -+#define SSFDC_RDSTATUS 0x70 -+#define SSFDC_READ_ID 0x90 -+ -+/* SmartMedia Status */ -+#define WR_FAIL 0x01 /* 0:Pass, 1:Fail */ -+#define SUSPENDED 0x20 /* 0:Not Suspended, 1:Suspended */ -+#define READY 0x40 /* 0:Busy, 1:Ready */ -+#define WR_PRTCT 0x80 /* 0:Protect, 1:Not Protect */ -+ -+#define USEC 1 -+#define MSEC 1000 * USEC -+#define JIFFY_TICK_MS (MSEC / HZ) -+ -+// #define BUSY_PROG 20 * MSEC /* 200-1000us ----- Program Time */ -+#define BUSY_PROG 1000 * USEC /* 200-1000us ----- Program Time */ -+#define BUSY_DUMMY_WRITE 10 * USEC /* 2-10us dummy write */ -+#define BUSY_MULTI_WRITE 1000 * USEC /* 200 - 1000 usec */ -+#define BUSY_ERASE 10 * MSEC /* 2-10ms ----- Block Erase Time */ -+#define BUSY_READ 100 * USEC /* tR : 100us ----- Data transfer Time */ -+#define BUSY_RESET 10 * USEC /* tRST : 10us ----- Device Resetting Time */ -+#define BUSY_ADDR_SET 25 * USEC -+ -+#define TIME_PON 30 /* 300ms ------ Power On Wait Time */ -+#define TIME_CDCHK 2 /* 20ms ------ Card Check Interval Timer */ -+#define TIME_WPCHK 1 /* 5ms ------ WP Check Interval Timer */ -+ -+/* Power On Timeout */ -+#define POWER_ON_TIMEOUT (HZ*2) -+ -+/* Default retry limit for Read/Write */ -+#define RD_RETRY_LIMIT 3 -+#define WR_RETRY_LIMIT 4 -+#define BLOCK_READ_RETRY_LIMIT 2 -+#define BLOCK_WRITE_RETRY_LIMIT 3 -+#define REASSIGN_RETRY_LIMIT 4 -+ -+/*************************************************************************** -+ Redundant Data -+ ***************************************************************************/ -+#define REDT_DATA 0x04 -+#define REDT_BLOCK 0x05 -+ -+#define REDT_ADDR1H 0x06 -+#define REDT_ADDR1L 0x07 -+#define REDT_ADDR2H 0x0B -+#define REDT_ADDR2L 0x0C -+ -+#define REDT_ECC10 0x0D -+#define REDT_ECC11 0x0E -+#define REDT_ECC12 0x0F -+ -+#define REDT_ECC20 0x08 -+#define REDT_ECC21 0x09 -+#define REDT_ECC22 0x0A -+ -+/*************************************************************************** -+ SmartMedia Model & Attribute -+ ***************************************************************************/ -+/* SmartMedia Attribute */ -+#define NOWP 0x00 /* 0... .... No Write Protect */ -+#define WP 0x80 /* 1... .... Write Protected */ -+#define MASK 0x00 /* .00. .... NAND MASK ROM Model */ -+#define FLASH 0x20 /* .01. .... NAND Flash ROM Model */ -+#define AD3CYC 0x00 /* ...0 .... Address 3-cycle */ -+#define AD4CYC 0x10 /* ...1 .... Address 4-cycle */ -+#define BS16 0x00 /* .... 00.. 16page/block */ -+#define BS32 0x04 /* .... 01.. 32page/block */ -+#define PS256 0x00 /* .... ..00 256byte/page */ -+#define PS512 0x01 /* .... ..01 512byte/page */ -+ -+#define MWP 0x80 /* WriteProtect mask */ -+#define MFLASH 0x60 /* Flash Rom mask */ -+#define MADC 0x10 /* Address Cycle */ -+#define MBS 0x0C /* BlockSize mask */ -+#define MPS 0x03 /* PageSize mask */ -+ -+/* SmartMedia Model */ -+#define NOSSFDC 0x00 /* NO SmartMedia */ -+#define SSFDC1MB 0x01 /* 1MB SmartMedia */ -+#define SSFDC2MB 0x02 /* 2MB SmartMedia */ -+#define SSFDC4MB 0x03 /* 4MB SmartMedia */ -+#define SSFDC8MB 0x04 /* 8MB SmartMedia */ -+#define SSFDC16MB 0x05 /* 16MB SmartMedia */ -+#define SSFDC32MB 0x06 /* 32MB SmartMedia */ -+#define SSFDC64MB 0x07 /* 64MB SmartMedia */ -+#define SSFDC128MB 0x08 /*128MB SmartMedia */ -+ -+#define EVEN 0 /* Even Page for 256byte/page */ -+#define ODD 1 /* Odd Page for 256byte/page */ -+ -+/*************************************************************************** -+ Struct Definition -+ ***************************************************************************/ -+/* Linux kernel additions */ -+ -+/* device buffer xfer status */ -+typedef enum { xfer_idle, xfer_busy} xfer_states; -+ -+/* Smartmedia device structure */ -+typedef struct { -+ unsigned long address; -+ int sm_minor; -+ int sm_flags; -+ int busy; -+ int waiting; -+ -+ /* queue of io requests for the device */ -+ spinlock_t req_queue_lock; -+ request_queue_t *req_queue; -+ -+ /* our thread related parameters */ -+ struct completion thread_dead; -+ int exiting; -+ wait_queue_head_t thread_wq; -+ -+ /* accounting variables for each buffer io operation -+ each request may have a chain of buffers, each of -+ which may require I/O of multiple sectors */ -+ unsigned int ReqSectorSize; -+ unsigned int BufIndex; -+ unsigned int SectorWriteIndex; -+ -+ /* CHS parameters */ -+ unsigned int HostCyl; -+ unsigned char HostHead; -+ unsigned char HostSect; -+ -+ /* State Information */ -+ xfer_states XferState; -+ unsigned int UseCount; -+ unsigned int RetryCount; -+ unsigned int ErrCode; -+ unsigned int MediaChange; -+ unsigned int CardPresent; -+ unsigned int SectCopyMode; -+ -+ /* Working Databuf Area */ -+ unsigned char SectBuf[SSFDC_SECTSIZE]; -+ unsigned char WorkBuf[SSFDC_SECTSIZE]; -+ unsigned char Redundant[REDTSIZE]; -+ unsigned char WorkRedund[REDTSIZE]; -+ unsigned int DataBuf_Valid; -+ unsigned int Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK]; -+ unsigned char Assign[MAX_ZONENUM][MAX_BLOCKNUM/8]; -+ unsigned int AssignStart[MAX_ZONENUM]; -+ unsigned int ReadBlock; -+ unsigned int WriteBlock; -+ -+ /* Card attributes */ -+ unsigned char Model; -+ unsigned char Attribute; -+ unsigned char MaxZones; -+ unsigned char MaxSectors; -+ unsigned int MaxBlocks; -+ unsigned int MaxLogBlocks; -+ -+ /* Address of current access (Media) */ -+ unsigned char Zone; /* Zone Number */ -+ unsigned char Sector; /* Sector(512byte) Number on Block */ -+ unsigned int PhyBlock; /* Physical Block Number on Zone */ -+ unsigned int LogBlock; /* Logical Block Number of Zone */ -+ -+ /* device statistics */ -+ unsigned int Sector_reads; -+ unsigned int Sector_writes; -+ unsigned int Sect_rd_errs_ttl; -+ unsigned int Sect_wr_errs_ttl; -+ unsigned int Bad_blks_rd; -+ unsigned int Bad_blks_wr; -+ unsigned int Bad_blks_erase; -+} ssfdc_dev; -+ -+ -+/****************************************************************************/ -+/* Handy defines */ -+/****************************************************************************/ -+#define WRITE_PROTECTED(p) (p->Attribute & WP) -+ -+/* End of Linux kernel additions */ -+#endif /* #ifndef _SSFDC_H */ diff --git a/packages/linux/linux-titan-sh4/titan-pcibios-scan-update.patch b/packages/linux/linux-titan-sh4/titan-pcibios-scan-update.patch deleted file mode 100644 index 9324ba4cc2..0000000000 --- a/packages/linux/linux-titan-sh4/titan-pcibios-scan-update.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- linux-2.6.17/include/asm-sh/pci.h.orig 2006-07-27 10:17:30.000000000 +1000 -+++ linux-2.6.17/include/asm-sh/pci.h 2006-07-27 10:21:53.000000000 +1000 -@@ -143,6 +143,19 @@ - /* generic pci stuff */ - #include <asm-generic/pci.h> - -+#ifdef CONFIG_SH_TITAN -+/* -+ * With the updated BIOS the RTL8139D is function 1 while the -+ * mini-pci card is function 0 of the RTL8139D. This is a feature -+ * which enables more pci bus-master inputs than are available by -+ * using a bus-master sharing feature of the RTL8139D. Without this -+ * patch the RTL8139D isn't detected when no mini-pci card is -+ * inserted. -+ */ -+#undef pcibios_scan_all_fns -+#define pcibios_scan_all_fns(a, b) ((b)?0:1) -+#endif -+ - /* generic DMA-mapping stuff */ - #include <asm-generic/pci-dma-compat.h> - |