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