summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-11-30 21:38:05 +0000
committermav <mav@FreeBSD.org>2015-11-30 21:38:05 +0000
commit751eec2ece6401e2c3344eba5e903ada596a2c4a (patch)
treee7fa621105c1ee1d8a43b832911ecdf5de57ac94 /sys/dev
parentd293293f6c10a65571fdd26d677924c1e7fba125 (diff)
downloadFreeBSD-src-751eec2ece6401e2c3344eba5e903ada596a2c4a.zip
FreeBSD-src-751eec2ece6401e2c3344eba5e903ada596a2c4a.tar.gz
MFC r291000: Register our FC4 Features in SNS.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/isp/isp.c122
-rw-r--r--sys/dev/isp/isp_library.c14
-rw-r--r--sys/dev/isp/isp_library.h1
-rw-r--r--sys/dev/isp/isp_stds.h14
-rw-r--r--sys/dev/isp/ispmbox.h1
5 files changed, 152 insertions, 0 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 3710a52..4ad46c8 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -125,6 +125,7 @@ static int isp_scan_fabric(ispsoftc_t *, int);
static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *);
static int isp_register_fc4_type(ispsoftc_t *, int);
static int isp_register_fc4_type_24xx(ispsoftc_t *, int);
+static int isp_register_fc4_features_24xx(ispsoftc_t *, int);
static uint16_t isp_next_handle(ispsoftc_t *, uint16_t *);
static int isp_fw_state(ispsoftc_t *, int);
static void isp_mboxcmd_qnw(ispsoftc_t *, mbreg_t *, int);
@@ -2927,6 +2928,8 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
}
fcp->isp_sns_hdl = NPH_SNS_ID;
r = isp_register_fc4_type_24xx(isp, chan);
+ if (r == 0)
+ isp_register_fc4_features_24xx(isp, chan);
} else {
fcp->isp_sns_hdl = SNS_ID;
r = isp_register_fc4_type(isp, chan);
@@ -4217,6 +4220,125 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp, int chan)
}
}
+static int
+isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan)
+{
+ mbreg_t mbs;
+ fcparam *fcp = FCPARAM(isp, chan);
+ union {
+ isp_ct_pt_t plocal;
+ rff_id_t clocal;
+ uint8_t q[QENTRY_LEN];
+ } un;
+ isp_ct_pt_t *pt;
+ ct_hdr_t *ct;
+ rff_id_t *rp;
+ uint8_t *scp = fcp->isp_scratch;
+
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return (-1);
+ }
+
+ /*
+ * Build a Passthrough IOCB in memory.
+ */
+ ISP_MEMZERO(un.q, QENTRY_LEN);
+ pt = &un.plocal;
+ pt->ctp_header.rqs_entry_count = 1;
+ pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
+ pt->ctp_handle = 0xffffffff;
+ pt->ctp_nphdl = fcp->isp_sns_hdl;
+ pt->ctp_cmd_cnt = 1;
+ pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan);
+ pt->ctp_time = 1;
+ pt->ctp_rsp_cnt = 1;
+ pt->ctp_rsp_bcnt = sizeof (ct_hdr_t);
+ pt->ctp_cmd_bcnt = sizeof (rff_id_t);
+ pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
+ pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
+ pt->ctp_dataseg[0].ds_count = sizeof (rff_id_t);
+ pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF);
+ pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF);
+ pt->ctp_dataseg[1].ds_count = sizeof (ct_hdr_t);
+ isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]);
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "IOCB CT Request", QENTRY_LEN, pt);
+ }
+
+ /*
+ * Build the CT header and command in memory.
+ *
+ * Note that the CT header has to end up as Big Endian format in memory.
+ */
+ ISP_MEMZERO(&un.clocal, sizeof (un.clocal));
+ ct = &un.clocal.rffid_hdr;
+ ct->ct_revision = CT_REVISION;
+ ct->ct_fcs_type = CT_FC_TYPE_FC;
+ ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
+ ct->ct_cmd_resp = SNS_RFF_ID;
+ ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2;
+ rp = &un.clocal;
+ rp->rffid_portid[0] = fcp->isp_portid >> 16;
+ rp->rffid_portid[1] = fcp->isp_portid >> 8;
+ rp->rffid_portid[2] = fcp->isp_portid;
+ rp->rffid_fc4features = 0;
+ if (fcp->role & ISP_ROLE_TARGET)
+ rp->rffid_fc4features |= 1;
+ if (fcp->role & ISP_ROLE_INITIATOR)
+ rp->rffid_fc4features |= 2;
+ rp->rffid_fc4type = FC4_SCSI;
+ isp_put_rff_id(isp, rp, (rff_id_t *) &scp[XTXOFF]);
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "CT Header", QENTRY_LEN, &scp[XTXOFF]);
+ }
+
+ ISP_MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t));
+
+ MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 1000000);
+ mbs.param[1] = QENTRY_LEN;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN, chan);
+ isp_mboxcmd(isp, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ return (-1);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN, chan);
+ pt = &un.plocal;
+ isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt);
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt);
+ }
+ if (pt->ctp_status) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d Register FC4 Features CT Passthrough returned 0x%x",
+ chan, pt->ctp_status);
+ return (1);
+ }
+
+ isp_get_ct_hdr(isp, (ct_hdr_t *) &scp[IGPOFF], ct);
+ FC_SCRATCH_RELEASE(isp, chan);
+
+ if (ct->ct_cmd_resp == LS_RJT) {
+ isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
+ "Chan %d Register FC4 Features rejected", chan);
+ return (-1);
+ } else if (ct->ct_cmd_resp == LS_ACC) {
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Register FC4 Features accepted", chan);
+ return (0);
+ } else {
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp);
+ return (-1);
+ }
+}
+
static uint16_t
isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
{
diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c
index 73f50a7..934295e 100644
--- a/sys/dev/isp/isp_library.c
+++ b/sys/dev/isp/isp_library.c
@@ -2157,6 +2157,20 @@ isp_put_rft_id(ispsoftc_t *isp, rft_id_t *src, rft_id_t *dst)
}
void
+isp_put_rff_id(ispsoftc_t *isp, rff_id_t *src, rff_id_t *dst)
+{
+ int i;
+
+ isp_put_ct_hdr(isp, &src->rffid_hdr, &dst->rffid_hdr);
+ ISP_IOZPUT_8(isp, src->rffid_reserved, &dst->rffid_reserved);
+ for (i = 0; i < 3; i++)
+ ISP_IOZPUT_8(isp, src->rffid_portid[i], &dst->rffid_portid[i]);
+ ISP_IOZPUT_16(isp, src->rffid_reserved2, &dst->rffid_reserved2);
+ ISP_IOZPUT_8(isp, src->rffid_fc4features, &dst->rffid_fc4features);
+ ISP_IOZPUT_8(isp, src->rffid_fc4type, &dst->rffid_fc4type);
+}
+
+void
isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst)
{
ISP_IOZGET_8(isp, &src->ct_revision, dst->ct_revision);
diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h
index 2e575b2..d881c8b 100644
--- a/sys/dev/isp/isp_library.h
+++ b/sys/dev/isp/isp_library.h
@@ -148,6 +148,7 @@ void isp_get_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *);
void isp_put_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *);
void isp_get_fcp_cmnd_iu(ispsoftc_t *, fcp_cmnd_iu_t *, fcp_cmnd_iu_t *);
void isp_put_rft_id(ispsoftc_t *, rft_id_t *, rft_id_t *);
+void isp_put_rff_id(ispsoftc_t *, rff_id_t *, rff_id_t *);
void isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
void isp_put_fcp_rsp_iu(ispsoftc_t *isp, fcp_rsp_iu_t *, fcp_rsp_iu_t *);
diff --git a/sys/dev/isp/isp_stds.h b/sys/dev/isp/isp_stds.h
index daa199c..315870e 100644
--- a/sys/dev/isp/isp_stds.h
+++ b/sys/dev/isp/isp_stds.h
@@ -139,6 +139,20 @@ typedef struct {
} rft_id_t;
/*
+ * RFF_ID Requet CT_IU
+ *
+ * Source: INCITS 463-2010 Generic Services 6 Section 5.2.5.34
+ */
+typedef struct {
+ ct_hdr_t rffid_hdr;
+ uint8_t rffid_reserved;
+ uint8_t rffid_portid[3];
+ uint16_t rffid_reserved2;
+ uint8_t rffid_fc4features;
+ uint8_t rffid_fc4type;
+} rff_id_t;
+
+/*
* FCP Response IU and bits of interest
* Source: NCITS T10, Project 1828D, Revision 02b (aka FCP4r02b)
*/
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index 83631cd..b0d74a6 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -1513,6 +1513,7 @@ typedef struct {
#define SNS_GFF_ID 0x11F
#define SNS_GID_FT 0x171
#define SNS_RFT_ID 0x217
+#define SNS_RFF_ID 0x21F
typedef struct {
uint16_t snscb_rblen; /* response buffer length (words) */
uint16_t snscb_reserved0;
OpenPOWER on IntegriCloud