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

📄 resource.c

📁 dma驱动开发程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    //        deviceDescription.DmaChannel = xxx;
    //        deviceDescription.DmaWidth = xxx;
    //        deviceDescription.DmaSpeed = xxx;
    //        deviceDescription.DmaPort = xxx;

    //
    // Get the adapter object.
    //

    deviceExtension->AdapterObject = HalGetAdapter(&deviceDescription,
                                                   &numberOfMapRegisters
                                                   );
    //
    // If we can't get the adapter object, clean up and exit.
    //

    if (deviceExtension->AdapterObject == NULL) {

        DebugPrint((1, "HalGetAdapter failed\n"));

        FreeDeviceResources(DriverObject,
                            DeviceObject
                            );

        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    //
    // The number of map registers will limit the number of physical pages 
    // the driver can support (i.e. how fragmented the user buffer can be).  
    // If we get less map registers than physical breaks we support, lower 
    // the maximum physical breaks value.
    //

    if (numberOfMapRegisters < deviceExtension->MaximumPhysicalPages) {
        deviceExtension->MaximumPhysicalPages = numberOfMapRegisters;
    }

    DebugPrint((2,
                "MaxTransferLength = 0x%08x   MaxPhysicalPages = 0x%x \n",
                deviceExtension->MaximumTransferLength,
                deviceExtension->MaximumPhysicalPages
                ));

                                  
    //
    // Allocate storage for the scatter/gather list.  Some adapters can DMA 
    // directly from this SG list, so this driver will allocate a buffer 
    // using HalAllocateCommonBuffer.  If this requirement is not needed, 
    // one can use ExAllocatePool (NonPaged of course).
    //
    
    // 
    // Since this sample only supports one I/O on the device at a time, the 
    // SG list is stored in the device extension.  If multiple I/O's are to
    // be supported, there would have to be a SG list for each outstanding
    // I/O and they would have to be stored and accessed differently.
    //

    deviceExtension->SGListLength = deviceExtension->MaximumPhysicalPages *
                                    sizeof(SG_ENTRY);

    deviceExtension->SGListCached = FALSE;
        
    deviceExtension->SGList = HalAllocateCommonBuffer(deviceExtension->AdapterObject,    
                                                      deviceExtension->SGListLength,
                                                      &deviceExtension->SGListPA,
                                                      deviceExtension->SGListCached
                                                      );
    
    //
    // Unable to get the SG list, cleanup and exit.
    //
    
    if (!deviceExtension->SGList) {
        
        DebugPrint((1, "HalAllocateCommonBuffer failed \n"));
        
        FreeDeviceResources(DriverObject,
                            DeviceObject
                            );
                            
        return STATUS_INSUFFICIENT_RESOURCES;                            
    }

    //
    // Indicate that the busmaster DMA information is ready to go.
    //
    
    return STATUS_SUCCESS;
                                 
}   // GetAdapterInfo

    
BOOLEAN
GetDeviceAddresses(
    IN PBASE_ADDRESS BaseAddress,
    IN ULONG AddressCount,
    IN INTERFACE_TYPE InterfaceType,
    IN ULONG BusNumber
    )
/*++

Routine Description:

    Translates a bus-specific address into the corresponding system logical
    address. Also, this will map a physical range to nonpaged system space if
    required.

    Most PCI devices respond to either an I/O range or a memory range, but 
    not both.  For simplicity, this function simply maps all the resources
    for a given PCI device.  In reality, only one of the ranges might be 
    used, so some cleanup may be needed here.

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.

    InterfaceType - Indicates the bus type for this adapter (PCI, ISA, EISA,
                    etc.).

    BusNumber - Zero-based system bus number for the PCI device.

Return Value:

    TRUE - At least one I/O or memory space has been translated and/or mapped.

    FALSE - No I/O or memory spaces successfully translated or mapped.

--*/
{
    ULONG               i;
    ULONG               addressSpace;

    PHYSICAL_ADDRESS    cardAddress;

    BOOLEAN             mappedOne = FALSE;

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

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

        //
        // Translate the bus-specific address to a system logical address.
        //

        addressSpace = !BaseAddress->RangeInMemory;
        cardAddress = BaseAddress->RangeStart;

        if (!HalTranslateBusAddress(InterfaceType,
                                    BusNumber,
                                    BaseAddress->RangeStart,
                                    &addressSpace,
                                    &cardAddress
                                    )) {

            DebugPrint((2,
                        "HalTranslateBusAddress failed for 0x%x \n",
                        BaseAddress->RangeStart
                        ));

            continue;

        }

        //
        // Indicate that we mapped at least one range.
        //

        mappedOne = TRUE;

        //
        // Save the (possibly changed) I/O-memory indicator.  Remember that 
        // zero indicates a memory address, and one indicates I/O space.  On
        // some RISC systems, there is no I/O space.  So an AddressSpace
        // indicating I/O space input to HalTranslateBusAddress may be 
        // changed to memory space on return.
        //

        BaseAddress->MappedRangeInMemory = (BOOLEAN)(addressSpace ? 0 : 1);

        //
        // Map the device base address into the virtual address space if the
        // address is in memory space.  Note that HalTranslateBusAddress may
        // have changed the address space indicator on return.
        //

        if (!addressSpace) {

            BaseAddress->MappedRangeStart = MmMapIoSpace(cardAddress,
                                                         BaseAddress->RangeLength,
                                                         FALSE
                                                         );

            //
            // Make sure we unmap this resource.
            //

            BaseAddress->ResourceMapped = TRUE;

        } else {

            BaseAddress->MappedRangeStart = (PVOID)cardAddress.LowPart;
        }

    }
    
    //
    // Indicate whether any address spaces were mapped.
    //
    
    return mappedOne;

}   // GetDeviceAddresses


NTSTATUS
GetPciResources(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT DeviceObject,
    IN PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    Retrieve the PCI resources from the HAL, parse the resource list, and
    save the information in a driver-specific structure.

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;
    PCM_RESOURCE_LIST   resourceList;
    
    NTSTATUS    status;
    
    ANSI_STRING classNameString;

    //
    // Set up a driver class name to put all the resources under.  If we are
    // unable to create a valid driver class name, we can assign the 
    // resources under the generic "Other" registry key.
    //

    RtlInitAnsiString(&classNameString,
                      DRIVER_NAME"Adapter"
                      );
                  
    status = RtlAnsiStringToUnicodeString(&deviceExtension->ClassUnicodeString,
                                          &classNameString,
                                          TRUE
                                          );

    //
    // If the driver class name couldn't be created, just display a debug
    // message and continue getting the PCI resources.
    //
    
    if (!NT_SUCCESS(status)) {

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

        RtlInitUnicodeString(&deviceExtension->ClassUnicodeString,
                             NULL
                             );
    }

    //
    // Assign the PCI resources.
    //

    status = HalAssignSlotResources(RegistryPath,
                                    &deviceExtension->ClassUnicodeString,
                                    DriverObject,
                                    DeviceObject,
                                    deviceExtension->InterfaceType,
                                    deviceExtension->BusNumber,
                                    deviceExtension->SlotNumber,
                                    &resourceList
                                    );

    //
    // If the resources couldn't be acquired, cleanup and exit.
    //
    
    if (!NT_SUCCESS(status)) {

        DebugPrint((1, "Unable to assign PCI resources.  Status = %x \n",
                    status
                    ));

        FreeDeviceResources(DriverObject,
                            DeviceObject
                            );

        return status;
    }

    //
    // Parse the resource list and save the information.
    //

    ParseResourceList(deviceExtension,
                      resourceList->List
                      );


    DebugPrint((2, "%d resource(s) found (I/O and memory) \n",
                deviceExtension->AddressCount
                ));

    return STATUS_SUCCESS;
                          
}   // GetPciResources
    


BOOLEAN
InitializePciHw(
    IN PVOID Context
    )
/*++

Routine Description:

    SyncCriticalSection routine used to initialize the PCI device.  Note that 
    this routine is run at DIRQL so the routines that can be called are 
    limited.  This sample resets the PCI device and configures the device
    to generate only one type of interrupt.
    
Arguments:

    Context - Driver determined context information.  For this driver,
              the context is a pointer to the device extension.
    

Return Value:

    TRUE
    
--*/
{
    PDEVICE_EXTENSION   deviceExtension = Context;

///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- START 
//
///////////////////////////////////////////////////////////////

#ifdef VENDORID_1000_DEVICEID_0004

    UCHAR   byteValue;

    //
    // Do whatever is necessary to enable the device.  This routine is run 
    // at DIRQL so as to not be preempted by the device interrupting.
    // Please insure this routine runs as quickly as possible.
    //

    // 
    // Vendor specific code.
    //
    
    //
    // Set the time value in the device extension.  This value is between 
    // 0x01 and 0x0f.
    //
    
    deviceExtension->TimerPeriod = 0x03;
    
    //
    // Software reset.
    //
    
    byteValue = READ_UCHAR(INT_STATUS) | 0x40;
    
    WRITE_UCHAR(INT_STATUS, byteValue);
    
    //
    // Clear the software reset.
    //

    byteValue = READ_UCHAR(INT_STATUS) & 0xbf;
    
    WRITE_UCHAR(INT_STATUS, byteValue);
    
    //
    // Enable only one type of interrupt for this sample.
    //

    WRITE_UCHAR(INT_ENABLE1, 0x02);    

#endif
///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- END 
//
///////////////////////////////////////////////////////////////
    
    return TRUE;

}   // InitializePciHw


VOID
ParseResourceList(
    IN PDEVICE_EXTENSION DeviceExtension,
    IN PCM_FULL_RESOURCE_DESCRIPTOR AdapterResources
    )
/*++

Routine Description:

    Given a full resource description, store away the relevant information 
    for the adapter in the device extension.

Arguments:

    DeviceExtension - Adapter-specific storage area.

    AdapterResources - The CM_FULL_RESOURCE_DESCRIPTOR list for this adapter.

Return Value:

    None.

--*/
{
    PBASE_ADDRESS   baseAddress = DeviceExtension->BaseAddress;

    ULONG           index;
    ULONG           rangeCount = 0;

    BOOLEAN         interruptSet = FALSE;

    PCM_PARTIAL_RESOURCE_DESCRIPTOR partialData;

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

    for (index = 0; index < AdapterResources->PartialResourceList.Count; index++) {

        partialData = &AdapterResources->PartialResourceList.PartialDescriptors[index];

        switch (partialData->Type) {
        case CmResourceTypePort:

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

            if (rangeCount < PCI_TYPE0_ADDRESSES) {

                DebugPrint((3,
                            "  I/O range:     Base = %08x : %08x   Length = %08x \n",
                            partialData->u.Port.Start.HighPart,
                            partialData->u.Port.Start.LowPart,
                            partialData->u.Port.Length
                            ));

                //
                // Save I/O resource information.
                //

                baseAddress->RangeStart = partialData->u.Port.Start;
                baseAddress->RangeLength = partialData->u.Port.Length;
                baseAddress->RangeInMemory = FALSE;
                baseAddress->ResourceMapped = FALSE;

                //
                // Bump up the count of memory and I/O resources.
                //

                rangeCount++;

                //
                // Point to the next base address storage area.
                //

                baseAddress++;
            }

            break;

        case CmResourceTypeInterrupt:

            DebugPrint((3,
                        "  Interrupt:  Level = %x    Vector = %x    Mode = %x \n",
                        partialData->u.Interrupt.Level,
                        partialData->u.Interrupt.Vector,
                        partialData->Flags
                        ));

            //
            // Save interrupt information.
            //

            DeviceExtension->InterruptLevel = partialData->u.Interrupt.Level;
            DeviceExtension->InterruptVector = partialData->u.Interrupt.Vector;

            //
            // Check interrupt mode.
            //

            DeviceExtension->InterruptMode = LevelSensitive;
            
            if (CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE != partialData->Flags) {
                DeviceExtension->InterruptMode = Latched;
            }

⌨️ 快捷键说明

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