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

印刷ビューの終了

更新: 2014 年 9 月
 
 

中止およびリセット管理

以降のセクションでは、SCSI HBA の中止とリセットのエントリポイントについて説明します。

tran_abort() エントリポイント

SCSI HBA の tran_abort(9E) エントリポイントは、特定のターゲットに対して現在トランスポート中のコマンドを中止するために呼び出されます。このエントリポイントは、ターゲットドライバがscsi_abort (9F) を呼び出したときに呼び出されます。

tran_abort() エントリポイントは、pkt パラメータで示されたコマンドの中止を試みます。pkt パラメータが NULL の場合、tran_abort() は特定のターゲットまたは論理ユニットのトランスポート層にある未処理のコマンドをすべて中止しようとします。

正常に中止された各コマンドは、pkt_reason CMD_ABORTED と、STAT_ABORTED との論理和がとられた pkt_statistics でマーク付けされます。

tran_reset() エントリポイント

SCSI HBA ドライバの tran_reset(9E) エントリポイントは、SCSI バスまたは特定の SCSI ターゲットデバイスをリセットするために呼び出されます。このエントリポイントは、ターゲットドライバがscsi_reset (9F) を呼び出したときに呼び出されます。

tran_reset() エントリポイントは、レベルが RESET_ALL の場合に SCSI バスをリセットする必要があります。レベルが RESET_TARGET の場合は、特定のターゲットまたは論理ユニットのみをリセットする必要があります。

リセットの影響を受けるアクティブなコマンドは、pkt_reason CMD_RESET でマーク付けされます。リセットの種類によって、STAT_BUS_RESET または STAT_DEV_RESET のどちらと、pkt_statistics との論理和をとるかが決まります。

トランスポート層にあり、まだターゲット上でアクティブになっていないコマンドは、pkt_reason CMD_RESET と、STAT_ABORTED との論理和が取得された pkt_statistics でマーク付けされる必要があります。

tran_bus_reset() エントリポイント

tran_bus_reset(9E) は、ターゲットをリセットしないで SCSI バスをリセットする必要があります。

#include <sys/scsi/scsi.h>

int tran_bus_reset(dev_info_t *hba-dip, int level);

ここでは:

*hba-dip

SCSI HBA に関連付けられたポインタです

level

ターゲットはリセットされず、SCSI バスのみがリセットされるように、RESET_BUS に設定します

scsi_hba_tran(9S) 構造体の tran_bus_reset() ベクトルは、HBA ドライバのattach(9E) の実行中に初期化されます。このベクトルは、ユーザーがバスのリセットを開始したときに呼び出される予定の HBA エントリポイントを指します。

実装方法はハードウェアによって異なります。HBA ドライバがターゲットに影響を与えずに SCSI バスをリセットできない場合、ドライバは RESET_BUS に失敗するか、このベクトルの初期化を行いません。

tran_reset_notify() エントリポイント

tran_reset_notify(9E) エントリポイントは、SCSI バスのリセットが行われたときに使用します。この関数は、コールバックによってターゲットドライバに通知するように SCSI HBA ドライバに要求します。

使用例 18-12  HBA ドライバの tran_reset_notify (9E) エントリポイント
isp_scsi_reset_notify(
    struct scsi_address    *ap,
    int                    flag,
    void                   (*callback)(caddr_t),
    caddr_t                arg)
{
    struct isp                       *isp;
    struct isp_reset_notify_entry    *p, *beforep;
    int                              rval = DDI_FAILURE;

    isp = (struct isp *)ap->a_hba_tran->tran_hba_private;
    mutex_enter(ISP_REQ_MUTEX(isp));
    /*
     * Try to find an existing entry for this target
     */
    p = isp->isp_reset_notify_listf;
    beforep = NULL;

    while (p) {
        if (p->ap == ap)
            break;
        beforep = p;
        p = p->next;
    }

    if ((flag & SCSI_RESET_CANCEL) && (p != NULL)) {
        if (beforep == NULL) {
            isp->isp_reset_notify_listf = p->next;
        } else {
            beforep->next = p->next;
        }
        kmem_free((caddr_t)p, sizeof (struct isp_reset_notify_entry));
        rval = DDI_SUCCESS;
    } else if ((flag & SCSI_RESET_NOTIFY) && (p == NULL)) {
        p = kmem_zalloc(sizeof (struct isp_reset_notify_entry),
          KM_SLEEP);
        p->ap = ap;
        p->callback = callback;
        p->arg = arg;
        p->next = isp->isp_reset_notify_listf;
        isp->isp_reset_notify_listf = p;
        rval = DDI_SUCCESS;
    }
    mutex_exit(ISP_REQ_MUTEX(isp));
    return (rval);
}