ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 11.1 Information Library (日本語) |
パート I Oracle Solaris プラットフォーム用デバイスドライバの設計
2. Oracle Solaris カーネルとデバイスツリー
dump() エントリポイントと print() エントリポイント
22. ドライバのコンパイル、ロード、パッケージ化、およびテスト
23. デバイスドライバのデバッグ、テスト、およびチューニング
attach(9E) は、デバイスのインスタンスごとに、次の一般的な初期化タスクを実行します。
インスタンスごとの状態構造体の割り当て
デバイスのレジスタのマッピング
デバイス割り込みの登録
mutex と条件変数の初期化
電源管理可能なコンポーネントの作成
マイナーノードの作成
ブロックデバイスドライバは、タイプ S_IFBLK のマイナーノードを作成します。その結果、このノードを表すブロック型特殊ファイルが /devices 階層に表示されます。
ブロックデバイスの論理デバイス名は /dev/dsk ディレクトリに表示され、コントローラ番号、バスアドレス番号、ディスク番号、およびスライス番号で構成されています。ノードタイプが DDI_NT_BLOCK または DDI_NT_BLOCK_CHAN に設定されている場合、これらの名前は devfsadm(1M) プログラムによって作成されます。そのデバイスがチャネル、つまり、追加のレベルのアドレス指定能力を備えたバス上で通信する場合は、DDI_NT_BLOCK_CHAN を指定します。SCSI ディスクがその良い例です。DDI_NT_BLOCK_CHAN を指定すると、論理名にバスアドレスフィールド (tN) が表示されます。ほかのほとんどのデバイスには DDI_NT_BLOCK を使用するべきです。
マイナーデバイスは、ディスク上のパーティションを参照します。ドライバは、マイナーデバイスごとに nblocks または Nblocks プロパティーを作成する必要があります。この整数プロパティーは、DEV_BSIZE (つまり、512 バイト) の単位で表された、マイナーデバイスでサポートされているブロック数を指定します。ファイルシステムは、nblocks プロパティーと Nblocks プロパティーを使用してデバイスの制限を判定します。Nblocks は、nblocks の 64 ビットバージョンです。Nblocks は、ディスクあたり 1T バイトを超える記憶領域を保持できるストレージデバイスに使用するべきです。詳細については、「デバイスプロパティー」を参照してください。
例 16-1 は、デバイスのマイナーノードとNblocks プロパティーの作成に重点を置いて、標準的な attach(9E) エントリポイントを示したものです。この例では nblocks ではなく Nblocks を使用しているため、ddi_prop_update_int(9F) の代わりに ddi_prop_update_int64(9F) が呼び出されることに注意してください。
参考までに、この例は makedevice(9F) を使用して ddi_prop_update_int64() のデバイス番号を作成する方法を示しています。makedevice 関数は、dev_info_t 構造体へのポインタからメジャー番号を生成する ddi_driver_major(9F) を使用します。ddi_driver_major() の使用は、dev_t 構造体ポインタを取得する getmajor(9F) の使用に似ています。
例 16-1 ブロックドライバの attach() ルーチン
static int xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd) { int instance = ddi_get_instance(dip); switch (cmd) { case DDI_ATTACH: /* * allocate a state structure and initialize it * map the devices registers * add the device driver's interrupt handler(s) * initialize any mutexes and condition variables * read label information if the device is a disk * create power manageable components * * Create the device minor node. Note that the node_type * argument is set to DDI_NT_BLOCK. */ if (ddi_create_minor_node(dip, "minor_name", S_IFBLK, instance, DDI_NT_BLOCK, 0) == DDI_FAILURE) { /* free resources allocated so far */ /* Remove any previously allocated minor nodes */ ddi_remove_minor_node(dip, NULL); return (DDI_FAILURE); } /* * Create driver properties like "Nblocks". If the device * is a disk, the Nblocks property is usually calculated from * information in the disk label. Use "Nblocks" instead of * "nblocks" to ensure the property works for large disks. */ xsp->Nblocks = size; /* size is the size of the device in 512 byte blocks */ maj_number = ddi_driver_major(dip); if (ddi_prop_update_int64(makedevice(maj_number, instance), dip, "Nblocks", xsp->Nblocks) != DDI_PROP_SUCCESS) { cmn_err(CE_CONT, "%s: cannot create Nblocks property\n", ddi_get_name(dip)); /* free resources allocated so far */ return (DDI_FAILURE); } xsp->open = 0; xsp->nlayered = 0; /* ... */ return (DDI_SUCCESS); case DDI_RESUME: /* For information, see Chapter 12, "Power Management," in this book. */ default: return (DDI_FAILURE); } }