Go to main content
Oracle® Solaris 11.3 デバイスドライバの記述

印刷ビューの終了

更新: 2016 年 11 月
 
 

ユーザーマッピングへのデバイスメモリーの関連付け

デバイスメモリーをユーザーアプリケーションにエクスポートするには、ドライバの 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);

ここでは:

handle

システムがマッピングの識別子として使用する不透明なデバイスマッピングハンドル。

dip

デバイスの dev_info 構造体へのポインタ。

callbackops

マッピングに関するユーザーイベントの通知をドライバが受け取れるようにするための devmap_callback_ctl(9S) 構造体へのポインタ。

rnumber

レジスタアドレス空間セットへのインデックス番号。

roff

デバイスメモリー内へのオフセット。

len

エクスポートされる長さ (バイト)。

maxprot

ドライバが、エクスポートされるデバイスメモリー内の個々の領域ごとに保護を指定できるようにします。

flags

DEVMAP_DEFAULTS に設定する必要があります。

accattrp

ddi_device_acc_attr(9S) 構造体へのポインタ。

roff および len 引数は、レジスタセット rnumber で指定されたデバイスメモリー内の範囲を記述します。rnumber が参照するレジスタ指定は、reg プロパティーによって記述されます。レジスタセットが 1 つしかないデバイスでは、rnumber にゼロを渡します。範囲は rofflen で定義されます。この範囲は、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) が呼び出され、デバイスメモリーがアプリケーションにエクスポートされます。

使用例 39  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, &regsize) != 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);
}