diff options
| author | Matt Jacob <mjacob@FreeBSD.org> | 2002-04-16 21:41:22 +0000 |
|---|---|---|
| committer | Matt Jacob <mjacob@FreeBSD.org> | 2002-04-16 21:41:22 +0000 |
| commit | 794e31e9a5487c789a6ad778bf7194b3480f638a (patch) | |
| tree | 291d6da48569bef69c5bd171316e348ca03b3eaf /sys/dev/isp | |
| parent | b52e510fa40b901076f579ad08b8d3fd4dc93bbf (diff) | |
Notes
Diffstat (limited to 'sys/dev/isp')
| -rw-r--r-- | sys/dev/isp/isp.c | 544 | ||||
| -rw-r--r-- | sys/dev/isp/isp_freebsd.c | 104 | ||||
| -rw-r--r-- | sys/dev/isp/isp_freebsd.h | 10 | ||||
| -rw-r--r-- | sys/dev/isp/isp_inline.h | 142 | ||||
| -rw-r--r-- | sys/dev/isp/isp_pci.c | 231 | ||||
| -rw-r--r-- | sys/dev/isp/ispmbox.h | 126 | ||||
| -rw-r--r-- | sys/dev/isp/ispvar.h | 18 |
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, |
