# 機能設計書 58-GPUドライバ

## 概要

本ドキュメントは、FreeBSDにおけるグラフィックスデバイスドライバ（DRM/KMS）の設計を記述する。DRM（Direct Rendering Manager）およびKMS（Kernel Mode Setting）フレームワークにより、GPUハードウェアの制御とグラフィックス出力を提供する。

### 本機能の処理概要

GPUドライバは、DRM（Direct Rendering Manager）フレームワークを用いてGPUハードウェアのモード設定、メモリ管理、コマンド発行を行う。FreeBSDではDRM2（Linux DRMのFreeBSD移植版）がsys/dev/drm2/に実装されている。

**業務上の目的・背景**：グラフィカルなデスクトップ環境やGPUアクセラレーションを必要とするアプリケーション（X Window System、Wayland等）の動作に、カーネルレベルのGPUドライバが必要である。KMSによるカーネル空間でのディスプレイモード設定は、安定したグラフィックス出力とユーザ空間グラフィックスドライバとの連携を実現する。

**機能の利用シーン**：Xorgサーバの起動とGPUアクセラレーション、コンソールのフレームバッファ出力、ディスプレイ解像度/リフレッシュレートの設定、マルチモニタ構成。

**主要な処理内容**：
1. GPUデバイスの検出・初期化（PCI）
2. DRMデバイスノードの作成（/dev/dri/card*）
3. GEM（Graphics Execution Manager）メモリ管理
4. TTM（Translation Table Maps）メモリ管理
5. KMS（カーネルモード設定）- CRTC/エンコーダ/コネクタ管理
6. フレームバッファ管理
7. DRM ioctl処理
8. 割り込み処理（VBlank等）
9. EDID解析（ディスプレイ情報）
10. DPヘルパー（DisplayPort補助チャネル通信）

**関連システム・外部連携**：VTコンソールドライバ（フレームバッファ連携）、X Window System/Wayland（ユーザ空間グラフィックス）、AGP/PCIeサブシステムとの連携。

**権限による制御**：DRMデバイスノード（/dev/dri/card*）へのアクセスにはvideo/drmグループの権限が必要。DRM_MASTERおよびDRM_ROOT_ONLYフラグにより特権操作を制限。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （カーネルドライバのため関連画面なし） | - | - |

## 機能種別

デバイスドライバ / グラフィックス出力 / GPU制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| PCI Device ID | uint32 | Yes | GPUのPCIデバイスID | 対応デバイスリストに一致 |
| DRM ioctl | struct | Yes | DRM制御コマンド | 有効なDRM ioctlコード |
| モード設定パラメータ | struct drm_mode_* | No | 解像度、リフレッシュレート等 | 有効なモードパラメータ |

### 入力データソース

- PCI構成空間（デバイス検出）
- DRM ioctl（ユーザ空間グラフィックスドライバ）
- EDID（ディスプレイから読み取り）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| フレームバッファ出力 | video | ディスプレイへの映像出力 |
| DRM ioctl応答 | struct | DRMコマンドの結果 |
| VBlankイベント | event | 垂直帰線期間イベント |

### 出力先

- ディスプレイ出力（HDMI/DP/VGA等）
- DRMデバイスノード（/dev/dri/card*）
- VTコンソール（フレームバッファ）
- sysctl（DRM統計情報）

## 処理フロー

### 処理シーケンス

```
1. PCI probe
   └─ GPUのPCI IDに基づくドライバマッチング
2. DRMデバイス初期化
   └─ DRMコアの初期化、デバイスノード作成
3. GPU初期化
   └─ GPU固有のハードウェア初期化
4. KMS初期化
   └─ CRTC、エンコーダ、コネクタの検出・初期化
5. EDID読み取り
   └─ 接続されたディスプレイのEDID解析
6. モード設定
   └─ 解像度・リフレッシュレートの設定
7. フレームバッファ設定
   └─ フレームバッファの割り当てとスキャンアウト設定
8. ioctl処理
   └─ ユーザ空間からのDRMコマンド処理
```

### フローチャート

```mermaid
flowchart TD
    A[PCI probe] --> B[DRM初期化]
    B --> C[GPU固有初期化]
    C --> D[KMS初期化]
    D --> E[コネクタ検出]
    E --> F[EDID読み取り]
    F --> G[モード設定]
    G --> H[フレームバッファ設定]
    H --> I[ioctl待ち受け]
    I --> J{ioctlコマンド}
    J -->|MODE_SET| K[モード変更]
    J -->|GEM_CREATE| L[GEMバッファ作成]
    J -->|PAGE_FLIP| M[ページフリップ]
    K --> I
    L --> I
    M --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | DRM_MASTER制限 | モード設定等の特権操作はDRM Master権限が必要 | KMS操作時 |
| BR-58-02 | DRM_ROOT_ONLY | 一部のioctlはrootのみ実行可能 | 管理ioctl発行時 |
| BR-58-03 | DRM_AUTH認証 | 認証済みクライアントのみGEM操作可能 | GEMバッファ操作時 |

### 計算ロジック

フレームバッファサイズ: 幅 x 高さ x BPP(Bytes Per Pixel) x バッファ数。

## データベース操作仕様

該当なし（カーネルドライバ）。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| -ENODEV | デバイス不存在 | 対応GPUが見つからない | フォールバックドライバ使用 |
| -ENOMEM | メモリ不足 | GEMバッファ割り当て失敗 | メモリ解放後リトライ |
| -EACCES | 権限エラー | DRM_MASTER/ROOT権限なし | 適切な権限で実行 |

### リトライ仕様

特になし。エラー時はユーザ空間に適切なエラーコードを返却。

## トランザクション仕様

該当なし。GEMバッファの参照カウント管理によりリソースライフサイクルを制御。

## パフォーマンス要件

- VBlank間隔内（16.67ms@60Hz）でのページフリップ完了
- GPU固有のハードウェアアクセラレーション性能

## セキュリティ考慮事項

- DRM_MASTER権限によるモード設定の制限
- DRM_AUTH認証によるGEMバッファアクセス制御
- ioctl入力のバリデーション（バッファオーバーフロー防止）

## 備考

- FreeBSDのDRM2はLinux 3.8前後のDRMをベースとした移植版
- 最新のGPUサポートにはdrm-kmod（portsから取得）が推奨される
- sys/dev/drm2/にはコアDRMフレームワークとTTMメモリマネージャが含まれる

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | drm.h | `sys/dev/drm2/drm.h` | DRM ioctl定義、基本データ構造 |
| 1-2 | drmP.h | `sys/dev/drm2/drmP.h` | DRMドライバ内部構造体 |
| 1-3 | drm_crtc.h | `sys/dev/drm2/drm_crtc.h` | KMS CRTC/エンコーダ/コネクタ構造体 |

**読解のコツ**: DRM2のコードはLinux DRMからの移植であるため、Linux APIとの互換性レイヤ（drm_os_freebsd.h）が存在する。FreeBSD固有の変更点はdrm_os_freebsd.cに集中している。

#### Step 2: DRMコアを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | drm_drv.c | `sys/dev/drm2/drm_drv.c` | DRMドライバエントリポイント |

**主要処理フロー**:
1. **56行目**: drm_global_mutex - グローバルミューテックス
2. **59-80行目**: drm_ioctls配列 - DRM ioctl定義テーブル
3. **60行目**: DRM_IOCTL_VERSION - バージョン取得
4. **63行目**: DRM_IOCTL_IRQ_BUSID - DRM_MASTER|DRM_ROOT_ONLY制限
5. **73行目**: DRM_IOCTL_AUTH_MAGIC - DRM_AUTH|DRM_MASTER制限

#### Step 3: KMS（モード設定）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | drm_crtc.c | `sys/dev/drm2/drm_crtc.c` | CRTC管理コア |
| 3-2 | drm_modes.c | `sys/dev/drm2/drm_modes.c` | ディスプレイモード管理 |
| 3-3 | drm_edid.c | `sys/dev/drm2/drm_edid.c` | EDID解析 |

#### Step 4: メモリ管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | drm_gem.c | `sys/dev/drm2/drm_gem.c` | GEMメモリ管理 |
| 4-2 | ttm/ | `sys/dev/drm2/ttm/` | TTMメモリ管理 |

### プログラム呼び出し階層図

```
ユーザ空間 (Xorg / Mesa / Wayland)
    |
    +-- ioctl(/dev/dri/card0)
        |
        +-- drm_ioctl() [drm_drv.c]
            |
            +-- drm_ioctls[] テーブルに基づくディスパッチ
                |
                +-- drm_version() (バージョン情報)
                +-- drm_setmaster() (マスター設定)
                +-- drm_mode_setcrtc() [drm_crtc.c] (モード設定)
                +-- drm_gem_open_ioctl() [drm_gem.c] (GEM操作)
                +-- drm_mode_getconnector() (コネクタ情報)

DRMフレームワーク
    +-- drm_fb_helper.c (フレームバッファヘルパー)
    +-- drm_irq.c (割り込み管理)
    +-- drm_dp_helper.c (DisplayPort)
```

### データフロー図

```
[入力]                    [処理]                         [出力]

DRM ioctl    ────▶ drm_drv.c                   ────▶ GPUレジスタ
(ユーザ空間)       drm_ioctl()ディスパッチ              (ハードウェア制御)

EDID         ────▶ drm_edid.c                  ────▶ モード情報
(ディスプレイ)     EDID解析                            (解像度一覧)

フレームバッファ ─▶ drm_crtc.c                 ────▶ ディスプレイ出力
(GEMバッファ)      スキャンアウト設定                   (映像信号)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| drm.h | `sys/dev/drm2/drm.h` | ヘッダ | DRM ioctl定義 |
| drmP.h | `sys/dev/drm2/drmP.h` | ヘッダ | DRM内部構造体 |
| drm_drv.c | `sys/dev/drm2/drm_drv.c` | ソース | DRMドライバエントリ |
| drm_crtc.c | `sys/dev/drm2/drm_crtc.c` | ソース | KMS CRTC管理 |
| drm_crtc.h | `sys/dev/drm2/drm_crtc.h` | ヘッダ | KMS構造体定義 |
| drm_modes.c | `sys/dev/drm2/drm_modes.c` | ソース | モード管理 |
| drm_edid.c | `sys/dev/drm2/drm_edid.c` | ソース | EDID解析 |
| drm_gem.c | `sys/dev/drm2/drm_gem.c` | ソース | GEMメモリ管理 |
| drm_irq.c | `sys/dev/drm2/drm_irq.c` | ソース | 割り込み管理 |
| drm_ioctl.c | `sys/dev/drm2/drm_ioctl.c` | ソース | ioctl処理 |
| drm_fb_helper.c | `sys/dev/drm2/drm_fb_helper.c` | ソース | FB連携 |
| drm_dp_helper.c | `sys/dev/drm2/drm_dp_helper.c` | ソース | DisplayPort |
| drm_os_freebsd.c | `sys/dev/drm2/drm_os_freebsd.c` | ソース | FreeBSD互換レイヤ |
| drm_pci.c | `sys/dev/drm2/drm_pci.c` | ソース | PCI接続 |
| ttm/ | `sys/dev/drm2/ttm/` | ディレクトリ | TTMメモリマネージャ |
