xref: /openbmc/linux/drivers/scsi/qla2xxx/qla_gs.c (revision 39b6f3aa)
1 /*
2  * QLogic Fibre Channel HBA Driver
3  * Copyright (c)  2003-2013 QLogic Corporation
4  *
5  * See LICENSE.qla2xxx for copyright and licensing details.
6  */
7 #include "qla_def.h"
8 #include "qla_target.h"
9 
10 static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
11 static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
12 static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
13 static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
14 static int qla2x00_sns_rft_id(scsi_qla_host_t *);
15 static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
16 
17 /**
18  * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
19  * @ha: HA context
20  * @req_size: request size in bytes
21  * @rsp_size: response size in bytes
22  *
23  * Returns a pointer to the @ha's ms_iocb.
24  */
25 void *
26 qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
27 {
28 	struct qla_hw_data *ha = vha->hw;
29 	ms_iocb_entry_t *ms_pkt;
30 
31 	ms_pkt = ha->ms_iocb;
32 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
33 
34 	ms_pkt->entry_type = MS_IOCB_TYPE;
35 	ms_pkt->entry_count = 1;
36 	SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
37 	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
38 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
39 	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
40 	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
41 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
42 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
43 
44 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
45 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
46 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
47 
48 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
49 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
50 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
51 
52 	return (ms_pkt);
53 }
54 
55 /**
56  * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.
57  * @ha: HA context
58  * @req_size: request size in bytes
59  * @rsp_size: response size in bytes
60  *
61  * Returns a pointer to the @ha's ms_iocb.
62  */
63 void *
64 qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
65 {
66 	struct qla_hw_data *ha = vha->hw;
67 	struct ct_entry_24xx *ct_pkt;
68 
69 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
70 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
71 
72 	ct_pkt->entry_type = CT_IOCB_TYPE;
73 	ct_pkt->entry_count = 1;
74 	ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS);
75 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
76 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
77 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
78 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
79 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
80 
81 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
82 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
83 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
84 
85 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
86 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
87 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
88 	ct_pkt->vp_index = vha->vp_idx;
89 
90 	return (ct_pkt);
91 }
92 
93 /**
94  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
95  * @ct_req: CT request buffer
96  * @cmd: GS command
97  * @rsp_size: response size in bytes
98  *
99  * Returns a pointer to the intitialized @ct_req.
100  */
101 static inline struct ct_sns_req *
102 qla2x00_prep_ct_req(struct ct_sns_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 
643 	if (IS_QLAFX00(ha))
644 		sprintf(snn, "%s FW:v%s DVR:v%s", ha->model_number,
645 		    ha->mr.fw_version, qla2x00_version_str);
646 	else
647 		sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
648 		    ha->fw_major_version, ha->fw_minor_version,
649 		    ha->fw_subminor_version, qla2x00_version_str);
650 }
651 
652 /**
653  * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
654  * @ha: HA context
655  *
656  * Returns 0 on success.
657  */
658 int
659 qla2x00_rsnn_nn(scsi_qla_host_t *vha)
660 {
661 	int		rval;
662 	struct qla_hw_data *ha = vha->hw;
663 	ms_iocb_entry_t	*ms_pkt;
664 	struct ct_sns_req	*ct_req;
665 	struct ct_sns_rsp	*ct_rsp;
666 
667 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
668 		ql_dbg(ql_dbg_disc, vha, 0x2050,
669 		    "RSNN_ID call unsupported on ISP2100/ISP2200.\n");
670 		return (QLA_SUCCESS);
671 	}
672 
673 	/* Issue RSNN_NN */
674 	/* Prepare common MS IOCB */
675 	/*   Request size adjusted after CT preparation */
676 	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
677 
678 	/* Prepare CT request */
679 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD,
680 	    RSNN_NN_RSP_SIZE);
681 	ct_rsp = &ha->ct_sns->p.rsp;
682 
683 	/* Prepare CT arguments -- node_name, symbolic node_name, size */
684 	memcpy(ct_req->req.rsnn_nn.node_name, vha->node_name, WWN_SIZE);
685 
686 	/* Prepare the Symbolic Node Name */
687 	qla2x00_get_sym_node_name(vha, ct_req->req.rsnn_nn.sym_node_name);
688 
689 	/* Calculate SNN length */
690 	ct_req->req.rsnn_nn.name_len =
691 	    (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name);
692 
693 	/* Update MS IOCB request */
694 	ms_pkt->req_bytecount =
695 	    cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
696 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
697 
698 	/* Execute MS IOCB */
699 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
700 	    sizeof(ms_iocb_entry_t));
701 	if (rval != QLA_SUCCESS) {
702 		/*EMPTY*/
703 		ql_dbg(ql_dbg_disc, vha, 0x2051,
704 		    "RSNN_NN issue IOCB failed (%d).\n", rval);
705 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RSNN_NN") !=
706 	    QLA_SUCCESS) {
707 		rval = QLA_FUNCTION_FAILED;
708 	} else {
709 		ql_dbg(ql_dbg_disc, vha, 0x2052,
710 		    "RSNN_NN exiting normally.\n");
711 	}
712 
713 	return (rval);
714 }
715 
716 /**
717  * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
718  * @ha: HA context
719  * @cmd: GS command
720  * @scmd_len: Subcommand length
721  * @data_size: response size in bytes
722  *
723  * Returns a pointer to the @ha's sns_cmd.
724  */
725 static inline struct sns_cmd_pkt *
726 qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
727     uint16_t data_size)
728 {
729 	uint16_t		wc;
730 	struct sns_cmd_pkt	*sns_cmd;
731 	struct qla_hw_data *ha = vha->hw;
732 
733 	sns_cmd = ha->sns_cmd;
734 	memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
735 	wc = data_size / 2;			/* Size in 16bit words. */
736 	sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
737 	sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
738 	sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
739 	sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
740 	sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
741 	wc = (data_size - 16) / 4;		/* Size in 32bit words. */
742 	sns_cmd->p.cmd.size = cpu_to_le16(wc);
743 
744 	return (sns_cmd);
745 }
746 
747 /**
748  * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
749  * @ha: HA context
750  * @fcport: fcport entry to updated
751  *
752  * This command uses the old Exectute SNS Command mailbox routine.
753  *
754  * Returns 0 on success.
755  */
756 static int
757 qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
758 {
759 	int		rval = QLA_SUCCESS;
760 	struct qla_hw_data *ha = vha->hw;
761 	struct sns_cmd_pkt	*sns_cmd;
762 
763 	/* Issue GA_NXT. */
764 	/* Prepare SNS command request. */
765 	sns_cmd = qla2x00_prep_sns_cmd(vha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
766 	    GA_NXT_SNS_DATA_SIZE);
767 
768 	/* Prepare SNS command arguments -- port_id. */
769 	sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
770 	sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
771 	sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
772 
773 	/* Execute SNS command. */
774 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
775 	    sizeof(struct sns_cmd_pkt));
776 	if (rval != QLA_SUCCESS) {
777 		/*EMPTY*/
778 		ql_dbg(ql_dbg_disc, vha, 0x205f,
779 		    "GA_NXT Send SNS failed (%d).\n", rval);
780 	} else if (sns_cmd->p.gan_data[8] != 0x80 ||
781 	    sns_cmd->p.gan_data[9] != 0x02) {
782 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084,
783 		    "GA_NXT failed, rejected request ga_nxt_rsp:\n");
784 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074,
785 		    sns_cmd->p.gan_data, 16);
786 		rval = QLA_FUNCTION_FAILED;
787 	} else {
788 		/* Populate fc_port_t entry. */
789 		fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
790 		fcport->d_id.b.area = sns_cmd->p.gan_data[18];
791 		fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
792 
793 		memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
794 		memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
795 
796 		if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
797 		    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
798 			fcport->d_id.b.domain = 0xf0;
799 
800 		ql_dbg(ql_dbg_disc, vha, 0x2061,
801 		    "GA_NXT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
802 		    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
803 		    "port_id=%02x%02x%02x.\n",
804 		    fcport->node_name[0], fcport->node_name[1],
805 		    fcport->node_name[2], fcport->node_name[3],
806 		    fcport->node_name[4], fcport->node_name[5],
807 		    fcport->node_name[6], fcport->node_name[7],
808 		    fcport->port_name[0], fcport->port_name[1],
809 		    fcport->port_name[2], fcport->port_name[3],
810 		    fcport->port_name[4], fcport->port_name[5],
811 		    fcport->port_name[6], fcport->port_name[7],
812 		    fcport->d_id.b.domain, fcport->d_id.b.area,
813 		    fcport->d_id.b.al_pa);
814 	}
815 
816 	return (rval);
817 }
818 
819 /**
820  * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
821  * @ha: HA context
822  * @list: switch info entries to populate
823  *
824  * This command uses the old Exectute SNS Command mailbox routine.
825  *
826  * NOTE: Non-Nx_Ports are not requested.
827  *
828  * Returns 0 on success.
829  */
830 static int
831 qla2x00_sns_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
832 {
833 	int		rval;
834 	struct qla_hw_data *ha = vha->hw;
835 	uint16_t	i;
836 	uint8_t		*entry;
837 	struct sns_cmd_pkt	*sns_cmd;
838 	uint16_t gid_pt_sns_data_size;
839 
840 	gid_pt_sns_data_size = qla2x00_gid_pt_rsp_size(vha);
841 
842 	/* Issue GID_PT. */
843 	/* Prepare SNS command request. */
844 	sns_cmd = qla2x00_prep_sns_cmd(vha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
845 	    gid_pt_sns_data_size);
846 
847 	/* Prepare SNS command arguments -- port_type. */
848 	sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
849 
850 	/* Execute SNS command. */
851 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
852 	    sizeof(struct sns_cmd_pkt));
853 	if (rval != QLA_SUCCESS) {
854 		/*EMPTY*/
855 		ql_dbg(ql_dbg_disc, vha, 0x206d,
856 		    "GID_PT Send SNS failed (%d).\n", rval);
857 	} else if (sns_cmd->p.gid_data[8] != 0x80 ||
858 	    sns_cmd->p.gid_data[9] != 0x02) {
859 		ql_dbg(ql_dbg_disc, vha, 0x202f,
860 		    "GID_PT failed, rejected request, gid_rsp:\n");
861 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2081,
862 		    sns_cmd->p.gid_data, 16);
863 		rval = QLA_FUNCTION_FAILED;
864 	} else {
865 		/* Set port IDs in switch info list. */
866 		for (i = 0; i < ha->max_fibre_devices; i++) {
867 			entry = &sns_cmd->p.gid_data[(i * 4) + 16];
868 			list[i].d_id.b.domain = entry[1];
869 			list[i].d_id.b.area = entry[2];
870 			list[i].d_id.b.al_pa = entry[3];
871 
872 			/* Last one exit. */
873 			if (entry[0] & BIT_7) {
874 				list[i].d_id.b.rsvd_1 = entry[0];
875 				break;
876 			}
877 		}
878 
879 		/*
880 		 * If we've used all available slots, then the switch is
881 		 * reporting back more devices that we can handle with this
882 		 * single call.  Return a failed status, and let GA_NXT handle
883 		 * the overload.
884 		 */
885 		if (i == ha->max_fibre_devices)
886 			rval = QLA_FUNCTION_FAILED;
887 	}
888 
889 	return (rval);
890 }
891 
892 /**
893  * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
894  * @ha: HA context
895  * @list: switch info entries to populate
896  *
897  * This command uses the old Exectute SNS Command mailbox routine.
898  *
899  * Returns 0 on success.
900  */
901 static int
902 qla2x00_sns_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
903 {
904 	int		rval = QLA_SUCCESS;
905 	struct qla_hw_data *ha = vha->hw;
906 	uint16_t	i;
907 	struct sns_cmd_pkt	*sns_cmd;
908 
909 	for (i = 0; i < ha->max_fibre_devices; i++) {
910 		/* Issue GPN_ID */
911 		/* Prepare SNS command request. */
912 		sns_cmd = qla2x00_prep_sns_cmd(vha, GPN_ID_CMD,
913 		    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
914 
915 		/* Prepare SNS command arguments -- port_id. */
916 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
917 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
918 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
919 
920 		/* Execute SNS command. */
921 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
922 		    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
923 		if (rval != QLA_SUCCESS) {
924 			/*EMPTY*/
925 			ql_dbg(ql_dbg_disc, vha, 0x2032,
926 			    "GPN_ID Send SNS failed (%d).\n", rval);
927 		} else if (sns_cmd->p.gpn_data[8] != 0x80 ||
928 		    sns_cmd->p.gpn_data[9] != 0x02) {
929 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207e,
930 			    "GPN_ID failed, rejected request, gpn_rsp:\n");
931 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207f,
932 			    sns_cmd->p.gpn_data, 16);
933 			rval = QLA_FUNCTION_FAILED;
934 		} else {
935 			/* Save portname */
936 			memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
937 			    WWN_SIZE);
938 		}
939 
940 		/* Last device exit. */
941 		if (list[i].d_id.b.rsvd_1 != 0)
942 			break;
943 	}
944 
945 	return (rval);
946 }
947 
948 /**
949  * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
950  * @ha: HA context
951  * @list: switch info entries to populate
952  *
953  * This command uses the old Exectute SNS Command mailbox routine.
954  *
955  * Returns 0 on success.
956  */
957 static int
958 qla2x00_sns_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
959 {
960 	int		rval = QLA_SUCCESS;
961 	struct qla_hw_data *ha = vha->hw;
962 	uint16_t	i;
963 	struct sns_cmd_pkt	*sns_cmd;
964 
965 	for (i = 0; i < ha->max_fibre_devices; i++) {
966 		/* Issue GNN_ID */
967 		/* Prepare SNS command request. */
968 		sns_cmd = qla2x00_prep_sns_cmd(vha, GNN_ID_CMD,
969 		    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
970 
971 		/* Prepare SNS command arguments -- port_id. */
972 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
973 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
974 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
975 
976 		/* Execute SNS command. */
977 		rval = qla2x00_send_sns(vha, ha->sns_cmd_dma,
978 		    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
979 		if (rval != QLA_SUCCESS) {
980 			/*EMPTY*/
981 			ql_dbg(ql_dbg_disc, vha, 0x203f,
982 			    "GNN_ID Send SNS failed (%d).\n", rval);
983 		} else if (sns_cmd->p.gnn_data[8] != 0x80 ||
984 		    sns_cmd->p.gnn_data[9] != 0x02) {
985 			ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2082,
986 			    "GNN_ID failed, rejected request, gnn_rsp:\n");
987 			ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207a,
988 			    sns_cmd->p.gnn_data, 16);
989 			rval = QLA_FUNCTION_FAILED;
990 		} else {
991 			/* Save nodename */
992 			memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
993 			    WWN_SIZE);
994 
995 			ql_dbg(ql_dbg_disc, vha, 0x206e,
996 			    "GID_PT entry - nn %02x%02x%02x%02x%02x%02x%02x%02x "
997 			    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
998 			    "port_id=%02x%02x%02x.\n",
999 			    list[i].node_name[0], list[i].node_name[1],
1000 			    list[i].node_name[2], list[i].node_name[3],
1001 			    list[i].node_name[4], list[i].node_name[5],
1002 			    list[i].node_name[6], list[i].node_name[7],
1003 			    list[i].port_name[0], list[i].port_name[1],
1004 			    list[i].port_name[2], list[i].port_name[3],
1005 			    list[i].port_name[4], list[i].port_name[5],
1006 			    list[i].port_name[6], list[i].port_name[7],
1007 			    list[i].d_id.b.domain, list[i].d_id.b.area,
1008 			    list[i].d_id.b.al_pa);
1009 		}
1010 
1011 		/* Last device exit. */
1012 		if (list[i].d_id.b.rsvd_1 != 0)
1013 			break;
1014 	}
1015 
1016 	return (rval);
1017 }
1018 
1019 /**
1020  * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
1021  * @ha: HA context
1022  *
1023  * This command uses the old Exectute SNS Command mailbox routine.
1024  *
1025  * Returns 0 on success.
1026  */
1027 static int
1028 qla2x00_sns_rft_id(scsi_qla_host_t *vha)
1029 {
1030 	int		rval;
1031 	struct qla_hw_data *ha = vha->hw;
1032 	struct sns_cmd_pkt	*sns_cmd;
1033 
1034 	/* Issue RFT_ID. */
1035 	/* Prepare SNS command request. */
1036 	sns_cmd = qla2x00_prep_sns_cmd(vha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
1037 	    RFT_ID_SNS_DATA_SIZE);
1038 
1039 	/* Prepare SNS command arguments -- port_id, FC-4 types */
1040 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1041 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1042 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1043 
1044 	sns_cmd->p.cmd.param[5] = 0x01;			/* FCP-3 */
1045 
1046 	/* Execute SNS command. */
1047 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
1048 	    sizeof(struct sns_cmd_pkt));
1049 	if (rval != QLA_SUCCESS) {
1050 		/*EMPTY*/
1051 		ql_dbg(ql_dbg_disc, vha, 0x2060,
1052 		    "RFT_ID Send SNS failed (%d).\n", rval);
1053 	} else if (sns_cmd->p.rft_data[8] != 0x80 ||
1054 	    sns_cmd->p.rft_data[9] != 0x02) {
1055 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2083,
1056 		    "RFT_ID failed, rejected request rft_rsp:\n");
1057 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2080,
1058 		    sns_cmd->p.rft_data, 16);
1059 		rval = QLA_FUNCTION_FAILED;
1060 	} else {
1061 		ql_dbg(ql_dbg_disc, vha, 0x2073,
1062 		    "RFT_ID exiting normally.\n");
1063 	}
1064 
1065 	return (rval);
1066 }
1067 
1068 /**
1069  * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
1070  * HBA.
1071  * @ha: HA context
1072  *
1073  * This command uses the old Exectute SNS Command mailbox routine.
1074  *
1075  * Returns 0 on success.
1076  */
1077 static int
1078 qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
1079 {
1080 	int		rval;
1081 	struct qla_hw_data *ha = vha->hw;
1082 	struct sns_cmd_pkt	*sns_cmd;
1083 
1084 	/* Issue RNN_ID. */
1085 	/* Prepare SNS command request. */
1086 	sns_cmd = qla2x00_prep_sns_cmd(vha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
1087 	    RNN_ID_SNS_DATA_SIZE);
1088 
1089 	/* Prepare SNS command arguments -- port_id, nodename. */
1090 	sns_cmd->p.cmd.param[0] = vha->d_id.b.al_pa;
1091 	sns_cmd->p.cmd.param[1] = vha->d_id.b.area;
1092 	sns_cmd->p.cmd.param[2] = vha->d_id.b.domain;
1093 
1094 	sns_cmd->p.cmd.param[4] = vha->node_name[7];
1095 	sns_cmd->p.cmd.param[5] = vha->node_name[6];
1096 	sns_cmd->p.cmd.param[6] = vha->node_name[5];
1097 	sns_cmd->p.cmd.param[7] = vha->node_name[4];
1098 	sns_cmd->p.cmd.param[8] = vha->node_name[3];
1099 	sns_cmd->p.cmd.param[9] = vha->node_name[2];
1100 	sns_cmd->p.cmd.param[10] = vha->node_name[1];
1101 	sns_cmd->p.cmd.param[11] = vha->node_name[0];
1102 
1103 	/* Execute SNS command. */
1104 	rval = qla2x00_send_sns(vha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
1105 	    sizeof(struct sns_cmd_pkt));
1106 	if (rval != QLA_SUCCESS) {
1107 		/*EMPTY*/
1108 		ql_dbg(ql_dbg_disc, vha, 0x204a,
1109 		    "RNN_ID Send SNS failed (%d).\n", rval);
1110 	} else if (sns_cmd->p.rnn_data[8] != 0x80 ||
1111 	    sns_cmd->p.rnn_data[9] != 0x02) {
1112 		ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207b,
1113 		    "RNN_ID failed, rejected request, rnn_rsp:\n");
1114 		ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x207c,
1115 		    sns_cmd->p.rnn_data, 16);
1116 		rval = QLA_FUNCTION_FAILED;
1117 	} else {
1118 		ql_dbg(ql_dbg_disc, vha, 0x204c,
1119 		    "RNN_ID exiting normally.\n");
1120 	}
1121 
1122 	return (rval);
1123 }
1124 
1125 /**
1126  * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
1127  * @ha: HA context
1128  *
1129  * Returns 0 on success.
1130  */
1131 static int
1132 qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
1133 {
1134 	int ret, rval;
1135 	uint16_t mb[MAILBOX_REGISTER_COUNT];
1136 	struct qla_hw_data *ha = vha->hw;
1137 	ret = QLA_SUCCESS;
1138 	if (vha->flags.management_server_logged_in)
1139 		return ret;
1140 
1141 	rval = ha->isp_ops->fabric_login(vha, vha->mgmt_svr_loop_id, 0xff, 0xff,
1142 	    0xfa, mb, BIT_1);
1143 	if (rval != QLA_SUCCESS || mb[0] != MBS_COMMAND_COMPLETE) {
1144 		if (rval == QLA_MEMORY_ALLOC_FAILED)
1145 			ql_dbg(ql_dbg_disc, vha, 0x2085,
1146 			    "Failed management_server login: loopid=%x "
1147 			    "rval=%d\n", vha->mgmt_svr_loop_id, rval);
1148 		else
1149 			ql_dbg(ql_dbg_disc, vha, 0x2024,
1150 			    "Failed management_server login: loopid=%x "
1151 			    "mb[0]=%x mb[1]=%x mb[2]=%x mb[6]=%x mb[7]=%x.\n",
1152 			    vha->mgmt_svr_loop_id, mb[0], mb[1], mb[2], mb[6],
1153 			    mb[7]);
1154 		ret = QLA_FUNCTION_FAILED;
1155 	} else
1156 		vha->flags.management_server_logged_in = 1;
1157 
1158 	return ret;
1159 }
1160 
1161 /**
1162  * qla2x00_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1163  * @ha: HA context
1164  * @req_size: request size in bytes
1165  * @rsp_size: response size in bytes
1166  *
1167  * Returns a pointer to the @ha's ms_iocb.
1168  */
1169 void *
1170 qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1171     uint32_t rsp_size)
1172 {
1173 	ms_iocb_entry_t *ms_pkt;
1174 	struct qla_hw_data *ha = vha->hw;
1175 	ms_pkt = ha->ms_iocb;
1176 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
1177 
1178 	ms_pkt->entry_type = MS_IOCB_TYPE;
1179 	ms_pkt->entry_count = 1;
1180 	SET_TARGET_ID(ha, ms_pkt->loop_id, vha->mgmt_svr_loop_id);
1181 	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
1182 	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1183 	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1184 	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
1185 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
1186 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
1187 
1188 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1189 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1190 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1191 
1192 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1193 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1194 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
1195 
1196 	return ms_pkt;
1197 }
1198 
1199 /**
1200  * qla24xx_prep_ms_fdmi_iocb() - Prepare common MS IOCB fields for FDMI query.
1201  * @ha: HA context
1202  * @req_size: request size in bytes
1203  * @rsp_size: response size in bytes
1204  *
1205  * Returns a pointer to the @ha's ms_iocb.
1206  */
1207 void *
1208 qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1209     uint32_t rsp_size)
1210 {
1211 	struct ct_entry_24xx *ct_pkt;
1212 	struct qla_hw_data *ha = vha->hw;
1213 
1214 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1215 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1216 
1217 	ct_pkt->entry_type = CT_IOCB_TYPE;
1218 	ct_pkt->entry_count = 1;
1219 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1220 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1221 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1222 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
1223 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1224 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1225 
1226 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1227 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1228 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1229 
1230 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1231 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1232 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1233 	ct_pkt->vp_index = vha->vp_idx;
1234 
1235 	return ct_pkt;
1236 }
1237 
1238 static inline ms_iocb_entry_t *
1239 qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
1240 {
1241 	struct qla_hw_data *ha = vha->hw;
1242 	ms_iocb_entry_t *ms_pkt = ha->ms_iocb;
1243 	struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1244 
1245 	if (IS_FWI2_CAPABLE(ha)) {
1246 		ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1247 		ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1248 	} else {
1249 		ms_pkt->req_bytecount = cpu_to_le32(req_size);
1250 		ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
1251 	}
1252 
1253 	return ms_pkt;
1254 }
1255 
1256 /**
1257  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
1258  * @ct_req: CT request buffer
1259  * @cmd: GS command
1260  * @rsp_size: response size in bytes
1261  *
1262  * Returns a pointer to the intitialized @ct_req.
1263  */
1264 static inline struct ct_sns_req *
1265 qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd,
1266     uint16_t rsp_size)
1267 {
1268 	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
1269 
1270 	ct_req->header.revision = 0x01;
1271 	ct_req->header.gs_type = 0xFA;
1272 	ct_req->header.gs_subtype = 0x10;
1273 	ct_req->command = cpu_to_be16(cmd);
1274 	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1275 
1276 	return ct_req;
1277 }
1278 
1279 /**
1280  * qla2x00_fdmi_rhba() -
1281  * @ha: HA context
1282  *
1283  * Returns 0 on success.
1284  */
1285 static int
1286 qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
1287 {
1288 	int rval, alen;
1289 	uint32_t size, sn;
1290 
1291 	ms_iocb_entry_t *ms_pkt;
1292 	struct ct_sns_req *ct_req;
1293 	struct ct_sns_rsp *ct_rsp;
1294 	uint8_t *entries;
1295 	struct ct_fdmi_hba_attr *eiter;
1296 	struct qla_hw_data *ha = vha->hw;
1297 
1298 	/* Issue RHBA */
1299 	/* Prepare common MS IOCB */
1300 	/*   Request size adjusted after CT preparation */
1301 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
1302 
1303 	/* Prepare CT request */
1304 	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD,
1305 	    RHBA_RSP_SIZE);
1306 	ct_rsp = &ha->ct_sns->p.rsp;
1307 
1308 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1309 	memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE);
1310 	ct_req->req.rhba.entry_count = __constant_cpu_to_be32(1);
1311 	memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE);
1312 	size = 2 * WWN_SIZE + 4 + 4;
1313 
1314 	/* Attributes */
1315 	ct_req->req.rhba.attrs.count =
1316 	    __constant_cpu_to_be32(FDMI_HBA_ATTR_COUNT);
1317 	entries = ct_req->req.rhba.hba_identifier;
1318 
1319 	/* Nodename. */
1320 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1321 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_NODE_NAME);
1322 	eiter->len = __constant_cpu_to_be16(4 + WWN_SIZE);
1323 	memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
1324 	size += 4 + WWN_SIZE;
1325 
1326 	ql_dbg(ql_dbg_disc, vha, 0x2025,
1327 	    "NodeName = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
1328 	    eiter->a.node_name[0], eiter->a.node_name[1],
1329 	    eiter->a.node_name[2], eiter->a.node_name[3],
1330 	    eiter->a.node_name[4], eiter->a.node_name[5],
1331 	    eiter->a.node_name[6], eiter->a.node_name[7]);
1332 
1333 	/* Manufacturer. */
1334 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1335 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MANUFACTURER);
1336 	alen = strlen(QLA2XXX_MANUFACTURER);
1337 	strncpy(eiter->a.manufacturer, QLA2XXX_MANUFACTURER, alen + 1);
1338 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1339 	eiter->len = cpu_to_be16(4 + alen);
1340 	size += 4 + alen;
1341 
1342 	ql_dbg(ql_dbg_disc, vha, 0x2026,
1343 	    "Manufacturer = %s.\n", eiter->a.manufacturer);
1344 
1345 	/* Serial number. */
1346 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1347 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
1348 	sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
1349 	sprintf(eiter->a.serial_num, "%c%05d", 'A' + sn / 100000, sn % 100000);
1350 	alen = strlen(eiter->a.serial_num);
1351 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1352 	eiter->len = cpu_to_be16(4 + alen);
1353 	size += 4 + alen;
1354 
1355 	ql_dbg(ql_dbg_disc, vha, 0x2027,
1356 	    "Serial no. = %s.\n", eiter->a.serial_num);
1357 
1358 	/* Model name. */
1359 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1360 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL);
1361 	strcpy(eiter->a.model, ha->model_number);
1362 	alen = strlen(eiter->a.model);
1363 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1364 	eiter->len = cpu_to_be16(4 + alen);
1365 	size += 4 + alen;
1366 
1367 	ql_dbg(ql_dbg_disc, vha, 0x2028,
1368 	    "Model Name = %s.\n", eiter->a.model);
1369 
1370 	/* Model description. */
1371 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1372 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
1373 	if (ha->model_desc)
1374 		strncpy(eiter->a.model_desc, ha->model_desc, 80);
1375 	alen = strlen(eiter->a.model_desc);
1376 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1377 	eiter->len = cpu_to_be16(4 + alen);
1378 	size += 4 + alen;
1379 
1380 	ql_dbg(ql_dbg_disc, vha, 0x2029,
1381 	    "Model Desc = %s.\n", eiter->a.model_desc);
1382 
1383 	/* Hardware version. */
1384 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1385 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
1386 	strcpy(eiter->a.hw_version, ha->adapter_id);
1387 	alen = strlen(eiter->a.hw_version);
1388 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1389 	eiter->len = cpu_to_be16(4 + alen);
1390 	size += 4 + alen;
1391 
1392 	ql_dbg(ql_dbg_disc, vha, 0x202a,
1393 	    "Hardware ver = %s.\n", eiter->a.hw_version);
1394 
1395 	/* Driver version. */
1396 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1397 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
1398 	strcpy(eiter->a.driver_version, qla2x00_version_str);
1399 	alen = strlen(eiter->a.driver_version);
1400 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1401 	eiter->len = cpu_to_be16(4 + alen);
1402 	size += 4 + alen;
1403 
1404 	ql_dbg(ql_dbg_disc, vha, 0x202b,
1405 	    "Driver ver = %s.\n", eiter->a.driver_version);
1406 
1407 	/* Option ROM version. */
1408 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1409 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
1410 	strcpy(eiter->a.orom_version, "0.00");
1411 	alen = strlen(eiter->a.orom_version);
1412 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1413 	eiter->len = cpu_to_be16(4 + alen);
1414 	size += 4 + alen;
1415 
1416 	ql_dbg(ql_dbg_disc, vha , 0x202c,
1417 	    "Optrom vers = %s.\n", eiter->a.orom_version);
1418 
1419 	/* Firmware version */
1420 	eiter = (struct ct_fdmi_hba_attr *) (entries + size);
1421 	eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
1422 	ha->isp_ops->fw_version_str(vha, eiter->a.fw_version);
1423 	alen = strlen(eiter->a.fw_version);
1424 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1425 	eiter->len = cpu_to_be16(4 + alen);
1426 	size += 4 + alen;
1427 
1428 	ql_dbg(ql_dbg_disc, vha, 0x202d,
1429 	    "Firmware vers = %s.\n", eiter->a.fw_version);
1430 
1431 	/* Update MS request size. */
1432 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1433 
1434 	ql_dbg(ql_dbg_disc, vha, 0x202e,
1435 	    "RHBA identifier = "
1436 	    "%02x%02x%02x%02x%02x%02x%02x%02x size=%d.\n",
1437 	    ct_req->req.rhba.hba_identifier[0],
1438 	    ct_req->req.rhba.hba_identifier[1],
1439 	    ct_req->req.rhba.hba_identifier[2],
1440 	    ct_req->req.rhba.hba_identifier[3],
1441 	    ct_req->req.rhba.hba_identifier[4],
1442 	    ct_req->req.rhba.hba_identifier[5],
1443 	    ct_req->req.rhba.hba_identifier[6],
1444 	    ct_req->req.rhba.hba_identifier[7], size);
1445 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
1446 	    entries, size);
1447 
1448 	/* Execute MS IOCB */
1449 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1450 	    sizeof(ms_iocb_entry_t));
1451 	if (rval != QLA_SUCCESS) {
1452 		/*EMPTY*/
1453 		ql_dbg(ql_dbg_disc, vha, 0x2030,
1454 		    "RHBA issue IOCB failed (%d).\n", rval);
1455 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
1456 	    QLA_SUCCESS) {
1457 		rval = QLA_FUNCTION_FAILED;
1458 		if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
1459 		    ct_rsp->header.explanation_code ==
1460 		    CT_EXPL_ALREADY_REGISTERED) {
1461 			ql_dbg(ql_dbg_disc, vha, 0x2034,
1462 			    "HBA already registered.\n");
1463 			rval = QLA_ALREADY_REGISTERED;
1464 		}
1465 	} else {
1466 		ql_dbg(ql_dbg_disc, vha, 0x2035,
1467 		    "RHBA exiting normally.\n");
1468 	}
1469 
1470 	return rval;
1471 }
1472 
1473 /**
1474  * qla2x00_fdmi_dhba() -
1475  * @ha: HA context
1476  *
1477  * Returns 0 on success.
1478  */
1479 static int
1480 qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
1481 {
1482 	int rval;
1483 	struct qla_hw_data *ha = vha->hw;
1484 	ms_iocb_entry_t *ms_pkt;
1485 	struct ct_sns_req *ct_req;
1486 	struct ct_sns_rsp *ct_rsp;
1487 
1488 	/* Issue RPA */
1489 	/* Prepare common MS IOCB */
1490 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
1491 	    DHBA_RSP_SIZE);
1492 
1493 	/* Prepare CT request */
1494 	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD,
1495 	    DHBA_RSP_SIZE);
1496 	ct_rsp = &ha->ct_sns->p.rsp;
1497 
1498 	/* Prepare FDMI command arguments -- portname. */
1499 	memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
1500 
1501 	ql_dbg(ql_dbg_disc, vha, 0x2036,
1502 	    "DHBA portname = %02x%02x%02x%02x%02x%02x%02x%02x.\n",
1503 	    ct_req->req.dhba.port_name[0], ct_req->req.dhba.port_name[1],
1504 	    ct_req->req.dhba.port_name[2], ct_req->req.dhba.port_name[3],
1505 	    ct_req->req.dhba.port_name[4], ct_req->req.dhba.port_name[5],
1506 	    ct_req->req.dhba.port_name[6], ct_req->req.dhba.port_name[7]);
1507 
1508 	/* Execute MS IOCB */
1509 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1510 	    sizeof(ms_iocb_entry_t));
1511 	if (rval != QLA_SUCCESS) {
1512 		/*EMPTY*/
1513 		ql_dbg(ql_dbg_disc, vha, 0x2037,
1514 		    "DHBA issue IOCB failed (%d).\n", rval);
1515 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "DHBA") !=
1516 	    QLA_SUCCESS) {
1517 		rval = QLA_FUNCTION_FAILED;
1518 	} else {
1519 		ql_dbg(ql_dbg_disc, vha, 0x2038,
1520 		    "DHBA exiting normally.\n");
1521 	}
1522 
1523 	return rval;
1524 }
1525 
1526 /**
1527  * qla2x00_fdmi_rpa() -
1528  * @ha: HA context
1529  *
1530  * Returns 0 on success.
1531  */
1532 static int
1533 qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
1534 {
1535 	int rval, alen;
1536 	uint32_t size, max_frame_size;
1537 	struct qla_hw_data *ha = vha->hw;
1538 	ms_iocb_entry_t *ms_pkt;
1539 	struct ct_sns_req *ct_req;
1540 	struct ct_sns_rsp *ct_rsp;
1541 	uint8_t *entries;
1542 	struct ct_fdmi_port_attr *eiter;
1543 	struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
1544 
1545 	/* Issue RPA */
1546 	/* Prepare common MS IOCB */
1547 	/*   Request size adjusted after CT preparation */
1548 	ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
1549 
1550 	/* Prepare CT request */
1551 	ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD,
1552 	    RPA_RSP_SIZE);
1553 	ct_rsp = &ha->ct_sns->p.rsp;
1554 
1555 	/* Prepare FDMI command arguments -- attribute block, attributes. */
1556 	memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
1557 	size = WWN_SIZE + 4;
1558 
1559 	/* Attributes */
1560 	ct_req->req.rpa.attrs.count =
1561 	    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT - 1);
1562 	entries = ct_req->req.rpa.port_name;
1563 
1564 	/* FC4 types. */
1565 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1566 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_FC4_TYPES);
1567 	eiter->len = __constant_cpu_to_be16(4 + 32);
1568 	eiter->a.fc4_types[2] = 0x01;
1569 	size += 4 + 32;
1570 
1571 	ql_dbg(ql_dbg_disc, vha, 0x2039,
1572 	    "FC4_TYPES=%02x %02x.\n",
1573 	    eiter->a.fc4_types[2],
1574 	    eiter->a.fc4_types[1]);
1575 
1576 	/* Supported speed. */
1577 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1578 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
1579 	eiter->len = __constant_cpu_to_be16(4 + 4);
1580 	if (IS_CNA_CAPABLE(ha))
1581 		eiter->a.sup_speed = __constant_cpu_to_be32(
1582 		    FDMI_PORT_SPEED_10GB);
1583 	else if (IS_QLA25XX(ha))
1584 		eiter->a.sup_speed = __constant_cpu_to_be32(
1585 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1586 		    FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
1587 	else if (IS_QLA24XX_TYPE(ha))
1588 		eiter->a.sup_speed = __constant_cpu_to_be32(
1589 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
1590 		    FDMI_PORT_SPEED_4GB);
1591 	else if (IS_QLA23XX(ha))
1592 		eiter->a.sup_speed =__constant_cpu_to_be32(
1593 		    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB);
1594 	else
1595 		eiter->a.sup_speed = __constant_cpu_to_be32(
1596 		    FDMI_PORT_SPEED_1GB);
1597 	size += 4 + 4;
1598 
1599 	ql_dbg(ql_dbg_disc, vha, 0x203a,
1600 	    "Supported_Speed=%x.\n", eiter->a.sup_speed);
1601 
1602 	/* Current speed. */
1603 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1604 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
1605 	eiter->len = __constant_cpu_to_be16(4 + 4);
1606 	switch (ha->link_data_rate) {
1607 	case PORT_SPEED_1GB:
1608 		eiter->a.cur_speed =
1609 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_1GB);
1610 		break;
1611 	case PORT_SPEED_2GB:
1612 		eiter->a.cur_speed =
1613 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_2GB);
1614 		break;
1615 	case PORT_SPEED_4GB:
1616 		eiter->a.cur_speed =
1617 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_4GB);
1618 		break;
1619 	case PORT_SPEED_8GB:
1620 		eiter->a.cur_speed =
1621 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_8GB);
1622 		break;
1623 	case PORT_SPEED_10GB:
1624 		eiter->a.cur_speed =
1625 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_10GB);
1626 		break;
1627 	case PORT_SPEED_16GB:
1628 		eiter->a.cur_speed =
1629 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_16GB);
1630 		break;
1631 	default:
1632 		eiter->a.cur_speed =
1633 		    __constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
1634 		break;
1635 	}
1636 	size += 4 + 4;
1637 
1638 	ql_dbg(ql_dbg_disc, vha, 0x203b,
1639 	    "Current_Speed=%x.\n", eiter->a.cur_speed);
1640 
1641 	/* Max frame size. */
1642 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1643 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
1644 	eiter->len = __constant_cpu_to_be16(4 + 4);
1645 	max_frame_size = IS_FWI2_CAPABLE(ha) ?
1646 	    le16_to_cpu(icb24->frame_payload_size):
1647 	    le16_to_cpu(ha->init_cb->frame_payload_size);
1648 	eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
1649 	size += 4 + 4;
1650 
1651 	ql_dbg(ql_dbg_disc, vha, 0x203c,
1652 	    "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
1653 
1654 	/* OS device name. */
1655 	eiter = (struct ct_fdmi_port_attr *) (entries + size);
1656 	eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
1657 	alen = strlen(QLA2XXX_DRIVER_NAME);
1658 	strncpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME, alen + 1);
1659 	alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1660 	eiter->len = cpu_to_be16(4 + alen);
1661 	size += 4 + alen;
1662 
1663 	ql_dbg(ql_dbg_disc, vha, 0x204b,
1664 	    "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
1665 
1666 	/* Hostname. */
1667 	if (strlen(fc_host_system_hostname(vha->host))) {
1668 		ct_req->req.rpa.attrs.count =
1669 		    __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT);
1670 		eiter = (struct ct_fdmi_port_attr *) (entries + size);
1671 		eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME);
1672 		snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
1673 		    "%s", fc_host_system_hostname(vha->host));
1674 		alen = strlen(eiter->a.host_name);
1675 		alen += (alen & 3) ? (4 - (alen & 3)) : 4;
1676 		eiter->len = cpu_to_be16(4 + alen);
1677 		size += 4 + alen;
1678 
1679 		ql_dbg(ql_dbg_disc, vha, 0x203d,
1680 		    "HostName=%s.\n", eiter->a.host_name);
1681 	}
1682 
1683 	/* Update MS request size. */
1684 	qla2x00_update_ms_fdmi_iocb(vha, size + 16);
1685 
1686 	ql_dbg(ql_dbg_disc, vha, 0x203e,
1687 	    "RPA portname= %02x%02x%02x%02x%02X%02x%02x%02x size=%d.\n",
1688 	    ct_req->req.rpa.port_name[0], ct_req->req.rpa.port_name[1],
1689 	    ct_req->req.rpa.port_name[2], ct_req->req.rpa.port_name[3],
1690 	    ct_req->req.rpa.port_name[4], ct_req->req.rpa.port_name[5],
1691 	    ct_req->req.rpa.port_name[6], ct_req->req.rpa.port_name[7],
1692 	    size);
1693 	ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
1694 	    entries, size);
1695 
1696 	/* Execute MS IOCB */
1697 	rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1698 	    sizeof(ms_iocb_entry_t));
1699 	if (rval != QLA_SUCCESS) {
1700 		/*EMPTY*/
1701 		ql_dbg(ql_dbg_disc, vha, 0x2040,
1702 		    "RPA issue IOCB failed (%d).\n", rval);
1703 	} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
1704 	    QLA_SUCCESS) {
1705 		rval = QLA_FUNCTION_FAILED;
1706 	} else {
1707 		ql_dbg(ql_dbg_disc, vha, 0x2041,
1708 		    "RPA exiting nornally.\n");
1709 	}
1710 
1711 	return rval;
1712 }
1713 
1714 /**
1715  * qla2x00_fdmi_register() -
1716  * @ha: HA context
1717  *
1718  * Returns 0 on success.
1719  */
1720 int
1721 qla2x00_fdmi_register(scsi_qla_host_t *vha)
1722 {
1723 	int rval;
1724        struct qla_hw_data *ha = vha->hw;
1725 
1726 	if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
1727 	    IS_QLAFX00(ha))
1728 		return QLA_FUNCTION_FAILED;
1729 
1730 	rval = qla2x00_mgmt_svr_login(vha);
1731 	if (rval)
1732 		return rval;
1733 
1734 	rval = qla2x00_fdmi_rhba(vha);
1735 	if (rval) {
1736 		if (rval != QLA_ALREADY_REGISTERED)
1737 			return rval;
1738 
1739 		rval = qla2x00_fdmi_dhba(vha);
1740 		if (rval)
1741 			return rval;
1742 
1743 		rval = qla2x00_fdmi_rhba(vha);
1744 		if (rval)
1745 			return rval;
1746 	}
1747 	rval = qla2x00_fdmi_rpa(vha);
1748 
1749 	return rval;
1750 }
1751 
1752 /**
1753  * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query.
1754  * @ha: HA context
1755  * @list: switch info entries to populate
1756  *
1757  * Returns 0 on success.
1758  */
1759 int
1760 qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
1761 {
1762 	int		rval = QLA_SUCCESS;
1763 	uint16_t	i;
1764 	struct qla_hw_data *ha = vha->hw;
1765 	ms_iocb_entry_t	*ms_pkt;
1766 	struct ct_sns_req	*ct_req;
1767 	struct ct_sns_rsp	*ct_rsp;
1768 
1769 	if (!IS_IIDMA_CAPABLE(ha))
1770 		return QLA_FUNCTION_FAILED;
1771 
1772 	for (i = 0; i < ha->max_fibre_devices; i++) {
1773 		/* Issue GFPN_ID */
1774 		/* Prepare common MS IOCB */
1775 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
1776 		    GFPN_ID_RSP_SIZE);
1777 
1778 		/* Prepare CT request */
1779 		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFPN_ID_CMD,
1780 		    GFPN_ID_RSP_SIZE);
1781 		ct_rsp = &ha->ct_sns->p.rsp;
1782 
1783 		/* Prepare CT arguments -- port_id */
1784 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
1785 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
1786 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
1787 
1788 		/* Execute MS IOCB */
1789 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1790 		    sizeof(ms_iocb_entry_t));
1791 		if (rval != QLA_SUCCESS) {
1792 			/*EMPTY*/
1793 			ql_dbg(ql_dbg_disc, vha, 0x2023,
1794 			    "GFPN_ID issue IOCB failed (%d).\n", rval);
1795 			break;
1796 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
1797 		    "GFPN_ID") != QLA_SUCCESS) {
1798 			rval = QLA_FUNCTION_FAILED;
1799 			break;
1800 		} else {
1801 			/* Save fabric portname */
1802 			memcpy(list[i].fabric_port_name,
1803 			    ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE);
1804 		}
1805 
1806 		/* Last device exit. */
1807 		if (list[i].d_id.b.rsvd_1 != 0)
1808 			break;
1809 	}
1810 
1811 	return (rval);
1812 }
1813 
1814 static inline void *
1815 qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
1816     uint32_t rsp_size)
1817 {
1818 	struct ct_entry_24xx *ct_pkt;
1819 	struct qla_hw_data *ha = vha->hw;
1820 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
1821 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
1822 
1823 	ct_pkt->entry_type = CT_IOCB_TYPE;
1824 	ct_pkt->entry_count = 1;
1825 	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
1826 	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
1827 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
1828 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
1829 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
1830 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
1831 
1832 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1833 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1834 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
1835 
1836 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
1837 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
1838 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
1839 	ct_pkt->vp_index = vha->vp_idx;
1840 
1841 	return ct_pkt;
1842 }
1843 
1844 
1845 static inline struct ct_sns_req *
1846 qla24xx_prep_ct_fm_req(struct ct_sns_req *ct_req, uint16_t cmd,
1847     uint16_t rsp_size)
1848 {
1849 	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
1850 
1851 	ct_req->header.revision = 0x01;
1852 	ct_req->header.gs_type = 0xFA;
1853 	ct_req->header.gs_subtype = 0x01;
1854 	ct_req->command = cpu_to_be16(cmd);
1855 	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
1856 
1857 	return ct_req;
1858 }
1859 
1860 /**
1861  * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
1862  * @ha: HA context
1863  * @list: switch info entries to populate
1864  *
1865  * Returns 0 on success.
1866  */
1867 int
1868 qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
1869 {
1870 	int		rval;
1871 	uint16_t	i;
1872 	struct qla_hw_data *ha = vha->hw;
1873 	ms_iocb_entry_t	*ms_pkt;
1874 	struct ct_sns_req	*ct_req;
1875 	struct ct_sns_rsp	*ct_rsp;
1876 
1877 	if (!IS_IIDMA_CAPABLE(ha))
1878 		return QLA_FUNCTION_FAILED;
1879 	if (!ha->flags.gpsc_supported)
1880 		return QLA_FUNCTION_FAILED;
1881 
1882 	rval = qla2x00_mgmt_svr_login(vha);
1883 	if (rval)
1884 		return rval;
1885 
1886 	for (i = 0; i < ha->max_fibre_devices; i++) {
1887 		/* Issue GFPN_ID */
1888 		/* Prepare common MS IOCB */
1889 		ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
1890 		    GPSC_RSP_SIZE);
1891 
1892 		/* Prepare CT request */
1893 		ct_req = qla24xx_prep_ct_fm_req(&ha->ct_sns->p.req,
1894 		    GPSC_CMD, GPSC_RSP_SIZE);
1895 		ct_rsp = &ha->ct_sns->p.rsp;
1896 
1897 		/* Prepare CT arguments -- port_name */
1898 		memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name,
1899 		    WWN_SIZE);
1900 
1901 		/* Execute MS IOCB */
1902 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
1903 		    sizeof(ms_iocb_entry_t));
1904 		if (rval != QLA_SUCCESS) {
1905 			/*EMPTY*/
1906 			ql_dbg(ql_dbg_disc, vha, 0x2059,
1907 			    "GPSC issue IOCB failed (%d).\n", rval);
1908 		} else if ((rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
1909 		    "GPSC")) != QLA_SUCCESS) {
1910 			/* FM command unsupported? */
1911 			if (rval == QLA_INVALID_COMMAND &&
1912 			    (ct_rsp->header.reason_code ==
1913 				CT_REASON_INVALID_COMMAND_CODE ||
1914 			     ct_rsp->header.reason_code ==
1915 				CT_REASON_COMMAND_UNSUPPORTED)) {
1916 				ql_dbg(ql_dbg_disc, vha, 0x205a,
1917 				    "GPSC command unsupported, disabling "
1918 				    "query.\n");
1919 				ha->flags.gpsc_supported = 0;
1920 				rval = QLA_FUNCTION_FAILED;
1921 				break;
1922 			}
1923 			rval = QLA_FUNCTION_FAILED;
1924 		} else {
1925 			/* Save port-speed */
1926 			switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
1927 			case BIT_15:
1928 				list[i].fp_speed = PORT_SPEED_1GB;
1929 				break;
1930 			case BIT_14:
1931 				list[i].fp_speed = PORT_SPEED_2GB;
1932 				break;
1933 			case BIT_13:
1934 				list[i].fp_speed = PORT_SPEED_4GB;
1935 				break;
1936 			case BIT_12:
1937 				list[i].fp_speed = PORT_SPEED_10GB;
1938 				break;
1939 			case BIT_11:
1940 				list[i].fp_speed = PORT_SPEED_8GB;
1941 				break;
1942 			case BIT_10:
1943 				list[i].fp_speed = PORT_SPEED_16GB;
1944 				break;
1945 			}
1946 
1947 			ql_dbg(ql_dbg_disc, vha, 0x205b,
1948 			    "GPSC ext entry - fpn "
1949 			    "%02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x "
1950 			    "speed=%04x.\n",
1951 			    list[i].fabric_port_name[0],
1952 			    list[i].fabric_port_name[1],
1953 			    list[i].fabric_port_name[2],
1954 			    list[i].fabric_port_name[3],
1955 			    list[i].fabric_port_name[4],
1956 			    list[i].fabric_port_name[5],
1957 			    list[i].fabric_port_name[6],
1958 			    list[i].fabric_port_name[7],
1959 			    be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
1960 			    be16_to_cpu(ct_rsp->rsp.gpsc.speed));
1961 		}
1962 
1963 		/* Last device exit. */
1964 		if (list[i].d_id.b.rsvd_1 != 0)
1965 			break;
1966 	}
1967 
1968 	return (rval);
1969 }
1970 
1971 /**
1972  * qla2x00_gff_id() - SNS Get FC-4 Features (GFF_ID) query.
1973  *
1974  * @ha: HA context
1975  * @list: switch info entries to populate
1976  *
1977  */
1978 void
1979 qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
1980 {
1981 	int		rval;
1982 	uint16_t	i;
1983 
1984 	ms_iocb_entry_t	*ms_pkt;
1985 	struct ct_sns_req	*ct_req;
1986 	struct ct_sns_rsp	*ct_rsp;
1987 	struct qla_hw_data *ha = vha->hw;
1988 	uint8_t fcp_scsi_features = 0;
1989 
1990 	for (i = 0; i < ha->max_fibre_devices; i++) {
1991 		/* Set default FC4 Type as UNKNOWN so the default is to
1992 		 * Process this port */
1993 		list[i].fc4_type = FC4_TYPE_UNKNOWN;
1994 
1995 		/* Do not attempt GFF_ID if we are not FWI_2 capable */
1996 		if (!IS_FWI2_CAPABLE(ha))
1997 			continue;
1998 
1999 		/* Prepare common MS IOCB */
2000 		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
2001 		    GFF_ID_RSP_SIZE);
2002 
2003 		/* Prepare CT request */
2004 		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFF_ID_CMD,
2005 		    GFF_ID_RSP_SIZE);
2006 		ct_rsp = &ha->ct_sns->p.rsp;
2007 
2008 		/* Prepare CT arguments -- port_id */
2009 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
2010 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
2011 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
2012 
2013 		/* Execute MS IOCB */
2014 		rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
2015 		   sizeof(ms_iocb_entry_t));
2016 
2017 		if (rval != QLA_SUCCESS) {
2018 			ql_dbg(ql_dbg_disc, vha, 0x205c,
2019 			    "GFF_ID issue IOCB failed (%d).\n", rval);
2020 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
2021 			       "GFF_ID") != QLA_SUCCESS) {
2022 			ql_dbg(ql_dbg_disc, vha, 0x205d,
2023 			    "GFF_ID IOCB status had a failure status code.\n");
2024 		} else {
2025 			fcp_scsi_features =
2026 			   ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
2027 			fcp_scsi_features &= 0x0f;
2028 
2029 			if (fcp_scsi_features)
2030 				list[i].fc4_type = FC4_TYPE_FCP_SCSI;
2031 			else
2032 				list[i].fc4_type = FC4_TYPE_OTHER;
2033 		}
2034 
2035 		/* Last device exit. */
2036 		if (list[i].d_id.b.rsvd_1 != 0)
2037 			break;
2038 	}
2039 }
2040