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

📄 nic_init.c

📁 ddk开发pci范例,使用9054芯片
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

Copyright (c) Microsoft Corporation.  All rights reserved.

    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY      
    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    PURPOSE.

Module Name:

    NIC_INIT.c

Abstract:

    Contains rotuines to do resource allocation and hardware
    initialization & shutdown.

Environment:

    Kernel mode


Revision History:

    Eliyas Yakub Feb 13, 2003

--*/

#include "precomp.h"

#if defined(EVENT_TRACING)
#include "nic_init.tmh"
#endif

#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, NICInitializeDeviceExtension)
#pragma alloc_text (PAGE, NICAllocateDeviceResources)
#pragma alloc_text (PAGE, NICMapHWResources)
#pragma alloc_text (PAGE, NICUnmapHWResources)
#pragma alloc_text (PAGE, NICGetDeviceInformation)
#pragma alloc_text (PAGE, NICReadAdapterInfo)
#pragma alloc_text (PAGE, NICAllocAdapterMemory)
#pragma alloc_text (PAGE, NICFreeAdapterMemory)
#pragma alloc_text (PAGE, NICInitRecv)
#pragma alloc_text (PAGE, NICSelfTest)
#pragma alloc_text (PAGE, NICInitializeAdapter)
#pragma alloc_text (PAGE, HwConfigure)
#pragma alloc_text (PAGE, HwClearAllCounters)
#pragma alloc_text (PAGE, HwSetupIAAddress)
#pragma alloc_text (PAGE, GetPCIBusInterfaceStandard)
#pragma alloc_text (PAGE, NICAllocRfd)
#pragma alloc_text (PAGE, NICFreeRfd)
#pragma alloc_text (PAGE, NICAllocRfdWorkItem)
#pragma alloc_text (PAGE, NICFreeRfdWorkItem)
#endif


NTSTATUS
NICInitializeDeviceExtension(
    IN OUT PFDO_DATA FdoData
    )
/*++
Routine Description:

    
Arguments:

    FdoData     Pointer to our FdoData

Return Value:

     None

--*/
{
    NTSTATUS status;

    //
    // Get the BUS_INTERFACE_STANDARD for our device so that we can
    // read & write to PCI config space at IRQL <= DISPATCH_LEVEL.
    //
    status = GetPCIBusInterfaceStandard(FdoData->Self, 
                                        &FdoData->BusInterface);
    if (!NT_SUCCESS (status)){
        return status;    
    }
    
    NICGetDeviceInfSettings(FdoData);
    
    FdoData->ConservationIdleTime = -SECOND_TO_100NS * PCIDRV_DEF_IDLE_TIME;
    FdoData->PerformanceIdleTime = -SECOND_TO_100NS * PCIDRV_DEF_IDLE_TIME;
    
    //
    // Initialize list heads, spinlocks, timers etc.
    //
    InitializeListHead(&FdoData->SendQueueHead);

    InitializeListHead(&FdoData->RecvList);
    InitializeListHead(&FdoData->RecvQueueHead);
    InitializeListHead(&FdoData->PoMgmt.PatternList);

    KeInitializeSpinLock(&FdoData->Lock);
    KeInitializeSpinLock(&FdoData->SendLock);
    KeInitializeSpinLock(&FdoData->RcvLock);    
    KeInitializeSpinLock(&FdoData->RecvQueueLock); 

    //
    // To minimize init-time, queue a DPC to do link detection.
    // This DPC will also be used to check of hardware hang.
    //
    KeInitializeDpc(&FdoData->WatchDogTimerDpc, // Dpc
                                NICWatchDogTimerDpc, // DeferredRoutine
                                FdoData           // DeferredContext
                                ); 

    KeInitializeTimer(&FdoData->WatchDogTimer );
    
    //
    // Event used to make sure the NICWatchDogTimerDpc has completed execution
    // before freeing the resources and unloading the driver.
    //
    KeInitializeEvent(&FdoData->WatchDogTimerEvent, NotificationEvent, TRUE);

    return status;
    
}


NTSTATUS
NICAllocateDeviceResources(
    IN OUT  PFDO_DATA   FdoData,
    IN      PIRP        Irp
    )
/*++
Routine Description:

    Allocates all the hw and software resources required for
    the device, enables interrupt, and initializes the device.

Arguments:

    FdoData     Pointer to our FdoData
    Irp         Pointer to start-device irp.

Return Value:

     None

--*/
{
    NTSTATUS        status;
    LARGE_INTEGER   DueTime;

    do{

        //
        // First make sure this is our device before doing whole lot
        // of other things.
        //
        status = NICGetDeviceInformation(FdoData);
        if (!NT_SUCCESS (status)){
            return status;
        }
        
        status = NICMapHWResources(FdoData, Irp);
        if (!NT_SUCCESS (status)){
            DebugPrint(ERROR, DBG_INIT,"NICMapHWResources failed: 0x%x\n",
                                    status);
            break;
        }       
        
        //
        // Read additional info from NIC such as MAC address
        //
        status = NICReadAdapterInfo(FdoData);
        if (status != STATUS_SUCCESS)
        {
            break;
        }


        status = NICAllocAdapterMemory(FdoData);
        if (status != STATUS_SUCCESS)
        {
            break;
        }    

        NICInitSend(FdoData);
        
        status = NICInitRecv(FdoData);
        if (status != STATUS_SUCCESS)
        {
            break;
        }    

        //
        // Test our adapter hardware
        //
        status = NICSelfTest(FdoData);
        if (status != STATUS_SUCCESS)
        {
            break;
        }    

        status = NICInitializeAdapter(FdoData);
        if (status != STATUS_SUCCESS)
        {
            break;
        }    

        //
        // Enable the interrupt
        //
        NICEnableInterrupt(FdoData);
                 
        //
        // Set the link detection flag to indicate that NICWatchDogTimerDpc
        // will be first doing link-detection.
        //
        MP_SET_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION);
        FdoData->CheckForHang = FALSE;
        FdoData->bLinkDetectionWait = FALSE;
        FdoData->bLookForLink = FALSE;   
        
        //
        // This event stays cleared until the NICWatchDogTimerDpc exits. 
        //
        KeClearEvent(&FdoData->WatchDogTimerEvent);

        //
        // Watch dog timer is used to do the initial link detection during
        // start and then used to make sure the device is not hung for 
        // any reason.
        //
        DueTime.QuadPart = NIC_LINK_DETECTION_DELAY;
        KeSetTimer( &FdoData->WatchDogTimer,   // Timer
                            DueTime,         // DueTime
                            &FdoData->WatchDogTimerDpc      // Dpc  
                            );                
    }while(FALSE);        

    return status;
    
}


NTSTATUS
NICFreeDeviceResources(
    IN OUT PFDO_DATA FdoData
    )
/*++
Routine Description:

    Free all the software resources. We shouldn't touch the hardware.

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

     None

--*/
{
    NTSTATUS    status;
    KIRQL       oldIrql;
    
    DebugPrint(INFO, DBG_INIT, "-->NICFreeDeviceResources\n");
            
    if(!KeCancelTimer(&FdoData->WatchDogTimer)){
        //
        // Wait for the timer to complete since it has already begun executing.
        //
        DebugPrint(INFO, DBG_INIT, 
                            "Waiting for the watchdogtimer to exit..\n");
        
        status = KeWaitForSingleObject( &FdoData->WatchDogTimerEvent,
                               Executive,
                               KernelMode,
                               FALSE,
                               NULL );
        ASSERT(NT_SUCCESS(status));
    }
       
    //
    // We need to raise the IRQL before acquiring the lock
    // because the functions called inside the guarded
    // region assume that they are called at Dpc level and release
    // and reacquire the lock using DpcLevel spinlock functions.
    //
    KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
    KeAcquireSpinLockAtDpcLevel(&FdoData->SendLock);

    //
    // Free the packets on SendWaitList                                                           
    //
    NICFreeQueuedSendPackets(FdoData);

    //
    // Free the packets being actively sent & stopped
    //
    NICFreeBusySendPackets(FdoData);
    
    KeReleaseSpinLockFromDpcLevel(&FdoData->SendLock);
    KeLowerIrql(oldIrql);

    
    NICFreeAdapterMemory(FdoData);

    //
    // Disconnect from the interrupt and unmap any I/O ports
    //
    NICUnmapHWResources(FdoData);

    DebugPrint(INFO, DBG_INIT, "<--NICFreeDeviceResources\n");
    
    return STATUS_SUCCESS;
    
}

NTSTATUS
NICMapHWResources(
    IN OUT PFDO_DATA FdoData,
    IN PIRP Irp
    )
/*++
Routine Description:

    Gets the HW resources assigned by the bus driver from the start-irp
    and maps it to system address space. Initializes the DMA adapter
    and sets up the ISR.

    Three base address registers are supported by the 8255x:
    1) CSR Memory Mapped Base Address Register (BAR 0 at offset 10)
    2) CSR I/O Mapped Base Address Register (BAR 1 at offset 14)
    3) Flash Memory Mapped Base Address Register (BAR 2 at offset 18)
    
    The 8255x requires one BAR for I/O mapping and one BAR for memory 
    mapping of these registers anywhere within the 32-bit memory address space.
    The driver determines which BAR (I/O or Memory) is used to access the 
    Control/Status Registers. 

    Just for illustration, this driver maps both memory and I/O registers and
    shows how to use READ_PORT_xxx or READ_REGISTER_xxx functions to perform 
    I/O in a platform independent basis. On some platforms, the I/O registers
    can get mapped in to memory space and your driver should be able to handle
    this transparently.
    
    One BAR is also required to map the accesses to an optional Flash memory. 
    The 82557 implements this register regardless of the presence or absence 
    of a Flash chip on the adapter. The 82558 and 82559 only implement this 
    register if a bit is set in the EEPROM. The size of the space requested 
    by this register is 1Mbyte, and it is always mapped anywhere in the 32-bit
    memory address space. 
    Note: Although the 82558 only supports up to 64 Kbytes of Flash memory 
    and the 82559 only supports 128 Kbytes of Flash memory, 1 Mbyte of
    address space is still requested. Software should not access Flash 
    addresses above 64 Kbytes for the 82558 or 128 Kbytes for the 82559 
    because Flash accesses above the limits are aliased to lower addresses.    
    
Arguments:

    FdoData     Pointer to our FdoData
    Irp         Pointer to start-device irp.

Return Value:

     None

--*/
{
    PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceTrans;
    PCM_PARTIAL_RESOURCE_LIST       partialResourceListTranslated;
    PIO_STACK_LOCATION              stack;
    ULONG                           i;
    NTSTATUS                        status = STATUS_SUCCESS;
    DEVICE_DESCRIPTION              deviceDescription;    
    ULONG                           MaximumPhysicalMapping;
    PDMA_ADAPTER                    DmaAdapterObject;
    ULONG                           maxMapRegistersRequired, miniMapRegisters;
    ULONG                           MapRegisters;
    BOOLEAN bResPort = FALSE, bResInterrupt = FALSE, bResMemory = FALSE;
    ULONG                           numberOfBARs = 0;
#if defined(DMA_VER2) // To avoid  unreferenced local variables error
    ULONG                           SGMapRegsisters;
    ULONG                           ScatterGatherListSize;        
#endif

    stack = IoGetCurrentIrpStackLocation (Irp);

    PAGED_CODE();

    if (NULL == stack->Parameters.StartDevice.AllocatedResourcesTranslated) {
        status = STATUS_DEVICE_CONFIGURATION_ERROR;
        goto End;
    }
    
    //
    // Parameters.StartDevice.AllocatedResourcesTranslated points
    // to a CM_RESOURCE_LIST describing the hardware resources that
    // the PnP Manager assigned to the device. This list contains
    // the resources in translated form. Use the translated resources
    // to connect the interrupt vector, map I/O space, and map memory.
    //

    partialResourceListTranslated = &stack->Parameters.StartDevice.\
                      AllocatedResourcesTranslated->List[0].PartialResourceList;

    resourceTrans = &partialResourceListTranslated->PartialDescriptors[0];

    for (i = 0;
         i < partialResourceListTranslated->Count;
         i++, resourceTrans++) {

        switch (resourceTrans->Type) {
            
        case CmResourceTypePort:
            //
            // We will increment the BAR count only for valid resources. We will
            // not count the private device types added by the PCI bus driver.
            //
            numberOfBARs++;
            

⌨️ 快捷键说明

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