Linux Kernel 2.6 Documentation:
/usr/src/linux/Documentation/eisa.txt
eisa.txt
EISA バスサポート
[プレインテキスト版]
- 原著作者: Marc Zyngier <maz@wild-wind.fr.eu.org>
- 翻訳者: 川崎 貴彦 <takahiko(a)hakubi.co.jp>
- バージョン: 2.6.6
- 翻訳日時: 2004/05/23
EISA バスサポート
Marc Zyngier <maz@wild-wind.fr.eu.org>
この文書群は、新しい EISA/sysfs API への EISA ドライバ移植に関するラン
ダムノートです。
バージョン 2.5.59 以降、EISA バスは、PCI や USB といった、もっと主流で
ある他のバスとほぼ同じ状況となっています。この状況は、sysfs により達成
されました。sysfs は、バス、デバイス、およびドライバを管理するための、
十分な抽象化セットを定義しています。
新しい API は非常に簡単に使用できますが、既存のドライバを新しいインフラ
ストラクチャへと変更するのは、簡単な作業ではありません (検出コードが、
概して ISA カードをプローブするためにも使用されている、というのが主な
理由です)。さらに、ほとんどの EISA ドライバが、もっとも古い Linux ドラ
イバ群に含まれるものであるため、ご想像のとおり、何年ものあいだゴミが
残り続けているのです。
EISA インフラストラクチャは、三つの部分で構成されています。
- バスコードは、汎用コードのほとんどを実装しています。バスコードは、
EISA コードが実行される全てのアーキテクチャで共有されます。バス
コードは、バスのプローブ (バス上に存在する EISA カードの検出) を
実装し、I/O リソースの割当てをおこない、sysfs で装飾名を与え、
ドライバが登録するインターフェースを提供します。
- バスルートドライバは、バスハードウェアと汎用バスコード間の接合部分
を実装します。バスを実装するデバイスの発見と、そのデバイスがあとで
バスコードによりプローブされるようにセットアップすることに、責任を
持ちます。これは、x86 上で I/O リージョンを予約するという程度の簡
単なものから、hppa EISA コードのように、もっと複雑なものになる場合
もあります。ここが、「新しい」プラットフォームで EISA を動かすため
に実装しなければならない部分です。
- ドライバは、管理するデバイスのリストをバスに提供し、要求された
ときにいつでもデバイスのプローブと解放をおこなえるようにするため
に必要なコールバックを実装します。
下記の関数と構造体はすべて <linux/eisa.h> 内にありますが、これらは
<linux/device.h> に大きく依存します。
バスルートドライバ
------------------
int eisa_root_register (struct eisa_root_device *root);
eisa_root_register 関数は、デバイスを EISA バスのルートとして宣言する
ために使用します。eisa_root_device 構造体は、プローブ用のパラメータと
一緒にこのデバイスの参照を保持します。
struct eisa_root_device {
struct device *dev; /* ブリッジデバイスへのポインタ */
struct resource *res;
unsigned long bus_base_addr;
int slots; /* 最大スロット数 */
int force_probe; /* スロット 0 がなくてもプローブする */
u64 dma_mask; /* ブリッジデバイスから */
int bus_nr; /* eisa_root_register によりセットされる */
struct resource eisa_root_res; /* 同上 */
};
node : eisa_root_register で内部的に使用されます
dev : ルートデバイスへのポインタ
res : ルートデバイス I/O リソース
bus_base_addr : このバス上のスロット 0 アドレス
slots : プローブする最大スロット数
force_probe : スロット 0 が空 (EISA メインボードが無い) でもプローブします
dma_mask : デフォルト DMA マスク。通常、ブリッジデバイスの dma_mask.
bus_nr : 一意のバス ID で、eisa_root_register によりセットされます
ドライバ
--------
int eisa_driver_register (struct eisa_driver *edrv);
void eisa_driver_unregister (struct eisa_driver *edrv);
何をする関数かは十分明確ですよね?
struct eisa_device_id {
char sig[EISA_SIG_LEN];
unsigned long driver_data;
};
struct eisa_driver {
const struct eisa_device_id *id_table;
struct device_driver driver;
};
id_table : ヌルで終端された EISA ID 文字列の配列であり、最後は
空文字列。各文字列は、ドライバ依存の値 (driver_data)
と任意で組にすることができます。
driver : Documentation/driver-model/driver.txt で説明されて
いる汎用ドライバ。.name, .probe, .remove メンバだけ
は必須です。
3c59x ドライバが例となります。
static struct eisa_device_id vortex_eisa_ids[] = {
{ "TCM5920", EISA_3C592_OFFSET },
{ "TCM5970", EISA_3C597_OFFSET },
{ "" }
};
static struct eisa_driver vortex_eisa_driver = {
.id_table = vortex_eisa_ids,
.driver = {
.name = "3c59x",
.probe = vortex_eisa_probe,
.remove = vortex_eisa_remove
}
};
デバイス
--------
sysfs フレームワークは、デバイスの発見と削除の際、.probe 関数と .remove
関数を呼びます (.remove 関数が呼ばれるのは、ドライバがモジュールとして
ビルドされている場合のみであることに注意してください)。
どちらの関数も、下記に示す 'struct eisa_device' 内にある 'struct device'
へのポインタを受け取ります。
struct eisa_device {
struct eisa_device_id id;
int slot;
int state;
unsigned long base_addr;
struct resource res[EISA_MAX_RESOURCES];
u64 dma_mask;
struct device dev; /* 汎用デバイス */
};
id : デバイスから読みとる EISA ID. id.driver_data は、対応する
ドライバ EISA ID をもとにセットされます。
slot : デバイスが検出されたスロットの番号
state : デバイスの状態を示すフラグのセット。現在のフラグは
EISA_CONFIG_ENABLED と EISA_CONFIG_FORCED.
res : このデバイスに割り当てられた 4 つの 256 バイト I/O リー
ジョンのセット
dma_mask : 親デバイスから引き継いだ DMA マスク
dev : 汎用デバイス (Documentation/driver-model/device.txt 参照)
'to_eisa_device' マクロを使い、'struct device' から 'struct eisa_device'
を取得できます。
その他
------
void eisa_set_drvdata (struct eisa_device *edev, void *data);
デバイスの driver_data 領域にデータを格納します。
void *eisa_get_drvdata (struct eisa_device *edev):
デバイスの driver_data 領域に格納されているポインタを取得します。
int eisa_get_region_index (void *addr);
渡されたアドレスのリージョン番号を返します (0 以上 EISA_MAX_RESOURCES
未満)。
カーネルパラメータ
------------------
eisa_bus.enable_dev :
有効にするスロットをカンマ区切りでリストしたもの。ファームウェアが
カードを無効にしている場合でも有効にします。ドライバは、そのような
状況の場合にも、適切にデバイスを初期化できなければなりません。
eisa_bus.disable_dev :
無効にするスロットをカンマ区切りでリストしたもの。ファームウェアが
カードを有効にしている場合でも無効にします。このデバイスを操作する
ために当該ドライバが呼ばれることはありません。
virtual_root.force_probe :
EISA 準拠のメインボードを発見できない場合でも (スロット 0 に何も
ない場合でも)、プローブコードに強制的に EISA スロットをプローブ
させます。デフォルトは 0 (強制しない) ですが、CONFIG_ALPHA_JENSEN
もしくは CONFIG_EISA_VLB_PRIMING がセットされている場合は、1 (プ
ローブを強制) にセットされます。
ランダムノート
--------------
EISA ドライバを新しい API に変更する作業は、ほとんどの場合、コードの
「削除」がおこなわれます (現在はコア EISA コードにプローブコードが存在
するからです)。残念ながら、ほとんどのドライバは、ISA, MCA, EISA 間で
自身のプローブルーチンを共有しています。これらの局所的な変更が他のバス
に影響を与えることがないよう、EISA コードを取り除くときには特別な注意が
必要です。
eisa_driver_register から戻ったときに何らかの EISA デバイスが検出されて
いることを期待しては「いけません」。というのは、バス自体がまだプローブ
されていない可能性があるからです。事実、たいていの場合はそうです (バス
ルートドライバは通常、どちらかというとブートプロセスのあとのほうで動作
し始めます)。残念ながら、ほとんどのドライバは自分でプローブをおこなって
おり、自らのプローブルーチンから抜けるときにはマシン全体を調べ終わって
いるものと期待しています。
例えば、お好みの EISA SCSI カードを「ホットプラグ」モデルに切り替える
ことは、"the right thing"(tm) です。(訳注:"right thing" には、「でも、
正常な人ならそんなことはしないけどね」、というニュアンスもあります。
http://www.catb.org/~esr/jargon/html/R/Right-Thing.html を参照のこと)
謝辞
----
ご協力していただいたことに対して、次の方々に感謝したいと思います。
- Xavier Benigni : 素晴らしい Alpha Jensen を私に貸してくれました。
- James Bottomley, Jeff Garzik : これをカーネルに取り込んでくれました。
- Andries Brouwer : 多数の EISA ID を提供してくれました。
- Catrin Jones : 自宅で非常にたくさんのマシンに対応してくれました。
------------------------------------------------------------
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
翻訳日: 2004/05/23
翻訳者: 川崎 貴彦 <takahiko(a)hakubi.co.jp>
Linux カーネル 2.6 付属文書一覧へ戻る