PCIe驱动开发-驱动加载

来源:互联网 发布:unity3d安卓真机调试 编辑:程序博客网 时间:2024/05/21 18:45

上篇中,我们探讨了PCIe设备是如何在Bios中被初始化的,Bios中各种准备工作做好后,就开始引导装载操作系统,系统的控制权移交给操作系统,操作系统中也要对系统中各PCI设备进行扫描以及初始化(和上文中提到的Bios对PCI设备的枚举和配置一样),事实上,早期的操作系统也是通过Bios调用的方式来获取系统PCI设备信息的,只不过现在变成亲自动手了。总体来说,操作系统对PCI的枚举以及初始化的过程和Bios的基本一致,在此我们就不在赘述了。我们把探讨的重点放在PCIe设备在驱动中如何启动,如何初始化等内容上。

我们知道所有驱动程序的入口点是DriverEntry函数,针对本次的PCIe设备,我们的DriverEntry函数设置如下:

[cpp] view plaincopyprint?
  1. NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObj, PUNICODE_STRING RegistryPath)  
  2. {  
  3.     DebugPrint("DriverEntry() Start\n");  
  4.       
  5.     /* 注册派遣函数 */  
  6.     DriverObj->DriverUnload              = DemoPciUnload;  
  7.     DriverObj->DriverExtension->AddDevice     = DemoPciAddDevice;  
  8.     DriverObj->DriverStartIo         = DemoPciStartIo;  
  9.     DriverObj->MajorFunction[IRP_MJ_PNP]     = DemoPciPnp;  
  10.     DriverObj->MajorFunction[IRP_MJ_POWER]       = DemoPciPower;  
  11.     DriverObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL]  = DemoPciSystemControl;  
  12.     DriverObj->MajorFunction[IRP_MJ_CREATE]      = DemoPciCreateClose;  
  13.     DriverObj->MajorFunction[IRP_MJ_CLOSE]       = DemoPciCreateClose;  
  14.     DriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = DemoPciDeviceControl;  
  15.   
  16.     DebugPrint("DriverEntry() End\n");  
  17.       
  18.     return STATUS_SUCCESS;  
  19. }  
[cpp] view plain copy
print?
  1. NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObj, PUNICODE_STRING RegistryPath)  
  2. {  
  3.     DebugPrint("DriverEntry() Start\n");  
  4.       
  5.     /* 注册派遣函数 */  
  6.     DriverObj->DriverUnload              = DemoPciUnload;  
  7.     DriverObj->DriverExtension->AddDevice     = DemoPciAddDevice;  
  8.     DriverObj->DriverStartIo         = DemoPciStartIo;  
  9.     DriverObj->MajorFunction[IRP_MJ_PNP]     = DemoPciPnp;  
  10.     DriverObj->MajorFunction[IRP_MJ_POWER]       = DemoPciPower;  
  11.     DriverObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL]  = DemoPciSystemControl;  
  12.     DriverObj->MajorFunction[IRP_MJ_CREATE]      = DemoPciCreateClose;  
  13.     DriverObj->MajorFunction[IRP_MJ_CLOSE]       = DemoPciCreateClose;  
  14.     DriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = DemoPciDeviceControl;  
  15.   
  16.     DebugPrint("DriverEntry() End\n");  
  17.       
  18.     return STATUS_SUCCESS;  
  19. }  

当PnP管理器检测到我们的PCIe设备时,它首先通过查阅相关的注册表来了解哪些驱动程序将管理我们的这个设备,并将驱动加载进来,然后调用驱动中的已经注册好的AddDevice函数(上述代码中注册的DemoPciAddDevice函数)。该函数将为我们的PCIe设备创建设备对象,并将该设备对象挂载在相应的设备栈上。

[cpp] view plaincopyprint?
  1. NTSTATUS DemoPciAddDevice(  
  2.     IN PDRIVER_OBJECT DriverObject,  
  3.     IN PDEVICE_OBJECT PhysicalDeviceObject  
  4. )  
  5. {  
  6.     UCHAR           i;  
  7.     UNICODE_STRING      devname;  
  8.     ULONG           xsize;  
  9.     NTSTATUS        status = STATUS_SUCCESS;  
  10.     PTSTDPCI_DEVICE_EXT pDevExt = NULL;  
  11.     PDEVICE_OBJECT      functionalDeviceObject = NULL;  
  12.       
  13.     DebugPrint("DemoPciAddDevice() Start\n");  
  14.       
  15.     if( (DriverObject == NULL) || (PhysicalDeviceObject == NULL) )  
  16.         return (STATUS_NO_SUCH_DEVICE);  
  17.       
  18.         /*设备名*/  
  19.     RtlInitUnicodeString(&devname,TSTDPCI_DEVICE_NAME);  
  20.   
  21.         /*我们定义的扩展设备对象的大小*/  
  22.         xsize=( (sizeof(DEMOPCI_DEVICE_EXT) + 7) & (~7) );  
  23.   
  24.         /*创建设备对象*/  
  25.     status = IoCreateDevice( DriverObject,  
  26.                  xsize,  
  27.                  &devname,  
  28.                  FILE_DEVICE_DEMOPCI,  
  29.                  0,             //FILE_DEVICE_SECURE_OPEN,  
  30.                  FALSE,  
  31.                  &functionalDeviceObject  
  32.                     );  
  33.     if( !NT_SUCCESS(status) )  
  34.     {  
  35.         return (status);  
  36.     }  
  37.     if(functionalDeviceObject == NULL)  
  38.     {  
  39.         return (STATUS_UNSUCCESSFUL);  
  40.     }  
  41.       
  42. __try  
  43. {  
  44.     /* 获取扩展设备对象 */  
  45.     pDevExt = (PDEMOPCI_DEVICE_EXT)(functionalDeviceObject->DeviceExtension);  
  46.   
  47.     if(pDevExt != NULL)  
  48.     {  
  49.         /* 扩展设备对象初始化 */  
  50.         pDevExt->FunctionalDeviceObject  = functionalDeviceObject;  
  51.         pDevExt->PhysicalDeviceObject    = PhysicalDeviceObject;  
  52.         pDevExt->OutstandingIO       = 0;  
  53.         pDevExt->Started                 = FALSE;  
  54.         pDevExt->Removed             = FALSE;  
  55.         pDevExt->Removing            = FALSE;  
  56.         pDevExt->State               = STATE_NEVER_STARTED;  
  57.   
  58.                 /*内核事件初始化*/       
  59.         KeInitializeEvent(&pDevExt->RemoveEvent, NotificationEvent, FALSE);  
  60.   
  61.         for(i=0; i<PCI_TYPE0_ADDRESSES; i++)  
  62.         {  
  63.             pDevExt->base[i].WhichMapped = TYPE_NONE;  
  64.         }  
  65.   
  66.         RtlZeroMemory(&(pDevExt->CmnBuffSysPhyAddr), sizeof(pDevExt->CmnBuffSysPhyAddr));  
  67.         pDevExt->CmnBuffSize         = 0;  
  68.         pDevExt->CmnBuffSysVirAddr   = NULL;  
  69.         pDevExt->CmnBuffMdl          = NULL;  
  70.         pDevExt->CmnBuffUserAddr     = NULL;  
  71.           
  72.         pDevExt->pDmaIrp             = NULL;  
  73.   
  74.                 /*注册接口*/  
  75.         status = IoRegisterDeviceInterface(PhysicalDeviceObject, (LPGUID)&DEMOPCI_GUID, NULL, &pDevExt->ifname);  
  76.     }  
  77.     else  
  78.     {  
  79.         status=STATUS_UNSUCCESSFUL;  
  80.     }  
  81.   
  82.     if ( !NT_SUCCESS(status) )  
  83.     {  
  84.         /* 删除FDO */  
  85.         if(pDevExt->FunctionalDeviceObject != NULL)  
  86.             IoDeleteDevice(pDevExt->FunctionalDeviceObject);  
  87.         __leave;  
  88.     }  
  89.   
  90.     // Ask the I/O Manager to use describe user read/write buffers using MDLs  
  91.     functionalDeviceObject->Flags |= DO_DIRECT_IO;  
  92.   
  93.         /*将该设备对象挂载在设备栈上*/  
  94.     pDevExt->LowerDeviceObject = IoAttachDeviceToDeviceStack(  
  95.                                 functionalDeviceObject,  
  96.                                 PhysicalDeviceObject);  
  97.     if(pDevExt->LowerDeviceObject == NULL)  
  98.     {  
  99.         status=STATUS_NO_SUCH_DEVICE;  
  100.     }  
  101.   
  102.       
  103.     functionalDeviceObject->AlignmentRequirement = FILE_QUAD_ALIGNMENT; //8  
  104.     functionalDeviceObject->Flags &= (~DO_DEVICE_INITIALIZING);  
  105. }  
  106. __finally  
  107. {  
  108.     // If that didn't work...   
  109.     if ( !NT_SUCCESS(status) )   
  110.     {  
  111.         RtlFreeUnicodeString(&pDevExt->ifname);  
  112.         if(pDevExt->LowerDeviceObject != NULL)  
  113.             IoDetachDevice(pDevExt->LowerDeviceObject);  
  114.         if(pDevExt->FunctionalDeviceObject != NULL)  
  115.             IoDeleteDevice(pDevExt->FunctionalDeviceObject);  
  116.     }  
  117. }  
  118.   
  119.     DebugPrint("DemoPciAddDevice() End\n");  
  120.   
  121.     return (status);  
  122. }  
[cpp] view plain copy
print?
  1. NTSTATUS DemoPciAddDevice(  
  2.     IN PDRIVER_OBJECT DriverObject,  
  3.     IN PDEVICE_OBJECT PhysicalDeviceObject  
  4. )  
  5. {  
  6.     UCHAR           i;  
  7.     UNICODE_STRING      devname;  
  8.     ULONG           xsize;  
  9.     NTSTATUS        status = STATUS_SUCCESS;  
  10.     PTSTDPCI_DEVICE_EXT pDevExt = NULL;  
  11.     PDEVICE_OBJECT      functionalDeviceObject = NULL;  
  12.       
  13.     DebugPrint("DemoPciAddDevice() Start\n");  
  14.       
  15.     if( (DriverObject == NULL) || (PhysicalDeviceObject == NULL) )  
  16.         return (STATUS_NO_SUCH_DEVICE);  
  17.       
  18.         /*设备名*/  
  19.     RtlInitUnicodeString(&devname,TSTDPCI_DEVICE_NAME);  
  20.   
  21.         /*我们定义的扩展设备对象的大小*/  
  22.         xsize=( (sizeof(DEMOPCI_DEVICE_EXT) + 7) & (~7) );  
  23.   
  24.         /*创建设备对象*/  
  25.     status = IoCreateDevice( DriverObject,  
  26.                  xsize,  
  27.                  &devname,  
  28.                  FILE_DEVICE_DEMOPCI,  
  29.                  0,             //FILE_DEVICE_SECURE_OPEN,  
  30.                  FALSE,  
  31.                  &functionalDeviceObject  
  32.                     );  
  33.     if( !NT_SUCCESS(status) )  
  34.     {  
  35.         return (status);  
  36.     }  
  37.     if(functionalDeviceObject == NULL)  
  38.     {  
  39.         return (STATUS_UNSUCCESSFUL);  
  40.     }  
  41.       
  42. __try  
  43. {  
  44.     /* 获取扩展设备对象 */  
  45.     pDevExt = (PDEMOPCI_DEVICE_EXT)(functionalDeviceObject->DeviceExtension);  
  46.   
  47.     if(pDevExt != NULL)  
  48.     {  
  49.         /* 扩展设备对象初始化 */  
  50.         pDevExt->FunctionalDeviceObject  = functionalDeviceObject;  
  51.         pDevExt->PhysicalDeviceObject    = PhysicalDeviceObject;  
  52.         pDevExt->OutstandingIO       = 0;  
  53.         pDevExt->Started                 = FALSE;  
  54.         pDevExt->Removed             = FALSE;  
  55.         pDevExt->Removing            = FALSE;  
  56.         pDevExt->State               = STATE_NEVER_STARTED;  
  57.   
  58.                 /*内核事件初始化*/       
  59.         KeInitializeEvent(&pDevExt->RemoveEvent, NotificationEvent, FALSE);  
  60.   
  61.         for(i=0; i<PCI_TYPE0_ADDRESSES; i++)  
  62.         {  
  63.             pDevExt->base[i].WhichMapped = TYPE_NONE;  
  64.         }  
  65.   
  66.         RtlZeroMemory(&(pDevExt->CmnBuffSysPhyAddr), sizeof(pDevExt->CmnBuffSysPhyAddr));  
  67.         pDevExt->CmnBuffSize         = 0;  
  68.         pDevExt->CmnBuffSysVirAddr   = NULL;  
  69.         pDevExt->CmnBuffMdl          = NULL;  
  70.         pDevExt->CmnBuffUserAddr     = NULL;  
  71.           
  72.         pDevExt->pDmaIrp             = NULL;  
  73.   
  74.                 /*注册接口*/  
  75.         status = IoRegisterDeviceInterface(PhysicalDeviceObject, (LPGUID)&DEMOPCI_GUID, NULL, &pDevExt->ifname);  
  76.     }  
  77.     else  
  78.     {  
  79.         status=STATUS_UNSUCCESSFUL;  
  80.     }  
  81.   
  82.     if ( !NT_SUCCESS(status) )  
  83.     {  
  84.         /* 删除FDO */  
  85.         if(pDevExt->FunctionalDeviceObject != NULL)  
  86.             IoDeleteDevice(pDevExt->FunctionalDeviceObject);  
  87.         __leave;  
  88.     }  
  89.   
  90.     // Ask the I/O Manager to use describe user read/write buffers using MDLs  
  91.     functionalDeviceObject->Flags |= DO_DIRECT_IO;  
  92.   
  93.         /*将该设备对象挂载在设备栈上*/  
  94.     pDevExt->LowerDeviceObject = IoAttachDeviceToDeviceStack(  
  95.                                 functionalDeviceObject,  
  96.                                 PhysicalDeviceObject);  
  97.     if(pDevExt->LowerDeviceObject == NULL)  
  98.     {  
  99.         status=STATUS_NO_SUCH_DEVICE;  
  100.     }  
  101.   
  102.       
  103.     functionalDeviceObject->AlignmentRequirement = FILE_QUAD_ALIGNMENT; //8  
  104.     functionalDeviceObject->Flags &= (~DO_DEVICE_INITIALIZING);  
  105. }  
  106. __finally  
  107. {  
  108.     // If that didn't work...  
  109.     if ( !NT_SUCCESS(status) )   
  110.     {  
  111.         RtlFreeUnicodeString(&pDevExt->ifname);  
  112.         if(pDevExt->LowerDeviceObject != NULL)  
  113.             IoDetachDevice(pDevExt->LowerDeviceObject);  
  114.         if(pDevExt->FunctionalDeviceObject != NULL)  
  115.             IoDeleteDevice(pDevExt->FunctionalDeviceObject);  
  116.     }  
  117. }  
  118.   
  119.     DebugPrint("DemoPciAddDevice() End\n");  
  120.   
  121.     return (status);  
  122. }  


上述动作完成后,PnP管理器将向每一个设备(当然也包括我们的PCIe设备)发送一个带IRP_MN_START_DEVICE副功能请求码的PnP请求。驱动将执行DriverEntry中注册的派遣函数(DemoPciPnp)。下面我们来看看具体的代码做了哪些工作,此阶段我们只谈论IRP_MN_START_DEVICE请求的处理,其他请求的处理后面继续探讨。

[cpp] view plaincopyprint?
  1. NTSTATUS DemoPciPnp(PDEVICE_OBJECT DeviceObject, PIRP pIrp)  
  2. {  
  3.     PIO_STACK_LOCATION  pIrpStack;  
  4.     PDEMOPCI_DEVICE_EXT pDevExt;  
  5.     KEVENT                  eventWaitLowerDrivers;  
  6.     NTSTATUS                status = STATUS_SUCCESS;  
  7.       
  8.     DebugPrint("DemoPciPnp() Start\n");  
  9.   
  10.     pDevExt = (PDEMOPCI_DEVICE_EXT)(DeviceObject->DeviceExtension);  
  11.     /* 设置使用标志位 */  
  12.     if( DemoPciRequestIncrement(pDevExt) == 0 )  
  13.     {  
  14.         pIrp->IoStatus.Status = STATUS_DELETE_PENDING;  
  15.         pIrp->IoStatus.Information = 0;  
  16.         IoCompleteRequest(pIrp,IO_NO_INCREMENT);  
  17.         return (status);  
  18.     }  
  19.     /* 初始化事件 */  
  20.     KeInitializeEvent(&eventWaitLowerDrivers, NotificationEvent, FALSE);  
  21.       
  22.     pIrpStack = IoGetCurrentIrpStackLocation(pIrp);  
  23.       
  24.     switch( pIrpStack->MinorFunction )  
  25.     {  
  26.     case IRP_MN_START_DEVICE:   /* 当设备被检测到时,PnP管理器将发送该IRP请求 */  
  27.         DebugPrint("IRP_MN_START_DEVICE Start\n");  
  28.         /* 将当前IRP中IRP stack location 中的相关堆栈参数复制到下一层驱动的IRP stack location */  
  29.         IoCopyCurrentIrpStackLocationToNext( pIrp );  
  30.                 /*设置IRP完成例程*/  
  31.         IoSetCompletionRoutine( pIrp,  
  32.                              DemoPciPnpComplete,  
  33.                              &eventWaitLowerDrivers,  
  34.                              TRUE,  
  35.                              TRUE,  
  36.                              TRUE );  
  37.                 /*将该IRP转发给下层驱动,该例中的下层驱动对应着AddDevice函数挂载本设备对象的PDO*/  
  38.         status = IoCallDriver(pDevExt->LowerDeviceObject, pIrp);  
  39.         if (status == STATUS_PENDING)  
  40.         {  
  41.                         /*等待PDO完成该IRP请求*/  
  42.             KeWaitForSingleObject(  &eventWaitLowerDrivers,  
  43.                                 Executive,  
  44.                                 KernelMode,  
  45.                                 FALSE,  
  46.                                 NULL );  
  47.             status = pIrp->IoStatus.Status;  
  48.         }  
  49.         if ( NT_SUCCESS (status) )   
  50.         {  
  51.                         /*若设备成功响应该IRP,则开始启动设备*/  
  52.             status = DemoPciStartDevice(pDevExt, pIrpStack);  
  53.             if ( NT_SUCCESS(status) )   
  54.             {  
  55.                 pDevExt->State     = STATE_STARTED;  
  56.                 pDevExt->Started = TRUE;  
  57.             }  
  58.             IoSetDeviceInterfaceState(&pDevExt->ifname, TRUE);  
  59.         }  
  60.                 /*IRP完成*/  
  61.         pIrp->IoStatus.Status = status;                    
  62.         pIrp->IoStatus.Information = 0;  
  63.         IoCompleteRequest(pIrp, IO_NO_INCREMENT);  
  64.         DebugPrint("IRP_MN_START_DEVICE End\n");  
  65.         break;  
  66.     case IRP_MN_STOP_DEVICE:  
  67.             .....  
  68.                 .....  
  69.         break;  
  70.     case IRP_MN_REMOVE_DEVICE:  
  71.                 .....  
  72.                 .....  
  73.         break;  
  74.     case IRP_MN_QUERY_STOP_DEVICE:  
  75.                 .....  
  76.                 .....  
  77.         break;  
  78.     case IRP_MN_QUERY_REMOVE_DEVICE:  
  79.                 .....  
  80.                 .....  
  81.         break;  
  82.     case IRP_MN_SURPRISE_REMOVAL:  
  83.                 .....  
  84.                 .....  
  85.         break;  
  86.     case IRP_MN_CANCEL_STOP_DEVICE:  
  87.                 .....  
  88.                 .....  
  89.         break;  
  90.     case IRP_MN_CANCEL_REMOVE_DEVICE:  
  91.                 .....  
  92.                 .....  
  93.         break;  
  94.     default:  
  95.         .....  
  96.                 .....  
  97.         break;  
  98.     }  
  99.     /* 释放使用标志位 */  
  100.     DemoPciRequestDecrement(pDevExt);  
  101.       
  102.     DebugPrint("DemoPciPnp() End\n");  
  103.       
  104.     return(status);  
  105. }  
[cpp] view plain copy
print?
  1. NTSTATUS DemoPciPnp(PDEVICE_OBJECT DeviceObject, PIRP pIrp)  
  2. {  
  3.     PIO_STACK_LOCATION  pIrpStack;  
  4.     PDEMOPCI_DEVICE_EXT pDevExt;  
  5.     KEVENT                  eventWaitLowerDrivers;  
  6.     NTSTATUS                status = STATUS_SUCCESS;  
  7.       
  8.     DebugPrint("DemoPciPnp() Start\n");  
  9.   
  10.     pDevExt = (PDEMOPCI_DEVICE_EXT)(DeviceObject->DeviceExtension);  
  11.     /* 设置使用标志位 */  
  12.     if( DemoPciRequestIncrement(pDevExt) == 0 )  
  13.     {  
  14.         pIrp->IoStatus.Status = STATUS_DELETE_PENDING;  
  15.         pIrp->IoStatus.Information = 0;  
  16.         IoCompleteRequest(pIrp,IO_NO_INCREMENT);  
  17.         return (status);  
  18.     }  
  19.     /* 初始化事件 */  
  20.     KeInitializeEvent(&eventWaitLowerDrivers, NotificationEvent, FALSE);  
  21.       
  22.     pIrpStack = IoGetCurrentIrpStackLocation(pIrp);  
  23.       
  24.     switch( pIrpStack->MinorFunction )  
  25.     {  
  26.     case IRP_MN_START_DEVICE:   /* 当设备被检测到时,PnP管理器将发送该IRP请求 */  
  27.         DebugPrint("IRP_MN_START_DEVICE Start\n");  
  28.         /* 将当前IRP中IRP stack location 中的相关堆栈参数复制到下一层驱动的IRP stack location */  
  29.         IoCopyCurrentIrpStackLocationToNext( pIrp );  
  30.                 /*设置IRP完成例程*/  
  31.         IoSetCompletionRoutine( pIrp,  
  32.                              DemoPciPnpComplete,  
  33.                              &eventWaitLowerDrivers,  
  34.                              TRUE,  
  35.                              TRUE,  
  36.                              TRUE );  
  37.                 /*将该IRP转发给下层驱动,该例中的下层驱动对应着AddDevice函数挂载本设备对象的PDO*/  
  38.         status = IoCallDriver(pDevExt->LowerDeviceObject, pIrp);  
  39.         if (status == STATUS_PENDING)  
  40.         {  
  41.                         /*等待PDO完成该IRP请求*/  
  42.             KeWaitForSingleObject(  &eventWaitLowerDrivers,  
  43.                                 Executive,  
  44.                                 KernelMode,  
  45.                                 FALSE,  
  46.                                 NULL );  
  47.             status = pIrp->IoStatus.Status;  
  48.         }  
  49.         if ( NT_SUCCESS (status) )   
  50.         {  
  51.                         /*若设备成功响应该IRP,则开始启动设备*/  
  52.             status = DemoPciStartDevice(pDevExt, pIrpStack);  
  53.             if ( NT_SUCCESS(status) )   
  54.             {  
  55.                 pDevExt->State     = STATE_STARTED;  
  56.                 pDevExt->Started = TRUE;  
  57.             }  
  58.             IoSetDeviceInterfaceState(&pDevExt->ifname, TRUE);  
  59.         }  
  60.                 /*IRP完成*/  
  61.         pIrp->IoStatus.Status = status;                    
  62.         pIrp->IoStatus.Information = 0;  
  63.         IoCompleteRequest(pIrp, IO_NO_INCREMENT);  
  64.         DebugPrint("IRP_MN_START_DEVICE End\n");  
  65.         break;  
  66.     case IRP_MN_STOP_DEVICE:  
  67.             .....  
  68.                 .....  
  69.         break;  
  70.     case IRP_MN_REMOVE_DEVICE:  
  71.                 .....  
  72.                 .....  
  73.         break;  
  74.     case IRP_MN_QUERY_STOP_DEVICE:  
  75.                 .....  
  76.                 .....  
  77.         break;  
  78.     case IRP_MN_QUERY_REMOVE_DEVICE:  
  79.                 .....  
  80.                 .....  
  81.         break;  
  82.     case IRP_MN_SURPRISE_REMOVAL:  
  83.                 .....  
  84.                 .....  
  85.         break;  
  86.     case IRP_MN_CANCEL_STOP_DEVICE:  
  87.                 .....  
  88.                 .....  
  89.         break;  
  90.     case IRP_MN_CANCEL_REMOVE_DEVICE:  
  91.                 .....  
  92.                 .....  
  93.         break;  
  94.     default:  
  95.         .....  
  96.                 .....  
  97.         break;  
  98.     }  
  99.     /* 释放使用标志位 */  
  100.     DemoPciRequestDecrement(pDevExt);  
  101.       
  102.     DebugPrint("DemoPciPnp() End\n");  
  103.       
  104.     return(status);  
  105. }  


上述代码中我们看到:若设备成功响应了带IRP_MN_START_DEVICE的请求之后,将执行DemoPciStartDevice函数,该函数中我们将针对我们的具体设备做具体的资源分配,中断注册等工作。下面我们来仔细看看代码的具体实现。

[cpp] view plaincopyprint?
  1. NTSTATUS DemoPciStartDevice(IN PDEMOPCI_DEVICE_EXT pDevExt, IN PIO_STACK_LOCATION pIrpStack)  
  2. {  
  3.     int                                                     i;  
  4.     ULONG                                               index;  
  5.     ULONG                                               count;  
  6.     PCM_RESOURCE_LIST                           pResourceList, pResourceListTranslated;  
  7.     PCM_PARTIAL_RESOURCE_LIST               prl, prlTranslated;  
  8.     PCM_PARTIAL_RESOURCE_DESCRIPTOR prd, prdTranslated;  
  9.     PCM_FULL_RESOURCE_DESCRIPTOR        frd, frdTranslated;  
  10.     ULONG                                               NumCount;  
  11.     NTSTATUS                                        status = STATUS_SUCCESS;  
  12.     DEVICE_DESCRIPTION              DeviceDescription;  
  13.     INTERFACE_TYPE                      BusType;  
  14.     ULONG                               Junk;  
  15.       
  16.     PUCHAR  pBaseMem0, pBaseMem2;  
  17.     ULONG   value = 0;  
  18.     ULONG   iCnt = 0;  
  19.       
  20.       
  21.     DebugPrint("DemoPciStartDevice() Start\n");  
  22.   
  23.         /*获取设备已经分配的资源*/   
  24.     pResourceListTranslated = pIrpStack->Parameters.StartDevice.AllocatedResourcesTranslated;  
  25.     if( (pResourceListTranslated == NULL) || (pResourceListTranslated->Count == 0) )  
  26.     {  
  27.         return (STATUS_INSUFFICIENT_RESOURCES);  
  28.     }  
  29.     frdTranslated  = &pResourceListTranslated->List[0];  
  30.     prlTranslated  = &frdTranslated->PartialResourceList;  
  31.     prdTranslated = prlTranslated->PartialDescriptors;  
  32.     NumCount       = prlTranslated->Count;  
  33.     count = 0;  
  34.     for (index=0; index<NumCount ; prdTranslated++,index++ )  
  35.     {  
  36.         switch (prdTranslated->Type)  
  37.         {  
  38.                 /*I/O端口资源*/  
  39.         case CmResourceTypePort:  
  40.             pDevExt->base[count].IoPortSize              = prdTranslated->u.Port.Length;  
  41.             pDevExt->base[count].IoPortMappedAddress     = (PVOID)prdTranslated->u.Port.Start.LowPart;  
  42.             pDevExt->base[count].WhichMapped         = TYPE_IO;  
  43.             count++;  
  44.             break;  
  45.                 /*Memory资源*/  
  46.         case CmResourceTypeMemory:  
  47.             pDevExt->base[count].MemorySize              = prdTranslated->u.Memory.Length;  
  48.             pDevExt->base[count].MemoryRegisterAddress   = prdTranslated->u.Memory.Start;  
  49.             pDevExt->base[count].MemoryMappedAddress = MmMapIoSpace( prdTranslated->u.Memory.Start, prdTranslated->u.Memory.Length, MmNonCached);  
  50.             pDevExt->base[count].WhichMapped         = TYPE_MEM;  
  51.             count++;  
  52.             break;  
  53.                 /*中断资源*/  
  54.         case CmResourceTypeInterrupt:  
  55.             pDevExt->InterruptLevel  = (KIRQL)prdTranslated->u.Interrupt.Level;  
  56.             pDevExt->InterruptVector = prdTranslated->u.Interrupt.Vector;  
  57.             pDevExt->InterruptAffinity   = prdTranslated->u.Interrupt.Affinity;  
  58.             pDevExt->InterruptMode   = (prdTranslated->Flags == CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;  
  59.             pDevExt->InterruptShare  = (prdTranslated->ShareDisposition == CmResourceShareShared);  
  60.             pDevExt->InterruptSupport    = 1;  
  61.             DebugPrint("Interrupt Support\n");  
  62.             break;  
  63.                 /*DMA资源*/  
  64.         case CmResourceTypeDma:  
  65.             break;  
  66.                 /*总线资源*/  
  67.         case CmResourceTypeBusNumber:  
  68.             break;  
  69.         default:  
  70.             break;  
  71.         }  
  72.     }  
  73.     /* It is fails if there is no resource */  
  74.     if ( count == 0 )   
  75.     {  
  76.         return (STATUS_UNSUCCESSFUL);  
  77.     }  
  78.       
  79.     {  
  80.                 /*插槽编号*/  
  81.         PCI_SLOT_NUMBER slot_number;  
  82.         IoGetDeviceProperty( pDevExt->PhysicalDeviceObject,  DevicePropertyAddress,  sizeof(ULONG), &slot_number, &Junk);  
  83.         pDevExt->SlotNumber = (slot_number.u.AsULONG >> 16);  
  84.     }  
  85.       
  86.     {  
  87.                 /*总线编号*/  
  88.         PCI_SLOT_NUMBER slot_number;  
  89.         IoGetDeviceProperty( pDevExt->PhysicalDeviceObject,  DevicePropertyBusNumber, sizeof(ULONG), &slot_number, &Junk);  
  90.         pDevExt->BusNumber = (slot_number.u.AsULONG);  
  91.     }  
  92.       
  93.     {  
  94.                 /*DMA控制器*/  
  95.         // The device description is clear  
  96.         RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));  
  97.         // Get busType   
  98.         IoGetDeviceProperty( pDevExt->PhysicalDeviceObject, DevicePropertyLegacyBusType, sizeof(BusType), &BusType, &Junk);  
  99.         // initial value is set  
  100.         DeviceDescription.Version           = DEVICE_DESCRIPTION_VERSION;  
  101.         DeviceDescription.Master            = TRUE;  
  102.         DeviceDescription.ScatterGather     = FALSE;  
  103.         DeviceDescription.Dma32BitAddresses = TRUE;  
  104.         DeviceDescription.InterfaceType     = BusType;  
  105.         DeviceDescription.MaximumLength = MAX_TRANSFER_SIZE;  
  106.         // Get DMA Adapter   
  107.         pDevExt->DmaAdapter = IoGetDmaAdapter( pDevExt->PhysicalDeviceObject, &DeviceDescription, &pDevExt->DmaMapRegsGot);  
  108.         if( pDevExt->DmaAdapter == NULL )  
  109.         {  
  110.             return((NTSTATUS)STATUS_UNSUCCESSFUL);  
  111.         }  
  112.         DebugPrint("DmaAdapter=%x MapRegs=%x\n",pDevExt->DmaAdapter,pDevExt->DmaMapRegsGot);  
  113.     }  
  114.       
  115.     /*本例中我们只使用了两个BAR*/  
  116.     pBaseMem0 = (PUCHAR)(pDevExt->base[0].MemoryMappedAddress);  
  117.     pBaseMem2 = (PUCHAR)(pDevExt->base[2].MemoryMappedAddress);  
  118.       
  119.         /*本设备我们使用了4124芯片作为PCI芯片,访问前需设置以下两个寄存器*/  
  120.     WRITE_REGISTER_ULONG( (PULONG)(pBaseMem2 + 0x808), 0x1F03C);  
  121.     WRITE_REGISTER_ULONG( (PULONG)(pBaseMem2 + 0x800), 0x25000);      
  122.   
  123.     do  
  124.     {  
  125.         value = READ_REGISTER_ULONG( (PULONG)(pBaseMem2 + 0x808));  
  126.         if ((value & 0xE0000000) == 0xE0000000)  
  127.         {  
  128.             break;  
  129.         }  
  130.         iCnt++;  
  131.     }while (iCnt < 10000000);  
  132.     DebugPrint("[0x808] = 0x%08X! \n", value);  
  133.     if (iCnt == 10000000)  
  134.     {  
  135.         DebugPrint("*************** Clock unlock! \n");  
  136.     }  
  137.   
  138.     if(pDevExt->InterruptSupport != 0)  
  139.     {  
  140.   
  141.         /*设置DPC*/  
  142.         IoInitializeDpcRequest(pDevExt->FunctionalDeviceObject, DpcForIsr);  
  143.           
  144.   
  145.           
  146.         /*注册中断处理程序*/  
  147.         status = IoConnectInterrupt(   &pDevExt->InterruptObject,        //. Interrupt object pointer  
  148.                                 (PKSERVICE_ROUTINE)InterruptHandler,    //. Interrupt processing routine name  
  149.                                 pDevExt,                                //. Context passed to interrupt handler  
  150.                                 NULL,                                   //. Spinlock  
  151.                                 pDevExt->InterruptVector,                //. Interrupt vector  
  152.                                 pDevExt->InterruptLevel,                 //. Interrupt IRQL  
  153.                                 pDevExt->InterruptLevel,                 //. Most significant IRQL  
  154.                                 pDevExt->InterruptMode,                  //. Levelsensitive value or latched value  
  155.                                 pDevExt->InterruptShare,             //. Interrupt share  
  156.                                 pDevExt->InterruptAffinity,          //. Interrupt affinity  
  157.                                 FALSE  );                               //. x86 case FALSE  
  158.         if( !NT_SUCCESS(status) )  
  159.         {  
  160.             return(status);  
  161.         }  
  162.           
  163.     }  
  164.       
  165.   
  166.       
  167.     DebugPrint("DemoPciStartDevice() End\n");  
  168.       
  169.     return (STATUS_SUCCESS);  
  170. }  
[cpp] view plain copy
print?
  1. NTSTATUS DemoPciStartDevice(IN PDEMOPCI_DEVICE_EXT pDevExt, IN PIO_STACK_LOCATION pIrpStack)  
  2. {  
  3.     int                                                     i;  
  4.     ULONG                                               index;  
  5.     ULONG                                               count;  
  6.     PCM_RESOURCE_LIST                           pResourceList, pResourceListTranslated;  
  7.     PCM_PARTIAL_RESOURCE_LIST               prl, prlTranslated;  
  8.     PCM_PARTIAL_RESOURCE_DESCRIPTOR prd, prdTranslated;  
  9.     PCM_FULL_RESOURCE_DESCRIPTOR        frd, frdTranslated;  
  10.     ULONG                                               NumCount;  
  11.     NTSTATUS                                        status = STATUS_SUCCESS;  
  12.     DEVICE_DESCRIPTION              DeviceDescription;  
  13.     INTERFACE_TYPE                      BusType;  
  14.     ULONG                               Junk;  
  15.       
  16.     PUCHAR  pBaseMem0, pBaseMem2;  
  17.     ULONG   value = 0;  
  18.     ULONG   iCnt = 0;  
  19.       
  20.       
  21.     DebugPrint("DemoPciStartDevice() Start\n");  
  22.   
  23.         /*获取设备已经分配的资源*/   
  24.     pResourceListTranslated = pIrpStack->Parameters.StartDevice.AllocatedResourcesTranslated;  
  25.     if( (pResourceListTranslated == NULL) || (pResourceListTranslated->Count == 0) )  
  26.     {  
  27.         return (STATUS_INSUFFICIENT_RESOURCES);  
  28.     }  
  29.     frdTranslated  = &pResourceListTranslated->List[0];  
  30.     prlTranslated  = &frdTranslated->PartialResourceList;  
  31.     prdTranslated = prlTranslated->PartialDescriptors;  
  32.     NumCount       = prlTranslated->Count;  
  33.     count = 0;  
  34.     for (index=0; index<NumCount ; prdTranslated++,index++ )  
  35.     {  
  36.         switch (prdTranslated->Type)  
  37.         {  
  38.                 /*I/O端口资源*/  
  39.         case CmResourceTypePort:  
  40.             pDevExt->base[count].IoPortSize              = prdTranslated->u.Port.Length;  
  41.             pDevExt->base[count].IoPortMappedAddress     = (PVOID)prdTranslated->u.Port.Start.LowPart;  
  42.             pDevExt->base[count].WhichMapped         = TYPE_IO;  
  43.             count++;  
  44.             break;  
  45.                 /*Memory资源*/  
  46.         case CmResourceTypeMemory:  
  47.             pDevExt->base[count].MemorySize              = prdTranslated->u.Memory.Length;  
  48.             pDevExt->base[count].MemoryRegisterAddress   = prdTranslated->u.Memory.Start;  
  49.             pDevExt->base[count].MemoryMappedAddress = MmMapIoSpace( prdTranslated->u.Memory.Start, prdTranslated->u.Memory.Length, MmNonCached);  
  50.             pDevExt->base[count].WhichMapped         = TYPE_MEM;  
  51.             count++;  
  52.             break;  
  53.                 /*中断资源*/  
  54.         case CmResourceTypeInterrupt:  
  55.             pDevExt->InterruptLevel  = (KIRQL)prdTranslated->u.Interrupt.Level;  
  56.             pDevExt->InterruptVector = prdTranslated->u.Interrupt.Vector;  
  57.             pDevExt->InterruptAffinity   = prdTranslated->u.Interrupt.Affinity;  
  58.             pDevExt->InterruptMode   = (prdTranslated->Flags == CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;  
  59.             pDevExt->InterruptShare  = (prdTranslated->ShareDisposition == CmResourceShareShared);  
  60.             pDevExt->InterruptSupport    = 1;  
  61.             DebugPrint("Interrupt Support\n");  
  62.             break;  
  63.                 /*DMA资源*/  
  64.         case CmResourceTypeDma:  
  65.             break;  
  66.                 /*总线资源*/  
  67.         case CmResourceTypeBusNumber:  
  68.             break;  
  69.         default:  
  70.             break;  
  71.         }  
  72.     }  
  73.     /* It is fails if there is no resource */  
  74.     if ( count == 0 )   
  75.     {  
  76.         return (STATUS_UNSUCCESSFUL);  
  77.     }  
  78.       
  79.     {  
  80.                 /*插槽编号*/  
  81.         PCI_SLOT_NUMBER slot_number;  
  82.         IoGetDeviceProperty( pDevExt->PhysicalDeviceObject,  DevicePropertyAddress,  sizeof(ULONG), &slot_number, &Junk);  
  83.         pDevExt->SlotNumber = (slot_number.u.AsULONG >> 16);  
  84.     }  
  85.       
  86.     {  
  87.                 /*总线编号*/  
  88.         PCI_SLOT_NUMBER slot_number;  
  89.         IoGetDeviceProperty( pDevExt->PhysicalDeviceObject,  DevicePropertyBusNumber, sizeof(ULONG), &slot_number, &Junk);  
  90.         pDevExt->BusNumber = (slot_number.u.AsULONG);  
  91.     }  
  92.       
  93.     {  
  94.                 /*DMA控制器*/  
  95.         // The device description is clear  
  96.         RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));  
  97.         // Get busType  
  98.         IoGetDeviceProperty( pDevExt->PhysicalDeviceObject, DevicePropertyLegacyBusType, sizeof(BusType), &BusType, &Junk);  
  99.         // initial value is set  
  100.         DeviceDescription.Version           = DEVICE_DESCRIPTION_VERSION;  
  101.         DeviceDescription.Master            = TRUE;  
  102.         DeviceDescription.ScatterGather     = FALSE;  
  103.         DeviceDescription.Dma32BitAddresses = TRUE;  
  104.         DeviceDescription.InterfaceType     = BusType;  
  105.         DeviceDescription.MaximumLength = MAX_TRANSFER_SIZE;  
  106.         // Get DMA Adapter  
  107.         pDevExt->DmaAdapter = IoGetDmaAdapter( pDevExt->PhysicalDeviceObject, &DeviceDescription, &pDevExt->DmaMapRegsGot);  
  108.         if( pDevExt->DmaAdapter == NULL )  
  109.         {  
  110.             return((NTSTATUS)STATUS_UNSUCCESSFUL);  
  111.         }  
  112.         DebugPrint("DmaAdapter=%x MapRegs=%x\n",pDevExt->DmaAdapter,pDevExt->DmaMapRegsGot);  
  113.     }  
  114.       
  115.     /*本例中我们只使用了两个BAR*/  
  116.     pBaseMem0 = (PUCHAR)(pDevExt->base[0].MemoryMappedAddress);  
  117.     pBaseMem2 = (PUCHAR)(pDevExt->base[2].MemoryMappedAddress);  
  118.       
  119.         /*本设备我们使用了4124芯片作为PCI芯片,访问前需设置以下两个寄存器*/  
  120.     WRITE_REGISTER_ULONG( (PULONG)(pBaseMem2 + 0x808), 0x1F03C);  
  121.     WRITE_REGISTER_ULONG( (PULONG)(pBaseMem2 + 0x800), 0x25000);      
  122.   
  123.     do  
  124.     {  
  125.         value = READ_REGISTER_ULONG( (PULONG)(pBaseMem2 + 0x808));  
  126.         if ((value & 0xE0000000) == 0xE0000000)  
  127.         {  
  128.             break;  
  129.         }  
  130.         iCnt++;  
  131.     }while (iCnt < 10000000);  
  132.     DebugPrint("[0x808] = 0x%08X! \n", value);  
  133.     if (iCnt == 10000000)  
  134.     {  
  135.         DebugPrint("*************** Clock unlock! \n");  
  136.     }  
  137.   
  138.     if(pDevExt->InterruptSupport != 0)  
  139.     {  
  140.   
  141.         /*设置DPC*/  
  142.         IoInitializeDpcRequest(pDevExt->FunctionalDeviceObject, DpcForIsr);  
  143.           
  144.   
  145.           
  146.         /*注册中断处理程序*/  
  147.         status = IoConnectInterrupt(   &pDevExt->InterruptObject,        //. Interrupt object pointer  
  148.                                 (PKSERVICE_ROUTINE)InterruptHandler,    //. Interrupt processing routine name  
  149.                                 pDevExt,                                //. Context passed to interrupt handler  
  150.                                 NULL,                                   //. Spinlock  
  151.                                 pDevExt->InterruptVector,                //. Interrupt vector  
  152.                                 pDevExt->InterruptLevel,                 //. Interrupt IRQL  
  153.                                 pDevExt->InterruptLevel,                 //. Most significant IRQL  
  154.                                 pDevExt->InterruptMode,                  //. Levelsensitive value or latched value  
  155.                                 pDevExt->InterruptShare,             //. Interrupt share  
  156.                                 pDevExt->InterruptAffinity,          //. Interrupt affinity  
  157.                                 FALSE  );                               //. x86 case FALSE  
  158.         if( !NT_SUCCESS(status) )  
  159.         {  
  160.             return(status);  
  161.         }  
  162.           
  163.     }  
  164.       
  165.   
  166.       
  167.     DebugPrint("DemoPciStartDevice() End\n");  
  168.       
  169.     return (STATUS_SUCCESS);  
  170. }  

原创粉丝点击