# 機能設計書 30-CAMストレージサブシステム

## 概要

本ドキュメントは、FreeBSDのCAM（Common Access Method）ストレージサブシステムの機能設計を記述する。CAMはSCSI、ATA、NVMe等の異なるストレージプロトコルに対して共通のアクセス層を提供するフレームワークであり、ストレージデバイスドライバとペリフェラルドライバの橋渡し役を担う。

### 本機能の処理概要

**業務上の目的・背景**：SCSI、ATA、NVMe、MMC等の異なるストレージインタフェースプロトコルに対して統一的なアクセス方法を提供する必要がある。CAMはXPT（Transport）層を中心に、SIM（SCSI Interface Module）とペリフェラルドライバを接続し、プロトコルに依存しないストレージアクセスを実現する。

**機能の利用シーン**：ハードディスク、SSD、光学ドライブ、テープドライブ等のストレージデバイスアクセス、camcontrol(8)によるデバイス管理、ストレージデバイスの検出・設定。

**主要な処理内容**：
1. XPT（Transport）層によるバスとデバイスの管理
2. CCB（CAM Control Block）によるコマンド発行・完了処理
3. SIM（SCSI Interface Module）ドライバとの通信
4. ペリフェラルドライバ（da, cd, ch, sa, pass等）の管理
5. デバイスプロービングとネゴシエーション
6. I/Oスケジューリング（cam_iosched）
7. エラーリカバリとリトライ処理

**関連システム・外部連携**：GEOMストレージフレームワーク（上位層）、各種HBAドライバ（下位層）、sbin/camcontrol（ユーザランドツール）

**権限による制御**：camcontrol操作にはroot権限が必要。passデバイス経由のSCSIコマンド発行にも権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

ストレージデバイスアクセスフレームワーク / デバイス管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path_id | path_id_t (u_int) | Yes | バスパスID | CAM_XPT_PATH_ID以外 |
| target_id | target_id_t (u_int) | Yes | ターゲットID | CAM_TARGET_WILDCARD以外（通常） |
| lun_id | lun_id_t (uint64_t) | Yes | LUN ID | CAM_LUN_WILDCARD以外（通常） |
| ccb | union ccb* | Yes | CAM Control Block | コマンドタイプに応じた検証 |

### 入力データソース

- ペリフェラルドライバからのI/Oリクエスト（xpt_action）
- camcontrol(8)からのpassデバイス経由コマンド
- HBAドライバからのデバイス検出通知

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ccb | union ccb* | コマンド完了結果を含むCCB |
| cam_status | cam_status_t | コマンド実行結果ステータス |

### 出力先

- ペリフェラルドライバへの完了コールバック
- HBAドライバへのコマンド発行（xpt_action → SIM action）

## 処理フロー

### 処理シーケンス

```
1. デバイス検出
   └─ HBAドライバ: バス登録（xpt_bus_register）
      └─ XPT: バススキャン
         └─ SCSIプローブ / ATAプローブ / NVMeプローブ
            └─ デバイス発見 → ペリフェラルドライバのprobe
               └─ attach → GEOMプロバイダ作成
2. I/Oリクエスト処理
   └─ ペリフェラルドライバ: CCB作成
      └─ xpt_action(ccb): XPTにコマンド投入
         └─ SIMドライバ: HBAにコマンド発行
            └─ HBA: デバイスにコマンド送信
               └─ 割り込み → SIM完了 → XPT完了
                  └─ ペリフェラルドライバ: 完了処理
3. エラーリカバリ
   └─ CAMステータス判定
      ├─ リトライ可能: リトライキューに投入
      ├─ ユニットアテンション: 再プローブ
      └─ 致命的エラー: エラー通知
```

### フローチャート

```mermaid
flowchart TD
    A[ペリフェラルドライバ] --> B[CCB作成]
    B --> C[xpt_action]
    C --> D[XPT: パス/ターゲット/LUN解決]
    D --> E[SIMドライバ: コマンド発行]
    E --> F[HBA: デバイスI/O]
    F --> G[割り込み: I/O完了]
    G --> H[SIM: 完了処理]
    H --> I[XPT: CCB完了通知]
    I --> J{CAMステータス}
    J -->|成功| K[ペリフェラル: 完了コールバック]
    J -->|リトライ可| L[リトライキュー]
    J -->|致命的| M[エラー通知]
    L --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-30-01 | ワイルドカードアドレス | CAM_BUS_WILDCARD/CAM_TARGET_WILDCARD/CAM_LUN_WILDCARDで範囲指定可能 | デバイススキャン時 |
| BR-30-02 | 優先度スケジューリング | CAM_PRIORITY_HOST/BUS/XPT/DEV/NORMALの優先度レベル | xpt_schedule時 |
| BR-30-03 | CDB最大長 | CAM_MAX_CDBLEN = 16バイト | SCSIコマンド発行時 |
| BR-30-04 | プロトコル自動判定 | SCSI/ATA/NVMe/MMCのプロトコルを自動検出 | デバイスプローブ時 |

### 計算ロジック

- LUNバイトスワップ: CAM_EXTLUN_BYTE_SWIZZLE(lun) - 64ビットLUNの16ビット単位バイトスワップ
- 優先度: (rl << 8) + 0x80 の形式で優先度値を計算

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

本機能はカーネル内フレームワークであり、RDBMS操作は行わない。

| 操作 | 対象データ構造 | 操作種別 | 概要 |
|-----|-------------|---------|------|
| デバイス検出 | cam_periph | CREATE | ペリフェラルデバイスの登録 |
| コマンド発行 | ccb | CREATE/READ | CCBの作成と結果取得 |
| デバイススキャン | path/target/lun | READ | バスツリーの走査 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| CAM_CMD_TIMEOUT | タイムアウト | コマンドがHBA/デバイスで完了しない | リトライまたはバスリセット |
| CAM_SEL_TIMEOUT | 選択タイムアウト | ターゲットデバイスが応答しない | デバイス接続確認 |
| CAM_SCSI_STATUS_ERROR | SCSIエラー | SCSIセンスデータを含むエラー | センスデータに基づく処理 |
| CAM_AUTOSENSE_FAIL | センス取得失敗 | REQUEST SENSE失敗 | リトライまたはバスリセット |

### リトライ仕様

cam_periph_error()によるエラー判定。リトライ可能なエラー（BUSY、UNIT ATTENTION等）は自動リトライ。リトライ回数は各ペリフェラルドライバで設定。

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

CCBは個別のI/O操作を表す原子単位。SIMドライバレベルでのコマンドキューイングとタグ付きコマンドサポート。

## パフォーマンス要件

- cam_iosched（I/Oスケジューラ）による帯域制御とレイテンシ最適化
- コマンドキューイングによる並列I/O
- 優先度ベースのスケジューリング

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

- passデバイス経由のSCSI/ATAコマンド発行にはroot権限が必要
- ATAセキュリティコマンド（パスワードロック等）のサポート

## 備考

- Justin T. Gibbsによる設計・開発（1997年）
- サブディレクトリ: ata（ATA固有）、ctl（CAM Target Layer）、mmc（MMC/SD）、nvme（NVMe固有）、scsi（SCSI固有）
- README.quirksファイルでデバイス固有の回避策を管理

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cam.h | `sys/cam/cam.h` | path_id_t/target_id_t/lun_id_t型定義（46-48行目）、ワイルドカード定数（50-53行目）、CAM_MAX_CDBLEN（64行目）、cam_rl優先度（77-84行目）、cam_pinfo構造体（89-100行目） |
| 1-2 | cam_ccb.h | `sys/cam/cam_ccb.h` | union ccb（CAM Control Block）の定義 |
| 1-3 | cam_xpt.h | `sys/cam/cam_xpt.h` | XPT APIの定義 |
| 1-4 | cam_periph.h | `sys/cam/cam_periph.h` | ペリフェラルドライバ構造体 |
| 1-5 | cam_sim.h | `sys/cam/cam_sim.h` | SIM（SCSI Interface Module）構造体 |

**読解のコツ**: CAMの基本は「ペリフェラル→XPT→SIM→HBA」の階層。path_id/target_id/lun_idの3つ組でデバイスを一意に特定する。CCBはコマンドの運搬体でunion型のため、コマンドタイプごとに異なるフィールドを持つ。

#### Step 2: XPT（Transport層）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cam_xpt.c | `sys/cam/cam_xpt.c` | XPTコア実装（xpt_action, xpt_done, バス管理） |

#### Step 3: ペリフェラルドライバを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cam_periph.c | `sys/cam/cam_periph.c` | ペリフェラルドライバ共通処理 |

#### Step 4: SIM/キューイングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | cam_sim.c | `sys/cam/cam_sim.c` | SIMモジュール管理 |
| 4-2 | cam_queue.c | `sys/cam/cam_queue.c` | コマンドキュー管理 |
| 4-3 | cam_iosched.c | `sys/cam/cam_iosched.c` | I/Oスケジューリング |

#### Step 5: プロトコル固有実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | scsi/ | `sys/cam/scsi/` | SCSI固有実装 |
| 5-2 | ata/ | `sys/cam/ata/` | ATA固有実装 |
| 5-3 | nvme/ | `sys/cam/nvme/` | NVMe固有実装 |
| 5-4 | mmc/ | `sys/cam/mmc/` | MMC/SD固有実装 |

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

```
ペリフェラルドライバ (da, cd, sa, pass等)
    │
    ├─ xpt_action(ccb) [cam_xpt.c]
    │       └─ SIM action (HBAドライバ)
    │               └─ HBA: デバイスにコマンド発行
    │                       └─ 割り込み
    │                               └─ SIM done
    │                                       └─ xpt_done(ccb) [cam_xpt.c]
    │                                               └─ periph callback
    │
    ├─ xpt_schedule(periph) [cam_xpt.c]
    │       └─ cam_iosched [cam_iosched.c]
    │
    └─ cam_periph_error() [cam_periph.c]
            └─ リトライ判定
            └─ バスリセット要求

HBAドライバ
    │
    └─ xpt_bus_register(sim) [cam_xpt.c]
            └─ バスプローブ開始
                    └─ デバイス検出
                            └─ ペリフェラル probe/attach
```

### データフロー図

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

VFS I/Oリクエスト   ───▶ ペリフェラルドライバ      ───▶ CCB作成
                          (da/cd/sa等)
                                │
                                ▼
                          XPT [cam_xpt.c]          ───▶ パス解決
                          (xpt_action)
                                │
                                ▼
                          SIM [HBAドライバ]         ───▶ HWコマンド
                          (デバイスI/O)
                                │
                                ▼
                          割り込み完了              ───▶ CCB完了
                          (xpt_done)
                                │
                                ▼
                          ペリフェラル完了          ───▶ GEOMプロバイダ
                          (コールバック)                  (I/O結果)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cam.h | `sys/cam/cam.h` | ヘッダ | 基本型・定数定義 |
| cam.c | `sys/cam/cam.c` | ソース | 共通ユーティリティ |
| cam_ccb.h | `sys/cam/cam_ccb.h` | ヘッダ | CCB定義 |
| cam_xpt.h | `sys/cam/cam_xpt.h` | ヘッダ | XPT API |
| cam_xpt.c | `sys/cam/cam_xpt.c` | ソース | XPTコア実装 |
| cam_periph.h | `sys/cam/cam_periph.h` | ヘッダ | ペリフェラルドライバ |
| cam_periph.c | `sys/cam/cam_periph.c` | ソース | ペリフェラル共通処理 |
| cam_sim.h | `sys/cam/cam_sim.h` | ヘッダ | SIM定義 |
| cam_sim.c | `sys/cam/cam_sim.c` | ソース | SIM管理 |
| cam_queue.h | `sys/cam/cam_queue.h` | ヘッダ | キュー定義 |
| cam_queue.c | `sys/cam/cam_queue.c` | ソース | キュー管理 |
| cam_iosched.h | `sys/cam/cam_iosched.h` | ヘッダ | I/Oスケジューラ |
| cam_iosched.c | `sys/cam/cam_iosched.c` | ソース | I/Oスケジューリング |
| cam_compat.c | `sys/cam/cam_compat.c` | ソース | 後方互換処理 |
| cam_debug.h | `sys/cam/cam_debug.h` | ヘッダ | デバッグ定義 |
| scsi/ | `sys/cam/scsi/` | ディレクトリ | SCSI固有実装 |
| ata/ | `sys/cam/ata/` | ディレクトリ | ATA固有実装 |
| nvme/ | `sys/cam/nvme/` | ディレクトリ | NVMe固有実装 |
| mmc/ | `sys/cam/mmc/` | ディレクトリ | MMC/SD固有実装 |
| ctl/ | `sys/cam/ctl/` | ディレクトリ | CAM Target Layer |
