ビデオモード変更コールバックを除き、ドライバとカーネル端末エミュレータの間のすべての動作は tem (端末エミュレータモジュール) によって開始されます。つまり、tem は、このドキュメントで説明されているすべての ioctl コマンドを発行します。以降のセクションでは、各 ioctl コマンドの実装の詳細について説明します。詳細については、visual_io(7I) のマニュアルページおよび /usr/include/sys/visual_io.h インクルードファイルを参照してください。ビデオモード変更コールバック関数の詳細については、ビデオモード変更コールバックインタフェースを参照してください。
VIS_DEVINIT ioctl コマンドは、フレームバッファードライバをシステムコンソールデバイスとして初期化します。この ioctl は vis_devinit 構造体のアドレスを渡します。
tem はまず、そのビデオモード変更コールバック関数のアドレスを vis_devinit 構造体の modechg_cb フィールドにロードし、次にそのソフト状態を modechg_arg フィールドに読み込みます。tem は次に、VIS_DEVINIT ioctl コマンドを発行します。フレームバッファードライバは次に、自身を初期化したあと、vis_devinit 構造体内の version、width、height、linebytes、depth、mode、および polledio フィールドを設定することによって、その構成のサマリーを tem に戻します。vis_devinit 構造体を次のコードに示します。
struct vis_devinit { /* * This set of fields are used as parameters passed from the * layered frame buffer driver to the terminal emulator. */ int version; /* Console IO interface rev */ screen_size_t width; /* Width of the device */ screen_size_t height; /* Height of the device */ screen_size_t linebytes; /* Bytes per scan line */ int depth; /* Device depth */ short mode; /* Display mode Mode */ struct vis_polledio *polledio; /* Polled output routines */ /* * The following fields are used as parameters passed from the * terminal emulator to the underlying frame buffer driver. */ vis_modechg_cb_t modechg_cb; /* Video mode change callback */ struct vis_modechg_arg *modechg_arg; /* Mode change cb arg */ };
コンソールフレームバッファードライバで VIS_DEVINIT ioctl コマンドを実装するには、次の一般的な段階に従います。
コンソール固有の状態を含む struct を定義します。この構造体は、コンソールフレームバッファードライバには非公開です。この構造体は、この付録では consinfo と呼ばれます。consinfo 構造体には、次のような情報が含まれています。
Blit バッファーの現在のサイズ
Blit バッファーへのポインタ
カラーマップ情報
行ピッチなどのドライバ描画モード情報
背景色
ビデオメモリーアドレス
端末エミュレータコールバックアドレス
次のメモリーを割り当てます。
もっとも高いビデオの深さで妥当なデフォルトサイズのピクセル矩形を格納できるほど十分に大きな Blit バッファーを割り当てます。受信要求がこのバッファーのサイズを超える場合は、増設メモリーを割り当てることができます。フレームバッファードライバの最大のフォントは 12 × 22 です。DEFAULT_HEIGHT が 12、DEFAULT_WIDTH が 22、最大のビデオの深さが 32 であると仮定すると、バッファーサイズは 8448 バイト (DEFAULT_HEIGHT × DEFAULT_WIDTH × 32) になります。
vis_polledio 構造体を割り当てます。
カーソルを保持するためのバッファーを割り当てます。このバッファーは最大の文字のサイズにします。このバッファーはサイズが変更されません。
tem のビデオ変更コールバックアドレスとコールバックコンテキストを modechg_cb と modechg_ctx から取得し、これらの情報を consinfo 構造体に格納します。
vis_polledio 構造体に、ポーリングされた表示、コピー、およびカーソル関数のエントリポイントアドレスを設定します。
tem からドライバに渡された vis_devinit 構造体の各フィールドに適切な情報を指定します。
version フィールドを /usr/include/sys/visual_io.h ヘッダーファイルで定義された定数である VIS_CONS_REV に設定します。
mode フィールドを VIS_PIXEL に設定します。
polledio フィールドを vis_polledio 構造体のアドレスに設定します。
height フィールドをビデオモードの高さ (ピクセル単位) に設定します。
width フィールドをビデオモードの幅 (ピクセル単位) に設定します。
depth フィールドをフレームバッファーのピクセルの深さ (バイト単位) に設定します (たとえば、32 ビットのピクセルの深さは 4 バイトになります)。
linebytes フィールドを height × width × depth の値に設定します。
これらの情報は、vis_devinit 構造体を使用してドライバから tem に送信されます。これらの情報は、情報を描画し、それをグラフィックスドライバに渡す方法を端末エミュレータに指示します。
コンソールフレームバッファードライバは、ビデオモード (具体的には、height、width、または depth) を変更した場合は常に、tem のビデオモード変更コールバック関数を呼び出して vis_devinit 構造体を更新し、この構造体を端末エミュレータに戻す必要があります。端末エミュレータは、自身のモード変更コールバック関数アドレスを vis_devinit 構造体の modechg_cb フィールドで渡します。モード変更コールバック関数には、次の関数シグニチャーがあります。
typedef void (*vis_modechg_cb_t) (struct vis_modechg_arg *, struct vis_devinit *);
この typedef に示すように、モード変更コールバック関数は 2 つの引数を取ります。最初の引数は modechg_arg であり、2 番目の引数は vis_devinit 構造体です。modechg_arg は、VIS_DEVINIT ioctl コマンドの初期化中に tem からドライバに送信されます。ドライバは、modechg_arg を各ビデオモード変更コールバックとともに tem に戻す必要があります。
カーネルコンソールのコンテキストを初期化します。具体的な要件は、グラフィックスデバイスの機能によって異なります。この初期化には、描画エンジンの状態の設定、パレットの初期化、画面にデータの Blit を実行できるようにするためのビデオメモリーや描画エンジンの検索とマッピングなどの手順が含まれることがあります。
vis_devinit 構造体を呼び出し元に返します。
VIS_DEFINI ioctl コマンドはドライバのコンソールリソースを解放し、セッションを完了します。
コンソールフレームバッファードライバで VIS_DEVFINI ioctl コマンドを実装するには、次の一般的な段階に従います。
コンソールフレームバッファードライバの状態をリセットします。
ポーリングされた入出力エントリポイントとカーネル端末エミュレータのビデオ変更関数コールバックアドレスをクリアーします。
メモリーを解放します。
VIS_CONSDISPLAY ioctl コマンドは、ピクセルの矩形を指定された場所に表示します。この表示は、矩形の Blit とも呼ばれます。vis_consdisplay 構造体には、ドライバと tem の両方が使用しているビデオの深さで矩形を描画するために必要な情報が含まれています。vis_consdisplay 構造体を次のコードに示します。
struct vis_consdisplay { screen_pos_t row; /* Row (in pixels) to display data at */ screen_pos_t col; /* Col (in pixels) to display data at */ screen_size_t width; /* Width of data (in pixels) */ screen_size_t height; /* Height of data (in pixels) */ unsigned char *data; /* Address of pixels to display */ unsigned char fg_color; /* Foreground color */ unsigned char bg_color; /* Background color */ };
コンソールフレームバッファードライバで VIS_CONSDISPLAY ioctl コマンドを実装するには、次の一般的な段階に従います。
vis_consdisplay 構造体をコピーします。
表示パラメータを検証します。いずれかの表示パラメータが範囲外の場合はエラーを返します。
ビデオメモリーに Blit が実行される矩形のサイズを計算します。このサイズを、VIS_DEVINIT 中に作成された Blit バッファーのサイズに対して検証します。必要に応じて、Blit バッファーのための増設メモリーを割り当てます。
Blit データを取得します。このデータは、一致したピクセルの深さで、カーネル端末エミュレータによって準備されています。その深さは、VIS_DEVINIT 中に tem から伝達されたピクセルの深さと同じです。ピクセルの深さは、デバイスドライバが tem へのコールバックを通してビデオモードを変更した場合は常に更新されます。標準的なピクセルの深さは、8 ビットのインデックスカラーマップと 32 ビットのトゥルーカラーです。
ユーザーアプリケーションがユーザーメモリーマッピングを通してフレームバッファーハードウェアに同時にアクセスすることができないように、すべてのユーザーコンテキストを無効化します。ポーリングされた入出力モードでは、ユーザーアプリケーションが実行されていないため、この手順は許可されず、また必要でもありません。VIS_CONSDISPLAY ioctl が完了するまでユーザーがページフォルトを通してマッピングを復元することができないように、必ずロックを保持するようにしてください。
ドライバ固有のコンソール描画コンテキストを確立します。
フレームバッファーが 8 ビットのインデックスカラーモードで実行されている場合は、tem が前の VIS_PUTCMAP ioctl を使用して設定したカーネルコンソールのカラーマップを復元します。パフォーマンスを最適化するために、遅延カラーマップをロードするスキームをお勧めします。遅延スキームでは、コンソールフレームバッファーは、VIS_DEVINIT ioctl が発行されたあとに実際に使用した色のみを復元します。
tem から渡されたデータを tem から送信されたピクセル座標に表示します。RGB ピクセルデータのバイト順序の変換が必要になることがあります。
VIS_CONSCOPY ioctl コマンドは、ピクセルの矩形領域をある場所から別の場所にコピーします。この ioctl の 1 つの使用法にスクロールがあります。
コンソールフレームバッファードライバで VIS_CONSCOPY ioctl コマンドを実装するには、次の一般的な段階に従います。
vis_conscopy 構造体をコピーします。vis_conscopy 構造体では、ソースとターゲットの矩形のサイズと場所を記述します。
表示パラメータを検証します。いずれかの表示パラメータが範囲外の場合はエラーを返します。
ユーザーアプリケーションがユーザーメモリーマッピングを通してフレームバッファーハードウェアに同時にアクセスすることができないように、すべてのユーザーコンテキストを無効化します。ポーリングされた入出力モードでは、ユーザーアプリケーションが実行されていないため、この手順は許可されず、また必要でもありません。VIS_CONSDISPLAY ioctl が完了するまでユーザーがページフォルトを通してマッピングを復元することができないように、必ずロックを保持するようにしてください。
矩形をコピーするための関数を呼び出します。
VIS_CONSCURSOR ioctl コマンドは、カーソルの表示/非表示を切り替えますvis_conscursor 構造体を次のコードに示します。
struct vis_conscursor { screen_pos_t row; /* Row to display cursor (in pixels) */ screen_pos_t col; /* Col to display cursor (in pixels) */ screen_size_t width; /* Width of cursor (in pixels) */ screen_size_t height; /* Height of cursor (in pixels) */ color_t fg_color; /* Foreground color */ color_t bg_color; /* Background color */ short action; /* Show or Hide cursor */ };
コンソールフレームバッファードライバで VIS_CONSCOPY ioctl コマンドを実装するには、次の一般的な段階に従います。
vis_conscursor 構造体をカーネル端末エミュレータからコピーします。
表示パラメータを検証します。いずれかの表示パラメータが範囲外の場合はエラーを返します。
ユーザーアプリケーションがユーザーメモリーマッピングを通してフレームバッファーハードウェアに同時にアクセスすることができないように、すべてのユーザーコンテキストを無効化します。ポーリングされた入出力モードでは、ユーザーアプリケーションが実行されていないため、この手順は許可されず、また必要でもありません。VIS_CONSDISPLAY ioctl が完了するまでユーザーがページフォルトを通してマッピングを復元することができないように、必ずロックを保持するようにしてください。
端末エミュレータは、SHOW_CURSOR または HIDE_CURSOR の 2 つのアクションのいずれかを使用して VIS_CONSCOPY ioctl を呼び出すことができます。次の手順では、ビデオメモリーの読み取りと書き込みによってこの機能を実装する方法について説明します。また、この作業を行うために描画エンジンを使用できる可能性もあります。描画エンジンを使用できるかどうかは、フレームバッファーハードウェアに依存します。
SHOW_CURSOR 機能を実装するには、次の手順を実行します。
カーソルが描画される矩形内のピクセルを保存します。これらの保存されたピクセルは、カーソルを非表示にするために必要になります。
カーソルが描画される矩形で区切られた画面上のすべてのピクセルをスキャンします。この矩形内の、指定されたカーソル前景色 (fg_color) に一致するピクセルを白いピクセルに置き換えます。指定されたカーソル背景色 (bg_color) に一致するピクセルを黒いピクセルに置き換えます。この視覚的な効果として、白いテキストの上に黒いカーソルが表示されます。この方法は、テキストの任意の前景色と背景色で機能します。カラーマップの位置に基づいて色を反転させようとしても実行できません。HSB 配色 (色合い、彩度、明度) を使用して色の反転を試みるなどの、より高度な方式は必要ありません。
HIDE_CURSOR 機能を実装するには、カーソルの矩形の下にあるピクセルを、前の SHOW_CURSOR アクションで保存されたピクセルに置き換えます。
VIS_PUTCMAP ioctl コマンドは、コンソールのカラーマップを確立します。端末エミュレータは、カーネルのカラーマップを設定するためにこの関数を呼び出します。vis_cmap 構造体を次のコードに示します。この構造体は、8 ビットのインデックスカラーモードにのみ適用されます。
struct vis_cmap { int index; /* Index into colormap to start updating */ int count; /* Number of entries to update */ unsigned char *red; /* List of red values */ unsigned char *green; /* List of green values */ unsigned char *blue; /* List of blue values */ };
VIS_PUTCMAP ioctl コマンドは、FBIOPUTCMAP コマンドに似ています。VIS_PUTCMAP コマンドは、フレームバッファーの端末エミュレータと互換性があるコンソールコードに固有です。
端末エミュレータは、コンソールのカラーマップを取得するために VIS_GETCMAP ioctl コマンドを呼び出します。