| ナビゲーションリンクをスキップ | |
| 印刷ビューの終了 | |
|
デバイスドライバの記述 Oracle Solaris 11.1 Information Library (日本語) |
パート I Oracle Solaris プラットフォーム用デバイスドライバの設計
2. Oracle Solaris カーネルとデバイスツリー
22. ドライバのコンパイル、ロード、パッケージ化、およびテスト
23. デバイスドライバのデバッグ、テスト、およびチューニング
ドライバは、ddi_get8(9F) および ddi_put8(9F) ルーチンファミリと、ddi_regs_map_setup(9F) から返されたハンドルとを組み合わせて使用することで、デバイス間でデータを転送します。DDI フレームワークは、ホストまたはデバイスのエンディアン形式に合わせるために必要なすべてのバイトスワップを自動的に処理するとともに、デバイスで発生する可能性のあるすべての格納順序付け制約を適用します。
DDI には、8 ビット、16 ビット、32 ビット、64 ビットの各サイズでデータを転送するためのインタフェースが用意されているほか、複数の値を繰り返し転送するためのインタフェースも用意されています。ddi_get8(9F)、ddi_put8(9F)、ddi_rep_get8(9F)、および ddi_rep_put8(9F) ルーチンファミリのマニュアルページで、これらのインタフェースの一覧表や説明を参照してください。
次の例は、ドライバ内でデバイスの CSR レジスタとデータレジスタのマッピングを行なった例 7-1 に基づいたものです。このドライバの write(9E) エントリポイントは、呼び出し時にデータバッファーを一度に 1 バイトずつデバイスに書き込みます。
例 7-2 マッピングの設定: バッファー
static int
pio_write(dev_t dev, struct uio *uiop, cred_t *credp)
{
int retval;
int error = OK;
Pio *pio_p = ddi_get_soft_state(pio_softstate, getminor(dev));
if (pio_p == NULL)
return (ENXIO);
mutex_enter(&pio_p->mutex);
/*
* enable interrupts from the device by setting the Interrupt
* Enable bit in the devices CSR register
*/
ddi_put8(pio_p->csr_handle, pio_p->csr,
(ddi_get8(pio_p->csr_handle, pio_p->csr) | PIO_INTR_ENABLE));
while (uiop->uio_resid > 0) {
/*
* This device issues an IDLE interrupt when it is ready
* to accept a character; the interrupt can be cleared
* by setting PIO_INTR_CLEAR. The interrupt is reasserted
* after the next character is written or the next time
* PIO_INTR_ENABLE is toggled on.
*
* wait for interrupt (see pio_intr)
*/
cv_wait(&pio_p->cv, &pio_p->mutex);
/*
* get a character from the user's write request
* fail the write request if any errors are encountered
*/
if ((retval = uwritec(uiop)) == -1) {
error = retval;
break;
}
/*
* pass the character to the device by writing it to
* the device's data register
*/
ddi_put8(pio_p->data_handle, pio_p->data, (uchar_t)retval);
}
/*
* disable interrupts by clearing the Interrupt Enable bit
* in the CSR
*/
ddi_put8(pio_p->csr_handle, pio_p->csr,
(ddi_get8(pio_p->csr_handle, pio_p->csr) & ~PIO_INTR_ENABLE));
mutex_exit(&pio_p->mutex);
return (error);
}
Oracle Solaris OS には、ddi_get8(9F) および ddi_put8(9F) インタフェースファミリ経由ですべてのデバイスアクセスを実装する方法だけでなく、特定のバス実装に固有のインタフェースも用意されています。これらの関数は一部のプラットフォームで効率が高くなる可能性もありますが、これらのルーチンを使用すると、デバイスのさまざまなバスバージョンでのドライバの移植性が低下する可能性があります。
メモリーマップアクセスでは、デバイスレジスタがメモリーアドレス空間に現れます。ddi_getX および ddi_putX ルーチンファミリが、標準のデバイスアクセスインタフェースの代替手段としてドライバから使用可能となっています。
入出力空間アクセスでは、デバイスレジスタが入出力空間に現れます。このとき、アドレス指定可能な各要素は入出力ポートと呼ばれます。ddi_io_get8(9F) および ddi_io_put8(9F) ルーチンが、標準のデバイスアクセスインタフェースの代替手段としてドライバから使用可能となっています。
通常のデバイスアクセスインタフェースを使用しないで PCI 構成空間にアクセスするには、ドライバ内で、PCI 構成空間をマップするために、pci_config_setup(9F) の代わりに ddi_regs_map_setup(9F) を呼び出す必要があります。その後ドライバ内で、pci_config_get8(9F) および pci_config_put8(9F) インタフェースファミリを呼び出して PCI 構成空間にアクセスできます。