可扩展主机控制器 (xHC) 具有周期性传输环。 Windows 对这个环进行编程,以在每次经过以毫秒为单位的间隔时触发传输。正确的间隔在 USB 设备返回的 USB 描述符中指定。当传输发生时,xHC 将传输事件 TRB 放在事件环上并触发 MSI-X 中断,该中断作为某种处理器间中断绕过 IOAPIC。如果 Windows 检测到按下的键发生了一些变化,它将向当前具有焦点的应用程序(调用窗口的过程)发送一条消息,其中一个参数中按下了键。
我不了解电信号,但我知道可扩展主机控制器是负责与现代 Windows 系统上的 USB 交互的 USB 控制器。由于现在的 Windows 需要 x64 处理器,因此 xHC 必须存在于您的主板上。 xHC 是符合 PCI-Express 规范的 PCI-Express 设备。
要查找 xHC,您:
- 在 RAM 中查找 RSDP ACPI 表;
此表将由 UEFI 固件找到,该固件在计算机启动期间充当某种小型操作系统 (OS)。然后,操作系统开发人员将编写一个名为 bootx64.efi 的小型 UEFI 应用程序,并将其放置在硬盘上的 FAT32 分区上。他们会将这个应用程序放在 /boot/efi 目录中。 UEFI 固件将在计算机启动时直接启动该应用程序,这允许启动不需要用户输入的操作系统(类似于它过去使用传统 BIOS 获取硬盘第一个扇区的方式并执行那里的指令)。
实际使用 EDK2 或 gnu-efi 编译 UEFI 应用程序。这些编译器了解 UEFI 环境和规范。因此,他们将代码编译为系统调用,这些系统调用在引导期间存在并且可用于操作系统开发人员编写的 UEFI 应用程序。系统表(通常是 ACPI 表)作为参数提供给 UEFI 应用程序中的 UEFI 固件调用的“主”函数(通常称为 UefiMain)。因此,应用程序的代码可以简单地使用这些参数来查找 RSDP 表并将其传递给操作系统。
- 使用 RSDP 查找 MCFG ACPI 表;
表链是 RSDP -> XSDT -> MCFG。一旦操作系统找到了 MCFG,这个表就指定了 PCI 配置空间的基地址。要与 PCI 设备交互,您使用内存映射 IO (MMIO)。您写入 RAM 中的某个位置,它将改为写入 PCI 设备的寄存器。因此,MCFG 指定了您将开始为插入计算机的不同 PCI 设备查找 MMIO 寄存器的基地址。
- 迭代 PCI 设备并查看它们的 ID,直到找到 xHC。
为了在 PCI 设备上进行迭代,PCI 约定指定了如下公式:
UINT64 physical_address = base_address + ((bus - first_bus) << 20 | device << 15 | function << 12);
base_address 用于特定的段组。每个段组可以有 256 条总线(适用于大型服务器或具有大量组件的大型计算机)。最多可以有 65536 个段组,每个段组最多可以有 256 条 PCI 总线。每条 PCI 总线最多可以插入 32 个设备,每个设备最多可以有 8 个功能。每个功能也可以是一个 PCI 桥。这很容易理解,因为术语很清楚。这里的总线是 PCI 设备(如网卡、显卡、xHC、AHCI 等)用来与 RAM 通信的实际串行总线。该功能是 PCI 设备的功能,例如控制 USB 设备、硬盘、HDMI 屏幕(用于显卡)等。PCI 桥将 PCI 总线桥接到另一条 PCI 总线。这意味着您可以拥有几乎无限数量的符合 PCI 规范的设备,因为桥接器允许通过添加其他 PCI 主机控制器来扩展设备树。
同时,总线只是一个介于 0 和 255 之间的数字。第一条总线在 MCFG ACPI 表中为特定的段组指定。设备是 0 到 31 之间的数字,函数是 0 到 7 之间的数字。此公式返回一个物理地址,该地址指向具有特定寄存器的常规配置空间(所有函数都相同)。这些寄存器用于确定设备的类型并为其加载适当的驱动程序。每个设备的每个功能都因此得到一个配置空间。
对于 xHC,将只有一个函数,其配置空间返回的 ID 将是类 ID 的 0x0C 和子类 ID (https://wiki.osdev.org/EXtensible_Host_Controller_Interface) 的 0x03。
一旦找到 xHC,它就会变得相当复杂。您需要对其进行初始化并获取当前插入计算机的USB设备。您需要采取几个步骤才能使 xHC 正常运行。对于这一部分,我将留给您阅读 xHCI 规范,该规范(在第 4 章中)详细说明了需要采取的步骤 (https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf)。
对于键盘部分,我会让您阅读我在计算机科学 stackexchange 上的一个答案:https://cs.stackexchange.com/questions/141870/when-are-a-controllers-registers-loaded-and-ready-to-inform-an-i-o-operation/141918#141918。
一些不错的链接:
https://wiki.osdev.org/Universal_Serial_Bus
https://wiki.osdev.org/PCI