以下各节讨论了 SCSI HBA 的中止入口点和重置入口点。
调用 SCSI HBA 驱动程序的 tran_abort(9E) 入口点可中止当前正在传输给特定目标的所有命令。目标驱动程序调用 scsi_abort(9F) 时,将会调用此入口点。
tran_abort() 入口点会尝试中止 pkt 参数表示的命令。如果 pkt 参数为 NULL,则 tran_abort() 会尝试中止传输层中针对特定目标或逻辑单元的所有未完成命令。
每个已成功中止的命令都必须标记为 pkt_reason CMD_ABORTED 以及 pkt_statistics 与 STAT_ABORTED 进行或运算所得的值。
调用 SCSI HBA 驱动程序的 tran_reset(9E) 入口点可重置 SCSI 总线或特定的 SCSI 目标设备。目标驱动程序调用 scsi_reset(9F) 时,将会调用此入口点。
如果级别为 RESET_ALL(),则 tran_reset 入口点必须重置 SCSI 总线。如果级别为 RESET_TARGET,则仅有特定目标或逻辑单元必须重置。
受重置影响的活动命令必须带有 pkt_reason CMD_RESET 标记。重置类型可确定应使用 STAT_BUS_RESET 还是使用 STAT_DEV_RESET 与 pkt_statistics 进行或运算。
在目标上尚未处于活动状态的传输层中的命令必须标记为 pkt_reason CMD_RESET 以及 pkt_statistics 与 STAT_ABORTED 进行或运算所得的值。
tran_bus_reset(9E) 必须重置 SCSI 总线而不重置目标。
#include <sys/scsi/scsi.h> int tran_bus_reset(dev_info_t *hba-dip, int level);
其中:
与 SCSI HBA 关联的指针
必须设置为 RESET_BUS,以便仅重置 SCSI 总线而不重置目标。
执行 HBA 驱动程序的 attach(9E) 的过程中,应初始化 scsi_hba_tran(9S) 结构中的 tran_bus_reset() 向量。该向量应指向用户启动总线重置时将调用的 HBA 入口点。
实现特定于硬件。如果 HBA 驱动程序无法在不影响目标的情况下重置 SCSI 总线,则驱动程序将无法执行 RESET_BUS 或不会初始化此向量。
重置 SCSI 总线时,请使用 tran_reset_notify(9E) 入口点。此函数将请求 SCSI HBA 驱动程序通过回调来通知目标驱动程序。
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);
}