nsc.c
来自「网络驱动开发」· C语言 代码 · 共 2,150 行 · 第 1/5 页
C
2,150 行
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);
}
}
NdisReleaseSpinLock(Lock);
}
/*
*************************************************************************
* DeliverFullBuffers
*************************************************************************
*
* Deliver received packets to the protocol.
* Return TRUE if delivered at least one frame.
*
*/
VOID
DeliverFullBuffers(IrDevice *thisDev)
{
PLIST_ENTRY ListEntry;
LOG("==> DeliverFullBuffers");
DBGOUT(("==> DeliverFullBuffers(0x%x)", thisDev));
/*
* Deliver all full rcv buffers
*/
for (
ListEntry = NDISSynchronizedRemoveHeadList(&thisDev->rcvBufFull,
&thisDev->interruptObj);
ListEntry;
ListEntry = NDISSynchronizedRemoveHeadList(&thisDev->rcvBufFull,
&thisDev->interruptObj)
)
{
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("Error: Bad FCS in DeliverFullBuffers %x", fcs);
DBGERR(("Bad FCS in DeliverFullBuffers 0x%x!=0x%x.",
(UINT)fcs, (UINT) GOOD_FCS));
rcvBuf->state = STATE_FREE;
DBGSTAT(("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)
{
NDISSynchronizedInsertTailList(&thisDev->rcvBufBuf,
RCV_BUF_TO_LIST_ENTRY(rcvBuf->dataBuf),
&thisDev->interruptObj);
}
rcvBuf->dataBuf = NULL;
rcvBuf->isDmaBuf = FALSE;
VerifyNdisPacket(rcvBuf->packet, 0);
NDISSynchronizedInsertHeadList(&thisDev->rcvBufFree,
&rcvBuf->listEntry,
&thisDev->interruptObj);
//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: %xh", 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("Error: NdisAllocateBuffer failed");
DBGERR(("NdisAllocateBuffer failed"));
ASSERT(0);
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(("Indicating rcv packet 0x%x.", rcvBuf->packet));
/*
* 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.
*/
NdisAcquireSpinLock(&thisDev->QueueLock);
if (thisDev->Halting) {
//
// the adapter is being halted, stop sending packets up
//
NdisReleaseSpinLock(&thisDev->QueueLock);
if (!rcvBuf->isDmaBuf) {
NDISSynchronizedInsertTailList(&thisDev->rcvBufBuf,
RCV_BUF_TO_LIST_ENTRY(rcvBuf->dataBuf),
&thisDev->interruptObj);
}
rcvBuf->dataBuf = NULL;
rcvBuf->isDmaBuf = FALSE;
VerifyNdisPacket(rcvBuf->packet, 0);
NDISSynchronizedInsertHeadList(&thisDev->rcvBufFree,
&rcvBuf->listEntry,
&thisDev->interruptObj);
//
// free the buffer we chained to the packet
//
packetBuf=NULL;
NdisUnchainBufferAtFront(rcvBuf->packet, &packetBuf);
if (packetBuf){
NdisFreeBuffer(packetBuf);
}
continue;
}
//
// increment the count of packets sent to the protocol
//
NdisInterlockedIncrement(&thisDev->PacketsSentToProtocol);
NdisReleaseSpinLock(&thisDev->QueueLock);
rcvBuf->state = STATE_PENDING;
*(rcvBuffer **)rcvBuf->packet->MiniportReserved = rcvBuf;
InterlockedInsertBufferSorted(
&thisDev->rcvBufPend,
rcvBuf,
&thisDev->QueueLock
);
VerifyNdisPacket(rcvBuf->packet, 1);
LOG_Data2(thisDev, rcvBuf->dataBuf);
NDIS_SET_PACKET_STATUS(rcvBuf->packet,STATUS_SUCCESS);
NdisMIndicateReceivePacket(thisDev->ndisAdapterHandle,
&rcvBuf->packet, 1);
/*
* The packet is being delivered asynchronously.
* Leave the rcv buffer's state as PENDING;
* we'll get a callback when the transfer is
*/
LOG("Indicated rcv complete (Async) bytes: %d",
rcvBuf->dataLen);
DBGSTAT(("Rcv Pending. Rcvd %d packets",
++thisDev->packetsRcvd));
}
LOG("<== DeliverFullBuffers");
DBGOUT(("<== DeliverFullBuffers"));
return ;
}
/*
*************************************************************************
* MiniportHandleInterrupt
*************************************************************************
*
*
* This is the deferred interrupt processing routine (DPC) which is
* optionally called following an interrupt serviced by MiniportISR.
*
*/
VOID MiniportHandleInterrupt(NDIS_HANDLE MiniportAdapterContext)
{
IrDevice *thisDev = CONTEXT_TO_DEV( MiniportAdapterContext);
PNDIS_PACKET PacketToComplete=NULL;
NDIS_STATUS PacketStatus=NDIS_STATUS_SUCCESS;
BOOLEAN SpeedChange=FALSE;
LOG("==> MiniportHandleInterrupt");
DBGOUT(("==> MiniportHandleInterrupt(0x%x)", MiniportAdapterContext));
/*
* If we have just started receiving a packet, indicate media-busy
* to the protocol.
*/
if (thisDev->mediaBusy && !thisDev->haveIndicatedMediaBusy) {
if (thisDev->currentSpeed > MAX_SIR_SPEED) {
LOG("Error: MiniportHandleInterrupt is in wrong state %d",
thisDev->currentSpeed);
DBGERR(("MiniportHandleInterrupt is in wrong state: speed is 0x%x",
thisDev->currentSpeed));
ASSERT(0);
}
NdisMIndicateStatus(thisDev->ndisAdapterHandle,
NDIS_STATUS_MEDIA_BUSY, NULL, 0);
NdisMIndicateStatusComplete(thisDev->ndisAdapterHandle);
thisDev->haveIndicatedMediaBusy = TRUE;
}
NdisDprAcquireSpinLock(&thisDev->QueueLock);
if (thisDev->currentSpeed > MAX_SIR_SPEED) {
//
// fir speed
//
//
// disable any other
//
thisDev->FirIntMask = 0x00;
if (thisDev->FirTransmitPending) {
ASSERT(thisDev->CurrentPacket != NULL);
thisDev->FirTransmitPending=FALSE;
//
// we seem to be transmitting now
//
{
ULONG CurrentDMACount;
UCHAR BytesInFifo;
ULONG LoopCount=0;
CurrentDMACount = NdisMReadDmaCounter(thisDev->DmaHandle);
if (CurrentDMACount > 0) {
LOG_ERROR("FIR send: Dma Count was not zero: %d\n\n", CurrentDMACount);
#if DBG
DbgPrint("FIR send: Count was not zero: %d\n\n", CurrentDMACount);
#endif
}
//
// see if the fifo is empty yet
//
BytesInFifo=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_2, TXFLV_OFFSET) & 0x3f;
if (BytesInFifo > 0) {
LOG_ERROR("FIR send: Bytes still in fifo: %d", BytesInFifo);
while ((BytesInFifo > 0) && (LoopCount < 64)) {
BytesInFifo=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_2, TXFLV_OFFSET) & 0x3f;
LoopCount++;
}
LOG_ERROR("FIR send: Bytes still in fifo after loop: %d, loops=%d", BytesInFifo,LoopCount);
}
}
PacketStatus=CompleteDmaTransferToDevice(
&thisDev->DmaUtil
);
if (PacketStatus != NDIS_STATUS_SUCCESS) {
DBGERR(("NdisMCompleteDmaTransfer failed: %d\n", PacketStatus));
#if DBG
DbgBreakPoint();
#endif
}
/*
* Check for Tx underrun.
*/
if (SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, ASCR_OFFSET) & ASCR_TXUR) {
USHORT TransmitCurrentCount;
//
// for debugging purposes, see where we were in the frame when it stopped
//
TransmitCurrentCount = SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_4, TFRCCL_OFFSET);
TransmitCurrentCount |= ((USHORT)SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_4, TFRCCH_OFFSET)) << 8;
//
// reset the fifo's
//
SyncWriteBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, 2, 0x07);
//
// clear the tx underrun
//
SyncWriteBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, ASCR_OFFSET, ASCR_TXUR);
RegStats.TxUnderruns++;
PacketStatus = NDIS_STATUS_FAILURE;
LOG_ERROR("MiniportDpc: Transmit Underrun: tx current count=%d",TransmitCurrentCount);
DEBUGFIR(DBG_TX|DBG_ERR, ("NSC: FIR_MegaSendComplete: Transmit Underrun\n"));
}
PacketToComplete=thisDev->CurrentPacket;
thisDev->CurrentPacket=NULL;
} else {
if (thisDev->FirReceiveDmaActive) {
FIR_DeliverFrames(thisDev);
} else {
DBGERR(("MiniportHandleInterrupt: fir: not sending and not RX state"));
LOG_ERROR("MiniportHandleInterrupt: fir: not sending and not RX state %02x",thisDev->InterruptStatus);
}
}
} else {
//
// in SIR mode
//
if (thisDev->CurrentPacket != NULL) {
//
//
UINT TransmitComplete=InterlockedExchange(&thisDev->portInfo.IsrDoneWithPacket,0);
if (TransmitComplete) {
PacketToComplete=thisDev->CurrentPacket;
thisDev->CurrentPacket=NULL;
}
}
}
thisDev->setSpeedAfterCurrentSendPacket = FALSE;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?