pciScan.c
上传用户:zhuqijet
上传日期:2007-01-04
资源大小:138k
文件大小:18k
源码类别:

驱动编程

开发平台:

Visual C++

  1. // pclUtil.c driver utilities for PCI bus adapters
  2. /*****************************************************************************
  3. *           Change Log
  4. *  Date     | Change
  5. *-----------+-----------------------------------------------------------------
  6.   09-13-96     create log
  7. *****************************************************************************/
  8. /*****************************************************************************
  9. *           To DO
  10. *-----------------------------------------------------------------------------
  11. *****************************************************************************/
  12.   
  13. #define NT_DEVICE_NAME L"\Device\PCISCAN" 
  14. #define DOS_DEVICE_NAME L"\DosDevices\PCISCAN"
  15. #define BYTE UCHAR
  16. /*++
  17. Module Name:
  18.     pclUtil.c
  19. Abstract:
  20.     Windows NT device driver utilities for PCI bus adapters.
  21.                   
  22. Author:
  23.     Edward Dekker
  24. Environment:
  25.     kernel mode only
  26. Notes:
  27.     --*/
  28. #include "ntddk.h"
  29. //#include "pciScan.h"       // include device extension for target driver here
  30. #include "pciScanIoctl.h"       // include device extension for target driver here
  31. typedef struct _PCISCAN_DEVICE_EXTENSION 
  32. {
  33.     PDEVICE_OBJECT   DeviceObject;
  34.         
  35.     PCI_SLOT_NUMBER returnSlotData;   
  36.     PCI_COMMON_CONFIG returnPciData;   
  37.     unsigned int returnBusNumber;
  38. } PCISCAN_DEVICE_EXTENSION;
  39. typedef PCISCAN_DEVICE_EXTENSION *PPCISCAN_DEVICE_EXTENSION;
  40. NTSTATUS pciScanOpen(
  41.     IN PDEVICE_OBJECT DeviceObject,
  42.     IN PIRP Irp );
  43. NTSTATUS pciScanClose(
  44.     IN PDEVICE_OBJECT DeviceObject,
  45.     IN PIRP Irp );
  46. VOID pciScanUnload( IN PDRIVER_OBJECT DriverObject);
  47. NTSTATUS  pciScanDeviceControl(
  48.     IN PDEVICE_OBJECT DeviceObject,
  49.     IN PIRP Irp );
  50.  
  51. void dumpPciConfig(    PCI_COMMON_CONFIG    pciData)
  52. {
  53.            // dump our PCI_COMMON_CONFIG record here
  54.            
  55.            KdPrint( ("pciScan: pciData.VendorID     = %xn", pciData.VendorID ) );
  56.            KdPrint( ("pciScan: pciData.DeviceID     = %xn", pciData.DeviceID ) );
  57.            KdPrint( ("pciScan: pciData.Command      = %xn", pciData.Command ) );
  58.            KdPrint( ("pciScan: pciData.Status       = %xn", pciData.Status ) );
  59.            KdPrint( ("pciScan: pciData.RevisionID   = %xn", pciData.RevisionID ) );
  60.            KdPrint( ("pciScan: pciData.ProgIf       = %xn", pciData.ProgIf ) );
  61.            KdPrint( ("pciScan: pciData.SubClass     = %xn", pciData.SubClass ) );
  62.            KdPrint( ("pciScan: pciData.BaseClass    = %xn", pciData.BaseClass ) );
  63.            KdPrint( ("pciScan: pciData.CacheLineSize= %xn", pciData.CacheLineSize ) );
  64.            KdPrint( ("pciScan: pciData.LatencyTimer = %xn", pciData.LatencyTimer ) );
  65.            KdPrint( ("pciScan: pciData.HeaderType   = %xn", pciData.HeaderType ) );
  66.            KdPrint( ("pciScan: pciData.BIST         = %xn", pciData.BIST ) );
  67.            KdPrint( ("pciScan: pciData.u.type0.BaseAddresses[0]    = %xn", pciData.u.type0.BaseAddresses[0] ) );
  68.            KdPrint( ("pciScan: pciData.u.type0.BaseAddresses[1]    = %xn", pciData.u.type0.BaseAddresses[1] ) );
  69.            KdPrint( ("pciScan: pciData.u.type0.BaseAddresses[2]    = %xn", pciData.u.type0.BaseAddresses[2] ) );
  70.            KdPrint( ("pciScan: pciData.u.type0.ROMBaseAddress = %xn", pciData.u.type0.ROMBaseAddress ) );
  71.            KdPrint( ("pciScan: pciData.u.type0.InterruptLine  = %xn", pciData.u.type0.InterruptLine ) );
  72.            KdPrint( ("pciScan: pciData.u.type0.InterruptPin   = %xn", pciData.u.type0.InterruptPin ) );
  73.            KdPrint( ("pciScan: pciData.u.type0.MinimumGrant   = %xn", pciData.u.type0.MinimumGrant ) );
  74.            KdPrint( ("pciScan: pciData.u.type0.MaximumLatency = %xn", pciData.u.type0.MaximumLatency ) );
  75. }
  76. /****************************************************************************
  77.     Function:
  78.           DriverEntry
  79.     Arguments:
  80.     Description:
  81.     Returns:
  82. *****************************************************************************/
  83. NTSTATUS DriverEntry(
  84.     IN PDRIVER_OBJECT DriverObject,
  85.     IN PUNICODE_STRING RegistryPath )
  86. {
  87.     PDEVICE_OBJECT deviceObject = NULL;
  88.     NTSTATUS status;
  89.     UNICODE_STRING uniNtNameString;
  90.     UNICODE_STRING uniWin32NameString;
  91.     PPCISCAN_DEVICE_EXTENSION extension;
  92.     BOOLEAN GotResources;
  93.     ULONG         ret = 0;
  94.     KdPrint( ("pciScan: Entered the pciScan driver!n") );
  95.     //
  96.     // Create counted string version of our device name.
  97.     //
  98.     RtlInitUnicodeString( &uniNtNameString, NT_DEVICE_NAME );
  99.     //
  100.     // Create the device object
  101.     //
  102.     status = IoCreateDevice(
  103.                  DriverObject,
  104.                  sizeof(PCISCAN_DEVICE_EXTENSION),                    
  105.                  &uniNtNameString,
  106.                  FILE_DEVICE_UNKNOWN,
  107.                  0,                     // No standard device characteristics
  108.                  FALSE,                 // This isn't an exclusive device
  109.                  &deviceObject
  110.                  );
  111.     if ( NT_SUCCESS(status) )
  112.     {
  113.         //
  114.         // Create dispatch points for create/open, close, unload.
  115.         //
  116.         KdPrint( ("pciScan: IoCreateDevice successn") );
  117.         DriverObject->MajorFunction[IRP_MJ_CREATE] = pciScanOpen;
  118.         DriverObject->MajorFunction[IRP_MJ_CLOSE] = pciScanClose;
  119.         DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = pciScanDeviceControl;
  120.         DriverObject->DriverUnload = pciScanUnload;
  121.         KdPrint( ("pciScan: just about ready!n") );
  122.                        
  123.         //
  124.         // Do direct I/O.  I.e., the I/O system will provide pointers to/from user data
  125.         // from/to the user buffer.
  126.         //
  127.         deviceObject->Flags |= DO_DIRECT_IO;
  128.         //
  129.         // Create counted string version of our Win32 device name.
  130.         //
  131.         RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
  132.                status = IoCreateSymbolicLink( &uniWin32NameString, &uniNtNameString );
  133.         if (!NT_SUCCESS(status))
  134.         {
  135.             KdPrint( ("pciScan: Couldn't create the symbolic linkn") );
  136.             IoDeleteDevice( DriverObject->DeviceObject );
  137.         }
  138.         else
  139.         {
  140.             KdPrint( ("pciScan: All initialized!n") );
  141.         }
  142.       }
  143.       else
  144.       {
  145.         KdPrint( ("pciScan: IoCreateDevice failedn") );
  146.       }      
  147.      return status;
  148. }
  149.  
  150. BOOLEAN pciScanIteratePCI( IN BOOLEAN First, IN unsigned int pciVendorId,
  151.                            IN unsigned int pciDeviceId,  
  152.                            IN OUT  PCI_SLOT_NUMBER *returnSlotData,   
  153.                            IN OUT  PCI_COMMON_CONFIG *returnPciData,   
  154.                            IN OUT  unsigned int *returnBusNumber   )
  155. /*++
  156. Routine Description:
  157.     This function is called by the driver to find the next PCI card and 
  158.     initialize the adapter's configuration.
  159. Arguments:
  160.     IN BOOLEAN First                          - TRUE if scan is to start with
  161.                                                 first device 
  162.                                                 FALSE to increment to the next
  163. device
  164.     IN unsigned int pciVendorId               - Specified vender ID,
  165.              or 0xFFFF for all venders
  166.     IN unsigned int pciDeviceId               - Specified device ID,
  167.              or 0xFFFF for all devices
  168.     IN OUT  PCI_SLOT_NUMBER *returnSlotData   - Slotdata for found device 
  169.      (starting point for
  170. first == FALSE)
  171.     IN OUT  unsigned int *returnBusNumber     - Bus number for found card
  172. Return Value:
  173.     ULONG
  174. --*/
  175. {
  176.     PCI_SLOT_NUMBER   slotData;
  177.     PCI_COMMON_CONFIG pciData;
  178.     BOOLEAN nextBus = FALSE;
  179.     ULONG   busNumber = 1;
  180.     ULONG   bytesReturned; 
  181.     BOOLEAN firstFunction;
  182.     BOOLEAN firstDevice;
  183.     KdPrint( ("pciScan: FindPCI n") );
  184.     //
  185.     // iterate over all PCI slots
  186.     //
  187.     firstFunction = First;
  188.     firstDevice = First;
  189.     
  190.     slotData.u.AsULONG = 0;
  191.     
  192.     if (!First)
  193.       { /* continuation */
  194.         //
  195.         // if not the first we want to point after the last device we found
  196.         //        
  197.        returnSlotData->u.bits.FunctionNumber++;
  198.        if (PCI_MAX_FUNCTION <= returnSlotData->u.bits.FunctionNumber)
  199.   { /* next device */
  200.    returnSlotData->u.bits.FunctionNumber = 0;
  201.    returnSlotData->u.bits.DeviceNumber++;
  202.    if (PCI_MAX_DEVICES <= returnSlotData->u.bits.DeviceNumber)
  203.       { /* next bus */
  204.        returnSlotData->u.bits.DeviceNumber = 0;
  205.        *returnBusNumber++;          
  206.       } /* next bus */
  207.   } /* next device */
  208.       } /* continuation */
  209.     //
  210.     // iterate over all PCI busses looking for devices 
  211.     //
  212.     for ( busNumber = First?0:*returnBusNumber;
  213.           busNumber < 256;
  214.           busNumber++, firstDevice = TRUE)
  215.   { /* busses loop */
  216.    unsigned int DeviceNumber; 
  217.    nextBus = FALSE;
  218.     
  219.    //
  220.    // Iterate over all devices
  221.    //
  222.    for ( DeviceNumber = firstDevice?0:returnSlotData->u.bits.DeviceNumber;
  223.          DeviceNumber < PCI_MAX_DEVICES ;
  224.  DeviceNumber++, firstFunction = TRUE )     
  225.          { /* devices loop */
  226.   unsigned int FunctionNumber;
  227.    
  228.   slotData.u.bits.DeviceNumber = DeviceNumber;
  229.   //
  230.   // Iterate over all functions 
  231.   //
  232.           
  233.           
  234.           
  235.   for ( FunctionNumber = 
  236.                          firstFunction?0:returnSlotData->u.bits.FunctionNumber;
  237.                         FunctionNumber < PCI_MAX_FUNCTION ;
  238.                         FunctionNumber++)
  239. { /* functions loop */
  240.  slotData.u.bits.FunctionNumber = FunctionNumber;
  241.             
  242.  KdPrint( ("pciScan: FindPCI - call HalGetBusData  DeviceNumber= %x, Function = %x, busNumber = %x  ", 
  243.   slotData.u.bits.DeviceNumber, 
  244. slotData.u.bits.FunctionNumber, 
  245. busNumber) );
  246.   RtlZeroMemory(&pciData, sizeof(PCI_COMMON_CONFIG));
  247.                           bytesReturned = HalGetBusData( PCIConfiguration,
  248.                                                          busNumber,
  249.  slotData.u.AsULONG,
  250.  &pciData,
  251.  sizeof(PCI_COMMON_CONFIG));
  252.                           if (2 == bytesReturned)  // device/function does not exist
  253.                              { /* no device/function */
  254.       KdPrint( (" - no match  2 returned   pciData.VendorID = %x   %xn", 
  255.        pciData.VendorID, 
  256. slotData.u.AsULONG) );
  257.                               //
  258.       // MUST CONTINUE WITH LOOP -- 
  259.       // functions do not have to be consective
  260.       //
  261.      } /* no device/function */
  262.   else 
  263.   if (0 == bytesReturned)  // bus does not exist
  264.      { /* no bus */
  265.       KdPrint( (" - no match  0 returned   pciData.VendorID = %x   %xn", 
  266.        pciData.VendorID, 
  267. slotData.u.AsULONG) );
  268.                               //
  269.       // We can skip to next bus
  270.       //    set flag to break out of device loop 
  271.       //    and break out of function loop 
  272.       //
  273.       nextBus = TRUE;
  274.       break;
  275.      } /* no bus */
  276.   else 
  277.   if (0xffff == pciData.VendorID) 
  278.      { /* invalid vendor ID */
  279.       KdPrint( (" - no match  PCI_INVALID_VENDER_ID  HalGetBusData  pciData.VendorID = %xn", 
  280.        pciData.VendorID) );                        
  281.      } /* invalid vendor ID */
  282.   else 
  283.   if (  ((0xFFFF == pciVendorId)  
  284.         || ( pciData.VendorID == pciVendorId )) &&
  285.                                    ((0xFFFF == pciDeviceId)  
  286.                                        || ( pciData.DeviceID == pciDeviceId)))
  287.      { /* found next */
  288.       // Found it this is the next instance of 
  289.       // this card type
  290.       KdPrint( ("npciScan: ( busNumber, device, function )    = ( %x, %x,  %x )n", 
  291.             busNumber,
  292.      slotData.u.bits.DeviceNumber, 
  293.      slotData.u.bits.FunctionNumber));
  294.                               dumpPciConfig( pciData );
  295.     
  296.       KdPrint( ("nn") );
  297.       *returnSlotData = slotData;
  298.       *returnPciData  = pciData;
  299.       *returnBusNumber =  busNumber;
  300.                       
  301.       KdPrint( ("pciScan: exitingn") );
  302.       return TRUE;       
  303.      } /* found next */
  304.   else
  305.      { /* does not match */
  306.       KdPrint( (" - no match   pciData.VendorID = %x   %xn", pciData.VendorID, slotData.u.AsULONG) );
  307.      } /* does not match */
  308. } /* functions loop */
  309.           
  310.      if (nextBus)
  311.  break;    // break to next bus
  312.  } /* devices loop */
  313.   } /* busses loop */
  314.     KdPrint( ("pciScan: exitingn") );
  315.     return FALSE;       
  316. } // end pciScanFindPCI()
  317.                                   
  318. /****************************************************************************
  319.     Function:
  320.               pciScanDeviceControl
  321.     Arguments:
  322.     Description:
  323.     Returns:
  324. *****************************************************************************/
  325. NTSTATUS  pciScanDeviceControl(
  326.                                IN PDEVICE_OBJECT DeviceObject,
  327.        IN PIRP Irp )
  328.    {
  329.     NTSTATUS  ret = STATUS_SUCCESS;
  330.     PIO_STACK_LOCATION irpStack;
  331.     PCISCAN_OUTPUT  *pOutBuffer;
  332.     PCISCAN_DEVICE_EXTENSION *extension;
  333.     PCI_SLOT_NUMBER returnSlotData;   
  334.     PCI_COMMON_CONFIG returnPciData;   
  335.     unsigned int returnBusNumber;
  336.     KdPrint( ("pciScan: Device Control!!n") );
  337.     extension = (PCISCAN_DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  338.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  339.     pOutBuffer = (PCISCAN_OUTPUT *)Irp->UserBuffer;    // for buffered i/o
  340.     switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
  341.        { /* IOCTL */
  342.         case  IOCTL_PCISCAN_GET_FIRST:
  343. KdPrint( ("pciScan: Device Control  -- enter GET FIRSTn") );
  344. if (pciScanIteratePCI( TRUE, 0xffff, 0xffff,
  345.                        &extension->returnSlotData,   
  346.        &extension->returnPciData,   
  347.        &extension->returnBusNumber   ))
  348.                    { /* got first */
  349.     KdPrint( ("pciScanIoctl: found first pci devicen") );
  350.     pOutBuffer->SlotData = extension->returnSlotData;   
  351.     pOutBuffer->PciData =  extension->returnPciData;   
  352.     pOutBuffer->BusNumber = extension->returnBusNumber;  
  353.                   
  354.     ret = STATUS_SUCCESS;                      
  355.     break;
  356.    } /* got first */
  357. else
  358.    { /* failed first */
  359.     KdPrint( ("pciScanIoctl: FAILED find first pci devicen") );
  360.     ret = STATUS_UNSUCCESSFUL;                      
  361.     break;
  362.    } /* failed first */
  363. break;
  364.              
  365. case  IOCTL_PCISCAN_GET_NEXT:
  366. KdPrint( ("pciScan: Device Control  -- enter GET NEXTn") );
  367. if (pciScanIteratePCI( FALSE, 0xffff, 0xffff,
  368.                                        &extension->returnSlotData,   
  369.        &extension->returnPciData,   
  370.        &extension->returnBusNumber   ))
  371.                   { /* got next */
  372.    KdPrint( ("npciScanIoctl: found next pci devicen") );
  373.    pOutBuffer->SlotData = extension->returnSlotData;   
  374.    pOutBuffer->PciData =  extension->returnPciData;   
  375.    pOutBuffer->BusNumber = extension->returnBusNumber;  
  376.                   
  377.    ret = STATUS_SUCCESS;                      
  378.    break;
  379.   } /* got next */
  380.        else
  381.   { /* no more */
  382.    KdPrint( ("pciScanIoctl: FAILED find next pci devicen") );
  383.    ret = STATUS_UNSUCCESSFUL;                      
  384.    break;
  385.   } /* no more */
  386.        break;
  387. default:
  388.        ret = STATUS_UNSUCCESSFUL;
  389.        } /* IOCTL */
  390.     KdPrint( ("pciScan: Device Control  -- returnn") );
  391.     
  392.     //
  393.     // Fill these in before calling IoCompleteRequest.
  394.     //
  395.     Irp->IoStatus.Status = ret;
  396.     Irp->IoStatus.Information = 0;
  397.     IoCompleteRequest( Irp, IO_NO_INCREMENT );
  398.     return ret;
  399.    }
  400. VOID pciScanUnload( IN PDRIVER_OBJECT DriverObject)
  401. {
  402.     UNICODE_STRING uniDosNameString;
  403.     //
  404.     // All *THIS* driver needs to do is to delete the allocated memory objects,  
  405.     // the device object and the
  406.     // symbolic link between our device name and the Win32 visible name.
  407.     //                       
  408.     // Almost every other driver ever witten would need to do a
  409.     // significant amount of work here deallocating stuff.
  410.     //
  411.     KdPrint( ("pciScan: Unloading!!n") );
  412.     //
  413.     // Create counted string version of our Win32 device name.
  414.     //
  415.     RtlInitUnicodeString( &uniDosNameString, DOS_DEVICE_NAME );
  416.     //
  417.     // Delete the link from our device name to a name in the Win32 namespace.
  418.     //
  419.     IoDeleteSymbolicLink( &uniDosNameString );
  420.     //
  421.     // Finally delete our device object
  422.     //
  423.     IoDeleteDevice( DriverObject->DeviceObject );
  424. }
  425.  
  426. NTSTATUS pciScanOpen(
  427.     IN PDEVICE_OBJECT DeviceObject,
  428.     IN PIRP Irp )
  429. {
  430.     KdPrint( ("pciScan: Opened!!n") );
  431.     //
  432.     // No need to do anything.
  433.     //
  434.     //
  435.     // Fill these in before calling IoCompleteRequest.
  436.     //
  437.     // DON'T get cute and try to use the status field of
  438.     // the irp in the return status.  That IRP IS GONE as
  439.     // soon as you call IoCompleteRequest.
  440.     //
  441.     Irp->IoStatus.Status = STATUS_SUCCESS;
  442.     Irp->IoStatus.Information = 0;
  443.     IoCompleteRequest( Irp, IO_NO_INCREMENT );
  444.     return STATUS_SUCCESS;
  445. }
  446. NTSTATUS pciScanClose(
  447.     IN PDEVICE_OBJECT DeviceObject,
  448.     IN PIRP Irp )
  449. {
  450.     KdPrint( ("pciScan: Closed!!n") );
  451.     //
  452.     // No need to do anything.
  453.     //
  454.     //
  455.     // Fill these in before calling IoCompleteRequest.
  456.     //
  457.     // DON'T get cute and try to use the status field of
  458.     // the irp in the return status.  That IRP IS GONE as
  459.     // soon as you call IoCompleteRequest.
  460.     //
  461.     Irp->IoStatus.Status = STATUS_SUCCESS;
  462.     Irp->IoStatus.Information = 0;
  463.     IoCompleteRequest( Irp, IO_NO_INCREMENT );
  464.     return STATUS_SUCCESS;
  465. }