From 126bb03b461c2f03f2d2a43b9a587941bf146e0e Mon Sep 17 00:00:00 2001 From: Al Cho Date: Wed, 8 Sep 2010 00:42:32 -0700 Subject: Staging: add USB ENE card reader driver This driver is for the ENE card reader that can be found in many different laptops. It was written by ENE, but cleaned up to work properly in the kernel tree by Novell. Signed-off-by: Al Cho Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/staging/keucr/smilmain.c | 1852 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 1852 insertions(+) create mode 100644 drivers/staging/keucr/smilmain.c (limited to 'drivers/staging/keucr/smilmain.c') diff --git a/drivers/staging/keucr/smilmain.c b/drivers/staging/keucr/smilmain.c new file mode 100644 index 0000000..bdfbf76 --- /dev/null +++ b/drivers/staging/keucr/smilmain.c @@ -0,0 +1,1852 @@ +#include +#include "usb.h" +#include "scsiglue.h" +#include "smcommon.h" +#include "smil.h" + +int Check_D_LogCHS (WORD *,BYTE *,BYTE *); +void Initialize_D_Media (void); +void PowerOff_D_Media (void); +int Check_D_MediaPower (void); +int Check_D_MediaExist (void); +int Check_D_MediaWP (void); +int Check_D_MediaFmt (struct us_data *); +int Check_D_MediaFmtForEraseAll (struct us_data *); +int Conv_D_MediaAddr (struct us_data *, DWORD); +int Inc_D_MediaAddr (struct us_data *); +int Check_D_FirstSect (void); +int Check_D_LastSect (void); +int Media_D_ReadOneSect (struct us_data *, WORD, BYTE *); +int Media_D_WriteOneSect (struct us_data *, WORD, BYTE *); +int Media_D_CopyBlockHead (struct us_data *); +int Media_D_CopyBlockTail (struct us_data *); +int Media_D_EraseOneBlock (void); +int Media_D_EraseAllBlock (void); + +int Copy_D_BlockAll (struct us_data *, DWORD); +int Copy_D_BlockHead (struct us_data *); +int Copy_D_BlockTail (struct us_data *); +int Reassign_D_BlockHead (struct us_data *); + +int Assign_D_WriteBlock (void); +int Release_D_ReadBlock (struct us_data *); +int Release_D_WriteBlock (struct us_data *); +int Release_D_CopySector (struct us_data *); + +int Copy_D_PhyOneSect (struct us_data *); +int Read_D_PhyOneSect (struct us_data *, WORD, BYTE *); +int Write_D_PhyOneSect (struct us_data *, WORD, BYTE *); +int Erase_D_PhyOneBlock (struct us_data *); + +int Set_D_PhyFmtValue (struct us_data *); +int Search_D_CIS (struct us_data *); +int Make_D_LogTable (struct us_data *); +void Check_D_BlockIsFull (void); + +int MarkFail_D_PhyOneBlock (struct us_data *); + +DWORD ErrXDCode; +DWORD ErrCode; +//BYTE SectBuf[SECTSIZE]; +BYTE WorkBuf[SECTSIZE]; +BYTE Redundant[REDTSIZE]; +BYTE WorkRedund[REDTSIZE]; +//WORD Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK]; +WORD *Log2Phy[MAX_ZONENUM]; // 128 x 1000, Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK]; +BYTE Assign[MAX_ZONENUM][MAX_BLOCKNUM/8]; +WORD AssignStart[MAX_ZONENUM]; +WORD ReadBlock; +WORD WriteBlock; +DWORD MediaChange; +DWORD SectCopyMode; + +extern struct SSFDCTYPE Ssfdc; +extern struct ADDRESS Media; +extern struct CIS_AREA CisArea; + +//BIT Controll Macro +BYTE BitData[] = { 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 } ; +#define Set_D_Bit(a,b) (a[(BYTE)((b)/8)]|= BitData[(b)%8]) +#define Clr_D_Bit(a,b) (a[(BYTE)((b)/8)]&=~BitData[(b)%8]) +#define Chk_D_Bit(a,b) (a[(BYTE)((b)/8)] & BitData[(b)%8]) + +//extern PBYTE SMHostAddr; +extern BYTE IsSSFDCCompliance; +extern BYTE IsXDCompliance; + + +// +////Power Controll & Media Exist Check Function +////----- Init_D_SmartMedia() -------------------------------------------- +//int Init_D_SmartMedia(void) +//{ +// int i; +// +// EMCR_Print("Init_D_SmartMedia start\n"); +// for (i=0; i len) + bn = len; + else + bn = count; + //if (Media_D_ReadOneSect(fdoExt, SectBuf)) + //if (Media_D_ReadOneSect(fdoExt, count, buf)) + if (Media_D_ReadOneSect(us, bn, buf)) + { + ErrCode = ERR_EccReadErr; + return(ErrCode); + } + + Media.Sector += bn; + count -= bn; + + if (count<=0) + break; + + buf += bn * SECTSIZE; + + if (Inc_D_MediaAddr(us)) + return(ErrCode); + } + + return(NO_ERROR); +} +// here +//----- Media_D_CopySector() ------------------------------------------ +int Media_D_CopySector(struct us_data *us, DWORD start,WORD count,BYTE *buf) +{ + //DWORD mode; + //int i; + WORD len, bn; + //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc; + //ADDRESS_T bb = (ADDRESS_T) &Media; + + //printk("Media_D_CopySector !!!\n"); + if (Conv_D_MediaAddr(us, start)) + return(ErrCode); + + while(1) + { + if (Assign_D_WriteBlock()) + return(ERROR); + + len = Ssfdc.MaxSectors - Media.Sector; + if (count > len) + bn = len; + else + bn = count; + + //if (Ssfdc_D_CopyBlock(fdoExt,count,buf,Redundant)) + if (Ssfdc_D_CopyBlock(us,bn,buf,Redundant)) + { + ErrCode = ERR_WriteFault; + return(ErrCode); + } + + Media.Sector = 0x1F; + //if (Release_D_ReadBlock(fdoExt)) + if (Release_D_CopySector(us)) + { + if (ErrCode==ERR_HwError) + { + ErrCode = ERR_WriteFault; + return(ErrCode); + } + } + count -= bn; + + if (count<=0) + break; + + buf += bn * SECTSIZE; + + if (Inc_D_MediaAddr(us)) + return(ErrCode); + + } + return(NO_ERROR); +} + +//----- Release_D_CopySector() ------------------------------------------ +int Release_D_CopySector(struct us_data *us) +{ + //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc; + //ADDRESS_T bb = (ADDRESS_T) &Media; + + Log2Phy[Media.Zone][Media.LogBlock]=WriteBlock; + Media.PhyBlock=ReadBlock; + + if (Media.PhyBlock==NO_ASSIGN) + { + Media.PhyBlock=WriteBlock; + return(SUCCESS); + } + + Clr_D_Bit(Assign[Media.Zone],Media.PhyBlock); + Media.PhyBlock=WriteBlock; + + return(SUCCESS); +} +/* +//----- Media_D_WriteSector() ------------------------------------------ +int Media_D_WriteSector(PFDO_DEVICE_EXTENSION fdoExt, DWORD start,WORD count,BYTE *buf) +{ + int i; + WORD len, bn; + SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc; + ADDRESS_T bb = (ADDRESS_T) &Media; + + //if (Check_D_MediaPower()) + // return(ErrCode); + // + //if (Check_D_MediaFmt(fdoExt)) + // return(ErrCode); + // + //if (Check_D_MediaWP()) + // return(ErrCode); + + if (Conv_D_MediaAddr(fdoExt, start)) + return(ErrCode); + + //ENE_Print("Media_D_WriteSector --- Sector = %x\n", Media.Sector); + if (Check_D_FirstSect()) + { + if (Media_D_CopyBlockHead(fdoExt)) + { + ErrCode = ERR_WriteFault; + return(ErrCode); + } + } + + while(1) + { + if (!Check_D_FirstSect()) + { + if (Assign_D_WriteBlock()) + return(ErrCode); + } + + len = Ssfdc.MaxSectors - Media.Sector; + if (count > len) + bn = len; + else + bn = count; + //for(i=0;iDrive_IsSWLED) +// { +// if (enable) +// Led_D_TernOn(); +// else +// Led_D_TernOff(); +// } +//} +// +////----- Led_D_TernOn() ------------------------------------------------- +//void Led_D_TernOn(void) +//{ +// if (Check_D_CardStsChg()) +// MediaChange=ERROR; +// +// Cnt_D_LedOn(); +//} +// +////----- Led_D_TernOff() ------------------------------------------------ +//void Led_D_TernOff(void) +//{ +// if (Check_D_CardStsChg()) +// MediaChange=ERROR; +// +// Cnt_D_LedOff(); +//} +// +////SmartMedia Logical Format Subroutine +////----- Check_D_LogCHS() ----------------------------------------------- +//int Check_D_LogCHS(WORD *c,BYTE *h,BYTE *s) +//{ +// switch(Ssfdc.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; ErrCode = ERR_NoSmartMedia; return(ERROR); +// } +// +// return(SUCCESS); +//} +// +////Power Controll & Media Exist Check Subroutine +////----- Initialize_D_Media() ------------------------------------------- +//void Initialize_D_Media(void) +//{ +// ErrCode = NO_ERROR; +// MediaChange = ERROR; +// SectCopyMode = COMPLETED; +// Cnt_D_Reset(); +//} +// +////----- PowerOff_D_Media() --------------------------------------------- +//void PowerOff_D_Media(void) +//{ +// Cnt_D_PowerOff(); +//} +// +////----- Check_D_MediaPower() ------------------------------------------- +//int Check_D_MediaPower(void) +//{ +// //usleep(56*1024); +// if (Check_D_CardStsChg()) +// MediaChange = ERROR; +// //usleep(56*1024); +// if ((!Check_D_CntPower())&&(!MediaChange)) // 有 power & Media 沒被 change, 則 return success +// return(SUCCESS); +// //usleep(56*1024); +// +// if (Check_D_CardExist()) // Check if card is not exist, return err +// { +// ErrCode = ERR_NoSmartMedia; +// MediaChange = ERROR; +// return(ERROR); +// } +// //usleep(56*1024); +// if (Cnt_D_PowerOn()) +// { +// ErrCode = ERR_NoSmartMedia; +// MediaChange = ERROR; +// return(ERROR); +// } +// //usleep(56*1024); +// Ssfdc_D_Reset(fdoExt); +// //usleep(56*1024); +// return(SUCCESS); +//} +// +////-----Check_D_MediaExist() -------------------------------------------- +//int Check_D_MediaExist(void) +//{ +// if (Check_D_CardStsChg()) +// MediaChange = ERROR; +// +// if (!Check_D_CardExist()) +// { +// if (!MediaChange) +// return(SUCCESS); +// +// ErrCode = ERR_ChangedMedia; +// return(ERROR); +// } +// +// ErrCode = ERR_NoSmartMedia; +// +// return(ERROR); +//} +// +////----- Check_D_MediaWP() ---------------------------------------------- +//int Check_D_MediaWP(void) +//{ +// if (Ssfdc.Attribute &MWP) +// { +// ErrCode = ERR_WrtProtect; +// return(ERROR); +// } +// +// return(SUCCESS); +//} +*/ +//SmartMedia Physical Format Test Subroutine +//----- Check_D_MediaFmt() --------------------------------------------- +int Check_D_MediaFmt(struct us_data *us) +{ + printk("Check_D_MediaFmt\n"); + //ULONG i,j, result=FALSE, zone,block; + + //usleep(56*1024); + if (!MediaChange) + return(SUCCESS); + + MediaChange = ERROR; + SectCopyMode = COMPLETED; + + //usleep(56*1024); + if (Set_D_PhyFmtValue(us)) + { + ErrCode = ERR_UnknownMedia; + return(ERROR); + } + + //usleep(56*1024); + if (Search_D_CIS(us)) + { + ErrCode = ERR_IllegalFmt; + return(ERROR); + } + + + MediaChange = SUCCESS; + return(SUCCESS); +} +/* +////----- Check_D_BlockIsFull() ---------------------------------- +//void Check_D_BlockIsFull() +//{ +// ULONG i, block; +// +// if (IsXDCompliance || IsSSFDCCompliance) +// { +// // If the blocks are full then return write-protect. +// block = Ssfdc.MaxBlocks/8; +// for (Media.Zone=0; Media.ZoneChildDeviceObject) return(ERROR); +// //pdoExt = fdoExt->ChildDeviceObject->DeviceExtension; +// +// Ssfdc_D_ReadID(idcode, READ_ID_1); +// + //if (Set_D_SsfdcModel(idcode[1])) + if (Set_D_SsfdcModel(us->SM_DeviceID)) + return(ERROR); + +// //Use Multi-function pin to differentiate SM and xD. +// UserDefData_1 = ReadPCIReg(fdoExt->BusID, fdoExt->DevID, fdoExt->FuncID, PCI_REG_USER_DEF) & 0x80; +// if (UserDefData_1) +// { +// if ( READ_PORT_BYTE(SM_REG_INT_STATUS) & 0x80 ) fdoExt->DiskType = DISKTYPE_XD; +// if ( READ_PORT_BYTE(SM_REG_INT_STATUS) & 0x40 ) fdoExt->DiskType = DISKTYPE_SM; +// +// if ( IsXDCompliance && (fdoExt->DiskType == DISKTYPE_XD) ) +// { +// Ssfdc_D_ReadID(idcode, READ_ID_3); +// if (idcode[2] != 0xB5) +// return(ERROR); +// } +// } +// +// //Use GPIO to differentiate SM and xD. +// UserDefData_2 = ReadPCIReg(fdoExt->BusID, fdoExt->DevID, fdoExt->FuncID, PCI_REG_USER_DEF) >> 8; +// if ( UserDefData_2 ) +// { +// Data = ReadPCIReg(fdoExt->BusID, fdoExt->DevID, 0, 0xAC); +// +// mask = 1 << (UserDefData_2-1); +// // 1 : xD , 0 : SM +// if ( Data & mask) +// fdoExt->DiskType = DISKTYPE_XD; +// else +// fdoExt->DiskType = DISKTYPE_SM; +// +// if ( IsXDCompliance && (fdoExt->DiskType == DISKTYPE_XD) ) +// { +// Ssfdc_D_ReadID(idcode, READ_ID_3); +// if (idcode[2] != 0xB5) +// return(ERROR); +// } +// } +// +// if ( !(UserDefData_1 | UserDefData_2) ) +// { +// // Use UserDefine Register to differentiate SM and xD. +// Ssfdc_D_ReadID(idcode, READ_ID_3); +// +// if (idcode[2] == 0xB5) +// fdoExt->DiskType = DISKTYPE_XD; +// else +// { +// if (!IsXDCompliance) +// fdoExt->DiskType = DISKTYPE_SM; +// else +// return(ERROR); +// } +// +// if (fdoExt->UserDef_DiskType == 0x04) fdoExt->DiskType = DISKTYPE_XD; +// if (fdoExt->UserDef_DiskType == 0x08) fdoExt->DiskType = DISKTYPE_SM; +// } +// +// if (!fdoExt->UserDef_DisableWP) +// { +// if (fdoExt->DiskType == DISKTYPE_SM) +// { +// if (Check_D_SsfdcWP()) +// Ssfdc.Attribute|=WP; +// } +// } + + return(SUCCESS); +} + +//----- Search_D_CIS() ------------------------------------------------- +int Search_D_CIS(struct us_data *us) +{ + //SSFDCTYPE_T aa = (SSFDCTYPE_T ) &Ssfdc; + //ADDRESS_T bb = (ADDRESS_T) &Media; + + Media.Zone=0; Media.Sector=0; + + for (Media.PhyBlock=0; Media.PhyBlock<(Ssfdc.MaxBlocks-Ssfdc.MaxLogBlocks-1); Media.PhyBlock++) + { + if (Ssfdc_D_ReadRedtData(us, Redundant)) + { + Ssfdc_D_Reset(us); + return(ERROR); + } + + if (!Check_D_FailBlock(Redundant)) + break; + } + + if (Media.PhyBlock==(Ssfdc.MaxBlocks-Ssfdc.MaxLogBlocks-1)) + { + Ssfdc_D_Reset(us); + return(ERROR); + } + + while (Media.Sector=Ssfdc.MaxLogBlocks) + continue; + + if (Log2Phy[Media.Zone][Media.LogBlock]==NO_ASSIGN) + { + Log2Phy[Media.Zone][Media.LogBlock]=Media.PhyBlock; + continue; + } + + phyblock = Media.PhyBlock; + logblock = Media.LogBlock; + Media.Sector = (BYTE)(Ssfdc.MaxSectors-1); + + if (Ssfdc_D_ReadRedtData(us, Redundant)) + { Ssfdc_D_Reset(us); return(ERROR); } + + if (!Load_D_LogBlockAddr(Redundant)) + { + if (Media.LogBlock==logblock) + { + Media.PhyBlock=Log2Phy[Media.Zone][logblock]; + + if (Ssfdc_D_ReadRedtData(us, Redundant)) + { Ssfdc_D_Reset(us); return(ERROR); } + + Media.PhyBlock=phyblock; + + if (!Load_D_LogBlockAddr(Redundant)) + { + if (Media.LogBlock!=logblock) + { + Media.PhyBlock=Log2Phy[Media.Zone][logblock]; + Log2Phy[Media.Zone][logblock]=phyblock; + } + } + else + { + Media.PhyBlock=Log2Phy[Media.Zone][logblock]; + Log2Phy[Media.Zone][logblock]=phyblock; + } + } + } + + Media.Sector=0; + +// here Not yet +//#ifdef L2P_ERR_ERASE +// if (!(Ssfdc.Attribute &MWP)) +// { +// Ssfdc_D_Reset(fdoExt); +// if (Ssfdc_D_EraseBlock(fdoExt)) +// return(ERROR); +// +// if (Ssfdc_D_CheckStatus()) +// { +// if (MarkFail_D_PhyOneBlock()) +// return(ERROR); +// } +// else +// Clr_D_Bit(Assign[Media.Zone],Media.PhyBlock); +// } +//#else +// Ssfdc.Attribute|=MWP; +//#endif + Media.PhyBlock=phyblock; + + } // End for (Media.PhyBlockErrCode = STATUS_CMD_FAIL; +// +// Init_D_SmartMedia(); +// +// if (Check_D_MediaPower()) +// return (ErrCode==ERR_NoSmartMedia) ? STATUS_CMD_NO_MEDIA : STATUS_CMD_FAIL; +// +// if (Set_D_PhyFmtValue(fdoExt)) +// return STATUS_CMD_FAIL; +// +// //usleep(56*1024); +// if (Search_D_CIS(fdoExt)) +// return STATUS_CMD_FAIL; +// +// if (Check_D_MediaWP()) +// return STATUS_CMD_MEDIA_WP; +// +// pParamOut->PageSize = Ssfdc.MaxSectors; +// pParamOut->BlockSize = Ssfdc.MaxBlocks; +// pParamOut->ZoneSize = Ssfdc.MaxZones; +// +// return STATUS_CMD_SUCCESS; +//}*/ -- cgit v1.1