reactos操作系统实现(73)

即插即用(Plug and Play,PnP)是计算机系统I/O设备与部件配置的应用技术。PnP就是指插入就可以使用,不需要进行任何的硬件配置。其实还是需要安装相应的驱动程序才可以使用的。随着人们对计算机使用多样化,不断地需要添加各种各样的硬件卡到计算机的主板上,这样就需要配置硬件卡的中断、I/O所占用的资源,才能正常工作。这个过程是非常复杂的,经常需要手工配置,还需要查看计算机那里中断是空闲的,那些I/O端口是没有占用的。使用PnP技术以后,只需要操作系统做统一分配就行了。下面就来分析PnP初始化的实现代码:

#001  VOID INIT_FUNCTION

#002  PnpInit(VOID)

#003  {

#004      PDEVICE_OBJECT Pdo;

#005      NTSTATUS Status;

#006 

#007      DPRINT("PnpInit()/n");

#008 

 

初始化IO设备树锁。

#009      KeInitializeSpinLock(&IopDeviceTreeLock);

#010 

 

分配总线类型的GUID列表。

#011      /* Initialize the Bus Type GUID List */

#012      IopBusTypeGuidList = ExAllocatePool(PagedPool, sizeof(IO_BUS_TYPE_GUID_LIST));

#013      if (!IopBusTypeGuidList) {

#014       DPRINT1("ExAllocatePool() failed/n");

#015       KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 0, 0, 0);

#016      }

#017 

#018      RtlZeroMemory(IopBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST));

#019      ExInitializeFastMutex(&IopBusTypeGuidList->Lock);

#020 

 

初始化即插即用的事件通知支持。

#021      /* Initialize PnP-Event notification support */

#022      Status = IopInitPlugPlayEvents();

#023      if (!NT_SUCCESS(Status))

#024      {

#025          DPRINT1("IopInitPlugPlayEvents() failed/n");

#026          KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);

#027      }

#028 

 

创建一个根设备驱动程序节点,保存在IopRootDriverObject里面。

#029      /*

#030      * Create root device node

#031      */

#032 

#033      Status = IopCreateDriver(NULL, PnpDriverInitializeEmpty, NULL, 0, 0, &IopRootDriverObject);

#034      if (!NT_SUCCESS(Status))

#035      {

#036          DPRINT1("IoCreateDriverObject() failed/n");

#037          KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);

#038      }

#039 

 

 

创建一个文件设备控制器对象保存到根驱动程序节点里。

#040      Status = IoCreateDevice(IopRootDriverObject, 0, NULL, FILE_DEVICE_CONTROLLER,

#041          0, FALSE, &Pdo);

#042      if (!NT_SUCCESS(Status))

#043      {

#044          DPRINT1("IoCreateDevice() failed/n");

#045          KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);

#046      }

#047 

 

创建一个文件设备控制器对象节点。

#048      Status = IopCreateDeviceNode(NULL, Pdo, NULL, &IopRootDeviceNode);

#049      if (!NT_SUCCESS(Status))

#050      {

#051          DPRINT1("Insufficient resources/n");

#052          KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);

#053      }

#054 

 

设置这个文件设备节点名称为HTREE//ROOT//

#055      if (!RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath,

#056          L"HTREE//ROOT//0"))

#057      {

#058          DPRINT1("Failed to create the instance path!/n");

#059          KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 0, 0, 0);

#060      }

#061 

 

报告这个设备到用户模式的PNP管理器。

#062      /* Report the device to the user-mode pnp manager */

#063      IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,

#064          &IopRootDeviceNode->InstancePath);

#065 

#066      IopRootDeviceNode->PhysicalDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;

#067      PnpRootDriverEntry(IopRootDriverObject, NULL);

#068      IopRootDeviceNode->PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

#069      IopRootDriverObject->DriverExtension->AddDevice(

#070          IopRootDriverObject,

#071          IopRootDeviceNode->PhysicalDeviceObject);

#072 

 

下面开始把Freeloader检测到的硬件信息移到注册表SYSTEM/CurrentControlSet/Root/键里。

#073      /* Move information about devices detected by Freeloader to SYSTEM/CurrentControlSet/Root/ */

#074      Status = IopUpdateRootKey();

#075      if (!NT_SUCCESS(Status))

#076      {

#077          DPRINT1("IopUpdateRootKey() failed/n");

#078          KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);

#079      }

#080  }

你可能感兴趣的:(react)