📄 pccard.cpp
字号:
#include <stdio.h>
#include "system.h"
#include "2443addr.h"
#include "pccard.h"
#include "etc.h"
#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 U32 PCCARD_DATA = (PCCARD_MEM_BASE + 0x00);
static U32 PCCARD_ERROR = (PCCARD_MEM_BASE + 0x01);
static U32 PCCARD_FEATURE = (PCCARD_MEM_BASE + 0x01);
static U32 PCCARD_SECTOR = (PCCARD_MEM_BASE + 0x02);
static U32 PCCARD_LOWLBA = (PCCARD_MEM_BASE + 0x03);
static U32 PCCARD_MIDLBA = (PCCARD_MEM_BASE + 0x04);
static U32 PCCARD_HIGHLBA = (PCCARD_MEM_BASE + 0x05);
static U32 PCCARD_DEVICE = (PCCARD_MEM_BASE + 0x06);
static U32 PCCARD_STATUS = (PCCARD_MEM_BASE + 0x07);
static U32 PCCARD_COMMAND = (PCCARD_MEM_BASE + 0x07);
static U32 PCCARD_DUP_EVEN = (PCCARD_MEM_BASE + 0x08);
static U32 PCCARD_DUP_ODD = (PCCARD_MEM_BASE + 0x09);
static U32 PCCARD_DUP_ERR = (PCCARD_MEM_BASE + 0x0D);
static U32 PCCARD_DUP_FEATURE = (PCCARD_MEM_BASE + 0x0D);
static U32 PCCARD_ALTANATE = (PCCARD_MEM_BASE + 0x0E);
static U32 PCCARD_CONTROL = (PCCARD_MEM_BASE + 0x0E);
static U32 PCCARD_DRV_ADDR = (PCCARD_MEM_BASE + 0x0F);
//=========================================================================
// PCCARD Functions
//=========================================================================
bool PCCARD::ChangeMode(U32 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);
}
}
bool PCCARD::OpenMedia(U32 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
rGPACON |= (1<<27)|(1<<11)|(1<<14)|(1<<13);// nWE_CF,nOE_CF,nRCS3,nRCS2 enable
rMISCCR &=(~(1<<30)); // card detect when card is detected ,the bit should be '0'.
// 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_CNF_STATUS = (1<<11)|(1<<10)|(1<<9)|(1<<8); // wain en, attr mem 16bit, com mem 16bit, IO 16bit
rPCCARD_INTMSK_SRC = (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_CNF_STATUS |= (1<<13);
TDelay(100); // 1ms
rPCCARD_CNF_STATUS &= ~(1<<13);
TDelay(10000); // 100ms
// Change access mode
ChangeMode(mode);
return true;
}
bool PCCARD::CloseMedia(void)
{
// Output pad disable, Card power off, PC card mode
Outp32(ATA_MUX, 0x06);
return true;
}
void PCCARD::GetAttribData(U32 index, U8& data)
{
Inp8(PCCARD_ATT_BASE+index, data);
}
void PCCARD::ReadRegister(U32 nRegister, U8& data)
{
Inp8(nRegister, data);
}
void PCCARD::WriteRegister(U32 nRegister, U8 nValue)
{
U8 temp;
do
{
ReadRegister(PCCARD_STATUS, temp);
} while (temp == 0x80) ;
Outp8(nRegister, nValue);
DbgPccard(("reg addr : 0x%x\n", nRegister));
}
void PCCARD::PutDataToDevice(U16 nData)
{
Outp16(PCCARD_DATA, nData);
}
void PCCARD::GetDataFromDevice(U16& uData)
{
Inp16(PCCARD_DATA, uData);
}
bool PCCARD::ReadBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
// uBlocks: sector count
// uLba: (head&0x0f)<<24 | (LBA_high<<16) | (LBA_mid<<8) | LBA_low
// uDstAddr: host address
U8 temp;
U16* uCurrentAddr = (U16*) uBufAddr;
WriteRegister(PCCARD_FEATURE,0);
WriteRegister(PCCARD_SECTOR,uBlocks);
WriteRegister(PCCARD_LOWLBA,(uStBlock&0x00ff));
WriteRegister(PCCARD_MIDLBA,((uStBlock>>8)&0x00ff));
WriteRegister(PCCARD_HIGHLBA,((uStBlock>>16)&0x00ff));
WriteRegister(PCCARD_DEVICE,((uStBlock>>24)&0x000f) | 0xe0); //LBA enabled, Drive 0
#ifdef DBG_PCCARD
ReadRegister(PCCARD_SECTOR,temp);
printf("Sector W:0x%x, R:0x%x\n",uBlocks,temp);
ReadRegister(PCCARD_LOWLBA,temp);
printf("lLBA W:0x%x, R:0x%x\n",(uStBlock&0x00ff),temp);
ReadRegister(PCCARD_MIDLBA,temp);
printf("mLBA W:0x%x, R:0x%x\n",((uStBlock>>8)&0x00ff),temp);
ReadRegister(PCCARD_HIGHLBA,temp);
printf("hLBA W:0x%x, R:0x%x\n",((uStBlock>>16)&0x00ff),temp);
ReadRegister(PCCARD_DEVICE,temp); //LBA enabled, Drive 0
printf("device W:0x%x, R:0x%x\n",((uStBlock>>24)&0x000f) | 0xe0,temp);
#endif
WriteRegister(PCCARD_COMMAND, READSECTOR);
do
{
ReadRegister(PCCARD_STATUS, temp);
TDelay(1); // need over 25MHz
DbgPccard(("(0x%x) ",temp));
}
while(temp != 0x58) ;
for (U32 j=0; j<uBlocks; j++)
{
for (U32 i=0; i<512/2; i++)
{
#if 1 // both case are OK
GetDataFromDevice(*uCurrentAddr);
#else
Inp16(PCCARD_BASE+0x400+i*2, *uCurrentAddr);
#endif
uCurrentAddr++;
}
do
{
ReadRegister(PCCARD_STATUS, temp);
TDelay(1); // need over 25MHz
DbgPccard(("{0x%x} ",temp));
}
while(temp != 0x50 && temp != 0x58);
}
return true;
}
bool PCCARD::WriteBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
U8 temp;
U16* uCurrentAddr = (U16*) uBufAddr;
// uBlocks: sector count
// uLba: (head&0x0f)<<24 | (LBA_high<<16) | (LBA_mid<<8) | LBA_low
// uSrcAddr: host address
WriteRegister(PCCARD_FEATURE,0);
WriteRegister(PCCARD_SECTOR,uBlocks);
WriteRegister(PCCARD_LOWLBA,(uStBlock&0x00ff));
WriteRegister(PCCARD_MIDLBA,((uStBlock>>8)&0x00ff));
WriteRegister(PCCARD_HIGHLBA,((uStBlock>>16)&0x00ff));
WriteRegister(PCCARD_DEVICE,((uStBlock>>24)&0x000f) | 0xe0); //LBA enabled, Drive 0
#ifdef DBG_PCCARD
ReadRegister(PCCARD_SECTOR,temp);
printf("Sector W:0x%x, R:0x%x\n",uBlocks,temp);
ReadRegister(PCCARD_LOWLBA,temp);
printf("lLBA W:0x%x, R:0x%x\n",(uStBlock&0x00ff),temp);
ReadRegister(PCCARD_MIDLBA,temp);
printf("mLBA W:0x%x, R:0x%x\n",((uStBlock>>8)&0x00ff),temp);
ReadRegister(PCCARD_HIGHLBA,temp);
printf("hLBA W:0x%x, R:0x%x\n",((uStBlock>>16)&0x00ff),temp);
ReadRegister(PCCARD_DEVICE,temp); //LBA enabled, Drive 0
printf("device W:0x%x, R:0x%x\n",((uStBlock>>24)&0x000f) | 0xe0,temp);
#endif
WriteRegister(PCCARD_COMMAND, WRITESECTOR);
do
{
ReadRegister(PCCARD_STATUS, temp);
TDelay(1); // need over 25MHz
DbgPccard(("[0x%x] ",temp));
}
while(temp != 0x58) ;
for (U32 j=0; j<uBlocks; j++)
{
for (U32 i=0; i<512/2; i++)
{
#if 1 // both case are OK
PutDataToDevice(*uCurrentAddr);
#else
Outp16(PCCARD_BASE+0x400+i*2, *uCurrentAddr);
#endif
uCurrentAddr++;
}
do
{
ReadRegister(PCCARD_STATUS, temp);
TDelay(1); // need over 25MHz
DbgPccard(("|0x%x| ",temp));
}
while(temp != 0x50 && temp != 0x58) ;
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -