📄 cfc_data.c
字号:
/***************************************************************************
* File: cfc_data.c - Read / Write Functions
*
* The content of this file or document is CONFIDENTIAL and PROPRIETARY
* to Jade Technologies Co., Ltd. It is subject to the terms of a
* License Agreement between Licensee and Jade Technologies Co., Ltd.
* restricting among other things, the use, reproduction, distribution
* and transfer. Each of the embodiments, including this information
* and any derivative work shall retain this copyright notice.
*
* Copyright (c) 2005 Jade Technologies Co., Ltd.
* All rights reserved.
****************************************************************************/
#include "cfcard.h"
//-----------------------------------------------------------------------------
// Global Variables and Macros in CFC_DATA.C
//-----------------------------------------------------------------------------
extern HANDLE cfIntrEvent;
extern HANDLE cfIntrThread;
extern HANDLE cfDataEvent;
extern unsigned char ChannelNumber;
extern unsigned long InterruptID;
extern HANDLE DMAIntrEvent;
unsigned long TempBuf[SECTORS_PER_BATCH*BYTES_PER_SECTOR/4];
#define MIN(__x,__y) ((__x)<(__y)?(__x):(__y))
#define RETRYNUM 5
//------------------------------------------------------------------------------
//
// Safe read - read sectors from the card
//
// Arguments:
// regs - Cf registers' base address
// buf - buffer to receive data
// sectornum - the number of first sector to be read
// sectorcnt - how many sectors to be read
//
// Functions:
// Call function CFC_ReadSectors_FIFO or CFC_ReadSectors_DMA
// to read data from sectors. Retry if error occured.
//
//------------------------------------------------------------------------------
BOOL
CFC_SafeRead(
CFRegs *regs,
unsigned short *buf,
unsigned long sectornum,
unsigned long sectorcnt
)
{
unsigned long error = 0;
int i;
int retry;
int batchnum = (int)((sectorcnt-1)/SECTORS_PER_BATCH); // transfer at most 128 sectors every time.
int sectorcntthis; // transfer sector number this time.
unsigned char * bufthis;
for (i=0;i<=batchnum;i++)
{
retry = RETRYNUM+1;
sectorcntthis = MIN((int)sectorcnt, (int)SECTORS_PER_BATCH);
if ((int)buf&0x3)
bufthis = (unsigned char*)TempBuf;
else
bufthis = (unsigned char*)buf;
// safe read
while (--retry)
{
error = 0;
if (sectorcnt > SECTORS_NEED_DMA_READ && InterruptID != 0 && SECTORS_NEED_DMA_READ != 0xFF)
{
if (CFC_ReadSectors_DMA(regs, (unsigned short*)bufthis, sectornum, sectorcntthis, &error))
break;
}
error = 0;
if (CFC_ReadSectors_FIFO(regs, (unsigned short*)bufthis, sectornum, sectorcntthis, &error))
break;
}
if ((int)buf&0x3)
memcpy(buf, TempBuf, BYTES_PER_SECTOR * sectorcntthis);
if (retry == 0)
{
break;
}
// to next batch
buf += BYTES_PER_SECTOR * sectorcntthis/(sizeof(unsigned short));
sectornum += sectorcntthis;
sectorcnt -= sectorcntthis;
}
if (retry && !sectorcnt)
return TRUE;
return FALSE;
}
//------------------------------------------------------------------------------
//
// Safe write - write sectors to the card
//
// Arguments:
// regs - Cf registers' base address
// buf - buffer to send data
// sectornum - the number of first sector to be write
// sectorcnt - how many sectors to be write
//
// Functions:
// Call function CFC_WriteSectors_FIFO or CFC_WriteSectors_DMA
// to write data to sectors. Retry if error occured.
//
//------------------------------------------------------------------------------
BOOL
CFC_SafeWrite(
CFRegs *regs,
unsigned short *buf,
unsigned long sectornum,
unsigned long sectorcnt
)
{
unsigned long error = 0;
int i;
int retry;
int batchnum = (int)((sectorcnt-1)/SECTORS_PER_BATCH); // transfer at most 255 sectors every time.
int sectorcntthis; // transfer sector number this time.
unsigned char * bufthis;
for (i=0;i<=batchnum;i++)
{
retry = RETRYNUM+1;
sectorcntthis = MIN((int)sectorcnt, (int)SECTORS_PER_BATCH);
if ((int)buf&0x3)
{
bufthis = (unsigned char*)TempBuf;
memcpy(TempBuf, buf, BYTES_PER_SECTOR * sectorcntthis);
}
else
bufthis = (unsigned char*)buf;
// safe write
while (--retry)
{
error = 0;
if (sectorcnt > SECTORS_NEED_DMA_WRITE && InterruptID != 0 && SECTORS_NEED_DMA_WRITE != 0xFF)
{
if (CFC_WriteSectors_DMA(regs, (unsigned short*)bufthis, sectornum, sectorcntthis, &error))
break;
}
error = 0;
if (CFC_WriteSectors_FIFO(regs, (unsigned short*)bufthis, sectornum, sectorcntthis, &error))
break;
}
if (retry == 0)
{
break;
}
// to next batch
buf += BYTES_PER_SECTOR * sectorcntthis/(sizeof(unsigned short));
sectornum += sectorcntthis;
sectorcnt -= sectorcntthis;
}
if (retry && !sectorcnt)
return TRUE;
return FALSE;
}
//------------------------------------------------------------------------------
//
// Read sectors from FIFO directly
//
// Arguments:
// regs - Cf registers' base address
// buf - buffer to receive data
// sectornum - the number of first sector to be read
// sectorcnt - how many sectors to be read
// errorcode - record error
//
// Functions:
// Send command to card, then read data from FIFO whenever FIFO is
// half full.
//
//------------------------------------------------------------------------------
BOOL
CFC_ReadSectors_FIFO(
CFRegs *regs,
unsigned short *buf,
unsigned long sectornum,
unsigned long sectorcnt,
unsigned long *errorcode)
{
unsigned long i = 0;
unsigned long k = SleepCircle;
unsigned char atastatus, ataerror;
unsigned long * Dbuf = (unsigned long *) buf;
unsigned long Opcode = DISK_IOCTL_READ;
unsigned long error = 0;
if (regs == NULL || buf == NULL)
error = 1;
if (!error)
{
AtaSetSectorNum(regs, (unsigned char)sectornum);
AtaSetCylinderLow(regs, (unsigned char)(sectornum>>8));
AtaSetCylinderHigh(regs, (unsigned char)(sectornum>>16));
AtaSetHead(regs, 0xe0 | (unsigned char)(sectornum>>24));
AtaSetSectorCount(regs, (unsigned char)sectorcnt);
AtaSetCommand(regs, ATA_CMD_READ);
while (k--)
{
AtaReadStatus(regs, atastatus);
if (atastatus == 0x58)
break;
if (atastatus & (0x01))
{
AtaReadError(regs, ataerror);
error = 2;
break;
}
}
}
if (!error)
{
CFC_SetFifoAccessMode(regs);
regs->CF_ADDR_FIFOreq = (1<<FIFOreq_ClearFifo)
| (1<<FIFOreq_IntrClr) | (1<<FIFOreq_FifoCntClr);
regs->CF_ADDR_SectorCfg = 0x7f00 + sectorcnt;
regs->CF_ADDR_FIFOreq = (1<<FIFOreq_StopFifo)
| (1<<FIFOreq_RXPush) | (1<<FIFOreq_RXPop) ;
while (i < (int)(BYTES_PER_SECTOR*sectorcnt/4))
{
unsigned long j;
regs->CF_ADDR_CFINTena = (1<<CfRawIntr_RxfifoHfReq);
if (WaitForSingleObject(cfDataEvent, 1000) == WAIT_TIMEOUT)
{
RETAILMSG(1, (_T("CFCARD: ReadSectorsFIFO - read rxfifohfreq TIMEOUT\r\n")));
regs->CF_ADDR_CFINTena = 0; //(1<<CfRawIntr_CfInsert) | (1<<CfRawIntr_CfRemove);
regs->CF_ADDR_CFINTR = CF_DATA_INTR_MASK;
InterruptDone(SYSINTR_CF);
error = 3;
break;
}
regs->CF_ADDR_CFINTena = 0; //(1<<CfRawIntr_CfInsert) | (1<<CfRawIntr_CfRemove);
for (j=0; j<16; j ++)
Dbuf[i++] = regs->CF_ADDR_FIFO;
regs->CF_ADDR_CFINTR = (1<<CfRawIntr_RxfifoHfReq);
InterruptDone(SYSINTR_CF);
if (regs->CF_ADDR_CFINTR & (1<<CfRawIntr_FifoUnderrun))
{
error = 4;
break;
}
}//while i<BYTES.../4
}
if (!error)
{
if (i == (int)(BYTES_PER_SECTOR*sectorcnt/4))
{
regs->CF_ADDR_CFINTena = (1<<CfRawIntr_RxPopOver);
if (WaitForSingleObject(cfDataEvent, 1000) == WAIT_TIMEOUT)
{
RETAILMSG(1, (_T("CFCARD: ReadSectorsFIFO - read rxpopover TIMEOUT\r\n")));
regs->CF_ADDR_CFINTena = 0; //(1<<CfRawIntr_CfInsert) | (1<<CfRawIntr_CfRemove);
regs->CF_ADDR_CFINTR = CF_DATA_INTR_MASK;
InterruptDone(SYSINTR_CF);
error = 5;
}
else
{
regs->CF_ADDR_CFINTena = 0; //(1<<CfRawIntr_CfInsert) | (1<<CfRawIntr_CfRemove);
regs->CF_ADDR_FIFOreq = (1<<FIFOreq_ClearFifo)
| (1<<FIFOreq_IntrClr) | (1<<FIFOreq_FifoCntClr);
regs->CF_ADDR_FIFOreq = 0x00;
regs->CF_ADDR_CFINTR = (1<<CfRawIntr_RxPopOver);
InterruptDone(SYSINTR_CF);
while (k--)
{
AtaReadStatus(regs, atastatus);
if (atastatus == 0x50)
break;
if (atastatus & 0x01)
{
AtaReadError(regs, ataerror);
error = 6;
break;
}
}
}
}//if i==BYTES.../4
else
error = 7;
}
if (error)
{
RETAILMSG(MSG_DATA, (_T("CFCARD: ReadSectorsFIFO - error:%d\r\n"), error));
if (errorcode)
*errorcode = error;
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Write sectors to FIFO directly
//
// Arguments:
// regs - Cf registers' base address
// buf - buffer to send data
// sectornum - the number of first sector to be write
// sectorcnt - how many sectors to be write
// errorcode - record error
//
// Functions:
// Send command to card, then write data to FIFO whenever FIFO is
// half empty.
//
//------------------------------------------------------------------------------
BOOL
CFC_WriteSectors_FIFO(
CFRegs *regs,
unsigned short *buf,
unsigned long sectornum,
unsigned long sectorcnt,
unsigned long *errorcode
)
{
unsigned long i = 0;
unsigned long k = SleepCircle;
unsigned char atastatus, ataerror;
unsigned long * Dbuf = (unsigned long *) buf;
unsigned long Opcode = DISK_IOCTL_WRITE;
unsigned long error = 0;
if (regs == NULL || buf == NULL)
error = 1;
if (!error)
{
AtaSetSectorNum(regs, (unsigned char)sectornum);
AtaSetCylinderLow(regs, (unsigned char)(sectornum>>8));
AtaSetCylinderHigh(regs, (unsigned char)(sectornum>>16));
AtaSetHead(regs, 0xe0 | (unsigned char)(sectornum>>24));
AtaSetSectorCount(regs, (unsigned char)sectorcnt);
AtaSetCommand(regs, ATA_CMD_WRITE);
while (k--)
{
AtaReadStatus(regs, atastatus);
if (atastatus == 0x58)
break;
if (atastatus & (0x01))
{
AtaReadError(regs, ataerror);
error = 2;
break;
}
}
}
if (!error)
{
CFC_SetFifoAccessMode(regs);
regs->CF_ADDR_FIFOreq = (1<<FIFOreq_ClearFifo)
| (1<<FIFOreq_IntrClr) | (1<<FIFOreq_FifoCntClr);
regs->CF_ADDR_SectorCfg = 0x7f00 + sectorcnt;
regs->CF_ADDR_FIFOreq = (1<<FIFOreq_StopFifo)
| (1<<FIFOreq_TXPush) | (1<<FIFOreq_TXPop) ;
while (i < (int)(BYTES_PER_SECTOR*sectorcnt/4))
{
unsigned long j;
regs->CF_ADDR_CFINTena = (1<<CfRawIntr_TxfifoHfReq);
if (WaitForSingleObject(cfDataEvent, 1000) == WAIT_TIMEOUT)
{
RETAILMSG(1, (_T("CFCARD: WriteSectorsFIFO - write txfifohfreq TIMEOUT\r\n")));
regs->CF_ADDR_CFINTena = 0; //(1<<CfRawIntr_CfInsert) | (1<<CfRawIntr_CfRemove);
regs->CF_ADDR_CFINTR = CF_DATA_INTR_MASK;
InterruptDone(SYSINTR_CF);
error = 3;
break;
}
regs->CF_ADDR_CFINTena = 0; //(1<<CfRawIntr_CfInsert) | (1<<CfRawIntr_CfRemove);
for (j=0; j<16; j ++)
regs->CF_ADDR_FIFO = Dbuf[i++];
regs->CF_ADDR_CFINTR = (1<<CfRawIntr_TxfifoHfReq);
InterruptDone(SYSINTR_CF);
if (regs->CF_ADDR_CFINTR & (1<<CfRawIntr_FifoUnderrun))
{
error = 4;
break;
}
}//while i<BYTES.../4
}
if (!error)
{
if (i == (int)(BYTES_PER_SECTOR*sectorcnt/4))
{
regs->CF_ADDR_CFINTena = (1<<CfRawIntr_TxPopOver);
if (WaitForSingleObject(cfDataEvent, 1000) == WAIT_TIMEOUT)
{
RETAILMSG(1, (_T("CFCARD: WriteSectorsFIFO - write txpopover TIMEOUT\r\n")));
regs->CF_ADDR_CFINTena = 0; //(1<<CfRawIntr_CfInsert) | (1<<CfRawIntr_CfRemove);
regs->CF_ADDR_CFINTR = CF_DATA_INTR_MASK;
InterruptDone(SYSINTR_CF);
error = 5;
}
else
{
regs->CF_ADDR_CFINTena = 0; //(1<<CfRawIntr_CfInsert) | (1<<CfRawIntr_CfRemove);
regs->CF_ADDR_FIFOreq = (1<<FIFOreq_ClearFifo)
| (1<<FIFOreq_IntrClr) | (1<<FIFOreq_FifoCntClr);
regs->CF_ADDR_FIFOreq = 0x00;
regs->CF_ADDR_CFINTR = (1<<CfRawIntr_TxPopOver);
InterruptDone(SYSINTR_CF);
while (k--)
{
AtaReadStatus(regs, atastatus);
if (atastatus == 0x50)
break;
if (atastatus & 0x01)
{
AtaReadError(regs, ataerror);
error = 6;
break;
}
}
}
}//if i==BYTES.../4
else
error = 7;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -