首页 >> 编程开发 >> 其他 >> 正文

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  }