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

📄 resource.c

📁 dma驱动开发程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 1997-1998  Microsoft Corporation

Module Name:

    resource.c

Abstract:

    This file contains routines that will initialize and configure a PCI 
    device, including getting the PCI resources, parsing the PCI resources,
    mapping memory and I/O spaces, connecting interrupts, initializing DPC 
    routines, and various memory allocations.

Author:

    Steve Dziok (SteveDz)

Environment:

    Kernel mode

Revision History:


--*/


#include <stdio.h>      // Needed for sprintf() routine.
#include "pcidma.h"

//
// Make sure the initialization code is removed from memory after use.
//


#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, CreateDeviceObject)
#pragma alloc_text(INIT, GetAdapterInfo)
#pragma alloc_text(INIT, GetDeviceAddresses)
#pragma alloc_text(INIT, GetPciResources)
#pragma alloc_text(INIT, ParseResourceList)
#pragma alloc_text(INIT, SetBaseAddress)
#pragma alloc_text(INIT, SetupIsrAndDpc)
#pragma alloc_text(INIT, SetupPciDevice)
#endif



NTSTATUS
CreateDeviceObject(
    IN PDRIVER_OBJECT       DriverObject,
    IN PUNICODE_STRING      RegistryPath,
    IN ULONG                BusNumber,
    IN ULONG                SlotNumber,
    IN USHORT               DeviceNumber,
    OUT PDEVICE_OBJECT      *NewDeviceObject
    )
/*++

Routine Description:


Arguments:

    DriverObject - Pointer to the driver object created by the I/O manager.

    RegistryPath - Pointer to the driver specific key 
                   \Registry
                      \Machine
                         \System
                            \CurrentControlSet
                               \Services
                                  \<DriverName>
    
    BusNumber - Zero-based system bus number for the PCI device.
    
    SlotNumber - Logical slot number indicating the location of the PCI
                 device.  See the PCI_SLOT_NUMBER for a description of 
                 this value.
    
    DeviceNumber - Zero-based device number.  Used to create unique device
                   names.
    
    DeviceObject - Pointer to the device object created by this routine if
                   successful.

Return Value:

    NTSTATUS

--*/
{
    PDEVICE_OBJECT          deviceObject;
    PDEVICE_EXTENSION       deviceExtension;
    
    NTSTATUS                status;

    UCHAR                   ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
    UCHAR                   win32NameBuffer[MAXIMUM_FILENAME_LENGTH];
    
    ANSI_STRING             ntNameString;
    ANSI_STRING             win32NameString;
    
    PUNICODE_STRING         originalPath;
    UNICODE_STRING          ntUnicodeString;

    //
    // Create device object name for this device.
    //

    //
    // Indicate we don't yet have a device object.
    //
    
    *NewDeviceObject = NULL;

    sprintf(ntNameBuffer,
            "\\Device\\"DRIVER_NAME"%d", 
            DeviceNumber
            );

    RtlInitAnsiString(&ntNameString,
                      ntNameBuffer
                      );

    DebugPrint((2, "Creating device object %s \n", ntNameBuffer));

    //
    // Allocate buffer for Unicode string and convert ANSI string to Unicode.
    //

    status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
                                          &ntNameString,
                                          TRUE
                                          );

    if (!NT_SUCCESS(status)) {

        DebugPrint((1, "Unable to convert ANSI string to UNICODE \n"));

        return status;
    }

    //
    // Create the device object.
    //

    status = IoCreateDevice(DriverObject,
                            sizeof(DEVICE_EXTENSION),
                            &ntUnicodeString,
                            FILE_DEVICE_UNKNOWN,
                            0,                      // No device-specific info
                            FALSE,                  // Not an exclusive device
                            &deviceObject
                            );

    //
    // Check whether IoCreateDevice was successful.
    //

    if (!NT_SUCCESS(status)) {

        DebugPrint((1, "Unable to create device object. \n"));

        RtlFreeUnicodeString(&ntUnicodeString);

        return status;
    }

    DebugPrint((3, "Device object 0x%x \n", deviceObject));
    
    //
    // Indicate that IRPs should include MDLs for data transfers.
    //

    deviceObject->Flags |= DO_DIRECT_IO;

    //
    // Set up the device extension.
    //

    deviceExtension = deviceObject->DeviceExtension;
    RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));

    deviceExtension->DeviceObject = deviceObject;

    deviceExtension->BusNumber = BusNumber;
    deviceExtension->SlotNumber = SlotNumber;

    deviceExtension->ScatterGather = SCATTER_GATHER_SUPPORT;
    deviceExtension->InterfaceType = PCIBus;
    deviceExtension->MaximumTransferLength = MAXIMUM_TRANSFER_LENGTH;
    
    //
    // Set the maximum physical pages for now, but this value may change if
    // the call to HalGetAdapter returns less pages.
    //
    
    deviceExtension->MaximumPhysicalPages = MAXIMUM_PHYSICAL_PAGES;

    //
    // Save a copy of the registry path for clean up purposes.
    //

    originalPath = &deviceExtension->RegistryPath;

    RtlInitUnicodeString(originalPath,
                         NULL
                         );

    originalPath->MaximumLength = RegistryPath->MaximumLength;
    originalPath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
                                                 originalPath->MaximumLength,
                                                 EX_POOL_TAG_VALUE
                                                 );

    //
    // If the buffer to create the registry path copy could not be created,
    // cleanup and exit.
    //
    
    if (!originalPath->Buffer) {

        DebugPrint((1, "Unable to create new registry path \n"));

        FreeDeviceResources(DriverObject,
                            deviceObject
                            );

        RtlFreeUnicodeString(&ntUnicodeString);

        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    RtlCopyUnicodeString(originalPath,
                         RegistryPath
                         );

    //
    // Create a symbolic link so a Win32 application can communicate with
    // this driver.
    //

    sprintf(win32NameBuffer,
            "\\DosDevices\\"DRIVER_NAME"%d",   
            DeviceNumber
            );

    RtlInitAnsiString(&win32NameString,
                      win32NameBuffer
                      );

    DebugPrint((2, "Creating symbolic link %s \n", win32NameBuffer));

    //
    // Allocate buffer for Unicode string and convert ANSI string to Unicode.
    //

    status = RtlAnsiStringToUnicodeString(&deviceExtension->Win32UnicodeString,
                                          &win32NameString,
                                          TRUE
                                          );

    //
    // If we are unable to create the Win32 name, we will continue to set up
    // the driver.  If the driver needs to have the symbolic link, then the
    // code can be changed to cleanup and exit.
    //

    if (NT_SUCCESS(status)) {

        //
        // Connect the symbolic link.
        //

        status = IoCreateSymbolicLink(&deviceExtension->Win32UnicodeString,
                                      &ntUnicodeString
                                      );

        if (!NT_SUCCESS(status)) {

            DebugPrint((1, "Unable to create symbolic link.  Status = %x \n",
                        status
                        ));

            //
            // On error, free the DosDevice name Unicode buffer.
            //

            RtlFreeUnicodeString(&deviceExtension->Win32UnicodeString);
            
            //
            // Don't leave this pointer once the buffer has been freed.
            //
            
            RtlInitUnicodeString(&deviceExtension->Win32UnicodeString,
                                 NULL
                                 );

        } else {

            deviceExtension->SymbolicLinkCreated = TRUE;

        }
    
        //
        // Note that we fall through and continue even if the symbolic
        // link failed.
        //
    }

    //
    // Release the NT device name Unicode buffer.
    //

    RtlFreeUnicodeString(&ntUnicodeString);
    
    //
    // Return the newly created device object.
    //
    
    *NewDeviceObject = deviceObject;
    
    return status;

}   // CreateDeviceObject


VOID
FreeDeviceResources(
    PDRIVER_OBJECT DriverObject,
    PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

    Free all system objects and resources used by the specified device object.
    Delete the device object after everything is freed.

Arguments:

    DriverObject - Pointer to the driver object created by the I/O manager.

    DeviceObject - Pointer to the device object for a specific adapter.

Return Value:

    None

--*/
{
    PCM_RESOURCE_LIST   resourceList;
    PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;

    //
    // If no device extension, something bad happened.  Just return.
    //
    
    if (!deviceExtension) {

        DebugPrint((1, "FreeDeviceResources invalid DeviceExtension \n"));
        DebugPrint((1, "  *** WARNING: Unable to free resources *** \n"));

        ASSERT(0);

        return;
    }

    //
    // If necessary, stop the PCI device from running before doing any
    // cleanup.  This may require stopping or resetting the PCI device.
    //
    
    //
    // Indicate that the device should not be interrupting anymore.
    //
    
    InterlockedExchange(&deviceExtension->DeviceConfigured,
                        (LONG)0
                        );
    
    //
    // Disconnect any interrupts.  This should be done first to insure that 
    // an interrupt doesn't occur and call into the driver's ISR.
    //

    if (deviceExtension->InterruptObject) {

        IoDisconnectInterrupt(deviceExtension->InterruptObject);
    }

    //
    // Delete the symbolic link.
    //

    if (deviceExtension->SymbolicLinkCreated) {

        IoDeleteSymbolicLink(&deviceExtension->Win32UnicodeString);

        //
        // Free the Win32 Unicode buffer.
        //

        RtlFreeUnicodeString(&deviceExtension->Win32UnicodeString);
    }

    //
    // Free any storage allocated.
    //

    if (deviceExtension->DpcContext) {

        ExFreePool(deviceExtension->DpcContext);
    }

    if (deviceExtension->SGList) {
        
        HalFreeCommonBuffer(deviceExtension->AdapterObject,
                            deviceExtension->SGListLength,
                            deviceExtension->SGListPA,
                            deviceExtension->SGList,
                            deviceExtension->SGListCached
                            );
                            
    }
    
    //
    // Unmap any memory or I/O resources.
    //

    ReleaseDeviceAddresses(deviceExtension->BaseAddress,
                           deviceExtension->AddressCount
                           );

    //
    // Free any resources claimed in the registry.
    //

    if (deviceExtension->RegistryPath.Buffer &&
        deviceExtension->RegistryPath.Length) {

        IoAssignResources(&deviceExtension->RegistryPath,
                          &deviceExtension->ClassUnicodeString,
                          DriverObject,
                          DeviceObject,
                          NULL,
                          &resourceList
                          );

        //
        // Free the registry path buffer.
        //

        ExFreePool(deviceExtension->RegistryPath.Buffer);
    }

    //
    // Free the DriverClassName Unicode buffer.
    //

    if (deviceExtension->ClassUnicodeString.Length) {
        
        RtlFreeUnicodeString(&deviceExtension->ClassUnicodeString);
    }

    //
    // Finally, delete the device object.
    //

    IoDeleteDevice(DeviceObject);

}   // FreeDeviceResources


NTSTATUS
GetAdapterInfo(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

    Get the adapter object required for busmaster DMA.  Allocate a structure
    for holding the scatter/gather lists.

Arguments:

    DriverObject - Pointer to the driver object created by the I/O manager.

    DeviceObject - Pointer to the device object for a specific adapter.

Return Value:

    NTSTATUS

--*/
{
    PDEVICE_EXTENSION       deviceExtension = DeviceObject->DeviceExtension;
    
    NTSTATUS                status;
    
    DEVICE_DESCRIPTION      deviceDescription;

    ULONG                   numberOfMapRegisters;
    
    //
    // Set up the adapter-specific information.
    //

    deviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
    deviceDescription.Master = TRUE;
    deviceDescription.ScatterGather = deviceExtension->ScatterGather;
    deviceDescription.BusNumber = deviceExtension->BusNumber;
    deviceDescription.InterfaceType = deviceExtension->InterfaceType;
    deviceDescription.MaximumLength = deviceExtension->MaximumTransferLength;

    //
    // The following adapter-specific information is not required.
    //

    //        deviceDescription.DemandMode = FALSE;
    //        deviceDescription.AutoInitialize = FALSE; 
    //        deviceDescription.Dma32BitAddresses = FALSE;
    //        deviceDescription.IgnoreCount = xxx;

⌨️ 快捷键说明

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