前のページ 次のページ 目次

6. ドライバ自身について

さて、本来の作業である殆どのドライバの機能を sdc_driver.c ファイル に書く段階に来ました。先ず、ドライバの主な機能の概要は次のとおり:

  1. サーバーのチップセット記述子のデータ構造を提供します。 このデータ構造はドライバ関数へのポインタといくつかのデータ 構造の初期値も含みます。
  2. ドライバ固有のチップセットのレジスタのデータ構造を提供し ます。このデータ構造には一般的な部分とドライバ固有の部分があ ります。チップセットの初期状態を保存したり、他のモードにチッ プセットを変えるときに初期化するのに用います。
  3. ドライバがサポートしているチップセットの一覧を呼び出せる ような識別機能を提供します。
  4. 他のチップセットと異なるということを認識してドライバが そのチップセットをサポートしインストールしてあれば正の応答 をし、そうでなければ負の応答をする探査機能を提供します。
  5. ボードで可能なドットクロックを選択する機能を提供します。
  6. ドライバに依存するデータ構造を保存、回復、初期化する機能を 提供します。
  7. ビデオメモリ内にディスプレイの開始アドレスを設定する機能 を提供します。これはサーバーに仮想スクリーンを実現します。
  8. VT 切り替えを行う機能を提供するでしょう。
  9. モードがチップセットの使用する各々のモードに一致するか チェックする機能を提供するでしょう。

詳細にドライバーのファイルを追いかける前に、重要な情報がここにあり ます:

  1. ドライバがカラーとモノクロサーバーの両方をサポートする 場合、一つのファイルに両方の事例が含まれていることに注意し てください。これらは殆ど同じですが、MONOVGA を #define してある所で両者を区別することが出来ま す。16 色サーバーをサポートする場合、XF86VGA16 の #define が有効になるようにプログラムに指定して ください。殆どの場合、次を stub_driver.c ファイルの先頭近く に指定する事で充分です。
       #ifdef XF86VGA16
       #define MONOVGA
       #endif
    
  2. カラーサーバーは SVGA の 8-ビットパックトピクセルモード を使用します。モノクロと vga16 サーバーは VGA の 16-色モード (4 ビットプレーン)を使用します。モノクロサーバーでは 1 プ レーンだけ使用します。 訳注 : パックトピクセル: 1 ドットのピクセル(画面上の点) を表現するのに、連続した 8 ビットを 4 つ並べて表わす方式。 4 ビットプレーン: 1 ドットを表わすのに、それぞれの色毎にプ レーンを持ち各プレーン上の連続しない 8 ビット 4 つを使って 表わす方式。
  3. バンク切り替えを使わないように、モノクロサーバーを設定 できます。これは表示領域のメモリをたった 64k に出来る事以外 は特に魅力的ではありません。
これらを踏まえて、所定の機能を制御するチップセットからレジスタを探 す必要があります。特に、レジスタは以下を制御します:
  1. クロック選択ビット。低位の 2 ビットは標準の(殆どの SVGA チップセットが 1 若くは 2 ビット以上持っている)周辺機器出力 レジスタ(Miscellaneous Output Register) の一部で、8 か 16 に分解し たクロックを使うように設定します。
  2. バンク選択。読み書きするバンク選択の制御を行うレジスタを SVGA チップセットは一つか二つ持っているでしょう。
  3. CRTC 機能拡張。標準的な VGA レジスタは大きな表示を行うのに十分なビッ ト数を持っていません。故に SVGA チップセットは拡張したビット数を持ってい ます。
  4. インターレースモード。標準的な VGA はインターレース表示 をサポートしていません。故に SVGA チップセットはインターレー スモードを制御するビットを持っています。インターレースモード 制御用の設定を行うレジスタを追加しているいくつかのチップセッ トがあります。
  5. 開始アドレス。標準的な VGA だけは表示用メモリの開始アドレ スを指定するのに 16 ビットのアドレスを使います。これは仮想ス クリーン機能で使うスクリーンのサイズを制限します。SVGA チッ プセットは通常一つかそれ以上の拡張ビットを持っています。
  6. レジスタロック。殆どの SVGA チップセットはレジスタを最初に ``unlocked'' にしない限り拡張レジスタの更新を防止します。 何か意図を持ってレジスタの保護を無効にしたい時に必要になります。
  7. その他の機能。例えば、いくつかのチップセットが拡張 VGA メモリを(IBM-標準の 265k を超えて)アクセスしたい時、正しい ビットを設定する必要があるでしょう。または全ての拡張レジスタ の内容を読み取るとか、目に留まった重要な何かを見る等の他の機 能があるでしょう。

運がよければ、チップセットのベンダーのデータブックに様々な BIOS モー ド用のレジスタの設定の表が掲載されているでしょう。様々な BIOS モード でどんな操作が可能であるか学習することが出来ます。

6.1 複数のチップセットとオプション

同じベンダーから出荷している複数のチップセットは単一のドライバでサ ポート可能で、実際魅力的です。複数のサポートしているチップセットが ある場合、一連の対応する #define とドライバを識別する為の変数の `SDCchipset' を保持して下さい。Trident と PVGA1/WD を例題として見て ください(Tseng ET3000 と ET4000は逆の意味での例題です。つまり複数 のチップセットに対応したドライバインターフェースが開発される前に実 現してしまいました。従ってこの場合はもうフォロー出来ません。)。追 加するドライバはこれらと異なるように作業をするときはバージョンを意 識するだけで良いことに注意してください。例えば、SDC ドライバが SDC-1a,SDC-1b と SDC-2 のチップセットをサポートしていると仮定して下 さい。この -1a と-1b は本質的には同一ですが、-2 とは異なります。追 加するドライバが -1 と -2 のチップセットをサポートすれば、-1a と -1b の違いを意識しなくても良いでしょう。この事はエンドユーザの作業を簡 単にします。

ユーザにドライバの挙動を制御させるか、ユーザの介入無しにドライバを 決定できない場合は、``option'' を使いましょう。SDC チップセットを 使用しているボードベンダーは 8 個か 16 個のクロックパラメータをオ プションで与えてなさいと言うでしょう。チップセットの探査の結果から 決定するしか方法は無いので XF86Config ファイル からユーザがオプショ ンで挙動を選択できるように提供しましょう。オプションは ``xf86_option.h'' ファイルに定義します。再利用可能なオプションが既 にそこにあるかもしれません。再利用可能な場合は追加するドライバに使 いましょう。再利用可能で無い場合は新たに #define を追加し、そ のファイルに 文字列->シンボルの割り当てを表形式で定義します。オプ ションの使い方を理解するには ET4000, PVGA1/WD と Trident のドライ バを見てください。

6.2 データ構造

上記の説明から何が必要なのか理解したら、ドライバのデータ構造を記入 する段階です。最初に `vgaSDCRec' の構造に取り掛かりましょう。このデ ータ構造は SVGA の状態情報を保持するドライバ特有のデータ構造です。 このデータ構造の最初の項目は常に `vgaHWRec std' です。この項目は汎 用 VGA の一部分の情報を保持します。それ以降に追加するドライバが操作 するレジスタ毎に一つの `unsigned char' の領域を取ってください。これ が最初のデータ構造の全てです。

次に `SDC' 構造(`vgaVideoChipRec' 型) の初期化をしなければいけませ ん。これは追加するドライバをサーバーに識別させるグローバルな構造体 です。その名称はすべて大文字で `SDC' としなければいけません。つまり、 追加するドライバのあるディレクトリの名称と一致しなければなりません。 この事はリンクキットの再構成を行う時に必要なディレクトリとグローバ ルなデータ構造の全てを確認することが必須です。

この構造体の始めの部分はドライバ関数へのポインタを単に保持します。

次は、チップセットがバンク切り替えをどうするかについての情報を初期 化します。以降の領域は次のように記入しなければいけません:

  1. ChipMapSize - サーバーのアドレス空間に割り付けるメモリ量。 ほぼ通常 64k (0xA0000 から 0xAFFFF まで) です。いくつかのチッ プセットは 128k を使います (0xA0000 から 0xBFFFF まで)。追加 するチップセットにオプションを付加すると、64k の窓を 128k の 窓にして Hercules またはモノクロ ディスプレイ アダプタカード で SVGA として使用出来ます。
  2. ChipSegmentSize - ChipMapSize の窓内のバンクの大きさ。 これもまた通常 64k ですが、いくつかのチップセットは割り付け られた窓を読み込み部分と書き込み部分に分割します(例えば PVGA1/Western Digita チップセット)。
  3. ChipSegmentShift - バンク番号をマスクするときのアドレス を右シフトする際のビット数。これは ChipSegmentSize の 2 を底 とした log になります。
  4. ChipSegmentMask - 与えられたバンクのアドレスをマスクオフするとき のビットマスク。これは (ChipSegmentSize-1) になります。
  5. ChipReadBottom,ChipReadTop - 読み込み操作を行ったときの 割り付けられた窓のアドレス。が、チップセットが分割された読み 込みと書き込みの窓を持っている場合を除いて、通常はおのおの 0 と 64k です。
  6. ChipWriteBottom,ChipWriteTop - 書き込み操作において上記 と同様です。
  7. ChipUse2Banks - 該当チップセットが一つ又は二つのバンク レジスタを持っているか、いないかに関わらないブーリアン値。 これはスクリーンからスクリーンへの操作の設定に適正に用いら れます。
さらに 3 個の領域を記入しましょう:
  1. ChipInterlaceType - VGA_NO_DIVIDE_VERT または VGA_DIVIDE_VERT のどちらかになります。いくつかのチップセットはインタレースモー ド用に垂直方向の調整数値を 2 で割ったものを必要とします。その ため、この設定には注意してください。
  2. ChipOptionFlags - データ構造の初期化では通常 `{0,}' に します。これはこのドライバで有効な オプション を含んだビッ ト列です。探査関数の終了時に適正なビット列に初期化されます。
  3. ChipRounding - 256 色サーバー用に仮想スクリーンの幅をこ の値の倍数になるように丸めるのに用いるため設定します。この値 は通常は 8 ですが、いくつかのチップセットでは 4 とか 16 にな ります。

6.3 Ident() 関数

Ident() 関数は大変単純な関数です。サーバーがこの関数を NULL を帰すまで繰り返し呼び出したときに、組み込まれているドライバの 一覧を出力します。Ident() 関数はサポートしているチップセッ トの名称を返します。この関数は各々の繰り返しで 0 から増加する数値を 渡します。

6.4 ClockSelect() 関数

ClockSelect() 関数はクロックの探査をするときに(例えば `Clocks' 行を XF86Config ファイルで指定しなかった場合)選択したドッ トクロックをパラメタで受け取るのに用います。受け取った数値によって 関数はチップセットの clock-select ビットを設定します。 (CLK_REG_SAVE, CLK_SAVE_RESTORE) のような値は二つのダミーとして受け 取る場合があります。CLK_REG_SAVE を受け取った時は、関数がクロック 選択途中に変更したレジスタの写しが保存されています。CLK_REG_RESTORE を受け取った時は、関数がレジスタを回復しました。クロック探査がレジ スタの内容を破壊しなかったことを保証します。

受け取ったインデックスの値が不正か、もしくはクロックが不正で設定出 来なかった場合、この関数は FALSE を返します

6.5 Probe() 関数

Probe() 関数はドライバの中で多分最も重要でかつ最も直感的で 無い関数でしょう。Probe 関数は全てのチップセットに依存せずにチップ セットを識別しなければなりません。XF86Config ファイルに `Chipset' 行を指定した時に、単純な文字列比較を行います。運 がよければ、チップセットの認識機構(識別/バージョン レジスタ, 等)が あって、それがデータブックに掲載されているでしょう。さもなければ、 以下に述べるような何らかの手順によって認識しなければなりません。

よくレジスタに特有のパターンや、一定の拡張レジスタを探して認識しま す。又はいくつかのボードやチップセットでは、必要な情報は一定の署名 文字列を BIOSから読みだして獲得しています。既存の探査関数を勉強する 事と参考文献を参照する事を強くお薦めします。追加する探査が非破壊で 行われていることを確認して、レジスタを更新するならば、更新前に保存 して、更新後に回復しなければいけません。

チップセットが認識できたら、Probe() 関数はいくつかの他の 初期化を行う必要があります。

  1. XF86Config ファイルに `VideoRam' パラメタを指定 しない場合は、搭載しているメモリ量を特定しなければいけません。
  2. XF86Config ファイルに `Clocks' パラメタを指定し ない場合は、可能なドットクロックの値を特定しなければいけませ ん。vgaGetClocks() 関数を呼ぶことで、可能なクロック の値とClockSelect() へのポインタを受け取れます。
  3. サーバーの `vga256InfoRec' 構造体の `maxClock' 領域をチッ プセットでの可能な最大ドットクロックを (KHz 単位で) 指定する ことをお薦めします。探査時にここを記入しないと、標準値 (現在 は 99MHz ) を使用します。
  4. サーバーの `vga256InfoRec' 構造体の `chipset' 領域を搭載 しているチップセットの名称で初期化しましょう。
  5. モノクロサーバーでドライバが使用されるならば、サーバーの `vga256InfoRec' 構造体の `bankedMono' 領域にモノクロドライバ がバンク切り替えをサポートしているかどうかを指定しなければい けません。
  6. 追加するサーバーが他のオプションをサポートする場合、 `vgaVideoChipRec' 型の `ChipOptionFlags'構造体を OFLG_SET() マクロを用いてオプションの使用許可を初期 設定しましょう。

6.6 EnterLeave() 関数

EnterLeave() 関数はサーバー上の仮想コンソールに入ったり出 たりする度に呼ばれます(仮想コンソールの無い OS では、この関数はサー バーの開始時に呼ばれ、終了時にもう一度呼ばれます)。この関数の目的は I/O の権限を(OS が要求するように)譲渡したり剥奪したりする事にある為 と ドライバが操作しなければならない``保護された''レジスタへのロック 解除と再ロックアクセスをする為です。これは、とても小さな関数ですが 以降のスタブドライバのコメントにあるように実現しました。

6.7 Restore() 関数

Restore() 関数は保存されたビデオ状態を回復するのに用いま す。restore という名称は少し誤った名称で、この関数は保存された状態 を回復する事とサーバーが新規に作成した状態を保存する事の両方に使用 します。Restore() 関数は次の手続きをふむ必要があります:

  1. バンク 0 を選択し、新規状態の出力に先だって要求されたバ ンク 0 のその他の状態情報が設定済みである事を確認する。
  2. vgaHWRestore() を状態情報の汎用 VGA 部分を回復 する為に呼ぶ。この関数は vgaHW.c ファイルの中にあります。
  3. 状態情報のチップセット特有部分を回復する。これは単純に レジスタに書き込むか、変更すべき適正なビットだけに read/modify/write 操作を行う。クロック選択ビットの扱いを如 何に行うかについて、ドライバの例題の中のコメントに注意事項 を書いたので確認してください。

6.8 Save() 関数

Save() 関数はサーバー開始時に初期ビデオ状態情報を取り出す のに使用する。Save() 関数は次の手続きをふむ必要があります:

  1. バンク 0 を選択したことを確認する。
  2. vgaHWSave() を状態情報の汎用 VGA 部分を取り出す 為に呼ぶ。この関数は vgaHW.c ファイルの中にあります。
  3. 状態情報のチップセット特有部分を取り出す。

6.9 Init() 関数

Init() 関数はドライバの中で (Probe() 関数の次に) 二番目に重要です。サーバーの中に定義された表示モード各々についてデー タ構造を初期化します。この関数は SVGA チップセットに必要な状態に `vgaSDCRec' データ構造全体を初期化するのに使います。構造体の汎用 VGA 部分は (これも vgaHW.c 内にある) vgaHWInit() を呼ぶこ とにより初期化します。

汎用の部分を初期化したら、必要なら Init() 関数が汎用レジス タのいくつかの初期化を行います。正しい初期化によってその他全ての領 域が埋められます。初期化した特有のモードの情報は `mode' パラメタで ある`DisplayModeRec' 構造体へのポインタで受け取ります。

レジスタの適正なビットの初期化の方法が分かっている場合はここで初期 化しましょう。Restore() 関数でしかそのビットを read/modify/write 出来ない事を確認してください。

6.10 Adjust() 関数

Adjust() 関数は比較的根本的な関数です。仮想スクリーンのス クロールや表示解像度の変更によって、サーバーがビデオメモリの表示用 領域の開始点を調整する必要のあるときはいつも呼ばれます。毎回、指定 した座標に合わせてチップセットの開始アドレスを設定します。これを実 現する方法の詳細はスタブドライバの中のコメントに従ってください。

6.11 ValidMode() 関数

ValidMode() 関数は必須です。何故グラフィックモードが妥当で 無いのか、チップセットに依存した理由を調査するのに使用します。 Probe() 実行後のプログラムのより上位のプログラムから呼ばれます。多くの場 合、特別な調査は必要なくこの関数は通常、単に TRUE を返します。

6.12 SaveScreen() 関数

SaveScreen() 関数は殆どのチップセットでは必要ありません。 追加するドライバが同期リセットをチップセットで実行する場合、拡張レ ジスタを更新するのでこの関数が必要になります(データブックに詳細に 記載があります)。この関数が必要*無い*とき、特に定義は必要無く、 vgaVideoChipRec 構造体型で初期化した `NoopDDA' を置きましょう (NoopDDA は汎用の空の関数です)。

この関数が*必要*ならば、比較的単純な次の作業を行ってください。二回 呼び出すのですが、一回目はリセット前と二回目はリセット後に呼び出し ます。前者の場合は 引数にSS_START を渡し、後者では SS_FINISH を渡し て下さい。毎回、SS_START で呼び出した場合はリセットによって影響のあ るレジスタを格納し、SS_FINISH で呼び出した場合はそれを回復する必要 があります。

6.13 GetMode() 関数

GetMode() 関数は XFree86 1.3 迄は使っていませんし、これは vgaVideoChipRec 型で `NoopDDA' を初期化したものです。

将来、いくつかの点でこの関数はサーバーのドライバライブラリを使うサー バー且つ/又はスタンドアローンのプログラムの対話型ビデオモード調節 に使用可能になるでしょう。この関数は SVGA レジスタを読み込み現在の ビデオモードの DisplayModeRec 構造体に書き込みます。

6.14 FbInit() 関数

FbInit() 関数はアクセラレータグラフィックスをサポートする ドライバに必須です。アクセラレータチップ固有のバージョンでは標準で cfb.banked 関数を置き換えて使用します。vga256LowlevFuncs は置き換え 可能な関数の一覧を含む構造体です。この構造体は vga256.h で定義して います。FbInit() 関数の例は et4000, pvga1 とcirrus のドラ イバにあります。

この関数が必要ない場合、単に定義をしないで、vgaVideoChipRec 型で初 期化した `NoopDDA' を置いてください。


前のページ 次のページ 目次