SCSI HBA 驱动程序的 tran_getcap(9E) 入口点通过 scsi_ifgetcap(9F) 进行调用。目标驱动程序调用 scsi_ifgetcap() 可确定 SCSA 定义的一组功能中其中一个的当前值。
目标驱动程序可以通过将 whom 参数设置为非零值来请求特定目标的功能的当前设置。whom 值为零表明请求 SCSI 总线或适配器硬件的一般功能的当前设置。
对于未定义的功能或所请求的功能的当前值,tran_getcap() 入口点应返回 -1。
HBA 驱动程序可以使用函数 scsi_hba_lookup_capstr(9F) 来比较功能字符串和已定义功能的标准集。
static int isp_scsi_getcap( struct scsi_address *ap, char *cap, int whom) { struct isp *isp; int rval = 0; u_char tgt = ap->a_target; /* * We don't allow getting capabilities for other targets */ if (cap == NULL || whom == 0) { return (-1); } isp = (struct isp *)ap->a_hba_tran->tran_hba_private; ISP_MUTEX_ENTER(isp); switch (scsi_hba_lookup_capstr(cap)) { case SCSI_CAP_DMA_MAX: rval = 1 << 24; /* Limit to 16MB max transfer */ break; case SCSI_CAP_MSG_OUT: rval = 1; break; case SCSI_CAP_DISCONNECT: if ((isp->isp_target_scsi_options[tgt] & SCSI_OPTIONS_DR) == 0) { break; } else if ( (isp->isp_cap[tgt] & ISP_CAP_DISCONNECT) == 0) { break; } rval = 1; break; case SCSI_CAP_SYNCHRONOUS: if ((isp->isp_target_scsi_options[tgt] & SCSI_OPTIONS_SYNC) == 0) { break; } else if ( (isp->isp_cap[tgt] & ISP_CAP_SYNC) == 0) { break; } rval = 1; break; case SCSI_CAP_WIDE_XFER: if ((isp->isp_target_scsi_options[tgt] & SCSI_OPTIONS_WIDE) == 0) { break; } else if ( (isp->isp_cap[tgt] & ISP_CAP_WIDE) == 0) { break; } rval = 1; break; case SCSI_CAP_TAGGED_QING: if ((isp->isp_target_scsi_options[tgt] & SCSI_OPTIONS_DR) == 0 || (isp->isp_target_scsi_options[tgt] & SCSI_OPTIONS_TAG) == 0) { break; } else if ( (isp->isp_cap[tgt] & ISP_CAP_TAG) == 0) { break; } rval = 1; break; case SCSI_CAP_UNTAGGED_QING: rval = 1; break; case SCSI_CAP_PARITY: if (isp->isp_target_scsi_options[tgt] & SCSI_OPTIONS_PARITY) { rval = 1; } break; case SCSI_CAP_INITIATOR_ID: rval = isp->isp_initiator_id; break; case SCSI_CAP_ARQ: if (isp->isp_cap[tgt] & ISP_CAP_AUTOSENSE) { rval = 1; } break; case SCSI_CAP_LINKED_CMDS: break; case SCSI_CAP_RESET_NOTIFICATION: rval = 1; break; case SCSI_CAP_GEOMETRY: rval = (64 << 16) | 32; break; default: rval = -1; break; } ISP_MUTEX_EXIT(isp); return (rval); }