Deleted Added
full compact
1c1
< /* $FreeBSD: head/sys/dev/isp/isp.c 92893 2002-03-21 21:10:16Z mjacob $ */
---
> /* $FreeBSD: head/sys/dev/isp/isp.c 93837 2002-04-04 23:46:01Z mjacob $ */
98a99,100
> static const char swrej[] =
> "Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x";
130c132,133
< 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);
2301,2303c2304
< #ifndef HICAP_MAX
< #define HICAP_MAX 256
< #endif
---
>
2305c2306
< isp_scan_fabric(struct ispsoftc *isp)
---
> isp_fabric_mbox_cmd(struct ispsoftc *isp, mbreg_t *mbp)
2306a2308,2356
> 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, int ftype)
> {
2309c2359
< int hicap, first_portid_seen, last_port_same;
---
> int hicap, last_port_same;
2315a2366
> FC_SCRATCH_ACQUIRE(isp);
2326c2377
< for (first_portid_seen = hicap = 0; hicap < HICAP_MAX; hicap++) {
---
> for (hicap = 0; hicap < GA_NXT_MAX; hicap++) {
2329,2330c2380,2382
< 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];
2333,2334c2385,2386
< 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;
2340c2392
< rq->snscb_data[0] = SNS_GAN;
---
> rq->snscb_data[0] = SNS_GA_NXT;
2343d2394
< FC_SCRATCH_ACQUIRE(isp);
2345c2396
< MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GAN_REQ_SIZE);
---
> MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GA_NXT_REQ_SIZE);
2347c2398
< mbs.param[1] = SNS_GAN_REQ_SIZE >> 1;
---
> mbs.param[1] = SNS_GA_NXT_REQ_SIZE >> 1;
2355,2357c2406,2407
< 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) {
2360,2389c2410
< 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);
2392,2393c2413,2420
< 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);
2395c2422,2423
< return (-1);
---
> fcp->isp_loopstate = LOOP_FSCAN_DONE;
> return (0);
2397,2402c2425,2426
< 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) |
2405c2429,2476
< (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);
> }
2407a2479
> FC_SCRATCH_RELEASE(isp);
2416a2489
> last_port_same = 0 ;
2419a2493,2502
> 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)
2421,2422c2504,2519
< if (hicap >= 65535) {
< isp_prt(isp, ISP_LOGWARN, "fabric too big (> 65535)");
---
> #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);
2424a2522,2542
> 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);
>
2426c2544
< * We either have a broken name server or a huge fabric if we get here.
---
> * Leave 4 and 5 alone
2427a2546,2736
> 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);
> }
>
> /*
> * 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);
2430a2740
> #endif
2436c2746
< u_int8_t local[SNS_RFT_REQ_SIZE];
---
> u_int8_t local[SNS_RFT_ID_REQ_SIZE];
2440,2441c2750,2751
< 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;
2447c2757
< reqp->snscb_data[0] = SNS_RFT;
---
> reqp->snscb_data[0] = SNS_RFT_ID;
2450c2760
< reqp->snscb_data[6] = 0x100; /* SCS - FCP */
---
> reqp->snscb_data[6] = (1 << FC4_SCSI);
2452c2762
< reqp->snscb_data[6] |= 20; /* ISO/IEC 8802-2 LLC/SNAP */
---
> reqp->snscb_data[6] |= (1 << FC4_IP); /* ISO/IEC 8802-2 LLC/SNAP */
2457c2767
< mbs.param[1] = SNS_RFT_REQ_SIZE >> 1;
---
> mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1;
2655c2965
< if (isp_scan_fabric(isp)) {
---
> if (isp_scan_fabric(isp, FC4_SCSI)) {
2954c3264,3265
< return (isp_scan_fabric(isp));
---
> int ftype = (arg)? *((int *) arg) : FC4_SCSI;
> return (isp_scan_fabric(isp, ftype));