📄 pccard.c
字号:
#include "system.h"
#include "etc.h"
#include "pccard.h"
#define PERF_TEST_PCCARD 0 // overall time
#define PERF_TEST_PCCARD_D 0 // only data transfering time
#define DBG_PCCARD
#ifdef DBG_PCCARD
#define DbgPccard(x) printf x
#else
#define DbgPccard(x) 0;
#endif
#define CFMEM_BASE 0x4B800000
// ATA, Basic PC card select
#define ATA_MUX CFMEM_BASE+0x1800
// PC card SFR base
#define PCCARD_SFR_BASE CFMEM_BASE+0x1820
// PC Card Memory map
#define PCCARD_ATT_BASE CFMEM_BASE // refer to attribute memory region
#define PCCARD_IO_BASE CFMEM_BASE+0x800 // refer to IO region
#define PCCARD_MEM_BASE CFMEM_BASE+0x1000 // refer to common memory region
#define PCCARD_MEM_MODE 0
#define PCCARD_IO_MODE1 1
#define PCCARD_IO_MODE2 2
#define PCCARD_IO_MODE3 3
/*=========================================================================
* ATA Commands
*=========================================================================
*/
#define IDENTIFYDEVICE 0xec
#define READSECTOR 0x20
#define READMULTIPLE 0xc4
#define READDMA 0xc8
#define WRITESECTOR 0x30
#define WRITEMULTIPLE 0xc5
#define WRITEDMA 0xca
#define SETFEATURES 0xef
/*=========================================================================
* I/O configuration address
*=========================================================================
*/
#define PCCARD_CONFIG_OPTION (PCCARD_ATT_BASE + 0x200)
#define PCCARD_CONFIG_STATUS (PCCARD_ATT_BASE + 0x202)
#define PCCARD_CONFIG_REPLACE (PCCARD_ATT_BASE + 0x200)
#define PCCARD_CONFIG_SOCKET (PCCARD_ATT_BASE + 0x200)
/*=========================================================================
* PC card ATA Register Address
*=========================================================================
*/
static unsigned int PCCARD_DATA = (PCCARD_MEM_BASE + 0x00);
//static unsigned int PCCARD_ERROR = (PCCARD_MEM_BASE + 0x01);
static unsigned int PCCARD_FEATURE = (PCCARD_MEM_BASE + 0x01);
static unsigned int PCCARD_SECTOR = (PCCARD_MEM_BASE + 0x02);
static unsigned int PCCARD_LOWLBA = (PCCARD_MEM_BASE + 0x03);
static unsigned int PCCARD_MIDLBA = (PCCARD_MEM_BASE + 0x04);
static unsigned int PCCARD_HIGHLBA = (PCCARD_MEM_BASE + 0x05);
static unsigned int PCCARD_DEVICE = (PCCARD_MEM_BASE + 0x06);
static unsigned int PCCARD_STATUS = (PCCARD_MEM_BASE + 0x07);
static unsigned int PCCARD_COMMAND = (PCCARD_MEM_BASE + 0x07);
//static unsigned int PCCARD_DUP_EVEN = (PCCARD_MEM_BASE + 0x08);
//static unsigned int PCCARD_DUP_ODD = (PCCARD_MEM_BASE + 0x09);
//static unsigned int PCCARD_DUP_ERR = (PCCARD_MEM_BASE + 0x0D);
//static unsigned int PCCARD_DUP_FEATURE = (PCCARD_MEM_BASE + 0x0D);
//static unsigned int PCCARD_ALTANATE = (PCCARD_MEM_BASE + 0x0E);
//static unsigned int PCCARD_CONTROL = (PCCARD_MEM_BASE + 0x0E);
//static unsigned int PCCARD_DRV_ADDR = (PCCARD_MEM_BASE + 0x0F);
//=========================================================================
// PCCARD Functions
//=========================================================================
bool ChangePccardMode(unsigned int mode)
{
if (mode == PCCARD_IO_MODE1)
{
PCCARD_DATA = (PCCARD_IO_BASE + 0x00);
// PCCARD_ERROR = (PCCARD_IO_BASE + 0x01);
PCCARD_FEATURE = (PCCARD_IO_BASE + 0x01);
PCCARD_SECTOR = (PCCARD_IO_BASE + 0x02);
PCCARD_LOWLBA = (PCCARD_IO_BASE + 0x03);
PCCARD_MIDLBA = (PCCARD_IO_BASE + 0x04);
PCCARD_HIGHLBA = (PCCARD_IO_BASE + 0x05);
PCCARD_DEVICE = (PCCARD_IO_BASE + 0x06);
PCCARD_STATUS = (PCCARD_IO_BASE + 0x07);
PCCARD_COMMAND = (PCCARD_IO_BASE + 0x07);
// PCCARD_DUP_EVEN = (PCCARD_IO_BASE + 0x08);
// PCCARD_DUP_ODD = (PCCARD_IO_BASE + 0x09);
// PCCARD_DUP_ERR = (PCCARD_IO_BASE + 0x0D);
// PCCARD_DUP_FEATURE =(PCCARD_IO_BASE + 0x0D);
// PCCARD_ALTANATE = (PCCARD_IO_BASE + 0x0E);
// PCCARD_CONTROL = (PCCARD_IO_BASE + 0x0E);
// PCCARD_DRV_ADDR = (PCCARD_IO_BASE + 0x0F);
Outp8(PCCARD_CONFIG_OPTION, PCCARD_IO_MODE1);
}
else if (mode == PCCARD_IO_MODE2)
{
PCCARD_DATA = (PCCARD_IO_BASE + 0x1F0);
//PCCARD_ERROR = (PCCARD_IO_BASE + 0x1F1);
PCCARD_FEATURE = (PCCARD_IO_BASE + 0x1F1);
PCCARD_SECTOR = (PCCARD_IO_BASE + 0x1F2);
PCCARD_LOWLBA = (PCCARD_IO_BASE + 0x1F3);
PCCARD_MIDLBA = (PCCARD_IO_BASE + 0x1F4);
PCCARD_HIGHLBA = (PCCARD_IO_BASE + 0x1F5);
PCCARD_DEVICE = (PCCARD_IO_BASE + 0x1F6);
PCCARD_STATUS = (PCCARD_IO_BASE + 0x1F7);
PCCARD_COMMAND = (PCCARD_IO_BASE + 0x1F7);
//PCCARD_ALTANATE = (PCCARD_IO_BASE + 0x3F6);
//PCCARD_DRV_ADDR = (PCCARD_IO_BASE + 0x3F7);
Outp8(PCCARD_CONFIG_OPTION, PCCARD_IO_MODE2);
}
else if (mode == PCCARD_IO_MODE3)
{
PCCARD_DATA = (PCCARD_IO_BASE + 0x170);
//PCCARD_ERROR = (PCCARD_IO_BASE + 0x171);
PCCARD_FEATURE = (PCCARD_IO_BASE + 0x171);
PCCARD_SECTOR = (PCCARD_IO_BASE + 0x172);
PCCARD_LOWLBA = (PCCARD_IO_BASE + 0x173);
PCCARD_MIDLBA = (PCCARD_IO_BASE + 0x174);
PCCARD_HIGHLBA = (PCCARD_IO_BASE + 0x175);
PCCARD_DEVICE = (PCCARD_IO_BASE + 0x176);
PCCARD_STATUS = (PCCARD_IO_BASE + 0x177);
PCCARD_COMMAND = (PCCARD_IO_BASE + 0x177);
//PCCARD_ALTANATE = (PCCARD_IO_BASE + 0x376);
//PCCARD_DRV_ADDR = (PCCARD_IO_BASE + 0x377);
Outp8(PCCARD_CONFIG_OPTION, PCCARD_IO_MODE3);
}
else // defualt PCCARD_MEM_MODE
{
PCCARD_DATA = (PCCARD_MEM_BASE + 0x00);
//PCCARD_ERROR = (PCCARD_MEM_BASE + 0x01);
PCCARD_FEATURE = (PCCARD_MEM_BASE + 0x01);
PCCARD_SECTOR = (PCCARD_MEM_BASE + 0x02);
PCCARD_LOWLBA = (PCCARD_MEM_BASE + 0x03);
PCCARD_MIDLBA = (PCCARD_MEM_BASE + 0x04);
PCCARD_HIGHLBA = (PCCARD_MEM_BASE + 0x05);
PCCARD_DEVICE = (PCCARD_MEM_BASE + 0x06);
PCCARD_STATUS = (PCCARD_MEM_BASE + 0x07);
PCCARD_COMMAND = (PCCARD_MEM_BASE + 0x07);
//PCCARD_DUP_EVEN = (PCCARD_MEM_BASE + 0x08);
//PCCARD_DUP_ODD = (PCCARD_MEM_BASE + 0x09);
//PCCARD_DUP_ERR = (PCCARD_MEM_BASE + 0x0D);
//PCCARD_DUP_FEATURE =(PCCARD_MEM_BASE + 0x0D);
//PCCARD_ALTANATE = (PCCARD_MEM_BASE + 0x0E);
//PCCARD_CONTROL = (PCCARD_MEM_BASE + 0x0E);
//PCCARD_DRV_ADDR = (PCCARD_MEM_BASE + 0x0F);
Outp8(PCCARD_CONFIG_OPTION, PCCARD_MEM_MODE);
}
return TRUE;
}
bool OpenPccardMediaWithMode(unsigned int mode)
{
// TDelay timer setting
SetResTDelay(10); // TDelay 1 unit = 10us
InitTDelayFunc();
// GPIO, EBI setting
rEBICON |= (1<<10)|(1<<9); // bank3_cfg->CF,bank2_cfg->CF
rGPGCON |= (3<<30)|(3<<28)|(3<<26)|(3<<24)|(3<<22); //nCARD_PWREN, RESET_CF,nRE3G_CF,nINPACK,nIREQ_CF
#ifdef __EVT1
//rGPACDH = 0x1aa8a; // GPA10 RDATA_OEN setting
#else
rGPACON |= (1<<27)|(1<<11)|(1<<14)|(1<<13);// nWE_CF,nOE_CF,nRCS3,nRCS2 enable //S3C2443X01
#endif
rMISCCR &=(~(1<<30)); // card detect when card is detected ,the bit should be '0'.
// Buffer direction mode setting for SMDK2443 061027
rGPBCON = rGPBCON & ~((3<<8)|(3)) | (1<<8)|(1); // GPB0,4 output setting (TOUT0, TCLK - TP21,20)
rGPBDAT &= ~((1<<4)|(1)); // GPB0,4 -> low => pc card mode
// CF controller - PC card mode setting
Outp32(ATA_MUX, 0x06); // Output pad disable, Card power off, PC card mode
TDelay(100);
Outp32(ATA_MUX, 0x02); // Output pad enable, Card power off, PC card mode
TDelay(100);
Outp32(ATA_MUX, 0x00); // Card Power on (PC Card mode)
// wait for at least 20ms (SanDisk: 25ms, MicroDrive: 125ms, Hagiwara: )
// No other method available.
TDelay(12500); // 125ms
// Card configuration
rPCCARD_CFG = (1<<11)|(1<<10)|(1<<9)|(1<<8); // wain en, attr mem 16bit, com mem 16bit, IO 16bit
rPCCARD_INT = (1<<10)|(1<<9)|(1<<8); // mask ERR, IREQ, CD
rPCCARD_ATTR = (3<<16)|(0x19<<8)|(9); // Timing Hold, Command, Setup in attr mem mode
rPCCARD_IO = (3<<16)|(0x19<<8)|(9); // Timing Hold, Command, Setup in IO mode
rPCCARD_COMM = (3<<16)|(0x19<<8)|(9); // Timing Hold, Command, Setup in comm mem mode
// Card reset
rPCCARD_CFG |= (1<<13);
TDelay(100); // 1ms
rPCCARD_CFG &= ~(1<<13);
TDelay(10000); // 100ms
// Change access mode
ChangePccardMode(mode);
return TRUE;
}
bool ClosePccardMedia(void)
{
// Output pad disable, Card power off, PC card mode
Outp32(ATA_MUX, 0x06);
return TRUE;
}
void GetAttribData(unsigned int index, unsigned char *data)
{
Inp8(PCCARD_ATT_BASE+index, *data);
}
void ReadPccardRegister(unsigned int nRegister, unsigned char *data)
{
Inp8(nRegister, *data);
}
void WritePccardRegister(unsigned int nRegister, unsigned char nValue)
{
unsigned char temp;
do
{
ReadPccardRegister(PCCARD_STATUS, &temp);
} while (temp == 0x80) ;
Outp8(nRegister, nValue);
DbgPccard(("reg addr : 0x%x\n", nRegister));
}
void PutDataToPccardDevice(unsigned short nData)
{
Outp16(PCCARD_DATA, nData);
}
void GetDataFromPccardDevice(unsigned short *uData)
{
Inp16(PCCARD_DATA, *uData);
}
bool ReadBlocks(unsigned int uStBlock, unsigned int uBlocks, unsigned int uBufAddr)
{
// uBlocks: sector count
// uLba: (head&0x0f)<<24 | (LBA_high<<16) | (LBA_mid<<8) | LBA_low
// uDstAddr: host address
unsigned char temp;
unsigned short* uCurrentAddr = (unsigned short*) uBufAddr;
unsigned int i,j;
unsigned int op_time=0;
#if PERF_TEST_PCCARD
SetResStopwatch(10000); // us order, 10000us = 10ms
StartStopwatch(); // Start timer
#endif
WritePccardRegister(PCCARD_FEATURE,0);
WritePccardRegister(PCCARD_SECTOR,uBlocks);
WritePccardRegister(PCCARD_LOWLBA,(uStBlock&0x00ff));
WritePccardRegister(PCCARD_MIDLBA,((uStBlock>>8)&0x00ff));
WritePccardRegister(PCCARD_HIGHLBA,((uStBlock>>16)&0x00ff));
WritePccardRegister(PCCARD_DEVICE,((uStBlock>>24)&0x000f) | 0xe0); //LBA enabled, Drive 0
#ifdef DBG_PCCARD
ReadPccardRegister(PCCARD_SECTOR,&temp);
printf("Sector W:0x%x, R:0x%x\n",uBlocks,temp);
ReadPccardRegister(PCCARD_LOWLBA,&temp);
printf("lLBA W:0x%x, R:0x%x\n",(uStBlock&0x00ff),temp);
ReadPccardRegister(PCCARD_MIDLBA,&temp);
printf("mLBA W:0x%x, R:0x%x\n",((uStBlock>>8)&0x00ff),temp);
ReadPccardRegister(PCCARD_HIGHLBA,&temp);
printf("hLBA W:0x%x, R:0x%x\n",((uStBlock>>16)&0x00ff),temp);
ReadPccardRegister(PCCARD_DEVICE,&temp); //LBA enabled, Drive 0
printf("device W:0x%x, R:0x%x\n",((uStBlock>>24)&0x000f) | 0xe0,temp);
#endif
WritePccardRegister(PCCARD_COMMAND, READSECTOR);
do
{
ReadPccardRegister(PCCARD_STATUS, &temp);
TDelay(1); // need over 25MHz
DbgPccard(("(0x%x) ",temp));
}
while(temp != 0x58) ;
#if PERF_TEST_PCCARD_D
SetResStopwatch(10000); // us order, 10000us = 10ms
StartStopwatch(); // Start timer
#endif
for (j=0; j<uBlocks; j++)
{
for (i=0; i<512/2; i++)
{
#if 1 // both case are OK
GetDataFromPccardDevice(uCurrentAddr);
#else
Inp16(PCCARD_BASE+0x400+i*2, *uCurrentAddr);
#endif
uCurrentAddr++;
}
do
{
ReadPccardRegister(PCCARD_STATUS, &temp);
TDelay(1); // need over 25MHz
DbgPccard(("{0x%x} ",temp));
}
while(temp != 0x50 && temp != 0x58);
}
#if PERF_TEST_PCCARD | PERF_TEST_PCCARD_D
op_time = EndStopwatch(); // end timer, us order
printf (" Reading time : %d us, Performance : %lf MByte/sec\n"
,op_time,(float)(uBlocks*512./op_time));
#endif
return TRUE;
}
bool WriteBlocks(unsigned int uStBlock, unsigned int uBlocks, unsigned int uBufAddr)
{
unsigned char temp;
unsigned short* uCurrentAddr = (unsigned short*) uBufAddr;
unsigned int i,j;
unsigned int op_time=0;
#if PERF_TEST_PCCARD
SetResStopwatch(10000); // us order, 10000us = 10ms
StartStopwatch(); // Start timer
#endif
// uBlocks: sector count
// uLba: (head&0x0f)<<24 | (LBA_high<<16) | (LBA_mid<<8) | LBA_low
// uSrcAddr: host address
WritePccardRegister(PCCARD_FEATURE,0);
WritePccardRegister(PCCARD_SECTOR,uBlocks);
WritePccardRegister(PCCARD_LOWLBA,(uStBlock&0x00ff));
WritePccardRegister(PCCARD_MIDLBA,((uStBlock>>8)&0x00ff));
WritePccardRegister(PCCARD_HIGHLBA,((uStBlock>>16)&0x00ff));
WritePccardRegister(PCCARD_DEVICE,((uStBlock>>24)&0x000f) | 0xe0); //LBA enabled, Drive 0
#ifdef DBG_PCCARD
ReadPccardRegister(PCCARD_SECTOR,&temp);
printf("Sector W:0x%x, R:0x%x\n",uBlocks,temp);
ReadPccardRegister(PCCARD_LOWLBA,&temp);
printf("lLBA W:0x%x, R:0x%x\n",(uStBlock&0x00ff),temp);
ReadPccardRegister(PCCARD_MIDLBA,&temp);
printf("mLBA W:0x%x, R:0x%x\n",((uStBlock>>8)&0x00ff),temp);
ReadPccardRegister(PCCARD_HIGHLBA,&temp);
printf("hLBA W:0x%x, R:0x%x\n",((uStBlock>>16)&0x00ff),temp);
ReadPccardRegister(PCCARD_DEVICE,&temp); //LBA enabled, Drive 0
printf("device W:0x%x, R:0x%x\n",((uStBlock>>24)&0x000f) | 0xe0,temp);
#endif
WritePccardRegister(PCCARD_COMMAND, WRITESECTOR);
do
{
ReadPccardRegister(PCCARD_STATUS, &temp);
TDelay(1); // need over 25MHz
DbgPccard(("[0x%x] ",temp));
}
while(temp != 0x58) ;
#if PERF_TEST_PCCARD_D
SetResStopwatch(10000); // us order, 10000us = 10ms
StartStopwatch(); // Start timer
#endif
for (j=0; j<uBlocks; j++)
{
for (i=0; i<512/2; i++)
{
#if 1 // both case are OK
PutDataToPccardDevice(*uCurrentAddr);
#else
Outp16(PCCARD_BASE+0x400+i*2, *uCurrentAddr);
#endif
uCurrentAddr++;
}
do
{
ReadPccardRegister(PCCARD_STATUS, &temp);
TDelay(1); // need over 25MHz
DbgPccard(("|0x%x| ",temp));
}
while(temp != 0x50 && temp != 0x58) ;
}
#if PERF_TEST_PCCARD | PERF_TEST_PCCARD_D
op_time = EndStopwatch(); // end timer, us order
printf (" Writing time : %d us, Performance : %lf MByte/sec\n"
,op_time,(float)(uBlocks*512./op_time));
#endif
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -