以降のセクションでは、SCSI HBA の中止とリセットのエントリポイントについて説明します。
SCSI HBA の tran_abort(9E) エントリポイントは、特定のターゲットに対して現在トランスポート中のコマンドを中止するために呼び出されます。このエントリポイントは、ターゲットドライバがscsi_abort (9F) を呼び出したときに呼び出されます。
tran_abort() エントリポイントは、pkt パラメータで示されたコマンドの中止を試みます。pkt パラメータが NULL の場合、tran_abort() は特定のターゲットまたは論理ユニットのトランスポート層にある未処理のコマンドをすべて中止しようとします。
正常に中止された各コマンドは、pkt_reason CMD_ABORTED と、STAT_ABORTED との論理和がとられた pkt_statistics でマーク付けされます。
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(9E) は、ターゲットをリセットしないで SCSI バスをリセットする必要があります。
#include <sys/scsi/scsi.h> int tran_bus_reset(dev_info_t *hba-dip, int level);
ここでは:
SCSI HBA に関連付けられたポインタです
ターゲットはリセットされず、SCSI バスのみがリセットされるように、RESET_BUS に設定します
scsi_hba_tran(9S) 構造体の tran_bus_reset() ベクトルは、HBA ドライバのattach(9E) の実行中に初期化されます。このベクトルは、ユーザーがバスのリセットを開始したときに呼び出される予定の HBA エントリポイントを指します。
実装方法はハードウェアによって異なります。HBA ドライバがターゲットに影響を与えずに SCSI バスをリセットできない場合、ドライバは RESET_BUS に失敗するか、このベクトルの初期化を行いません。
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); }