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

📄 resource.c

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

        case CmResourceTypeMemory:

            //
            // Verify that we haven't exceeded the maximum resources for a 
            // PCI device.
            //

            if (rangeCount < PCI_TYPE0_ADDRESSES) {

                DebugPrint((3,
                            "  Memory range:  Base = %08x : %08x   Length = %08x \n",
                            partialData->u.Port.Start.HighPart,
                            partialData->u.Port.Start.LowPart,
                            partialData->u.Port.Length
                            ));
                
                //
                // This driver will only look at read/write memory.
                //
                
                if (CM_RESOURCE_MEMORY_READ_WRITE == partialData->Flags) {
                    
                    //
                    // Save memory resource information.
                    //
    
                    baseAddress->RangeStart = partialData->u.Port.Start;
                    baseAddress->RangeLength = partialData->u.Port.Length;
                    baseAddress->RangeInMemory = TRUE;
                    baseAddress->ResourceMapped = FALSE;
    
                    //
                    // Bump up the count of memory and I/O resources.
                    //
    
                    rangeCount++;
                
                    //
                    // Point to the next base address storage area.
                    //
    
                    baseAddress++;
                
                } else {

                    DebugPrint((3,
                                "  ** Ignoring memory: flags = %08x \n",
                                partialData->Flags
                                ));
                }

            }

            break;

        case CmResourceTypeDma:

            //
            // Don't do anything with DMA type resources.  This doesn't
            // really make sense for a PCI busmaster device.
            //
            
            DebugPrint((3, "CmResourceTypeDma not supported \n"));

            break;
        
        default:
        
            //
            // Skip unknown resource types.
            //
            
            DebugPrint((3, "Unknown resource type \n"));
            
            break;
        
        }   // switch
        

    }

    //
    // Save the count of the number of resources found.
    //

    DeviceExtension->AddressCount = rangeCount;

}   // ParseResourceList


VOID
ReleaseDeviceAddresses(
    IN PBASE_ADDRESS BaseAddress,
    IN ULONG AddressCount
    )
/*++

Routine Description:

    Unmap any physical addresses previously mapped.

Arguments:

    BaseAddress - Array holding information about I/O and memory resources.

    AddressCount - Indicates the total number of I/O and memory resources
                   available for this adapter.

Return Value:

    None.

--*/
{
    ULONG   i;

    //
    // Loop through each of the raw I/O ports and memory ranges.
    //

    for (i = 0; i < AddressCount; i++, BaseAddress++) {

        if (BaseAddress->ResourceMapped) {

            MmUnmapIoSpace(BaseAddress->MappedRangeStart,
                           BaseAddress->RangeLength
                           );
        }

    }

}   // ReleaseDeviceAddresses



BOOLEAN
SetBaseAddress(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

    Choose one of the address spaces to be the base address for the device.
    All device accesses will be an offset from this base address.
    
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:

    TRUE
    
--*/
{
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    PBASE_ADDRESS   baseAddress = deviceExtension->BaseAddress;

    ULONG   i;

    BOOLEAN     status = FALSE;

///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- START
//
///////////////////////////////////////////////////////////////
#ifdef VENDORID_1000_DEVICEID_0004
    
    //
    // For this sample, simply pick the first memory or I/O range and use 
    // this as the device base.
    //

    // Note that if this sample is changed to use I/O ports rather than 
    // memory mapped registers, all the APIs to access the adapter registers 
    // must also be changed.
    //

    for (i = 0; i < deviceExtension->AddressCount; i++ ) {

#ifdef USE_MEMORY_MAPPED_REGISTERS
        if (baseAddress->MappedRangeInMemory) {
#else
        if (!baseAddress->MappedRangeInMemory) {
#endif
            deviceExtension->RegisterBase = baseAddress->MappedRangeStart;

            status = TRUE;

            DebugPrint((3, 
                        "RegisterBase %x  \n",
                        deviceExtension->RegisterBase
                        ));
                        
            break;
        }

        baseAddress++;
    }

    //
    // If unable to set base address, free resources and return.
    //
    
    if (FALSE == status) {
        
        FreeDeviceResources(DriverObject,
                            DeviceObject
                            );                          
    }
    
#endif
///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- END 
//
///////////////////////////////////////////////////////////////
    
    return status;


}   // SetBaseAddress

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

Routine Description:

    Initialize the DPC and ISR.  Allocate any storage needed by the DPC
    routine to maintain context.
                                                                     
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;

    ULONG               vector;

    KIRQL               irql;
    KAFFINITY           affinity;

    //
    // Register the DPC routine.
    //

    IoInitializeDpcRequest(DeviceObject,
                           PciDmaDpc
                           );

    //
    // Allocate storage for the DPC context if needed.  This sample
    // allocates storage, but does not use anything for the DPC.  This code
    // can be removed in a real driver if the DPC context is unused.  If 
    // removed here, remove the corresponding code from FreeDeviceResources().
    //

    deviceExtension->DpcContext = ExAllocatePoolWithTag(NonPagedPool,
                                                        sizeof(DPC_CONTEXT),
                                                        EX_POOL_TAG_VALUE
                                                        );

    if (!deviceExtension->DpcContext) {

        DebugPrint((1, "Unable to allocate DpcContext \n"));

        FreeDeviceResources(DriverObject,
                            DeviceObject
                            );

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // Set up the device interrupt.  Need to set up the interrupt after 
    // setting up the memory and I/O resources in case the card suddenly 
    // generates an interrupt and the driver's ISR is called.  If this 
    // happens, the device registers will be properly mapped so we can 
    // safely clear the interrupt.
    //

    if (deviceExtension->InterruptLevel || deviceExtension->InterruptVector) {

        vector = HalGetInterruptVector(deviceExtension->InterfaceType,
                                       deviceExtension->BusNumber,
                                       deviceExtension->InterruptLevel,
                                       deviceExtension->InterruptVector,
                                       &irql,
                                       &affinity
                                       );


        status = IoConnectInterrupt(&deviceExtension->InterruptObject,
                                    (PKSERVICE_ROUTINE)PciDmaISR,
                                    DeviceObject,                       // Context passed to ISR
                                    NULL,                               // Single vector supported
                                    vector,
                                    irql,
                                    irql,                               // Synchronization IRQL
                                    deviceExtension->InterruptMode,
                                    TRUE,                               // Shareable interrupts
                                    affinity,
                                    FALSE                               // Don't save FP stack
                                    );

        if (!NT_SUCCESS(status)) {

            DebugPrint((1, "Unable to connect interrupt. Status = %x \n",
                        status
                        ));

            deviceExtension->InterruptObject = NULL;

            FreeDeviceResources(DriverObject,
                                DeviceObject
                                );

            return status;
        }

        DebugPrint((2, "Interrupt connected \n"));
    }

    return STATUS_SUCCESS;
    
}   // SetupIsrAndDpc


NTSTATUS
SetupPciDevice(
    IN PDRIVER_OBJECT       DriverObject,
    IN PUNICODE_STRING      RegistryPath,
    IN ULONG                BusNumber,
    IN ULONG                SlotNumber,
    IN USHORT               DeviceNumber
    )
/*++

Routine Description:

    Sets up a PCI device for use.  Creates a device object, claims the 
    resources, maps the I/O and memory ranges, prepares the interrupt, and 
    stores any adapter-specific information in the adapter's device extension.

Arguments:

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

    RegistryPath - Pointer to the registry path for this driver object.

    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.
    
Return Value:

    NTSTATUS

--*/
{
    PDEVICE_EXTENSION       deviceExtension = NULL;
    PDEVICE_OBJECT          deviceObject = NULL;

    NTSTATUS                status;

    DebugPrint((3, "SetupPciDevice \n"));

    //
    // Create device object and fill in device extension.
    //

    status = CreateDeviceObject(DriverObject,
                                RegistryPath,
                                BusNumber,
                                SlotNumber,
                                DeviceNumber,
                                &deviceObject
                                );
    
    if (!NT_SUCCESS(status) || !(deviceObject)) {
    
        return status;
    }

    //
    // Get the device extension from the newly created device object.
    //
    
    deviceExtension = deviceObject->DeviceExtension;
    
    ASSERT(deviceExtension != NULL);
                                                        
    //
    // Get the PCI device resources.
    //
    
    status = GetPciResources(DriverObject,
                             deviceObject,
                             RegistryPath
                             );

    if (!NT_SUCCESS(status)) {
        
        return status;
    }
    
    //
    // Get the adapter object and setup DMA information.
    //
    
    status = GetAdapterInfo(DriverObject,
                            deviceObject
                            );
                            
    if (!NT_SUCCESS(status)) {
        
        return status;
    }
                                  
    //
    // Map the memory and/or I/O spaces.
    //

    if (!GetDeviceAddresses(deviceExtension->BaseAddress,
                            deviceExtension->AddressCount,
                            deviceExtension->InterfaceType,
                            deviceExtension->BusNumber
                            )) {

        DebugPrint((1, "Unable to map memory and I/O resources \n"));

        FreeDeviceResources(DriverObject,
                            deviceObject
                            );

        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    //
    // Set the base registers for the chip, usually either I/O or memory 
    // mapped, not both.  Note that there are different APIs for I/O versus 
    // memory access, so if the base registers are changed from I/O to memory
    // mapped, the corresponding access API must also be changed.
    //

    if (!SetBaseAddress(DriverObject, deviceObject)) {

        DebugPrint((1, "Unable to set base address register \n"));

        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    status = SetupIsrAndDpc(DriverObject,
                            deviceObject
                            );
    
    if (!NT_SUCCESS(status)) {
        
        return status;
    }

    //
    // If we're all the way to the end of this routine, we've successfully
    // configured one PCI device.  Indicate this fact.
    //

    InterlockedIncrement(&deviceExtension->DeviceConfigured);
    
    DebugPrint((1, "Device #%d created and configured \n", DeviceNumber));

///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- START 
//
///////////////////////////////////////////////////////////////
#ifdef VENDORID_1000_DEVICEID_0004

    //
    // Vendor may have to program the device to prepare it for I/O requests.
    //
    
    KeSynchronizeExecution(deviceExtension->InterruptObject,
                           InitializePciHw,
                           deviceExtension
                           );

#endif    
///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- END 
//
///////////////////////////////////////////////////////////////

    return STATUS_SUCCESS;

}   // SetupPciDevice



⌨️ 快捷键说明

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