2011年4月24日

NetBSDのUSBホストコントローラのドライバIF

NetBSDカーネル内部の話になります。

NetBSDのUSB(ホスト)ドライバでは各種ホストコントローラ(以下、HC)とUSBプロトコルドライバ間でIFが切られています。上位のプロトコルドライバからはHC種別(ehci, ohci, uhci)は意識せず、このIF関数をコールすることでホストコントローラを制御しています。今回、このIF形式と各IF関数で行う処理内容に関して簡単にまとめます。

なお今回、NetBSD-5.1を対象に記載しています。NetBSDでUSBホストドライバがサポートされてからIFは大きく変わっていません。

インタフェース形式
HCドライバのIFは、usbd_bus_methods構造体とusbd_pipe_methds構造体で宣言されています。本構造体は dev/usb/usbdivar.h で型宣言されており以下のような構造になります。



struct usbd_bus_methods {
    usbd_status         (*open_pipe)(struct usbd_pipe *pipe);
    void                (*soft_intr)(void *);
    void                (*do_poll)(struct usbd_bus *);
    usbd_status         (*allocm)(struct usbd_bus *, usb_dma_t *, u_int32_t bufsize);
    void                (*freem)(struct usbd_bus *, usb_dma_t *);
    struct usbd_xfer *  (*allocx)(struct usbd_bus *);
    void                (*freex)(struct usbd_bus *, struct usbd_xfer *);
};

struct usbd_pipe_methods {
    usbd_status      (*transfer)(usbd_xfer_handle xfer);
    usbd_status      (*start)(usbd_xfer_handle xfer);
    void              (*abort)(usbd_xfer_handle xfer);
    void              (*close)(usbd_pipe_handle pipe);
    void              (*cleartoggle)(usbd_pipe_handle pipe);
    void              (*done)(usbd_xfer_handle xfer);
};

構造体名から想像できますが、usbd_bus_methodsはHCに紐付けられたHCとして行うべき関数をまとめた構造体です。一方usbd_pipe_methodsはUSBの転送パイプ(コントロール転送とかバルク転送)として行うべき関数をまとめた構造体になります。

各関数で行うべき処理に関して、以下に記載します。

open_pipe
  USB転送パイプのオープンを行います。上位で転送パイプを用いてデータ転送する場合にはまず本IFで転送パイプの初期化処理を行います。HCごとに転送パイプの取扱いおよび必要なデータ構造が異なるため本IFが用意されています。また本関数内部でUSB転送パイプとusbd_pipe_methodsの紐付けを行います。

soft_intr
  割り込み処理を行う関数です。NetBSDのUSBホストドライバではUSB関連の割り込み処理はハード割り込みのコンテキストではなく、ソフト割り込みのコンテキストで実行することが設計ポリシーとなっており、ソフト割り込み実行時にも本関数が実行されます。各HCドライバ内での動きとしては、ハード割り込みが発生した際にソフト割り込みのスケジューリングを行い、そのソフト割り込み内で割り込み処理を行う流れになります。

do_poll
  割り込をソフト側でポーリングするためのIFです。割り込み禁止状態でハードからのイベント(=割り込み)待ちが必要となるような場合に利用するIFです。

allocm
  HCに渡す送受信用データ領域のメモリ確保を行う際のIFです。メモリ領域確保自体はHCに依存する部分は少なくNetBSD-5.1でも各HCでほとんど共通の処理を行っています。(HCによって送受信データのアライメントがある場合や特殊制御が必要な場合には本IFが意味を持ちます。)

freem
  allocmで確保したメモリ領域を解放する際のIFです。

allocx
  USB転送(usbd_xfer)を確保する際のIFです。HCでは転送単位で必要となる処理が多いたえめ、本IFは(allocmと異なり)HCごとに大きく異なるため、各HCごとに必要なデータ領域の確保等を行います。

freex
  allocxで確保したUSB転送データ構造を解放する際のIFです。

transfer
  上位USBプロトコルドライバからUSB転送を開始する際のIFです。

start
  実際にHCに対してUSB転送を行う際のIFです。上記transferとstartの差異について説明しますが、NetBSDのUSBドライバの作りとしてUSB転送はパイプごとにキューイングする作りになっています。transfer()はこのキューにデータをエンキューするためのIFで、start()はキューのデータを実際に転送するIFです。またNetBSDのUSBドライバはデータ転送が終了した際にコールバック内でstart()を実行することで次の転送を開始するような作りにもなっています。

abort
  転送中のUSB転送を中止する際のIFです。

close
  open_pipe()でオープンしたパイプをクローズするIFです。

cleartoggle
  USBプロトコルで定められているトグルをクリアするIFです。トグルの制御方法はHCごとに異なっておりHC(ハード)が完全制御するもののありますが、ソフト側で制御が必要なものもあるため本IFが存在します。

以上。

0 件のコメント: