📄 mp_main.c
字号:
IN NDIS_HANDLE MiniportAdapterContext,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets)
/*++
Routine Description:
MiniportSendPackets handler
Arguments:
MiniportAdapterContext Pointer to our adapter
PacketArray Set of packets to send
NumberOfPackets Self-explanatory
Return Value:
None
--*/
{
PMP_ADAPTER Adapter;
NDIS_STATUS Status;
UINT PacketCount;
#if LBFO
PMP_ADAPTER ThisAdapter;
#endif
DBGPRINT(MP_TRACE, ("====> MPSendPackets\n"));
Adapter = (PMP_ADAPTER)MiniportAdapterContext;
#if LBFO
NdisAcquireSpinLock(&Adapter->LockLBFO);
// Any secondary adapters?
if (Adapter->NumSecondary)
{
// In this sample driver, we do very simple load balancing ...
// Walk through the secondary miniport list, send the packets on a secondary
// miniport if it's ready
// If none of the secondary miniports is ready, we'll use the primary miniport
ThisAdapter = Adapter->NextSecondary;
while (ThisAdapter)
{
if (MP_IS_NOT_READY(ThisAdapter))
{
ThisAdapter = ThisAdapter->NextSecondary;
continue;
}
//
// Found a good secondary miniport to send packets on
// Need to put a ref on this adapter so it won't go away
//
MP_LBFO_INC_REF(ThisAdapter);
NdisReleaseSpinLock(&Adapter->LockLBFO);
NdisAcquireSpinLock(&ThisAdapter->SendLock);
//
// Send these packets
//
for (PacketCount=0;PacketCount < NumberOfPackets; PacketCount++)
{
MpSendPacket(ThisAdapter, PacketArray[PacketCount], FALSE);
}
NdisReleaseSpinLock(&ThisAdapter->SendLock);
//
// Done with this adapter for now, deref it
//
MP_LBFO_DEC_REF(ThisAdapter);
//
// Sent all the packets on a secondary miniport, return
//
return;
}
}
NdisReleaseSpinLock(&Adapter->LockLBFO);
#endif
NdisAcquireSpinLock(&Adapter->SendLock);
// Is this adapter ready for sending?
if (MP_IS_NOT_READY(Adapter))
{
//
// there is link
//
if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
{
for (PacketCount = 0; PacketCount < NumberOfPackets; PacketCount++)
{
InsertTailQueue(&Adapter->SendWaitQueue,
MP_GET_PACKET_MR(PacketArray[PacketCount]));
Adapter->nWaitSend++;
DBGPRINT(MP_WARN, ("MpSendPackets: link detection - queue packet "PTR_FORMAT"\n",
PacketArray[PacketCount]));
}
NdisReleaseSpinLock(&Adapter->SendLock);
return;
}
//
// Adapter is not ready and there is not link
//
Status = MP_GET_STATUS_FROM_FLAGS(Adapter);
NdisReleaseSpinLock(&Adapter->SendLock);
for (PacketCount = 0; PacketCount < NumberOfPackets; PacketCount++)
{
NdisMSendComplete(
MP_GET_ADAPTER_HANDLE(Adapter),
PacketArray[PacketCount],
Status);
}
return;
}
//
// Adapter is ready, send these packets
//
for (PacketCount = 0; PacketCount < NumberOfPackets; PacketCount++)
{
//
// queue is not empty or tcb is not available
//
if (!IsQueueEmpty(&Adapter->SendWaitQueue) ||
!MP_TCB_RESOURCES_AVAIABLE(Adapter))
{
InsertTailQueue(&Adapter->SendWaitQueue, MP_GET_PACKET_MR(PacketArray[PacketCount]));
Adapter->nWaitSend++;
}
else
{
MpSendPacket(Adapter, PacketArray[PacketCount], FALSE);
}
}
NdisReleaseSpinLock(&Adapter->SendLock);
DBGPRINT(MP_TRACE, ("<==== MPSendPackets\n"));
return;
}
VOID MPShutdown(
IN NDIS_HANDLE MiniportAdapterContext)
/*++
Routine Description:
MiniportShutdown handler
Arguments:
MiniportAdapterContext Pointer to our adapter
Return Value:
None
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
DBGPRINT(MP_TRACE, ("====> MPShutdown\n"));
//
// Disable interrupt and issue a full reset
//
NICDisableInterrupt(Adapter);
NICIssueFullReset(Adapter);
DBGPRINT(MP_TRACE, ("<==== MPShutdown\n"));
}
VOID MPAllocateComplete(
IN NDIS_HANDLE MiniportAdapterContext,
IN PVOID VirtualAddress,
IN PNDIS_PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG Length,
IN PVOID Context)
/*++
Routine Description:
MiniportAllocateComplete handler
This handler is needed because we make calls to NdisMAllocateSharedMemoryAsync
Arguments:
MiniportAdapterContext Pointer to our adapter
VirtualAddress Pointer to the allocated memory block
PhysicalAddress Physical address of the memory block
Length Length of the memory block
Context Context in NdisMAllocateSharedMemoryAsync
Return Value:
None
--*/
{
ULONG ErrorValue;
PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
PMP_RFD pMpRfd = (PMP_RFD)Context;
#if !DBG
UNREFERENCED_PARAMETER(Length);
#endif
DBGPRINT(MP_TRACE, ("==== MPAllocateComplete\n"));
ASSERT(pMpRfd);
ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_ALLOC_PEND));
MP_CLEAR_FLAG(pMpRfd, fMP_RFD_ALLOC_PEND);
NdisAcquireSpinLock(&Adapter->RcvLock);
//
// Is allocation successful?
//
if (VirtualAddress)
{
ASSERT(Length == Adapter->HwRfdSize);
pMpRfd->OriginalHwRfd = (PHW_RFD)VirtualAddress;
pMpRfd->OriginalHwRfdPa = *PhysicalAddress;
//
// First get a HwRfd at 8 byte boundary from OriginalHwRfd
//
pMpRfd->HwRfd = (PHW_RFD)DATA_ALIGN(pMpRfd->OriginalHwRfd);
//
// Then shift HwRfd so that the data(after ethernet header) is at 8 bytes boundary
//
pMpRfd->HwRfd = (PHW_RFD)((PUCHAR)pMpRfd->HwRfd + HWRFD_SHIFT_OFFSET);
//
// Update physical address as well
//
pMpRfd->HwRfdPa.QuadPart = pMpRfd->OriginalHwRfdPa.QuadPart + BYTES_SHIFT(pMpRfd->HwRfd, pMpRfd->OriginalHwRfd);
ErrorValue = NICAllocRfd(Adapter, pMpRfd);
if (ErrorValue == 0)
{
// Add this RFD to the RecvList
Adapter->CurrNumRfd++;
NICReturnRFD(Adapter, pMpRfd);
ASSERT(Adapter->CurrNumRfd <= Adapter->MaxNumRfd);
DBGPRINT(MP_TRACE, ("CurrNumRfd=%d\n", Adapter->CurrNumRfd));
}
else
{
NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pMpRfd);
}
}
else
{
NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pMpRfd);
}
Adapter->bAllocNewRfd = FALSE;
MP_DEC_REF(Adapter);
if (MP_GET_REF(Adapter) == 0)
{
NdisSetEvent(&Adapter->ExitEvent);
}
NdisReleaseSpinLock(&Adapter->RcvLock);
}
VOID MPIsr(
OUT PBOOLEAN InterruptRecognized,
OUT PBOOLEAN QueueMiniportHandleInterrupt,
IN NDIS_HANDLE MiniportAdapterContext)
/*++
Routine Description:
MiniportIsr handler
Arguments:
InterruptRecognized TRUE on return if the interrupt comes from this NIC
QueueMiniportHandleInterrupt TRUE on return if MiniportHandleInterrupt should be called
MiniportAdapterContext Pointer to our adapter
Return Value:
None
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
USHORT IntStatus;
DBGPRINT(MP_LOUD, ("====> MPIsr\n"));
do
{
//
// If the adapter is in low power state, then it should not
// recognize any interrupt
//
if (Adapter->CurrentPowerState > NdisDeviceStateD0)
{
*InterruptRecognized = FALSE;
*QueueMiniportHandleInterrupt = FALSE;
break;
}
//
// We process the interrupt if it's not disabled and it's active
//
if (!NIC_INTERRUPT_DISABLED(Adapter) && NIC_INTERRUPT_ACTIVE(Adapter))
{
*InterruptRecognized = TRUE;
*QueueMiniportHandleInterrupt = TRUE;
//
// Disable the interrupt (will be re-enabled in MPHandleInterrupt
//
NICDisableInterrupt(Adapter);
//
// Acknowledge the interrupt(s) and get the interrupt status
//
NIC_ACK_INTERRUPT(Adapter, IntStatus);
}
else
{
*InterruptRecognized = FALSE;
*QueueMiniportHandleInterrupt = FALSE;
}
}
while (FALSE);
DBGPRINT(MP_LOUD, ("<==== MPIsr\n"));
}
VOID MPHandleInterrupt(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
MiniportHandleInterrupt handler
Arguments:
MiniportAdapterContext Pointer to our adapter
Return Value:
None
--*/
{
PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
NdisDprAcquireSpinLock(&Adapter->RcvLock);
MpHandleRecvInterrupt(Adapter);
NdisDprReleaseSpinLock(&Adapter->RcvLock);
//
// Handle send interrupt
//
NdisDprAcquireSpinLock(&Adapter->SendLock);
MpHandleSendInterrupt(Adapter);
NdisDprReleaseSpinLock(&Adapter->SendLock);
//
// Start the receive unit if it had stopped
//
NdisDprAcquireSpinLock(&Adapter->RcvLock);
NICStartRecv(Adapter);
NdisDprReleaseSpinLock(&Adapter->RcvLock);
//
// Re-enable the interrupt (disabled in MPIsr)
//
NdisMSynchronizeWithInterrupt(
&Adapter->Interrupt,
(PVOID)NICEnableInterrupt,
Adapter);
}
VOID MPCancelSendPackets(
IN NDIS_HANDLE MiniportAdapterContext,
IN PVOID CancelId)
/*++
Routine Description:
MiniportCancelSendpackets handler - NDIS51 and later
Arguments:
MiniportAdapterContext Pointer to our adapter
CancelId All the packets with this Id should be cancelled
Return Value:
None
--*/
{
PQUEUE_ENTRY pEntry, pPrevEntry, pNextEntry;
PNDIS_PACKET Packet;
PVOID PacketId;
PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
DBGPRINT(MP_TRACE, ("====> MPCancelSendPackets\n"));
pPrevEntry = NULL;
NdisAcquireSpinLock(&Adapter->SendLock);
//
// Walk through the send wait queue and complete the sends with matching Id
//
pEntry = Adapter->SendWaitQueue.Head;
while (pEntry)
{
Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
PacketId = NdisGetPacketCancelId(Packet);
if (PacketId == CancelId)
{
Adapter->nWaitSend--;
//
// This packet has the right CancelId
//
pNextEntry = pEntry->Next;
if (pPrevEntry == NULL)
{
Adapter->SendWaitQueue.Head = pNextEntry;
if (pNextEntry == NULL)
{
Adapter->SendWaitQueue.Tail = NULL;
}
}
else
{
pPrevEntry->Next = pNextEntry;
if (pNextEntry == NULL)
{
Adapter->SendWaitQueue.Tail = pPrevEntry;
}
}
pEntry = pEntry->Next;
// Put this packet on SendCancelQueue
InsertTailQueue(&Adapter->SendCancelQueue, MP_GET_PACKET_MR(Packet));
Adapter->nCancelSend++;
}
else
{
// This packet doesn't have the right CancelId
pPrevEntry = pEntry;
pEntry = pEntry->Next;
}
}
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -