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

📄 pci_sample.c

📁 PCI驱动程序开发示例。是我从OSR网站下载的
💻 C
📖 第 1 页 / 共 3 页
字号:
///////////////////////////////////////////////////////////////////////////////
//
//    (C) Copyright 1995 - 1997 OSR Open Systems Resources, Inc.
//    All Rights Reserved
//
//    This sofware is supplied for instructional purposes only.
//
//    OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty
//    for this software.  THIS SOFTWARE IS PROVIDED  "AS IS" WITHOUT WARRANTY
//    OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
//    THE IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR
//    PURPOSE.  THE ENTIRE RISK ARISING FROM THE USE OF THIS SOFTWARE REMAINS
//    WITH YOU.  OSR's entire liability and your exclusive remedy shall not
//    exceed the price paid for this material.  In no event shall OSR or its
//    suppliers be liable for any damages whatsoever (including, without
//    limitation, damages for loss of business profit, business interruption,
//    loss of business information, or any other pecuniary loss) arising out
//    of the use or inability to use this software, even if OSR has been
//    advised of the possibility of such damages.  Because some states/
//    jurisdictions do not allow the exclusion or limitation of liability for
//    consequential or incidental damages, the above limitation may not apply
//    to you.
//
//    OSR Open Systems Resources, Inc.
//    105 Route 101A Suite 19
//    Amherst, NH 03031  (603) 595-6500 FAX: (603) 595-6503
//    email bugs to: bugs@osr.com
//
//
//    This driver is the example Busmaster DMA device driver that
//    accompanies the book Windows NT Device Driver Development, by
//    Peter Viscarola and W. Anthony Mason, (c) 1998 OSR Open Systems
//    Resources, Inc. and published by MacMillan Technical Publishing
//    ISBN 1578700582.  
//
//    MODULE:
//
//        PCI_SAMPLE.C
//
//    ABSTRACT:
//
//      This file contains the initial entry point for the OSR Sample
//      PCI Busmaster DMA device driver for the AMCC 5933 chip.
//
//    AUTHOR(S):
//
//        OSR Open Systems Resources, Inc.
// 
//    REVISION:   
//
//          V1.1    Fix to typo in OsrWrite() to correctly set cancel
//                  routine to NULL when completing a request that's
//                  been cancelled very early in its processing.
//
//
///////////////////////////////////////////////////////////////////////////////

//#include <ntddk.h>
#include "osr-pci.h"

//
// Forward Declarations
//
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObj, PUNICODE_STRING RegistryPath);
static VOID OsrUnload(PDRIVER_OBJECT DriverObject);
static VOID OsrReturnPool(PPCI_COMMON_CONFIG  configInfo, PDEVICE_DESCRIPTION
            deviceDescription,  PCM_RESOURCE_LIST resources);

#if DBG
static VOID OsrPrintResourceList(PCM_RESOURCE_LIST);
static VOID OsrPrintConfig(PPCI_COMMON_CONFIG  configInfo);
#endif


//
// The following pragma allows the DriverEntry code to be discarded once
// initialization is completed
//
#pragma alloc_text(INIT,DriverEntry)

///////////////////////////////////////////////////////////////////////////////
//
//  DriverEntry
//
//      This routine is called by NT when the driver is first loaded.  It is the
//    responsibility of this routine to find it's device and create whatever
//    device objects it needs.
//
//  INPUTS:
//
//      DriverObj - Address of the DRIVER_OBJECT created by NT for this driver.
//
//      RegistryPath - UNICODE_STRING which represents this drivers KEY in the
//                   Registry.  
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      STATUS_SUCCESS. Otherwise an error indicating why the driver could not
//                    Load.
//
//  IRQL:
//
//    This routine is called at IRQL_PASSIVE_LEVEL.
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObj, PUNICODE_STRING RegistryPath)
{
    NTSTATUS code;
    PPCI_COMMON_CONFIG  configInfo = NULL;
    ULONG busNumber;
    ULONG deviceNumber;
    ULONG AddressSpace;
    PCI_SLOT_NUMBER slotNumber;
    ULONG length;
    BOOLEAN moreBuses;
    BOOLEAN adapterFound;
    ULONG index;
    ULONG addressSpace;
    PHYSICAL_ADDRESS address;
    POSR_DEVICE_EXT devExt;
    PDEVICE_OBJECT devObj;
    UNICODE_STRING devName, linkName;
    PDEVICE_DESCRIPTION deviceDescription = NULL;
    PCM_RESOURCE_LIST resources = NULL;
    ULONG interruptLevel;
    ULONG interruptVector;
    ULONG mappedSystemVector;
    PHYSICAL_ADDRESS portStart;
    ULONG portLength;
    KIRQL irql;
    KAFFINITY affinity;
    
    DbgPrint("\nOSR PCI Sample Driver -- Compiled %s %s\n",__DATE__, __TIME__);
    DbgPrint("(c) 1997 OSR Open Systems Resources, Inc.\n\n");

    //
    // Establish dispatch entry points for the functions we support
    //

    DriverObj->MajorFunction[IRP_MJ_CREATE]         =  OsrCreateClose;
    DriverObj->MajorFunction[IRP_MJ_CLOSE]          =  OsrCreateClose;

    DriverObj->MajorFunction[IRP_MJ_READ]           =  OsrRead;
    DriverObj->MajorFunction[IRP_MJ_WRITE]          =  OsrWrite;
    DriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] =  OsrDeviceControl;
    
    //
    // Unload function
    //
    DriverObj->DriverUnload = OsrUnload;

    
    //
    // Allocate space for a configuration information structure
    //
    configInfo = ExAllocatePoolWithTag(PagedPool,
                                       sizeof(PCI_COMMON_CONFIG),
                                       'pRSO');

    if (!configInfo) {

        //
        // Clean up the mess
        //
        OsrReturnPool(configInfo, deviceDescription, resources);

        //
        // Indicate load failure to the I/O manager
        //
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    //
    // Search for our device on all the PCI busses in the system
    //
    // We do this by ennumerating the configuration information for each
    // slot on each PCI bus in the system, until we find a device with
    // our Vendor ID and Device ID.
    //
    // Since this sample driver supports only a single card, we stop looking as
    // soon as we find one device.  Drivers that support multiple cards would
    // ennumerate all the busses and slots, finding as many devices as exist.
    //
    // Since our device is not a PCI "multifunction" device, we don't search
    // each function in each slot.
    //
    //
    adapterFound = FALSE;
    moreBuses = TRUE;

    for (busNumber = 0; !adapterFound && moreBuses; busNumber++) {
    
        //
        // Ennumerate all the devices on this bus
        //
        for (deviceNumber = 0; 
             !adapterFound && deviceNumber < PCI_MAX_DEVICES;
             deviceNumber++)  {

            //
            // For PCI buses, the logical slot number is a PCI_SLOT_NUMBER
            // structure, comprising a combination of the device number and the
            // function number on the card.  The Reserved section MUST be set
            // to zero.
            //
            // Note that since we're not a multifunction device, we only look
            // at FunctionNumber 0 in each slot.
            //
            slotNumber.u.bits.Reserved = 0;
            slotNumber.u.bits.DeviceNumber = deviceNumber;
            slotNumber.u.bits.FunctionNumber = 0;
            
            //
            // Get the configuration space for the adapter in this slot
            //
            length = HalGetBusData(PCIConfiguration,
                                   busNumber,
                                   slotNumber.u.AsULONG,
                                   configInfo,
                                   sizeof(PCI_COMMON_CONFIG) );

            //
            // A return value of zero indicates no more PCI buses on the system
            //                       
            if (length == 0) {
#if DBG
                DbgPrint("Reached end of PCI bus list\n");
#endif
                moreBuses = FALSE;
                break;
            }

            //
            // If there's nothing in this slot, PCI_INVALID_VENDORID is returned
            // as the vendor ID.  If this is the case, just continue running
            // the bus.
            //
            if (configInfo->VendorID == PCI_INVALID_VENDORID)  {
                
                continue;
            }

            //
            // Dump out information about the device found.
            //
#if DBG
            DbgPrint("Found a PCI device at Bus %d. Device %d.\n",
                          busNumber,
                          deviceNumber);

            DbgPrint("Vendor id = 0x%0x, Device id = 0x%0x\n", 
                          (int)configInfo->VendorID,
                          (int)configInfo->DeviceID);
#endif   // DBG
            
            //
            // Is this the PCI device for which we've been searching?  It is 
            // if both the vendor and device ID match
            //
            if ( (configInfo->VendorID == OSR_PCI_VID) &&
                  (configInfo->DeviceID == OSR_PCI_DID) )  {
                    
                ULONG index;
                
                //
                // FOUND IT!  No need to keep searching.  We support only
                // one device.
                //
                adapterFound = TRUE;

#if DBG
                DbgPrint("*** Found OUR PCI ADAPTER ***");
                
                //
                // Just for the sake of interest, let's dump some of the
                // configuration information for our device.
                //
                OsrPrintConfig(configInfo);
#endif
            }

        }

    }

    //
    // If we didn't find our adapter, we bail out here, thereby aborting
    // the driver load process.  The I/O Manager will delete our driver
    // object.
    //
    if (!adapterFound) {

#if DBG
        DbgPrint("OSR PCI Sample device was not found!? -- EXITING.\n");
#endif
        //
        // Clean up the mess
        //
        OsrReturnPool(configInfo, deviceDescription, resources);

        //
        // Indicate load failure to the I/O manager; driver image is deleted...
        //
        return(STATUS_NO_SUCH_DEVICE);
    }
    
    //
    // ***************************************************************
    //
    // Hooray!  We've found our device!
    //
    // Lets create a device object for it
    //

    //
    // Initialize the UNICODE device name.  This will be the "native NT" name
    // for our device.
    //
    RtlInitUnicodeString(&devName, L"\\Device\\OSRPCI");

    //
    // Ask the I/O Manager to create the device object and
    // device extension
    //
    code = IoCreateDevice(DriverObj,
                          sizeof(OSR_DEVICE_EXT),
                          &devName,
                          FILE_DEVICE_OSR,
                          0,       
                          FALSE,
                          &devObj);

        
    if(!NT_SUCCESS(code))  {
        
#if DBG
        DbgPrint("IoCreateDevice failed.  Status = 0x%0x\n", code);
#endif
        return(STATUS_UNSUCCESSFUL);
    }    

    //
    // Get a pointer to our device extension
    //
    devExt = (POSR_DEVICE_EXT)devObj->DeviceExtension;
    
    //
    // Zero out the device extension.  While not strictly necessary
    // (the documentation says the device extension is zeroed) it's
    // better to be safe.
    //
    RtlZeroMemory(devExt, sizeof(OSR_DEVICE_EXT));

    //
    // Save the device object pointer away for future reference
    //
    devExt->DeviceObject = devObj;

    //
    // Store the bus and slot number away for the device we found
    //
    devExt->BusNumber = busNumber-1;
    devExt->SlotNumber = slotNumber;

    //
    // Next, make the device accessible from user-mode applications.
    // Note that this name can be either the same or different from
    // the native "kernel mode" name of the device object, given above.
    //
    RtlInitUnicodeString(&linkName, L"\\??\\OSRPCI");

    code = IoCreateSymbolicLink(&linkName, &devName);
    
    if (!NT_SUCCESS(code))
    {

#if DBG
        DbgPrint("IoCreateSymbolicLink failed.  Status = 0x%x\n", code);
#endif
        //
        // Clean up the mess
        //
        OsrReturnPool(configInfo, deviceDescription, resources);

        OsrUnload(DriverObj);

        //
        // Indicate load failure to the I/O manager; driver image is deleted...
        //
        return(code);
    }


    //
    // Initialize our IRP queues
    //
    InitializeListHead(&devExt->ReadQueue);
    InitializeListHead(&devExt->WriteQueue);
    
    //
    // Initialize our Spin Locks
    //
    KeInitializeSpinLock(&devExt->ReadQueueLock);
    KeInitializeSpinLock(&devExt->WriteQueueLock);
    
    //
    // Ask the I/O Manager to use describe user read/write buffers using MDLs
    //
    devObj->Flags |= DO_DIRECT_IO;

    //
    // Next, get the HAL to tell us about the resources the device will use. 
    // These resources include ports, shared memory regions, interrupts, and
    // the like.  The resources will be resevered for us in the registry (so
    // we do not have to call either IoReportResourceUsage or IoAssignResources).
    //
    code = HalAssignSlotResources(RegistryPath,
                                  NULL,
                                  DriverObj,
                                  devObj,
                                  PCIBus,
                                  devExt->BusNumber,
                                  devExt->SlotNumber.u.AsULONG,
                                  &resources);

    //
    // On return from this call, all resources are identified and assigned for
    // use by our device.
    //
    if (!NT_SUCCESS(code)) {

        //
        // log an appropriate error string.
        //
#if DBG
        DbgPrint("HalAssignSlotResourced failed!  Status = 0x%0x", code);

⌨️ 快捷键说明

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