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

📄 mp_main.c

📁 Intel EtherExpressTM PRO/100+ Ethernet 网卡在Windows2000/xp下的PCI驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    if (Adapter->nBusySend > 0)
    {
        pMpTcb = Adapter->CurrSendHead;
        pMpTcb->Count++;
        if (pMpTcb->Count > NIC_SEND_HANG_THRESHOLD)
        {
            NdisDprReleaseSpinLock(&Adapter->SendLock);
            DBGPRINT(MP_WARN, ("Send stuck - reset\n"));
            return(TRUE);
        }
    }
    
    NdisDprReleaseSpinLock(&Adapter->SendLock);
    NdisDprAcquireSpinLock(&Adapter->RcvLock);

    //
    // Update the RFD shrink count                                          
    //
    if (Adapter->CurrNumRfd > Adapter->NumRfd)
    {
        Adapter->RfdShrinkCount++;          
    }



    NdisDprReleaseSpinLock(&Adapter->RcvLock);
    NdisDprAcquireSpinLock(&Adapter->Lock);
    CurrMediaState = NICGetMediaState(Adapter);

    if (CurrMediaState != Adapter->MediaState)
    {
        DBGPRINT(MP_WARN, ("Media state changed to %s\n",
            ((CurrMediaState == NdisMediaStateConnected)? 
            "Connected": "Disconnected")));

        Adapter->MediaState = CurrMediaState;
        Status = (CurrMediaState == NdisMediaStateConnected) ? 
                 NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT;          
        if (Status == NDIS_STATUS_MEDIA_CONNECT)
        {
            MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
        }
        else
        {
            MP_SET_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
        }
        
        NdisDprReleaseSpinLock(&Adapter->Lock);
        
        // Indicate the media event
        NdisMIndicateStatus(Adapter->AdapterHandle, Status, (PVOID)0, 0);

        NdisMIndicateStatusComplete(Adapter->AdapterHandle);
    }
    else
    {
        NdisDprReleaseSpinLock(&Adapter->Lock);
    }
    return(FALSE);
}


VOID MPHalt(
    IN  NDIS_HANDLE     MiniportAdapterContext)
/*++

Routine Description:
    
    MiniportHalt handler
    
Arguments:

    MiniportAdapterContext  Pointer to our adapter

Return Value:

    None
    
--*/
{
    LONG            Count;

    PMP_ADAPTER     Adapter = (PMP_ADAPTER) MiniportAdapterContext;
    
    MP_SET_FLAG(Adapter, fMP_ADAPTER_HALT_IN_PROGRESS);
                                           
    DBGPRINT(MP_TRACE, ("====> MPHalt\n"));

    //
    // Call Shutdown handler to disable interrupt and turn the hardware off 
    // by issuing a full reset
    //
    MPShutdown(MiniportAdapterContext);
    
    //
    // Deregister interrupt as early as possible
    //
    if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE))
    {
        NdisMDeregisterInterrupt(&Adapter->Interrupt);                           
        MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE);
    }

#if LBFO
    MpRemoveAdapterFromList(Adapter);

    //
    // For a regualr miniport, no send packets and OID requests should be outstanding 
    // when Halt handler is called. But for a LBFO miniport in secondary mode, 
    // some packets from primary miniport may be still around
    //

    NdisAcquireSpinLock(&Adapter->SendLock);
              
    //
    // Free the packets on SendWaitList                                                           
    //
    MpFreeQueuedSendPackets(Adapter);

    //
    // Free the packets being actively sent & stopped
    //
    MpFreeBusySendPackets(Adapter);
    
    NdisReleaseSpinLock(&Adapter->SendLock);

#endif

    //
    // Decrement the ref count which was incremented in MPInitialize
    //
    Count = MP_DEC_REF(Adapter);

    //
    // Possible non-zero ref counts mean one or more of the following conditions: 
    // 1) Pending async shared memory allocation;
    // 2) DPC's are not finished (e.g. link detection)
    //
    if (Count)
    {
        DBGPRINT(MP_WARN, ("RefCount=%d --- waiting!\n", MP_GET_REF(Adapter)));

        while (TRUE)
        {
            if (NdisWaitEvent(&Adapter->ExitEvent, 2000))
            {
                break;
            }

            DBGPRINT(MP_WARN, ("RefCount=%d --- rewaiting!\n", MP_GET_REF(Adapter)));
        }
    }
    
    NdisAcquireSpinLock(&Adapter->RcvLock);
    //
    // wait for all the received packets to return
    //
    MP_DEC_RCV_REF(Adapter);
    Count = MP_GET_RCV_REF(Adapter);
    
    NdisReleaseSpinLock(&Adapter->RcvLock);

    if (Count)
    {
        DBGPRINT(MP_WARN, ("RcvRefCount=%d --- waiting!\n", Count));

        while (TRUE)
        {
            if (NdisWaitEvent(&Adapter->AllPacketsReturnedEvent, 2000))
            {
                break;
            }

            DBGPRINT(MP_WARN, ("RcvRefCount=%d --- rewaiting!\n", MP_GET_RCV_REF(Adapter)));
        }
    }
        

    //
    // Reset the PHY chip.  We do this so that after a warm boot, the PHY will
    // be in a known state, with auto-negotiation enabled.
    //
    ResetPhy(Adapter);

    //
    // Free the entire adapter object, including the shared memory structures.
    //
    MpFreeAdapter(Adapter);

    DBGPRINT(MP_TRACE, ("<==== MPHalt\n"));
}

NDIS_STATUS MPReset(
    OUT PBOOLEAN        AddressingReset,
    IN  NDIS_HANDLE     MiniportAdapterContext)
/*++

Routine Description:
    
    MiniportReset handler
    
Arguments:

    AddressingReset         To let NDIS know whether we need help from it with our reset
    MiniportAdapterContext  Pointer to our adapter

Return Value:

    NDIS_STATUS_SUCCESS
    NDIS_STATUS_PENDING
    NDIS_STATUS_RESET_IN_PROGRESS
    NDIS_STATUS_HARD_ERRORS

Note:
    ResetHandler is called at DPC. take advantage of this fact when acquiring or releasing
    spinlocks
    
--*/
{
    NDIS_STATUS     Status;
    
    PMP_ADAPTER     Adapter = (PMP_ADAPTER) MiniportAdapterContext;

    DBGPRINT(MP_TRACE, ("====> MPReset\n"));

    *AddressingReset = TRUE;

    NdisDprAcquireSpinLock(&Adapter->Lock);
    NdisDprAcquireSpinLock(&Adapter->SendLock);
    NdisDprAcquireSpinLock(&Adapter->RcvLock);

    do
    {
        ASSERT(!MP_TEST_FLAG(Adapter, fMP_ADAPTER_HALT_IN_PROGRESS));
  
        //
        // Is this adapter already doing a reset?
        //
        if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS))
        {
            Status = NDIS_STATUS_RESET_IN_PROGRESS;
            MP_EXIT;
        }

        MP_SET_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);

        //
        // Is this adapter doing link detection?                                      
        //
        if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
        {
            DBGPRINT(MP_WARN, ("Reset is pended...\n"));
        
            Adapter->bResetPending = TRUE;
            Status = NDIS_STATUS_PENDING;
            MP_EXIT;
        }
        //
        // Is this adapter going to be removed
        //
        if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_NON_RECOVER_ERROR))
        {
           Status = NDIS_STATUS_HARD_ERRORS;
           if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_REMOVE_IN_PROGRESS))
           {
               MP_EXIT;
           }
                      
           // This is an unrecoverable hardware failure. 
           // We need to tell NDIS to remove this miniport
           MP_SET_FLAG(Adapter, fMP_ADAPTER_REMOVE_IN_PROGRESS);
           MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
           
           NdisDprReleaseSpinLock(&Adapter->RcvLock);
           NdisDprReleaseSpinLock(&Adapter->SendLock);
           NdisDprReleaseSpinLock(&Adapter->Lock);
           
           NdisWriteErrorLogEntry(
               Adapter->AdapterHandle,
               NDIS_ERROR_CODE_HARDWARE_FAILURE,
               1,
               ERRLOG_REMOVE_MINIPORT);
           
           NdisMRemoveMiniport(Adapter->AdapterHandle);
           
           DBGPRINT_S(Status, ("<==== MPReset, Status=%x\n", Status));
            
           return Status;
        }   
                

        //
        // Disable the interrupt and issue a reset to the NIC
        //
        NICDisableInterrupt(Adapter);
        NICIssueSelectiveReset(Adapter);


        //
        // release all the locks and then acquire back the send lock
        // we are going to clean up the send queues
        // which may involve calling Ndis APIs
        // release all the locks before grabbing the send lock to
        // avoid deadlocks
        //
        NdisDprReleaseSpinLock(&Adapter->RcvLock);
        NdisDprReleaseSpinLock(&Adapter->SendLock);
        NdisDprReleaseSpinLock(&Adapter->Lock);
        
        NdisDprAcquireSpinLock(&Adapter->SendLock);


        //
        // This is a deserialized miniport, we need to free all the send packets
        // Free the packets on SendWaitList                                                           
        //
        MpFreeQueuedSendPackets(Adapter);

        //
        // Free the packets being actively sent & stopped
        //
        MpFreeBusySendPackets(Adapter);

#if DBG
        if (MP_GET_REF(Adapter) > 1)
        {
            DBGPRINT(MP_WARN, ("RefCount=%d\n", MP_GET_REF(Adapter)));
        }
#endif

        NdisZeroMemory(Adapter->MpTcbMem, Adapter->MpTcbMemSize);

        //
        // Re-initialize the send structures
        //
        NICInitSend(Adapter);
        
        NdisDprReleaseSpinLock(&Adapter->SendLock);

        //
        // get all the locks again in the right order
        //
        NdisDprAcquireSpinLock(&Adapter->Lock);
        NdisDprAcquireSpinLock(&Adapter->SendLock);
        NdisDprAcquireSpinLock(&Adapter->RcvLock);

        //
        // Reset the RFD list and re-start RU         
        //
        NICResetRecv(Adapter);
        Status = NICStartRecv(Adapter);
        if (Status != NDIS_STATUS_SUCCESS) 
        {
            // Are we having failures in a few consecutive resets?                  
            if (Adapter->HwErrCount < NIC_HARDWARE_ERROR_THRESHOLD)
            {
                // It's not over the threshold yet, let it to continue
                Adapter->HwErrCount++;
            }
            else
            {
                // This is an unrecoverable hardware failure. 
                // We need to tell NDIS to remove this miniport
                MP_SET_FLAG(Adapter, fMP_ADAPTER_REMOVE_IN_PROGRESS);
                MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
                
                NdisDprReleaseSpinLock(&Adapter->RcvLock);
                NdisDprReleaseSpinLock(&Adapter->SendLock);
                NdisDprReleaseSpinLock(&Adapter->Lock);
                
                NdisWriteErrorLogEntry(
                    Adapter->AdapterHandle,
                    NDIS_ERROR_CODE_HARDWARE_FAILURE,
                    1,
                    ERRLOG_REMOVE_MINIPORT);
                     
                NdisMRemoveMiniport(Adapter->AdapterHandle);
                
                DBGPRINT_S(Status, ("<==== MPReset, Status=%x\n", Status));
                return(Status);
            }
            
            break;
        }
        
        Adapter->HwErrCount = 0;
        MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_HARDWARE_ERROR);

        NICEnableInterrupt(Adapter);

    } while (FALSE);

    MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);

    exit:

    NdisDprReleaseSpinLock(&Adapter->RcvLock);
    NdisDprReleaseSpinLock(&Adapter->SendLock);
    NdisDprReleaseSpinLock(&Adapter->Lock);



    DBGPRINT_S(Status, ("<==== MPReset, Status=%x\n", Status));
    return(Status);
}

VOID MPReturnPacket(
    IN  NDIS_HANDLE     MiniportAdapterContext,
    IN  PNDIS_PACKET    Packet
    )
/*++

Routine Description:
    
    MiniportReturnPacket handler
    
Arguments:

    MiniportAdapterContext  Pointer to our adapter
    Packet                  Pointer to a packet being returned to the miniport

Return Value:

    None

Note:
    ReturnPacketHandler is called at DPC. take advantage of this fact when acquiring or releasing
    spinlocks
    
--*/
{
    PMP_ADAPTER     Adapter = (PMP_ADAPTER)MiniportAdapterContext;
    PMP_RFD         pMpRfd = MP_GET_PACKET_RFD(Packet);
    ULONG           Count;

    DBGPRINT(MP_TRACE, ("====> MPReturnPacket\n"));

    ASSERT(pMpRfd);

    ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_PEND));
    MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_PEND);

    NdisDprAcquireSpinLock(&Adapter->RcvLock);

    RemoveEntryList((PLIST_ENTRY)pMpRfd);


    // Decrement the Power Mgmt Ref.
    Adapter->PoMgmt.OutstandingRecv --;
    //
    // 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 (Adapter->RfdShrinkCount < NIC_RFD_SHRINK_THRESHOLD)
    {
        NICReturnRFD(Adapter, pMpRfd);
    }
    else
    {
        ASSERT(Adapter->CurrNumRfd > Adapter->NumRfd);

        Adapter->RfdShrinkCount = 0;
        NICFreeRfd(Adapter, pMpRfd);
        Adapter->CurrNumRfd--;

        DBGPRINT(MP_TRACE, ("Shrink... CurrNumRfd = %d\n", Adapter->CurrNumRfd));
    }


    //
    // note that we get the ref count here, but check
    // to see if it is zero and signal the event -after-
    // releasign the SpinLock. otherwise, we may let the Halthandler
    // continue while we are holding a lock.
    //
    MP_DEC_RCV_REF(Adapter);
    Count =  MP_GET_RCV_REF(Adapter);

    NdisDprReleaseSpinLock(&Adapter->RcvLock);

    if (Count == 0)
        NdisSetEvent(&Adapter->AllPacketsReturnedEvent);

    DBGPRINT(MP_TRACE, ("<==== MPReturnPacket\n"));
}


VOID MPSendPackets(

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -