xref: /openbmc/linux/drivers/scsi/qla2xxx/qla_gs.c (revision 0d456bad)
1 /*
2  * QLogic Fibre Channel HBA Driver
3  * Copyright (c)  2003-2012 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_req *ct_req, uint16_t cmd, uint16_t rsp_size)
103 {
104 	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
105 
106 	ct_req->header.revision = 0x01;
107 	ct_req->header.gs_type = 0xFC;
108 	ct_req->header.gs_subtype = 0x02;
109 	ct_req->command = cpu_to_be16(cmd);
110 	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
111 
112 	return (ct_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->p.req, 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->p.req, GID_PT_CMD,
288 	    gid_pt_rsp_size);
289 	ct_rsp = &ha->ct_sns->p.rsp;
290 
291 	/* Prepare CT arguments -- port_type */
292 	ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;
293 
294 	/* Execute MS IOCB */
295 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
296 	    sizeof(ms_iocb_entry_t));
297 	if (rval != QLA_SUCCESS) {
298 		/*EMPTY*/
299 		ql_dbg(ql_dbg_disc, vha, 0x2055,
300 		    "GID_PT issue IOCB failed (%d).\n", rval);
301 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "GID_PT") !=
302 	    QLA_SUCCESS) {
303 		rval = QLA_FUNCTION_FAILED;
304 	} else {
305 		/* Set port IDs in switch info list. */
306 		for (i = 0; i < ha->max_fibre_devices; i++) {
307 			gid_data = &ct_rsp->rsp.gid_pt.entries[i];
308 			list[i].d_id.b.domain = gid_data->port_id[0];
309 			list[i].d_id.b.area = gid_data->port_id[1];
310 			list[i].d_id.b.al_pa = gid_data->port_id[2];
311 			memset(list[i].fabric_port_name, 0, WWN_SIZE);
312 			list[i].fp_speed = PORT_SPEED_UNKNOWN;
313 
314 			/* Last one exit. */
315 			if (gid_data->control_byte & BIT_7) {
316 				list[i].d_id.b.rsvd_1 = gid_data->control_byte;
317 				break;
318 			}
319 		}
320 
321 		/*
322 		 * If we've used all available slots, then the switch is
323 		 * reporting back more devices than we can handle with this
324 		 * single call.  Return a failed status, and let GA_NXT handle
325 		 * the overload.
326 		 */
327 		if (i == ha->max_fibre_devices)
328 			rval = QLA_FUNCTION_FAILED;
329 	}
330 
331 	return (rval);
332 }
333 
334 /**
335  * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.
336  * @ha: HA context
337  * @list: switch info entries to populate
338  *
339  * Returns 0 on success.
340  */
341 int
342 qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
343 {
344 	int		rval = QLA_SUCCESS;
345 	uint16_t	i;
346 
347 	ms_iocb_entry_t	*ms_pkt;
348 	struct ct_sns_req	*ct_req;
349 	struct ct_sns_rsp	*ct_rsp;
350 	struct qla_hw_data *ha = vha->hw;
351 
352 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
353 		return qla2x00_sns_gpn_id(vha, list);
354 
355 	for (i = 0; i < ha->max_fibre_devices; i++) {
356 		/* Issue GPN_ID */
357 		/* Prepare common MS IOCB */
358 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GPN_ID_REQ_SIZE,
359 		    GPN_ID_RSP_SIZE);
360 
361 		/* Prepare CT request */
362 		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GPN_ID_CMD,
363 		    GPN_ID_RSP_SIZE);
364 		ct_rsp = &ha->ct_sns->p.rsp;
365 
366 		/* Prepare CT arguments -- port_id */
367 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
368 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
369 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
370 
371 		/* Execute MS IOCB */
372 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
373 		    sizeof(ms_iocb_entry_t));
374 		if (rval != QLA_SUCCESS) {
375 			/*EMPTY*/
376 			ql_dbg(ql_dbg_disc, vha, 0x2056,
377 			    "GPN_ID issue IOCB failed (%d).\n", rval);
378 			break;
379 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
380 		    "GPN_ID") != QLA_SUCCESS) {
381 			rval = QLA_FUNCTION_FAILED;
382 			break;
383 		} else {
384 			/* Save portname */
385 			memcpy(list[i].port_name,
386 			    ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
387 		}
388 
389 		/* Last device exit. */
390 		if (list[i].d_id.b.rsvd_1 != 0)
391 			break;
392 	}
393 
394 	return (rval);
395 }
396 
397 /**
398  * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.
399  * @ha: HA context
400  * @list: switch info entries to populate
401  *
402  * Returns 0 on success.
403  */
404 int
405 qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
406 {
407 	int		rval = QLA_SUCCESS;
408 	uint16_t	i;
409 	struct qla_hw_data *ha = vha->hw;
410 	ms_iocb_entry_t	*ms_pkt;
411 	struct ct_sns_req	*ct_req;
412 	struct ct_sns_rsp	*ct_rsp;
413 
414 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
415 		return qla2x00_sns_gnn_id(vha, list);
416 
417 	for (i = 0; i < ha->max_fibre_devices; i++) {
418 		/* Issue GNN_ID */
419 		/* Prepare common MS IOCB */
420 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GNN_ID_REQ_SIZE,
421 		    GNN_ID_RSP_SIZE);
422 
423 		/* Prepare CT request */
424 		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GNN_ID_CMD,
425 		    GNN_ID_RSP_SIZE);
426 		ct_rsp = &ha->ct_sns->p.rsp;
427 
428 		/* Prepare CT arguments -- port_id */
429 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
430 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
431 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
432 
433 		/* Execute MS IOCB */
434 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
435 		    sizeof(ms_iocb_entry_t));
436 		if (rval != QLA_SUCCESS) {
437 			/*EMPTY*/
438 			ql_dbg(ql_dbg_disc, vha, 0x2057,
439 			    "GNN_ID issue IOCB failed (%d).\n", rval);
440 			break;
441 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
442 		    "GNN_ID") != QLA_SUCCESS) {
443 			rval = QLA_FUNCTION_FAILED;
444 			break;
445 		} else {
446 			/* Save nodename */
447 			memcpy(list[i].node_name,
448 			    ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
449 
450 			ql_dbg(ql_dbg_disc, vha, 0x2058,
451 			    "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02X%02x "
452 			    "pn %02x%02x%02x%02x%02x%02x%02X%02x "
453 			    "portid=%02x%02x%02x.\n",
454 			    list[i].node_name[0], list[i].node_name[1],
455 			    list[i].node_name[2], list[i].node_name[3],
456 			    list[i].node_name[4], list[i].node_name[5],
457 			    list[i].node_name[6], list[i].node_name[7],
458 			    list[i].port_name[0], list[i].port_name[1],
459 			    list[i].port_name[2], list[i].port_name[3],
460 			    list[i].port_name[4], list[i].port_name[5],
461 			    list[i].port_name[6], list[i].port_name[7],
462 			    list[i].d_id.b.domain, list[i].d_id.b.area,
463 			    list[i].d_id.b.al_pa);
464 		}
465 
466 		/* Last device exit. */
467 		if (list[i].d_id.b.rsvd_1 != 0)
468 			break;
469 	}
470 
471 	return (rval);
472 }
473 
474 /**
475  * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
476  * @ha: HA context
477  *
478  * Returns 0 on success.
479  */
480 int
481 qla2x00_rft_id(scsi_qla_host_t *vha)
482 {
483 	int		rval;
484 	struct qla_hw_data *ha = vha->hw;
485 	ms_iocb_entry_t	*ms_pkt;
486 	struct ct_sns_req	*ct_req;
487 	struct ct_sns_rsp	*ct_rsp;
488 
489 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
490 		return qla2x00_sns_rft_id(vha);
491 
492 	/* Issue RFT_ID */
493 	/* Prepare common MS IOCB */
494 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
495 	    RFT_ID_RSP_SIZE);
496 
497 	/* Prepare CT request */
498 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD,
499 	    RFT_ID_RSP_SIZE);
500 	ct_rsp = &ha->ct_sns->p.rsp;
501 
502 	/* Prepare CT arguments -- port_id, FC-4 types */
503 	ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
504 	ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
505 	ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
506 
507 	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */
508 
509 	/* Execute MS IOCB */
510 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
511 	    sizeof(ms_iocb_entry_t));
512 	if (rval != QLA_SUCCESS) {
513 		/*EMPTY*/
514 		ql_dbg(ql_dbg_disc, vha, 0x2043,
515 		    "RFT_ID issue IOCB failed (%d).\n", rval);
516 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFT_ID") !=
517 	    QLA_SUCCESS) {
518 		rval = QLA_FUNCTION_FAILED;
519 	} else {
520 		ql_dbg(ql_dbg_disc, vha, 0x2044,
521 		    "RFT_ID exiting normally.\n");
522 	}
523 
524 	return (rval);
525 }
526 
527 /**
528  * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
529  * @ha: HA context
530  *
531  * Returns 0 on success.
532  */
533 int
534 qla2x00_rff_id(scsi_qla_host_t *vha)
535 {
536 	int		rval;
537 	struct qla_hw_data *ha = vha->hw;
538 	ms_iocb_entry_t	*ms_pkt;
539 	struct ct_sns_req	*ct_req;
540 	struct ct_sns_rsp	*ct_rsp;
541 
542 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
543 		ql_dbg(ql_dbg_disc, vha, 0x2046,
544 		    "RFF_ID call not supported on ISP2100/ISP2200.\n");
545 		return (QLA_SUCCESS);
546 	}
547 
548 	/* Issue RFF_ID */
549 	/* Prepare common MS IOCB */
550 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
551 	    RFF_ID_RSP_SIZE);
552 
553 	/* Prepare CT request */
554 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD,
555 	    RFF_ID_RSP_SIZE);
556 	ct_rsp = &ha->ct_sns->p.rsp;
557 
558 	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
559 	ct_req->req.rff_id.port_id[0] = vha->d_id.b.domain;
560 	ct_req->req.rff_id.port_id[1] = vha->d_id.b.area;
561 	ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa;
562 
563 	qlt_rff_id(vha, ct_req);
564 
565 	ct_req->req.rff_id.fc4_type = 0x08;		/* SCSI - FCP */
566 
567 	/* Execute MS IOCB */
568 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
569 	    sizeof(ms_iocb_entry_t));
570 	if (rval != QLA_SUCCESS) {
571 		/*EMPTY*/
572 		ql_dbg(ql_dbg_disc, vha, 0x2047,
573 		    "RFF_ID issue IOCB failed (%d).\n", rval);
574 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RFF_ID") !=
575 	    QLA_SUCCESS) {
576 		rval = QLA_FUNCTION_FAILED;
577 	} else {
578 		ql_dbg(ql_dbg_disc, vha, 0x2048,
579 		    "RFF_ID exiting normally.\n");
580 	}
581 
582 	return (rval);
583 }
584 
585 /**
586  * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
587  * @ha: HA context
588  *
589  * Returns 0 on success.
590  */
591 int
592 qla2x00_rnn_id(scsi_qla_host_t *vha)
593 {
594 	int		rval;
595 	struct qla_hw_data *ha = vha->hw;
596 	ms_iocb_entry_t	*ms_pkt;
597 	struct ct_sns_req	*ct_req;
598 	struct ct_sns_rsp	*ct_rsp;
599 
600 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
601 		return qla2x00_sns_rnn_id(vha);
602 
603 	/* Issue RNN_ID */
604 	/* Prepare common MS IOCB */
605 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
606 	    RNN_ID_RSP_SIZE);
607 
608 	/* Prepare CT request */
609 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD,
610 	    RNN_ID_RSP_SIZE);
611 	ct_rsp = &ha->ct_sns->p.rsp;
612 
613 	/* Prepare CT arguments -- port_id, node_name */
614 	ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
615 	ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
616 	ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
617 
618 	memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
619 
620 	/* Execute MS IOCB */
621 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
622 	    sizeof(ms_iocb_entry_t));
623 	if (rval != QLA_SUCCESS) {
624 		/*EMPTY*/
625 		ql_dbg(ql_dbg_disc, vha, 0x204d,
626 		    "RNN_ID issue IOCB failed (%d).\n", rval);
627 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RNN_ID") !=
628 	    QLA_SUCCESS) {
629 		rval = QLA_FUNCTION_FAILED;
630 	} else {
631 		ql_dbg(ql_dbg_disc, vha, 0x204e,
632 		    "RNN_ID exiting normally.\n");
633 	}
634 
635 	return (rval);
636 }
637 
638 void
639 qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn)
640 {
641 	struct qla_hw_data *ha = vha->hw;
642 	sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s",ha->model_number,
643 	    ha->fw_major_version, ha->fw_minor_version,
644 	    ha->fw_subminor_version, qla2x00_version_str);
645 }
646 
647 /**
648  * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
649  * @ha: HA context
650  *
651  * Returns 0 on success.
652  */
653 int
654 qla2x00_rsnn_nn(scsi_qla_host_t *vha)
655 {
656 	int		rval;
657 	struct qla_hw_data *ha = vha->hw;
658 	ms_iocb_entry_t	*ms_pkt;
659 	struct ct_sns_req	*ct_req;
660 	struct ct_sns_rsp	*ct_rsp;
661 
662 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
663 		ql_dbg(ql_dbg_disc, vha, 0x2050,
664 		    "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
665 		return (QLA_SUCCESS);
666 	}
667 
668 	/* Issue RSNN_NN */
669 	/* Prepare common MS IOCB */
670 	/*   Request size adjusted after CT preparation */
671 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
672 
673 	/* Prepare CT request */
674 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD,
675 	    RSNN_NN_RSP_SIZE);
676 	ct_rsp = &ha->ct_sns->p.rsp;
677 
678 	/* Prepare CT arguments -- node_name, symbolic node_name, size */
679 	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
680 
681 	/* Prepare the Symbolic Node Name */
682 	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name);
683 
684 	/* Calculate SNN length */
685 	ct_req->req.rsnn_nn.name_len =
686 	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
687 
688 	/* Update MS IOCB request */
689 	ms_pkt->req_bytecount =
690 	    cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
691 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
692 
693 	/* Execute MS IOCB */
694 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
695 	    sizeof(ms_iocb_entry_t));
696 	if (rval != QLA_SUCCESS) {
697 		/*EMPTY*/
698 		ql_dbg(ql_dbg_disc, vha, 0x2051,
699 		    "RSNN_NN issue IOCB failed (%d).\n", rval);
700 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
701 	    QLA_SUCCESS) {
702 		rval = QLA_FUNCTION_FAILED;
703 	} else {
704 		ql_dbg(ql_dbg_disc, vha, 0x2052,
705 		    "RSNN_NN exiting normally.\n");
706 	}
707 
708 	return (rval);
709 }
710 
711 /**
712  * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
713  * @ha: HA context
714  * @cmd: GS command
715  * @scmd_len: Subcommand length
716  * @data_size: response size in bytes
717  *
718  * Returns a pointer to the @ha's sns_cmd.
719  */
720 static inline struct sns_cmd_pkt *
721 qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
722     uint16_t data_size)
723 {
724 	uint16_t		wc;
725 	struct sns_cmd_pkt	*sns_cmd;
726 	struct qla_hw_data *ha = vha->hw;
727 
728 	sns_cmd = ha->sns_cmd;
729 	memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
730 	wc = data_size / 2;			/* Size in 16bit words. */
731 	sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
732 	sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
733 	sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
734 	sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
735 	sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
736 	wc = (data_size - 16) / 4;		/* Size in 32bit words. */
737 	sns_cmd->p.cmd.size = cpu_to_le16(wc);
738 
739 	return (sns_cmd);
740 }
741 
742 /**
743  * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
744  * @ha: HA context
745  * @fcport: fcport entry to updated
746  *
747  * This command uses the old Exectute SNS Command mailbox routine.
748  *
749  * Returns 0 on success.
750  */
751 static int
752 qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
753 {
754 	int		rval = QLA_SUCCESS;
755 	struct qla_hw_data *ha = vha->hw;
756 	struct sns_cmd_pkt	*sns_cmd;
757 
758 	/* Issue GA_NXT. */
759 	/* Prepare SNS command request. */
760 	sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
761 	    GA_NXT_SNS_DATA_SIZE);
762 
763 	/* Prepare SNS command arguments -- port_id. */
764 	sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
765 	sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
766 	sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
767 
768 	/* Execute SNS command. */
769 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
770 	    sizeof(struct sns_cmd_pkt));
771 	if (rval != QLA_SUCCESS) {
772 		/*EMPTY*/
773 		ql_dbg(ql_dbg_disc, vha, 0x205f,
774 		    "GA_NXT Send SNS failed (%d).\n", rval);
775 	} else if (sns_cmd->p.gan_data[8] != 0x80 ||
776 	    sns_cmd->p.gan_data[9] != 0x02) {
777 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,
778 		    "GA_NXT failed, rejected request ga_nxt_rsp:\n");
779 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
780 		    sns_cmd->p.gan_data, 16);
781 		rval = QLA_FUNCTION_FAILED;
782 	} else {
783 		/* Populate fc_port_t entry. */
784 		fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
785 		fcport->d_id.b.area = sns_cmd->p.gan_data[18];
786 		fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
787 
788 		memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
789 		memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
790 
791 		if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
792 		    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
793 			fcport->d_id.b.domain = 0xf0;
794 
795 		ql_dbg(ql_dbg_disc, vha, 0x2061,
796 		    "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
797 		    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
798 		    "port_id=%02x%02x%02x.\n",
799 		    fcport->node_name[0], fcport->node_name[1],
800 		    fcport->node_name[2], fcport->node_name[3],
801 		    fcport->node_name[4], fcport->node_name[5],
802 		    fcport->node_name[6], fcport->node_name[7],
803 		    fcport->port_name[0], fcport->port_name[1],
804 		    fcport->port_name[2], fcport->port_name[3],
805 		    fcport->port_name[4], fcport->port_name[5],
806 		    fcport->port_name[6], fcport->port_name[7],
807 		    fcport->d_id.b.domain, fcport->d_id.b.area,
808 		    fcport->d_id.b.al_pa);
809 	}
810 
811 	return (rval);
812 }
813 
814 /**
815  * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
816  * @ha: HA context
817  * @list: switch info entries to populate
818  *
819  * This command uses the old Exectute SNS Command mailbox routine.
820  *
821  * NOTE: Non-Nx_Ports are not requested.
822  *
823  * Returns 0 on success.
824  */
825 static int
826 qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
827 {
828 	int		rval;
829 	struct qla_hw_data *ha = vha->hw;
830 	uint16_t	i;
831 	uint8_t		*entry;
832 	struct sns_cmd_pkt	*sns_cmd;
833 	uint16_t gid_pt_sns_data_size;
834 
835 	gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);
836 
837 	/* Issue GID_PT. */
838 	/* Prepare SNS command request. */
839 	sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
840 	    gid_pt_sns_data_size);
841 
842 	/* Prepare SNS command arguments -- port_type. */
843 	sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
844 
845 	/* Execute SNS command. */
846 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
847 	    sizeof(struct sns_cmd_pkt));
848 	if (rval != QLA_SUCCESS) {
849 		/*EMPTY*/
850 		ql_dbg(ql_dbg_disc, vha, 0x206d,
851 		    "GID_PT Send SNS failed (%d).\n", rval);
852 	} else if (sns_cmd->p.gid_data[8] != 0x80 ||
853 	    sns_cmd->p.gid_data[9] != 0x02) {
854 		ql_dbg(ql_dbg_disc, vha, 0x202f,
855 		    "GID_PT failed, rejected request, gid_rsp:\n");
856 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
857 		    sns_cmd->p.gid_data, 16);
858 		rval = QLA_FUNCTION_FAILED;
859 	} else {
860 		/* Set port IDs in switch info list. */
861 		for (i = 0; i < ha->max_fibre_devices; i++) {
862 			entry = &sns_cmd->p.gid_data[(i * 4) + 16];
863 			list[i].d_id.b.domain = entry[1];
864 			list[i].d_id.b.area = entry[2];
865 			list[i].d_id.b.al_pa = entry[3];
866 
867 			/* Last one exit. */
868 			if (entry[0] & BIT_7) {
869 				list[i].d_id.b.rsvd_1 = entry[0];
870 				break;
871 			}
872 		}
873 
874 		/*
875 		 * If we've used all available slots, then the switch is
876 		 * reporting back more devices that we can handle with this
877 		 * single call.  Return a failed status, and let GA_NXT handle
878 		 * the overload.
879 		 */
880 		if (i == ha->max_fibre_devices)
881 			rval = QLA_FUNCTION_FAILED;
882 	}
883 
884 	return (rval);
885 }
886 
887 /**
888  * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
889  * @ha: HA context
890  * @list: switch info entries to populate
891  *
892  * This command uses the old Exectute SNS Command mailbox routine.
893  *
894  * Returns 0 on success.
895  */
896 static int
897 qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
898 {
899 	int		rval = QLA_SUCCESS;
900 	struct qla_hw_data *ha = vha->hw;
901 	uint16_t	i;
902 	struct sns_cmd_pkt	*sns_cmd;
903 
904 	for (i = 0; i < ha->max_fibre_devices; i++) {
905 		/* Issue GPN_ID */
906 		/* Prepare SNS command request. */
907 		sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,
908 		    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
909 
910 		/* Prepare SNS command arguments -- port_id. */
911 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
912 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
913 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
914 
915 		/* Execute SNS command. */
916 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
917 		    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
918 		if (rval != QLA_SUCCESS) {
919 			/*EMPTY*/
920 			ql_dbg(ql_dbg_disc, vha, 0x2032,
921 			    "GPN_ID Send SNS failed (%d).\n", rval);
922 		} else if (sns_cmd->p.gpn_data[8] != 0x80 ||
923 		    sns_cmd->p.gpn_data[9] != 0x02) {
924 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
925 			    "GPN_ID failed, rejected request, gpn_rsp:\n");
926 			ql_dump_buffer(ql_dbg_disc, vha, 0x207f,
927 			    sns_cmd->p.gpn_data, 16);
928 			rval = QLA_FUNCTION_FAILED;
929 		} else {
930 			/* Save portname */
931 			memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
932 			    WWN_SIZE);
933 		}
934 
935 		/* Last device exit. */
936 		if (list[i].d_id.b.rsvd_1 != 0)
937 			break;
938 	}
939 
940 	return (rval);
941 }
942 
943 /**
944  * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
945  * @ha: HA context
946  * @list: switch info entries to populate
947  *
948  * This command uses the old Exectute SNS Command mailbox routine.
949  *
950  * Returns 0 on success.
951  */
952 static int
953 qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
954 {
955 	int		rval = QLA_SUCCESS;
956 	struct qla_hw_data *ha = vha->hw;
957 	uint16_t	i;
958 	struct sns_cmd_pkt	*sns_cmd;
959 
960 	for (i = 0; i < ha->max_fibre_devices; i++) {
961 		/* Issue GNN_ID */
962 		/* Prepare SNS command request. */
963 		sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,
964 		    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
965 
966 		/* Prepare SNS command arguments -- port_id. */
967 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
968 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
969 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
970 
971 		/* Execute SNS command. */
972 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
973 		    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
974 		if (rval != QLA_SUCCESS) {
975 			/*EMPTY*/
976 			ql_dbg(ql_dbg_disc, vha, 0x203f,
977 			    "GNN_ID Send SNS failed (%d).\n", rval);
978 		} else if (sns_cmd->p.gnn_data[8] != 0x80 ||
979 		    sns_cmd->p.gnn_data[9] != 0x02) {
980 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
981 			    "GNN_ID failed, rejected request, gnn_rsp:\n");
982 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
983 			    sns_cmd->p.gnn_data, 16);
984 			rval = QLA_FUNCTION_FAILED;
985 		} else {
986 			/* Save nodename */
987 			memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
988 			    WWN_SIZE);
989 
990 			ql_dbg(ql_dbg_disc, vha, 0x206e,
991 			    "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
992 			    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
993 			    "port_id=%02x%02x%02x.\n",
994 			    list[i].node_name[0], list[i].node_name[1],
995 			    list[i].node_name[2], list[i].node_name[3],
996 			    list[i].node_name[4], list[i].node_name[5],
997 			    list[i].node_name[6], list[i].node_name[7],
998 			    list[i].port_name[0], list[i].port_name[1],
999 			    list[i].port_name[2], list[i].port_name[3],
1000 			    list[i].port_name[4], list[i].port_name[5],
1001 			    list[i].port_name[6], list[i].port_name[7],
1002 			    list[i].d_id.b.domain, list[i].d_id.b.area,
1003 			    list[i].d_id.b.al_pa);
1004 		}
1005 
1006 		/* Last device exit. */
1007 		if (list[i].d_id.b.rsvd_1 != 0)
1008 			break;
1009 	}
1010 
1011 	return (rval);
1012 }
1013 
1014 /**
1015  * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
1016  * @ha: HA context
1017  *
1018  * This command uses the old Exectute SNS Command mailbox routine.
1019  *
1020  * Returns 0 on success.
1021  */
1022 static int
1023 qla2x00_sns_rft_id(scsi_qla_host_t *vha)
1024 {
1025 	int		rval;
1026 	struct qla_hw_data *ha = vha->hw;
1027 	struct sns_cmd_pkt	*sns_cmd;
1028 
1029 	/* Issue RFT_ID. */
1030 	/* Prepare SNS command request. */
1031 	sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
1032 	    RFT_ID_SNS_DATA_SIZE);
1033 
1034 	/* Prepare SNS command arguments -- port_id, FC-4 types */
1035 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1036 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1037 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1038 
1039 	sns_cmd->p.cmd.param[5] = 0x01;			/* FCP-3 */
1040 
1041 	/* Execute SNS command. */
1042 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
1043 	    sizeof(struct sns_cmd_pkt));
1044 	if (rval != QLA_SUCCESS) {
1045 		/*EMPTY*/
1046 		ql_dbg(ql_dbg_disc, vha, 0x2060,
1047 		    "RFT_ID Send SNS failed (%d).\n", rval);
1048 	} else if (sns_cmd->p.rft_data[8] != 0x80 ||
1049 	    sns_cmd->p.rft_data[9] != 0x02) {
1050 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
1051 		    "RFT_ID failed, rejected request rft_rsp:\n");
1052 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
1053 		    sns_cmd->p.rft_data, 16);
1054 		rval = QLA_FUNCTION_FAILED;
1055 	} else {
1056 		ql_dbg(ql_dbg_disc, vha, 0x2073,
1057 		    "RFT_ID exiting normally.\n");
1058 	}
1059 
1060 	return (rval);
1061 }
1062 
1063 /**
1064  * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
1065  * HBA.
1066  * @ha: HA context
1067  *
1068  * This command uses the old Exectute SNS Command mailbox routine.
1069  *
1070  * Returns 0 on success.
1071  */
1072 static int
1073 qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
1074 {
1075 	int		rval;
1076 	struct qla_hw_data *ha = vha->hw;
1077 	struct sns_cmd_pkt	*sns_cmd;
1078 
1079 	/* Issue RNN_ID. */
1080 	/* Prepare SNS command request. */
1081 	sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
1082 	    RNN_ID_SNS_DATA_SIZE);
1083 
1084 	/* Prepare SNS command arguments -- port_id, nodename. */
1085 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1086 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1087 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1088 
1089 	sns_cmd->p.cmd.param[4] = vha->node_name[7];
1090 	sns_cmd->p.cmd.param[5] = vha->node_name[6];
1091 	sns_cmd->p.cmd.param[6] = vha->node_name[5];
1092 	sns_cmd->p.cmd.param[7] = vha->node_name[4];
1093 	sns_cmd->p.cmd.param[8] = vha->node_name[3];
1094 	sns_cmd->p.cmd.param[9] = vha->node_name[2];
1095 	sns_cmd->p.cmd.param[10] = vha->node_name[1];
1096 	sns_cmd->p.cmd.param[11] = vha->node_name[0];
1097 
1098 	/* Execute SNS command. */
1099 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
1100 	    sizeof(struct sns_cmd_pkt));
1101 	if (rval != QLA_SUCCESS) {
1102 		/*EMPTY*/
1103 		ql_dbg(ql_dbg_disc, vha, 0x204a,
1104 		    "RNN_ID Send SNS failed (%d).\n", rval);
1105 	} else if (sns_cmd->p.rnn_data[8] != 0x80 ||
1106 	    sns_cmd->p.rnn_data[9] != 0x02) {
1107 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
1108 		    "RNN_ID failed, rejected request, rnn_rsp:\n");
1109 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
1110 		    sns_cmd->p.rnn_data, 16);
1111 		rval = QLA_FUNCTION_FAILED;
1112 	} else {
1113 		ql_dbg(ql_dbg_disc, vha, 0x204c,
1114 		    "RNN_ID exiting normally.\n");
1115 	}
1116 
1117 	return (rval);
1118 }
1119 
1120 /**
1121  * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
1122  * @ha: HA context
1123  *
1124  * Returns 0 on success.
1125  */
1126 static int
1127 qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
1128 {
1129 	int ret, rval;
1130 	uint16_t mb[MAILBOX_REGISTER_COUNT];
1131 	struct qla_hw_data *ha = vha->hw;
1132 	ret = QLA_SUCCESS;
1133 	if (vha->flags.management_server_logged_in)
1134 		return ret;
1135 
1136 	rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,
1137 	    0xfa, mb, BIT_1);
1138 	if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
1139 		if (rval == QLA_MEMORY_ALLOC_FAILED)
1140 			ql_dbg(ql_dbg_disc, vha, 0x2085,
1141 			    "Failed management_server login: loopid=%x "
1142 			    "rval=%d\n", vha->mgmt_svr_loop_id, rval);
1143 		else
1144 			ql_dbg(ql_dbg_disc, vha, 0x2024,
1145 			    "Failed management_server login: loopid=%x "
1146 			    "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
1147 			    vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],
1148 			    mb[7]);
1149 		ret = QLA_FUNCTION_FAILED;
1150 	} else
1151 		vha->flags.management_server_logged_in = 1;
1152 
1153 	return ret;
1154 }
1155 
1156 /**
1157  * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1158  * @ha: HA context
1159  * @req_size: request size in bytes
1160  * @rsp_size: response size in bytes
1161  *
1162  * Returns a pointer to the @ha's ms_iocb.
1163  */
1164 void *
1165 qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1166     uint32_t rsp_size)
1167 {
1168 	ms_iocb_entry_t *ms_pkt;
1169 	struct qla_hw_data *ha = vha->hw;
1170 	ms_pkt = ha->ms_iocb;
1171 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
1172 
1173 	ms_pkt->entry_type = MS_IOCB_TYPE;
1174 	ms_pkt->entry_count = 1;
1175 	SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);
1176 	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
1177 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1178 	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1179 	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
1180 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
1181 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
1182 
1183 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1184 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1185 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1186 
1187 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1188 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1189 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
1190 
1191 	return ms_pkt;
1192 }
1193 
1194 /**
1195  * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1196  * @ha: HA context
1197  * @req_size: request size in bytes
1198  * @rsp_size: response size in bytes
1199  *
1200  * Returns a pointer to the @ha's ms_iocb.
1201  */
1202 void *
1203 qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1204     uint32_t rsp_size)
1205 {
1206 	struct ct_entry_24xx *ct_pkt;
1207 	struct qla_hw_data *ha = vha->hw;
1208 
1209 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1210 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1211 
1212 	ct_pkt->entry_type = CT_IOCB_TYPE;
1213 	ct_pkt->entry_count = 1;
1214 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1215 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1216 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1217 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
1218 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1219 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1220 
1221 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1222 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1223 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1224 
1225 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1226 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1227 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1228 	ct_pkt->vp_index = vha->vp_idx;
1229 
1230 	return ct_pkt;
1231 }
1232 
1233 static inline ms_iocb_entry_t *
1234 qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
1235 {
1236 	struct qla_hw_data *ha = vha->hw;
1237 	ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
1238 	struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1239 
1240 	if (IS_FWI2_CAPABLE(ha)) {
1241 		ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1242 		ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1243 	} else {
1244 		ms_pkt->req_bytecount = cpu_to_le32(req_size);
1245 		ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1246 	}
1247 
1248 	return ms_pkt;
1249 }
1250 
1251 /**
1252  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
1253  * @ct_req: CT request buffer
1254  * @cmd: GS command
1255  * @rsp_size: response size in bytes
1256  *
1257  * Returns a pointer to the intitialized @ct_req.
1258  */
1259 static inline struct ct_sns_req *
1260 qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd,
1261     uint16_t rsp_size)
1262 {
1263 	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
1264 
1265 	ct_req->header.revision = 0x01;
1266 	ct_req->header.gs_type = 0xFA;
1267 	ct_req->header.gs_subtype = 0x10;
1268 	ct_req->command = cpu_to_be16(cmd);
1269 	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1270 
1271 	return ct_req;
1272 }
1273 
1274 /**
1275  * qla2x00_fdmi_rhba() -
1276  * @ha: HA context
1277  *
1278  * Returns 0 on success.
1279  */
1280 static int
1281 qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
1282 {
1283 	int rval, alen;
1284 	uint32_t size, sn;
1285 
1286 	ms_iocb_entry_t *ms_pkt;
1287 	struct ct_sns_req *ct_req;
1288 	struct ct_sns_rsp *ct_rsp;
1289 	uint8_t *entries;
1290 	struct ct_fdmi_hba_attr *eiter;
1291 	struct qla_hw_data *ha = vha->hw;
1292 
1293 	/* Issue RHBA */
1294 	/* Prepare common MS IOCB */
1295 	/*   Request size adjusted after CT preparation */
1296 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1297 
1298 	/* Prepare CT request */
1299 	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD,
1300 	    RHBA_RSP_SIZE);
1301 	ct_rsp = &ha->ct_sns->p.rsp;
1302 
1303 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1304 	memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE);
1305 	ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1);
1306 	memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE);
1307 	size = 2 * WWN_SIZE + 4 + 4;
1308 
1309 	/* Attributes */
1310 	ct_req->req.rhba.attrs.count =
1311 	    __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT);
1312 	entries = ct_req->req.rhba.hba_identifier;
1313 
1314 	/* Nodename. */
1315 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1316 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME);
1317 	eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE);
1318 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1319 	size += 4 + WWN_SIZE;
1320 
1321 	ql_dbg(ql_dbg_disc, vha, 0x2025,
1322 	    "NodeName = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
1323 	    eiter->a.node_name[0], eiter->a.node_name[1],
1324 	    eiter->a.node_name[2], eiter->a.node_name[3],
1325 	    eiter->a.node_name[4], eiter->a.node_name[5],
1326 	    eiter->a.node_name[6], eiter->a.node_name[7]);
1327 
1328 	/* Manufacturer. */
1329 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1330 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
1331 	strcpy(eiter->a.manufacturer, "QLogic Corporation");
1332 	alen = strlen(eiter->a.manufacturer);
1333 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1334 	eiter->len = cpu_to_be16(4 + alen);
1335 	size += 4 + alen;
1336 
1337 	ql_dbg(ql_dbg_disc, vha, 0x2026,
1338 	    "Manufacturer = %s.\n", eiter->a.manufacturer);
1339 
1340 	/* Serial number. */
1341 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1342 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1343 	sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
1344 	sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000);
1345 	alen = strlen(eiter->a.serial_num);
1346 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1347 	eiter->len = cpu_to_be16(4 + alen);
1348 	size += 4 + alen;
1349 
1350 	ql_dbg(ql_dbg_disc, vha, 0x2027,
1351 	    "Serial no. = %s.\n", eiter->a.serial_num);
1352 
1353 	/* Model name. */
1354 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1355 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL);
1356 	strcpy(eiter->a.model, ha->model_number);
1357 	alen = strlen(eiter->a.model);
1358 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1359 	eiter->len = cpu_to_be16(4 + alen);
1360 	size += 4 + alen;
1361 
1362 	ql_dbg(ql_dbg_disc, vha, 0x2028,
1363 	    "Model Name = %s.\n", eiter->a.model);
1364 
1365 	/* Model description. */
1366 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1367 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1368 	if (ha->model_desc)
1369 		strncpy(eiter->a.model_desc, ha->model_desc, 80);
1370 	alen = strlen(eiter->a.model_desc);
1371 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1372 	eiter->len = cpu_to_be16(4 + alen);
1373 	size += 4 + alen;
1374 
1375 	ql_dbg(ql_dbg_disc, vha, 0x2029,
1376 	    "Model Desc = %s.\n", eiter->a.model_desc);
1377 
1378 	/* Hardware version. */
1379 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1380 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1381 	strcpy(eiter->a.hw_version, ha->adapter_id);
1382 	alen = strlen(eiter->a.hw_version);
1383 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1384 	eiter->len = cpu_to_be16(4 + alen);
1385 	size += 4 + alen;
1386 
1387 	ql_dbg(ql_dbg_disc, vha, 0x202a,
1388 	    "Hardware ver = %s.\n", eiter->a.hw_version);
1389 
1390 	/* Driver version. */
1391 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1392 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1393 	strcpy(eiter->a.driver_version, qla2x00_version_str);
1394 	alen = strlen(eiter->a.driver_version);
1395 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1396 	eiter->len = cpu_to_be16(4 + alen);
1397 	size += 4 + alen;
1398 
1399 	ql_dbg(ql_dbg_disc, vha, 0x202b,
1400 	    "Driver ver = %s.\n", eiter->a.driver_version);
1401 
1402 	/* Option ROM version. */
1403 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1404 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1405 	strcpy(eiter->a.orom_version, "0.00");
1406 	alen = strlen(eiter->a.orom_version);
1407 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1408 	eiter->len = cpu_to_be16(4 + alen);
1409 	size += 4 + alen;
1410 
1411 	ql_dbg(ql_dbg_disc, vha , 0x202c,
1412 	    "Optrom vers = %s.\n", eiter->a.orom_version);
1413 
1414 	/* Firmware version */
1415 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1416 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1417 	ha->isp_ops->fw_version_str(vha, eiter->a.fw_version);
1418 	alen = strlen(eiter->a.fw_version);
1419 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1420 	eiter->len = cpu_to_be16(4 + alen);
1421 	size += 4 + alen;
1422 
1423 	ql_dbg(ql_dbg_disc, vha, 0x202d,
1424 	    "Firmware vers = %s.\n", eiter->a.fw_version);
1425 
1426 	/* Update MS request size. */
1427 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1428 
1429 	ql_dbg(ql_dbg_disc, vha, 0x202e,
1430 	    "RHBA identifier = "
1431 	    "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n",
1432 	    ct_req->req.rhba.hba_identifier[0],
1433 	    ct_req->req.rhba.hba_identifier[1],
1434 	    ct_req->req.rhba.hba_identifier[2],
1435 	    ct_req->req.rhba.hba_identifier[3],
1436 	    ct_req->req.rhba.hba_identifier[4],
1437 	    ct_req->req.rhba.hba_identifier[5],
1438 	    ct_req->req.rhba.hba_identifier[6],
1439 	    ct_req->req.rhba.hba_identifier[7], size);
1440 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
1441 	    entries, size);
1442 
1443 	/* Execute MS IOCB */
1444 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1445 	    sizeof(ms_iocb_entry_t));
1446 	if (rval != QLA_SUCCESS) {
1447 		/*EMPTY*/
1448 		ql_dbg(ql_dbg_disc, vha, 0x2030,
1449 		    "RHBA issue IOCB failed (%d).\n", rval);
1450 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
1451 	    QLA_SUCCESS) {
1452 		rval = QLA_FUNCTION_FAILED;
1453 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1454 		    ct_rsp->header.explanation_code ==
1455 		    CT_EXPL_ALREADY_REGISTERED) {
1456 			ql_dbg(ql_dbg_disc, vha, 0x2034,
1457 			    "HBA already registered.\n");
1458 			rval = QLA_ALREADY_REGISTERED;
1459 		}
1460 	} else {
1461 		ql_dbg(ql_dbg_disc, vha, 0x2035,
1462 		    "RHBA exiting normally.\n");
1463 	}
1464 
1465 	return rval;
1466 }
1467 
1468 /**
1469  * qla2x00_fdmi_dhba() -
1470  * @ha: HA context
1471  *
1472  * Returns 0 on success.
1473  */
1474 static int
1475 qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
1476 {
1477 	int rval;
1478 	struct qla_hw_data *ha = vha->hw;
1479 	ms_iocb_entry_t *ms_pkt;
1480 	struct ct_sns_req *ct_req;
1481 	struct ct_sns_rsp *ct_rsp;
1482 
1483 	/* Issue RPA */
1484 	/* Prepare common MS IOCB */
1485 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
1486 	    DHBA_RSP_SIZE);
1487 
1488 	/* Prepare CT request */
1489 	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD,
1490 	    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->p.req, RPA_CMD,
1547 	    RPA_RSP_SIZE);
1548 	ct_rsp = &ha->ct_sns->p.rsp;
1549 
1550 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1551 	memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
1552 	size = WWN_SIZE + 4;
1553 
1554 	/* Attributes */
1555 	ct_req->req.rpa.attrs.count =
1556 	    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT - 1);
1557 	entries = ct_req->req.rpa.port_name;
1558 
1559 	/* FC4 types. */
1560 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1561 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES);
1562 	eiter->len = __constant_cpu_to_be16(4 + 32);
1563 	eiter->a.fc4_types[2] = 0x01;
1564 	size += 4 + 32;
1565 
1566 	ql_dbg(ql_dbg_disc, vha, 0x2039,
1567 	    "FC4_TYPES=%02x %02x.\n",
1568 	    eiter->a.fc4_types[2],
1569 	    eiter->a.fc4_types[1]);
1570 
1571 	/* Supported speed. */
1572 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1573 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
1574 	eiter->len = __constant_cpu_to_be16(4 + 4);
1575 	if (IS_CNA_CAPABLE(ha))
1576 		eiter->a.sup_speed = __constant_cpu_to_be32(
1577 		    FDMI_PORT_SPEED_10GB);
1578 	else if (IS_QLA25XX(ha))
1579 		eiter->a.sup_speed = __constant_cpu_to_be32(
1580 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1581 		    FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
1582 	else if (IS_QLA24XX_TYPE(ha))
1583 		eiter->a.sup_speed = __constant_cpu_to_be32(
1584 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1585 		    FDMI_PORT_SPEED_4GB);
1586 	else if (IS_QLA23XX(ha))
1587 		eiter->a.sup_speed =__constant_cpu_to_be32(
1588 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB);
1589 	else
1590 		eiter->a.sup_speed = __constant_cpu_to_be32(
1591 		    FDMI_PORT_SPEED_1GB);
1592 	size += 4 + 4;
1593 
1594 	ql_dbg(ql_dbg_disc, vha, 0x203a,
1595 	    "Supported_Speed=%x.\n", eiter->a.sup_speed);
1596 
1597 	/* Current speed. */
1598 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1599 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
1600 	eiter->len = __constant_cpu_to_be16(4 + 4);
1601 	switch (ha->link_data_rate) {
1602 	case PORT_SPEED_1GB:
1603 		eiter->a.cur_speed =
1604 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_1GB);
1605 		break;
1606 	case PORT_SPEED_2GB:
1607 		eiter->a.cur_speed =
1608 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_2GB);
1609 		break;
1610 	case PORT_SPEED_4GB:
1611 		eiter->a.cur_speed =
1612 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_4GB);
1613 		break;
1614 	case PORT_SPEED_8GB:
1615 		eiter->a.cur_speed =
1616 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_8GB);
1617 		break;
1618 	case PORT_SPEED_10GB:
1619 		eiter->a.cur_speed =
1620 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_10GB);
1621 		break;
1622 	case PORT_SPEED_16GB:
1623 		eiter->a.cur_speed =
1624 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_16GB);
1625 		break;
1626 	default:
1627 		eiter->a.cur_speed =
1628 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
1629 		break;
1630 	}
1631 	size += 4 + 4;
1632 
1633 	ql_dbg(ql_dbg_disc, vha, 0x203b,
1634 	    "Current_Speed=%x.\n", eiter->a.cur_speed);
1635 
1636 	/* Max frame size. */
1637 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1638 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
1639 	eiter->len = __constant_cpu_to_be16(4 + 4);
1640 	max_frame_size = IS_FWI2_CAPABLE(ha) ?
1641 	    le16_to_cpu(icb24->frame_payload_size):
1642 	    le16_to_cpu(ha->init_cb->frame_payload_size);
1643 	eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
1644 	size += 4 + 4;
1645 
1646 	ql_dbg(ql_dbg_disc, vha, 0x203c,
1647 	    "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
1648 
1649 	/* OS device name. */
1650 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1651 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
1652 	strcpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME);
1653 	alen = strlen(eiter->a.os_dev_name);
1654 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1655 	eiter->len = cpu_to_be16(4 + alen);
1656 	size += 4 + alen;
1657 
1658 	ql_dbg(ql_dbg_disc, vha, 0x204b,
1659 	    "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
1660 
1661 	/* Hostname. */
1662 	if (strlen(fc_host_system_hostname(vha->host))) {
1663 		ct_req->req.rpa.attrs.count =
1664 		    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
1665 		eiter = (struct ct_fdmi_port_attr *) (entries + size);
1666 		eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME);
1667 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1668 		    "%s", fc_host_system_hostname(vha->host));
1669 		alen = strlen(eiter->a.host_name);
1670 		alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1671 		eiter->len = cpu_to_be16(4 + alen);
1672 		size += 4 + alen;
1673 
1674 		ql_dbg(ql_dbg_disc, vha, 0x203d,
1675 		    "HostName=%s.\n", eiter->a.host_name);
1676 	}
1677 
1678 	/* Update MS request size. */
1679 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1680 
1681 	ql_dbg(ql_dbg_disc, vha, 0x203e,
1682 	    "RPA portname= %02x%02x%02x%02x%02X%02x%02x%02x size=%d.\n",
1683 	    ct_req->req.rpa.port_name[0], ct_req->req.rpa.port_name[1],
1684 	    ct_req->req.rpa.port_name[2], ct_req->req.rpa.port_name[3],
1685 	    ct_req->req.rpa.port_name[4], ct_req->req.rpa.port_name[5],
1686 	    ct_req->req.rpa.port_name[6], ct_req->req.rpa.port_name[7],
1687 	    size);
1688 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
1689 	    entries, size);
1690 
1691 	/* Execute MS IOCB */
1692 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1693 	    sizeof(ms_iocb_entry_t));
1694 	if (rval != QLA_SUCCESS) {
1695 		/*EMPTY*/
1696 		ql_dbg(ql_dbg_disc, vha, 0x2040,
1697 		    "RPA issue IOCB failed (%d).\n", rval);
1698 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
1699 	    QLA_SUCCESS) {
1700 		rval = QLA_FUNCTION_FAILED;
1701 	} else {
1702 		ql_dbg(ql_dbg_disc, vha, 0x2041,
1703 		    "RPA exiting nornally.\n");
1704 	}
1705 
1706 	return rval;
1707 }
1708 
1709 /**
1710  * qla2x00_fdmi_register() -
1711  * @ha: HA context
1712  *
1713  * Returns 0 on success.
1714  */
1715 int
1716 qla2x00_fdmi_register(scsi_qla_host_t *vha)
1717 {
1718 	int rval;
1719        struct qla_hw_data *ha = vha->hw;
1720 
1721 	if (IS_QLA2100(ha) || IS_QLA2200(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->p.req, 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_req *ct_req, uint16_t cmd,
1841     uint16_t rsp_size)
1842 {
1843 	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
1844 
1845 	ct_req->header.revision = 0x01;
1846 	ct_req->header.gs_type = 0xFA;
1847 	ct_req->header.gs_subtype = 0x01;
1848 	ct_req->command = cpu_to_be16(cmd);
1849 	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1850 
1851 	return ct_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->p.req,
1888 		    GPSC_CMD, 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->p.req, 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