SCSA HBA 接口包括 HBA 入口点、HBA 数据结构和 HBA 框架。
SCSA 定义了许多 HBA 驱动程序入口点。下表中列出了这些入口点。配置连接到 HBA 驱动程序的目标驱动程序实例时,系统将会调用这些入口点。另外,目标驱动程序发出 SCSA 请求时,也会调用这些入口点。有关更多信息,请参见SCSA HBA 驱动程序入口点。
表 18–1 SCSA HBA 入口点摘要
函数名 |
调用原因 |
---|---|
目标驱动程序调用 scsi_abort(9F) |
|
系统重置总线 |
|
目标驱动程序调用 scsi_destroy_pkt(9F) |
|
目标驱动程序调用 scsi_dmafree(9F) |
|
目标驱动程序调用 scsi_ifgetcap(9F) |
|
目标驱动程序调用 scsi_init_pkt(9F) |
|
系统使总线处于静止状态 |
|
目标驱动程序调用 scsi_reset(9F) |
|
目标驱动程序调用 scsi_reset_notify(9F) |
|
目标驱动程序调用 scsi_ifsetcap(9F) |
|
目标驱动程序调用 scsi_transport(9F) |
|
目标驱动程序调用 scsi_sync_pkt(9F) |
|
tran_tgt_free(9E) |
系统分离目标设备实例 |
tran_tgt_init(9E) |
系统连接目标设备实例 |
tran_tgt_probe(9E) |
目标驱动程序调用 scsi_probe(9F) |
系统恢复总线上的活动 |
SCSA 定义了多种数据结构,以便可在目标驱动程序和 HBA 驱动程序之间交换信息。其中包括以下数据结构:
HBA 驱动程序的每个实例都必须在 attach(9E) 入口点中使用 scsi_hba_tran_alloc(9F) 函数分配 scsi_hba_tran(9S) 结构。scsi_hba_tran_alloc() 函数可初始化 scsi_hba_tran 结构。HBA 驱动程序必须初始化传输结构中的特定向量才能指向 HBA 驱动程序中的入口点。初始化 scsi_hba_tran 结构后,HBA 驱动程序通过调用 scsi_hba_attach_setup(9F) 函数将传输结构导出到 SCSA。
由于 SCSA 将指向传输结构的指针保存在 devinfo 节点的驱动程序专用字段中,因此 HBA 驱动程序决不能使用 ddi_set_driver_private(9F)。但是,HBA 驱动程序可以使用 ddi_get_driver_private(9F) 来检索指向传输结构的指针。
SCSA 接口要求 HBA 驱动程序提供许多可通过 scsi_hba_tran 结构调用的入口点。有关更多信息,请参见SCSA HBA 驱动程序入口点。
scsi_hba_tran 结构包含以下字段:
struct scsi_hba_tran { dev_info_t *tran_hba_dip; /* HBAs dev_info pointer */ void *tran_hba_private; /* HBA softstate */ void *tran_tgt_private; /* HBA target private pointer */ struct scsi_device *tran_sd; /* scsi_device */ int (*tran_tgt_init)(); /* Transport target */ /* Initialization */ int (*tran_tgt_probe)(); /* Transport target probe */ void (*tran_tgt_free)(); /* Transport target free */ int (*tran_start)(); /* Transport start */ int (*tran_reset)(); /* Transport reset */ int (*tran_abort)(); /* Transport abort */ int (*tran_getcap)(); /* Capability retrieval */ int (*tran_setcap)(); /* Capability establishment */ struct scsi_pkt *(*tran_init_pkt)(); /* Packet and DMA allocation */ void (*tran_destroy_pkt)(); /* Packet and DMA */ /* Deallocation */ void (*tran_dmafree)(); /* DMA deallocation */ void (*tran_sync_pkt)(); /* Sync DMA */ void (*tran_reset_notify)(); /* Bus reset notification */ int (*tran_bus_reset)(); /* Reset bus only */ int (*tran_quiesce)(); /* Quiesce a bus */ int (*tran_unquiesce)(); /* Unquiesce a bus */ int tran_interconnect_type; /* transport interconnect */ };
下面的描述提供了有关这些 scsi_hba_tran 结构字段的更多信息:
指向 HBA 设备实例 dev_info 结构的指针。函数 scsi_hba_attach_setup(9F) 可用于设置此字段。
指向 HBA 驱动程序维护的专用数据的指针。通常,tran_hba_private 包含指向 HBA 驱动程序状态结构的指针。
指向使用克隆时 HBA 驱动程序维护的专用数据的指针。通过在调用 scsi_hba_attach_setup(9F) 时指定 SCSI_HBA_TRAN_CLONE,可对每个目标克隆一次 scsi_hba_tran(9S) 结构。借助该方法,HBA 可将此字段初始化为指向 tran_tgt_init(9E) 入口点中按目标实例的数据结构。如果未指定 SCSI_HBA_TRAN_CLONE,则 tran_tgt_private 为 NULL,并且决不能引用 tran_tgt_private。有关更多信息,请参见传输结构克隆。
指向克隆时使用的按目标实例的 scsi_device(9S) 结构的指针。如果将 SCSI_HBA_TRAN_CLONE 传递给 scsi_hba_attach_setup(9F),则 tran_sd 会初始化指向按目标的 scsi_device 结构。在代表目标调用任何 HBA 函数之前,将进行此初始化。如果未指定 SCSI_HBA_TRAN_CLONE,则 tran_sd 为 NULL,并且决不能引用 tran_sd。有关更多信息,请参见传输结构克隆。
指向初始化目标设备实例时调用的 HBA 驱动程序入口点的指针。如果无需进行按目标的初始化,则 HBA 可保持将 tran_tgt_init 设置为 NULL。
指向在目标驱动程序实例调用 scsi_probe(9F) 时调用的 HBA 驱动程序入口点的指针。调用该例程可探测目标设备是否存在。如果此 HBA 无需进行目标探测自定义,则 HBA 应将 tran_tgt_probe 设置为 scsi_hba_probe(9F)。
指向在目标设备实例被销毁时调用的 HBA 驱动程序入口点的指针。如果无需进行按目标的取消分配,则 HBA 可保持将 tran_tgt_free 设置为 NULL。
指向在目标驱动程序调用 scsi_transport(9F) 时调用的 HBA 驱动程序入口点的指针。
指向在目标驱动程序调用 scsi_reset(9F) 时调用的 HBA 驱动程序入口点的指针。
指向在目标驱动程序调用 scsi_abort(9F) 时调用的 HBA 驱动程序入口点的指针。
指向在目标驱动程序调用 scsi_ifgetcap(9F) 时调用的 HBA 驱动程序入口点的指针。
指向在目标驱动程序调用 scsi_ifsetcap(9F) 时调用的 HBA 驱动程序入口点的指针。
指向在目标驱动程序调用 scsi_init_pkt(9F) 时调用的 HBA 驱动程序入口点的指针。
指向在目标驱动程序调用 scsi_destroy_pkt(9F) 时调用的 HBA 驱动程序入口点的指针。
指向在目标驱动程序调用 scsi_dmafree(9F) 时调用的 HBA 驱动程序入口点的指针。
指向在目标驱动程序调用 scsi_sync_pkt(9F) 时调用的 HBA 驱动程序入口点的指针。
指向在目标驱动程序调用 tran_reset_notify(9E) 时调用的 HBA 驱动程序入口点的指针。
重置 SCSI 总线但不重置目标的函数项。
等待所有未完成的命令完成并阻塞(或排队)任何发出的 I/O 请求的函数项。
允许 I/O 活动在 SCSI 总线上恢复的函数项。
表示 services.h 头文件中定义的传输互连类型的整数值。
scsi_address(9S) 结构可为目标驱动程序实例分配和传输的各个 SCSI 命令提供传输及寻址信息。
scsi_address 结构包含以下字段:
struct scsi_address { struct scsi_hba_tran *a_hba_tran; /* Transport vectors */ ushort_t a_target; /* Target identifier */ uchar_t a_lun; /* LUN on that target */ uchar_t a_sublun; /* Sub LUN on that LUN */ /* Not used */ };
指向 HBA 驱动程序分配和初始化的 scsi_hba_tran(9S) 结构的指针。如果将 SCSI_HBA_TRAN_CLONE 指定为 scsi_hba_attach_setup(9F) 的标志, 则 a_hba_tran 指向该结构的副本。
标识 SCSI 总线上的 SCSI 目标。
标识 SCSI 目标的 SCSI 逻辑单元。
HBA 框架可为目标设备的各个实例分配和初始化 scsi_device(9S) 结构。该框架调用 HBA 驱动程序的 tran_tgt_init(9E) 入口点之前,将进行分配和初始化。此结构可存储有关每个 SCSI 逻辑单元的信息,包括指向信息区(包含通用信息和特定于设备的信息)的指针。对于连接到系统的每个目标设备实例,都存在一个 scsi_device(9S) 结构。
如果按目标的初始化成功,则 HBA 框架会使用 ddi_set_driver_private(9F) 将目标驱动程序的按实例的专用数据设置为指向 scsi_device(9S) 结构。请注意,如果 tran_tgt_init () 返回成功信息或该向量为 null,则表明初始化成功。
scsi_device(9S) 结构包含以下字段:
struct scsi_device { struct scsi_address sd_address; /* routing information */ dev_info_t *sd_dev; /* device dev_info node */ kmutex_t sd_mutex; /* mutex used by device */ void *sd_reserved; struct scsi_inquiry *sd_inq; struct scsi_extended_sense *sd_sense; caddr_t sd_private; /* for driver's use */ };
其中:
为了进行 SCSI 资源分配而传递给例程的数据结构。
指向目标的 dev_info 结构的指针。
供目标驱动程序使用的互斥锁。此互斥锁通过 HBA 框架进行初始化。目标驱动程序可将此互斥锁用作按设备的互斥锁。在调用 scsi_transport(9F) 或 scsi_poll(9F) 期间,不应持有此互斥锁。有关互斥锁的更多信息,请参见第 3 章。
目标设备的 SCSI 查询数据的指针。scsi_probe(9F) 例程可用于分配缓冲区、填充该缓冲区并将该缓冲区附加到此字段。
指向用于包含设备中的请求检测数据的缓冲区的指针。目标驱动程序必须分配和管理此缓冲区本身。有关更多信息,请参见attach() 入口点中目标驱动程序的 attach(9E) 例程。
供目标驱动程序使用的指针字段。此字段通常用于存储指向专用目标驱动程序状态结构的指针。
要执行 SCSI 命令,目标驱动程序必须首先为该命令分配 scsi_pkt(9S) 结构。然后,目标驱动程序必须指定其自身的专用数据区长度、命令状态和命令长度。HBA 驱动程序负责实现 tran_init_pkt(9E) 入口点中的包分配。另外,HBA 驱动程序还负责释放其 tran_destroy_pkt(9E) 入口点中的包。有关更多信息,请参见scsi_pkt 结构(目标驱动程序)。
scsi_pkt(9S) 结构包含以下字段:
struct scsi_pkt { opaque_t pkt_ha_private; /* private data for host adapter */ struct scsi_address pkt_address; /* destination address */ opaque_t pkt_private; /* private data for target driver */ void (*pkt_comp)(struct scsi_pkt *); /* completion routine */ uint_t pkt_flags; /* flags */ int pkt_time; /* time allotted to complete command */ uchar_t *pkt_scbp; /* pointer to status block */ uchar_t *pkt_cdbp; /* pointer to command block */ ssize_t pkt_resid; /* data bytes not transferred */ uint_t pkt_state; /* state of command */ uint_t pkt_statistics; /* statistics */ uchar_t pkt_reason; /* reason completion called */ };
其中:
指向按命令的 HBA 驱动程序专用数据的指针。
指向用于为此命令提供地址信息的 scsi_address(9S) 结构的指针。
指向按包的目标驱动程序专用数据的指针。
指向在传输层完成此命令时 HBA 驱动程序调用的目标驱动程序完成例程的指针。
命令的标志。
指定命令的完成超时时间(以秒为单位)。
指向命令的状态完成块的指针。
指向命令的命令描述符块 (command descriptor block, CDB) 的指针。
命令完成时未传送的数据字节计数。此字段也可能会用于指定尚未分配资源的数据量。在传输过程中,HBA 必须修改此字段。
命令的状态。在传输过程中,HBA 必须修改此字段。
提供命令在传输层中发生的事件的历史记录。在传输过程中,HBA 必须修改此字段。
命令完成的原因。在传输过程中,HBA 必须修改此字段。
在执行 attach(9E) 期间,HBA 驱动程序必须分配 scsi_hba_tran(9S) 结构。然后,HBA 驱动程序必须将此传输结构中的向量初始化为指向 HBA 驱动程序所需的入口点。此 scsi_hba_tran 结构随后将传递给 scsi_hba_attach_setup(9F)。
scsi_hba_tran 结构包含 tran_hba_private 字段,该字段可用于引用 HBA 驱动程序的按实例状态。
每个 scsi_address(9S) 结构都包含一个指向 scsi_hba_tran 结构的指针。此外,scsi_address 结构还为特定的目标设备提供了目标(即 a_target)和逻辑单元 (a_lun) 地址。 通过 scsi_device(9S) 结构可直接或间接向 HBA 驱动程序的每个入口点传递一个指向 scsi_address 结构的指针。因此,HBA 驱动程序可以引用其自身的状态。HBA 驱动程序还可以标识已寻址的目标设备。
下图说明了用于传输操作的 HBA 数据结构。
如果 HBA 驱动程序需要维护 scsi_hba_tran(9S) 结构中按目标的专用数据,则克隆可能会非常有用。克隆还可用于维护比 scsi_address(9S) 结构中所提供的更为复杂的地址。
在克隆过程中,HBA 驱动程序仍必须在执行 attach(9E) 期间分配 scsi_hba_tran 结构。此外,HBA 驱动程序还必须初始化 HBA 驱动程序的 tran_hba_private 软状态指针和入口点向量。当框架开始将目标驱动程序实例连接到 HBA 驱动程序时,将会产生差异。调用 HBA 驱动程序的 tran_tgt_init(9E) 入口点之前,框架会克隆与 HBA 的该实例关联的 scsi_hba_tran 结构。相应地,为特定目标设备实例分配和初始化的每个 scsi_address 结构都会指向 scsi_hba_tran 结构的按目标实例的副本。scsi_address 结构不会指向 HBA 驱动程序在执行 attach() 期间分配的 scsi_hba_tran 结构。
指定克隆时,HBA 驱动程序可以使用两个重要的指针。这些指针包含在 scsi_hba_tran 结构中。第一个指针是 tran_tgt_private 字段,驱动程序可以使用该指针指向按目标的 HBA 专用数据。tran_tgt_private 指针非常有用,例如在 HBA 驱动程序需要维护比 a_target 和 a_lun 所提供的更为复杂的地址的情况下。第二个指针是 tran_sd 字段,该指针指向引用特定目标设备的 scsi_device(9S) 结构。
指定克隆时,HBA 驱动程序必须分配和初始化按目标的数据。HBA 驱动程序随后必须在执行其 tran_tgt_init(9E) 入口点过程中将 tran_tgt_private 字段初始化为指向此数据。 HBA 驱动程序必须在执行其 tran_tgt_free(9E) 入口点过程中释放按目标的数据。
克隆时,框架会在调用 HBA 驱动程序 tran_tgt_init() 入口点之前将 tran_sd 字段初始化为指向 scsi_device 结构。该驱动程序通过将 SCSI_HBA_TRAN_CLONE 标志传递给 scsi_hba_attach_setup(9F) 来请求克隆。下图说明了用于克隆传输操作的 HBA 数据结构。
SCSA 还提供了许多函数。下表中列出了这些函数,供 HBA 驱动程序使用。
表 18–2 SCSA HBA 函数
函数名 |
进行调用的驱动程序入口点 |
---|---|