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

📄 mp_nic.c

📁 Intel EtherExpressTM PRO/100+ Ethernet 网卡在Windows2000/xp下的PCI驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:

    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 + -