2010-09-08 09:42:32 +02:00
|
|
|
|
#include <linux/slab.h>
|
|
|
|
|
#include "usb.h"
|
|
|
|
|
#include "scsiglue.h"
|
|
|
|
|
#include "transport.h"
|
|
|
|
|
|
|
|
|
|
#include "smcommon.h"
|
|
|
|
|
#include "smil.h"
|
|
|
|
|
|
|
|
|
|
void _Set_D_SsfdcRdCmd (BYTE);
|
|
|
|
|
void _Set_D_SsfdcRdAddr (BYTE);
|
|
|
|
|
void _Set_D_SsfdcRdChip (void);
|
|
|
|
|
void _Set_D_SsfdcRdStandby (void);
|
|
|
|
|
void _Start_D_SsfdcRdHwECC (void);
|
|
|
|
|
void _Stop_D_SsfdcRdHwECC (void);
|
|
|
|
|
void _Load_D_SsfdcRdHwECC (BYTE);
|
|
|
|
|
void _Set_D_SsfdcWrCmd (BYTE);
|
|
|
|
|
void _Set_D_SsfdcWrAddr (BYTE);
|
|
|
|
|
void _Set_D_SsfdcWrBlock (void);
|
|
|
|
|
void _Set_D_SsfdcWrStandby (void);
|
|
|
|
|
void _Start_D_SsfdcWrHwECC (void);
|
|
|
|
|
void _Load_D_SsfdcWrHwECC (BYTE);
|
|
|
|
|
int _Check_D_SsfdcBusy (WORD);
|
|
|
|
|
int _Check_D_SsfdcStatus (void);
|
|
|
|
|
void _Reset_D_SsfdcErr (void);
|
|
|
|
|
void _Read_D_SsfdcBuf (BYTE *);
|
|
|
|
|
void _Write_D_SsfdcBuf (BYTE *);
|
|
|
|
|
void _Read_D_SsfdcByte (BYTE *);
|
|
|
|
|
void _ReadRedt_D_SsfdcBuf (BYTE *);
|
|
|
|
|
void _WriteRedt_D_SsfdcBuf (BYTE *);
|
|
|
|
|
BYTE _Check_D_DevCode (BYTE);
|
|
|
|
|
|
|
|
|
|
void _Set_D_ECCdata (BYTE,BYTE *);
|
|
|
|
|
void _Calc_D_ECCdata (BYTE *);
|
|
|
|
|
|
2011-07-22 13:17:04 +02:00
|
|
|
|
|
2010-09-08 09:42:32 +02:00
|
|
|
|
struct SSFDCTYPE Ssfdc;
|
|
|
|
|
struct ADDRESS Media;
|
|
|
|
|
struct CIS_AREA CisArea;
|
|
|
|
|
|
2011-05-09 19:46:24 +02:00
|
|
|
|
static BYTE EccBuf[6];
|
2010-09-08 09:42:32 +02:00
|
|
|
|
extern PBYTE SMHostAddr;
|
|
|
|
|
extern DWORD ErrXDCode;
|
|
|
|
|
|
|
|
|
|
extern WORD ReadBlock;
|
|
|
|
|
extern WORD WriteBlock;
|
|
|
|
|
|
2011-07-22 13:17:04 +02:00
|
|
|
|
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
|
|
|
|
#define EVEN 0 // Even Page for 256byte/page
|
|
|
|
|
#define ODD 1 // Odd Page for 256byte/page
|
|
|
|
|
|
|
|
|
|
|
2011-03-31 03:57:33 +02:00
|
|
|
|
//SmartMedia Redundant buffer data Control Subroutine
|
2010-09-08 09:42:32 +02:00
|
|
|
|
//----- Check_D_DataBlank() --------------------------------------------
|
|
|
|
|
int Check_D_DataBlank(BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
char i;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<REDTSIZE; i++)
|
|
|
|
|
if (*redundant++!=0xFF)
|
|
|
|
|
return(ERROR);
|
|
|
|
|
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return(SMSUCCESS);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Check_D_FailBlock() --------------------------------------------
|
|
|
|
|
int Check_D_FailBlock(BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
redundant+=REDT_BLOCK;
|
|
|
|
|
|
|
|
|
|
if (*redundant==0xFF)
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return(SMSUCCESS);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
if (!*redundant)
|
|
|
|
|
return(ERROR);
|
2011-02-27 23:20:24 +01:00
|
|
|
|
if (hweight8(*redundant)<7)
|
2010-09-08 09:42:32 +02:00
|
|
|
|
return(ERROR);
|
|
|
|
|
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return(SMSUCCESS);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Check_D_DataStatus() -------------------------------------------
|
|
|
|
|
int Check_D_DataStatus(BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
redundant+=REDT_DATA;
|
|
|
|
|
|
|
|
|
|
if (*redundant==0xFF)
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return(SMSUCCESS);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
if (!*redundant)
|
|
|
|
|
{
|
|
|
|
|
ErrXDCode = ERR_DataStatus;
|
|
|
|
|
return(ERROR);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ErrXDCode = NO_ERROR;
|
|
|
|
|
|
2011-02-27 23:20:24 +01:00
|
|
|
|
if (hweight8(*redundant)<5)
|
2010-09-08 09:42:32 +02:00
|
|
|
|
return(ERROR);
|
|
|
|
|
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return(SMSUCCESS);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Load_D_LogBlockAddr() ------------------------------------------
|
|
|
|
|
int Load_D_LogBlockAddr(BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
WORD addr1,addr2;
|
|
|
|
|
|
|
|
|
|
addr1=(WORD)*(redundant+REDT_ADDR1H)*0x0100+(WORD)*(redundant+REDT_ADDR1L);
|
|
|
|
|
addr2=(WORD)*(redundant+REDT_ADDR2H)*0x0100+(WORD)*(redundant+REDT_ADDR2L);
|
|
|
|
|
|
|
|
|
|
if (addr1==addr2)
|
|
|
|
|
if ((addr1 &0xF000)==0x1000)
|
2011-05-09 19:47:51 +02:00
|
|
|
|
{ Media.LogBlock=(addr1 &0x0FFF)/2; return(SMSUCCESS); }
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
2011-02-27 23:20:24 +01:00
|
|
|
|
if (hweight16((WORD)(addr1^addr2))!=0x01) return(ERROR);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
|
|
|
|
if ((addr1 &0xF000)==0x1000)
|
2011-02-27 23:20:24 +01:00
|
|
|
|
if (!(hweight16(addr1) &0x01))
|
2011-05-09 19:47:51 +02:00
|
|
|
|
{ Media.LogBlock=(addr1 &0x0FFF)/2; return(SMSUCCESS); }
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
|
|
|
|
if ((addr2 &0xF000)==0x1000)
|
2011-02-27 23:20:24 +01:00
|
|
|
|
if (!(hweight16(addr2) &0x01))
|
2011-05-09 19:47:51 +02:00
|
|
|
|
{ Media.LogBlock=(addr2 &0x0FFF)/2; return(SMSUCCESS); }
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
|
|
|
|
return(ERROR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Clr_D_RedundantData() ------------------------------------------
|
|
|
|
|
void Clr_D_RedundantData(BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
char i;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<REDTSIZE; i++)
|
|
|
|
|
*(redundant+i)=0xFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Set_D_LogBlockAddr() -------------------------------------------
|
|
|
|
|
void Set_D_LogBlockAddr(BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
WORD addr;
|
|
|
|
|
|
|
|
|
|
*(redundant+REDT_BLOCK)=0xFF;
|
|
|
|
|
*(redundant+REDT_DATA) =0xFF;
|
|
|
|
|
addr=Media.LogBlock*2+0x1000;
|
|
|
|
|
|
2011-02-27 23:20:24 +01:00
|
|
|
|
if ((hweight16(addr)%2))
|
2010-09-08 09:42:32 +02:00
|
|
|
|
addr++;
|
|
|
|
|
|
|
|
|
|
*(redundant+REDT_ADDR1H)=*(redundant+REDT_ADDR2H)=(BYTE)(addr/0x0100);
|
|
|
|
|
*(redundant+REDT_ADDR1L)=*(redundant+REDT_ADDR2L)=(BYTE)addr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Set_D_FailBlock() ----------------------------------------------
|
|
|
|
|
void Set_D_FailBlock(BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
char i;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<REDTSIZE; i++)
|
|
|
|
|
*redundant++=(BYTE)((i==REDT_BLOCK)?0xF0:0xFF);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Set_D_DataStaus() ----------------------------------------------
|
|
|
|
|
void Set_D_DataStaus(BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
redundant+=REDT_DATA;
|
|
|
|
|
*redundant=0x00;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//SmartMedia Function Command Subroutine
|
|
|
|
|
// 6250 CMD 6
|
|
|
|
|
//----- Ssfdc_D_Reset() ------------------------------------------------
|
|
|
|
|
void Ssfdc_D_Reset(struct us_data *us)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Ssfdc_D_ReadCisSect() ------------------------------------------
|
|
|
|
|
int Ssfdc_D_ReadCisSect(struct us_data *us, BYTE *buf,BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
BYTE zone,sector;
|
|
|
|
|
WORD block;
|
|
|
|
|
|
|
|
|
|
zone=Media.Zone; block=Media.PhyBlock; sector=Media.Sector;
|
|
|
|
|
Media.Zone=0;
|
|
|
|
|
Media.PhyBlock=CisArea.PhyBlock;
|
|
|
|
|
Media.Sector=CisArea.Sector;
|
|
|
|
|
|
|
|
|
|
if (Ssfdc_D_ReadSect(us,buf,redundant))
|
|
|
|
|
{
|
|
|
|
|
Media.Zone=zone; Media.PhyBlock=block; Media.Sector=sector;
|
|
|
|
|
return(ERROR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Media.Zone=zone; Media.PhyBlock=block; Media.Sector=sector;
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return(SMSUCCESS);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
}
|
2011-07-22 13:17:04 +02:00
|
|
|
|
|
2010-09-08 09:42:32 +02:00
|
|
|
|
// 6250 CMD 1
|
|
|
|
|
//----- Ssfdc_D_ReadSect() ---------------------------------------------
|
|
|
|
|
int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf,BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
|
|
|
|
|
int result;
|
|
|
|
|
WORD addr;
|
|
|
|
|
|
|
|
|
|
result = ENE_LoadBinCode(us, SM_RW_PATTERN);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
{
|
|
|
|
|
printk("Load SM RW Code Fail !!\n");
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
|
|
|
|
|
addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
|
|
|
|
|
|
|
|
|
|
// Read sect data
|
2010-10-29 03:18:18 +02:00
|
|
|
|
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
|
2010-09-08 09:42:32 +02:00
|
|
|
|
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
|
|
|
|
|
bcb->DataTransferLength = 0x200;
|
|
|
|
|
bcb->Flags = 0x80;
|
|
|
|
|
bcb->CDB[0] = 0xF1;
|
|
|
|
|
bcb->CDB[1] = 0x02;
|
|
|
|
|
bcb->CDB[4] = (BYTE)addr;
|
|
|
|
|
bcb->CDB[3] = (BYTE)(addr/0x0100);
|
|
|
|
|
bcb->CDB[2] = Media.Zone/2;
|
|
|
|
|
|
|
|
|
|
result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
|
|
|
|
|
// Read redundant
|
2010-10-29 03:18:18 +02:00
|
|
|
|
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
|
2010-09-08 09:42:32 +02:00
|
|
|
|
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
|
|
|
|
|
bcb->DataTransferLength = 0x10;
|
|
|
|
|
bcb->Flags = 0x80;
|
|
|
|
|
bcb->CDB[0] = 0xF1;
|
|
|
|
|
bcb->CDB[1] = 0x03;
|
|
|
|
|
bcb->CDB[4] = (BYTE)addr;
|
|
|
|
|
bcb->CDB[3] = (BYTE)(addr/0x0100);
|
|
|
|
|
bcb->CDB[2] = Media.Zone/2;
|
|
|
|
|
bcb->CDB[8] = 0;
|
|
|
|
|
bcb->CDB[9] = 1;
|
|
|
|
|
|
|
|
|
|
result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
|
|
|
|
|
return USB_STOR_TRANSPORT_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Ssfdc_D_ReadBlock() ---------------------------------------------
|
|
|
|
|
int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf,BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
|
|
|
|
|
int result;
|
|
|
|
|
WORD addr;
|
|
|
|
|
|
|
|
|
|
result = ENE_LoadBinCode(us, SM_RW_PATTERN);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
{
|
|
|
|
|
printk("Load SM RW Code Fail !!\n");
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
|
|
|
|
|
addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
|
|
|
|
|
|
|
|
|
|
// Read sect data
|
2010-10-29 03:18:18 +02:00
|
|
|
|
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
|
2010-09-08 09:42:32 +02:00
|
|
|
|
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
|
|
|
|
|
bcb->DataTransferLength = 0x200*count;
|
|
|
|
|
bcb->Flags = 0x80;
|
|
|
|
|
bcb->CDB[0] = 0xF1;
|
|
|
|
|
bcb->CDB[1] = 0x02;
|
|
|
|
|
bcb->CDB[4] = (BYTE)addr;
|
|
|
|
|
bcb->CDB[3] = (BYTE)(addr/0x0100);
|
|
|
|
|
bcb->CDB[2] = Media.Zone/2;
|
|
|
|
|
|
|
|
|
|
result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
|
|
|
|
|
// Read redundant
|
2010-10-29 03:18:18 +02:00
|
|
|
|
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
|
2010-09-08 09:42:32 +02:00
|
|
|
|
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
|
|
|
|
|
bcb->DataTransferLength = 0x10;
|
|
|
|
|
bcb->Flags = 0x80;
|
|
|
|
|
bcb->CDB[0] = 0xF1;
|
|
|
|
|
bcb->CDB[1] = 0x03;
|
|
|
|
|
bcb->CDB[4] = (BYTE)addr;
|
|
|
|
|
bcb->CDB[3] = (BYTE)(addr/0x0100);
|
|
|
|
|
bcb->CDB[2] = Media.Zone/2;
|
|
|
|
|
bcb->CDB[8] = 0;
|
|
|
|
|
bcb->CDB[9] = 1;
|
|
|
|
|
|
|
|
|
|
result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
|
|
|
|
|
return USB_STOR_TRANSPORT_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-22 13:17:04 +02:00
|
|
|
|
|
2010-09-08 09:42:32 +02:00
|
|
|
|
//----- Ssfdc_D_CopyBlock() --------------------------------------------
|
|
|
|
|
int Ssfdc_D_CopyBlock(struct us_data *us, WORD count, BYTE *buf,BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
|
|
|
|
|
int result;
|
|
|
|
|
WORD ReadAddr, WriteAddr;
|
|
|
|
|
|
|
|
|
|
result = ENE_LoadBinCode(us, SM_RW_PATTERN);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
{
|
|
|
|
|
printk("Load SM RW Code Fail !!\n");
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReadAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks+ReadBlock;
|
|
|
|
|
ReadAddr = ReadAddr*(WORD)Ssfdc.MaxSectors;
|
|
|
|
|
WriteAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks+WriteBlock;
|
|
|
|
|
WriteAddr = WriteAddr*(WORD)Ssfdc.MaxSectors;
|
|
|
|
|
|
|
|
|
|
// Write sect data
|
2010-10-29 03:18:18 +02:00
|
|
|
|
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
|
2010-09-08 09:42:32 +02:00
|
|
|
|
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
|
|
|
|
|
bcb->DataTransferLength = 0x200*count;
|
|
|
|
|
bcb->Flags = 0x00;
|
|
|
|
|
bcb->CDB[0] = 0xF0;
|
|
|
|
|
bcb->CDB[1] = 0x08;
|
|
|
|
|
bcb->CDB[7] = (BYTE)WriteAddr;
|
|
|
|
|
bcb->CDB[6] = (BYTE)(WriteAddr/0x0100);
|
|
|
|
|
bcb->CDB[5] = Media.Zone/2;
|
|
|
|
|
bcb->CDB[8] = *(redundant+REDT_ADDR1H);
|
|
|
|
|
bcb->CDB[9] = *(redundant+REDT_ADDR1L);
|
|
|
|
|
bcb->CDB[10] = Media.Sector;
|
|
|
|
|
|
|
|
|
|
if (ReadBlock != NO_ASSIGN)
|
|
|
|
|
{
|
|
|
|
|
bcb->CDB[4] = (BYTE)ReadAddr;
|
|
|
|
|
bcb->CDB[3] = (BYTE)(ReadAddr/0x0100);
|
|
|
|
|
bcb->CDB[2] = Media.Zone/2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
bcb->CDB[11] = 1;
|
|
|
|
|
|
|
|
|
|
result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
|
|
|
|
|
return USB_STOR_TRANSPORT_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Ssfdc_D_WriteSectForCopy() -------------------------------------
|
|
|
|
|
int Ssfdc_D_WriteSectForCopy(struct us_data *us, BYTE *buf, BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
|
|
|
|
|
int result;
|
|
|
|
|
WORD addr;
|
|
|
|
|
|
|
|
|
|
result = ENE_LoadBinCode(us, SM_RW_PATTERN);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
{
|
|
|
|
|
printk("Load SM RW Code Fail !!\n");
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
|
|
|
|
|
addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
|
|
|
|
|
|
|
|
|
|
// Write sect data
|
2010-10-29 03:18:18 +02:00
|
|
|
|
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
|
2010-09-08 09:42:32 +02:00
|
|
|
|
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
|
|
|
|
|
bcb->DataTransferLength = 0x200;
|
|
|
|
|
bcb->Flags = 0x00;
|
|
|
|
|
bcb->CDB[0] = 0xF0;
|
|
|
|
|
bcb->CDB[1] = 0x04;
|
|
|
|
|
bcb->CDB[7] = (BYTE)addr;
|
|
|
|
|
bcb->CDB[6] = (BYTE)(addr/0x0100);
|
|
|
|
|
bcb->CDB[5] = Media.Zone/2;
|
2010-11-15 04:04:48 +01:00
|
|
|
|
bcb->CDB[8] = *(redundant+REDT_ADDR1H);
|
|
|
|
|
bcb->CDB[9] = *(redundant+REDT_ADDR1L);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
|
|
|
|
result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
|
|
|
|
|
return USB_STOR_TRANSPORT_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 6250 CMD 5
|
|
|
|
|
//----- Ssfdc_D_EraseBlock() -------------------------------------------
|
|
|
|
|
int Ssfdc_D_EraseBlock(struct us_data *us)
|
|
|
|
|
{
|
|
|
|
|
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
|
|
|
|
|
int result;
|
|
|
|
|
WORD addr;
|
|
|
|
|
|
|
|
|
|
result = ENE_LoadBinCode(us, SM_RW_PATTERN);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
{
|
|
|
|
|
printk("Load SM RW Code Fail !!\n");
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr=(WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
|
|
|
|
|
addr=addr*(WORD)Ssfdc.MaxSectors;
|
|
|
|
|
|
2010-10-29 03:18:18 +02:00
|
|
|
|
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
|
2010-09-08 09:42:32 +02:00
|
|
|
|
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
|
|
|
|
|
bcb->DataTransferLength = 0x200;
|
|
|
|
|
bcb->Flags = 0x80;
|
|
|
|
|
bcb->CDB[0] = 0xF2;
|
|
|
|
|
bcb->CDB[1] = 0x06;
|
|
|
|
|
bcb->CDB[7] = (BYTE)addr;
|
|
|
|
|
bcb->CDB[6] = (BYTE)(addr/0x0100);
|
|
|
|
|
bcb->CDB[5] = Media.Zone/2;
|
|
|
|
|
|
|
|
|
|
result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
|
|
|
|
|
return USB_STOR_TRANSPORT_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 6250 CMD 2
|
|
|
|
|
//----- Ssfdc_D_ReadRedtData() -----------------------------------------
|
|
|
|
|
int Ssfdc_D_ReadRedtData(struct us_data *us, BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
|
|
|
|
|
int result;
|
|
|
|
|
WORD addr;
|
|
|
|
|
BYTE *buf;
|
|
|
|
|
|
|
|
|
|
result = ENE_LoadBinCode(us, SM_RW_PATTERN);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
{
|
|
|
|
|
printk("Load SM RW Code Fail !!\n");
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
|
|
|
|
|
addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
|
|
|
|
|
|
2010-10-29 03:18:18 +02:00
|
|
|
|
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
|
2010-09-08 09:42:32 +02:00
|
|
|
|
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
|
|
|
|
|
bcb->DataTransferLength = 0x10;
|
|
|
|
|
bcb->Flags = 0x80;
|
|
|
|
|
bcb->CDB[0] = 0xF1;
|
|
|
|
|
bcb->CDB[1] = 0x03;
|
|
|
|
|
bcb->CDB[4] = (BYTE)addr;
|
|
|
|
|
bcb->CDB[3] = (BYTE)(addr/0x0100);
|
|
|
|
|
bcb->CDB[2] = Media.Zone/2;
|
|
|
|
|
bcb->CDB[8] = 0;
|
|
|
|
|
bcb->CDB[9] = 1;
|
|
|
|
|
|
|
|
|
|
buf = kmalloc(0x10, GFP_KERNEL);
|
|
|
|
|
result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
|
|
|
|
|
memcpy(redundant, buf, 0x10);
|
|
|
|
|
kfree(buf);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
|
|
|
|
|
return USB_STOR_TRANSPORT_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 6250 CMD 4
|
|
|
|
|
//----- Ssfdc_D_WriteRedtData() ----------------------------------------
|
|
|
|
|
int Ssfdc_D_WriteRedtData(struct us_data *us, BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
|
|
|
|
|
int result;
|
|
|
|
|
WORD addr;
|
|
|
|
|
|
|
|
|
|
result = ENE_LoadBinCode(us, SM_RW_PATTERN);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
{
|
|
|
|
|
printk("Load SM RW Code Fail !!\n");
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr = (WORD)Media.Zone*Ssfdc.MaxBlocks+Media.PhyBlock;
|
|
|
|
|
addr = addr*(WORD)Ssfdc.MaxSectors+Media.Sector;
|
|
|
|
|
|
2010-10-29 03:18:18 +02:00
|
|
|
|
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
|
2010-09-08 09:42:32 +02:00
|
|
|
|
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
|
|
|
|
|
bcb->DataTransferLength = 0x10;
|
|
|
|
|
bcb->Flags = 0x80;
|
|
|
|
|
bcb->CDB[0] = 0xF2;
|
|
|
|
|
bcb->CDB[1] = 0x05;
|
|
|
|
|
bcb->CDB[7] = (BYTE)addr;
|
|
|
|
|
bcb->CDB[6] = (BYTE)(addr/0x0100);
|
|
|
|
|
bcb->CDB[5] = Media.Zone/2;
|
|
|
|
|
bcb->CDB[8] = *(redundant+REDT_ADDR1H);
|
|
|
|
|
bcb->CDB[9] = *(redundant+REDT_ADDR1L);
|
|
|
|
|
|
|
|
|
|
result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
|
|
|
|
|
if (result != USB_STOR_XFER_GOOD)
|
|
|
|
|
return USB_STOR_TRANSPORT_ERROR;
|
|
|
|
|
|
|
|
|
|
return USB_STOR_TRANSPORT_GOOD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Ssfdc_D_CheckStatus() ------------------------------------------
|
|
|
|
|
int Ssfdc_D_CheckStatus(void)
|
|
|
|
|
{
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return(SMSUCCESS);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
}
|
2011-07-22 13:17:04 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-09-08 09:42:32 +02:00
|
|
|
|
//SmartMedia ID Code Check & Mode Set Subroutine
|
|
|
|
|
//----- Set_D_SsfdcModel() ---------------------------------------------
|
|
|
|
|
int Set_D_SsfdcModel(BYTE dcode)
|
|
|
|
|
{
|
|
|
|
|
switch (_Check_D_DevCode(dcode)) {
|
|
|
|
|
case SSFDC1MB:
|
|
|
|
|
Ssfdc.Model = SSFDC1MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS256;
|
|
|
|
|
Ssfdc.MaxZones = 1;
|
|
|
|
|
Ssfdc.MaxBlocks = 256;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 250;
|
|
|
|
|
Ssfdc.MaxSectors = 8;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC2MB:
|
|
|
|
|
Ssfdc.Model = SSFDC2MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS256;
|
|
|
|
|
Ssfdc.MaxZones = 1;
|
|
|
|
|
Ssfdc.MaxBlocks = 512;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 500;
|
|
|
|
|
Ssfdc.MaxSectors = 8;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC4MB:
|
|
|
|
|
Ssfdc.Model = SSFDC4MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 1;
|
|
|
|
|
Ssfdc.MaxBlocks = 512;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 500;
|
|
|
|
|
Ssfdc.MaxSectors = 16;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC8MB:
|
|
|
|
|
Ssfdc.Model = SSFDC8MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD3CYC | BS16 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 1;
|
|
|
|
|
Ssfdc.MaxBlocks = 1024;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 1000;
|
|
|
|
|
Ssfdc.MaxSectors = 16;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC16MB:
|
|
|
|
|
Ssfdc.Model = SSFDC16MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD3CYC | BS32 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 1;
|
|
|
|
|
Ssfdc.MaxBlocks = 1024;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 1000;
|
|
|
|
|
Ssfdc.MaxSectors = 32;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC32MB:
|
|
|
|
|
Ssfdc.Model = SSFDC32MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD3CYC | BS32 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 2;
|
|
|
|
|
Ssfdc.MaxBlocks = 1024;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 1000;
|
|
|
|
|
Ssfdc.MaxSectors = 32;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC64MB:
|
|
|
|
|
Ssfdc.Model = SSFDC64MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 4;
|
|
|
|
|
Ssfdc.MaxBlocks = 1024;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 1000;
|
|
|
|
|
Ssfdc.MaxSectors = 32;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC128MB:
|
|
|
|
|
Ssfdc.Model = SSFDC128MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 8;
|
|
|
|
|
Ssfdc.MaxBlocks = 1024;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 1000;
|
|
|
|
|
Ssfdc.MaxSectors = 32;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC256MB:
|
|
|
|
|
Ssfdc.Model = SSFDC256MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 16;
|
|
|
|
|
Ssfdc.MaxBlocks = 1024;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 1000;
|
|
|
|
|
Ssfdc.MaxSectors = 32;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC512MB:
|
|
|
|
|
Ssfdc.Model = SSFDC512MB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 32;
|
|
|
|
|
Ssfdc.MaxBlocks = 1024;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 1000;
|
|
|
|
|
Ssfdc.MaxSectors = 32;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC1GB:
|
|
|
|
|
Ssfdc.Model = SSFDC1GB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 64;
|
|
|
|
|
Ssfdc.MaxBlocks = 1024;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 1000;
|
|
|
|
|
Ssfdc.MaxSectors = 32;
|
|
|
|
|
break;
|
|
|
|
|
case SSFDC2GB:
|
|
|
|
|
Ssfdc.Model = SSFDC2GB;
|
|
|
|
|
Ssfdc.Attribute = FLASH | AD4CYC | BS32 | PS512;
|
|
|
|
|
Ssfdc.MaxZones = 128;
|
|
|
|
|
Ssfdc.MaxBlocks = 1024;
|
|
|
|
|
Ssfdc.MaxLogBlocks = 1000;
|
|
|
|
|
Ssfdc.MaxSectors = 32;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
Ssfdc.Model = NOSSFDC;
|
|
|
|
|
return(ERROR);
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return(SMSUCCESS);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- _Check_D_DevCode() ---------------------------------------------
|
|
|
|
|
BYTE _Check_D_DevCode(BYTE 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
|
|
|
|
|
case 0x71: return(SSFDC256MB);
|
|
|
|
|
case 0xDC: return(SSFDC512MB);
|
|
|
|
|
case 0xD3: return(SSFDC1GB);
|
|
|
|
|
case 0xD5: return(SSFDC2GB);
|
|
|
|
|
default: return(NOSSFDC);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-07-22 13:17:04 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-03-31 03:57:33 +02:00
|
|
|
|
//SmartMedia ECC Control Subroutine
|
2010-09-08 09:42:32 +02:00
|
|
|
|
//----- Check_D_ReadError() ----------------------------------------------
|
|
|
|
|
int Check_D_ReadError(BYTE *redundant)
|
|
|
|
|
{
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return SMSUCCESS;
|
2010-09-08 09:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Check_D_Correct() ----------------------------------------------
|
|
|
|
|
int Check_D_Correct(BYTE *buf,BYTE *redundant)
|
|
|
|
|
{
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return SMSUCCESS;
|
2010-09-08 09:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Check_D_CISdata() ----------------------------------------------
|
|
|
|
|
int Check_D_CISdata(BYTE *buf, BYTE *redundant)
|
|
|
|
|
{
|
2011-01-02 23:14:26 +01:00
|
|
|
|
BYTE cis[] = {0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02,
|
|
|
|
|
0xDF, 0x01, 0x20};
|
|
|
|
|
|
|
|
|
|
int cis_len = sizeof(cis);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
2011-01-02 23:14:26 +01:00
|
|
|
|
if (!IsSSFDCCompliance && !IsXDCompliance)
|
2011-05-09 19:47:51 +02:00
|
|
|
|
return SMSUCCESS;
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
2011-01-02 23:14:26 +01:00
|
|
|
|
if (!memcmp(redundant + 0x0D, EccBuf, 3))
|
|
|
|
|
return memcmp(buf, cis, cis_len);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
2011-01-02 23:14:26 +01:00
|
|
|
|
if (!_Correct_D_SwECC(buf, redundant + 0x0D, EccBuf))
|
|
|
|
|
return memcmp(buf, cis, cis_len);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
2011-01-02 23:14:26 +01:00
|
|
|
|
buf += 0x100;
|
|
|
|
|
if (!memcmp(redundant + 0x08, EccBuf + 0x03, 3))
|
|
|
|
|
return memcmp(buf, cis, cis_len);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
2011-01-02 23:14:26 +01:00
|
|
|
|
if (!_Correct_D_SwECC(buf, redundant + 0x08, EccBuf + 0x03))
|
|
|
|
|
return memcmp(buf, cis, cis_len);
|
2010-09-08 09:42:32 +02:00
|
|
|
|
|
2011-01-02 23:14:26 +01:00
|
|
|
|
return ERROR;
|
2010-09-08 09:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----- Set_D_RightECC() ----------------------------------------------
|
|
|
|
|
void Set_D_RightECC(BYTE *redundant)
|
|
|
|
|
{
|
|
|
|
|
// Driver <20><><EFBFBD><EFBFBD> ECC Check
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-22 13:17:04 +02:00
|
|
|
|
|