📄 pccard.c
字号:
void PCCARD_ReadBlocks(u8 ucCon, u32 uDeviceLba, u32 uBlockCount, u32 uBufAddr)
{
u8 ucTaskFileRegValue = 0;
u32 uBlockLoopCount = 0;
u32 uByteLoopCount = 0;
u16* usCurrBufAddr = (u16*) g_oaPCCARDInform[ucCon].puPCCARDReadBuf;
u16 usReadData = 0;
// Disp("uDeviceLab : 0x%x, uBlockCount : 0x%x\n", uDeviceLba, uBlockCount);
#if PERF_TEST_PCCARD
u32 uElapsedTime = 0;
#endif
//-------- step 1. Set up task file registers ------------
// uBlocks: sector count
// uLba: (head&0x0f)<<24 | (LBA_high<<16) | (LBA_mid<<8) | LBA_low
// uSrcAddr: host address
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_FEATURE, 0);
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_SECTOR, uBlockCount);
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_LOWLBA, (uDeviceLba&0xff));
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_MIDLBA, ((uDeviceLba>> 8)&0xff));
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_HIGHLBA, ((uDeviceLba>>16)&0xff));
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_DEVICE, ((uDeviceLba>>24)&0x0f) | 0xe0); //LBA enabled, Drive 0
#ifdef DBG_PCCARD
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_SECTOR);
printf("Sector W:0x%x, R:0x%x\n",uBlockCount,ucTaskFileRegValue);
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_LOWLBA);
printf("lLBA W:0x%x, R:0x%x\n",(uDeviceLba&0x00ff),ucTaskFileRegValue);
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_MIDLBA);
printf("mLBA W:0x%x, R:0x%x\n",((uDeviceLba>>8)&0x00ff),ucTaskFileRegValue);
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_HIGHLBA);
printf("hLBA W:0x%x, R:0x%x\n",((uDeviceLba>>16)&0x00ff),ucTaskFileRegValue);
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_DEVICE);
printf("device W:0x%x, R:0x%x\n",((uDeviceLba>>24)&0x000f) | 0xe0,ucTaskFileRegValue);
#endif
//-------- step 2. Set '0x30(eATA_CMD_WRITESECTOR)' in the command register of task file registers ------------
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_COMMAND, eATA_CMD_READSECTOR );
//-------- step 3. Read status register & compare with '0x58' ------------
// 0x58 : Data of device side is ready. The host should not write the command register when 0x58. (DRQ = 1)
do
{
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_STATUS);
Delay(1); // need over 25MHz
// Disp("[STATUS:0x%x]\n", ucTaskFileRegValue);
}
while( ucTaskFileRegValue != 0x58) ;
#if PERF_TEST_PCCARD
StartTimer(0);
#endif
//-------- step 4. Writes the data register until 256 times(512bytes) ------------
// Note. We can transfer data in 16bit mode because PCCARD_DATA register is overlapped to the PCCARD_ERROR register.
for ( uBlockLoopCount = 0; uBlockLoopCount < uBlockCount; uBlockLoopCount++ )
{
for ( uByteLoopCount = 0; uByteLoopCount < (512/2); uByteLoopCount++ )
{
usReadData = PCCARD_GetTaskFileRegValue16(ucCon, eCF_TASKFILE_DATA);
// printf("BufADDR:0x%x, Data : 0x%x\n", usCurrBufAddr, usReadData);
*usCurrBufAddr = usReadData;
usCurrBufAddr++;
}
//-------- step 3. Read status register & compare with '0x50' ------------
do
{
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_STATUS);
Delay(1); // need over 25MHz
// Disp("[STATUS:0x%x]\n", ucTaskFileRegValue);
}
while( ucTaskFileRegValue != 0x50 && ucTaskFileRegValue != 0x58 ) ;
}
#if PERF_TEST_PCCARD
uElapsedTime = StopTimer(0);
Disp(" PCCard Mode Reading time : %d us, Performance : %lf MByte/sec\n"
,uElapsedTime,(float)(uBlockCount*512./uElapsedTime));
#endif
}
//////////
// Function Name : PCCARD_WriteBlocks
// Function Description : This function implements block write function to PCCARD TaskFile Registers.
// Input : ucCon - PCCRAD controller number
// uDeviceLba - LBA number
// uBlockCount - Block number
// uBufAddr - Buffer Address
// Output : NONE
// Version : v0.1
void PCCARD_WriteBlocks(u8 ucCon, u32 uDeviceLba, u32 uBlockCount, u32 uBufAddr)
{
u8 ucTaskFileRegValue = 0;
u32 uBlockLoopCount = 0;
u32 uByteLoopCount = 0;
u16* usCurrBufAddr = (u16*) g_oaPCCARDInform[ucCon].puPCCARDWriteBuf;
// Disp("uDeviceLab : 0x%x, uBlockCount : 0x%x\n", uDeviceLba, uBlockCount);
#if PERF_TEST_PCCARD
u32 uElapsedTime = 0;
#endif
//-------- step 1. Set up task file registers ------------
// uBlocks: sector count
// uLba: (head&0x0f)<<24 | (LBA_high<<16) | (LBA_mid<<8) | LBA_low
// uSrcAddr: host address
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_FEATURE, 0);
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_SECTOR, uBlockCount);
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_LOWLBA, (uDeviceLba&0xff));
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_MIDLBA, ((uDeviceLba>> 8)&0xff));
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_HIGHLBA, ((uDeviceLba>>16)&0xff));
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_DEVICE, ((uDeviceLba>>24)&0x0f) | 0xe0); //LBA enabled, Drive 0
#ifdef DBG_PCCARD
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_SECTOR);
printf("Sector W:0x%x, R:0x%x\n",uBlockCount,ucTaskFileRegValue);
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_LOWLBA);
printf("lLBA W:0x%x, R:0x%x\n",(uDeviceLba&0x00ff),ucTaskFileRegValue);
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_MIDLBA);
printf("mLBA W:0x%x, R:0x%x\n",((uDeviceLba>>8)&0x00ff),ucTaskFileRegValue);
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_HIGHLBA);
printf("hLBA W:0x%x, R:0x%x\n",((uDeviceLba>>16)&0x00ff),ucTaskFileRegValue);
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_DEVICE);
printf("device W:0x%x, R:0x%x\n",((uDeviceLba>>24)&0x000f) | 0xe0,ucTaskFileRegValue);
#endif
//-------- step 2. Set '0x30(eATA_CMD_WRITESECTOR)' in the command register of task file registers ------------
PCCARD_SetTaskFileRegValue(ucCon, eCF_TASKFILE_COMMAND, eATA_CMD_WRITESECTOR );
//-------- step 3. Read status register & compare with '0x58' ------------
// 0x58 : Data of device side is ready. The host should not write the command register when 0x58. (DRQ = 1)
do
{
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_STATUS);
Delay(1); // need over 25MHz
Disp("[STATUS:0x%x]\n", ucTaskFileRegValue);
}
while( ucTaskFileRegValue != 0x58) ;
#if PERF_TEST_PCCARD
StartTimer(0);
#endif
//-------- step 4. Writes the data register until 256 times(512bytes) ------------
// Note. We can transfer data in 16bit mode because PCCARD_DATA register is overlapped to the PCCARD_ERROR register.
for ( uBlockLoopCount = 0; uBlockLoopCount < uBlockCount; uBlockLoopCount++ )
{
for ( uByteLoopCount = 0; uByteLoopCount < (512/2); uByteLoopCount++ )
{
PCCARD_SetTaskFileRegValue16(ucCon, eCF_TASKFILE_DATA, *usCurrBufAddr );
// printf("BufADDR:0x%x\n", usCurrBufAddr);
usCurrBufAddr++;
}
//-------- step 3. Read status register & compare with '0x50' ------------
do
{
ucTaskFileRegValue = PCCARD_GetTaskFileRegValue(ucCon, eCF_TASKFILE_STATUS);
Delay(1); // need over 25MHz
// Disp("[STATUS:0x%x]\n", ucTaskFileRegValue);
}
while( ucTaskFileRegValue != 0x50 && ucTaskFileRegValue != 0x58 ) ;
}
#if PERF_TEST_PCCARD
uElapsedTime = StopTimer(0);
Disp(" PCCard Mode Writing time : %d us, Performance : %lf MByte/sec\n"
,uElapsedTime,(float)(uBlockCount*512./uElapsedTime));
#endif
}
//=========================================================================
// ATTRIBUTE MEMORY AREA
//=========================================================================
/*---------------------------------- APIs of controling Attribute memory area in PCCARD mode ---------------------------------*/
//////////
// Function Name : PCCARD_SetAttConfigBaseAddr
// Function Description : This function sets up the base address of PCCARD Attribute Configuration Registers.
// Input : ucCon - PCCRAD controller number
// Output : uBaseAddress - the baseaddress of PCCARD Task File registers
// Version : v0.1
void PCCARD_SetAttConfigBaseAddr(u8 ucCon, u32 uBaseAddress)
{
g_paPCCARDATTBase[ucCon] = (void *)uBaseAddress;
}
//////////
// Function Name : PCCARD_SetCardMode
// Function Description :
// This function changes CF CARD mode.
// Input : ucCon - PCCARD Controller Number
// ePccardAttId - Attribute configuration register select
// ePccardMode -MEM/IO1/IO2/IO3 mode select
// Output : NONE
// Version : v0.1
void PCCARD_SetCardMode(u8 ucCon, u8 ucPccardAttIdOffset, ePCCARD_MODE ePccardMode)
{
u8 uRegValue = 0;
uRegValue = PCCARD_GetAttRegValue(ucCon, ucPccardAttIdOffset);
uRegValue = uRegValue & ~(0x3f<< 0 ) | (ePccardMode<<0);
PCCARD_SetAttRegValue(ucCon, ucPccardAttIdOffset, uRegValue);
}
//////////
// Function Name : PCCARD_GetAttRegValue
// Function Description : This function gets the value of PCCARD Registers.
// Input : ucCon - PCCRAD controller number
// uPCCARDAttRegId - the Id of PCCARD Attribute Configuration Register
// Output : *puPCCARDReg - the value of specified register
// Version : v0.1
u8 PCCARD_GetAttRegValue(u8 ucCon, u8 uPCCARDAttRegIdOffset)
{
volatile u16 * puPCCARDAttBaseAddr;
volatile u16 * puPCCARDReg;
puPCCARDAttBaseAddr = &(PCCARD_ATTR(ucCon)->rPCCARD_CONFIG_OPTION);
puPCCARDReg = puPCCARDAttBaseAddr + uPCCARDAttRegIdOffset;
return (u8)(*puPCCARDReg);
}
//////////
// Function Name : PCCARD_SetAttRegValue
// Function Description : This function clears the value of PCCARD TaskFile Registers.
// Input : ucCon - PCCRAD controller number
// ucPCCARDRegId - the Id of PCCARD Registers
// uValue - the value of register
// Output : NONE
// Version : v0.1
void PCCARD_SetAttRegValue(u8 ucCon, u8 uPCCARDAttRegIdOffset, u8 uValue)
{
volatile u16 * puPCCARDAttBaseAddr;
volatile u16 * puPCCARDReg;
puPCCARDAttBaseAddr = &(PCCARD_ATTR(ucCon)->rPCCARD_CONFIG_OPTION);
puPCCARDReg = puPCCARDAttBaseAddr + uPCCARDAttRegIdOffset;
*puPCCARDReg = uValue;
}
//////////
// Function Name : PCCARD_GetAttribData
// Function Description : This function gets the value of PCCARD Registers.
// Input : ucCon - PCCRAD controller number
// uIndex - the Index of PCCARD Attribute Memory
// Output : *puPCCARDReg - the value of specified register
// Version : v0.1
u8 PCCARD_GetAttribData(u8 ucCon, u8 uIndex)
{
volatile u16 * puPCCARDAttBaseAddr;
volatile u16 * puPCCARDReg;
puPCCARDAttBaseAddr = &(PCCARD_ATTR(ucCon)->rPCCARD_CONFIG_OPTION);
puPCCARDAttBaseAddr -= 0x100;
puPCCARDReg = puPCCARDAttBaseAddr + uIndex;
// printf("uIndex:0x%x, BaseAddr:0x%x, DestAddr:0x%x\n", uIndex, puPCCARDAttBaseAddr, puPCCARDReg);
return (u8)(*puPCCARDReg);
}
//////////
// Function Name : PCCARD_SetAttribData
// Function Description : This function clears the value of PCCARD TaskFile Registers.
// Input : ucCon - PCCRAD controller number
// uIndex - the Index of PCCARD Attribute Memory
// uValue - the value of register
// Output : NONE
// Version : v0.1
void PCCARD_SetAttribData(u8 ucCon, u8 uIndex, u8 uValue)
{
volatile u16 * puPCCARDAttBaseAddr;
volatile u8 * puPCCARDReg;
puPCCARDAttBaseAddr = &(PCCARD_ATTR(ucCon)->rPCCARD_CONFIG_OPTION);
puPCCARDAttBaseAddr -= 0x100;
puPCCARDReg = (u8 *)puPCCARDAttBaseAddr + uIndex;
*puPCCARDReg = uValue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -