Skip to content
uchan-nos edited this page Aug 6, 2017 · 40 revisions

USB のホスト側の制御(特に xHCI)についてのメモ書き

2017/08/05 by uchan

USB 制御の概要

USB を制御するには、いくつかの層のドライバを書く必要がある。

  • USB クラスドライバ:例えば HID(キーボードやマウス)とか、Web カメラとか用のドライバ
  • USB ドライバ:USB 規格で規定された、データのやり取りとかを実装する部分
  • ホストコントローラドライバ:xHCI など、ホストコントローラを制御する部分
  • PCI ドライバ:ホストコントローラは PCI バスに繋がることが前提になっているので、PCI ドライバも必要

USB 規格はあくまでもデータのやり取りの形式(フレームの構造、USB 機器とやり取りする際のプロトコルなど)を規定している。 USB 規格と物理層をつなぐのがホストコントローラで、これは USB 規格とは別物。

ホストコントローラ規格には幾つか種類がある:UHCI, OHCI, EHCI, xHCI

資料リンク

xHCI のレジスタ

xHCI のレジスタは大きく 2 箇所に存在する。

  • PCI コンフィギュレーション空間のレジスタ:MMIO 空間のスタートアドレスを設定する BAR を含む。
  • MMIO 空間のレジスタ:こちらがメイン。USB 機器に送るデータをためるキューなどはこちらにある。

PCI コンフィギュレーション空間の BAR で MMIO 空間のアドレスを設定し、後は MMIO 空間のレジスタでいろいろ制御する感じになる。

MMIO 空間

"xHCI for Universal Serial Bus: Specification"(以降 "xHCI Spec" と書く)5.3 節によれば、規格書に出てくる MMIO レジスタは、すべて MMIO 空間の先頭を基準に配置されているらしい。規格書の中では一貫して MMIO 空間の先頭のことを Base と呼んでいる。

MMIO 空間の先頭(Base offset 00h)には xHCI Capability Registers が配置されている。 Capability Registers の直後から Operational Registers が続く。

Device Slot 関連の用語

xHCI 規格書の 1.6 "Terms and Abbreviations" 参照。

  • Device Slot
    • "Device Slot" は個々の USB デバイスに紐づけられた xHC のインターフェース(DCBAA の 1 つのエントリ、1 つの Doorbell Array レジスタ、1 つの Device Context)を意味する。
  • Device Context Base Address Array (DCBAA)
    • 1 つの Device Slot を 1 つの Device Context データ構造と紐づけるもの。
    • DCBAA の場所は Operational Registers の DCBAAP から指される。
    • DCBAA は MaxSlotsEn + 1 個のエントリを持つ配列(となるようにプログラマがメモリを用意する)。
  • Device Context
    • 個々の USB デバイスを記述するデータ構造。
    • 1 つの Device Context はコンテキストデータ構造の配列。1 つの Slot Context と 31 個以下の Endpoint Context を持つ。

xHC の初期化

xHCI 規格書の 4.2 "Host Controller Initialization" にいろいろ書いてあるが、UEFI が良い感じに初期化してくれているはず。 したがって、USBCMD レジスタの Run/Stop ビットを 1 にするだけでコントローラの初期化は完了する。

この後、接続されているデバイスの列挙とそれぞれのデバイスの初期化を行う。 やはり、電源投入時から接続されている USB デバイスについては UEFI が初期化してくれているので、やるべき作業はとても少ない。 これは UEFI の実装に依るかもしれないが、UEFI の OSS 実装である OVMF(を載せた QEMU)では、USB デバイスの一般的な初期化は完了した状態で OS に処理が渡ってくる。

QEMU に -device usb-kbd を指定すると PS/2 キーボードの代わりに USB キーボードが接続される。 OS に処理が渡った時点でこの USB キーボードは状態 "Configured" になっており、USB デバイスアドレスやいくつかのエンドポイントなどが設定済みだ。 ただ、USB キーボードから PC 方向のエンドポイントが Disabled になっているようなので、Configure Endpoint コマンドを発行する必要がある。

Command Ring

xHC に対するコマンドの発行は Command Ring というキューにより行う。 Command Ring にコマンドを積み、xHC にコマンド発行の合図を送ると xHC がコマンドを読み取って動作する。 OS が「プロデューサ」、xHC が「コンシューマ」の役目である。

Command Ring は 1 つの xHC インスタンスにつき 1 つだけ存在する。 Command Ring は TRB(Transfer Request Block)というデータ構造をやり取りするためのキューだ。 TRB にはいくつも種類があるが、Command Ring で処理できる TRB の種類は限られている。

Command Ring にコマンドを発行するやり方:

  1. 1 つ以上の Command Descriptor(Command TRB の別名)を Command Ring に配置する。
  2. Host Controller Doorbell を鳴らす。

Event Ring

コマンドに対する結果などが通知されるキュー。 xHCI 規格書 4.9.4 Figure 19: Segmented Event Ring Example

Interrupter 毎に Event Ring が用意されている。 0 番目の Interrupter(Interrupter 0)に対する Event Ring を "Primary Event Ring"、その他の Interrupter に対するものを "Secondary Event Ring" と呼ぶ。

各 Interrupter は Interrupter Register Set というレジスタセットを持っていて、その中の ERSTBA、ERDP がそれぞれ Event Ring のベースアドレス、Event Ring の読み出しポインタを示す。 Interrupter Register Set は Runtime Registers(Capability Registers の RTSOFF でオフセットを取得できる)に存在する。 Interrupter 0 のための Interrupter Register Set 0 は、Runtime Registers の 0x0020h にある。

各 Event Ring は実際にはいくつものセグメント(Event Ring Segment)からなる。 各セグメントのベースアドレスとサイズ(Event Ring Segment に格納できる TRB の数)は、Event Ring Segment Table(ERST)に設定されている。 ERST がどこにあるかは、Event Ring Segment Table Base Address(ERSTBA、上述)レジスタに設定されている。

TRB のためのキューは 3 種類ある。Transfer Ring、Command Ring、Event Ring。

Clone this wiki locally