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
This commit is contained in:
parent
635435f4f6
commit
029f13c671
@ -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_scan_fabric(struct ispsoftc *isp)
|
||||
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, 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);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
if (fcp->isp_fwstate != FW_READY ||
|
||||
fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
|
||||
FC_SCRATCH_RELEASE(isp);
|
||||
return (-1);
|
||||
}
|
||||
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) |
|
||||
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);
|
||||
fcp->isp_loopstate = LOOP_FSCAN_DONE;
|
||||
return (0);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (hicap >= 65535) {
|
||||
isp_prt(isp, ISP_LOGWARN, "fabric too big (> 65535)");
|
||||
FC_SCRATCH_RELEASE(isp);
|
||||
if (hicap >= GA_NXT_MAX) {
|
||||
isp_prt(isp, ISP_LOGWARN, "fabric too big (> %d)", GA_NXT_MAX);
|
||||
}
|
||||
|
||||
/*
|
||||
* We either have a broken name server or a huge fabric if we get here.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
@ -2734,43 +2734,13 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
|
||||
break;
|
||||
case ISPASYNC_FABRIC_DEV:
|
||||
{
|
||||
int target, lrange;
|
||||
struct lportdb *lp = NULL;
|
||||
char *pt;
|
||||
sns_ganrsp_t *resp = (sns_ganrsp_t *) arg;
|
||||
u_int32_t portid;
|
||||
u_int64_t wwpn, wwnn;
|
||||
int target, base, lim;
|
||||
fcparam *fcp = isp->isp_param;
|
||||
struct lportdb *lp = NULL;
|
||||
struct lportdb *clp = (struct lportdb *) arg;
|
||||
char *pt;
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
* We're only interested in SCSI_FCP types (for now)
|
||||
* If we don't have an initiator role we bail.
|
||||
*
|
||||
* We just use ISPASYNC_FABRIC_DEV for announcement purposes.
|
||||
*/
|
||||
if ((resp->snscb_fc4_types[2] & 1) == 0) {
|
||||
|
||||
if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
|
||||
break;
|
||||
}
|
||||
if (fcp->isp_topo != TOPO_F_PORT)
|
||||
lrange = FC_SNS_ID+1;
|
||||
|
||||
/*
|
||||
* Is this entry for us? If so, we bail.
|
||||
*/
|
||||
|
||||
if (fcp->isp_portid == clp->portid) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
{
|
||||
@ -688,14 +732,52 @@ 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],
|
||||
|
@ -240,16 +240,6 @@ static struct ispmdvec mdvec_2300 = {
|
||||
#define PCI_QLOGIC_ISP2312 \
|
||||
((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.
|
||||
*/
|
||||
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user