以降のセクションでは、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);
}