Skip to content

Instantly share code, notes, and snippets.

@tsutsui
Created February 21, 2026 07:02
Show Gist options
  • Select an option

  • Save tsutsui/65570a9fd67a0e57a4eb7c56969136e2 to your computer and use it in GitHub Desktop.

Select an option

Save tsutsui/65570a9fd67a0e57a4eb7c56969136e2 to your computer and use it in GitHub Desktop.

以下は、あなたが挙げた 3 つの参照(デバドラ書き方・genfb_pci.cgenfb_machdep.c)の“やり方”に合わせて、ISA VGA(VESA LFB 前提)で genfb を wsdisplay フレームバッファコンソールとして使うための

  • src/sys/dev/isa/genfb_isa.c設計書(要点)
  • 実装(KNF寄り)

を、NetBSD/x86(i386/amd64)限定としてまとめたものです。


設計書:genfb_isa の狙いと前提

1) 目的とスコープ

  • 目的: 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 がコンソール選択を確定」という流れに乗るのが今回の設計の中核です。


2) 依存関係(情報ソース)

  • LFB の諸元は bootinfostruct 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)


3) アタッチ条件(衝突回避方針)

ISA の “display-class” の自動判定は PCI ほど強くできないため、衝突回避は 保守的にします。

match 条件(全部満たす)

  1. x86(i386/amd64)であること
  2. genfb_is_enabled() が真(genfb 無効化されていない)(ftp.iij.ad.jp)
  3. BTINFO_FRAMEBUFFER が存在し physaddr != 0 (ftp.iij.ad.jp)
  4. vbemode != 0(VBE モード番号がある=VESA VBE 経由っぽい)(ftp.iij.ad.jp)
  5. genfb_is_console() が真(つまり consinit が genfb をコンソールとして選んでいる)(ftp.iij.ad.jp)

→ これにより、シリアルコンソール別の FB ドライバがコンソールのケースでは基本的にアタッチしません。


4) プロパティ設計(genfb へ渡す契約)

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)へ書く簡易実装を載せます。

5) メモリマップ戦略

  • genfb 本体は FB の KVA を自動マップしないので、フロントエンドが

    • bus_space_map(BUS_SPACE_MAP_LINEAR) で FB をマップし
    • bus_space_vaddr()sc_gen.sc_fbaddr を設定
    • genfb_attach() を呼ぶ という流れにします(genfb_pci と同様の役割分担の考え方)。

実装:src/sys/dev/isa/genfb_isa.c

[省略]


組み込みに必要な周辺(最小)

1) カーネルコンフィグ

例(LEGACY っぽい環境を想定):

genfb*	at isa?
wsdisplay*	at genfb?

pcdisplay/vga と競合させたくないなら、コンソール選択を genfb に寄せる(ブートローダで VESA モード使用)+ pcdisplay を外す等を検討。

2) files 追加

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_consolegenfb_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“最低限動く・衝突しにくい” ラインです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment