xref: /openbmc/linux/drivers/scsi/qla2xxx/qla_gs.c (revision ee8a99bd)
1 /*
2  * QLogic Fibre Channel HBA Driver
3  * Copyright (c)  2003-2013 QLogic Corporation
4  *
5  * See LICENSE.qla2xxx for copyright and licensing details.
6  */
7 #include "qla_def.h"
8 #include "qla_target.h"
9 
10 static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
11 static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
12 static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
13 static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
14 static int qla2x00_sns_rft_id(scsi_qla_host_t *);
15 static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
16 
17 /**
18  * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
19  * @ha: HA context
20  * @req_size: request size in bytes
21  * @rsp_size: response size in bytes
22  *
23  * Returns a pointer to the @ha's ms_iocb.
24  */
25 void *
26 qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
27 {
28 	struct qla_hw_data *ha = vha->hw;
29 	ms_iocb_entry_t *ms_pkt;
30 
31 	ms_pkt = ha->ms_iocb;
32 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
33 
34 	ms_pkt->entry_type = MS_IOCB_TYPE;
35 	ms_pkt->entry_count = 1;
36 	SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
37 	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
38 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
39 	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
40 	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
41 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
42 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
43 
44 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
45 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
46 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
47 
48 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
49 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
50 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
51 
52 	return (ms_pkt);
53 }
54 
55 /**
56  * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.
57  * @ha: HA context
58  * @req_size: request size in bytes
59  * @rsp_size: response size in bytes
60  *
61  * Returns a pointer to the @ha's ms_iocb.
62  */
63 void *
64 qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
65 {
66 	struct qla_hw_data *ha = vha->hw;
67 	struct ct_entry_24xx *ct_pkt;
68 
69 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
70 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
71 
72 	ct_pkt->entry_type = CT_IOCB_TYPE;
73 	ct_pkt->entry_count = 1;
74 	ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS);
75 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
76 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
77 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
78 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
79 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
80 
81 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
82 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
83 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
84 
85 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
86 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
87 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
88 	ct_pkt->vp_index = vha->vp_idx;
89 
90 	return (ct_pkt);
91 }
92 
93 /**
94  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
95  * @ct_req: CT request buffer
96  * @cmd: GS command
97  * @rsp_size: response size in bytes
98  *
99  * Returns a pointer to the intitialized @ct_req.
100  */
101 static inline struct ct_sns_req *
102 qla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size)
103 {
104 	memset(p, 0, sizeof(struct ct_sns_pkt));
105 
106 	p->p.req.header.revision = 0x01;
107 	p->p.req.header.gs_type = 0xFC;
108 	p->p.req.header.gs_subtype = 0x02;
109 	p->p.req.command = cpu_to_be16(cmd);
110 	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
111 
112 	return &p->p.req;
113 }
114 
115 static int
116 qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
117     struct ct_sns_rsp *ct_rsp, const char *routine)
118 {
119 	int rval;
120 	uint16_t comp_status;
121 	struct qla_hw_data *ha = vha->hw;
122 
123 	rval = QLA_FUNCTION_FAILED;
124 	if (ms_pkt->entry_status != 0) {
125 		ql_dbg(ql_dbg_disc, vha, 0x2031,
126 		    "%s failed, error status (%x) on port_id: %02x%02x%02x.\n",
127 		    routine, ms_pkt->entry_status, vha->d_id.b.domain,
128 		    vha->d_id.b.area, vha->d_id.b.al_pa);
129 	} else {
130 		if (IS_FWI2_CAPABLE(ha))
131 			comp_status = le16_to_cpu(
132 			    ((struct ct_entry_24xx *)ms_pkt)->comp_status);
133 		else
134 			comp_status = le16_to_cpu(ms_pkt->status);
135 		switch (comp_status) {
136 		case CS_COMPLETE:
137 		case CS_DATA_UNDERRUN:
138 		case CS_DATA_OVERRUN:		/* Overrun? */
139 			if (ct_rsp->header.response !=
140 			    __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
141 				ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2077,
142 				    "%s failed rejected request on port_id: "
143 				    "%02x%02x%02x.\n", routine,
144 				    vha->d_id.b.domain, vha->d_id.b.area,
145 				    vha->d_id.b.al_pa);
146 				ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
147 				    0x2078, (uint8_t *)&ct_rsp->header,
148 				    sizeof(struct ct_rsp_hdr));
149 				rval = QLA_INVALID_COMMAND;
150 			} else
151 				rval = QLA_SUCCESS;
152 			break;
153 		default:
154 			ql_dbg(ql_dbg_disc, vha, 0x2033,
155 			    "%s failed, completion status (%x) on port_id: "
156 			    "%02x%02x%02x.\n", routine, comp_status,
157 			    vha->d_id.b.domain, vha->d_id.b.area,
158 			    vha->d_id.b.al_pa);
159 			break;
160 		}
161 	}
162 	return rval;
163 }
164 
165 /**
166  * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
167  * @ha: HA context
168  * @fcport: fcport entry to updated
169  *
170  * Returns 0 on success.
171  */
172 int
173 qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
174 {
175 	int		rval;
176 
177 	ms_iocb_entry_t	*ms_pkt;
178 	struct ct_sns_req	*ct_req;
179 	struct ct_sns_rsp	*ct_rsp;
180 	struct qla_hw_data *ha = vha->hw;
181 
182 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
183 		return qla2x00_sns_ga_nxt(vha, fcport);
184 
185 	/* Issue GA_NXT */
186 	/* Prepare common MS IOCB */
187 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GA_NXT_REQ_SIZE,
188 	    GA_NXT_RSP_SIZE);
189 
190 	/* Prepare CT request */
191 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
192 	    GA_NXT_RSP_SIZE);
193 	ct_rsp = &ha->ct_sns->p.rsp;
194 
195 	/* Prepare CT arguments -- port_id */
196 	ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
197 	ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
198 	ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
199 
200 	/* Execute MS IOCB */
201 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
202 	    sizeof(ms_iocb_entry_t));
203 	if (rval != QLA_SUCCESS) {
204 		/*EMPTY*/
205 		ql_dbg(ql_dbg_disc, vha, 0x2062,
206 		    "GA_NXT issue IOCB failed (%d).\n", rval);
207 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GA_NXT") !=
208 	    QLA_SUCCESS) {
209 		rval = QLA_FUNCTION_FAILED;
210 	} else {
211 		/* Populate fc_port_t entry. */
212 		fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];
213 		fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];
214 		fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];
215 
216 		memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
217 		    WWN_SIZE);
218 		memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
219 		    WWN_SIZE);
220 
221 		fcport->fc4_type = (ct_rsp->rsp.ga_nxt.fc4_types[2] & BIT_0) ?
222 		    FC4_TYPE_FCP_SCSI : FC4_TYPE_OTHER;
223 
224 		if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
225 		    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
226 			fcport->d_id.b.domain = 0xf0;
227 
228 		ql_dbg(ql_dbg_disc, vha, 0x2063,
229 		    "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
230 		    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
231 		    "port_id=%02x%02x%02x.\n",
232 		    fcport->node_name[0], fcport->node_name[1],
233 		    fcport->node_name[2], fcport->node_name[3],
234 		    fcport->node_name[4], fcport->node_name[5],
235 		    fcport->node_name[6], fcport->node_name[7],
236 		    fcport->port_name[0], fcport->port_name[1],
237 		    fcport->port_name[2], fcport->port_name[3],
238 		    fcport->port_name[4], fcport->port_name[5],
239 		    fcport->port_name[6], fcport->port_name[7],
240 		    fcport->d_id.b.domain, fcport->d_id.b.area,
241 		    fcport->d_id.b.al_pa);
242 	}
243 
244 	return (rval);
245 }
246 
247 static inline int
248 qla2x00_gid_pt_rsp_size(scsi_qla_host_t *vha)
249 {
250 	return vha->hw->max_fibre_devices * 4 + 16;
251 }
252 
253 /**
254  * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command.
255  * @ha: HA context
256  * @list: switch info entries to populate
257  *
258  * NOTE: Non-Nx_Ports are not requested.
259  *
260  * Returns 0 on success.
261  */
262 int
263 qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
264 {
265 	int		rval;
266 	uint16_t	i;
267 
268 	ms_iocb_entry_t	*ms_pkt;
269 	struct ct_sns_req	*ct_req;
270 	struct ct_sns_rsp	*ct_rsp;
271 
272 	struct ct_sns_gid_pt_data *gid_data;
273 	struct qla_hw_data *ha = vha->hw;
274 	uint16_t gid_pt_rsp_size;
275 
276 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
277 		return qla2x00_sns_gid_pt(vha, list);
278 
279 	gid_data = NULL;
280 	gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
281 	/* Issue GID_PT */
282 	/* Prepare common MS IOCB */
283 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GID_PT_REQ_SIZE,
284 	    gid_pt_rsp_size);
285 
286 	/* Prepare CT request */
287 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
288 	ct_rsp = &ha->ct_sns->p.rsp;
289 
290 	/* Prepare CT arguments -- port_type */
291 	ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;
292 
293 	/* Execute MS IOCB */
294 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
295 	    sizeof(ms_iocb_entry_t));
296 	if (rval != QLA_SUCCESS) {
297 		/*EMPTY*/
298 		ql_dbg(ql_dbg_disc, vha, 0x2055,
299 		    "GID_PT issue IOCB failed (%d).\n", rval);
300 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=
301 	    QLA_SUCCESS) {
302 		rval = QLA_FUNCTION_FAILED;
303 	} else {
304 		/* Set port IDs in switch info list. */
305 		for (i = 0; i < ha->max_fibre_devices; i++) {
306 			gid_data = &ct_rsp->rsp.gid_pt.entries[i];
307 			list[i].d_id.b.domain = gid_data->port_id[0];
308 			list[i].d_id.b.area = gid_data->port_id[1];
309 			list[i].d_id.b.al_pa = gid_data->port_id[2];
310 			memset(list[i].fabric_port_name, 0, WWN_SIZE);
311 			list[i].fp_speed = PORT_SPEED_UNKNOWN;
312 
313 			/* Last one exit. */
314 			if (gid_data->control_byte & BIT_7) {
315 				list[i].d_id.b.rsvd_1 = gid_data->control_byte;
316 				break;
317 			}
318 		}
319 
320 		/*
321 		 * If we've used all available slots, then the switch is
322 		 * reporting back more devices than we can handle with this
323 		 * single call.  Return a failed status, and let GA_NXT handle
324 		 * the overload.
325 		 */
326 		if (i == ha->max_fibre_devices)
327 			rval = QLA_FUNCTION_FAILED;
328 	}
329 
330 	return (rval);
331 }
332 
333 /**
334  * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.
335  * @ha: HA context
336  * @list: switch info entries to populate
337  *
338  * Returns 0 on success.
339  */
340 int
341 qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
342 {
343 	int		rval = QLA_SUCCESS;
344 	uint16_t	i;
345 
346 	ms_iocb_entry_t	*ms_pkt;
347 	struct ct_sns_req	*ct_req;
348 	struct ct_sns_rsp	*ct_rsp;
349 	struct qla_hw_data *ha = vha->hw;
350 
351 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
352 		return qla2x00_sns_gpn_id(vha, list);
353 
354 	for (i = 0; i < ha->max_fibre_devices; i++) {
355 		/* Issue GPN_ID */
356 		/* Prepare common MS IOCB */
357 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GPN_ID_REQ_SIZE,
358 		    GPN_ID_RSP_SIZE);
359 
360 		/* Prepare CT request */
361 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
362 		    GPN_ID_RSP_SIZE);
363 		ct_rsp = &ha->ct_sns->p.rsp;
364 
365 		/* Prepare CT arguments -- port_id */
366 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
367 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
368 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
369 
370 		/* Execute MS IOCB */
371 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
372 		    sizeof(ms_iocb_entry_t));
373 		if (rval != QLA_SUCCESS) {
374 			/*EMPTY*/
375 			ql_dbg(ql_dbg_disc, vha, 0x2056,
376 			    "GPN_ID issue IOCB failed (%d).\n", rval);
377 			break;
378 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
379 		    "GPN_ID") != QLA_SUCCESS) {
380 			rval = QLA_FUNCTION_FAILED;
381 			break;
382 		} else {
383 			/* Save portname */
384 			memcpy(list[i].port_name,
385 			    ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
386 		}
387 
388 		/* Last device exit. */
389 		if (list[i].d_id.b.rsvd_1 != 0)
390 			break;
391 	}
392 
393 	return (rval);
394 }
395 
396 /**
397  * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.
398  * @ha: HA context
399  * @list: switch info entries to populate
400  *
401  * Returns 0 on success.
402  */
403 int
404 qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
405 {
406 	int		rval = QLA_SUCCESS;
407 	uint16_t	i;
408 	struct qla_hw_data *ha = vha->hw;
409 	ms_iocb_entry_t	*ms_pkt;
410 	struct ct_sns_req	*ct_req;
411 	struct ct_sns_rsp	*ct_rsp;
412 
413 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
414 		return qla2x00_sns_gnn_id(vha, list);
415 
416 	for (i = 0; i < ha->max_fibre_devices; i++) {
417 		/* Issue GNN_ID */
418 		/* Prepare common MS IOCB */
419 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GNN_ID_REQ_SIZE,
420 		    GNN_ID_RSP_SIZE);
421 
422 		/* Prepare CT request */
423 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
424 		    GNN_ID_RSP_SIZE);
425 		ct_rsp = &ha->ct_sns->p.rsp;
426 
427 		/* Prepare CT arguments -- port_id */
428 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
429 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
430 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
431 
432 		/* Execute MS IOCB */
433 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
434 		    sizeof(ms_iocb_entry_t));
435 		if (rval != QLA_SUCCESS) {
436 			/*EMPTY*/
437 			ql_dbg(ql_dbg_disc, vha, 0x2057,
438 			    "GNN_ID issue IOCB failed (%d).\n", rval);
439 			break;
440 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
441 		    "GNN_ID") != QLA_SUCCESS) {
442 			rval = QLA_FUNCTION_FAILED;
443 			break;
444 		} else {
445 			/* Save nodename */
446 			memcpy(list[i].node_name,
447 			    ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
448 
449 			ql_dbg(ql_dbg_disc, vha, 0x2058,
450 			    "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02X%02x "
451 			    "pn %02x%02x%02x%02x%02x%02x%02X%02x "
452 			    "portid=%02x%02x%02x.\n",
453 			    list[i].node_name[0], list[i].node_name[1],
454 			    list[i].node_name[2], list[i].node_name[3],
455 			    list[i].node_name[4], list[i].node_name[5],
456 			    list[i].node_name[6], list[i].node_name[7],
457 			    list[i].port_name[0], list[i].port_name[1],
458 			    list[i].port_name[2], list[i].port_name[3],
459 			    list[i].port_name[4], list[i].port_name[5],
460 			    list[i].port_name[6], list[i].port_name[7],
461 			    list[i].d_id.b.domain, list[i].d_id.b.area,
462 			    list[i].d_id.b.al_pa);
463 		}
464 
465 		/* Last device exit. */
466 		if (list[i].d_id.b.rsvd_1 != 0)
467 			break;
468 	}
469 
470 	return (rval);
471 }
472 
473 /**
474  * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
475  * @ha: HA context
476  *
477  * Returns 0 on success.
478  */
479 int
480 qla2x00_rft_id(scsi_qla_host_t *vha)
481 {
482 	int		rval;
483 	struct qla_hw_data *ha = vha->hw;
484 	ms_iocb_entry_t	*ms_pkt;
485 	struct ct_sns_req	*ct_req;
486 	struct ct_sns_rsp	*ct_rsp;
487 
488 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
489 		return qla2x00_sns_rft_id(vha);
490 
491 	/* Issue RFT_ID */
492 	/* Prepare common MS IOCB */
493 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
494 	    RFT_ID_RSP_SIZE);
495 
496 	/* Prepare CT request */
497 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
498 	    RFT_ID_RSP_SIZE);
499 	ct_rsp = &ha->ct_sns->p.rsp;
500 
501 	/* Prepare CT arguments -- port_id, FC-4 types */
502 	ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
503 	ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
504 	ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
505 
506 	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */
507 
508 	/* Execute MS IOCB */
509 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
510 	    sizeof(ms_iocb_entry_t));
511 	if (rval != QLA_SUCCESS) {
512 		/*EMPTY*/
513 		ql_dbg(ql_dbg_disc, vha, 0x2043,
514 		    "RFT_ID issue IOCB failed (%d).\n", rval);
515 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
516 	    QLA_SUCCESS) {
517 		rval = QLA_FUNCTION_FAILED;
518 	} else {
519 		ql_dbg(ql_dbg_disc, vha, 0x2044,
520 		    "RFT_ID exiting normally.\n");
521 	}
522 
523 	return (rval);
524 }
525 
526 /**
527  * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
528  * @ha: HA context
529  *
530  * Returns 0 on success.
531  */
532 int
533 qla2x00_rff_id(scsi_qla_host_t *vha)
534 {
535 	int		rval;
536 	struct qla_hw_data *ha = vha->hw;
537 	ms_iocb_entry_t	*ms_pkt;
538 	struct ct_sns_req	*ct_req;
539 	struct ct_sns_rsp	*ct_rsp;
540 
541 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
542 		ql_dbg(ql_dbg_disc, vha, 0x2046,
543 		    "RFF_ID call not supported on ISP2100/ISP2200.\n");
544 		return (QLA_SUCCESS);
545 	}
546 
547 	/* Issue RFF_ID */
548 	/* Prepare common MS IOCB */
549 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
550 	    RFF_ID_RSP_SIZE);
551 
552 	/* Prepare CT request */
553 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
554 	    RFF_ID_RSP_SIZE);
555 	ct_rsp = &ha->ct_sns->p.rsp;
556 
557 	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
558 	ct_req->req.rff_id.port_id[0] = vha->d_id.b.domain;
559 	ct_req->req.rff_id.port_id[1] = vha->d_id.b.area;
560 	ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa;
561 
562 	qlt_rff_id(vha, ct_req);
563 
564 	ct_req->req.rff_id.fc4_type = 0x08;		/* SCSI - FCP */
565 
566 	/* Execute MS IOCB */
567 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
568 	    sizeof(ms_iocb_entry_t));
569 	if (rval != QLA_SUCCESS) {
570 		/*EMPTY*/
571 		ql_dbg(ql_dbg_disc, vha, 0x2047,
572 		    "RFF_ID issue IOCB failed (%d).\n", rval);
573 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
574 	    QLA_SUCCESS) {
575 		rval = QLA_FUNCTION_FAILED;
576 	} else {
577 		ql_dbg(ql_dbg_disc, vha, 0x2048,
578 		    "RFF_ID exiting normally.\n");
579 	}
580 
581 	return (rval);
582 }
583 
584 /**
585  * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
586  * @ha: HA context
587  *
588  * Returns 0 on success.
589  */
590 int
591 qla2x00_rnn_id(scsi_qla_host_t *vha)
592 {
593 	int		rval;
594 	struct qla_hw_data *ha = vha->hw;
595 	ms_iocb_entry_t	*ms_pkt;
596 	struct ct_sns_req	*ct_req;
597 	struct ct_sns_rsp	*ct_rsp;
598 
599 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
600 		return qla2x00_sns_rnn_id(vha);
601 
602 	/* Issue RNN_ID */
603 	/* Prepare common MS IOCB */
604 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
605 	    RNN_ID_RSP_SIZE);
606 
607 	/* Prepare CT request */
608 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
609 	ct_rsp = &ha->ct_sns->p.rsp;
610 
611 	/* Prepare CT arguments -- port_id, node_name */
612 	ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
613 	ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
614 	ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
615 
616 	memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
617 
618 	/* Execute MS IOCB */
619 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
620 	    sizeof(ms_iocb_entry_t));
621 	if (rval != QLA_SUCCESS) {
622 		/*EMPTY*/
623 		ql_dbg(ql_dbg_disc, vha, 0x204d,
624 		    "RNN_ID issue IOCB failed (%d).\n", rval);
625 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
626 	    QLA_SUCCESS) {
627 		rval = QLA_FUNCTION_FAILED;
628 	} else {
629 		ql_dbg(ql_dbg_disc, vha, 0x204e,
630 		    "RNN_ID exiting normally.\n");
631 	}
632 
633 	return (rval);
634 }
635 
636 void
637 qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn)
638 {
639 	struct qla_hw_data *ha = vha->hw;
640 
641 	if (IS_QLAFX00(ha))
642 		sprintf(snn, "%s FW:v%s DVR:v%s", ha->model_number,
643 		    ha->mr.fw_version, qla2x00_version_str);
644 	else
645 		sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
646 		    ha->fw_major_version, ha->fw_minor_version,
647 		    ha->fw_subminor_version, qla2x00_version_str);
648 }
649 
650 /**
651  * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
652  * @ha: HA context
653  *
654  * Returns 0 on success.
655  */
656 int
657 qla2x00_rsnn_nn(scsi_qla_host_t *vha)
658 {
659 	int		rval;
660 	struct qla_hw_data *ha = vha->hw;
661 	ms_iocb_entry_t	*ms_pkt;
662 	struct ct_sns_req	*ct_req;
663 	struct ct_sns_rsp	*ct_rsp;
664 
665 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
666 		ql_dbg(ql_dbg_disc, vha, 0x2050,
667 		    "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
668 		return (QLA_SUCCESS);
669 	}
670 
671 	/* Issue RSNN_NN */
672 	/* Prepare common MS IOCB */
673 	/*   Request size adjusted after CT preparation */
674 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
675 
676 	/* Prepare CT request */
677 	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
678 	    RSNN_NN_RSP_SIZE);
679 	ct_rsp = &ha->ct_sns->p.rsp;
680 
681 	/* Prepare CT arguments -- node_name, symbolic node_name, size */
682 	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
683 
684 	/* Prepare the Symbolic Node Name */
685 	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name);
686 
687 	/* Calculate SNN length */
688 	ct_req->req.rsnn_nn.name_len =
689 	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
690 
691 	/* Update MS IOCB request */
692 	ms_pkt->req_bytecount =
693 	    cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
694 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
695 
696 	/* Execute MS IOCB */
697 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
698 	    sizeof(ms_iocb_entry_t));
699 	if (rval != QLA_SUCCESS) {
700 		/*EMPTY*/
701 		ql_dbg(ql_dbg_disc, vha, 0x2051,
702 		    "RSNN_NN issue IOCB failed (%d).\n", rval);
703 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
704 	    QLA_SUCCESS) {
705 		rval = QLA_FUNCTION_FAILED;
706 	} else {
707 		ql_dbg(ql_dbg_disc, vha, 0x2052,
708 		    "RSNN_NN exiting normally.\n");
709 	}
710 
711 	return (rval);
712 }
713 
714 /**
715  * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
716  * @ha: HA context
717  * @cmd: GS command
718  * @scmd_len: Subcommand length
719  * @data_size: response size in bytes
720  *
721  * Returns a pointer to the @ha's sns_cmd.
722  */
723 static inline struct sns_cmd_pkt *
724 qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
725     uint16_t data_size)
726 {
727 	uint16_t		wc;
728 	struct sns_cmd_pkt	*sns_cmd;
729 	struct qla_hw_data *ha = vha->hw;
730 
731 	sns_cmd = ha->sns_cmd;
732 	memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
733 	wc = data_size / 2;			/* Size in 16bit words. */
734 	sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
735 	sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
736 	sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
737 	sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
738 	sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
739 	wc = (data_size - 16) / 4;		/* Size in 32bit words. */
740 	sns_cmd->p.cmd.size = cpu_to_le16(wc);
741 
742 	return (sns_cmd);
743 }
744 
745 /**
746  * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
747  * @ha: HA context
748  * @fcport: fcport entry to updated
749  *
750  * This command uses the old Exectute SNS Command mailbox routine.
751  *
752  * Returns 0 on success.
753  */
754 static int
755 qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
756 {
757 	int		rval = QLA_SUCCESS;
758 	struct qla_hw_data *ha = vha->hw;
759 	struct sns_cmd_pkt	*sns_cmd;
760 
761 	/* Issue GA_NXT. */
762 	/* Prepare SNS command request. */
763 	sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
764 	    GA_NXT_SNS_DATA_SIZE);
765 
766 	/* Prepare SNS command arguments -- port_id. */
767 	sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
768 	sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
769 	sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
770 
771 	/* Execute SNS command. */
772 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
773 	    sizeof(struct sns_cmd_pkt));
774 	if (rval != QLA_SUCCESS) {
775 		/*EMPTY*/
776 		ql_dbg(ql_dbg_disc, vha, 0x205f,
777 		    "GA_NXT Send SNS failed (%d).\n", rval);
778 	} else if (sns_cmd->p.gan_data[8] != 0x80 ||
779 	    sns_cmd->p.gan_data[9] != 0x02) {
780 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,
781 		    "GA_NXT failed, rejected request ga_nxt_rsp:\n");
782 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
783 		    sns_cmd->p.gan_data, 16);
784 		rval = QLA_FUNCTION_FAILED;
785 	} else {
786 		/* Populate fc_port_t entry. */
787 		fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
788 		fcport->d_id.b.area = sns_cmd->p.gan_data[18];
789 		fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
790 
791 		memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
792 		memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
793 
794 		if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
795 		    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
796 			fcport->d_id.b.domain = 0xf0;
797 
798 		ql_dbg(ql_dbg_disc, vha, 0x2061,
799 		    "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
800 		    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
801 		    "port_id=%02x%02x%02x.\n",
802 		    fcport->node_name[0], fcport->node_name[1],
803 		    fcport->node_name[2], fcport->node_name[3],
804 		    fcport->node_name[4], fcport->node_name[5],
805 		    fcport->node_name[6], fcport->node_name[7],
806 		    fcport->port_name[0], fcport->port_name[1],
807 		    fcport->port_name[2], fcport->port_name[3],
808 		    fcport->port_name[4], fcport->port_name[5],
809 		    fcport->port_name[6], fcport->port_name[7],
810 		    fcport->d_id.b.domain, fcport->d_id.b.area,
811 		    fcport->d_id.b.al_pa);
812 	}
813 
814 	return (rval);
815 }
816 
817 /**
818  * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
819  * @ha: HA context
820  * @list: switch info entries to populate
821  *
822  * This command uses the old Exectute SNS Command mailbox routine.
823  *
824  * NOTE: Non-Nx_Ports are not requested.
825  *
826  * Returns 0 on success.
827  */
828 static int
829 qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
830 {
831 	int		rval;
832 	struct qla_hw_data *ha = vha->hw;
833 	uint16_t	i;
834 	uint8_t		*entry;
835 	struct sns_cmd_pkt	*sns_cmd;
836 	uint16_t gid_pt_sns_data_size;
837 
838 	gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);
839 
840 	/* Issue GID_PT. */
841 	/* Prepare SNS command request. */
842 	sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
843 	    gid_pt_sns_data_size);
844 
845 	/* Prepare SNS command arguments -- port_type. */
846 	sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
847 
848 	/* Execute SNS command. */
849 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
850 	    sizeof(struct sns_cmd_pkt));
851 	if (rval != QLA_SUCCESS) {
852 		/*EMPTY*/
853 		ql_dbg(ql_dbg_disc, vha, 0x206d,
854 		    "GID_PT Send SNS failed (%d).\n", rval);
855 	} else if (sns_cmd->p.gid_data[8] != 0x80 ||
856 	    sns_cmd->p.gid_data[9] != 0x02) {
857 		ql_dbg(ql_dbg_disc, vha, 0x202f,
858 		    "GID_PT failed, rejected request, gid_rsp:\n");
859 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
860 		    sns_cmd->p.gid_data, 16);
861 		rval = QLA_FUNCTION_FAILED;
862 	} else {
863 		/* Set port IDs in switch info list. */
864 		for (i = 0; i < ha->max_fibre_devices; i++) {
865 			entry = &sns_cmd->p.gid_data[(i * 4) + 16];
866 			list[i].d_id.b.domain = entry[1];
867 			list[i].d_id.b.area = entry[2];
868 			list[i].d_id.b.al_pa = entry[3];
869 
870 			/* Last one exit. */
871 			if (entry[0] & BIT_7) {
872 				list[i].d_id.b.rsvd_1 = entry[0];
873 				break;
874 			}
875 		}
876 
877 		/*
878 		 * If we've used all available slots, then the switch is
879 		 * reporting back more devices that we can handle with this
880 		 * single call.  Return a failed status, and let GA_NXT handle
881 		 * the overload.
882 		 */
883 		if (i == ha->max_fibre_devices)
884 			rval = QLA_FUNCTION_FAILED;
885 	}
886 
887 	return (rval);
888 }
889 
890 /**
891  * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
892  * @ha: HA context
893  * @list: switch info entries to populate
894  *
895  * This command uses the old Exectute SNS Command mailbox routine.
896  *
897  * Returns 0 on success.
898  */
899 static int
900 qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
901 {
902 	int		rval = QLA_SUCCESS;
903 	struct qla_hw_data *ha = vha->hw;
904 	uint16_t	i;
905 	struct sns_cmd_pkt	*sns_cmd;
906 
907 	for (i = 0; i < ha->max_fibre_devices; i++) {
908 		/* Issue GPN_ID */
909 		/* Prepare SNS command request. */
910 		sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,
911 		    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
912 
913 		/* Prepare SNS command arguments -- port_id. */
914 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
915 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
916 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
917 
918 		/* Execute SNS command. */
919 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
920 		    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
921 		if (rval != QLA_SUCCESS) {
922 			/*EMPTY*/
923 			ql_dbg(ql_dbg_disc, vha, 0x2032,
924 			    "GPN_ID Send SNS failed (%d).\n", rval);
925 		} else if (sns_cmd->p.gpn_data[8] != 0x80 ||
926 		    sns_cmd->p.gpn_data[9] != 0x02) {
927 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
928 			    "GPN_ID failed, rejected request, gpn_rsp:\n");
929 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207f,
930 			    sns_cmd->p.gpn_data, 16);
931 			rval = QLA_FUNCTION_FAILED;
932 		} else {
933 			/* Save portname */
934 			memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
935 			    WWN_SIZE);
936 		}
937 
938 		/* Last device exit. */
939 		if (list[i].d_id.b.rsvd_1 != 0)
940 			break;
941 	}
942 
943 	return (rval);
944 }
945 
946 /**
947  * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
948  * @ha: HA context
949  * @list: switch info entries to populate
950  *
951  * This command uses the old Exectute SNS Command mailbox routine.
952  *
953  * Returns 0 on success.
954  */
955 static int
956 qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
957 {
958 	int		rval = QLA_SUCCESS;
959 	struct qla_hw_data *ha = vha->hw;
960 	uint16_t	i;
961 	struct sns_cmd_pkt	*sns_cmd;
962 
963 	for (i = 0; i < ha->max_fibre_devices; i++) {
964 		/* Issue GNN_ID */
965 		/* Prepare SNS command request. */
966 		sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,
967 		    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
968 
969 		/* Prepare SNS command arguments -- port_id. */
970 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
971 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
972 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
973 
974 		/* Execute SNS command. */
975 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
976 		    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
977 		if (rval != QLA_SUCCESS) {
978 			/*EMPTY*/
979 			ql_dbg(ql_dbg_disc, vha, 0x203f,
980 			    "GNN_ID Send SNS failed (%d).\n", rval);
981 		} else if (sns_cmd->p.gnn_data[8] != 0x80 ||
982 		    sns_cmd->p.gnn_data[9] != 0x02) {
983 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
984 			    "GNN_ID failed, rejected request, gnn_rsp:\n");
985 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
986 			    sns_cmd->p.gnn_data, 16);
987 			rval = QLA_FUNCTION_FAILED;
988 		} else {
989 			/* Save nodename */
990 			memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
991 			    WWN_SIZE);
992 
993 			ql_dbg(ql_dbg_disc, vha, 0x206e,
994 			    "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
995 			    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
996 			    "port_id=%02x%02x%02x.\n",
997 			    list[i].node_name[0], list[i].node_name[1],
998 			    list[i].node_name[2], list[i].node_name[3],
999 			    list[i].node_name[4], list[i].node_name[5],
1000 			    list[i].node_name[6], list[i].node_name[7],
1001 			    list[i].port_name[0], list[i].port_name[1],
1002 			    list[i].port_name[2], list[i].port_name[3],
1003 			    list[i].port_name[4], list[i].port_name[5],
1004 			    list[i].port_name[6], list[i].port_name[7],
1005 			    list[i].d_id.b.domain, list[i].d_id.b.area,
1006 			    list[i].d_id.b.al_pa);
1007 		}
1008 
1009 		/* Last device exit. */
1010 		if (list[i].d_id.b.rsvd_1 != 0)
1011 			break;
1012 	}
1013 
1014 	return (rval);
1015 }
1016 
1017 /**
1018  * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
1019  * @ha: HA context
1020  *
1021  * This command uses the old Exectute SNS Command mailbox routine.
1022  *
1023  * Returns 0 on success.
1024  */
1025 static int
1026 qla2x00_sns_rft_id(scsi_qla_host_t *vha)
1027 {
1028 	int		rval;
1029 	struct qla_hw_data *ha = vha->hw;
1030 	struct sns_cmd_pkt	*sns_cmd;
1031 
1032 	/* Issue RFT_ID. */
1033 	/* Prepare SNS command request. */
1034 	sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
1035 	    RFT_ID_SNS_DATA_SIZE);
1036 
1037 	/* Prepare SNS command arguments -- port_id, FC-4 types */
1038 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1039 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1040 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1041 
1042 	sns_cmd->p.cmd.param[5] = 0x01;			/* FCP-3 */
1043 
1044 	/* Execute SNS command. */
1045 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
1046 	    sizeof(struct sns_cmd_pkt));
1047 	if (rval != QLA_SUCCESS) {
1048 		/*EMPTY*/
1049 		ql_dbg(ql_dbg_disc, vha, 0x2060,
1050 		    "RFT_ID Send SNS failed (%d).\n", rval);
1051 	} else if (sns_cmd->p.rft_data[8] != 0x80 ||
1052 	    sns_cmd->p.rft_data[9] != 0x02) {
1053 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
1054 		    "RFT_ID failed, rejected request rft_rsp:\n");
1055 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
1056 		    sns_cmd->p.rft_data, 16);
1057 		rval = QLA_FUNCTION_FAILED;
1058 	} else {
1059 		ql_dbg(ql_dbg_disc, vha, 0x2073,
1060 		    "RFT_ID exiting normally.\n");
1061 	}
1062 
1063 	return (rval);
1064 }
1065 
1066 /**
1067  * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
1068  * HBA.
1069  * @ha: HA context
1070  *
1071  * This command uses the old Exectute SNS Command mailbox routine.
1072  *
1073  * Returns 0 on success.
1074  */
1075 static int
1076 qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
1077 {
1078 	int		rval;
1079 	struct qla_hw_data *ha = vha->hw;
1080 	struct sns_cmd_pkt	*sns_cmd;
1081 
1082 	/* Issue RNN_ID. */
1083 	/* Prepare SNS command request. */
1084 	sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
1085 	    RNN_ID_SNS_DATA_SIZE);
1086 
1087 	/* Prepare SNS command arguments -- port_id, nodename. */
1088 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1089 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1090 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1091 
1092 	sns_cmd->p.cmd.param[4] = vha->node_name[7];
1093 	sns_cmd->p.cmd.param[5] = vha->node_name[6];
1094 	sns_cmd->p.cmd.param[6] = vha->node_name[5];
1095 	sns_cmd->p.cmd.param[7] = vha->node_name[4];
1096 	sns_cmd->p.cmd.param[8] = vha->node_name[3];
1097 	sns_cmd->p.cmd.param[9] = vha->node_name[2];
1098 	sns_cmd->p.cmd.param[10] = vha->node_name[1];
1099 	sns_cmd->p.cmd.param[11] = vha->node_name[0];
1100 
1101 	/* Execute SNS command. */
1102 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
1103 	    sizeof(struct sns_cmd_pkt));
1104 	if (rval != QLA_SUCCESS) {
1105 		/*EMPTY*/
1106 		ql_dbg(ql_dbg_disc, vha, 0x204a,
1107 		    "RNN_ID Send SNS failed (%d).\n", rval);
1108 	} else if (sns_cmd->p.rnn_data[8] != 0x80 ||
1109 	    sns_cmd->p.rnn_data[9] != 0x02) {
1110 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
1111 		    "RNN_ID failed, rejected request, rnn_rsp:\n");
1112 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
1113 		    sns_cmd->p.rnn_data, 16);
1114 		rval = QLA_FUNCTION_FAILED;
1115 	} else {
1116 		ql_dbg(ql_dbg_disc, vha, 0x204c,
1117 		    "RNN_ID exiting normally.\n");
1118 	}
1119 
1120 	return (rval);
1121 }
1122 
1123 /**
1124  * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
1125  * @ha: HA context
1126  *
1127  * Returns 0 on success.
1128  */
1129 static int
1130 qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
1131 {
1132 	int ret, rval;
1133 	uint16_t mb[MAILBOX_REGISTER_COUNT];
1134 	struct qla_hw_data *ha = vha->hw;
1135 	ret = QLA_SUCCESS;
1136 	if (vha->flags.management_server_logged_in)
1137 		return ret;
1138 
1139 	rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,
1140 	    0xfa, mb, BIT_1);
1141 	if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
1142 		if (rval == QLA_MEMORY_ALLOC_FAILED)
1143 			ql_dbg(ql_dbg_disc, vha, 0x2085,
1144 			    "Failed management_server login: loopid=%x "
1145 			    "rval=%d\n", vha->mgmt_svr_loop_id, rval);
1146 		else
1147 			ql_dbg(ql_dbg_disc, vha, 0x2024,
1148 			    "Failed management_server login: loopid=%x "
1149 			    "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
1150 			    vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],
1151 			    mb[7]);
1152 		ret = QLA_FUNCTION_FAILED;
1153 	} else
1154 		vha->flags.management_server_logged_in = 1;
1155 
1156 	return ret;
1157 }
1158 
1159 /**
1160  * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1161  * @ha: HA context
1162  * @req_size: request size in bytes
1163  * @rsp_size: response size in bytes
1164  *
1165  * Returns a pointer to the @ha's ms_iocb.
1166  */
1167 void *
1168 qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1169     uint32_t rsp_size)
1170 {
1171 	ms_iocb_entry_t *ms_pkt;
1172 	struct qla_hw_data *ha = vha->hw;
1173 	ms_pkt = ha->ms_iocb;
1174 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
1175 
1176 	ms_pkt->entry_type = MS_IOCB_TYPE;
1177 	ms_pkt->entry_count = 1;
1178 	SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);
1179 	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
1180 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1181 	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1182 	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
1183 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
1184 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
1185 
1186 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1187 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1188 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1189 
1190 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1191 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1192 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
1193 
1194 	return ms_pkt;
1195 }
1196 
1197 /**
1198  * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1199  * @ha: HA context
1200  * @req_size: request size in bytes
1201  * @rsp_size: response size in bytes
1202  *
1203  * Returns a pointer to the @ha's ms_iocb.
1204  */
1205 void *
1206 qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1207     uint32_t rsp_size)
1208 {
1209 	struct ct_entry_24xx *ct_pkt;
1210 	struct qla_hw_data *ha = vha->hw;
1211 
1212 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1213 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1214 
1215 	ct_pkt->entry_type = CT_IOCB_TYPE;
1216 	ct_pkt->entry_count = 1;
1217 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1218 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1219 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1220 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
1221 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1222 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1223 
1224 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1225 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1226 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1227 
1228 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1229 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1230 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1231 	ct_pkt->vp_index = vha->vp_idx;
1232 
1233 	return ct_pkt;
1234 }
1235 
1236 static inline ms_iocb_entry_t *
1237 qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
1238 {
1239 	struct qla_hw_data *ha = vha->hw;
1240 	ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
1241 	struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1242 
1243 	if (IS_FWI2_CAPABLE(ha)) {
1244 		ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1245 		ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1246 	} else {
1247 		ms_pkt->req_bytecount = cpu_to_le32(req_size);
1248 		ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1249 	}
1250 
1251 	return ms_pkt;
1252 }
1253 
1254 /**
1255  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
1256  * @ct_req: CT request buffer
1257  * @cmd: GS command
1258  * @rsp_size: response size in bytes
1259  *
1260  * Returns a pointer to the intitialized @ct_req.
1261  */
1262 static inline struct ct_sns_req *
1263 qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd,
1264     uint16_t rsp_size)
1265 {
1266 	memset(p, 0, sizeof(struct ct_sns_pkt));
1267 
1268 	p->p.req.header.revision = 0x01;
1269 	p->p.req.header.gs_type = 0xFA;
1270 	p->p.req.header.gs_subtype = 0x10;
1271 	p->p.req.command = cpu_to_be16(cmd);
1272 	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1273 
1274 	return &p->p.req;
1275 }
1276 
1277 /**
1278  * qla2x00_fdmi_rhba() -
1279  * @ha: HA context
1280  *
1281  * Returns 0 on success.
1282  */
1283 static int
1284 qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
1285 {
1286 	int rval, alen;
1287 	uint32_t size, sn;
1288 
1289 	ms_iocb_entry_t *ms_pkt;
1290 	struct ct_sns_req *ct_req;
1291 	struct ct_sns_rsp *ct_rsp;
1292 	uint8_t *entries;
1293 	struct ct_fdmi_hba_attr *eiter;
1294 	struct qla_hw_data *ha = vha->hw;
1295 
1296 	/* Issue RHBA */
1297 	/* Prepare common MS IOCB */
1298 	/*   Request size adjusted after CT preparation */
1299 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1300 
1301 	/* Prepare CT request */
1302 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE);
1303 	ct_rsp = &ha->ct_sns->p.rsp;
1304 
1305 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1306 	memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE);
1307 	ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1);
1308 	memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE);
1309 	size = 2 * WWN_SIZE + 4 + 4;
1310 
1311 	/* Attributes */
1312 	ct_req->req.rhba.attrs.count =
1313 	    __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT);
1314 	entries = ct_req->req.rhba.hba_identifier;
1315 
1316 	/* Nodename. */
1317 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1318 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME);
1319 	eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE);
1320 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1321 	size += 4 + WWN_SIZE;
1322 
1323 	ql_dbg(ql_dbg_disc, vha, 0x2025,
1324 	    "NodeName = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
1325 	    eiter->a.node_name[0], eiter->a.node_name[1],
1326 	    eiter->a.node_name[2], eiter->a.node_name[3],
1327 	    eiter->a.node_name[4], eiter->a.node_name[5],
1328 	    eiter->a.node_name[6], eiter->a.node_name[7]);
1329 
1330 	/* Manufacturer. */
1331 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1332 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
1333 	alen = strlen(QLA2XXX_MANUFACTURER);
1334 	strncpy(eiter->a.manufacturer, QLA2XXX_MANUFACTURER, alen + 1);
1335 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1336 	eiter->len = cpu_to_be16(4 + alen);
1337 	size += 4 + alen;
1338 
1339 	ql_dbg(ql_dbg_disc, vha, 0x2026,
1340 	    "Manufacturer = %s.\n", eiter->a.manufacturer);
1341 
1342 	/* Serial number. */
1343 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1344 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1345 	sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
1346 	sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000);
1347 	alen = strlen(eiter->a.serial_num);
1348 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1349 	eiter->len = cpu_to_be16(4 + alen);
1350 	size += 4 + alen;
1351 
1352 	ql_dbg(ql_dbg_disc, vha, 0x2027,
1353 	    "Serial no. = %s.\n", eiter->a.serial_num);
1354 
1355 	/* Model name. */
1356 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1357 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL);
1358 	strcpy(eiter->a.model, ha->model_number);
1359 	alen = strlen(eiter->a.model);
1360 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1361 	eiter->len = cpu_to_be16(4 + alen);
1362 	size += 4 + alen;
1363 
1364 	ql_dbg(ql_dbg_disc, vha, 0x2028,
1365 	    "Model Name = %s.\n", eiter->a.model);
1366 
1367 	/* Model description. */
1368 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1369 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1370 	strncpy(eiter->a.model_desc, ha->model_desc, 80);
1371 	alen = strlen(eiter->a.model_desc);
1372 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1373 	eiter->len = cpu_to_be16(4 + alen);
1374 	size += 4 + alen;
1375 
1376 	ql_dbg(ql_dbg_disc, vha, 0x2029,
1377 	    "Model Desc = %s.\n", eiter->a.model_desc);
1378 
1379 	/* Hardware version. */
1380 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1381 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1382 	strcpy(eiter->a.hw_version, ha->adapter_id);
1383 	alen = strlen(eiter->a.hw_version);
1384 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1385 	eiter->len = cpu_to_be16(4 + alen);
1386 	size += 4 + alen;
1387 
1388 	ql_dbg(ql_dbg_disc, vha, 0x202a,
1389 	    "Hardware ver = %s.\n", eiter->a.hw_version);
1390 
1391 	/* Driver version. */
1392 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1393 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1394 	strcpy(eiter->a.driver_version, qla2x00_version_str);
1395 	alen = strlen(eiter->a.driver_version);
1396 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1397 	eiter->len = cpu_to_be16(4 + alen);
1398 	size += 4 + alen;
1399 
1400 	ql_dbg(ql_dbg_disc, vha, 0x202b,
1401 	    "Driver ver = %s.\n", eiter->a.driver_version);
1402 
1403 	/* Option ROM version. */
1404 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1405 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1406 	strcpy(eiter->a.orom_version, "0.00");
1407 	alen = strlen(eiter->a.orom_version);
1408 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1409 	eiter->len = cpu_to_be16(4 + alen);
1410 	size += 4 + alen;
1411 
1412 	ql_dbg(ql_dbg_disc, vha , 0x202c,
1413 	    "Optrom vers = %s.\n", eiter->a.orom_version);
1414 
1415 	/* Firmware version */
1416 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1417 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1418 	ha->isp_ops->fw_version_str(vha, eiter->a.fw_version);
1419 	alen = strlen(eiter->a.fw_version);
1420 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1421 	eiter->len = cpu_to_be16(4 + alen);
1422 	size += 4 + alen;
1423 
1424 	ql_dbg(ql_dbg_disc, vha, 0x202d,
1425 	    "Firmware vers = %s.\n", eiter->a.fw_version);
1426 
1427 	/* Update MS request size. */
1428 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1429 
1430 	ql_dbg(ql_dbg_disc, vha, 0x202e,
1431 	    "RHBA identifier = "
1432 	    "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n",
1433 	    ct_req->req.rhba.hba_identifier[0],
1434 	    ct_req->req.rhba.hba_identifier[1],
1435 	    ct_req->req.rhba.hba_identifier[2],
1436 	    ct_req->req.rhba.hba_identifier[3],
1437 	    ct_req->req.rhba.hba_identifier[4],
1438 	    ct_req->req.rhba.hba_identifier[5],
1439 	    ct_req->req.rhba.hba_identifier[6],
1440 	    ct_req->req.rhba.hba_identifier[7], size);
1441 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
1442 	    entries, size);
1443 
1444 	/* Execute MS IOCB */
1445 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1446 	    sizeof(ms_iocb_entry_t));
1447 	if (rval != QLA_SUCCESS) {
1448 		/*EMPTY*/
1449 		ql_dbg(ql_dbg_disc, vha, 0x2030,
1450 		    "RHBA issue IOCB failed (%d).\n", rval);
1451 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
1452 	    QLA_SUCCESS) {
1453 		rval = QLA_FUNCTION_FAILED;
1454 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1455 		    ct_rsp->header.explanation_code ==
1456 		    CT_EXPL_ALREADY_REGISTERED) {
1457 			ql_dbg(ql_dbg_disc, vha, 0x2034,
1458 			    "HBA already registered.\n");
1459 			rval = QLA_ALREADY_REGISTERED;
1460 		}
1461 	} else {
1462 		ql_dbg(ql_dbg_disc, vha, 0x2035,
1463 		    "RHBA exiting normally.\n");
1464 	}
1465 
1466 	return rval;
1467 }
1468 
1469 /**
1470  * qla2x00_fdmi_dhba() -
1471  * @ha: HA context
1472  *
1473  * Returns 0 on success.
1474  */
1475 static int
1476 qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
1477 {
1478 	int rval;
1479 	struct qla_hw_data *ha = vha->hw;
1480 	ms_iocb_entry_t *ms_pkt;
1481 	struct ct_sns_req *ct_req;
1482 	struct ct_sns_rsp *ct_rsp;
1483 
1484 	/* Issue RPA */
1485 	/* Prepare common MS IOCB */
1486 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
1487 	    DHBA_RSP_SIZE);
1488 
1489 	/* Prepare CT request */
1490 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE);
1491 	ct_rsp = &ha->ct_sns->p.rsp;
1492 
1493 	/* Prepare FDMI command arguments -- portname. */
1494 	memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
1495 
1496 	ql_dbg(ql_dbg_disc, vha, 0x2036,
1497 	    "DHBA portname = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
1498 	    ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1],
1499 	    ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3],
1500 	    ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5],
1501 	    ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]);
1502 
1503 	/* Execute MS IOCB */
1504 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1505 	    sizeof(ms_iocb_entry_t));
1506 	if (rval != QLA_SUCCESS) {
1507 		/*EMPTY*/
1508 		ql_dbg(ql_dbg_disc, vha, 0x2037,
1509 		    "DHBA issue IOCB failed (%d).\n", rval);
1510 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
1511 	    QLA_SUCCESS) {
1512 		rval = QLA_FUNCTION_FAILED;
1513 	} else {
1514 		ql_dbg(ql_dbg_disc, vha, 0x2038,
1515 		    "DHBA exiting normally.\n");
1516 	}
1517 
1518 	return rval;
1519 }
1520 
1521 /**
1522  * qla2x00_fdmi_rpa() -
1523  * @ha: HA context
1524  *
1525  * Returns 0 on success.
1526  */
1527 static int
1528 qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
1529 {
1530 	int rval, alen;
1531 	uint32_t size, max_frame_size;
1532 	struct qla_hw_data *ha = vha->hw;
1533 	ms_iocb_entry_t *ms_pkt;
1534 	struct ct_sns_req *ct_req;
1535 	struct ct_sns_rsp *ct_rsp;
1536 	uint8_t *entries;
1537 	struct ct_fdmi_port_attr *eiter;
1538 	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1539 
1540 	/* Issue RPA */
1541 	/* Prepare common MS IOCB */
1542 	/*   Request size adjusted after CT preparation */
1543 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
1544 
1545 	/* Prepare CT request */
1546 	ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE);
1547 	ct_rsp = &ha->ct_sns->p.rsp;
1548 
1549 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1550 	memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
1551 	size = WWN_SIZE + 4;
1552 
1553 	/* Attributes */
1554 	ct_req->req.rpa.attrs.count =
1555 	    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT - 1);
1556 	entries = ct_req->req.rpa.port_name;
1557 
1558 	/* FC4 types. */
1559 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1560 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES);
1561 	eiter->len = __constant_cpu_to_be16(4 + 32);
1562 	eiter->a.fc4_types[2] = 0x01;
1563 	size += 4 + 32;
1564 
1565 	ql_dbg(ql_dbg_disc, vha, 0x2039,
1566 	    "FC4_TYPES=%02x %02x.\n",
1567 	    eiter->a.fc4_types[2],
1568 	    eiter->a.fc4_types[1]);
1569 
1570 	/* Supported speed. */
1571 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1572 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
1573 	eiter->len = __constant_cpu_to_be16(4 + 4);
1574 	if (IS_CNA_CAPABLE(ha))
1575 		eiter->a.sup_speed = __constant_cpu_to_be32(
1576 		    FDMI_PORT_SPEED_10GB);
1577 	else if (IS_QLA25XX(ha))
1578 		eiter->a.sup_speed = __constant_cpu_to_be32(
1579 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1580 		    FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
1581 	else if (IS_QLA24XX_TYPE(ha))
1582 		eiter->a.sup_speed = __constant_cpu_to_be32(
1583 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1584 		    FDMI_PORT_SPEED_4GB);
1585 	else if (IS_QLA23XX(ha))
1586 		eiter->a.sup_speed =__constant_cpu_to_be32(
1587 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB);
1588 	else
1589 		eiter->a.sup_speed = __constant_cpu_to_be32(
1590 		    FDMI_PORT_SPEED_1GB);
1591 	size += 4 + 4;
1592 
1593 	ql_dbg(ql_dbg_disc, vha, 0x203a,
1594 	    "Supported_Speed=%x.\n", eiter->a.sup_speed);
1595 
1596 	/* Current speed. */
1597 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1598 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
1599 	eiter->len = __constant_cpu_to_be16(4 + 4);
1600 	switch (ha->link_data_rate) {
1601 	case PORT_SPEED_1GB:
1602 		eiter->a.cur_speed =
1603 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_1GB);
1604 		break;
1605 	case PORT_SPEED_2GB:
1606 		eiter->a.cur_speed =
1607 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_2GB);
1608 		break;
1609 	case PORT_SPEED_4GB:
1610 		eiter->a.cur_speed =
1611 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_4GB);
1612 		break;
1613 	case PORT_SPEED_8GB:
1614 		eiter->a.cur_speed =
1615 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_8GB);
1616 		break;
1617 	case PORT_SPEED_10GB:
1618 		eiter->a.cur_speed =
1619 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_10GB);
1620 		break;
1621 	case PORT_SPEED_16GB:
1622 		eiter->a.cur_speed =
1623 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_16GB);
1624 		break;
1625 	default:
1626 		eiter->a.cur_speed =
1627 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
1628 		break;
1629 	}
1630 	size += 4 + 4;
1631 
1632 	ql_dbg(ql_dbg_disc, vha, 0x203b,
1633 	    "Current_Speed=%x.\n", eiter->a.cur_speed);
1634 
1635 	/* Max frame size. */
1636 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1637 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
1638 	eiter->len = __constant_cpu_to_be16(4 + 4);
1639 	max_frame_size = IS_FWI2_CAPABLE(ha) ?
1640 	    le16_to_cpu(icb24->frame_payload_size):
1641 	    le16_to_cpu(ha->init_cb->frame_payload_size);
1642 	eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
1643 	size += 4 + 4;
1644 
1645 	ql_dbg(ql_dbg_disc, vha, 0x203c,
1646 	    "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
1647 
1648 	/* OS device name. */
1649 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1650 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
1651 	alen = strlen(QLA2XXX_DRIVER_NAME);
1652 	strncpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME, alen + 1);
1653 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1654 	eiter->len = cpu_to_be16(4 + alen);
1655 	size += 4 + alen;
1656 
1657 	ql_dbg(ql_dbg_disc, vha, 0x204b,
1658 	    "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
1659 
1660 	/* Hostname. */
1661 	if (strlen(fc_host_system_hostname(vha->host))) {
1662 		ct_req->req.rpa.attrs.count =
1663 		    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
1664 		eiter = (struct ct_fdmi_port_attr *) (entries + size);
1665 		eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME);
1666 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1667 		    "%s", fc_host_system_hostname(vha->host));
1668 		alen = strlen(eiter->a.host_name);
1669 		alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1670 		eiter->len = cpu_to_be16(4 + alen);
1671 		size += 4 + alen;
1672 
1673 		ql_dbg(ql_dbg_disc, vha, 0x203d,
1674 		    "HostName=%s.\n", eiter->a.host_name);
1675 	}
1676 
1677 	/* Update MS request size. */
1678 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1679 
1680 	ql_dbg(ql_dbg_disc, vha, 0x203e,
1681 	    "RPA portname= %02x%02x%02x%02x%02X%02x%02x%02x size=%d.\n",
1682 	    ct_req->req.rpa.port_name[0], ct_req->req.rpa.port_name[1],
1683 	    ct_req->req.rpa.port_name[2], ct_req->req.rpa.port_name[3],
1684 	    ct_req->req.rpa.port_name[4], ct_req->req.rpa.port_name[5],
1685 	    ct_req->req.rpa.port_name[6], ct_req->req.rpa.port_name[7],
1686 	    size);
1687 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
1688 	    entries, size);
1689 
1690 	/* Execute MS IOCB */
1691 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1692 	    sizeof(ms_iocb_entry_t));
1693 	if (rval != QLA_SUCCESS) {
1694 		/*EMPTY*/
1695 		ql_dbg(ql_dbg_disc, vha, 0x2040,
1696 		    "RPA issue IOCB failed (%d).\n", rval);
1697 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
1698 	    QLA_SUCCESS) {
1699 		rval = QLA_FUNCTION_FAILED;
1700 	} else {
1701 		ql_dbg(ql_dbg_disc, vha, 0x2041,
1702 		    "RPA exiting nornally.\n");
1703 	}
1704 
1705 	return rval;
1706 }
1707 
1708 /**
1709  * qla2x00_fdmi_register() -
1710  * @ha: HA context
1711  *
1712  * Returns 0 on success.
1713  */
1714 int
1715 qla2x00_fdmi_register(scsi_qla_host_t *vha)
1716 {
1717 	int rval;
1718        struct qla_hw_data *ha = vha->hw;
1719 
1720 	if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
1721 	    IS_QLAFX00(ha))
1722 		return QLA_FUNCTION_FAILED;
1723 
1724 	rval = qla2x00_mgmt_svr_login(vha);
1725 	if (rval)
1726 		return rval;
1727 
1728 	rval = qla2x00_fdmi_rhba(vha);
1729 	if (rval) {
1730 		if (rval != QLA_ALREADY_REGISTERED)
1731 			return rval;
1732 
1733 		rval = qla2x00_fdmi_dhba(vha);
1734 		if (rval)
1735 			return rval;
1736 
1737 		rval = qla2x00_fdmi_rhba(vha);
1738 		if (rval)
1739 			return rval;
1740 	}
1741 	rval = qla2x00_fdmi_rpa(vha);
1742 
1743 	return rval;
1744 }
1745 
1746 /**
1747  * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.
1748  * @ha: HA context
1749  * @list: switch info entries to populate
1750  *
1751  * Returns 0 on success.
1752  */
1753 int
1754 qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
1755 {
1756 	int		rval = QLA_SUCCESS;
1757 	uint16_t	i;
1758 	struct qla_hw_data *ha = vha->hw;
1759 	ms_iocb_entry_t	*ms_pkt;
1760 	struct ct_sns_req	*ct_req;
1761 	struct ct_sns_rsp	*ct_rsp;
1762 
1763 	if (!IS_IIDMA_CAPABLE(ha))
1764 		return QLA_FUNCTION_FAILED;
1765 
1766 	for (i = 0; i < ha->max_fibre_devices; i++) {
1767 		/* Issue GFPN_ID */
1768 		/* Prepare common MS IOCB */
1769 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
1770 		    GFPN_ID_RSP_SIZE);
1771 
1772 		/* Prepare CT request */
1773 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
1774 		    GFPN_ID_RSP_SIZE);
1775 		ct_rsp = &ha->ct_sns->p.rsp;
1776 
1777 		/* Prepare CT arguments -- port_id */
1778 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
1779 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
1780 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
1781 
1782 		/* Execute MS IOCB */
1783 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1784 		    sizeof(ms_iocb_entry_t));
1785 		if (rval != QLA_SUCCESS) {
1786 			/*EMPTY*/
1787 			ql_dbg(ql_dbg_disc, vha, 0x2023,
1788 			    "GFPN_ID issue IOCB failed (%d).\n", rval);
1789 			break;
1790 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
1791 		    "GFPN_ID") != QLA_SUCCESS) {
1792 			rval = QLA_FUNCTION_FAILED;
1793 			break;
1794 		} else {
1795 			/* Save fabric portname */
1796 			memcpy(list[i].fabric_port_name,
1797 			    ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);
1798 		}
1799 
1800 		/* Last device exit. */
1801 		if (list[i].d_id.b.rsvd_1 != 0)
1802 			break;
1803 	}
1804 
1805 	return (rval);
1806 }
1807 
1808 static inline void *
1809 qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1810     uint32_t rsp_size)
1811 {
1812 	struct ct_entry_24xx *ct_pkt;
1813 	struct qla_hw_data *ha = vha->hw;
1814 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1815 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1816 
1817 	ct_pkt->entry_type = CT_IOCB_TYPE;
1818 	ct_pkt->entry_count = 1;
1819 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1820 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1821 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1822 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
1823 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1824 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1825 
1826 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1827 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1828 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1829 
1830 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1831 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1832 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1833 	ct_pkt->vp_index = vha->vp_idx;
1834 
1835 	return ct_pkt;
1836 }
1837 
1838 
1839 static inline struct ct_sns_req *
1840 qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
1841     uint16_t rsp_size)
1842 {
1843 	memset(p, 0, sizeof(struct ct_sns_pkt));
1844 
1845 	p->p.req.header.revision = 0x01;
1846 	p->p.req.header.gs_type = 0xFA;
1847 	p->p.req.header.gs_subtype = 0x01;
1848 	p->p.req.command = cpu_to_be16(cmd);
1849 	p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1850 
1851 	return &p->p.req;
1852 }
1853 
1854 /**
1855  * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
1856  * @ha: HA context
1857  * @list: switch info entries to populate
1858  *
1859  * Returns 0 on success.
1860  */
1861 int
1862 qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
1863 {
1864 	int		rval;
1865 	uint16_t	i;
1866 	struct qla_hw_data *ha = vha->hw;
1867 	ms_iocb_entry_t	*ms_pkt;
1868 	struct ct_sns_req	*ct_req;
1869 	struct ct_sns_rsp	*ct_rsp;
1870 
1871 	if (!IS_IIDMA_CAPABLE(ha))
1872 		return QLA_FUNCTION_FAILED;
1873 	if (!ha->flags.gpsc_supported)
1874 		return QLA_FUNCTION_FAILED;
1875 
1876 	rval = qla2x00_mgmt_svr_login(vha);
1877 	if (rval)
1878 		return rval;
1879 
1880 	for (i = 0; i < ha->max_fibre_devices; i++) {
1881 		/* Issue GFPN_ID */
1882 		/* Prepare common MS IOCB */
1883 		ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
1884 		    GPSC_RSP_SIZE);
1885 
1886 		/* Prepare CT request */
1887 		ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
1888 		    GPSC_RSP_SIZE);
1889 		ct_rsp = &ha->ct_sns->p.rsp;
1890 
1891 		/* Prepare CT arguments -- port_name */
1892 		memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,
1893 		    WWN_SIZE);
1894 
1895 		/* Execute MS IOCB */
1896 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1897 		    sizeof(ms_iocb_entry_t));
1898 		if (rval != QLA_SUCCESS) {
1899 			/*EMPTY*/
1900 			ql_dbg(ql_dbg_disc, vha, 0x2059,
1901 			    "GPSC issue IOCB failed (%d).\n", rval);
1902 		} else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
1903 		    "GPSC")) != QLA_SUCCESS) {
1904 			/* FM command unsupported? */
1905 			if (rval == QLA_INVALID_COMMAND &&
1906 			    (ct_rsp->header.reason_code ==
1907 				CT_REASON_INVALID_COMMAND_CODE ||
1908 			     ct_rsp->header.reason_code ==
1909 				CT_REASON_COMMAND_UNSUPPORTED)) {
1910 				ql_dbg(ql_dbg_disc, vha, 0x205a,
1911 				    "GPSC command unsupported, disabling "
1912 				    "query.\n");
1913 				ha->flags.gpsc_supported = 0;
1914 				rval = QLA_FUNCTION_FAILED;
1915 				break;
1916 			}
1917 			rval = QLA_FUNCTION_FAILED;
1918 		} else {
1919 			/* Save port-speed */
1920 			switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
1921 			case BIT_15:
1922 				list[i].fp_speed = PORT_SPEED_1GB;
1923 				break;
1924 			case BIT_14:
1925 				list[i].fp_speed = PORT_SPEED_2GB;
1926 				break;
1927 			case BIT_13:
1928 				list[i].fp_speed = PORT_SPEED_4GB;
1929 				break;
1930 			case BIT_12:
1931 				list[i].fp_speed = PORT_SPEED_10GB;
1932 				break;
1933 			case BIT_11:
1934 				list[i].fp_speed = PORT_SPEED_8GB;
1935 				break;
1936 			case BIT_10:
1937 				list[i].fp_speed = PORT_SPEED_16GB;
1938 				break;
1939 			}
1940 
1941 			ql_dbg(ql_dbg_disc, vha, 0x205b,
1942 			    "GPSC ext entry - fpn "
1943 			    "%02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
1944 			    "speed=%04x.\n",
1945 			    list[i].fabric_port_name[0],
1946 			    list[i].fabric_port_name[1],
1947 			    list[i].fabric_port_name[2],
1948 			    list[i].fabric_port_name[3],
1949 			    list[i].fabric_port_name[4],
1950 			    list[i].fabric_port_name[5],
1951 			    list[i].fabric_port_name[6],
1952 			    list[i].fabric_port_name[7],
1953 			    be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
1954 			    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
1955 		}
1956 
1957 		/* Last device exit. */
1958 		if (list[i].d_id.b.rsvd_1 != 0)
1959 			break;
1960 	}
1961 
1962 	return (rval);
1963 }
1964 
1965 /**
1966  * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query.
1967  *
1968  * @ha: HA context
1969  * @list: switch info entries to populate
1970  *
1971  */
1972 void
1973 qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
1974 {
1975 	int		rval;
1976 	uint16_t	i;
1977 
1978 	ms_iocb_entry_t	*ms_pkt;
1979 	struct ct_sns_req	*ct_req;
1980 	struct ct_sns_rsp	*ct_rsp;
1981 	struct qla_hw_data *ha = vha->hw;
1982 	uint8_t fcp_scsi_features = 0;
1983 
1984 	for (i = 0; i < ha->max_fibre_devices; i++) {
1985 		/* Set default FC4 Type as UNKNOWN so the default is to
1986 		 * Process this port */
1987 		list[i].fc4_type = FC4_TYPE_UNKNOWN;
1988 
1989 		/* Do not attempt GFF_ID if we are not FWI_2 capable */
1990 		if (!IS_FWI2_CAPABLE(ha))
1991 			continue;
1992 
1993 		/* Prepare common MS IOCB */
1994 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
1995 		    GFF_ID_RSP_SIZE);
1996 
1997 		/* Prepare CT request */
1998 		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
1999 		    GFF_ID_RSP_SIZE);
2000 		ct_rsp = &ha->ct_sns->p.rsp;
2001 
2002 		/* Prepare CT arguments -- port_id */
2003 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
2004 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
2005 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
2006 
2007 		/* Execute MS IOCB */
2008 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2009 		   sizeof(ms_iocb_entry_t));
2010 
2011 		if (rval != QLA_SUCCESS) {
2012 			ql_dbg(ql_dbg_disc, vha, 0x205c,
2013 			    "GFF_ID issue IOCB failed (%d).\n", rval);
2014 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2015 			       "GFF_ID") != QLA_SUCCESS) {
2016 			ql_dbg(ql_dbg_disc, vha, 0x205d,
2017 			    "GFF_ID IOCB status had a failure status code.\n");
2018 		} else {
2019 			fcp_scsi_features =
2020 			   ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
2021 			fcp_scsi_features &= 0x0f;
2022 
2023 			if (fcp_scsi_features)
2024 				list[i].fc4_type = FC4_TYPE_FCP_SCSI;
2025 			else
2026 				list[i].fc4_type = FC4_TYPE_OTHER;
2027 		}
2028 
2029 		/* Last device exit. */
2030 		if (list[i].d_id.b.rsvd_1 != 0)
2031 			break;
2032 	}
2033 }
2034