以下は、あなたが挙げた 3 つの参照(デバドラ書き方・genfb_pci.c・genfb_machdep.c)の“やり方”に合わせて、ISA VGA(VESA LFB 前提)で genfb を wsdisplay フレームバッファコンソールとして使うための
src/sys/dev/isa/genfb_isa.cの設計書(要点)- 実装(KNF寄り)
を、NetBSD/x86(i386/amd64)限定としてまとめたものです。
-
目的: x86 のブートローダが VESA VBE で設定した Linear Framebuffer (LFB) の情報(
BTINFO_FRAMEBUFFER)を使い、ISA バス上にぶら下がる レガシー VGA 環境でもgenfb(4)をアタッチしてwsdisplay(4)を提供する。 -
非目的:
- カーネルから VBE BIOS を呼んで モード変更はしない(それはブートローダ側の仕事)。
- VGA 互換のバンク切替 FB は対象外(LFB 前提)。
x86 のコンソール初期化 consinit は、BTINFO_FRAMEBUFFER があり物理アドレスがあれば x86_genfb_cnattach を試し、成功したら genfb_cnattach により genfb がコンソール選択済みであることを示します(後段で genfb_is_console() が真になる)。(ftp.iij.ad.jp)
この「先に consinit がコンソール選択を確定」という流れに乗るのが今回の設計の中核です。
-
LFB の諸元は bootinfo の
struct btinfo_framebufferを読む。フィールド(physaddr/width/height/stride/depth/vbemodeなど)はここで定義されています。(ftp.iij.ad.jp) -
genfb 本体はデバイスプロパティ(proplib)から
"width","height","depth","address","linebytes"を読んで初期化します。(ftp.iij.ad.jp)
-
wsdisplayの mmap は、genfb 側がgenfb_ops.genfb_mmapを呼び出す形でフロントエンドに委譲できます(未提供なら-1返し)。(ftp.iij.ad.jp) -
genfb_opsでフロントエンドが差し込めるフックはこの構造体。(ftp.iij.ad.jp)
ISA の “display-class” の自動判定は PCI ほど強くできないため、衝突回避は 保守的にします。
match 条件(全部満たす)
- x86(i386/amd64)であること
genfb_is_enabled()が真(genfb 無効化されていない)(ftp.iij.ad.jp)BTINFO_FRAMEBUFFERが存在しphysaddr != 0(ftp.iij.ad.jp)vbemode != 0(VBE モード番号がある=VESA VBE 経由っぽい)(ftp.iij.ad.jp)genfb_is_console()が真(つまり consinit が genfb をコンソールとして選んでいる)(ftp.iij.ad.jp)
→ これにより、シリアルコンソールや 別の FB ドライバがコンソールのケースでは基本的にアタッチしません。
device_properties(self) に以下を設定します(genfb 本体が読むキーに合わせる)(ftp.iij.ad.jp)
必須:
"width"=fbinfo->width"height"=fbinfo->height"depth"=fbinfo->depth"linebytes"=fbinfo->stride"address"=fbinfo->physaddr(uint64)
任意(あると嬉しい):
"is_console"=genfb_is_console()(真)"virtual_address"= 既に consinit がマップ済みならその KVA(今回は 未設定でも可。設定されていない場合は本ドライバでbus_space_mapしてsc_fbaddrを埋める)"clear-screen"= false(コンソール上の既存表示を消さない)
色(8bpp 対応のため):
"cmap_callback"にstruct genfb_colormap_callback *を詰めると、genfb がパレット更新で呼びます(genfb はcmap_callbackを uint64 として受け取ってポインタ化)。(ftp.iij.ad.jp) 今回は ISA VGA の DAC ポート(0x3c8/0x3c9)へ書く簡易実装を載せます。
-
genfb 本体は FB の KVA を自動マップしないので、フロントエンドが
bus_space_map(BUS_SPACE_MAP_LINEAR)で FB をマップしbus_space_vaddr()でsc_gen.sc_fbaddrを設定genfb_attach()を呼ぶ という流れにします(genfb_pci と同様の役割分担の考え方)。
[省略]
例(LEGACY っぽい環境を想定):
genfb* at isa?
wsdisplay* at genfb?
※ pcdisplay/vga と競合させたくないなら、コンソール選択を genfb に寄せる(ブートローダで VESA モード使用)+ pcdisplay を外す等を検討。
sys/dev/isa/files.isa 相当に 1 行追加するのが典型です(名称はあなたのツリーの流儀に合わせてください):
file dev/isa/genfb_isa.c genfb & isa- 「ISA VGA で VESA LFB」が本当に成立するかは、実機/BIOS/ブートローダ次第です。カーネルは
BTINFO_FRAMEBUFFERを信じるだけなので、LFB が取れていない環境では当然動きません。struct btinfo_framebufferの定義(vbemode等)を前提にしています。(ftp.iij.ad.jp) - mmap は genfb からフロントエンドへ委譲されるので、提供しないと userland mmap は基本死にます(今回
genfb_ops.genfb_mmapを実装)。(ftp.iij.ad.jp) - 8bpp で色が欲しい場合、DAC を叩く callback が必要です(今回の最小実装)。genfb は callback があれば
putpalreg経由で呼びます。(ftp.iij.ad.jp) is_consoleをgenfb_is_console()に追随させるのが衝突回避の肝です。genfb_is_console()はgenfb_cnattach()呼び出しの有無で決まります。(ftp.iij.ad.jp)
必要なら、次の段階として「btinfo_framebuffer の rpos/rnum を genfb の rasops_info に忠実に反映する(現状 genfb は is_bgr/is_10bit くらいしか見ない)」とか、「device_register 的に ISA 側でもプロパティ注入したい」などの方向にも拡張できますが、まずは上の genfb_isa.c が “最低限動く・衝突しにくい” ラインです。