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 必须修改此字段。