The tran_getcap(9E) entry point for a SCSI HBA driver is called by scsi_ifgetcap(9F). The target driver calls scsi_ifgetcap() to determine the current value of one of a set of SCSA-defined capabilities.
The target driver can request the current setting of the capability for a particular target by setting the whom parameter to nonzero. A whom value of zero indicates a request for the current setting of the general capability for the SCSI bus or for adapter hardware.
The tran_getcap() entry point should return -1 for undefined capabilities or the current value of the requested capability.
The HBA driver can use the function scsi_hba_lookup_capstr(9F) to compare the capability string against the canonical set of defined capabilities.
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); }