📄 interrup.c
字号:
{
ASSERT(SwRfd->Status & RFD_STATUS_OK);
ASSERT((Rfd->RfdActualCount & 0xc000) == 0xc000);
// Adjust our buffer length for this swrfd
NdisAdjustBufferLength((PNDIS_BUFFER) SwRfd->ReceiveBuffer,
(UINT) SwRfd->FrameLength);
ASSERT(SwRfd->FrameLength == (UINT)(Rfd->RfdActualCount & 0x3fff));
// we dont do recalculatepacketcounts because we only
// have one buffer and its count is always correct
// we could, however, do it if we were paranoid
// or supported multiple receive buffers per packet
// NdisRecalculatePacketCounts(SwRfd->ReceivePacket);
PacketArray[PacketArrayCount] = SwRfd->ReceivePacket;
// keep track of how many we've used
Adapter->UsedRfdCount++;
ASSERT(Adapter->UsedRfdCount <= Adapter->NumRfd);
// set the status on the packet, either resources or success
if (Adapter->UsedRfdCount < Adapter->NumRfd - MIN_NUM_RFD)
{
NDIS_SET_PACKET_STATUS(PacketArray[PacketArrayCount],NDIS_STATUS_SUCCESS);
// Keep track of the highest array index in which a packet
// with status NDIS_STATUS_SUCCESS is found. Once we hit the low
// resource condition, all further packets will be marked with status
// NDIS_STATUS_RESOURCES. This is because we hold the adapter lock
// here which prevents UsedRfdCount/NumRfd from being modified
// elsewhere.
}
else
{
NDIS_SET_PACKET_STATUS(PacketArray[PacketArrayCount],
NDIS_STATUS_RESOURCES);
PacketFreeCount++;
// okay, we ran low on resources so allocate a bunch more
if ((Adapter->Last_RMD_used != (NUM_RMD - 1))
&& (Adapter->AsynchronousAllocationPending == FALSE))
{
NDIS_STATUS AllocationStatus;
AllocationStatus = NdisMAllocateSharedMemoryAsync(
Adapter->D100AdapterHandle,
packet_count[Adapter->Last_RMD_used] * sizeof(RFD_STRUC),
FALSE,
(PVOID) Adapter->Last_RMD_used);
if (AllocationStatus != NDIS_STATUS_PENDING)
{
INITSTR(("Async memory allocation not possible at this time!!!"));
}
else
{
// set this state variable so if we keep on receiving
// before our new memory is set up, we wont repeatedly
// call our allocate function
Adapter->AsynchronousAllocationPending = TRUE;
}
}
}
// have to increment our packetcount
PacketArrayCount++;
// this limits the number of packets that we will indicate
// to MAX_ARRAY_RECEIVE_PACKETS or the available number of RFDS
if (( PacketArrayCount >= MAX_ARRAY_RECEIVE_PACKETS) ||
( Adapter->UsedRfdCount == Adapter->NumRfd))
{
ContinueToCheckRFDs = TRUE;
break;
}
}
}// end while 1
// if we didn't process any receives, just return from here
if (0 == PacketArrayCount)
{
DEBUGCHAR(Adapter,'g');
return(FALSE);
}
#if DBG
Adapter->IndicateReceivePacketCounter++;
Adapter->PacketsIndicated+=PacketArrayCount;
#endif
////////////////////////////////////////////////////////////////
// Indicate the packets and return the completed ones to our
// receive list. If the packet is pended NDIS gets to keep it
// and will return it with D100GetReturnedPackets.
// NDIS should always leave us at least MIN_NUM_RFD packets
// because we set Status_resources on our last MIN_NUM_RFD packets
////////////////////////////////////////////////////////////////
if(PacketArrayCount)
{
NdisReleaseSpinLock(&Adapter->Lock);
NdisMIndicateReceivePacket(Adapter->D100AdapterHandle,
PacketArray,
PacketArrayCount);
NdisAcquireSpinLock(&Adapter->Lock);
}
//
// NDIS will call our ReturnPackets handler for each packet
// that was *not* marked NDIS_STATUS_RESOURCES. For those
// that were marked with the resources status, the miniport
// should assume that they are immediately returned.
// Go through the packets that were marked NDIS_STATUS_RESOURCES
// and reclaim them.
//
for (i=PacketArrayCount-PacketFreeCount;i<PacketArrayCount ;i++ )
{
// get the SwRfd associated with this packet
SwRfd = *(D100SwRfd **)(PacketArray[i]->MiniportReserved);
InitAndChainPacket(Adapter,SwRfd);
Adapter->UsedRfdCount--;
ASSERT(Adapter->UsedRfdCount <= Adapter->NumRfd);
} // end for
} while (ContinueToCheckRFDs);
// check to see if we came out of this routine with the correct amount of
// receive buffers left over
ASSERT(Adapter->UsedRfdCount <= (Adapter->NumRfd - MIN_NUM_RFD));
DEBUGCHAR(Adapter,'r');
return (TRUE);
}
//-----------------------------------------------------------------------------
// Procedure: StartReceiveUnit
//
// Description: This routine checks the status of the 82557's receive unit(RU),
// and starts the RU if it was not already active. However,
// before restarting the RU, the driver cleans up any recent
// pending receives (this is very important).
//
// Arguments:
// Adapter - ptr to Adapter object instance
//
// Returns:
// TRUE - If we indicated any receives during this function call
// FALSE - If we didn't indicate any receives
//-----------------------------------------------------------------------------
BOOLEAN
StartReceiveUnit(
IN PD100_ADAPTER Adapter
)
{
PD100SwRfd SwRfd;
BOOLEAN Status;
UINT WaitCount = 80000;
#if DBG
UINT i;
#endif
DEBUGFUNC("StartReceiveUnit");
TRACE2(Adapter, ("\n"));
Status = FALSE;
DEBUGCHAR(Adapter,'>');
// If the receiver is ready, then don't try to restart.
if ((Adapter->CSRAddress->ScbStatus & SCB_RUS_MASK) == SCB_RUS_READY)
return Status;
TRACE2(Adapter, ("Re-starting the RU!!!\n"));
SwRfd = (PD100SwRfd) QueueGetHead(&Adapter->RfdList);
// Check to make sure that our RFD head is available. If its not, then
// we should process the rest of our receives
if ((SwRfd == NULL) || (SwRfd->Rfd->RfdCbHeader.CbStatus))
{
Status = ProcessRXInterrupt(Adapter);
// Get the new RFD "head" after processing the pending receives.
SwRfd = (PD100SwRfd) QueueGetHead(&Adapter->RfdList);
}
#if DBG
if ((Adapter->CSRAddress->ScbStatus & SCB_RUS_MASK) == SCB_RUS_READY)
{
TRACESTR(Adapter, ("RU is active!!!\n"));
}
// Big hack to check to make sure that all of the RFDs are indeed clear.
// If they are not then we'll generate a break point.
for (i=0; i< (Adapter->NumRfd - Adapter->UsedRfdCount); i++)
{
SwRfd = (PD100SwRfd) QueuePopHead(&Adapter->RfdList);
if (SwRfd->Rfd->RfdCbHeader.CbStatus & RFD_STATUS_COMPLETE)
{
TRACESTR(Adapter,("RFD NOT PROCESSED!!!\n"));
// DbgBreakPoint();
}
QueuePutTail(&Adapter->RfdList, &SwRfd->Link);
}
SwRfd = (PD100SwRfd) QueueGetHead(&Adapter->RfdList);
#endif //DBG
// Wait for the SCB to clear before we set the general pointer
if (WaitScb(Adapter) == FALSE)
ASSERT(0);
if (SwRfd != NULL)
{
// Set the SCB General Pointer to point the current Rfd
Adapter->CSRAddress->ScbGeneralPointer = SwRfd->RfdPhys;
}
// Issue the SCB RU start command
(void) D100IssueScbCommand(Adapter, SCB_RUC_START, FALSE);
// wait for the command to be accepted
WaitScb(Adapter);
// wait for RUS to be Ready
while (WaitCount !=0)
{
if ((Adapter->CSRAddress->ScbStatus & SCB_RUS_MASK) == SCB_RUS_READY)
break;
NdisStallExecution(10);
WaitCount--;
}
if (!WaitCount)
{
HARDWARE_NOT_RESPONDING (Adapter);
}
#if DBG
// If we fall through, we have a problem.
if (WaitCount == 0)
TRACESTR(Adapter, ("Failed, RU won't ready -- ScbStatus %08x\n",
Adapter->CSRAddress->ScbStatus));
#endif
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -