fir24a0.c
来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C语言 代码 · 共 1,319 行 · 第 1/3 页
C
1,319 行
}
/* This is the function which sets up the DMA channel for transmission
and sends the packet thru it.
*/
BOOLEAN Irda_DMA_Tx(IrDevice *thisDev)
{
NDIS_STATUS stat;
PNDIS_PACKET Packet;
PNDIS_IRDA_PACKET_INFO packetInfo;
int ret_val;
DEBUGMSG(DBGIRDA, (TEXT("==> Irda_DMA_Tx(0x%x)\r\n"), (UINT) thisDev));
thisDev->HangChk = 0;
if (IsListEmpty(&thisDev->SendQueue)) {
ret_val = FALSE;
} else {
thisDev->portInfo.writePending = TRUE;
Packet = HEAD_SEND_PACKET(thisDev);
// Check for min turnaround time set.
packetInfo = GetPacketInfo(Packet);
//
// NOTE: Don't use NdisStallExecution for turnaround delay since
// you shouldn't stall for more than 60 us. Calling
// NdisStallExecution for large times will degrade system
// performance.
//
if (packetInfo->MinTurnAroundTime) {
UINT usecToWait = packetInfo->MinTurnAroundTime;
UINT msecToWait;
packetInfo->MinTurnAroundTime = 0;
#if 1
// Ndis timer has a 1ms granularity (in theory). Let's round off.
msecToWait = (usecToWait<=1000) ? 1 : (usecToWait+500)/1000;
NdisMSetTimer(&thisDev->TurnaroundTimer, msecToWait);
// RETAILMSG(DBGIRDA, (TEXT("Irda_DMA_Tx:- Do min TAT wait\r\n")));
return TRUE; // Say we're successful. We'll come back here.
#endif
}
NdisToFirPacket(thisDev,
Packet, (UCHAR *) thisDev->portInfo.writeBuf,
MAX_IRDA_DATA_SIZE, &thisDev->portInfo.writeBufLen);
DEBUGFIR(DBGIRDA, (TEXT("Irda_DMA_Tx: Sending packet 0x%x, len = %d\r\n"), Packet, thisDev->portInfo.writeBufLen));
/* Setup Transmit DMA. */
NdisMSetupDmaTransfer(&stat, thisDev->DmaHandle,
// thisDev->xmitDmaBuffer, 0,
(PNDIS_BUFFER)thisDev->portInfo.writeBuf, 0,
thisDev->portInfo.writeBufLen, TRUE);
if (stat != NDIS_STATUS_SUCCESS) {
DBGERR( (TEXT("Irda_DMA_Tx: NdisMSetupDmaTransfer(Tx)failed\r\n")));
DbgBreakPoint();
ret_val = FALSE;
}
else {
ret_val = TRUE;
}
}
// RETAILMSG(DBGIRDA, (TEXT("<== Irda_DMA_Tx\r\n")));
return ret_val;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
NdisMSetupIntTransfer(
PNDIS_STATUS pStatus,
PNDIS_BUFFER pBuffer,
ULONG Offset,
ULONG Length,
BOOLEAN WriteToDevice
)
{
PVOID VirtualAddress;
UINT BufferLength;
DEBUGFIR(DBGIRDA, (TEXT("+NdisMSetupIntransfer %s: buf = 0x%x, offset = %d, len = %d"),
(WriteToDevice == TRUE) ? TEXT("TX") : TEXT("RX"),
pBuffer, Offset, Length));
#if 0
RETAILMSG(1, (TEXT("+NdisMSetupDmaTransfer %s: buf = 0x%x, offset = %d, len = %d"),
(WriteToDevice == TRUE) ? TEXT("TX") : TEXT("RX"),
pBuffer, Offset, Length));
#endif
if(Length <1000)
RETAILMSG(1, (TEXT("%x "),Length));
*pStatus = NDIS_STATUS_SUCCESS;
NdisQueryBuffer(pBuffer, &VirtualAddress, &BufferLength);
if (Offset + Length > BufferLength)
{
DBGERR( (TEXT("Whoa! The offset+length is greater than the buffer length!")));
*pStatus = NDIS_STATUS_RESOURCES;
goto done;
}
DEBUGFIR(DBGIRDA, (TEXT("Address = 0x%X\r\n"), (PBYTE)VirtualAddress + Offset));
DEBUGFIR(DBGIRDA, (TEXT("Length = 0x%X\r\n"), BufferLength));
Init_Irda_Rx(Length,S24A0_IRDA_RXMODEINT);
done:
// RETAILMSG(DBGIRDA, (TEXT("-NdisMSetupDmaTransfer [%s]"), DBG_NDIS_RESULT_STR(*pStatus)));
return;
}
#ifdef DEBUG
void DumpFrame(PUCHAR pStart, UINT len)
{
UINT i;
for(i=0;i<len;i++) {
RETAILMSG(DBGIRDA, (TEXT(" 0x%x"),*pStart++));
if((len %16 ) == 15)
RETAILMSG(DBGIRDA, (TEXT(" \r\n")));
}
}
#else
#define DumpFrame(pStart,len)
#endif
#if 0
VOID FIR_HandleDMARxFrame(IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
IrDevice *thisDev = FunctionContext;
DEBUGMSG(DBGIRDA, (TEXT("==> FIR_HandleDMARxFrame\r\n")));
NdisAcquireSpinLock(&thisDev->Lock);
Read the DMA cnt.
if the DMA cnt is not changed
restart the timer..
NdisReleaseSpinLock(&thisDev->Lock);
DEBUGMSG(DBGIRDA, (TEXT("<== DelayedWrite\r\n")));
}
#endif
void FIR_HandleRxFrame(IrDevice *thisDev)
{
UCHAR frameStat,frameLSR;
// NDIS_STATUS stat;
ULONG rcvFrameSize = 0,i;
PUCHAR FrameStart,readPtr;
BOOLEAN bDoSetupAgain = TRUE;
g_pINTregs->INTSUBMSK |= BIT_SUB_IRDA;
// g_pIRDAregs->IRDA_IER = 0x1<<6|1<<4|1<<3|1; // Enable the interrupts
// RETAILMSG(1, (TEXT("FIR_HandleRxFrame \r\n")));
frameStat = thisDev->InterruptStatus;
frameLSR = thisDev->FrameStatus;
while(1){
// RETAILMSG(1, (TEXT("FS (0x%x) LSR(0x%x) \r\n"), frameStat,frameLSR));
// DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> FrameStat (0x%x)"), frameStat));
// DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> FrameLSR (0x%x)"), frameLSR));
if((frameStat & 0x40) || (frameLSR & 0x1c)) {
DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> Error Indication")));
if(frameLSR & 0x04) {
RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> CRC Error")));
RegStats.ReceiveCRCErrors++;
}
if(frameLSR & 0x08) {
RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> PHY Error")));
RegStats.ReceiveCRCErrors++;
}
if(frameLSR & 0x10) {
RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> FL Error, len LL%x LH%x"),g_pIRDAregs->IRDA_RXFLL,g_pIRDAregs->IRDA_RXFLH));
RegStats.ReceiveCRCErrors++;
}
break;
}else if(frameStat & 0x08) {
// RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> Rx Over Run error")));
RegStats.ReceiveFIFOOverflows++;
break;
// }else if(frameLSR & 0x01) {
// DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> Rx Empty")));
// RegStats.ReceiveFIFOOverflows++;
#if 0
}
else if (frameLSR & 0x01) {
Sleep(1);
// RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> Rx Fifo Empty\r\n)")));
bDoSetupAgain = FALSE;
NdisMSetupIntTransfer(&stat,thisDev->rcvDmaBuffer,
thisDev->rcvDmaOffset,
thisDev->rcvDmaSize, FALSE);
if (stat != NDIS_STATUS_SUCCESS) {
LOG(TEXT("Error: NdisMSetupDmaTransfer failed in SetupRecv"), stat);
DBGERR((TEXT("NdisMSetupDmaTransfer failed (0x%x) in SetupRecv"),
(UINT)stat));
}
break;
#endif
} else if(((frameStat & 0x10) || (frameStat & 0x80))){
DEBUGFIR(DBG_RX, (TEXT("Last Byte Detected\r\n")));
//
// Half Duplex, received last byte, so disable Rx
//
g_pIRDAregs->IRDA_CNT &= ~(3<<6); //Resest Tx and Rx bits
g_pIRDAregs->IRDA_CNF = 0x0; // Disable Interrupt & DMA
// Interrupt Enable Register
g_pIRDAregs->IRDA_IER = 0x0; // Disable All interrupts
FrameStart = readPtr = thisDev->portInfo.dmaReadBuf + thisDev->rcvPktOffset;
while(!(g_pIRDAregs->IRDA_LSR & 0x20)) {
*readPtr++ = g_pIRDAregs->IRDA_RBR;
}
DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> Completed")));
rcvFrameSize = readPtr -FrameStart;
thisDev->rcvdFrameLen += rcvFrameSize;
DumpFrame(FrameStart,rcvFrameSize);
FrameStart = thisDev->portInfo.dmaReadBuf + thisDev->rcvdFrameStart;
thisDev->rcvPktOffset += rcvFrameSize;
if (thisDev->rcvdFrameLen <= MAX_NDIS_DATA_SIZE &&
thisDev->rcvdFrameLen>= IR_ADDR_SIZE + IR_CONTROL_SIZE) {
//
// Queue this rcv packet. Move Newframe pointer
// into RxDMA buffer.
//
RegStats.ReceivedPackets++;
RegStats.RxWindow++;
QueueReceivePacket(thisDev, FrameStart, thisDev->rcvdFrameLen, TRUE);
thisDev->bRcvdFullFrame = TRUE;
}
else {
LOG(TEXT("Error: invalid packet size in FIR_DeliverFrames"),
rcvFrameSize);
DEBUGFIR(DBG_RX|DBG_ERR,
(TEXT("Invalid packet size in FIR_DeliverFrames; %xh > %xh"),
rcvFrameSize, MAX_RCV_DATA_SIZE));
thisDev->DiscardNextPacketSet = TRUE;
}
break;
}else if(frameStat & 0x01) {
DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> Rx Fifo is full (0x%x)"), (UINT) thisDev));
// RETAILMSG(1, (TEXT("RxF\r\n")));
FrameStart = readPtr = thisDev->portInfo.dmaReadBuf + thisDev->rcvPktOffset;
for(i=0; i <16;i++)
*readPtr++ = g_pIRDAregs->IRDA_RBR;
// rcvFrameSize = readPtr -FrameStart;
rcvFrameSize = 16;
/* Step offset for next buffer. */
thisDev->rcvPktOffset += rcvFrameSize;
thisDev->rcvdFrameLen += rcvFrameSize;
DumpFrame(FrameStart,rcvFrameSize);
}else if (frameLSR & 0x01) { // Rx Fifo empty
Sleep(1);
}
// thisDev->InterruptStatus = g_pIRDAregs->IRDA_IIR;
// thisDev->FrameStatus = g_pIRDAregs->IRDA_LSR;
frameStat = g_pIRDAregs->IRDA_IIR;
frameLSR = g_pIRDAregs->IRDA_LSR;
}
if(bDoSetupAgain)
FirSetupIntRecv(thisDev);
LOG(TEXT("<== FIR_DeliverFrames"), 1);
DEBUGFIR(DBG_RX|DBG_OUT, (TEXT("<== FIR_DeliverFrames")));
}
BOOLEAN IR24A0_Setup(IrDevice *thisDev)
{
NDIS_DMA_DESCRIPTION DMAChannelDcr;
NDIS_STATUS stat;
thisDev->rcvDmaOffset = 0;
/*
* Because we enable rcv DMA while SIR receives may still be
* going on, we need to keep a separate receive buffer for DMA.
* This buffer gets swapped with the rcvBuffer data pointer
* and must be the same size.
*/
#ifdef UNDER_CE
// Windows CE. We get a chunk of memory from our contiguous physical
// buffer. See externs.h for detailed information.
ASSERT(g_pvDmaVirtualBase);
thisDev->portInfo.dmaReadBuf = (PUCHAR)g_pvDmaVirtualBase + RCVDMA_OFFSET;
#else // UNDER_CE
thisDev->portInfo.dmaReadBuf = MyMemAlloc(RCV_DMA_SIZE, TRUE);
if (!thisDev->portInfo.dmaReadBuf){
return FALSE;
}
#endif //!UNDER_CE
NdisAllocateBufferPool(&stat, &thisDev->dmaBufferPoolHandle, 2);
if (stat != NDIS_STATUS_SUCCESS){
RETAILMSG(DBGIRDA, (TEXT("24A0: NdisAllocateBufferPool failed in IR24A0_setup\r\n")));
return FALSE;
}
NdisAllocateBuffer(&stat, &thisDev->rcvDmaBuffer,
thisDev->dmaBufferPoolHandle,
thisDev->portInfo.dmaReadBuf,
RCV_DMA_SIZE);
if (stat != NDIS_STATUS_SUCCESS) {
RETAILMSG(DBGIRDA, (TEXT("24A0: NdisAllocateBuffer failed (rcv) in IRDA24A0_Setup\r\n")));
return FALSE;
}
NdisAllocateBuffer(&stat, &thisDev->xmitDmaBuffer,
thisDev->dmaBufferPoolHandle,
thisDev->portInfo.writeBuf,
MAX_IRDA_DATA_SIZE);
if (stat != NDIS_STATUS_SUCCESS) {
RETAILMSG(DBGIRDA, (TEXT("24A0: NdisAllocateBuffer failed (xmit) in IRDA24A0_Setup\r\n")));
return FALSE;
}
/*
* Initialize rcv DMA channel
*/
DMAChannelDcr.DemandMode = TRUE;
DMAChannelDcr.AutoInitialize = FALSE;
DMAChannelDcr.DmaChannelSpecified = FALSE;
DMAChannelDcr.DmaWidth = Width8Bits;
DMAChannelDcr.DmaSpeed = Compatible;
DMAChannelDcr.DmaPort = 0;
DMAChannelDcr.DmaChannel = thisDev->DMAChannel;
stat = NdisMRegisterDmaChannel(&thisDev->DmaHandle,
thisDev->ndisAdapterHandle,
thisDev->DMAChannel,
FALSE, &DMAChannelDcr, RCV_DMA_SIZE);
if (stat != NDIS_STATUS_SUCCESS) {
RETAILMSG(DBGIRDA, (TEXT("24A0: NdisMRegisterDmaChannel failed\r\n")));
return FALSE;
}
return TRUE;
}
void IR24A0_Shutdown(IrDevice *thisDev)
{
if (thisDev->DmaHandle){
NdisMDeregisterDmaChannel(thisDev->DmaHandle);
thisDev->DmaHandle = NULL;
}
if (thisDev->xmitDmaBuffer){
NdisFreeBuffer( thisDev->xmitDmaBuffer);
thisDev->xmitDmaBuffer = NULL;
}
if (thisDev->rcvDmaBuffer){
NdisFreeBuffer(thisDev->rcvDmaBuffer);
thisDev->rcvDmaBuffer = NULL;
}
if (thisDev->dmaBufferPoolHandle){
NdisFreeBufferPool(thisDev->dmaBufferPoolHandle);
thisDev->dmaBufferPoolHandle = NULL;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?