📄 mp_nic.c
字号:
NDIS_STATUS_SUCCESS
NDIS_STATUS_HARD_ERRORS
NDIS_STATUS_PENDING
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PMP_TCB pMpTcb;
#if DBG
LONG i;
#endif
DBGPRINT(MP_TRACE, ("---> MpHandleSendInterrupt\n"));
//
// Any packets being sent? Any packet waiting in the send queue?
//
if (Adapter->nBusySend == 0 &&
IsQueueEmpty(&Adapter->SendWaitQueue))
{
ASSERT(Adapter->CurrSendHead == Adapter->CurrSendTail);
DBGPRINT(MP_TRACE, ("<--- MpHandleSendInterrupt\n"));
return Status;
}
//
// Check the first TCB on the send list
//
while (Adapter->nBusySend > 0)
{
#if DBG
pMpTcb = Adapter->CurrSendHead;
for (i = 0; i < Adapter->nBusySend; i++)
{
pMpTcb = pMpTcb->Next;
}
if (pMpTcb != Adapter->CurrSendTail)
{
DBGPRINT(MP_ERROR, ("nBusySend= %d\n", Adapter->nBusySend));
DBGPRINT(MP_ERROR, ("CurrSendhead= "PTR_FORMAT"\n", Adapter->CurrSendHead));
DBGPRINT(MP_ERROR, ("CurrSendTail= "PTR_FORMAT"\n", Adapter->CurrSendTail));
ASSERT(FALSE);
}
#endif
pMpTcb = Adapter->CurrSendHead;
//
// Is this TCB completed?
//
if (pMpTcb->HwTcb->TxCbHeader.CbStatus & CB_STATUS_COMPLETE)
{
//
// Check if this is a multicast hw workaround packet
//
if ((pMpTcb->HwTcb->TxCbHeader.CbCommand & CB_CMD_MASK) != CB_MULTICAST)
{
MP_FREE_SEND_PACKET_FUN(Adapter, pMpTcb);
}
else
{
}
}
else
{
break;
}
}
//
// If we queued any transmits because we didn't have any TCBs earlier,
// dequeue and send those packets now, as long as we have free TCBs.
//
if (MP_IS_READY(Adapter))
{
while (!IsQueueEmpty(&Adapter->SendWaitQueue) &&
MP_TCB_RESOURCES_AVAIABLE(Adapter))
{
PNDIS_PACKET Packet;
PQUEUE_ENTRY pEntry;
#if OFFLOAD
if (MP_TEST_FLAG(Adapter, fMP_SHARED_MEM_IN_USE))
{
break;
}
#endif
pEntry = RemoveHeadQueue(&Adapter->SendWaitQueue);
ASSERT(pEntry);
Adapter->nWaitSend--;
Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
DBGPRINT(MP_INFO, ("MpHandleSendInterrupt - send a queued packet\n"));
Status = MpSendPacketFun(Adapter, Packet, TRUE);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
}
}
DBGPRINT(MP_TRACE, ("<--- MpHandleSendInterrupt\n"));
return Status;
}
VOID MpHandleRecvInterrupt(
IN PMP_ADAPTER Adapter
)
/*++
Routine Description:
Interrupt handler for receive processing
Put the received packets into an array and call NdisMIndicateReceivePacket
If we run low on RFDs, allocate another one
Assumption: Rcv spinlock has been acquired
Arguments:
Adapter Pointer to our adapter
Return Value:
None
--*/
{
PMP_RFD pMpRfd;
PHW_RFD pHwRfd;
PNDIS_PACKET PacketArray[NIC_DEF_RFDS];
PNDIS_PACKET PacketFreeArray[NIC_DEF_RFDS];
UINT PacketArrayCount;
UINT PacketFreeCount;
UINT Index;
UINT LoopIndex = 0;
UINT LoopCount = NIC_MAX_RFDS / NIC_DEF_RFDS + 1; // avoid staying here too long
BOOLEAN bContinue = TRUE;
BOOLEAN bAllocNewRfd = FALSE;
USHORT PacketStatus;
DBGPRINT(MP_TRACE, ("---> MpHandleRecvInterrupt\n"));
ASSERT(Adapter->nReadyRecv >= NIC_MIN_RFDS);
while (LoopIndex++ < LoopCount && bContinue)
{
PacketArrayCount = 0;
PacketFreeCount = 0;
//
// Process up to the array size RFD's
//
while (PacketArrayCount < NIC_DEF_RFDS)
{
if (IsListEmpty(&Adapter->RecvList))
{
ASSERT(Adapter->nReadyRecv == 0);
bContinue = FALSE;
break;
}
//
// Get the next MP_RFD to process
//
pMpRfd = (PMP_RFD)GetListHeadEntry(&Adapter->RecvList);
//
// Get the associated HW_RFD
//
pHwRfd = pMpRfd->HwRfd;
//
// Is this packet completed?
//
PacketStatus = NIC_RFD_GET_STATUS(pHwRfd);
if (!NIC_RFD_STATUS_COMPLETED(PacketStatus))
{
bContinue = FALSE;
break;
}
//
// HW specific - check if actual count field has been updated
//
if (!NIC_RFD_VALID_ACTUALCOUNT(pHwRfd))
{
bContinue = FALSE;
break;
}
//
// Remove the RFD from the head of the List
//
RemoveEntryList((PLIST_ENTRY)pMpRfd);
Adapter->nReadyRecv--;
ASSERT(Adapter->nReadyRecv >= 0);
ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_READY));
MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_READY);
//
// A good packet? drop it if not.
//
if (!NIC_RFD_STATUS_SUCCESS(PacketStatus))
{
DBGPRINT(MP_WARN, ("Receive failure = %x\n", PacketStatus));
NICReturnRFD(Adapter, pMpRfd);
continue;
}
//
// Do not receive any packets until a filter has been set
//
if (!Adapter->PacketFilter)
{
NICReturnRFD(Adapter, pMpRfd);
continue;
}
//
// Do not receive any packets until we are at D0
//
if (Adapter->CurrentPowerState != NdisDeviceStateD0)
{
NICReturnRFD(Adapter, pMpRfd);
continue;
}
pMpRfd->PacketSize = NIC_RFD_GET_PACKET_SIZE(pHwRfd);
NdisAdjustBufferLength(pMpRfd->NdisBuffer, pMpRfd->PacketSize);
NdisFlushBuffer(pMpRfd->NdisBuffer, FALSE);
// we don't mess up the buffer chain, no need to make this call in this case
// NdisRecalculatePacketCounts(pMpRfd->ReceivePacket);
//
// set the status on the packet, either resources or success
//
if (Adapter->nReadyRecv >= MIN_NUM_RFD)
{
// NDIS_STATUS_SUCCESS
NDIS_SET_PACKET_STATUS(pMpRfd->NdisPacket, NDIS_STATUS_SUCCESS);
MP_SET_FLAG(pMpRfd, fMP_RFD_RECV_PEND);
InsertTailList(&Adapter->RecvPendList, (PLIST_ENTRY)pMpRfd);
MP_INC_RCV_REF(Adapter);
}
else
{
//
// NDIS_STATUS_RESOURCES
//
NDIS_SET_PACKET_STATUS(pMpRfd->NdisPacket, NDIS_STATUS_RESOURCES);
MP_SET_FLAG(pMpRfd, fMP_RFD_RESOURCES);
PacketFreeArray[PacketFreeCount] = pMpRfd->NdisPacket;
PacketFreeCount++;
//
// Reset the RFD shrink count - don't attempt to shrink RFD
//
Adapter->RfdShrinkCount = 0;
//
// Remember to allocate a new RFD later
//
bAllocNewRfd = TRUE;
}
PacketArray[PacketArrayCount] = pMpRfd->NdisPacket;
PacketArrayCount++;
}
//
// if we didn't process any receives, just return from here
//
if (PacketArrayCount == 0)
{
break;
}
//
// Update the number of outstanding Recvs
//
Adapter->PoMgmt.OutstandingRecv += PacketArrayCount;
NdisDprReleaseSpinLock(&Adapter->RcvLock);
NdisDprAcquireSpinLock(&Adapter->Lock);
//
// if we have a Recv interrupt and have reported a media disconnect status
// time to indicate the new status
//
if (NdisMediaStateDisconnected == Adapter->MediaState)
{
DBGPRINT(MP_WARN, ("Media state changed to Connected\n"));
MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
Adapter->MediaState = NdisMediaStateConnected;
NdisDprReleaseSpinLock(&Adapter->Lock);
//
// Indicate the media event
//
NdisMIndicateStatus(Adapter->AdapterHandle, NDIS_STATUS_MEDIA_CONNECT, (PVOID)0, 0);
NdisMIndicateStatusComplete(Adapter->AdapterHandle);
}
else
{
NdisDprReleaseSpinLock(&Adapter->Lock);
}
NdisMIndicateReceivePacket(
Adapter->AdapterHandle,
PacketArray,
PacketArrayCount);
NdisDprAcquireSpinLock(&Adapter->RcvLock);
//
// NDIS won't take ownership for the packets with NDIS_STATUS_RESOURCES.
// For other packets, NDIS always takes the ownership and gives them back
// by calling MPReturnPackets
//
for (Index = 0; Index < PacketFreeCount; Index++)
{
//
// Get the MP_RFD saved in this packet, in NICAllocRfd
//
pMpRfd = MP_GET_PACKET_RFD(PacketFreeArray[Index]);
ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RESOURCES));
MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RESOURCES);
//
// Decrement the number of outstanding Recvs
//
Adapter->PoMgmt.OutstandingRecv --;
NICReturnRFD(Adapter, pMpRfd);
}
//
//If we have set power pending, then complete it
//
if (((Adapter->bSetPending == TRUE)
&& (Adapter->SetRequest.Oid == OID_PNP_SET_POWER))
&& (Adapter->PoMgmt.OutstandingRecv == 0))
{
MpSetPowerLowComplete(Adapter);
}
}
//
// If we ran low on RFD's, we need to allocate a new RFD
//
if (bAllocNewRfd)
{
//
// Allocate one more RFD only if no pending new RFD allocation AND
// it doesn't exceed the max RFD limit
//
if (!Adapter->bAllocNewRfd && Adapter->CurrNumRfd < Adapter->MaxNumRfd)
{
PMP_RFD TempMpRfd;
NDIS_STATUS TempStatus;
TempMpRfd = NdisAllocateFromNPagedLookasideList(&Adapter->RecvLookaside);
if (TempMpRfd)
{
MP_INC_REF(Adapter);
Adapter->bAllocNewRfd = TRUE;
MP_SET_FLAG(TempMpRfd, fMP_RFD_ALLOC_PEND);
//
// Allocate the shared memory for this RFD.
//
TempStatus = NdisMAllocateSharedMemoryAsync(
Adapter->AdapterHandle,
Adapter->HwRfdSize,
FALSE,
TempMpRfd);
//
// The return value will be either NDIS_STATUS_PENDING or NDIS_STATUS_FAILURE
//
if (TempStatus == NDIS_STATUS_FAILURE)
{
MP_CLEAR_FLAGS(TempMpRfd);
NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, TempMpRfd);
Adapter->bAllocNewRfd = FALSE;
MP_DEC_REF(Adapter);
}
}
}
}
ASSERT(Adapter->nReadyRecv >= NIC_MIN_RFDS);
DBGPRINT(MP_TRACE, ("<--- MpHandleRecvInterrupt\n"));
}
VOID NICReturnRFD(
IN PMP_ADAPTER Adapter,
IN PMP_RFD pMpRfd
)
/*++
Routine Description:
Recycle a RFD and put it back onto the receive list
Assumption: Rcv spinlock has been acquired
Arguments:
Adapter Pointer to our adapter
pMpRfd Pointer to the RFD
Return Value:
None
--*/
{
PMP_RFD pLastMpRfd;
PHW_RFD pHwRfd = pMpRfd->HwRfd;
ASSERT(pMpRfd->Flags == 0);
MP_SET_FLAG(pMpRfd, fMP_RFD_RECV_READY);
//
// HW_SPECIFIC_START
//
pHwRfd->RfdCbHeader.CbStatus = 0;
pHwRfd->RfdActualCount = 0;
pHwRfd->RfdCbHeader.CbCommand = (RFD_EL_BIT);
pHwRfd->RfdCbHeader.CbLinkPointer = DRIVER_NULL;
//
// We don't use any of the OOB data besides status
// Otherwise, we need to clean up OOB data
// NdisZeroMemory(NDIS_OOB_DATA_FROM_PACKET(pMpRfd->NdisPacket),14);
//
// Append this RFD to the RFD chain
if (!IsListEmpty(&Adapter->RecvList))
{
pLastMpRfd = (PMP_RFD)GetListTailEntry(&Adapter->RecvList);
// Link it onto the end of the chain dynamically
pHwRfd = pLastMpRfd->HwRfd;
pHwRfd->RfdCbHeader.CbLinkPointer = pMpRfd->HwRfdPhys;
pHwRfd->RfdCbHeader.CbCommand = 0;
}
//
// HW_SPECIFIC_END
//
//
// The processing on this RFD is done, so put it back on the tail of
// our list
//
InsertTailList(&Adapter->RecvList, (PLIST_ENTRY)pMpRfd);
Adapter->nReadyRecv++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -