firda.c
来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C语言 代码 · 共 2,000 行 · 第 1/5 页
C
2,000 行
NdisAcquireSpinLock(&thisDev->Lock);
if (thisDev->portInfo.writePending)
{
switch (thisDev->HangChk)
{
case 0:
thisDev->HangChk++;
break;
default:
thisDev->HangChk++;
// RETAILMSG(DBGIRDA, (TEXT("IRDA: CheckForHang--we appear hung\n")));
// Issue a soft reset to the transmitter & receiver.
// g_pIRDAregs->rIRDA_FCR |= (3 <<1);
NdisReleaseSpinLock(&thisDev->Lock);
MiniportHandleInterrupt(MiniportAdapterContext);
NdisAcquireSpinLock(&thisDev->Lock);
break;
}
}
NdisReleaseSpinLock(&thisDev->Lock);
return FALSE;
}
/*
*************************************************************************
* MiniportDisableInterrupt
*************************************************************************
*
* Disables the NIC from generating interrupts.
*
*/
VOID MiniportDisableInterrupt(NDIS_HANDLE MiniportAdapterContext)
{
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
// RETAILMSG(DBGIRDA,(TEXT("==> MiniportDisableInterrupt\r\n")));
NdisAcquireSpinLock(&thisDev->Lock);
if (!thisDev->resourcesReleased){
SetCOMInterrupts(thisDev, FALSE);
}
NdisReleaseSpinLock(&thisDev->Lock);
}
/*
*************************************************************************
* MiniportEnableInterrupt
*************************************************************************
*
* Enables the IR card to generate interrupts.
*
*/
VOID MiniportEnableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
{
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
//RETAILMSG(DBGIRDA, (TEXT("==> MiniportEnableInterrupt\r\n")));
NdisAcquireSpinLock(&thisDev->Lock);
if (!thisDev->resourcesReleased){
SetCOMInterrupts(thisDev, TRUE);
}
NdisReleaseSpinLock(&thisDev->Lock);
}
/*
*************************************************************************
* MiniportHalt
*************************************************************************
*
* Halts the network interface card.
*
*/
VOID MiniportHalt(IN NDIS_HANDLE MiniportAdapterContext)
{
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
DEBUGFIR(DBGIRDA, (TEXT("==> MiniportHalt\r\n")));
DEBUGFIR(DBGIRDA, (TEXT("==> MiniportHalt(0x%x)"), (UINT)MiniportAdapterContext));
/*
* Remove this device from our global list
*/
if (thisDev == firstIrDADevice){
firstIrDADevice = firstIrDADevice->next;
}
else {
IrDevice *dev;
for (dev = firstIrDADevice; dev && (dev->next != thisDev);
dev = dev->next){}
if (dev) {
dev->next = dev->next->next;
}
else {
/*
* Don't omit this error check. I've seen NDIS call
* MiniportHalt with a bogus context when the system
* gets corrupted.
*/
DBGERR((TEXT("Error: Bad context in MiniportHalt\r\n")));
return;
}
}
/*
* Now destroy the device object.
*/
NdisAcquireSpinLock(&thisDev->Lock);
IR24A0_Shutdown(thisDev);
DoClose(thisDev);
// NdisMDeregisterIoPortRange(thisDev->ndisAdapterHandle, thisDev->ioBase, 8, (PVOID)thisDev->mappedPortRange);
FreeDevice(thisDev);
DEBUGFIR(DBGIRDA, (TEXT("<== MiniportHalt\r\n")));
DEBUGFIR(DBGIRDA, (TEXT("<== MiniportHalt(0x%x)"), (UINT)MiniportAdapterContext));
}
/*
*************************************************************************
* MiniportSyncHandleInterrupt
*************************************************************************
*
* This function is called from MiniportHandleInterrupt via
* NdisMSynchronizeWithInterrupt to synchronize with MiniportISR. This is
* required because the deferred procedure call (MiniportHandleInterrupt)
* shares data with MiniportISR but cannot achieve mutual exclusion with a
* spinlock because ISR's are not allowed to acquire spinlocks.
* This function should be called WITH DEVICE LOCK HELD, however, to
* synchronize with the rest of the miniport code (besides the ISR).
* The device's IRQ is masked out in the PIC while this function executes,
* so don't make calls up the stack.
*/
BOOLEAN MiniportSyncHandleInterrupt(PVOID MiniportAdapterContext)
{
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
// QueueLock should be held.
DEBUGFIR(DBGIRDA, (TEXT("==> MiniportSyncHandleInterrupt\r\n")));
DEBUGFIR(DBGIRDA, (TEXT("==> MiniportSyncHandleInterrupt(0x%x)"), (UINT)MiniportAdapterContext));
#if 0 // Since we're using queues, this function doesn't really do anything.
/*
* Update .firstRcvBufIndex and .lastRcvBufIndex.
*/
while ((thisDev->firstRcvBufIndex != NO_BUF_INDEX) &&
(thisDev->rcvBufs[thisDev->firstRcvBufIndex].state ==
STATE_FREE)) {
if (thisDev->firstRcvBufIndex == thisDev->lastRcvBufIndex) {
thisDev->firstRcvBufIndex =
thisDev->lastRcvBufIndex = NO_BUF_INDEX;
}
else {
thisDev->firstRcvBufIndex =
NEXT_RCV_BUF_INDEX(thisDev->firstRcvBufIndex);
}
}
#endif
DEBUGFIR(DBGIRDA, (TEXT("<== MiniportSyncHandleInterrupt\r\n")));
DEBUGFIR(DBGIRDA, (TEXT("<== MiniportSyncHandleInterrupt(0x%x)"), (UINT)MiniportAdapterContext));
return TRUE;
}
void
InsertBufferSorted(
PLIST_ENTRY Head,
rcvBuffer *rcvBuf
)
{
PLIST_ENTRY ListEntry;
if (IsListEmpty(Head))
{
InsertHeadList(Head, &rcvBuf->listEntry);
}
else
{
BOOLEAN EntryInserted = FALSE;
for (ListEntry = Head->Flink;
ListEntry != Head;
ListEntry = ListEntry->Flink)
{
rcvBuffer *temp = CONTAINING_RECORD(ListEntry,
rcvBuffer,
listEntry);
if (temp->dataBuf > rcvBuf->dataBuf)
{
// We found one that comes after ours.
// We need to insert before it
InsertTailList(ListEntry, &rcvBuf->listEntry);
EntryInserted = TRUE;
break;
}
}
if (!EntryInserted)
{
// We didn't find an entry on the last who's address was later
// than our buffer. We go at the end.
InsertTailList(Head, &rcvBuf->listEntry);
}
}
}
/*
*************************************************************************
* DeliverFullBuffers
*************************************************************************
*
* Deliver received packets to the protocol.
* Return TRUE if delivered at least one frame.
*
*/
BOOLEAN DeliverFullBuffers(IrDevice *thisDev)
{
BOOLEAN result = FALSE;
PLIST_ENTRY ListEntry;
LOG(TEXT("==> DeliverFullBuffers"), 0);
DBGOUT((TEXT("==> DeliverFullBuffers(0x%x)"), (UINT) thisDev));
/*
* Deliver all full rcv buffers
*/
for (
ListEntry = MyRemoveHeadList(&thisDev->rcvBufFull);
ListEntry;
ListEntry = MyRemoveHeadList(&thisDev->rcvBufFull)
)
{
rcvBuffer *rcvBuf = CONTAINING_RECORD(ListEntry,
rcvBuffer,
listEntry);
NDIS_STATUS stat;
PNDIS_BUFFER packetBuf;
SLOW_IR_FCS_TYPE fcs;
VerifyNdisPacket(rcvBuf->packet, 0);
if (thisDev->currentSpeed <= MAX_SIR_SPEED) {
/*
* The packet we have already has had BOFs,
* EOF, and * escape-sequences removed. It
* contains an FCS code at the end, which we
* need to verify and then remove before
* delivering the frame. We compute the FCS
* on the packet with the packet FCS attached;
* this should produce the constant value
* GOOD_FCS.
*/
fcs = ComputeFCS(rcvBuf->dataBuf,
rcvBuf->dataLen);
if (fcs != GOOD_FCS) {
/*
* FCS Error. Drop this frame.
*/
LOG(TEXT("Error: Bad FCS in DeliverFullBuffers"), fcs);
DBGERR((TEXT("Bad FCS in DeliverFullBuffers bad != good 0x%x!=0x%x."),
(UINT)fcs, (UINT) GOOD_FCS));
rcvBuf->state = STATE_FREE;
DBGSTAT((TEXT("Dropped %d/%d pkts; BAD FCS (%xh!=%xh):"),
++thisDev->packetsDropped,
thisDev->packetsDropped +
thisDev->packetsRcvd, fcs,
GOOD_FCS));
DBGPRINTBUF(rcvBuf->dataBuf,
rcvBuf->dataLen);
if (!rcvBuf->isDmaBuf) {
InsertTailList(&thisDev->rcvBufBuf, RCV_BUF_TO_LIST_ENTRY(rcvBuf->dataBuf));
}
rcvBuf->dataBuf = NULL;
rcvBuf->isDmaBuf = FALSE;
VerifyNdisPacket(rcvBuf->packet, 0);
InsertHeadList(&thisDev->rcvBufFree, &rcvBuf->listEntry);
//break;
continue;
}
/* Remove the FCS from the end of the packet. */
rcvBuf->dataLen -= SLOW_IR_FCS_SIZE;
}
#ifdef DBG_ADD_PKT_ID
if (addPktIdOn) {
/* Remove dbg packet id. */
USHORT uniqueId;
rcvBuf->dataLen -= sizeof(USHORT);
uniqueId = *(USHORT *)(rcvBuf->dataBuf+
rcvBuf->dataLen);
DBGOUT(("ID: RCVing packet %xh **",
(UINT)uniqueId));
LOG("ID: Rcv Pkt id:", uniqueId);
}
#endif
/*
* The packet array is set up with its NDIS_PACKET.
* Now we need to allocate a single NDIS_BUFFER for
* the NDIS_PACKET and set the NDIS_BUFFER to the
* part of dataBuf that we want to deliver.
*/
NdisAllocateBuffer(&stat, &packetBuf,
thisDev->bufferPoolHandle,
(PVOID)rcvBuf->dataBuf, rcvBuf->dataLen);
if (stat != NDIS_STATUS_SUCCESS){
LOG(TEXT("Error: NdisAllocateBuffer failed"), 0);
DBGERR((TEXT("NdisAllocateBuffer failed")));
DbgBreakPoint();
break;
}
VerifyNdisPacket(rcvBuf->packet, 0);
NdisChainBufferAtFront(rcvBuf->packet, packetBuf);
LOG_PacketChain(thisDev, rcvBuf->packet);
VerifyNdisPacket(rcvBuf->packet, 1);
/*
* Fix up some other packet fields.
*/
NDIS_SET_PACKET_HEADER_SIZE(rcvBuf->packet,
IR_ADDR_SIZE+IR_CONTROL_SIZE);
DBGPKT((TEXT("Indicating rcv packet 0x%x."),
(UINT)rcvBuf->packet));
DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen);
/*
* Indicate to the protocol that another packet is
* ready. Set the rcv buffer's state to PENDING first
* to avoid a race condition with NDIS's call to the
* return packet handler.
*/
rcvBuf->state = STATE_PENDING;
*(rcvBuffer **)rcvBuf->packet->MiniportReserved = rcvBuf;
InsertBufferSorted(&thisDev->rcvBufPend, rcvBuf);
VerifyNdisPacket(rcvBuf->packet, 1);
LOG_Data2(thisDev, rcvBuf->dataBuf);
NdisReleaseSpinLock(&thisDev->Lock);
NdisMIndicateReceivePacket(thisDev->ndisAdapterHandle, &rcvBuf->packet, 1);
NdisAcquireSpinLock(&thisDev->Lock);
IRFIR_LOG_NDIS_PACKET(LOG_RXFRAME, rcvBuf->packet);
result = TRUE;
stat = NDIS_GET_PACKET_STATUS(rcvBuf->packet);
if (stat == NDIS_STATUS_PENDING) {
/*
* The packet is being delivered asynchronously.
* Leave the rcv buffer's state as PENDING;
* we'll get a callback when the transfer is
* complete. Do NOT step firstRcvBufIndex.
* We don't really need to break out here,
* but we will anyways just to make things
* simple. This is ok since we get this
* deferred interrupt callback for each packet
* anyway. It'll give the protocol a chance
* to catch up.
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?