aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/isp
diff options
context:
space:
mode:
authorMatt Jacob <mjacob@FreeBSD.org>2002-04-16 21:41:22 +0000
committerMatt Jacob <mjacob@FreeBSD.org>2002-04-16 21:41:22 +0000
commit794e31e9a5487c789a6ad778bf7194b3480f638a (patch)
tree291d6da48569bef69c5bd171316e348ca03b3eaf /sys/dev/isp
parentb52e510fa40b901076f579ad08b8d3fd4dc93bbf (diff)
Notes
Diffstat (limited to 'sys/dev/isp')
-rw-r--r--sys/dev/isp/isp.c544
-rw-r--r--sys/dev/isp/isp_freebsd.c104
-rw-r--r--sys/dev/isp/isp_freebsd.h10
-rw-r--r--sys/dev/isp/isp_inline.h142
-rw-r--r--sys/dev/isp/isp_pci.c231
-rw-r--r--sys/dev/isp/ispmbox.h126
-rw-r--r--sys/dev/isp/ispvar.h18
7 files changed, 882 insertions, 293 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index b6b9d4d7b838..2070df7f5e16 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -96,6 +96,8 @@ static const char pskip[] =
"SCSI phase skipped for target %d.%d.%d";
static const char topology[] =
"Loop ID %d, AL_PA 0x%x, Port ID 0x%x, Loop State 0x%x, Topology '%s'";
+static const char swrej[] =
+ "Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x";
static const char finmsg[] =
"(%d.%d.%d): FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x";
static const char sc0[] =
@@ -127,7 +129,8 @@ static int isp_fclink_test(struct ispsoftc *, int);
static char *isp2100_fw_statename(int);
static int isp_pdb_sync(struct ispsoftc *);
static int isp_scan_loop(struct ispsoftc *);
-static int isp_scan_fabric(struct ispsoftc *);
+static int isp_fabric_mbox_cmd(struct ispsoftc *, mbreg_t *);
+static int isp_scan_fabric(struct ispsoftc *, int);
static void isp_register_fc4_type(struct ispsoftc *);
static void isp_fw_state(struct ispsoftc *);
static void isp_mboxcmd_qnw(struct ispsoftc *, mbreg_t *, int);
@@ -770,7 +773,7 @@ again:
* of knowing how many luns we support.
*
* Expanded lun firmware gives you 32 luns for SCSI cards and
- * 65536 luns for Fibre Channel cards.
+ * 16384 luns for Fibre Channel cards.
*
* It turns out that even for QLogic 2100s with ROM 1.10 and above
* we do get a firmware attributes word returned in mailbox register 6.
@@ -793,7 +796,7 @@ again:
}
} else {
if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
- isp->isp_maxluns = 65536;
+ isp->isp_maxluns = 16384;
} else {
isp->isp_maxluns = 16;
}
@@ -1816,7 +1819,7 @@ isp_pdb_sync(struct ispsoftc *isp)
* that has, in fact, gone away. And it hangs trying to
* log it out.
*/
- if (lp->loggedin &&
+ if (lp->loggedin && lp->force_logout == 0 &&
isp_getpdb(isp, lp->loopid, &pdb) == 0) {
int nrole;
u_int64_t nwwnn, nwwpn;
@@ -1852,8 +1855,6 @@ isp_pdb_sync(struct ispsoftc *isp)
}
}
- lp->force_logout = 0;
-
if (fcp->isp_fwstate != FW_READY ||
fcp->isp_loopstate != LOOP_SYNCING_PDB) {
return (-1);
@@ -1863,18 +1864,18 @@ isp_pdb_sync(struct ispsoftc *isp)
* Force a logout if we were logged in.
*/
if (lp->loggedin) {
- if (isp_getpdb(isp, lp->loopid, &pdb) == 0) {
+ if (lp->force_logout ||
+ isp_getpdb(isp, lp->loopid, &pdb) == 0) {
mbs.param[0] = MBOX_FABRIC_LOGOUT;
mbs.param[1] = lp->loopid << 8;
mbs.param[2] = 0;
mbs.param[3] = 0;
isp_mboxcmd(isp, &mbs, MBLOGNONE);
- lp->loggedin = 0;
isp_prt(isp, ISP_LOGINFO, plogout,
(int) (lp - fcp->portdb), lp->loopid,
lp->portid);
}
- lp->loggedin = 0;
+ lp->force_logout = lp->loggedin = 0;
if (fcp->isp_fwstate != FW_READY ||
fcp->isp_loopstate != LOOP_SYNCING_PDB) {
return (-1);
@@ -1891,10 +1892,6 @@ isp_pdb_sync(struct ispsoftc *isp)
mbs.param[1] = loopid << 8;
mbs.param[2] = portid >> 16;
mbs.param[3] = portid & 0xffff;
- if (IS_2200(isp) || IS_23XX(isp)) {
- /* only issue a PLOGI if not logged in */
- mbs.param[1] |= 0x1;
- }
isp_mboxcmd(isp, &mbs, MBLOGALL & ~(MBOX_LOOP_ID_USED |
MBOX_PORT_ID_USED | MBOX_COMMAND_ERROR));
if (fcp->isp_fwstate != FW_READY ||
@@ -2298,21 +2295,69 @@ isp_scan_loop(struct ispsoftc *isp)
return (0);
}
-#ifndef HICAP_MAX
-#define HICAP_MAX 256
-#endif
+
+static int
+isp_fabric_mbox_cmd(struct ispsoftc *isp, mbreg_t *mbp)
+{
+ isp_mboxcmd(isp, mbp, MBLOGNONE);
+ if (mbp->param[0] != MBOX_COMMAND_COMPLETE) {
+ if (FCPARAM(isp)->isp_loopstate == LOOP_SCANNING_FABRIC) {
+ FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ if (mbp->param[0] == MBOX_COMMAND_ERROR) {
+ char tbuf[16];
+ char *m;
+ switch (mbp->param[1]) {
+ case 1:
+ m = "No Loop";
+ break;
+ case 2:
+ m = "Failed to allocate IOCB buffer";
+ break;
+ case 3:
+ m = "Failed to allocate XCB buffer";
+ break;
+ case 4:
+ m = "timeout or transmit failed";
+ break;
+ case 5:
+ m = "no fabric loop";
+ break;
+ case 6:
+ m = "remote device not a target";
+ break;
+ default:
+ SNPRINTF(tbuf, sizeof tbuf, "%x",
+ mbp->param[1]);
+ m = tbuf;
+ break;
+ }
+ isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m);
+ }
+ return (-1);
+ }
+
+ if (FCPARAM(isp)->isp_fwstate != FW_READY ||
+ FCPARAM(isp)->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ return (-1);
+ }
+ return(0);
+}
+
+#ifdef ISP_USE_GA_NXT
static int
-isp_scan_fabric(struct ispsoftc *isp)
+isp_scan_fabric(struct ispsoftc *isp, int ftype)
{
fcparam *fcp = isp->isp_param;
u_int32_t portid, first_portid, last_portid;
- int hicap, first_portid_seen, last_port_same;
+ int hicap, last_port_same;
if (fcp->isp_onfabric == 0) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
return (0);
}
+ FC_SCRATCH_ACQUIRE(isp);
/*
* Since Port IDs are 24 bits, we can check against having seen
@@ -2323,28 +2368,28 @@ isp_scan_fabric(struct ispsoftc *isp)
first_portid = portid = fcp->isp_portid;
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
- for (first_portid_seen = hicap = 0; hicap < HICAP_MAX; hicap++) {
+ for (hicap = 0; hicap < GA_NXT_MAX; hicap++) {
mbreg_t mbs;
sns_screq_t *rq;
- sns_ganrsp_t *rs0, *rs1;
- u_int8_t sc[SNS_GAN_REQ_SIZE];
+ sns_ga_nxt_rsp_t *rs0, *rs1;
+ struct lportdb lcl;
+ u_int8_t sc[SNS_GA_NXT_RESP_SIZE];
rq = (sns_screq_t *)sc;
- MEMZERO((void *) rq, SNS_GAN_REQ_SIZE);
- rq->snscb_rblen = SNS_GAN_RESP_SIZE >> 1;
+ MEMZERO((void *) rq, SNS_GA_NXT_REQ_SIZE);
+ rq->snscb_rblen = SNS_GA_NXT_RESP_SIZE >> 1;
rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+0x100);
rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+0x100);
rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+0x100);
rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+0x100);
rq->snscb_sblen = 6;
- rq->snscb_data[0] = SNS_GAN;
+ rq->snscb_data[0] = SNS_GA_NXT;
rq->snscb_data[4] = portid & 0xffff;
rq->snscb_data[5] = (portid >> 16) & 0xff;
- FC_SCRATCH_ACQUIRE(isp);
isp_put_sns_request(isp, rq, (sns_screq_t *) fcp->isp_scratch);
- MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GAN_REQ_SIZE);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GA_NXT_REQ_SIZE);
mbs.param[0] = MBOX_SEND_SNS;
- mbs.param[1] = SNS_GAN_REQ_SIZE >> 1;
+ mbs.param[1] = SNS_GA_NXT_REQ_SIZE >> 1;
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
/*
@@ -2352,59 +2397,80 @@ isp_scan_fabric(struct ispsoftc *isp)
*/
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
- isp_mboxcmd(isp, &mbs, MBLOGNONE);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- if (fcp->isp_loopstate == LOOP_SCANNING_FABRIC) {
+ if (isp_fabric_mbox_cmd(isp, &mbs)) {
+ if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
fcp->isp_loopstate = LOOP_PDB_RCVD;
}
- if (mbs.param[0] == MBOX_COMMAND_ERROR) {
- char tbuf[16];
- char *m;
- switch (mbs.param[1]) {
- case 1:
- m = "No Loop";
- break;
- case 2:
- m = "Failed to allocate IOCB buffer";
- break;
- case 3:
- m = "Failed to allocate XCB buffer";
- break;
- case 4:
- m = "timeout or transmit failed";
- break;
- case 5:
- m = "no fabric loop";
- break;
- case 6:
- m = "remote device not a target";
- break;
- default:
- SNPRINTF(tbuf, sizeof tbuf, "%x",
- mbs.param[1]);
- m = tbuf;
- break;
- }
- isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m);
- }
+ FC_SCRATCH_RELEASE(isp);
return (-1);
}
- if (fcp->isp_fwstate != FW_READY ||
- fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GA_NXT_RESP_SIZE);
+ rs1 = (sns_ga_nxt_rsp_t *) sc;
+ rs0 = (sns_ga_nxt_rsp_t *) ((u_int8_t *)fcp->isp_scratch+0x100);
+ isp_get_ga_nxt_response(isp, rs0, rs1);
+ if (rs1->snscb_cthdr.ct_response != FS_ACC) {
+ isp_prt(isp, ISP_LOGWARN, swrej, "GA_NXT",
+ rs1->snscb_cthdr.ct_reason,
+ rs1->snscb_cthdr.ct_explanation, portid);
FC_SCRATCH_RELEASE(isp);
- return (-1);
+ fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ return (0);
}
- MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GAN_RESP_SIZE);
- rs1 = (sns_ganrsp_t *) fcp->isp_scratch;
- rs0 = (sns_ganrsp_t *) ((u_int8_t *)fcp->isp_scratch + 0x100);
- isp_get_gan_response(isp, rs0, rs1);
- FC_SCRATCH_RELEASE(isp);
- portid = (((u_int32_t) rs1->snscb_port_id[0]) << 16) |
+ portid =
+ (((u_int32_t) rs1->snscb_port_id[0]) << 16) |
(((u_int32_t) rs1->snscb_port_id[1]) << 8) |
(((u_int32_t) rs1->snscb_port_id[2]));
- (void) isp_async(isp, ISPASYNC_FABRIC_DEV, rs1);
+
+ /*
+ * Okay, we now have information about a fabric object.
+ * If it is the type we're interested in, tell the outer layers
+ * about it. The outer layer needs to know: Port ID, WWNN,
+ * WWPN, FC4 type, and port type.
+ *
+ * The lportdb structure is adequate for this.
+ */
+ MEMZERO(&lcl, sizeof (lcl));
+ lcl.port_type = rs1->snscb_port_type;
+ lcl.fc4_type = ftype;
+ lcl.portid = portid;
+ lcl.node_wwn =
+ (((u_int64_t)rs1->snscb_nodename[0]) << 56) |
+ (((u_int64_t)rs1->snscb_nodename[1]) << 48) |
+ (((u_int64_t)rs1->snscb_nodename[2]) << 40) |
+ (((u_int64_t)rs1->snscb_nodename[3]) << 32) |
+ (((u_int64_t)rs1->snscb_nodename[4]) << 24) |
+ (((u_int64_t)rs1->snscb_nodename[5]) << 16) |
+ (((u_int64_t)rs1->snscb_nodename[6]) << 8) |
+ (((u_int64_t)rs1->snscb_nodename[7]));
+ lcl.port_wwn =
+ (((u_int64_t)rs1->snscb_portname[0]) << 56) |
+ (((u_int64_t)rs1->snscb_portname[1]) << 48) |
+ (((u_int64_t)rs1->snscb_portname[2]) << 40) |
+ (((u_int64_t)rs1->snscb_portname[3]) << 32) |
+ (((u_int64_t)rs1->snscb_portname[4]) << 24) |
+ (((u_int64_t)rs1->snscb_portname[5]) << 16) |
+ (((u_int64_t)rs1->snscb_portname[6]) << 8) |
+ (((u_int64_t)rs1->snscb_portname[7]));
+
+ /*
+ * Does this fabric object support the type we want?
+ * If not, skip it.
+ */
+ if (rs1->snscb_fc4_types[ftype >> 5] & (1 << (ftype & 0x1f))) {
+ if (first_portid == portid) {
+ lcl.last_fabric_dev = 1;
+ } else {
+ lcl.last_fabric_dev = 0;
+ }
+ (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
+ } else {
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "PortID 0x%x doesn't support FC4 type 0x%x",
+ portid, ftype);
+ }
if (first_portid == portid) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ FC_SCRATCH_RELEASE(isp);
return (0);
}
if (portid == last_portid) {
@@ -2414,47 +2480,346 @@ isp_scan_fabric(struct ispsoftc *isp)
break;
}
} else {
+ last_port_same = 0 ;
last_portid = portid;
}
}
+ FC_SCRATCH_RELEASE(isp);
+ if (hicap >= GA_NXT_MAX) {
+ isp_prt(isp, ISP_LOGWARN, "fabric too big (> %d)", GA_NXT_MAX);
+ }
+ fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ return (0);
+}
+#else
+#define GIDLEN ((ISP2100_SCRLEN >> 1) + 16)
+#define NGENT ((GIDLEN - 16) >> 2)
+
+#define IGPOFF (ISP2100_SCRLEN - GIDLEN)
+#define GXOFF (256)
+
+static int
+isp_scan_fabric(struct ispsoftc *isp, int ftype)
+{
+ fcparam *fcp = FCPARAM(isp);
+ mbreg_t mbs;
+ int i;
+ sns_gid_ft_req_t *rq;
+ sns_gid_ft_rsp_t *rs0, *rs1;
- if (hicap >= 65535) {
- isp_prt(isp, ISP_LOGWARN, "fabric too big (> 65535)");
+ if (fcp->isp_onfabric == 0) {
+ fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ return (0);
+ }
+
+ FC_SCRATCH_ACQUIRE(isp);
+ fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
+
+ rq = (sns_gid_ft_req_t *)fcp->tport;
+ MEMZERO((void *) rq, SNS_GID_FT_REQ_SIZE);
+ rq->snscb_rblen = GIDLEN >> 1;
+ rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+IGPOFF);
+ rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+IGPOFF);
+ rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+IGPOFF);
+ rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+IGPOFF);
+ rq->snscb_sblen = 6;
+ rq->snscb_cmd = SNS_GID_FT;
+ rq->snscb_mword_div_2 = NGENT;
+ rq->snscb_fc4_type = ftype;
+ isp_put_gid_ft_request(isp, rq, (sns_gid_ft_req_t *) fcp->isp_scratch);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE);
+ mbs.param[0] = MBOX_SEND_SNS;
+ mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+
+ /*
+ * Leave 4 and 5 alone
+ */
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+ if (isp_fabric_mbox_cmd(isp, &mbs)) {
+ if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN);
+ rs1 = (sns_gid_ft_rsp_t *) fcp->tport;
+ rs0 = (sns_gid_ft_rsp_t *) ((u_int8_t *)fcp->isp_scratch+IGPOFF);
+ isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
+ if (rs1->snscb_cthdr.ct_response != FS_ACC) {
+ isp_prt(isp, ISP_LOGWARN, swrej, "GID_FT",
+ rs1->snscb_cthdr.ct_reason,
+ rs1->snscb_cthdr.ct_explanation, 0);
+ FC_SCRATCH_RELEASE(isp);
+ fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ return (0);
}
/*
- * We either have a broken name server or a huge fabric if we get here.
+ * Okay, we now have a list of Port IDs for this class of device.
+ * Go through the list and for each one get the WWPN/WWNN for it
+ * and tell the outer layers about it. The outer layer needs to
+ * know: Port ID, WWNN, WWPN, FC4 type, and (possibly) port type.
+ *
+ * The lportdb structure is adequate for this.
+ */
+ i = -1;
+ do {
+ sns_gxn_id_req_t grqbuf, *gq = &grqbuf;
+ sns_gxn_id_rsp_t *gs0, grsbuf, *gs1 = &grsbuf;
+ struct lportdb lcl;
+#if 0
+ sns_gff_id_rsp_t *fs0, ffsbuf, *fs1 = &ffsbuf;
+#endif
+
+ i++;
+ MEMZERO(&lcl, sizeof (lcl));
+ lcl.fc4_type = ftype;
+ lcl.portid =
+ (((u_int32_t) rs1->snscb_ports[i].portid[0]) << 16) |
+ (((u_int32_t) rs1->snscb_ports[i].portid[1]) << 8) |
+ (((u_int32_t) rs1->snscb_ports[i].portid[2]));
+
+ MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
+ gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
+ gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
+ gq->snscb_sblen = 6;
+ gq->snscb_cmd = SNS_GPN_ID;
+ gq->snscb_portid = lcl.portid;
+ isp_put_gxn_id_request(isp, gq,
+ (sns_gxn_id_req_t *) fcp->isp_scratch);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
+ mbs.param[0] = MBOX_SEND_SNS;
+ mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ /*
+ * Leave 4 and 5 alone
+ */
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+ if (isp_fabric_mbox_cmd(isp, &mbs)) {
+ if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
+ gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
+ isp_get_gxn_id_response(isp, gs0, gs1);
+ if (gs1->snscb_cthdr.ct_response != FS_ACC) {
+ isp_prt(isp, ISP_LOGWARN, swrej, "GPN_ID",
+ gs1->snscb_cthdr.ct_reason,
+ gs1->snscb_cthdr.ct_explanation, lcl.portid);
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ continue;
+ }
+ lcl.port_wwn =
+ (((u_int64_t)gs1->snscb_wwn[0]) << 56) |
+ (((u_int64_t)gs1->snscb_wwn[1]) << 48) |
+ (((u_int64_t)gs1->snscb_wwn[2]) << 40) |
+ (((u_int64_t)gs1->snscb_wwn[3]) << 32) |
+ (((u_int64_t)gs1->snscb_wwn[4]) << 24) |
+ (((u_int64_t)gs1->snscb_wwn[5]) << 16) |
+ (((u_int64_t)gs1->snscb_wwn[6]) << 8) |
+ (((u_int64_t)gs1->snscb_wwn[7]));
+
+ MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
+ gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
+ gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
+ gq->snscb_sblen = 6;
+ gq->snscb_cmd = SNS_GNN_ID;
+ gq->snscb_portid = lcl.portid;
+ isp_put_gxn_id_request(isp, gq,
+ (sns_gxn_id_req_t *) fcp->isp_scratch);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
+ mbs.param[0] = MBOX_SEND_SNS;
+ mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ /*
+ * Leave 4 and 5 alone
+ */
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+ if (isp_fabric_mbox_cmd(isp, &mbs)) {
+ if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
+ gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
+ isp_get_gxn_id_response(isp, gs0, gs1);
+ if (gs1->snscb_cthdr.ct_response != FS_ACC) {
+ isp_prt(isp, ISP_LOGWARN, swrej, "GNN_ID",
+ gs1->snscb_cthdr.ct_reason,
+ gs1->snscb_cthdr.ct_explanation, lcl.portid);
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ continue;
+ }
+ lcl.node_wwn =
+ (((u_int64_t)gs1->snscb_wwn[0]) << 56) |
+ (((u_int64_t)gs1->snscb_wwn[1]) << 48) |
+ (((u_int64_t)gs1->snscb_wwn[2]) << 40) |
+ (((u_int64_t)gs1->snscb_wwn[3]) << 32) |
+ (((u_int64_t)gs1->snscb_wwn[4]) << 24) |
+ (((u_int64_t)gs1->snscb_wwn[5]) << 16) |
+ (((u_int64_t)gs1->snscb_wwn[6]) << 8) |
+ (((u_int64_t)gs1->snscb_wwn[7]));
+
+ /*
+ * The QLogic f/w is bouncing this with a parameter error.
+ */
+#if 0
+ /*
+ * Try and get FC4 Features (FC-GS-3 only).
+ * We can use the sns_gxn_id_req_t for this request.
+ */
+ MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
+ gq->snscb_rblen = SNS_GFF_ID_RESP_SIZE >> 1;
+ gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
+ gq->snscb_sblen = 6;
+ gq->snscb_cmd = SNS_GFF_ID;
+ gq->snscb_portid = lcl.portid;
+ isp_put_gxn_id_request(isp, gq,
+ (sns_gxn_id_req_t *) fcp->isp_scratch);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
+ mbs.param[0] = MBOX_SEND_SNS;
+ mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ /*
+ * Leave 4 and 5 alone
+ */
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+ if (isp_fabric_mbox_cmd(isp, &mbs)) {
+ if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GFF_ID_RESP_SIZE);
+ fs0 = (sns_gff_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
+ isp_get_gff_id_response(isp, fs0, fs1);
+ if (fs1->snscb_cthdr.ct_response != FS_ACC) {
+ isp_prt(isp, /* ISP_LOGDEBUG0 */ ISP_LOGWARN,
+ swrej, "GFF_ID",
+ fs1->snscb_cthdr.ct_reason,
+ fs1->snscb_cthdr.ct_explanation, lcl.portid);
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ } else {
+ int index = (ftype >> 3);
+ int bshft = (ftype & 0x7) * 4;
+ int fc4_fval =
+ (fs1->snscb_fc4_features[index] >> bshft) & 0xf;
+ if (fc4_fval & 0x1) {
+ lcl.roles |=
+ (SVC3_INI_ROLE >> SVC3_ROLE_SHIFT);
+ }
+ if (fc4_fval & 0x2) {
+ lcl.roles |=
+ (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
+ }
+ }
+#endif
+
+ /*
+ * If we really want to know what kind of port type this is,
+ * we have to run another CT command. Otherwise, we'll leave
+ * it as undefined.
+ *
+ lcl.port_type = 0;
+ */
+ if (rs1->snscb_ports[i].control & 0x80) {
+ lcl.last_fabric_dev = 1;
+ } else {
+ lcl.last_fabric_dev = 0;
+ }
+ (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
+
+ } while ((rs1->snscb_ports[i].control & 0x80) == 0 && i < NGENT-1);
+
+ /*
+ * If we're not at the last entry, our list isn't big enough.
*/
+ if ((rs1->snscb_ports[i].control & 0x80) == 0) {
+ isp_prt(isp, ISP_LOGWARN, "fabric too big for scratch area");
+ }
+
+ FC_SCRATCH_RELEASE(isp);
fcp->isp_loopstate = LOOP_FSCAN_DONE;
return (0);
}
+#endif
static void
isp_register_fc4_type(struct ispsoftc *isp)
{
fcparam *fcp = isp->isp_param;
- u_int8_t local[SNS_RFT_REQ_SIZE];
+ u_int8_t local[SNS_RFT_ID_REQ_SIZE];
sns_screq_t *reqp = (sns_screq_t *) local;
mbreg_t mbs;
- MEMZERO((void *) reqp, SNS_RFT_REQ_SIZE);
- reqp->snscb_rblen = SNS_RFT_RESP_SIZE >> 1;
+ MEMZERO((void *) reqp, SNS_RFT_ID_REQ_SIZE);
+ reqp->snscb_rblen = SNS_RFT_ID_RESP_SIZE >> 1;
reqp->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + 0x100);
reqp->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + 0x100);
reqp->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + 0x100);
reqp->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + 0x100);
reqp->snscb_sblen = 22;
- reqp->snscb_data[0] = SNS_RFT;
+ reqp->snscb_data[0] = SNS_RFT_ID;
reqp->snscb_data[4] = fcp->isp_portid & 0xffff;
reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff;
- reqp->snscb_data[6] = 0x100; /* SCS - FCP */
+ reqp->snscb_data[6] = (1 << FC4_SCSI);
#if 0
- reqp->snscb_data[6] |= 20; /* ISO/IEC 8802-2 LLC/SNAP */
+ reqp->snscb_data[6] |= (1 << FC4_IP); /* ISO/IEC 8802-2 LLC/SNAP */
#endif
FC_SCRATCH_ACQUIRE(isp);
isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch);
mbs.param[0] = MBOX_SEND_SNS;
- mbs.param[1] = SNS_RFT_REQ_SIZE >> 1;
+ mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1;
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
/*
@@ -2652,7 +3017,7 @@ isp_start(XS_T *xs)
* out and try again later if this doesn't work.
*/
if (fcp->isp_loopstate == LOOP_PDB_RCVD && fcp->isp_onfabric) {
- if (isp_scan_fabric(isp)) {
+ if (isp_scan_fabric(isp, FC4_SCSI)) {
return (CMD_RQLATER);
}
if (fcp->isp_fwstate != FW_READY ||
@@ -2951,7 +3316,8 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg)
case ISPCTL_SCAN_FABRIC:
if (IS_FC(isp)) {
- return (isp_scan_fabric(isp));
+ int ftype = (arg)? *((int *) arg) : FC4_SCSI;
+ return (isp_scan_fabric(isp, ftype));
}
break;
@@ -3291,10 +3657,18 @@ again:
}
xs = isp_find_xs(isp, sp->req_handle);
if (xs == NULL) {
+ u_int8_t ts = sp->req_completion_status & 0xff;
MEMZERO(hp, QENTRY_LEN); /* PERF */
- isp_prt(isp, ISP_LOGERR,
- "cannot find handle 0x%x in xflist",
- sp->req_handle);
+ /*
+ * Only whine if this isn't the expected fallout of
+ * aborting the command.
+ */
+ if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE ||
+ ts != RQCS_ABORTED) {
+ isp_prt(isp, ISP_LOGERR,
+ "cannot find handle 0x%x in xflist",
+ sp->req_handle);
+ }
WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
continue;
}
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 2aab004790ac..cedfaa8cfa4d 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -1711,7 +1711,7 @@ isp_watchdog(void *arg)
isp_destroy_handle(isp, handle);
xpt_print_path(xs->ccb_h.path);
isp_prt(isp, ISP_LOGWARN,
- "watchdog timeout for handle %x", handle);
+ "watchdog timeout for handle 0x%x", handle);
XS_SETERR(xs, CAM_CMD_TIMEOUT);
XS_CMD_C_WDOG(xs);
isp_done(xs);
@@ -2520,43 +2520,13 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
break;
case ISPASYNC_FABRIC_DEV:
{
- int target, lrange;
+ int target, base, lim;
+ fcparam *fcp = isp->isp_param;
struct lportdb *lp = NULL;
+ struct lportdb *clp = (struct lportdb *) arg;
char *pt;
- sns_ganrsp_t *resp = (sns_ganrsp_t *) arg;
- u_int32_t portid;
- u_int64_t wwpn, wwnn;
- fcparam *fcp = isp->isp_param;
-
- portid =
- (((u_int32_t) resp->snscb_port_id[0]) << 16) |
- (((u_int32_t) resp->snscb_port_id[1]) << 8) |
- (((u_int32_t) resp->snscb_port_id[2]));
-
- wwpn =
- (((u_int64_t)resp->snscb_portname[0]) << 56) |
- (((u_int64_t)resp->snscb_portname[1]) << 48) |
- (((u_int64_t)resp->snscb_portname[2]) << 40) |
- (((u_int64_t)resp->snscb_portname[3]) << 32) |
- (((u_int64_t)resp->snscb_portname[4]) << 24) |
- (((u_int64_t)resp->snscb_portname[5]) << 16) |
- (((u_int64_t)resp->snscb_portname[6]) << 8) |
- (((u_int64_t)resp->snscb_portname[7]));
-
- wwnn =
- (((u_int64_t)resp->snscb_nodename[0]) << 56) |
- (((u_int64_t)resp->snscb_nodename[1]) << 48) |
- (((u_int64_t)resp->snscb_nodename[2]) << 40) |
- (((u_int64_t)resp->snscb_nodename[3]) << 32) |
- (((u_int64_t)resp->snscb_nodename[4]) << 24) |
- (((u_int64_t)resp->snscb_nodename[5]) << 16) |
- (((u_int64_t)resp->snscb_nodename[6]) << 8) |
- (((u_int64_t)resp->snscb_nodename[7]));
- if (portid == 0 || wwpn == 0) {
- break;
- }
- switch (resp->snscb_port_type) {
+ switch (clp->port_type) {
case 1:
pt = " N_Port";
break;
@@ -2579,40 +2549,66 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
pt = " E_port";
break;
default:
- pt = "?";
+ pt = " ";
break;
}
+
isp_prt(isp, ISP_LOGINFO,
- "%s @ 0x%x, Node 0x%08x%08x Port %08x%08x",
- pt, portid, ((u_int32_t) (wwnn >> 32)), ((u_int32_t) wwnn),
- ((u_int32_t) (wwpn >> 32)), ((u_int32_t) wwpn));
+ "%s Fabric Device @ PortID 0x%x", pt, clp->portid);
+
+ /*
+ * If we don't have an initiator role we bail.
+ *
+ * We just use ISPASYNC_FABRIC_DEV for announcement purposes.
+ */
+
+ if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
+ break;
+ }
+
/*
- * We're only interested in SCSI_FCP types (for now)
+ * Is this entry for us? If so, we bail.
*/
- if ((resp->snscb_fc4_types[2] & 1) == 0) {
+
+ if (fcp->isp_portid == clp->portid) {
break;
}
- if (fcp->isp_topo != TOPO_F_PORT)
- lrange = FC_SNS_ID+1;
+
+ /*
+ * Else, the default policy is to find room for it in
+ * our local port database. Later, when we execute
+ * the call to isp_pdb_sync either this newly arrived
+ * or already logged in device will be (re)announced.
+ */
+
+ if (fcp->isp_topo == TOPO_FL_PORT)
+ base = FC_SNS_ID+1;
else
- lrange = 0;
+ base = 0;
+
+ if (fcp->isp_topo == TOPO_N_PORT)
+ lim = 1;
+ else
+ lim = MAX_FC_TARG;
+
/*
* Is it already in our list?
*/
- for (target = lrange; target < MAX_FC_TARG; target++) {
+ for (target = base; target < lim; target++) {
if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
continue;
}
lp = &fcp->portdb[target];
- if (lp->port_wwn == wwpn && lp->node_wwn == wwnn) {
+ if (lp->port_wwn == clp->port_wwn &&
+ lp->node_wwn == clp->node_wwn) {
lp->fabric_dev = 1;
break;
}
}
- if (target < MAX_FC_TARG) {
+ if (target < lim) {
break;
}
- for (target = lrange; target < MAX_FC_TARG; target++) {
+ for (target = base; target < lim; target++) {
if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
continue;
}
@@ -2621,14 +2617,16 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
break;
}
}
- if (target == MAX_FC_TARG) {
+ if (target == lim) {
isp_prt(isp, ISP_LOGWARN,
- "no more space for fabric devices");
+ "out of space for fabric devices");
break;
}
- lp->node_wwn = wwnn;
- lp->port_wwn = wwpn;
- lp->portid = portid;
+ lp->port_type = clp->port_type;
+ lp->fc4_type = clp->fc4_type;
+ lp->node_wwn = clp->node_wwn;
+ lp->port_wwn = clp->port_wwn;
+ lp->portid = clp->portid;
lp->fabric_dev = 1;
break;
}
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index 2735d135a0a5..efd54e1150d9 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -68,7 +68,7 @@
#define HANDLE_LOOPSTATE_IN_OUTER_LAYERS 1
-typedef void ispfwfunc __P((int, int, int, u_int16_t **));
+typedef void ispfwfunc(int, int, int, u_int16_t **);
#ifdef ISP_TARGET_MODE
#define ISP_TARGET_FUNCTIONS 1
@@ -114,6 +114,10 @@ struct isposinfo {
int islocked;
int splsaved;
struct proc *kproc;
+ bus_dma_tag_t cdmat;
+ bus_dmamap_t cdmap;
+#define isp_cdmat isp_osinfo.cdmat
+#define isp_cdmap isp_osinfo.cdmap
#ifdef ISP_TARGET_MODE
#define TM_WANTED 0x80
#define TM_BUSY 0x40
@@ -124,7 +128,7 @@ struct isposinfo {
u_int16_t rollinfo;
tstate_t tsdflt[2]; /* two busses */
tstate_t *lun_hash[LUN_HASH_SIZE];
- atio_private_data_t atpdp[ATPDPSIZE];
+ atio_private_data_t atpdp[ATPDPSIZE];
#endif
};
@@ -145,7 +149,7 @@ struct isposinfo {
#define INLINE __inline
-#define ISP2100_SCRLEN 0x400
+#define ISP2100_SCRLEN 0x800
#define MEMZERO bzero
#define MEMCPY(dst, src, amt) bcopy((src), (dst), (amt))
diff --git a/sys/dev/isp/isp_inline.h b/sys/dev/isp/isp_inline.h
index f65c3656d6f5..5a1694df05f8 100644
--- a/sys/dev/isp/isp_inline.h
+++ b/sys/dev/isp/isp_inline.h
@@ -275,11 +275,29 @@ isp_put_icb(struct ispsoftc *, isp_icb_t *, isp_icb_t *);
static INLINE void
isp_get_pdb(struct ispsoftc *, isp_pdb_t *, isp_pdb_t *);
static INLINE void
+isp_get_ct_hdr(struct ispsoftc *isp, ct_hdr_t *, ct_hdr_t *);
+static INLINE void
isp_put_sns_request(struct ispsoftc *, sns_screq_t *, sns_screq_t *);
static INLINE void
+isp_put_gid_ft_request(struct ispsoftc *, sns_gid_ft_req_t *,
+ sns_gid_ft_req_t *);
+static INLINE void
+isp_put_gxn_id_request(struct ispsoftc *, sns_gxn_id_req_t *,
+ sns_gxn_id_req_t *);
+static INLINE void
isp_get_sns_response(struct ispsoftc *, sns_scrsp_t *, sns_scrsp_t *, int);
static INLINE void
-isp_get_gan_response(struct ispsoftc *, sns_ganrsp_t *, sns_ganrsp_t *);
+isp_get_gid_ft_response(struct ispsoftc *, sns_gid_ft_rsp_t *,
+ sns_gid_ft_rsp_t *, int);
+static INLINE void
+isp_get_gxn_id_response(struct ispsoftc *, sns_gxn_id_rsp_t *,
+ sns_gxn_id_rsp_t *);
+static INLINE void
+isp_get_gff_id_response(struct ispsoftc *, sns_gff_id_rsp_t *,
+ sns_gff_id_rsp_t *);
+static INLINE void
+isp_get_ga_nxt_response(struct ispsoftc *, sns_ga_nxt_rsp_t *,
+ sns_ga_nxt_rsp_t *);
#ifdef ISP_TARGET_MODE
#ifndef _ISP_TARGET_H
#include "isp_target.h"
@@ -673,6 +691,35 @@ isp_get_pdb(struct ispsoftc *isp, isp_pdb_t *src, isp_pdb_t *dst)
ISP_IOXGET_16(isp, &src->pdb_sl_ptr, dst->pdb_sl_ptr);
}
+
+/*
+ * CT_HDR canonicalization- only needed for SNS responses
+ */
+static INLINE void
+isp_get_ct_hdr(struct ispsoftc *isp, ct_hdr_t *src, ct_hdr_t *dst)
+{
+ ISP_IOXGET_8(isp, &src->ct_revision, dst->ct_revision);
+ ISP_IOXGET_8(isp, &src->ct_portid[0], dst->ct_portid[0]);
+ ISP_IOXGET_8(isp, &src->ct_portid[1], dst->ct_portid[1]);
+ ISP_IOXGET_8(isp, &src->ct_portid[2], dst->ct_portid[2]);
+ ISP_IOXGET_8(isp, &src->ct_fcs_type, dst->ct_fcs_type);
+ ISP_IOXGET_8(isp, &src->ct_fcs_subtype, dst->ct_fcs_subtype);
+ ISP_IOXGET_8(isp, &src->ct_options, dst->ct_options);
+ ISP_IOXGET_8(isp, &src->ct_res0, dst->ct_res0);
+ ISP_IOXGET_16(isp, &src->ct_response, dst->ct_response);
+ dst->ct_response = (dst->ct_response << 8) | (dst->ct_response >> 8);
+ ISP_IOXGET_16(isp, &src->ct_resid, dst->ct_resid);
+ dst->ct_resid = (dst->ct_resid << 8) | (dst->ct_resid >> 8);
+ ISP_IOXGET_8(isp, &src->ct_res1, dst->ct_res1);
+ ISP_IOXGET_8(isp, &src->ct_reason, dst->ct_reason);
+ ISP_IOXGET_8(isp, &src->ct_explanation, dst->ct_explanation);
+ ISP_IOXGET_8(isp, &src->ct_vunique, dst->ct_vunique);
+}
+
+/*
+ * Generic SNS request - not particularly useful since the per-command data
+ * isn't always 16 bit words.
+ */
static INLINE void
isp_put_sns_request(struct ispsoftc *isp, sns_screq_t *src, sns_screq_t *dst)
{
@@ -689,13 +736,51 @@ isp_put_sns_request(struct ispsoftc *isp, sns_screq_t *src, sns_screq_t *dst)
}
static INLINE void
+isp_put_gid_ft_request(struct ispsoftc *isp, sns_gid_ft_req_t *src,
+ sns_gid_ft_req_t *dst)
+{
+ ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
+ ISP_IOXPUT_16(isp, src->snscb_res0, &dst->snscb_res0);
+ ISP_IOXPUT_16(isp, src->snscb_addr[0], &dst->snscb_addr[0]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[1], &dst->snscb_addr[1]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[2], &dst->snscb_addr[2]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[3], &dst->snscb_addr[3]);
+ ISP_IOXPUT_16(isp, src->snscb_sblen, &dst->snscb_sblen);
+ ISP_IOXPUT_16(isp, src->snscb_res1, &dst->snscb_res1);
+ ISP_IOXPUT_16(isp, src->snscb_cmd, &dst->snscb_cmd);
+ ISP_IOXPUT_16(isp, src->snscb_mword_div_2, &dst->snscb_mword_div_2);
+ ISP_IOXPUT_32(isp, src->snscb_res3, &dst->snscb_res3);
+ ISP_IOXPUT_32(isp, src->snscb_fc4_type, &dst->snscb_fc4_type);
+}
+
+static INLINE void
+isp_put_gxn_id_request(struct ispsoftc *isp, sns_gxn_id_req_t *src,
+ sns_gxn_id_req_t *dst)
+{
+ ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
+ ISP_IOXPUT_16(isp, src->snscb_res0, &dst->snscb_res0);
+ ISP_IOXPUT_16(isp, src->snscb_addr[0], &dst->snscb_addr[0]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[1], &dst->snscb_addr[1]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[2], &dst->snscb_addr[2]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[3], &dst->snscb_addr[3]);
+ ISP_IOXPUT_16(isp, src->snscb_sblen, &dst->snscb_sblen);
+ ISP_IOXPUT_16(isp, src->snscb_res1, &dst->snscb_res1);
+ ISP_IOXPUT_16(isp, src->snscb_cmd, &dst->snscb_cmd);
+ ISP_IOXPUT_16(isp, src->snscb_res2, &dst->snscb_res2);
+ ISP_IOXPUT_32(isp, src->snscb_res3, &dst->snscb_res3);
+ ISP_IOXPUT_32(isp, src->snscb_portid, &dst->snscb_portid);
+}
+
+/*
+ * Generic SNS response - not particularly useful since the per-command data
+ * isn't always 16 bit words.
+ */
+static INLINE void
isp_get_sns_response(struct ispsoftc *isp, sns_scrsp_t *src,
sns_scrsp_t *dst, int nwords)
{
int i;
- for (i = 0; i < 16; i++) {
- ISP_IOXGET_8(isp, &src->snscb_cthdr[i], dst->snscb_cthdr[i]);
- }
+ isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
ISP_IOXGET_8(isp, &src->snscb_port_type, dst->snscb_port_type);
for (i = 0; i < 3; i++) {
ISP_IOXGET_8(isp, &src->snscb_port_id[i],
@@ -711,12 +796,55 @@ isp_get_sns_response(struct ispsoftc *isp, sns_scrsp_t *src,
}
static INLINE void
-isp_get_gan_response(struct ispsoftc *isp, sns_ganrsp_t *src, sns_ganrsp_t *dst)
+isp_get_gid_ft_response(struct ispsoftc *isp, sns_gid_ft_rsp_t *src,
+ sns_gid_ft_rsp_t *dst, int nwords)
{
int i;
- for (i = 0; i < 16; i++) {
- ISP_IOXGET_8(isp, &src->snscb_cthdr[i], dst->snscb_cthdr[i]);
+ isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
+ for (i = 0; i < nwords; i++) {
+ int j;
+ ISP_IOXGET_8(isp,
+ &src->snscb_ports[i].control,
+ dst->snscb_ports[i].control);
+ for (j = 0; j < 3; j++) {
+ ISP_IOXGET_8(isp,
+ &src->snscb_ports[i].portid[j],
+ dst->snscb_ports[i].portid[j]);
+ }
+ if (dst->snscb_ports[i].control & 0x80) {
+ break;
+ }
+ }
+}
+
+static INLINE void
+isp_get_gxn_id_response(struct ispsoftc *isp, sns_gxn_id_rsp_t *src,
+ sns_gxn_id_rsp_t *dst)
+{
+ int i;
+ isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
+ for (i = 0; i < 8; i++)
+ ISP_IOXGET_8(isp, &src->snscb_wwn[i], dst->snscb_wwn[i]);
+}
+
+static INLINE void
+isp_get_gff_id_response(struct ispsoftc *isp, sns_gff_id_rsp_t *src,
+ sns_gff_id_rsp_t *dst)
+{
+ int i;
+ isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
+ for (i = 0; i < 32; i++) {
+ ISP_IOXGET_32(isp, &src->snscb_fc4_features[i],
+ dst->snscb_fc4_features[i]);
}
+}
+
+static INLINE void
+isp_get_ga_nxt_response(struct ispsoftc *isp, sns_ga_nxt_rsp_t *src,
+ sns_ga_nxt_rsp_t *dst)
+{
+ int i;
+ isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
ISP_IOXGET_8(isp, &src->snscb_port_type, dst->snscb_port_type);
for (i = 0; i < 3; i++) {
ISP_IOXGET_8(isp, &src->snscb_port_id[i],
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 8c4e36291b3e..9419ae8c6df2 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -254,6 +254,7 @@ static struct ispmdvec mdvec_2300 = {
static int isp_pci_probe (device_t);
static int isp_pci_attach (device_t);
+
struct isp_pcisoftc {
struct ispsoftc pci_isp;
device_t pci_dev;
@@ -262,9 +263,7 @@ struct isp_pcisoftc {
bus_space_handle_t pci_sh;
void * ih;
int16_t pci_poff[_NREG_BLKS];
- bus_dma_tag_t parent_dmat;
- bus_dma_tag_t cntrol_dmat;
- bus_dmamap_t cntrol_dmap;
+ bus_dma_tag_t dmat;
bus_dmamap_t *dmaps;
};
ispfwfunc *isp_get_firmware_p = NULL;
@@ -565,16 +564,6 @@ isp_pci_attach(device_t dev)
data &= ~1;
pci_write_config(dev, PCIR_ROMADDR, data, 4);
-
- if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
- BUS_SPACE_MAXADDR, NULL, NULL, lim + 1,
- 255, lim, 0, &pcs->parent_dmat) != 0) {
- device_printf(dev, "could not create master dma tag\n");
- free(isp->isp_param, M_DEVBUF);
- free(pcs, M_DEVBUF);
- return (ENXIO);
- }
-
iqd = 0;
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &iqd, 0, ~0,
1, RF_ACTIVE | RF_SHAREABLE);
@@ -973,60 +962,49 @@ isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val)
}
}
-static void isp_map_rquest(void *, bus_dma_segment_t *, int, int);
-static void isp_map_result(void *, bus_dma_segment_t *, int, int);
-static void isp_map_fcscrt(void *, bus_dma_segment_t *, int, int);
struct imush {
struct ispsoftc *isp;
int error;
};
-static void
-isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- struct imush *imushp = (struct imush *) arg;
- if (error) {
- imushp->error = error;
- } else {
- imushp->isp->isp_rquest_dma = segs->ds_addr;
- }
-}
+static void imc(void *, bus_dma_segment_t *, int, int);
static void
-isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+imc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
struct imush *imushp = (struct imush *) arg;
if (error) {
imushp->error = error;
} else {
- imushp->isp->isp_result_dma = segs->ds_addr;
- }
-}
+ struct ispsoftc *isp =imushp->isp;
+ bus_addr_t addr = segs->ds_addr;
-static void
-isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- struct imush *imushp = (struct imush *) arg;
- if (error) {
- imushp->error = error;
- } else {
- fcparam *fcp = imushp->isp->isp_param;
- fcp->isp_scdma = segs->ds_addr;
+ isp->isp_rquest_dma = addr;
+ addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
+ isp->isp_result_dma = addr;
+ if (IS_FC(isp)) {
+ addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
+ FCPARAM(isp)->isp_scdma = addr;
+ }
}
}
+/*
+ * Should be BUS_SPACE_MAXSIZE, but MAXPHYS is larger than BUS_SPACE_MAXSIZE
+ */
+#define ISP_NSEGS ((MAXPHYS / PAGE_SIZE) + 1)
+
static int
isp_pci_mbxdma(struct ispsoftc *isp)
{
- struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
+ struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
caddr_t base;
u_int32_t len;
- int i, error;
- bus_size_t lim;
+ int i, error, ns;
+ bus_size_t bl;
struct imush im;
-
/*
* Already been here? If so, leave...
*/
@@ -1034,6 +1012,20 @@ isp_pci_mbxdma(struct ispsoftc *isp)
return (0);
}
+ if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) {
+ bl = BUS_SPACE_UNRESTRICTED;
+ } else {
+ bl = BUS_SPACE_MAXADDR_24BIT;
+ }
+
+ if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE,
+ ISP_NSEGS, bl, 0, &pcs->dmat)) {
+ isp_prt(isp, ISP_LOGERR, "could not create master dma tag");
+ return(1);
+ }
+
+
len = sizeof (XS_T **) * isp->isp_maxcmds;
isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
if (isp->isp_xflist == NULL) {
@@ -1041,18 +1033,13 @@ isp_pci_mbxdma(struct ispsoftc *isp)
return (1);
}
len = sizeof (bus_dmamap_t) * isp->isp_maxcmds;
- pci->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK);
- if (pci->dmaps == NULL) {
- isp_prt(isp, ISP_LOGERR, "can't alloc dma maps");
+ pcs->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK);
+ if (pcs->dmaps == NULL) {
+ isp_prt(isp, ISP_LOGERR, "can't alloc dma map storage");
free(isp->isp_xflist, M_DEVBUF);
return (1);
}
- if (IS_FC(isp) || IS_ULTRA2(isp))
- lim = BUS_SPACE_MAXADDR + 1;
- else
- lim = BUS_SPACE_MAXADDR_24BIT + 1;
-
/*
* Allocate and map the request, result queues, plus FC scratch area.
*/
@@ -1061,80 +1048,64 @@ isp_pci_mbxdma(struct ispsoftc *isp)
if (IS_FC(isp)) {
len += ISP2100_SCRLEN;
}
- if (bus_dma_tag_create(pci->parent_dmat, PAGE_SIZE, lim,
- BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1,
- BUS_SPACE_MAXSIZE_32BIT, 0, &pci->cntrol_dmat) != 0) {
+
+ ns = (len / PAGE_SIZE) + 1;
+ if (bus_dma_tag_create(pcs->dmat, QENTRY_LEN, 0, BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR, NULL, NULL, len, ns, bl, 0, &isp->isp_cdmat)) {
isp_prt(isp, ISP_LOGERR,
"cannot create a dma tag for control spaces");
+ free(pcs->dmaps, M_DEVBUF);
free(isp->isp_xflist, M_DEVBUF);
- free(pci->dmaps, M_DEVBUF);
- return (1);
- }
- if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base,
- BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) {
- isp_prt(isp, ISP_LOGERR,
- "cannot allocate %d bytes of CCB memory", len);
- free(isp->isp_xflist, M_DEVBUF);
- free(pci->dmaps, M_DEVBUF);
return (1);
}
- isp->isp_rquest = base;
- im.isp = isp;
- im.error = 0;
- bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest,
- ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), isp_map_rquest, &im, 0);
- if (im.error) {
+ if (bus_dmamem_alloc(isp->isp_cdmat, (void **)&base, BUS_DMA_NOWAIT,
+ &isp->isp_cdmap) != 0) {
isp_prt(isp, ISP_LOGERR,
- "error %d loading dma map for DMA request queue", im.error);
- free(isp->isp_xflist, M_DEVBUF);
- free(pci->dmaps, M_DEVBUF);
- isp->isp_rquest = NULL;
- return (1);
- }
- isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
- im.error = 0;
- bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result,
- ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)), isp_map_result, &im, 0);
- if (im.error) {
- isp_prt(isp, ISP_LOGERR,
- "error %d loading dma map for DMA result queue", im.error);
+ "cannot allocate %d bytes of CCB memory", len);
+ bus_dma_tag_destroy(isp->isp_cdmat);
free(isp->isp_xflist, M_DEVBUF);
- free(pci->dmaps, M_DEVBUF);
- isp->isp_rquest = NULL;
+ free(pcs->dmaps, M_DEVBUF);
return (1);
}
for (i = 0; i < isp->isp_maxcmds; i++) {
- error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]);
+ error = bus_dmamap_create(pcs->dmat, 0, &pcs->dmaps[i]);
if (error) {
isp_prt(isp, ISP_LOGERR,
"error %d creating per-cmd DMA maps", error);
- free(isp->isp_xflist, M_DEVBUF);
- free(pci->dmaps, M_DEVBUF);
- isp->isp_rquest = NULL;
- return (1);
+ while (--i >= 0) {
+ bus_dmamap_destroy(pcs->dmat, pcs->dmaps[i]);
+ }
+ goto bad;
}
}
+ im.isp = isp;
+ im.error = 0;
+ bus_dmamap_load(isp->isp_cdmat, isp->isp_cdmap, base, len, imc, &im, 0);
+ if (im.error) {
+ isp_prt(isp, ISP_LOGERR,
+ "error %d loading dma map for control areas", im.error);
+ goto bad;
+ }
+
+ isp->isp_rquest = base;
+ base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
+ isp->isp_result = base;
if (IS_FC(isp)) {
- fcparam *fcp = (fcparam *) isp->isp_param;
- fcp->isp_scratch = base +
- ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) +
- ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
- im.error = 0;
- bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap,
- fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, &im, 0);
- if (im.error) {
- isp_prt(isp, ISP_LOGERR,
- "error %d loading FC scratch area", im.error);
- free(isp->isp_xflist, M_DEVBUF);
- free(pci->dmaps, M_DEVBUF);
- isp->isp_rquest = NULL;
- return (1);
- }
+ base += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
+ FCPARAM(isp)->isp_scratch = base;
}
return (0);
+
+bad:
+ bus_dmamem_free(isp->isp_cdmat, base, isp->isp_cdmap);
+ bus_dma_tag_destroy(isp->isp_cdmat);
+ free(isp->isp_xflist, M_DEVBUF);
+ free(pcs->dmaps, M_DEVBUF);
+ isp->isp_rquest = NULL;
+ return (1);
}
typedef struct {
@@ -1176,7 +1147,7 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
mush_t *mp;
struct ccb_scsiio *csio;
struct ispsoftc *isp;
- struct isp_pcisoftc *pci;
+ struct isp_pcisoftc *pcs;
bus_dmamap_t *dp;
ct_entry_t *cto, *qe;
u_int8_t scsi_status;
@@ -1257,12 +1228,12 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
cto->ct_resid = 0;
cto->ct_scsi_status = 0;
- pci = (struct isp_pcisoftc *)isp;
- dp = &pci->dmaps[isp_handle_index(handle)];
+ pcs = (struct isp_pcisoftc *)isp;
+ dp = &pcs->dmaps[isp_handle_index(handle)];
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
} else {
- bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
}
nxti = *mp->nxtip;
@@ -1414,7 +1385,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
u_int8_t sense[QLTM_SENSELEN];
struct ccb_scsiio *csio;
struct ispsoftc *isp;
- struct isp_pcisoftc *pci;
+ struct isp_pcisoftc *pcs;
bus_dmamap_t *dp;
ct2_entry_t *cto, *qe;
u_int16_t scsi_status, send_status, send_sense, handle;
@@ -1531,12 +1502,12 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
cto->rsp.m0.ct_scsi_status = 0;
MEMZERO(&cto->rsp, sizeof (cto->rsp));
- pci = (struct isp_pcisoftc *)isp;
- dp = &pci->dmaps[isp_handle_index(handle)];
+ pcs = (struct isp_pcisoftc *)isp;
+ dp = &pcs->dmaps[isp_handle_index(handle)];
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
} else {
- bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
}
nxti = *mp->nxtip;
@@ -1721,7 +1692,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
mush_t *mp;
struct ispsoftc *isp;
struct ccb_scsiio *csio;
- struct isp_pcisoftc *pci;
+ struct isp_pcisoftc *pcs;
bus_dmamap_t *dp;
bus_dma_segment_t *eseg;
ispreq_t *rq;
@@ -1742,14 +1713,14 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
csio = mp->cmd_token;
isp = mp->isp;
rq = mp->rq;
- pci = (struct isp_pcisoftc *)mp->isp;
- dp = &pci->dmaps[isp_handle_index(rq->req_handle)];
+ pcs = (struct isp_pcisoftc *)mp->isp;
+ dp = &pcs->dmaps[isp_handle_index(rq->req_handle)];
nxti = *mp->nxtip;
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
} else {
- bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
}
datalen = XS_XFRLEN(csio);
@@ -1843,7 +1814,7 @@ static int
isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq,
u_int16_t *nxtip, u_int16_t optr)
{
- struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
+ struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
ispreq_t *qep;
bus_dmamap_t *dp = NULL;
mush_t mush, *mp;
@@ -1895,12 +1866,12 @@ isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq,
if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) {
int error, s;
- dp = &pci->dmaps[isp_handle_index(rq->req_handle)];
+ dp = &pcs->dmaps[isp_handle_index(rq->req_handle)];
s = splsoftvm();
- error = bus_dmamap_load(pci->parent_dmat, *dp,
+ error = bus_dmamap_load(pcs->dmat, *dp,
csio->data_ptr, csio->dxfer_len, eptr, mp, 0);
if (error == EINPROGRESS) {
- bus_dmamap_unload(pci->parent_dmat, *dp);
+ bus_dmamap_unload(pcs->dmat, *dp);
mp->error = EINVAL;
isp_prt(isp, ISP_LOGERR,
"deferred dma allocation not supported");
@@ -1968,14 +1939,14 @@ mbxsync:
static void
isp_pci_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int16_t handle)
{
- struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
- bus_dmamap_t *dp = &pci->dmaps[isp_handle_index(handle)];
+ struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
+ bus_dmamap_t *dp = &pcs->dmaps[isp_handle_index(handle)];
if ((xs->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_POSTREAD);
} else {
- bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_POSTWRITE);
}
- bus_dmamap_unload(pci->parent_dmat, *dp);
+ bus_dmamap_unload(pcs->dmat, *dp);
}
@@ -1991,7 +1962,7 @@ isp_pci_reset1(struct ispsoftc *isp)
static void
isp_pci_dumpregs(struct ispsoftc *isp, const char *msg)
{
- struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
+ struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
if (msg)
printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg);
else
@@ -2024,5 +1995,5 @@ isp_pci_dumpregs(struct ispsoftc *isp, const char *msg)
ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3),
ISP_READ(isp, OUTMAILBOX4));
printf(" PCI Status Command/Status=%x\n",
- pci_read_config(pci->pci_dev, PCIR_COMMAND, 1));
+ pci_read_config(pcs->pci_dev, PCIR_COMMAND, 1));
}
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index ea628779046e..6241f16504e6 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -773,9 +773,40 @@ typedef struct {
#define SVC3_ROLE_MASK 0x30
#define SVC3_ROLE_SHIFT 4
-#define SNS_GAN 0x100
-#define SNS_GP3 0x171
-#define SNS_RFT 0x217
+/*
+ * CT definition
+ *
+ * This is as the QLogic f/w documentations defines it- which is just opposite,
+ * bit wise, from what the specification defines it as. Additionally, the
+ * ct_response and ct_resid (really from FC-GS-2) need to be byte swapped.
+ */
+
+typedef struct {
+ u_int8_t ct_revision;
+ u_int8_t ct_portid[3];
+ u_int8_t ct_fcs_type;
+ u_int8_t ct_fcs_subtype;
+ u_int8_t ct_options;
+ u_int8_t ct_res0;
+ u_int16_t ct_response;
+ u_int16_t ct_resid;
+ u_int8_t ct_res1;
+ u_int8_t ct_reason;
+ u_int8_t ct_explanation;
+ u_int8_t ct_vunique;
+} ct_hdr_t;
+#define FS_ACC 0x8002
+#define FS_RJT 0x8001
+
+#define FC4_IP 5 /* ISO/EEC 8802-2 LLC/SNAP "Out of Order Delivery" */
+#define FC4_SCSI 8 /* SCSI-3 via Fivre Channel Protocol (FCP) */
+
+#define SNS_GA_NXT 0x100
+#define SNS_GPN_ID 0x112
+#define SNS_GNN_ID 0x113
+#define SNS_GFF_ID 0x11F
+#define SNS_GID_FT 0x171
+#define SNS_RFT_ID 0x217
typedef struct {
u_int16_t snscb_rblen; /* response buffer length (words) */
u_int16_t snscb_res0;
@@ -784,23 +815,70 @@ typedef struct {
u_int16_t snscb_res1;
u_int16_t snscb_data[1]; /* variable data */
} sns_screq_t; /* Subcommand Request Structure */
-#define SNS_GAN_REQ_SIZE (sizeof (sns_screq_t)+(5*(sizeof (u_int16_t))))
-#define SNS_GP3_REQ_SIZE (sizeof (sns_screq_t)+(5*(sizeof (u_int16_t))))
-#define SNS_RFT_REQ_SIZE (sizeof (sns_screq_t)+(21*(sizeof (u_int16_t))))
typedef struct {
- u_int8_t snscb_cthdr[16];
+ u_int16_t snscb_rblen; /* response buffer length (words) */
+ u_int16_t snscb_res0;
+ u_int16_t snscb_addr[4]; /* response buffer address */
+ u_int16_t snscb_sblen; /* subcommand buffer length (words) */
+ u_int16_t snscb_res1;
+ u_int16_t snscb_cmd;
+ u_int16_t snscb_res2;
+ u_int32_t snscb_res3;
+ u_int32_t snscb_port;
+} sns_ga_nxt_req_t;
+#define SNS_GA_NXT_REQ_SIZE (sizeof (sns_ga_nxt_req_t))
+
+typedef struct {
+ u_int16_t snscb_rblen; /* response buffer length (words) */
+ u_int16_t snscb_res0;
+ u_int16_t snscb_addr[4]; /* response buffer address */
+ u_int16_t snscb_sblen; /* subcommand buffer length (words) */
+ u_int16_t snscb_res1;
+ u_int16_t snscb_cmd;
+ u_int16_t snscb_res2;
+ u_int32_t snscb_res3;
+ u_int32_t snscb_portid;
+} sns_gxn_id_req_t;
+#define SNS_GXN_ID_REQ_SIZE (sizeof (sns_gxn_id_req_t))
+
+typedef struct {
+ u_int16_t snscb_rblen; /* response buffer length (words) */
+ u_int16_t snscb_res0;
+ u_int16_t snscb_addr[4]; /* response buffer address */
+ u_int16_t snscb_sblen; /* subcommand buffer length (words) */
+ u_int16_t snscb_res1;
+ u_int16_t snscb_cmd;
+ u_int16_t snscb_mword_div_2;
+ u_int32_t snscb_res3;
+ u_int32_t snscb_fc4_type;
+} sns_gid_ft_req_t;
+#define SNS_GID_FT_REQ_SIZE (sizeof (sns_gid_ft_req_t))
+
+typedef struct {
+ u_int16_t snscb_rblen; /* response buffer length (words) */
+ u_int16_t snscb_res0;
+ u_int16_t snscb_addr[4]; /* response buffer address */
+ u_int16_t snscb_sblen; /* subcommand buffer length (words) */
+ u_int16_t snscb_res1;
+ u_int16_t snscb_cmd;
+ u_int16_t snscb_res2;
+ u_int32_t snscb_res3;
+ u_int32_t snscb_port;
+ u_int32_t snscb_fc4_types[8];
+} sns_rft_id_req_t;
+#define SNS_RFT_ID_REQ_SIZE (sizeof (sns_rft_id_req_t))
+
+typedef struct {
+ ct_hdr_t snscb_cthdr;
u_int8_t snscb_port_type;
u_int8_t snscb_port_id[3];
u_int8_t snscb_portname[8];
u_int16_t snscb_data[1]; /* variable data */
} sns_scrsp_t; /* Subcommand Response Structure */
-#define SNS_GAN_RESP_SIZE 608 /* Maximum response size (bytes) */
-#define SNS_GP3_RESP_SIZE 532 /* XXX: For 128 ports */
-#define SNS_RFT_RESP_SIZE 16
typedef struct {
- u_int8_t snscb_cthdr[16];
+ ct_hdr_t snscb_cthdr;
u_int8_t snscb_port_type;
u_int8_t snscb_port_id[3];
u_int8_t snscb_portname[8];
@@ -816,6 +894,30 @@ typedef struct {
u_int8_t snscb_fpname[8];
u_int8_t snscb_reserved;
u_int8_t snscb_hardaddr[3];
-} sns_ganrsp_t; /* Subcommand Response Structure */
+} sns_ga_nxt_rsp_t; /* Subcommand Response Structure */
+#define SNS_GA_NXT_RESP_SIZE (sizeof (sns_ga_nxt_rsp_t))
+
+typedef struct {
+ ct_hdr_t snscb_cthdr;
+ u_int8_t snscb_wwn[8];
+} sns_gxn_id_rsp_t;
+#define SNS_GXN_ID_RESP_SIZE (sizeof (sns_gxn_id_rsp_t))
+
+typedef struct {
+ ct_hdr_t snscb_cthdr;
+ u_int32_t snscb_fc4_features[32];
+} sns_gff_id_rsp_t;
+#define SNS_GFF_ID_RESP_SIZE (sizeof (sns_gff_id_rsp_t))
+
+typedef struct {
+ ct_hdr_t snscb_cthdr;
+ struct {
+ u_int8_t control;
+ u_int8_t portid[3];
+ } snscb_ports[1];
+} sns_gid_ft_rsp_t;
+#define SNS_GID_FT_RESP_SIZE(x) ((sizeof (sns_gid_ft_rsp_t)) + ((x - 1) << 2))
+
+#define SNS_RFT_ID_RESP_SIZE (sizeof (ct_hdr_t))
#endif /* _ISPMBOX_H */
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index 53025f1f27b8..982bb2e9ab8d 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -54,7 +54,7 @@
#endif
#define ISP_CORE_VERSION_MAJOR 2
-#define ISP_CORE_VERSION_MINOR 5
+#define ISP_CORE_VERSION_MINOR 6
/*
* Vector for bus specific code to provide specific services.
@@ -149,8 +149,12 @@ struct ispmdvec {
#define QENTRY_LEN 64
/* Both request and result queue length must be a power of two */
#define RQUEST_QUEUE_LEN(x) MAXISPREQUEST(x)
+#ifdef ISP_TARGET_MODE
+#define RESULT_QUEUE_LEN(x) MAXISPREQUEST(x)
+#else
#define RESULT_QUEUE_LEN(x) \
(((MAXISPREQUEST(x) >> 2) < 64)? 64 : MAXISPREQUEST(x) >> 2)
+#endif
#define ISP_QUEUE_ENTRY(q, idx) ((q) + ((idx) * QENTRY_LEN))
#define ISP_QUEUE_SIZE(n) ((n) * QENTRY_LEN)
#define ISP_NXT_QENTRY(idx, qlen) (((idx) + 1) & ((qlen)-1))
@@ -242,6 +246,11 @@ typedef struct {
#define FC_PORT_ID 0x7f /* Fabric Controller Special ID */
#define FC_SNS_ID 0x80 /* SNS Server Special ID */
+/* #define ISP_USE_GA_NXT 1 */ /* Use GA_NXT with switches */
+#ifndef GA_NXT_MAX
+#define GA_NXT_MAX 256
+#endif
+
typedef struct {
u_int32_t isp_fwoptions : 16,
isp_gbspeed : 2,
@@ -276,9 +285,12 @@ typedef struct {
* to move around.
*/
struct lportdb {
- u_int
+ u_int32_t
+ port_type : 8,
+ : 4,
+ fc4_type : 4,
loopid : 8,
- : 1,
+ last_fabric_dev : 1,
force_logout : 1,
was_fabric_dev : 1,
fabric_dev : 1,