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

📄 pcidma.h

📁 dma驱动开发程序
💻 H
字号:
/*++

Copyright (c) 1997-1998  Microsoft Corporation

Module Name:

    pcidma.h

Abstract:


Author:

    Steve Dziok (SteveDz)

Environment:

    Kernel mode

Revision History:


--*/

#include <ntddk.h>
#include "debug.h"
#include "driver.h"



#define MAX_PCIDEVICELIST_ENTRIES   100
#define MAX_PCI_BUSES               256

#define EX_POOL_TAG_VALUE           'icPz'

//
// The following #define is used to include only the code appropriate
// for this specific PCI device.
//
// If the PCI SCSI vendor specific code is to be included, uncomment 
// the following definition.  See the README.TXT file for warnings
// about including this code.  If the PCI SCSI vendor specific code
// is not to be included, remove (comment) the following definition.
//

#define VENDORID_1000_DEVICEID_0004     1

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

#pragma message(" ")
#pragma message("*********************************************************************** ")
#pragma message("*                                                                     * ")
#pragma message("*  This sample driver is compiled for a specific PCI device:          * ")
#pragma message("*    VendorID 0x1000 DeviceID 0x0004 Symbios Logic 53c815 SCSI        * ")
#pragma message("*                                                                     * ")
#pragma message("*  If a different device is going to be supported, the vendor-unique  * ")
#pragma message("*  information in the driver must be updated and the driver rebuilt.  * ")
#pragma message("*                                                                     * ")
#pragma message("*  Search for VENDOR_UNIQUE in the source code.                       * ")
#pragma message("*                                                                     * ")
#pragma message("*********************************************************************** ")
#pragma message(" ")



//
// Change the PCI VendorId and DeviceId to match those
// of the PCI device this driver supports.
//

#define PCI_VENDOR_ID  0x1000
#define PCI_DEVICE_ID  0x0004


//
// Set the maximum number of devices this driver will support.
//

#define MAXIMUM_DEVICES_SUPPORTED   10

//
// Set the device specific information.
//

#define MAXIMUM_TRANSFER_LENGTH     64*1024
#define MAXIMUM_PHYSICAL_PAGES      16

#define SCATTER_GATHER_SUPPORT      TRUE

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

//
// Set up default values so the sample will compile.
//

#define PCI_VENDOR_ID  0x0000
#define PCI_DEVICE_ID  0x0000
#define MAXIMUM_DEVICES_SUPPORTED   1
#define MAXIMUM_TRANSFER_LENGTH     1024
#define MAXIMUM_PHYSICAL_PAGES      1
#define SCATTER_GATHER_SUPPORT      FALSE

#pragma message(" ")
#pragma message("*********************************************************************** ")
#pragma message("*                                                                     * ")
#pragma message("*  This sample driver is compiled without the PCI SCSI vendor         * ")
#pragma message("*  code included.  Without modification, this sample doesn't do       * ")
#pragma message("*  much.                                                              * ")
#pragma message("*                                                                     * ")
#pragma message("*********************************************************************** ")
#pragma message(" ")

#endif


//
// Define various storage layouts.
//

typedef struct _REGISTER_BASE {

//
// Register offsets
//


///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Vendor unique code -- START 
//
///////////////////////////////////////////////////////////////
#ifdef VENDORID_1000_DEVICEID_0004
    
    //
    // This just shows how you can define different register sizes in 
    // the structure.  There is a mix of UCHARs, ULONGs, UCHAR arrays,
    // and ULONG arrays.  Layout this structure to best map the specific 
    // device registers.
    //
                            // offset
    UCHAR   REG_00;         // 00
    UCHAR   REG_01;         // 01
    UCHAR   REG_02;         // 02
    UCHAR   REG_03;         // 03
    ULONG   REG_04;         // 04-07
    ULONG   REG_08;         // 08-0b
    UCHAR   REG_0C;         // 0c
    UCHAR   REG_0D;         // 0d
    UCHAR   REG_0E;         // 0e
    UCHAR   REG_0F;         // 0f
    ULONG   REG_10;         // 10-13
    UCHAR   INT_STATUS;     // 14
    UCHAR   REG_15;         // 15
    UCHAR   REG_16;         // 16
    UCHAR   REG_17;         // 17
    ULONG   REG_ARRAY0[10]; // 18-3f
    UCHAR   INT_ENABLE0;    // 40
    UCHAR   INT_ENABLE1;    // 41
    UCHAR   INT_STAT0;      // 42
    UCHAR   INT_STAT1;      // 43
    UCHAR   REG_ARRAY1[5];  // 44-48
    UCHAR   TIMER1;         // 49
    
    //
    // And so on...
    //
    

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

    ULONG   Dummy;          // Define a dummy element until the vendor unique code
                            // is included.

#endif
    
} REGISTER_BASE, *PREGISTER_BASE;
    

typedef struct _SG_ENTRY {

    PHYSICAL_ADDRESS    LogicalAddress;     // Mapped physical address
    ULONG               Length;

} SG_ENTRY, *PSG_ENTRY;

typedef struct _DPC_CONTEXT {

    ULONG       DpcInfo1;       // Some really useful info for the DPC
    ULONG       DpcInfo2;       // This sample doesn't use this info.
    ULONG       DpcInfo3;

} DPC_CONTEXT, *PDPC_CONTEXT;


typedef struct _BASE_ADDRESS {

    PHYSICAL_ADDRESS RangeStart;    // Original device physical address
    ULONG   RangeLength;            // Length of I/O or memory range
    BOOLEAN RangeInMemory;          // Flag: unmapped range is I/O or memory range

    PVOID   MappedRangeStart;       // Mapped I/O or memory range
    BOOLEAN MappedRangeInMemory;    // Flag: mapped range is I/O or memory range

    BOOLEAN ResourceMapped;         // Flag: resource is mapped (i.e. MmMapIoSpace called)

} BASE_ADDRESS, *PBASE_ADDRESS;

typedef struct _TRANSFER_INFO {

    PIRP        Irp;                    // IRP that the transfer info describes
    PVOID       CurrentVA;              // Virtual address of this transfer
    ULONG       ByteCount;              // Current transfer length
    BOOLEAN     WriteToDevice;          // Flag indicating Write operation
    ULONG       NumberOfMapRegisters;   // Number of map registers for current operation
    PVOID       MapRegisterBase;        // Map register base of current operation
    
} TRANSFER_INFO, *PTRANSFER_INFO;


typedef struct _DEVICE_EXTENSION {

    PDEVICE_OBJECT      DeviceObject;           // Returned by IoCreateDevice
    UNICODE_STRING      RegistryPath;           // Registry path to service control key
    UNICODE_STRING      Win32UnicodeString;     // DosDevice name for user mode
    UNICODE_STRING      ClassUnicodeString;     // DeviceClass name for registry resources

    BOOLEAN             SymbolicLinkCreated;    // Flag: DosDevice name created

    ULONG               BusNumber;              // System bus number
    ULONG               SlotNumber;             // PCI slot number

    PADAPTER_OBJECT     AdapterObject;          // Returned by HalGetAdapter
    PVOID               MapRegisterBase;        // Passed into the AdapterControl routine

    BOOLEAN             ScatterGather;          // Flag: scatter/gather support
    INTERFACE_TYPE      InterfaceType;          // Bus type -- PCI, ISA, EISA, etc.
    ULONG               MaximumTransferLength;  // Maximum transfer length for adapter
    ULONG               MaximumPhysicalPages;   // Maximum number of breaks adapter
                                                // supports

    PKINTERRUPT         InterruptObject;        // Returned by IoConnectInterrupt
    ULONG               InterruptLevel;         // Unmapped system interrupt level
    ULONG               InterruptVector;        // Unmapped system interrupt vector
    KINTERRUPT_MODE     InterruptMode;          // LevelSensitive or Latched
    
    LONG                DeviceConfigured;       // Flag: indicate device ready to go
    
    ULONG               AddressCount;           // Number of I/O and memory resources

    BASE_ADDRESS        BaseAddress[PCI_TYPE0_ADDRESSES];   // PCI base address info

    PREGISTER_BASE      RegisterBase;           // This is vendor defined structure
    UCHAR               TimerPeriod;            // Vendor specific (sample uses this value)

    PDPC_CONTEXT        DpcContext;             // Info for DpcForIsr routine

    TRANSFER_INFO       TransferInfo[1];        // Array of transfer info

    PHYSICAL_ADDRESS    SGListPA;               // Physical address of scatter/gather list
    ULONG               SGListLength;           // Length of scatter/gather list    
    BOOLEAN             SGListCached;           // Flag indicating whether SG list cached
    PSG_ENTRY           SGList;                 // Scatter/gather list
    
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;


//
// Define structures used to locate the PCI device.
//

typedef struct _PCI_DEVICE_LOCATION {
    ULONG BusNumber;
    PCI_SLOT_NUMBER SlotNumber;
} PCI_DEVICE_LOCATION, *PPCI_DEVICE_LOCATION;


typedef struct _PCI_DEVICE_LIST {
    ULONG Count;
    PCI_DEVICE_LOCATION List[1];
} PCI_DEVICE_LIST, *PPCI_DEVICE_LIST;


///////////////////////////////////////////////////////////////
//
// VENDOR_UNIQUE  -- Chose either memory mapped or I/O mapped
//
///////////////////////////////////////////////////////////////

//
// To use memory mapped registers, include the following #define.  
// To use I/O mapped registers, comment out the following #define.
//

#define USE_MEMORY_MAPPED_REGISTERS     1

#ifdef USE_MEMORY_MAPPED_REGISTERS

    //
    // Use memory mapped registers
    //

#define READ_UCHAR(RegXX)               \
    (READ_REGISTER_UCHAR(&(deviceExtension->RegisterBase)->RegXX))

#define READ_USHORT(RegXX)              \
    (READ_REGISTER_USHORT(&(deviceExtension->RegisterBase)->RegXX))

#define READ_ULONG(RegXX)               \
    (READ_REGISTER_ULONG(&(deviceExtension->RegisterBase)->RegXX))

#define WRITE_UCHAR(RegXX, ValueXX)     \
    (WRITE_REGISTER_UCHAR(&(deviceExtension->RegisterBase)->RegXX, ValueXX))

#define WRITE_USHORT(RegXX, ValueXX)    \
    (WRITE_REGISTER_USHORT(&(deviceExtension->RegisterBase)->RegXX, ValueXX))

#define WRITE_ULONG(RegXX, ValueXX)     \
    (WRITE_REGISTER_ULONG(&(deviceExtension->RegisterBase)->RegXX, ValueXX))


#else

    //
    // Use I/O mapped registers
    //


#define READ_UCHAR(RegXX)               \
    (READ_PORT_UCHAR(&(deviceExtension->RegisterBase)->RegXX))

#define READ_USHORT(RegXX)              \
    (READ_PORT_USHORT(&(deviceExtension->RegisterBase)->RegXX))

#define READ_ULONG(RegXX)               \
    (READ_PORT_ULONG(&(deviceExtension->RegisterBase)->RegXX))

#define WRITE_UCHAR(RegXX, ValueXX)     \
    (WRITE_PORT_UCHAR(&(deviceExtension->RegisterBase)->RegXX, ValueXX))

#define WRITE_USHORT(RegXX, ValueXX)    \
    (WRITE_PORT_USHORT(&(deviceExtension->RegisterBase)->RegXX, ValueXX))

#define WRITE_ULONG(RegXX, ValueXX)     \
    (WRITE_PORT_ULONG(&(deviceExtension->RegisterBase)->RegXX, ValueXX))


#endif

//
// Function prototypes
//

IO_ALLOCATION_ACTION
BuildScatterGatherList(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID MapRegisterBase,
    IN PVOID Context
    );

NTSTATUS
CreateDeviceObject(
    IN PDRIVER_OBJECT       DriverObject,
    IN PUNICODE_STRING      RegistryPath,
    IN ULONG                BusNumber,
    IN ULONG                SlotNumber,
    IN USHORT               DeviceNumber,
    OUT PDEVICE_OBJECT      *DeviceObject
    );

VOID
DebugPrintRoutine(
    ULONG PrintLevel,
    PCCHAR DebugMessage,
    ...
    );

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    );

NTSTATUS
FindPciDevice(
    IN USHORT VendorId,
    IN USHORT DeviceId,
    OUT PPCI_DEVICE_LIST PciDeviceList
    );

VOID
FreeDeviceResources(
    PDRIVER_OBJECT DriverObject,
    PDEVICE_OBJECT DeviceObject
    );

BOOLEAN
GetDeviceAddresses(
    IN PBASE_ADDRESS BaseAddress,
    IN ULONG ResourceCount,
    IN INTERFACE_TYPE InterfaceType,
    IN ULONG BusNumber
    );

NTSTATUS
GetAdapterInfo(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT DeviceOBject
    );
    
BOOLEAN
InitializePciHw(
    IN PVOID Context
    );

NTSTATUS
GetPciResources(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT DeviceOBject,
    IN PUNICODE_STRING RegistryPath
    );

VOID
ParseResourceList(
    IN PDEVICE_EXTENSION DeviceExtension,
    IN PCM_FULL_RESOURCE_DESCRIPTOR AdapterResources
    );

NTSTATUS
PciDmaCreateClose(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

VOID
PciDmaDpc(
    IN PKDPC Dpc,
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    );

BOOLEAN
PciDmaISR(
    IN PKINTERRUPT Interrupt,
    IN PVOID ServiceContext
    );

NTSTATUS
PciDmaReadWrite(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

VOID
PciDmaStartIo(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

VOID
PciDmaUnload(
    IN PDRIVER_OBJECT DriverObject
    );

VOID
ReleaseDeviceAddresses(
    IN PBASE_ADDRESS BaseAddress,
    IN ULONG ResourceCount
    );

BOOLEAN
SetBaseAddress(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT DeviceObject
    );

NTSTATUS
SetupIsrAndDpc(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT DeviceObject
    );

NTSTATUS
SetupPciDevice(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath,
    IN ULONG BusNumber,
    IN ULONG SlotNumber,
    IN USHORT DeviceNumber
    );

BOOLEAN
StartIoSynchronized(
    IN PVOID Context
    );
    

⌨️ 快捷键说明

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