Oracle® Solaris 11.2 デバイスドライバの記述

印刷ビューの終了

更新: 2014 年 9 月
 
 

コンソールフレームバッファードライバ

システムコンソールに使用されるフレームバッファーのドライバは、システムがコンソール上にテキストを表示できるようにするためのインタフェースを提供する必要があります。Oracle Solaris OS には、カーネル端末エミュレータがコンソールフレームバッファー上に直接テキストを表示できる、拡張された視覚的な入出力インタフェースが用意されています。この付録では、必要なインタフェースをフレームバッファードライバに追加することにより、そのドライバが Oracle Solaris カーネル端末エミュレータと対話できるようにする方法について説明します。

Oracle Solaris コンソールとカーネル端末エミュレータ

カーネル端末エミュレータの役割は、コンソールフレームバッファーに、そのフレームバッファーの画面の高さ、幅、およびピクセルの深さモードによって決定される正しい位置と表現でテキストを描画することです。端末エミュレータはまた、スクロールの操作、ソフトウェアカーソルの制御、および ANSI 端末のエスケープシーケンスの解釈も行います。端末エミュレータは、グラフィックスカードに応じて VGA テキストモードまたはピクセルモードのどちらかでコンソールフレームバッファーにアクセスします。フレームバッファードライバを Oracle Solaris コンソールフレームバッファードライバとして使用するには、そのドライバが Oracle Solaris カーネル端末エミュレータとの互換性を備えている必要があります。ターゲットプラットフォームは、フレームバッファードライバを変更して Oracle Solaris カーネル端末エミュレータとの互換性を確保する必要があるかどうかを判定するための、もっとも重要な要因です。

  • x86 プラットフォーム – x86 コンソールフレームバッファードライバは、すでにコンソールのフレームバッファーインタフェースをサポートしているため、コンソールフレームバッファードライバを変更する必要はありません。

  • SPARC プラットフォーム – コンソールフレームバッファードライバが Oracle Solaris カーネル端末エミュレータと対話できるようにするには、そのドライバはこの付録で説明されているインタフェースを使用するべきです。

x86 プラットフォームのコンソール通信

x86 プラットフォームでは、Oracle Solaris カーネル端末エミュレータモジュール (tem) は VGA テキストモードを排他的に使用して vgatext モジュールと対話します。vgatext モジュールは、業界標準の VGA テキストモードを使用して、x86 と互換性のあるフレームバッファーデバイスと対話します。vgatext モジュールは、すでにコンソールのフレームバッファーインタフェースをサポートしているため、x86 フレームバッファードライバはカーネルの tem モジュールと互換性があります。x86 フレームバッファードライバに特殊なインタフェースを追加する必要はありません。

この付録の残りの部分は、SPARC プラットフォームにのみ適用されます。

SPARC プラットフォームのコンソール通信

SPARC フレームバッファードライバは通常、VGA テキストモードでは動作しません。SPARC フレームバッファードライバは通常、表示されるテキストとイメージを示すピクセルパターンを送信する必要があります。カーネルの tem が、画面へのデータの描画、スクロールの実行、およびテキストカーソルの表示を容易にする特定のインタフェースをサポートするには、SPARC ドライバが必要です。ドライバが tem から送信されたデータを実際に画面に描画する方法は、デバイスによって異なります。ドライバは通常、ハードウェアとビデオモードに従って、データをビデオメモリーに描画します。

Oracle Solaris OS には、カーネル端末エミュレータが互換性のあるコンソールフレームバッファーを直接操作できるインタフェースが用意されています。ドライバを変換してカーネル端末エミュレータとの互換性を確保する利点は、次のとおりです。

  • パフォーマンス (特に、スクロール) の大幅な向上

  • ANSI 文字列色の機能の拡張

  • システムコンソールのストリームがシリアルポートから出力されている場合でも、コンソールフレームバッファー上でログインセッションを開始する機能

SPARC コンソールフレームバッファードライバに、カーネル端末エミュレータとの互換性を確保する必要はありません。コンソールフレームバッファードライバにカーネル端末エミュレータとの互換性がない場合、システムは、OpenBoot PROM 内の FCode 端末エミュレータを使用します。

コンソールフレームバッファーは、EEPROM の screen 環境変数によって識別されます。システムは、フレームバッファードライバが tem-support DDI プロパティーをエクスポートするかどうかをチェックすることによって、コンソールフレームバッファーにカーネル端末エミュレータモジュールとの互換性があるかどうかを判定します。tem-support プロパティーがエクスポートされる場合、システムは、システムブート時のコンソールの構成中にフレームバッファードライバに VIS_DEVINIT 入出力制御 (ioctl) コマンドを発行します。tem-support DDI プロパティーがエクスポートされ、かつ VIS_DEVINIT ioctl コマンドが成功して tem に互換性があるバージョン番号を返した場合、システムは、そのフレームバッファードライバをカーネル端末エミュレータ経由で利用するようにシステムコンソールを構成します。入出力制御のドライバエントリポイントについては、ioctl (9E) のマニュアルページを参照してください。

カーネル端末エミュレータをサポートする SPARC ドライバは、tem-support DDI プロパティーをエクスポートします。このプロパティーは、そのドライバがカーネル端末エミュレータをサポートすることを示します。フレームバッファードライバが tem-support DDI プロパティーをエクスポートする場合、そのドライバは、コンソールの構成中のブートプロセス内の早い段階で処理されます。フレームバッファードライバが tem-support プロパティーをエクスポートしない場合、そのドライバは、ブートプロセス内の十分早い段階では処理されない可能性があります。

tem-support

1 に設定されていると、この DDI プロパティーは、このドライバがコンソールのカーネルフレームバッファーインタフェースと互換性があることを示します。

カーネル端末エミュレータモジュールは、次の 2 つの主要なインタフェースを介してコンソールフレームバッファードライバと相互に作用します。

  • 通常のシステム動作中に ioctl インタフェースを介して

  • スタンドアロンモード中に、ポーリングされた入出力インタフェースを介して

詳細については、次のセクションで説明します。

コンソールの視覚的な入出力インタフェース

カーネル端末エミュレータは、次の 2 つのインタフェースを介してコンソールフレームバッファードライバと相互に作用します。通常のシステム動作中 (システムのブートが成功したあと)、カーネル端末エミュレータとコンソールフレームバッファードライバの間の通信は ioctl インタフェースを介して行われます。スタンドアロンモード中 (システムブートの前またはデバッグ中)、カーネル端末エミュレータとコンソールフレームバッファードライバの間の通信は、ポーリングされた入出力インタフェースを介して行われます。カーネル端末エミュレータとコンソールフレームバッファードライバの間のすべての動作は、カーネル端末エミュレータにビデオモードの変更を通知するためにコンソールフレームバッファードライバによって使用されるコールバック関数を除き、カーネル端末エミュレータによって開始されます。

コンソールの視覚的な入出力インタフェースについては、visual_io(7I) のマニュアルページに詳細が説明されています。ビデオモード変更コールバック関数の詳細については、Video Mode Change Callback Interfaceを参照してください。

入出力制御インタフェース

通常のシステム動作中、カーネル端末エミュレータは、次の表に示されている ioctl インタフェースを介してコンソールフレームバッファードライバと通信します。

ioctl の名前
対応するデータ構造体
説明
VIS_DEVINIT
vis_devinit
端末エミュレータモジュールとフレームバッファーの間のセッションを初期化します。VIS_DEVINITを参照してください。
VIS_DEVFINI
該当なし
端末エミュレータモジュールとフレームバッファーの間のセッションを終了します。VIS_DEFINIを参照してください。
VIS_CONSDISPLAY
vis_consdisplay
ピクセルを矩形として表示します。VIS_CONSDISPLAYを参照してください。
VIS_CONSCOPY
vis_conscopy
ピクセルの矩形をコピーします (スクロール)。VIS_CONSCOPYを参照してください。
VIS_CONSCURSOR
vis_conscursor
テキストカーソルの表示/非表示を切り替えますVIS_CONSCURSORを参照してください。
VIS_PUTCMAP
vis_cmap
端末エミュレータモジュールのカラーマップをフレームバッファードライバに送信します。VIS_PUTCMAPを参照してください。
VIS_GETCMAP
vis_cmap
端末エミュレータモジュールのカラーマップをフレームバッファーから読み取ります。VIS_GETCMAPを参照してください。

ポーリングされた入出力インタフェース

ポーリングされた入出力インタフェースは、VIS_CONSDISPLAY、VIS_CONSCOPY、および VIS_CONSCURSOR ioctl インタフェースと同じ機能を提供します。ポーリングされた入出力インタフェースは、オペレーティングシステムが休止状態にあり、かつスタンドアロンモードにある場合にのみ呼び出されます。詳細については、Implementing Polled I/O in Console Frame Buffer Driversを参照してください。

スタンドアロンモード中、カーネル端末エミュレータは、次の表に示されているポーリングされた入出力インタフェースを介してコンソールフレームバッファードライバと通信します。

ポーリングされた入出力関数
対応するデータ構造体
説明
(*display)()
vis_consdisplay
ピクセルを矩形として表示します。
(*copy)()
vis_conscopy
ピクセルの矩形をコピーします (スクロール)。
(*cursor)()
vis_conscursor
テキストカーソルの表示/非表示を切り替えます

ビデオモード変更コールバックインタフェース

コンソールフレームバッファードライバとカーネル端末エミュレータは、常にビデオモードに関して一致している必要があります。ビデオモードには、コンソール画面の高さ、幅、およびピクセルの深さが含まれます。ビデオモードにはまた、カーネル端末エミュレータとコンソールフレームバッファーの間の通信が VGA テキストモードまたはピクセルモードのどちらになっているかも含まれます。

コンソールフレームバッファードライバがカーネル端末エミュレータにビデオモードの変更を通知するために、コンソールフレームバッファードライバは、次の表で説明されている (*modechg_cb)() カーネル端末エミュレータコールバック関数のアドレスで初期化されます。

コールバック関数
対応するデータ構造体
説明
(*modechg_cb)()
vis_modechg_arg
vis_devinit
端末エミュレータモジュールとドライバのビデオモード (画面の高さ、幅、およびピクセルの深さ) との同期を維持します。

コンソールフレームバッファードライバでの視覚的な入出力インタフェースの実装

ビデオモード変更コールバックを除き、ドライバとカーネル端末エミュレータの間のすべての動作は tem (端末エミュレータモジュール) によって開始されます。つまり、tem は、このドキュメントで説明されているすべての ioctl コマンドを発行します。以降のセクションでは、各 ioctl コマンドの実装の詳細について説明します。詳細については、 visual_io(7I) のマニュアルページおよび /usr/include/sys/visual_io.h インクルードファイルを参照してください。ビデオモード変更コールバック関数の詳細については、Video Mode Change Callback Interfaceを参照してください。


注 - ioctl コマンドは、ioctl フラグ引数で FKIOCTL が設定されているかどうかを判定し、そのビットが設定されていない場合は EPERM を返します。

VIS_DEVINIT

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 コマンドを実装するには、次の一般的な段階に従います。

  1. コンソール固有の状態を含む struct を定義します。この構造体は、コンソールフレームバッファードライバには非公開です。この構造体は、この付録では consinfo と呼ばれます。consinfo 構造体には、次のような情報が含まれています。

    • Blit バッファーの現在のサイズ

    • Blit バッファーへのポインタ

    • カラーマップ情報

    • 行ピッチなどのドライバ描画モード情報

    • 背景色

    • ビデオメモリーアドレス

    • 端末エミュレータコールバックアドレス

  2. 次のメモリーを割り当てます。

    1. もっとも高いビデオの深さで妥当なデフォルトサイズのピクセル矩形を格納できるほど十分に大きな Blit バッファーを割り当てます。受信要求がこのバッファーのサイズを超える場合は、増設メモリーを割り当てることができます。フレームバッファードライバの最大のフォントは 12 × 22 です。DEFAULT_HEIGHT が 12、DEFAULT_WIDTH が 22、最大のビデオの深さが 32 であると仮定すると、バッファーサイズは 8448 バイト (DEFAULT_HEIGHT × DEFAULT_WIDTH × 32) になります。

    2. vis_polledio 構造体を割り当てます。

    3. カーソルを保持するためのバッファーを割り当てます。このバッファーは最大の文字のサイズにします。このバッファーはサイズが変更されません。

  3. tem のビデオ変更コールバックアドレスとコールバックコンテキストを modechg_cb と modechg_ctx から取得し、これらの情報を consinfo 構造体に格納します。

  4. vis_polledio 構造体に、ポーリングされた表示、コピー、およびカーソル関数のエントリポイントアドレスを設定します。

  5. tem からドライバに渡された vis_devinit 構造体の各フィールドに適切な情報を指定します。

    1. version フィールドを /usr/include/sys/visual_io.h ヘッダーファイルで定義された定数である VIS_CONS_REV に設定します。

    2. mode フィールドを VIS_PIXEL に設定します。

    3. polledio フィールドを vis_polledio 構造体のアドレスに設定します。

    4. height フィールドをビデオモードの高さ (ピクセル単位) に設定します。

    5. width フィールドをビデオモードの幅 (ピクセル単位) に設定します。

    6. depth フィールドをフレームバッファーのピクセルの深さ (バイト単位) に設定します (たとえば、32 ビットのピクセルの深さは 4 バイトになります)。

    7. 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 に戻す必要があります。

  6. カーネルコンソールのコンテキストを初期化します。具体的な要件は、グラフィックスデバイスの機能によって異なります。この初期化には、描画エンジンの状態の設定、パレットの初期化、画面にデータの Blit を実行できるようにするためのビデオメモリーや描画エンジンの検索とマッピングなどの手順が含まれることがあります。

  7. vis_devinit 構造体を呼び出し元に返します。

VIS_DEFINI

VIS_DEFINI ioctl コマンドはドライバのコンソールリソースを解放し、セッションを完了します。

コンソールフレームバッファードライバで VIS_DEVFINI ioctl コマンドを実装するには、次の一般的な段階に従います。

  1. コンソールフレームバッファードライバの状態をリセットします。

  2. ポーリングされた入出力エントリポイントとカーネル端末エミュレータのビデオ変更関数コールバックアドレスをクリアーします。

  3. メモリーを解放します。

VIS_CONSDISPLAY

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 コマンドを実装するには、次の一般的な段階に従います。

  1. vis_consdisplay 構造体をコピーします。

  2. 表示パラメータを検証します。いずれかの表示パラメータが範囲外の場合はエラーを返します。

  3. ビデオメモリーに Blit が実行される矩形のサイズを計算します。このサイズを、VIS_DEVINIT 中に作成された Blit バッファーのサイズに対して検証します。必要に応じて、Blit バッファーのための増設メモリーを割り当てます。

  4. Blit データを取得します。このデータは、一致したピクセルの深さで、カーネル端末エミュレータによって準備されています。その深さは、VIS_DEVINIT 中に tem から伝達されたピクセルの深さと同じです。ピクセルの深さは、デバイスドライバが tem へのコールバックを通してビデオモードを変更した場合は常に更新されます。標準的なピクセルの深さは、8 ビットのインデックスカラーマップと 32 ビットのトゥルーカラーです。

  5. ユーザーアプリケーションがユーザーメモリーマッピングを通してフレームバッファーハードウェアに同時にアクセスすることができないように、すべてのユーザーコンテキストを無効化します。ポーリングされた入出力モードでは、ユーザーアプリケーションが実行されていないため、この手順は許可されず、また必要でもありません。VIS_CONSDISPLAY ioctl が完了するまでユーザーがページフォルトを通してマッピングを復元することができないように、必ずロックを保持するようにしてください。

  6. ドライバ固有のコンソール描画コンテキストを確立します。

  7. フレームバッファーが 8 ビットのインデックスカラーモードで実行されている場合は、tem が前の VIS_PUTCMAP ioctl を使用して設定したカーネルコンソールのカラーマップを復元します。パフォーマンスを最適化するために、遅延カラーマップをロードするスキームをお勧めします。遅延スキームでは、コンソールフレームバッファーは、VIS_DEVINIT ioctl が発行されたあとに実際に使用した色のみを復元します。

  8. tem から渡されたデータを tem から送信されたピクセル座標に表示します。RGB ピクセルデータのバイト順序の変換が必要になることがあります。

VIS_CONSCOPY

VIS_CONSCOPY ioctl コマンドは、ピクセルの矩形領域をある場所から別の場所にコピーします。この ioctl の 1 つの使用法にスクロールがあります。

コンソールフレームバッファードライバで VIS_CONSCOPY ioctl コマンドを実装するには、次の一般的な段階に従います。

  1. vis_conscopy 構造体をコピーします。vis_conscopy 構造体では、ソースとターゲットの矩形のサイズと場所を記述します。

  2. 表示パラメータを検証します。いずれかの表示パラメータが範囲外の場合はエラーを返します。

  3. ユーザーアプリケーションがユーザーメモリーマッピングを通してフレームバッファーハードウェアに同時にアクセスすることができないように、すべてのユーザーコンテキストを無効化します。ポーリングされた入出力モードでは、ユーザーアプリケーションが実行されていないため、この手順は許可されず、また必要でもありません。VIS_CONSDISPLAY ioctl が完了するまでユーザーがページフォルトを通してマッピングを復元することができないように、必ずロックを保持するようにしてください。

  4. 矩形をコピーするための関数を呼び出します。


    注 - 最適なパフォーマンスを得るには、グラフィックスデバイスの描画エンジンを使用してコピー関数を実装してください。最適なパフォーマンスが得られるように描画エンジンを設定するには、ドライバ内でどのようにコンテキスト管理を実行するかを決定する必要があります。

VIS_CONSCURSOR

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 コマンドを実装するには、次の一般的な段階に従います。

  1. vis_conscursor 構造体をカーネル端末エミュレータからコピーします。

  2. 表示パラメータを検証します。いずれかの表示パラメータが範囲外の場合はエラーを返します。

  3. ユーザーアプリケーションがユーザーメモリーマッピングを通してフレームバッファーハードウェアに同時にアクセスすることができないように、すべてのユーザーコンテキストを無効化します。ポーリングされた入出力モードでは、ユーザーアプリケーションが実行されていないため、この手順は許可されず、また必要でもありません。VIS_CONSDISPLAY ioctl が完了するまでユーザーがページフォルトを通してマッピングを復元することができないように、必ずロックを保持するようにしてください。

  4. 端末エミュレータは、SHOW_CURSOR または HIDE_CURSOR の 2 つのアクションのいずれかを使用して VIS_CONSCOPY ioctl を呼び出すことができます。次の手順では、ビデオメモリーの読み取りと書き込みによってこの機能を実装する方法について説明します。また、この作業を行うために描画エンジンを使用できる可能性もあります。描画エンジンを使用できるかどうかは、フレームバッファーハードウェアに依存します。

    SHOW_CURSOR 機能を実装するには、次の手順を実行します。

    1. カーソルが描画される矩形内のピクセルを保存します。これらの保存されたピクセルは、カーソルを非表示にするために必要になります。

    2. カーソルが描画される矩形で区切られた画面上のすべてのピクセルをスキャンします。この矩形内の、指定されたカーソル前景色 (fg_color) に一致するピクセルを白いピクセルに置き換えます。指定されたカーソル背景色 (bg_color) に一致するピクセルを黒いピクセルに置き換えます。この視覚的な効果として、白いテキストの上に黒いカーソルが表示されます。この方法は、テキストの任意の前景色と背景色で機能します。カラーマップの位置に基づいて色を反転させようとしても実行できません。HSB 配色 (色合い、彩度、明度) を使用して色の反転を試みるなどの、より高度な方式は必要ありません。

    HIDE_CURSOR 機能を実装するには、カーソルの矩形の下にあるピクセルを、前の SHOW_CURSOR アクションで保存されたピクセルに置き換えます。

VIS_PUTCMAP

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

端末エミュレータは、コンソールのカラーマップを取得するために VIS_GETCMAP ioctl コマンドを呼び出します。

コンソールフレームバッファードライバでのポーリングされた入出力の実装

ポーリングされた入出力インタフェースはドライバ内の関数として実装され、カーネル端末エミュレータから直接呼び出されます。ドライバは、VIS_DEVINIT ioctl コマンドの実行中に、自身のポーリングされた入出力エントリポイントのアドレスを端末エミュレータに渡します。VIS_DEVINIT コマンドは、端末エミュレータによって開始されます。

vis_polledio 構造体を次のコードに示します。

typedef void * vis_opaque_arg_t;

struct vis_polledio {
      struct vis_polledio_arg *arg;
      void    (*display)(vis_opaque_arg_t, struct vis_consdisplay *);
      void    (*copy)(vis_opaque_arg_t, struct vis_conscopy *);
      void    (*cursor)(vis_opaque_arg_t, struct vis_conscursor *);
};

ポーリングされた入出力インタフェースは、VIS_CONSDISPLAY、VIS_CONSCOPY、および VIS_CONSCURSOR ioctl インタフェースと同じ機能を提供します。ポーリングされた入出力インタフェースは、対応する ioctl コマンドに関して上で説明されたのと同じ手順に従います。ポーリングされた入出力インタフェースは、このセクションの残りの部分で説明されている追加の制限に非常に厳密に従う必要があります。

ポーリングされた入出力インタフェースは、オペレーティングシステムが休止状態にあり、かつスタンドアロンモードにある場合にのみ呼び出されます。システムは、ユーザーが OpenBoot PROM に入った場合、または kmdb デバッガに入った場合には常にスタンドアロンモードに入り、システムがパニック状態になった場合にもこのモードに入ります。1 つの CPU と 1 つのスレッドのみがアクティブです。ほかの CPU とスレッドはすべて停止されます。タイムシェアリング、DDI 割り込み、およびシステムサービスはオフに設定されます。

スタンドアロンモードではドライバ機能が厳しく制限されますが、ドライバの同期要件は簡素化されます。たとえば、ユーザーアプリケーションが、ポーリングされた入出力ルーチン内からドライバのメモリーマッピングを通してコンソールフレームバッファードライバにアクセスすることはできません。

スタンドアロンモードでは、コンソールフレームバッファードライバは、次のどのアクションも実行してはいけません

  • 割り込みの待機

  • mutex の待機

  • メモリーの割り当て

  • DDI または LDI インタフェースの使用

  • システムサービスの使用

ポーリングされた入出力関数は比較的単純な操作であるため、これらの制限に従うことは難しくありません。たとえば、描画エンジンを操作する場合、コンソールフレームバッファードライバは割り込みを待機するのではなく、このデバイス内のビットをポーリングできます。ドライバは、割り当て済みのメモリーを使用して Blit データを描画できます。DDI または LDI インタフェースは必要ないはずです。

フレームバッファー固有の構成モジュール

ドライバ固有の fbconfig() モジュールのために解像度または発色数の変更が発生した場合、その fbconfig() モジュールはフレームバッファードライバに ioctl を送信する必要があります。この ioctl により、フレームバッファードライバは、新しい画面サイズと深さを指定して端末エミュレータのモード変更コールバック関数を呼び出します。フレームバッファードライバと端末エミュレータは、常にビデオモードに関して一致している必要があります。フレームバッファードライバと端末エミュレータがビデオモードに関して一致していない場合、画面上の情報は読み取り不可能になり、無意味になります。

X Window System のフレームバッファー固有の DDX モジュール

X Window System が終了してコマンド行に戻るとき、フレームバッファーの DDX モジュールは、フレームバッファードライバに ioctl を送信する必要があります。この ioctl により、フレームバッファードライバは、端末エミュレータのモード変更コールバック関数を呼び出します。X Window System が起動したあと、終了する前にビデオ解像度を変更した場合は、この通信によってフレームバッファードライバと端末エミュレータでのビデオモードの一致が維持されます。フレームバッファードライバと端末エミュレータは、常にビデオモードに関して一致している必要があります。フレームバッファードライバと端末エミュレータがビデオモードに関して一致していない場合、画面上の情報は読み取り不可能になり、無意味になります。

コンソールフレームバッファードライバの開発、テスト、およびデバッグ

アクティブなシステム上でのコンソールフレームバッファードライバのデバッグでは、問題が発生する場合があります。

  • システムブートの早い段階で検出されたエラーでは、コアダンプが生成されません。

  • エラーまたは通知メッセージが、画面上に正しく表示されない可能性があります。

  • USB キーボードの入力が失敗する可能性があります。

このセクションでは、コンソールフレームバッファードライバの開発、テスト、およびデバッグに役立ついくつかの提案を示します。

入出力制御インタフェースのテスト

ioctl コマンドをテストするには、ユーザーアプリケーションから呼び出し可能な追加の ioctl エントリポイントを作成します。引数を適切にコピーする必要があります。ユーザーのアドレス空間との間でデータを転送するには、ddi_copyin (9F) ルーチンと ddi_copyout (9F) ルーチンを使用します。次に、描画、スクロール、およびカーソル動作を検証するためのアプリケーションを記述します。これによって、これらの ioctl コマンドの開発またはテスト中にコンソールが影響を受けることはなくなります。

ioctl コマンドが正しく機能することを確認するには、システムをブートしてログインします。prstat(1M)、ls(1)、vi(1)、man(1) などのコマンドを実行したときに予期した動作が得られるかどうかをチェックします。

ANSI カラーが正しく機能することを検証するには、次のスクリプトを実行します。

#!/bin/bash
printf "\n\n\n\e[37;40m             Color List       \e[m\n\n"
printf "\e[30m Color 30 black\e[m\n"
printf "\e[31m Color 31 red\e[m\n"
printf "\e[32m Color 32 green\e[m\n"
printf "\e[33m Color 33 yellow\e[m\n"
printf "\e[34m Color 34 blue\e[m\n"
printf "\e[35m Color 35 purple\e[m\n"
printf "\e[36m Color 36 cyan\e[m\n"
printf "\e[37m Color 37 white\e[m\n\n"
printf "\e[40m Backlight 40 black \e[m\n"
printf "\e[41m Backlight 41 red   \e[m\n"
printf "\e[34;42m Backlight 42 green \e[m\n"
printf "\e[43m Backlight 43 yellow\e[m\n"
printf "\e[37;44m Backlight 44 blue  \e[m\n"
printf "\e[45m Backlight 45 purple\e[m\n"
printf "\e[30;46m Backlight 46 cyan  \e[m\n"
printf "\e[30;47m Backlight 47 white \e[m\n\n"

ポーリングされた入出力インタフェースのテスト

ポーリングされた入出力インタフェースは、次の状況でのみ使用できます。

  • L1+A のキーストロークシーケンスを使用して OpenBoot PROM に入る場合

  • kmdb (1) などのスタンドアロンデバッガを使用してシステムをブートする場合

  • システムがパニック状態になった場合

ポーリングされた入出力インタフェースは、ブートプロセス内の特定の時点でのみ使用可能になります。システムが稼働する前に OpenBoot PROM から発行され、ポーリングされた入出力要求は描画されません。同様に、コンソールが構成される前に発行された kmdb プロンプトは描画されません。

ポーリングされた入出力インタフェースをテストするには、L1+A のキーストロークシーケンスを使用して OpenBoot PROM に入ります。ポーリングされた入出力インタフェースが使用されていることを検証するには、OpenBoot PROM の ok プロンプトで次のコマンドを入力します。

ok 1b emit ." [32m This is a test" 1b emit ." [m"

次の文章の内容が当てはまる場合、ポーリングされた入出力インタフェースは正しく機能しています。

  • 上のコマンドを実行すると、This is a test というフレーズが緑色で表示される。

  • OpenBoot PROM が引き続き正しく機能している。

  • スクロールが予期したとおりに実行される。

  • カーソルが正しく表示される。

  • システムに繰り返し入って続行できる。

ビデオモード変更コールバック関数のテスト

ビデオモード変更コールバック関数が正しく機能するかどうかを判定するには、システムにログインし、fbconfig (1M) を使用して解像度とフレームバッファーの深さを複数回変更します。コンソールにテキストが引き続き正しく表示される場合、ビデオモード変更コールバック関数は正しく機能しています。異なる画面サイズに対応するためにカーネル端末エミュレータがフォントサイズを調整する可能性がありますが、それはコンソールフレームバッファードライバにとって重大な問題ではありません。

X Window System とコンソールフレームバッファードライバが相互に正しく作用しているかどうかを判定するには、X Window System のビデオ解像度とコマンド行の解像度を異なる方法で変更しているときに、X Window System とコマンド行を複数回切り換えます。X Window System が終了したときにコンソール文字が正しく表示されない場合は、X Window System がドライバのコンソールコードにビデオモードが変更されたことを通知しなかったか、またはドライバがカーネル端末エミュレータのビデオモード変更コールバック関数を呼び出さなかったかのどちらかです。

コンソールフレームバッファードライバをテストするための追加の提案

ブート中に、システムがカーネル端末エミュレータと互換性があるフレームバッファードライバを見つけられないか、または正常にロードできなかった場合、システムは /var/adm/messages にメッセージを送信します。これらのメッセージをモニターするには、別のウィンドウで次のコマンドを入力します。

% tail -f /var/adm/messages

ドライバをデバッグしているときの USB に関する問題を回避するには、EEPROM の input-device NVRAM 構成パラメータが、キーボードの代わりにシリアルポートを使用するように変更します。このパラメータの詳細については、eeprom (1M) のマニュアルページを参照してください。