ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 10 8/11 Information Library (日本語) |
パート I Solaris プラットフォーム用デバイスドライバの設計
ユーザーアクセス用にエクスポートされたカーネルメモリーの解放
21. ドライバのコンパイル、ロード、パッケージ化、およびテスト
デバイスメモリーをユーザーアプリケーションにエクスポートするには、ドライバの devmap(9E) エントリポイントから devmap_devmem_setup(9F) を呼び出します。
devmap_devmem_setup(9F) 関数の構文は次のとおりです。
int devmap_devmem_setup(devmap_cookie_t handle, dev_info_t *dip, struct devmap_callback_ctl *callbackops, uint_t rnumber, offset_t roff, size_t len, uint_t maxprot, uint_t flags, ddi_device_acc_attr_t *accattrp);
各表記の意味は次のとおりです。
システムがマッピングの識別子として使用する不透明なデバイスマッピングハンドル。
デバイスの dev_info 構造体へのポインタ。
マッピングに関するユーザーイベントの通知をドライバが受け取れるようにするための devmap_callback_ctl(9S) 構造体へのポインタ。
レジスタアドレス空間セットへのインデックス番号。
デバイスメモリー内へのオフセット。
エクスポートされる長さ (バイト)。
ドライバが、エクスポートされるデバイスメモリー内の個々の領域ごとに保護を指定できるようにします。
DEVMAP_DEFAULTS に設定する必要があります。
ddi_device_acc_attr(9S) 構造体へのポインタ。
roff および len 引数は、レジスタセット rnumber で指定されたデバイスメモリー内の範囲を記述します。rnumber が参照するレジスタ指定は、reg プロパティーによって記述されます。レジスタセットが 1 つしかないデバイスでは、rnumber にゼロを渡します。範囲は roff と len で定義されます。この範囲は、devmap(9E) エントリポイントから渡された offset の位置で、ユーザーのアプリケーションマッピングからアクセス可能となります。通常、ドライバは devmap(9E) のオフセットを devmap_devmem_setup(9F) に直接渡します。このとき、mmap(2) から返されるアドレスは、レジスタセットの先頭アドレスにマップします。
ドライバは maxprot 引数を使用することで、エクスポートされるデバイスメモリー内の個々の領域ごとに保護を指定できます。たとえば、ある領域の書き込みアクセス権を拒否するには、その領域で PROT_READ と PROT_USER のみを設定します。
次の例は、デバイスメモリーをアプリケーションにエクスポートする方法を示したものです。ドライバはまず、要求されたマッピングがデバイスメモリーの領域内に収まっているかどうかを判定します。デバイスメモリーのサイズは、ddi_dev_regsize(9F) を使用して判定します。マッピングの長さは、ptob(9F) および btopr(9F) を使用してページサイズの倍数に切り上げられます。その後、devmap_devmem_setup(9F) が呼び出され、デバイスメモリーがアプリケーションにエクスポートされます。
例 10-3 devmap_devmem_setup() ルーチンの使用
static int xxdevmap(dev_t dev, devmap_cookie_t handle, offset_t off, size_t len, size_t *maplen, uint_t model) { struct xxstate *xsp; int error, rnumber; off_t regsize; /* Set up data access attribute structure */ struct ddi_device_acc_attr xx_acc_attr = { DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC }; xsp = ddi_get_soft_state(statep, getminor(dev)); if (xsp == NULL) return (-1); /* use register set 0 */ rnumber = 0; /* get size of register set */ if (ddi_dev_regsize(xsp->dip, rnumber, ®size) != DDI_SUCCESS) return (-1); /* round up len to a multiple of a page size */ len = ptob(btopr(len)); if (off + len > regsize) return (-1); /* Set up the device mapping */ error = devmap_devmem_setup(handle, xsp->dip, NULL, rnumber, off, len, PROT_ALL, DEVMAP_DEFAULTS, &xx_acc_attr); /* acknowledge the entire range */ *maplen = len; return (error); }