diff options
author | mjacob <mjacob@FreeBSD.org> | 2002-04-04 23:46:01 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2002-04-04 23:46:01 +0000 |
commit | f62deac6f06bab39d2dffeb95d82b8341445d5af (patch) | |
tree | 58b8cc455f67309f7a70758f449ddc01e0ded92b /sys | |
parent | 2be9f95449ddaa06d1bf21938e091ea7ecd27626 (diff) | |
download | FreeBSD-src-f62deac6f06bab39d2dffeb95d82b8341445d5af.zip FreeBSD-src-f62deac6f06bab39d2dffeb95d82b8341445d5af.tar.gz |
Fix bus dma segment count to be based off of MAXPHYS, not BUS_SPACE_MAXSIZE.
Grumble. I've seen better documented architectures out of Redmond.
Redo fabric evaluation to not use GET ALL NEXT (GA_NXT). Switches seem
to be trying to wriggle out of supporting this well. Instead, use
GID_FT to get a list of Port IDs and then use GPN_ID/GNN_ID to find the
port and node wwn. This should make working on fabrics a bit cleaner and
more stable.
This also caused some cleanup of SNS subcommand canonicalization so that
we can actually check for FS_ACC and FS_RJT, and if we get an FS_RJT,
print out the reason and explanation codes.
We'll keep the old GA_NXT method around if people want to uncomment a
controlling definition in ispvar.h.
This also had us clean up ISPASYNC_FABRICDEV to use a local lportdb argument
and to have the caller explicitly say that a device is at the end of the
fabric list.
MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/isp/isp.c | 451 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 102 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.h | 2 | ||||
-rw-r--r-- | sys/dev/isp/isp_inline.h | 127 | ||||
-rw-r--r-- | sys/dev/isp/isp_pci.c | 15 | ||||
-rw-r--r-- | sys/dev/isp/ispmbox.h | 120 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 14 |
7 files changed, 675 insertions, 156 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index b6b9d4d..83af43e 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); @@ -2298,21 +2301,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 +2374,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 +2403,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 +2486,285 @@ 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; + u_int8_t sc[GIDLEN]; /* XXX USE ->tport */ + int i; + sns_gid_ft_req_t *rq; + sns_gid_ft_rsp_t *rs0, *rs1; + + 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 *)sc; + 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); - if (hicap >= 65535) { - isp_prt(isp, ISP_LOGWARN, "fabric too big (> 65535)"); + /* + * 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 *) sc; + 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; + + 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", + rs1->snscb_cthdr.ct_reason, + rs1->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", + rs1->snscb_cthdr.ct_reason, + rs1->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])); + + /* + * XXX: Argh! I saw some PDF which I now can't find that + * XXX: had proposed that the bottom nibble of CONTROL + * XXX: would have the SCSI-FCP role flags, which would + * XXX: be *awesome*. + * + lcl.roles = rs1->snscb_port[i].control & 0xf; + */ + + /* + * 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 +2962,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 +3261,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; diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 228669b..dda04a9 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -2734,43 +2734,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; @@ -2793,40 +2763,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; } @@ -2835,14 +2831,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 38f0b36..5496b1a 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -156,7 +156,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 f65c365..559cad0 100644 --- a/sys/dev/isp/isp_inline.h +++ b/sys/dev/isp/isp_inline.h @@ -275,11 +275,26 @@ 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_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 +688,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 +733,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_16(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 +793,43 @@ 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_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 65aa923..66a9534 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -241,16 +241,6 @@ static struct ispmdvec mdvec_2300 = { ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) /* - * I/O Mapping Stuff - */ -#if _MACHINE_ARCH == SPARC64 -/* An IOMMU means that we only will ever need one descriptor. */ -#define ISP_NSEG 2 -#else -#define ISP_NSEG ((MAXPHYS/PAGE_SIZE) + 1) -#endif - -/* * Odd case for some AMI raid cards... We need to *not* attach to this. */ #define AMI_RAID_SUBVENDOR_ID 0x101e @@ -1031,7 +1021,10 @@ imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) } } -#define ISP_NSEGS ((BUS_SPACE_MAXSIZE / PAGE_SIZE) + 1) +/* + * 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) diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h index ea62877..1bf7648 100644 --- a/sys/dev/isp/ispmbox.h +++ b/sys/dev/isp/ispmbox.h @@ -773,9 +773,39 @@ 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_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 +814,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 +893,25 @@ 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; + 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 6ceab04..982bb2e 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. @@ -246,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, @@ -280,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, |