⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp_main.c

📁 Intel EtherExpressTM PRO/100+ Ethernet 网卡在Windows2000/xp下的PCI驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 + -