Oracle® Solaris 11.2 デバイスドライバの記述

印刷ビューの終了

更新: 2014 年 9 月
 
 

probe() エントリポイント

自身を識別できないデバイスの場合は、probe (9E) エントリポイントで、そのハードウェアデバイスがシステム上に存在するかどうかを判定します。

probe() でデバイスのインスタンスが存在するかどうかを判定するには、probe() は、一般に attach(9E) によっても実行される多くのタスクを実行する必要があります。特に、probe() によるデバイスレジスタのマッピングが必要になることがあります。

デバイスレジスタのプローブはデバイス固有の操作ですドライバは多くの場合、ハードウェアが実際に存在することを確認するために、そのハードウェアの一連のテストを実行する必要があります。このテストの条件は、デバイスの誤った識別を回避できるほど十分に厳格である必要があります。たとえば、別のデバイスが予期したデバイスと同様に動作しているように見えるため、そのデバイスが実際には使用できないのに、存在しているように見える可能性があります。

このテストは次のフラグを返します。

  • プローブが成功した場合は、DDI_PROBE_SUCCESS

  • プローブが失敗した場合は、DDI_PROBE_FAILURE

  • プローブは失敗したが、attach(9E) を引き続き呼び出す必要がある場合は、DDI_PROBE_DONTCARE

  • 現在はインスタンスが存在しないが、将来存在する可能性がある場合は、DDI_PROBE_PARTIAL

特定のデバイスインスタンスの場合は、そのデバイスに対して probe(9E) が少なくとも 1 回成功するまで attach(9E) は呼び出されません。

probe() は複数回呼び出される可能性があるため、probe(9E) は、probe() が割り当てたすべてのリソースを解放する必要があります。ただし、probe(9E) が成功した場合でも、必ずしも attach(9E) が呼び出されるわけではありません。

ドライバの probe(9E) ルーチンで ddi_dev_is_sid(9F) を使用すると、デバイスが自身を識別できるかどうかを判定できます。ddi_dev_is_sid() は、同じデバイスの自身を識別できるバージョンおよび自身を識別できないバージョンのために記述されたドライバで有効です。

次の例は、サンプルの probe() ルーチンです。

使用例 6-3  probe (9E) ルーチン
static int
xxprobe(dev_info_t *dip)
{
    ddi_acc_handle_t dev_hdl;
    ddi_device_acc_attr_t dev_attr;
    Pio_csr *csrp;
    uint8_t csrval;

    /*
     * if the device is self identifying, no need to probe
     */
    if (ddi_dev_is_sid(dip) == DDI_SUCCESS)
    return (DDI_PROBE_DONTCARE);

    /*
     * Initalize the device access attributes and map in
     * the devices CSR register (register 0)
     */
    dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
    dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
    dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;

    if (ddi_regs_map_setup(dip, 0, (caddr_t *)&csrp, 0, sizeof (Pio_csr),
    &dev_attr, &dev_hdl) != DDI_SUCCESS)
    return (DDI_PROBE_FAILURE);

    /*
     * Reset the device
     * Once the reset completes the CSR should read back
     * (PIO_DEV_READY | PIO_IDLE_INTR)
     */
    ddi_put8(dev_hdl, csrp, PIO_RESET);
    csrval = ddi_get8(dev_hdl, csrp);

    /*
     * tear down the mappings and return probe success/failure
     */
    ddi_regs_map_free(&dev_hdl);
    if ((csrval & 0xff) == (PIO_DEV_READY | PIO_IDLE_INTR))
    return (DDI_PROBE_SUCCESS);
    else
    return (DDI_PROBE_FAILURE);
}

ドライバの probe(9E) ルーチンが呼び出されたとき、そのドライバは、プローブされているデバイスがバス上に存在するかどうかを認識していません。そのため、ドライバは、存在しないデバイスのデバイスレジスタへのアクセスを試みる可能性があります。その結果、一部のバスではバス障害が発生することがあります。

次の例は、ddi_poke8(9F) を使用してデバイスの存在をチェックする probe(9E) ルーチンを示しています。ddi_poke8() は、必要な場合はこのプロセスを支援するために親ネクサスドライバを使用して、指定された仮想アドレスへの値の書き込みを慎重に試みます。アドレスが有効でないか、またはエラーを発生させずに値を書き込むことができない場合は、エラーコードが返されます。 ddi_peek(9F)も参照してください。

この例では、デバイスレジスタをマッピングするために ddi_regs_map_setup(9F) が使用されています。

使用例 6-4   ddi_poke8(9F) を使用した probe (9E) ルーチン
static int
xxprobe(dev_info_t *dip)
{
    ddi_acc_handle_t dev_hdl;
    ddi_device_acc_attr_t dev_attr;
    Pio_csr *csrp;
    uint8_t csrval;

    /*
     * if the device is self-identifying, no need to probe
     */
    if (ddi_dev_is_sid(dip) == DDI_SUCCESS)
    return (DDI_PROBE_DONTCARE);

    /*
     * Initialize the device access attrributes and map in
     * the device's CSR register (register 0)
     */
    dev_attr.devacc_attr_version - DDI_DEVICE_ATTR_V0;
    dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
    dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;

    if (ddi_regs_map_setup(dip, 0, (caddr_t *)&csrp, 0, sizeof (Pio_csr),
    &dev_attr, &dev_hdl) != DDI_SUCCESS)
    return (DDI_PROBE_FAILURE);

    /*
     * The bus can generate a fault when probing for devices that
     * do not exist.  Use ddi_poke8(9f) to handle any faults that
     * might occur.
     *
     * Reset the device.  Once the reset completes the CSR should read
     * back (PIO_DEV_READY | PIO_IDLE_INTR)
     */
    if (ddi_poke8(dip, csrp, PIO_RESET) != DDI_SUCCESS) {
    ddi_regs_map_free(&dev_hdl);
    return (DDI_FAILURE);

    csrval = ddi_get8(dev_hdl, csrp);
    /*
     * tear down the mappings and return probe success/failure
     */
    ddi_regs_map_free(&dev_hdl);
    if ((csrval & 0xff) == (PIO_DEV_READY | PIO_IDLE_INTR))
    return (DDI_PROBE_SUCCESS);
    else
    return (DDI_PROBE_FAILURE);
}