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

📄 mp_main.c

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

Copyright (c) 1999  Microsoft Corporation

Module Name:
    mp_main.c

Abstract:
    This module contains NDIS miniport handlers

Revision History:
    Who         When        What
    --------    --------    ----------------------------------------------
    DChen       11-01-99    created

Notes:

--*/

#include "precomp.h"

#if DBG
#define _FILENUMBER     'NIAM'
#endif

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#endif


//                 
// Global data for LBFO
//
#if LBFO
LIST_ENTRY g_AdapterList;
NDIS_SPIN_LOCK g_Lock;
#endif

NDIS_STATUS DriverEntry(
    IN  PDRIVER_OBJECT   DriverObject,
    IN  PUNICODE_STRING  RegistryPath
    )
/*++
Routine Description:

Arguments:

    DriverObject    -   pointer to the driver object
    RegistryPath    -   pointer to the driver registry path
     
Return Value:
    
    NDIS_STATUS - the value returned by NdisMRegisterMiniport 
    
--*/
{
    NDIS_STATUS                   Status;
    NDIS_HANDLE                   NdisWrapperHandle;
    NDIS_MINIPORT_CHARACTERISTICS MPChar;

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

    //
    // Notify the NDIS wrapper about this driver, get a NDIS wrapper handle back
    //
    NdisMInitializeWrapper(
        &NdisWrapperHandle,
        DriverObject,
        RegistryPath,
        NULL);

    if (NdisWrapperHandle == NULL)
    {
        Status = NDIS_STATUS_FAILURE;

        DBGPRINT_S(Status, ("<==== DriverEntry failed to InitWrapper, Status=%x\n", Status));
        return Status;
    }

#if LBFO
    //
    // Init the global data
    //
    InitializeListHead(&g_AdapterList);
    NdisAllocateSpinLock(&g_Lock);

    //
    // For regular miniports, there is NO need to have an Unload handler
    // For a LBFO miniport, register an Unload handler for global data cleanup
    // The unload handler has a more global scope, whereas the scope of the 
    // MiniportHalt function is restricted to a particular miniport instance.
    //
    NdisMRegisterUnloadHandler(NdisWrapperHandle, MPUnload);
#endif      

    //
    // Fill in the Miniport characteristics structure with the version numbers 
    // and the entry points for driver-supplied MiniportXxx 
    //
    NdisZeroMemory(&MPChar, sizeof(MPChar));

    MPChar.MajorNdisVersion         = MP_NDIS_MAJOR_VERSION;
    MPChar.MinorNdisVersion         = MP_NDIS_MINOR_VERSION;

    MPChar.CheckForHangHandler      = MPCheckForHang;
    MPChar.DisableInterruptHandler  = NULL;
    MPChar.EnableInterruptHandler   = NULL;
    MPChar.HaltHandler              = MPHalt;
    MPChar.InitializeHandler        = MPInitialize;
    MPChar.QueryInformationHandler  = MPQueryInformation;
    MPChar.ResetHandler             = MPReset;
    MPChar.ReturnPacketHandler      = MPReturnPacket;
    
    MPChar.SendPacketsHandler       = MpSendPacketsHandler;
    
    MPChar.SetInformationHandler    = MPSetInformation;
    MPChar.AllocateCompleteHandler  = MPAllocateComplete;
    MPChar.HandleInterruptHandler   = MPHandleInterrupt;
    MPChar.ISRHandler               = MPIsr;

    MPChar.CancelSendPacketsHandler = MPCancelSendPackets;
    MPChar.PnPEventNotifyHandler    = MPPnPEventNotify;
    MPChar.AdapterShutdownHandler   = MPShutdown;

    DBGPRINT(MP_LOUD, ("Calling NdisMRegisterMiniport...\n"));

    Status = NdisMRegisterMiniport(
                 NdisWrapperHandle,
                 &MPChar,
                 sizeof(NDIS_MINIPORT_CHARACTERISTICS));

    if (Status != NDIS_STATUS_SUCCESS)
    {
        NdisTerminateWrapper(NdisWrapperHandle, NULL);
    }
    DBGPRINT_S(Status, ("<==== DriverEntry, Status=%x\n", Status));

    return Status;
}


NDIS_STATUS MPInitialize(
    OUT PNDIS_STATUS    OpenErrorStatus,
    OUT PUINT           SelectedMediumIndex,
    IN  PNDIS_MEDIUM    MediumArray,
    IN  UINT            MediumArraySize,
    IN  NDIS_HANDLE     MiniportAdapterHandle,
    IN  NDIS_HANDLE     WrapperConfigurationContext
    )
/*++
Routine Description:

    MiniportInitialize handler

Arguments:

    OpenErrorStatus         Not used
    SelectedMediumIndex     Place-holder for what media we are using
    MediumArray             Array of ndis media passed down to us to pick from
    MediumArraySize         Size of the array
    MiniportAdapterHandle   The handle NDIS uses to refer to us
    WrapperConfigurationContext For use by NdisOpenConfiguration

Return Value:

    NDIS_STATUS_SUCCESS unless something goes wrong

--*/
{
    NDIS_STATUS     Status;
    PMP_ADAPTER     Adapter = NULL;
    UINT            index;
    
#if DBG
    LARGE_INTEGER   TS, TD, TE;
#endif

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

#if DBG
    NdisGetCurrentSystemTime(&TS);
#endif    

    do
    {
        //
        // Find the media type we support
        //
        for (index = 0; index < MediumArraySize; ++index)
        {
            if (MediumArray[index] == NIC_MEDIA_TYPE) 
	    {
                break;
            }
        }

        if (index == MediumArraySize)
        {
            DBGPRINT(MP_ERROR, ("Expected media (%x) is not in MediumArray.\n", NIC_MEDIA_TYPE));
            Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
            break;
        }

        *SelectedMediumIndex = index;

        //
        // Allocate MP_ADAPTER structure
        //
        Status = MpAllocAdapterBlock(&Adapter);
        if (Status != NDIS_STATUS_SUCCESS) 
        {
            break;
        }

        Adapter->AdapterHandle = MiniportAdapterHandle;

        //
        // Read the registry parameters
        //
        Status = NICReadRegParameters(
                     Adapter,
                     WrapperConfigurationContext);
        if (Status != NDIS_STATUS_SUCCESS) 
        {
            break;
        }

        //
        // Inform NDIS of the attributes of our adapter.
        // This has to be done before calling NdisMRegisterXxx or NdisXxxx function
        // that depends on the information supplied to NdisMSetAttributesEx
        // e.g. NdisMInitializeScatterGatherDma 
        // As this is NDIS51 miniport, it should use safe APIs. 
        // 
        NdisMSetAttributesEx(
            MiniportAdapterHandle,
            (NDIS_HANDLE) Adapter,
            0,
            NDIS_ATTRIBUTE_DESERIALIZE | 
            NDIS_ATTRIBUTE_BUS_MASTER,
            NIC_INTERFACE_TYPE);

        //
        // Find the physical adapter
        //
        Status = MpFindAdapter(Adapter, WrapperConfigurationContext);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        //
        // Map bus-relative IO range to system IO space
        //
        Status = NdisMRegisterIoPortRange(
                     (PVOID *)&Adapter->PortOffset,
                     Adapter->AdapterHandle,
                     Adapter->IoBaseAddress,
                     Adapter->IoRange);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            DBGPRINT(MP_ERROR, ("NdisMRegisterioPortRange failed\n"));
    
            NdisWriteErrorLogEntry(
                Adapter->AdapterHandle,
                NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,
                0);
        
            break;
        }
        
        //
        // Read additional info from NIC such as MAC address
        //
        Status = NICReadAdapterInfo(Adapter);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }
        
        //
        // Allocate all other memory blocks including shared memory
        //
        Status = NICAllocAdapterMemory(Adapter);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        //
        // Init send data structures
        //
        NICInitSend(Adapter);

        //
        // Init receive data structures
        //
        Status = NICInitRecv(Adapter);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }
        
        // Map bus-relative registers to virtual system-space
        Status = NdisMMapIoSpace(
                     (PVOID *) &(Adapter->CSRAddress),
                     Adapter->AdapterHandle,
                     Adapter->MemPhysAddress,
                     NIC_MAP_IOSPACE_LENGTH);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            DBGPRINT(MP_ERROR, ("NdisMMapIoSpace failed\n"));
    
            NdisWriteErrorLogEntry(
                Adapter->AdapterHandle,
                NDIS_ERROR_CODE_RESOURCE_CONFLICT,
                1,
                ERRLOG_MAP_IO_SPACE);
        
            break;
        }

        DBGPRINT(MP_INFO, ("CSRAddress="PTR_FORMAT"\n", Adapter->CSRAddress));

        //
        // Disable interrupts here which is as soon as possible
        //
        NICDisableInterrupt(Adapter);
                     
        //
        // Register the interrupt
        //
        Status = NdisMRegisterInterrupt(
                     &Adapter->Interrupt,
                     Adapter->AdapterHandle,
                     Adapter->InterruptLevel,
                     Adapter->InterruptLevel,
                     TRUE,       // RequestISR
                     TRUE,       // SharedInterrupt
                     NIC_INTERRUPT_MODE);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            DBGPRINT(MP_ERROR, ("NdisMRegisterInterrupt failed\n"));
    
            NdisWriteErrorLogEntry(
                Adapter->AdapterHandle,
                NDIS_ERROR_CODE_INTERRUPT_CONNECT,
                0);
        
            break;
        }
        
        MP_SET_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE);

        //
        // Test our adapter hardware
        //
        Status = NICSelfTest(Adapter);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }
        
        //
        // Init the hardware and set up everything
        //
        Status = NICInitializeAdapter(Adapter);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }
        
        //
        // Enable the interrupt
        //
        NICEnableInterrupt(Adapter);

        //
        // Minimize init-time
        //
        NdisMInitializeTimer(
            &Adapter->LinkDetectionTimer, 
            Adapter->AdapterHandle,
            MpLinkDetectionDpc, 
            Adapter);

        //
        // Set the link detection flag
        //
        MP_SET_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION);

        //
        // Increment the reference count so halt handler will wait 
        //
        MP_INC_REF(Adapter);
        NdisMSetTimer(&Adapter->LinkDetectionTimer, NIC_LINK_DETECTION_DELAY);
        
#if LBFO
        //
        // Add this adapter to the global miniport list
        //
        MpAddAdapterToList(Adapter);
#endif

    } while (FALSE);

    if (Adapter && Status != NDIS_STATUS_SUCCESS)
    {
        //
        // Undo everything if it failed
        //
        MP_DEC_REF(Adapter);
        MpFreeAdapter(Adapter);
    }

    
#if DBG
    NdisGetCurrentSystemTime(&TE);
    TD.QuadPart = TE.QuadPart - TS.QuadPart;
    TD.QuadPart /= 10000;       // Convert to ms
    DBGPRINT(MP_WARN, ("Init time = %d ms\n", TD.LowPart));
#endif    
    
    DBGPRINT_S(Status, ("<==== MPInitialize, Status=%x\n", Status));
    //
    // Ndis doesn't check OpenErrorStatus.
    //
    *OpenErrorStatus = Status;
    
    return Status;
}


BOOLEAN MPCheckForHang(
    IN  NDIS_HANDLE     MiniportAdapterContext
    )
/*++

Routine Description:
    
    MiniportCheckForHang handler
    
Arguments:

    MiniportAdapterContext  Pointer to our adapter

Return Value:

    TRUE    This NIC needs a reset
    FALSE   Everything is fine

Note: 
    CheckForHang handler is called in the context of a timer DPC. 
    take advantage of this fact when acquiring/releasing spinlocks

--*/
{
    PMP_ADAPTER         Adapter = (PMP_ADAPTER) MiniportAdapterContext;
    NDIS_MEDIA_STATE    CurrMediaState;
    NDIS_STATUS         Status;
    PMP_TCB             pMpTcb;
    
    //
    // Just skip this part if the adapter is doing link detection
    //
    if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
    {
        return(FALSE);   
    }

    //
    // any nonrecoverable hardware error?
    //
    if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_NON_RECOVER_ERROR))
    {
        DBGPRINT(MP_WARN, ("Non recoverable error - remove\n"));
        return (TRUE);
    }
            
    //
    // hardware failure?
    //
    if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_HARDWARE_ERROR))
    {
        DBGPRINT(MP_WARN, ("hardware error - reset\n"));
        return(TRUE);
    }
          
    //
    // Is send stuck?                  
    //
    
    NdisDprAcquireSpinLock(&Adapter->SendLock);

⌨️ 快捷键说明

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