xref: /linux/drivers/scsi/qla2xxx/qla_gs.c (revision 13abf8130139c2ccd4962a7e5a8902be5e6cb5a7)
1 /*
2  *                  QLOGIC LINUX SOFTWARE
3  *
4  * QLogic ISP2x00 device driver for Linux 2.6.x
5  * Copyright (C) 2003-2005 QLogic Corporation
6  * (www.qlogic.com)
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2, or (at your option) any
11  * later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  */
19 #include "qla_def.h"
20 
21 static inline struct ct_sns_req *
22 qla2x00_prep_ct_req(struct ct_sns_req *, uint16_t, uint16_t);
23 
24 static inline struct sns_cmd_pkt *
25 qla2x00_prep_sns_cmd(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
26 
27 static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
28 static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
29 static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
30 static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);
31 static int qla2x00_sns_rft_id(scsi_qla_host_t *);
32 static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
33 
34 /**
35  * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
36  * @ha: HA context
37  * @req_size: request size in bytes
38  * @rsp_size: response size in bytes
39  *
40  * Returns a pointer to the @ha's ms_iocb.
41  */
42 void *
43 qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size)
44 {
45 	ms_iocb_entry_t *ms_pkt;
46 
47 	ms_pkt = ha->ms_iocb;
48 	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
49 
50 	ms_pkt->entry_type = MS_IOCB_TYPE;
51 	ms_pkt->entry_count = 1;
52 	SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
53 	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
54 	ms_pkt->timeout = __constant_cpu_to_le16(25);
55 	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
56 	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
57 	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
58 	ms_pkt->req_bytecount = cpu_to_le32(req_size);
59 
60 	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
61 	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
62 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
63 
64 	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
65 	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
66 	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
67 
68 	return (ms_pkt);
69 }
70 
71 /**
72  * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query.
73  * @ha: HA context
74  * @req_size: request size in bytes
75  * @rsp_size: response size in bytes
76  *
77  * Returns a pointer to the @ha's ms_iocb.
78  */
79 void *
80 qla24xx_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size)
81 {
82 	struct ct_entry_24xx *ct_pkt;
83 
84 	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
85 	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
86 
87 	ct_pkt->entry_type = CT_IOCB_TYPE;
88 	ct_pkt->entry_count = 1;
89 	ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS);
90 	ct_pkt->timeout = __constant_cpu_to_le16(25);
91 	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
92 	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
93 	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
94 	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
95 
96 	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
97 	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
98 	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
99 
100 	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
101 	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
102 	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
103 
104 	return (ct_pkt);
105 }
106 
107 /**
108  * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query.
109  * @ct_req: CT request buffer
110  * @cmd: GS command
111  * @rsp_size: response size in bytes
112  *
113  * Returns a pointer to the intitialized @ct_req.
114  */
115 static inline struct ct_sns_req *
116 qla2x00_prep_ct_req(struct ct_sns_req *ct_req, uint16_t cmd, uint16_t rsp_size)
117 {
118 	memset(ct_req, 0, sizeof(struct ct_sns_pkt));
119 
120 	ct_req->header.revision = 0x01;
121 	ct_req->header.gs_type = 0xFC;
122 	ct_req->header.gs_subtype = 0x02;
123 	ct_req->command = cpu_to_be16(cmd);
124 	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);
125 
126 	return (ct_req);
127 }
128 
129 static int
130 qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt,
131     struct ct_sns_rsp *ct_rsp, const char *routine)
132 {
133 	int rval;
134 	uint16_t comp_status;
135 
136 	rval = QLA_FUNCTION_FAILED;
137 	if (ms_pkt->entry_status != 0) {
138 		DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n",
139 		    ha->host_no, routine, ms_pkt->entry_status));
140 	} else {
141 		if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
142 			comp_status =
143 			    ((struct ct_entry_24xx *)ms_pkt)->comp_status;
144 		else
145 			comp_status = le16_to_cpu(ms_pkt->status);
146 		switch (comp_status) {
147 		case CS_COMPLETE:
148 		case CS_DATA_UNDERRUN:
149 		case CS_DATA_OVERRUN:		/* Overrun? */
150 			if (ct_rsp->header.response !=
151 			    __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
152 				DEBUG2_3(printk("scsi(%ld): %s failed, "
153 				    "rejected request:\n", ha->host_no,
154 				    routine));
155 				DEBUG2_3(qla2x00_dump_buffer(
156 				    (uint8_t *)&ct_rsp->header,
157 				    sizeof(struct ct_rsp_hdr)));
158 			} else
159 				rval = QLA_SUCCESS;
160 			break;
161 		default:
162 			DEBUG2_3(printk("scsi(%ld): %s failed, completion "
163 			    "status (%x).\n", ha->host_no, routine,
164 			    comp_status));
165 			break;
166 		}
167 	}
168 	return rval;
169 }
170 
171 /**
172  * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
173  * @ha: HA context
174  * @fcport: fcport entry to updated
175  *
176  * Returns 0 on success.
177  */
178 int
179 qla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport)
180 {
181 	int		rval;
182 
183 	ms_iocb_entry_t	*ms_pkt;
184 	struct ct_sns_req	*ct_req;
185 	struct ct_sns_rsp	*ct_rsp;
186 
187 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
188 		return (qla2x00_sns_ga_nxt(ha, fcport));
189 	}
190 
191 	/* Issue GA_NXT */
192 	/* Prepare common MS IOCB */
193 	ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GA_NXT_REQ_SIZE, GA_NXT_RSP_SIZE);
194 
195 	/* Prepare CT request */
196 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD,
197 	    GA_NXT_RSP_SIZE);
198 	ct_rsp = &ha->ct_sns->p.rsp;
199 
200 	/* Prepare CT arguments -- port_id */
201 	ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
202 	ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
203 	ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
204 
205 	/* Execute MS IOCB */
206 	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
207 	    sizeof(ms_iocb_entry_t));
208 	if (rval != QLA_SUCCESS) {
209 		/*EMPTY*/
210 		DEBUG2_3(printk("scsi(%ld): GA_NXT issue IOCB failed (%d).\n",
211 		    ha->host_no, rval));
212 	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "GA_NXT") !=
213 	    QLA_SUCCESS) {
214 		rval = QLA_FUNCTION_FAILED;
215 	} else {
216 		/* Populate fc_port_t entry. */
217 		fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];
218 		fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];
219 		fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];
220 
221 		memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
222 		    WWN_SIZE);
223 		memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,
224 		    WWN_SIZE);
225 
226 		if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&
227 		    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)
228 			fcport->d_id.b.domain = 0xf0;
229 
230 		DEBUG2_3(printk("scsi(%ld): GA_NXT entry - "
231 		    "nn %02x%02x%02x%02x%02x%02x%02x%02x "
232 		    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
233 		    "portid=%02x%02x%02x.\n",
234 		    ha->host_no,
235 		    fcport->node_name[0], fcport->node_name[1],
236 		    fcport->node_name[2], fcport->node_name[3],
237 		    fcport->node_name[4], fcport->node_name[5],
238 		    fcport->node_name[6], fcport->node_name[7],
239 		    fcport->port_name[0], fcport->port_name[1],
240 		    fcport->port_name[2], fcport->port_name[3],
241 		    fcport->port_name[4], fcport->port_name[5],
242 		    fcport->port_name[6], fcport->port_name[7],
243 		    fcport->d_id.b.domain, fcport->d_id.b.area,
244 		    fcport->d_id.b.al_pa));
245 	}
246 
247 	return (rval);
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 *ha, 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 
271 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
272 		return (qla2x00_sns_gid_pt(ha, list));
273 	}
274 
275 	gid_data = NULL;
276 
277 	/* Issue GID_PT */
278 	/* Prepare common MS IOCB */
279 	ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GID_PT_REQ_SIZE, GID_PT_RSP_SIZE);
280 
281 	/* Prepare CT request */
282 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD,
283 	    GID_PT_RSP_SIZE);
284 	ct_rsp = &ha->ct_sns->p.rsp;
285 
286 	/* Prepare CT arguments -- port_type */
287 	ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;
288 
289 	/* Execute MS IOCB */
290 	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
291 	    sizeof(ms_iocb_entry_t));
292 	if (rval != QLA_SUCCESS) {
293 		/*EMPTY*/
294 		DEBUG2_3(printk("scsi(%ld): GID_PT issue IOCB failed (%d).\n",
295 		    ha->host_no, rval));
296 	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "GID_PT") !=
297 	    QLA_SUCCESS) {
298 		rval = QLA_FUNCTION_FAILED;
299 	} else {
300 		/* Set port IDs in switch info list. */
301 		for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
302 			gid_data = &ct_rsp->rsp.gid_pt.entries[i];
303 			list[i].d_id.b.domain = gid_data->port_id[0];
304 			list[i].d_id.b.area = gid_data->port_id[1];
305 			list[i].d_id.b.al_pa = gid_data->port_id[2];
306 
307 			/* Last one exit. */
308 			if (gid_data->control_byte & BIT_7) {
309 				list[i].d_id.b.rsvd_1 = gid_data->control_byte;
310 				break;
311 			}
312 		}
313 
314 		/*
315 		 * If we've used all available slots, then the switch is
316 		 * reporting back more devices than we can handle with this
317 		 * single call.  Return a failed status, and let GA_NXT handle
318 		 * the overload.
319 		 */
320 		if (i == MAX_FIBRE_DEVICES)
321 			rval = QLA_FUNCTION_FAILED;
322 	}
323 
324 	return (rval);
325 }
326 
327 /**
328  * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query.
329  * @ha: HA context
330  * @list: switch info entries to populate
331  *
332  * Returns 0 on success.
333  */
334 int
335 qla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list)
336 {
337 	int		rval;
338 	uint16_t	i;
339 
340 	ms_iocb_entry_t	*ms_pkt;
341 	struct ct_sns_req	*ct_req;
342 	struct ct_sns_rsp	*ct_rsp;
343 
344 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
345 		return (qla2x00_sns_gpn_id(ha, list));
346 	}
347 
348 	for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
349 		/* Issue GPN_ID */
350 		/* Prepare common MS IOCB */
351 		ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GPN_ID_REQ_SIZE,
352 		    GPN_ID_RSP_SIZE);
353 
354 		/* Prepare CT request */
355 		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GPN_ID_CMD,
356 		    GPN_ID_RSP_SIZE);
357 		ct_rsp = &ha->ct_sns->p.rsp;
358 
359 		/* Prepare CT arguments -- port_id */
360 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
361 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
362 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
363 
364 		/* Execute MS IOCB */
365 		rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
366 		    sizeof(ms_iocb_entry_t));
367 		if (rval != QLA_SUCCESS) {
368 			/*EMPTY*/
369 			DEBUG2_3(printk("scsi(%ld): GPN_ID issue IOCB failed "
370 			    "(%d).\n", ha->host_no, rval));
371 		} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,
372 		    "GPN_ID") != QLA_SUCCESS) {
373 			rval = QLA_FUNCTION_FAILED;
374 		} else {
375 			/* Save portname */
376 			memcpy(list[i].port_name,
377 			    ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
378 		}
379 
380 		/* Last device exit. */
381 		if (list[i].d_id.b.rsvd_1 != 0)
382 			break;
383 	}
384 
385 	return (rval);
386 }
387 
388 /**
389  * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query.
390  * @ha: HA context
391  * @list: switch info entries to populate
392  *
393  * Returns 0 on success.
394  */
395 int
396 qla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list)
397 {
398 	int		rval;
399 	uint16_t	i;
400 
401 	ms_iocb_entry_t	*ms_pkt;
402 	struct ct_sns_req	*ct_req;
403 	struct ct_sns_rsp	*ct_rsp;
404 
405 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
406 		return (qla2x00_sns_gnn_id(ha, list));
407 	}
408 
409 	for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
410 		/* Issue GNN_ID */
411 		/* Prepare common MS IOCB */
412 		ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GNN_ID_REQ_SIZE,
413 		    GNN_ID_RSP_SIZE);
414 
415 		/* Prepare CT request */
416 		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GNN_ID_CMD,
417 		    GNN_ID_RSP_SIZE);
418 		ct_rsp = &ha->ct_sns->p.rsp;
419 
420 		/* Prepare CT arguments -- port_id */
421 		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
422 		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
423 		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
424 
425 		/* Execute MS IOCB */
426 		rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
427 		    sizeof(ms_iocb_entry_t));
428 		if (rval != QLA_SUCCESS) {
429 			/*EMPTY*/
430 			DEBUG2_3(printk("scsi(%ld): GNN_ID issue IOCB failed "
431 			    "(%d).\n", ha->host_no, rval));
432 		} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,
433 		    "GNN_ID") != QLA_SUCCESS) {
434 			rval = QLA_FUNCTION_FAILED;
435 		} else {
436 			/* Save nodename */
437 			memcpy(list[i].node_name,
438 			    ct_rsp->rsp.gnn_id.node_name, WWN_SIZE);
439 
440 			DEBUG2_3(printk("scsi(%ld): GID_PT entry - "
441 			    "nn %02x%02x%02x%02x%02x%02x%02x%02x "
442 			    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
443 			    "portid=%02x%02x%02x.\n",
444 			    ha->host_no,
445 			    list[i].node_name[0], list[i].node_name[1],
446 			    list[i].node_name[2], list[i].node_name[3],
447 			    list[i].node_name[4], list[i].node_name[5],
448 			    list[i].node_name[6], list[i].node_name[7],
449 			    list[i].port_name[0], list[i].port_name[1],
450 			    list[i].port_name[2], list[i].port_name[3],
451 			    list[i].port_name[4], list[i].port_name[5],
452 			    list[i].port_name[6], list[i].port_name[7],
453 			    list[i].d_id.b.domain, list[i].d_id.b.area,
454 			    list[i].d_id.b.al_pa));
455 		}
456 
457 		/* Last device exit. */
458 		if (list[i].d_id.b.rsvd_1 != 0)
459 			break;
460 	}
461 
462 	return (rval);
463 }
464 
465 /**
466  * qla2x00_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
467  * @ha: HA context
468  *
469  * Returns 0 on success.
470  */
471 int
472 qla2x00_rft_id(scsi_qla_host_t *ha)
473 {
474 	int		rval;
475 
476 	ms_iocb_entry_t	*ms_pkt;
477 	struct ct_sns_req	*ct_req;
478 	struct ct_sns_rsp	*ct_rsp;
479 
480 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
481 		return (qla2x00_sns_rft_id(ha));
482 	}
483 
484 	/* Issue RFT_ID */
485 	/* Prepare common MS IOCB */
486 	ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFT_ID_REQ_SIZE, RFT_ID_RSP_SIZE);
487 
488 	/* Prepare CT request */
489 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD,
490 	    RFT_ID_RSP_SIZE);
491 	ct_rsp = &ha->ct_sns->p.rsp;
492 
493 	/* Prepare CT arguments -- port_id, FC-4 types */
494 	ct_req->req.rft_id.port_id[0] = ha->d_id.b.domain;
495 	ct_req->req.rft_id.port_id[1] = ha->d_id.b.area;
496 	ct_req->req.rft_id.port_id[2] = ha->d_id.b.al_pa;
497 
498 	ct_req->req.rft_id.fc4_types[2] = 0x01;		/* FCP-3 */
499 
500 	/* Execute MS IOCB */
501 	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
502 	    sizeof(ms_iocb_entry_t));
503 	if (rval != QLA_SUCCESS) {
504 		/*EMPTY*/
505 		DEBUG2_3(printk("scsi(%ld): RFT_ID issue IOCB failed (%d).\n",
506 		    ha->host_no, rval));
507 	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RFT_ID") !=
508 	    QLA_SUCCESS) {
509 		rval = QLA_FUNCTION_FAILED;
510 	} else {
511 		DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n",
512 		    ha->host_no));
513 	}
514 
515 	return (rval);
516 }
517 
518 /**
519  * qla2x00_rff_id() - SNS Register FC-4 Features (RFF_ID) supported by the HBA.
520  * @ha: HA context
521  *
522  * Returns 0 on success.
523  */
524 int
525 qla2x00_rff_id(scsi_qla_host_t *ha)
526 {
527 	int		rval;
528 
529 	ms_iocb_entry_t	*ms_pkt;
530 	struct ct_sns_req	*ct_req;
531 	struct ct_sns_rsp	*ct_rsp;
532 
533 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
534 		DEBUG2(printk("scsi(%ld): RFF_ID call unsupported on "
535 		    "ISP2100/ISP2200.\n", ha->host_no));
536 		return (QLA_SUCCESS);
537 	}
538 
539 	/* Issue RFF_ID */
540 	/* Prepare common MS IOCB */
541 	ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFF_ID_REQ_SIZE, RFF_ID_RSP_SIZE);
542 
543 	/* Prepare CT request */
544 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD,
545 	    RFF_ID_RSP_SIZE);
546 	ct_rsp = &ha->ct_sns->p.rsp;
547 
548 	/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
549 	ct_req->req.rff_id.port_id[0] = ha->d_id.b.domain;
550 	ct_req->req.rff_id.port_id[1] = ha->d_id.b.area;
551 	ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa;
552 
553 	ct_req->req.rff_id.fc4_type = 0x08;		/* SCSI - FCP */
554 
555 	/* Execute MS IOCB */
556 	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
557 	    sizeof(ms_iocb_entry_t));
558 	if (rval != QLA_SUCCESS) {
559 		/*EMPTY*/
560 		DEBUG2_3(printk("scsi(%ld): RFF_ID issue IOCB failed (%d).\n",
561 		    ha->host_no, rval));
562 	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RFF_ID") !=
563 	    QLA_SUCCESS) {
564 		rval = QLA_FUNCTION_FAILED;
565 	} else {
566 		DEBUG2(printk("scsi(%ld): RFF_ID exiting normally.\n",
567 		    ha->host_no));
568 	}
569 
570 	return (rval);
571 }
572 
573 /**
574  * qla2x00_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
575  * @ha: HA context
576  *
577  * Returns 0 on success.
578  */
579 int
580 qla2x00_rnn_id(scsi_qla_host_t *ha)
581 {
582 	int		rval;
583 
584 	ms_iocb_entry_t	*ms_pkt;
585 	struct ct_sns_req	*ct_req;
586 	struct ct_sns_rsp	*ct_rsp;
587 
588 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
589 		return (qla2x00_sns_rnn_id(ha));
590 	}
591 
592 	/* Issue RNN_ID */
593 	/* Prepare common MS IOCB */
594 	ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RNN_ID_REQ_SIZE, RNN_ID_RSP_SIZE);
595 
596 	/* Prepare CT request */
597 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD,
598 	    RNN_ID_RSP_SIZE);
599 	ct_rsp = &ha->ct_sns->p.rsp;
600 
601 	/* Prepare CT arguments -- port_id, node_name */
602 	ct_req->req.rnn_id.port_id[0] = ha->d_id.b.domain;
603 	ct_req->req.rnn_id.port_id[1] = ha->d_id.b.area;
604 	ct_req->req.rnn_id.port_id[2] = ha->d_id.b.al_pa;
605 
606 	memcpy(ct_req->req.rnn_id.node_name, ha->node_name, WWN_SIZE);
607 
608 	/* Execute MS IOCB */
609 	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
610 	    sizeof(ms_iocb_entry_t));
611 	if (rval != QLA_SUCCESS) {
612 		/*EMPTY*/
613 		DEBUG2_3(printk("scsi(%ld): RNN_ID issue IOCB failed (%d).\n",
614 		    ha->host_no, rval));
615 	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RNN_ID") !=
616 	    QLA_SUCCESS) {
617 		rval = QLA_FUNCTION_FAILED;
618 	} else {
619 		DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n",
620 		    ha->host_no));
621 	}
622 
623 	return (rval);
624 }
625 
626 /**
627  * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA.
628  * @ha: HA context
629  *
630  * Returns 0 on success.
631  */
632 int
633 qla2x00_rsnn_nn(scsi_qla_host_t *ha)
634 {
635 	int		rval;
636 	uint8_t		*snn;
637 	uint8_t		version[20];
638 
639 	ms_iocb_entry_t	*ms_pkt;
640 	struct ct_sns_req	*ct_req;
641 	struct ct_sns_rsp	*ct_rsp;
642 
643 	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
644 		DEBUG2(printk("scsi(%ld): RSNN_ID call unsupported on "
645 		    "ISP2100/ISP2200.\n", ha->host_no));
646 		return (QLA_SUCCESS);
647 	}
648 
649 	/* Issue RSNN_NN */
650 	/* Prepare common MS IOCB */
651 	/*   Request size adjusted after CT preparation */
652 	ms_pkt = ha->isp_ops.prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE);
653 
654 	/* Prepare CT request */
655 	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD,
656 	    RSNN_NN_RSP_SIZE);
657 	ct_rsp = &ha->ct_sns->p.rsp;
658 
659 	/* Prepare CT arguments -- node_name, symbolic node_name, size */
660 	memcpy(ct_req->req.rsnn_nn.node_name, ha->node_name, WWN_SIZE);
661 
662 	/* Prepare the Symbolic Node Name */
663 	/* Board type */
664 	snn = ct_req->req.rsnn_nn.sym_node_name;
665 	strcpy(snn, ha->model_number);
666 	/* Firmware version */
667 	strcat(snn, " FW:v");
668 	sprintf(version, "%d.%02d.%02d", ha->fw_major_version,
669 	    ha->fw_minor_version, ha->fw_subminor_version);
670 	strcat(snn, version);
671 	/* Driver version */
672 	strcat(snn, " DVR:v");
673 	strcat(snn, qla2x00_version_str);
674 
675 	/* Calculate SNN length */
676 	ct_req->req.rsnn_nn.name_len = (uint8_t)strlen(snn);
677 
678 	/* Update MS IOCB request */
679 	ms_pkt->req_bytecount =
680 	    cpu_to_le32(24 + 1 + ct_req->req.rsnn_nn.name_len);
681 	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
682 
683 	/* Execute MS IOCB */
684 	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,
685 	    sizeof(ms_iocb_entry_t));
686 	if (rval != QLA_SUCCESS) {
687 		/*EMPTY*/
688 		DEBUG2_3(printk("scsi(%ld): RSNN_NN issue IOCB failed (%d).\n",
689 		    ha->host_no, rval));
690 	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "RSNN_NN") !=
691 	    QLA_SUCCESS) {
692 		rval = QLA_FUNCTION_FAILED;
693 	} else {
694 		DEBUG2(printk("scsi(%ld): RSNN_NN exiting normally.\n",
695 		    ha->host_no));
696 	}
697 
698 	return (rval);
699 }
700 
701 
702 /**
703  * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query.
704  * @ha: HA context
705  * @cmd: GS command
706  * @scmd_len: Subcommand length
707  * @data_size: response size in bytes
708  *
709  * Returns a pointer to the @ha's sns_cmd.
710  */
711 static inline struct sns_cmd_pkt *
712 qla2x00_prep_sns_cmd(scsi_qla_host_t *ha, uint16_t cmd, uint16_t scmd_len,
713     uint16_t data_size)
714 {
715 	uint16_t		wc;
716 	struct sns_cmd_pkt	*sns_cmd;
717 
718 	sns_cmd = ha->sns_cmd;
719 	memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
720 	wc = data_size / 2;			/* Size in 16bit words. */
721 	sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
722 	sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
723 	sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
724 	sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
725 	sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
726 	wc = (data_size - 16) / 4;		/* Size in 32bit words. */
727 	sns_cmd->p.cmd.size = cpu_to_le16(wc);
728 
729 	return (sns_cmd);
730 }
731 
732 /**
733  * qla2x00_sns_ga_nxt() - SNS scan for fabric devices via GA_NXT command.
734  * @ha: HA context
735  * @fcport: fcport entry to updated
736  *
737  * This command uses the old Exectute SNS Command mailbox routine.
738  *
739  * Returns 0 on success.
740  */
741 static int
742 qla2x00_sns_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport)
743 {
744 	int		rval;
745 
746 	struct sns_cmd_pkt	*sns_cmd;
747 
748 	/* Issue GA_NXT. */
749 	/* Prepare SNS command request. */
750 	sns_cmd = qla2x00_prep_sns_cmd(ha, GA_NXT_CMD, GA_NXT_SNS_SCMD_LEN,
751 	    GA_NXT_SNS_DATA_SIZE);
752 
753 	/* Prepare SNS command arguments -- port_id. */
754 	sns_cmd->p.cmd.param[0] = fcport->d_id.b.al_pa;
755 	sns_cmd->p.cmd.param[1] = fcport->d_id.b.area;
756 	sns_cmd->p.cmd.param[2] = fcport->d_id.b.domain;
757 
758 	/* Execute SNS command. */
759 	rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, GA_NXT_SNS_CMD_SIZE / 2,
760 	    sizeof(struct sns_cmd_pkt));
761 	if (rval != QLA_SUCCESS) {
762 		/*EMPTY*/
763 		DEBUG2_3(printk("scsi(%ld): GA_NXT Send SNS failed (%d).\n",
764 		    ha->host_no, rval));
765 	} else if (sns_cmd->p.gan_data[8] != 0x80 ||
766 	    sns_cmd->p.gan_data[9] != 0x02) {
767 		DEBUG2_3(printk("scsi(%ld): GA_NXT failed, rejected request, "
768 		    "ga_nxt_rsp:\n", ha->host_no));
769 		DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gan_data, 16));
770 		rval = QLA_FUNCTION_FAILED;
771 	} else {
772 		/* Populate fc_port_t entry. */
773 		fcport->d_id.b.domain = sns_cmd->p.gan_data[17];
774 		fcport->d_id.b.area = sns_cmd->p.gan_data[18];
775 		fcport->d_id.b.al_pa = sns_cmd->p.gan_data[19];
776 
777 		memcpy(fcport->node_name, &sns_cmd->p.gan_data[284], WWN_SIZE);
778 		memcpy(fcport->port_name, &sns_cmd->p.gan_data[20], WWN_SIZE);
779 
780 		if (sns_cmd->p.gan_data[16] != NS_N_PORT_TYPE &&
781 		    sns_cmd->p.gan_data[16] != NS_NL_PORT_TYPE)
782 			fcport->d_id.b.domain = 0xf0;
783 
784 		DEBUG2_3(printk("scsi(%ld): GA_NXT entry - "
785 		    "nn %02x%02x%02x%02x%02x%02x%02x%02x "
786 		    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
787 		    "portid=%02x%02x%02x.\n",
788 		    ha->host_no,
789 		    fcport->node_name[0], fcport->node_name[1],
790 		    fcport->node_name[2], fcport->node_name[3],
791 		    fcport->node_name[4], fcport->node_name[5],
792 		    fcport->node_name[6], fcport->node_name[7],
793 		    fcport->port_name[0], fcport->port_name[1],
794 		    fcport->port_name[2], fcport->port_name[3],
795 		    fcport->port_name[4], fcport->port_name[5],
796 		    fcport->port_name[6], fcport->port_name[7],
797 		    fcport->d_id.b.domain, fcport->d_id.b.area,
798 		    fcport->d_id.b.al_pa));
799 	}
800 
801 	return (rval);
802 }
803 
804 /**
805  * qla2x00_sns_gid_pt() - SNS scan for fabric devices via GID_PT command.
806  * @ha: HA context
807  * @list: switch info entries to populate
808  *
809  * This command uses the old Exectute SNS Command mailbox routine.
810  *
811  * NOTE: Non-Nx_Ports are not requested.
812  *
813  * Returns 0 on success.
814  */
815 static int
816 qla2x00_sns_gid_pt(scsi_qla_host_t *ha, sw_info_t *list)
817 {
818 	int		rval;
819 
820 	uint16_t	i;
821 	uint8_t		*entry;
822 	struct sns_cmd_pkt	*sns_cmd;
823 
824 	/* Issue GID_PT. */
825 	/* Prepare SNS command request. */
826 	sns_cmd = qla2x00_prep_sns_cmd(ha, GID_PT_CMD, GID_PT_SNS_SCMD_LEN,
827 	    GID_PT_SNS_DATA_SIZE);
828 
829 	/* Prepare SNS command arguments -- port_type. */
830 	sns_cmd->p.cmd.param[0] = NS_NX_PORT_TYPE;
831 
832 	/* Execute SNS command. */
833 	rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, GID_PT_SNS_CMD_SIZE / 2,
834 	    sizeof(struct sns_cmd_pkt));
835 	if (rval != QLA_SUCCESS) {
836 		/*EMPTY*/
837 		DEBUG2_3(printk("scsi(%ld): GID_PT Send SNS failed (%d).\n",
838 		    ha->host_no, rval));
839 	} else if (sns_cmd->p.gid_data[8] != 0x80 ||
840 	    sns_cmd->p.gid_data[9] != 0x02) {
841 		DEBUG2_3(printk("scsi(%ld): GID_PT failed, rejected request, "
842 		    "gid_rsp:\n", ha->host_no));
843 		DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gid_data, 16));
844 		rval = QLA_FUNCTION_FAILED;
845 	} else {
846 		/* Set port IDs in switch info list. */
847 		for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
848 			entry = &sns_cmd->p.gid_data[(i * 4) + 16];
849 			list[i].d_id.b.domain = entry[1];
850 			list[i].d_id.b.area = entry[2];
851 			list[i].d_id.b.al_pa = entry[3];
852 
853 			/* Last one exit. */
854 			if (entry[0] & BIT_7) {
855 				list[i].d_id.b.rsvd_1 = entry[0];
856 				break;
857 			}
858 		}
859 
860 		/*
861 		 * If we've used all available slots, then the switch is
862 		 * reporting back more devices that we can handle with this
863 		 * single call.  Return a failed status, and let GA_NXT handle
864 		 * the overload.
865 		 */
866 		if (i == MAX_FIBRE_DEVICES)
867 			rval = QLA_FUNCTION_FAILED;
868 	}
869 
870 	return (rval);
871 }
872 
873 /**
874  * qla2x00_sns_gpn_id() - SNS Get Port Name (GPN_ID) query.
875  * @ha: HA context
876  * @list: switch info entries to populate
877  *
878  * This command uses the old Exectute SNS Command mailbox routine.
879  *
880  * Returns 0 on success.
881  */
882 static int
883 qla2x00_sns_gpn_id(scsi_qla_host_t *ha, sw_info_t *list)
884 {
885 	int		rval;
886 
887 	uint16_t	i;
888 	struct sns_cmd_pkt	*sns_cmd;
889 
890 	for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
891 		/* Issue GPN_ID */
892 		/* Prepare SNS command request. */
893 		sns_cmd = qla2x00_prep_sns_cmd(ha, GPN_ID_CMD,
894 		    GPN_ID_SNS_SCMD_LEN, GPN_ID_SNS_DATA_SIZE);
895 
896 		/* Prepare SNS command arguments -- port_id. */
897 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
898 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
899 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
900 
901 		/* Execute SNS command. */
902 		rval = qla2x00_send_sns(ha, ha->sns_cmd_dma,
903 		    GPN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
904 		if (rval != QLA_SUCCESS) {
905 			/*EMPTY*/
906 			DEBUG2_3(printk("scsi(%ld): GPN_ID Send SNS failed "
907 			    "(%d).\n", ha->host_no, rval));
908 		} else if (sns_cmd->p.gpn_data[8] != 0x80 ||
909 		    sns_cmd->p.gpn_data[9] != 0x02) {
910 			DEBUG2_3(printk("scsi(%ld): GPN_ID failed, rejected "
911 			    "request, gpn_rsp:\n", ha->host_no));
912 			DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gpn_data, 16));
913 			rval = QLA_FUNCTION_FAILED;
914 		} else {
915 			/* Save portname */
916 			memcpy(list[i].port_name, &sns_cmd->p.gpn_data[16],
917 			    WWN_SIZE);
918 		}
919 
920 		/* Last device exit. */
921 		if (list[i].d_id.b.rsvd_1 != 0)
922 			break;
923 	}
924 
925 	return (rval);
926 }
927 
928 /**
929  * qla2x00_sns_gnn_id() - SNS Get Node Name (GNN_ID) query.
930  * @ha: HA context
931  * @list: switch info entries to populate
932  *
933  * This command uses the old Exectute SNS Command mailbox routine.
934  *
935  * Returns 0 on success.
936  */
937 static int
938 qla2x00_sns_gnn_id(scsi_qla_host_t *ha, sw_info_t *list)
939 {
940 	int		rval;
941 
942 	uint16_t	i;
943 	struct sns_cmd_pkt	*sns_cmd;
944 
945 	for (i = 0; i < MAX_FIBRE_DEVICES; i++) {
946 		/* Issue GNN_ID */
947 		/* Prepare SNS command request. */
948 		sns_cmd = qla2x00_prep_sns_cmd(ha, GNN_ID_CMD,
949 		    GNN_ID_SNS_SCMD_LEN, GNN_ID_SNS_DATA_SIZE);
950 
951 		/* Prepare SNS command arguments -- port_id. */
952 		sns_cmd->p.cmd.param[0] = list[i].d_id.b.al_pa;
953 		sns_cmd->p.cmd.param[1] = list[i].d_id.b.area;
954 		sns_cmd->p.cmd.param[2] = list[i].d_id.b.domain;
955 
956 		/* Execute SNS command. */
957 		rval = qla2x00_send_sns(ha, ha->sns_cmd_dma,
958 		    GNN_ID_SNS_CMD_SIZE / 2, sizeof(struct sns_cmd_pkt));
959 		if (rval != QLA_SUCCESS) {
960 			/*EMPTY*/
961 			DEBUG2_3(printk("scsi(%ld): GNN_ID Send SNS failed "
962 			    "(%d).\n", ha->host_no, rval));
963 		} else if (sns_cmd->p.gnn_data[8] != 0x80 ||
964 		    sns_cmd->p.gnn_data[9] != 0x02) {
965 			DEBUG2_3(printk("scsi(%ld): GNN_ID failed, rejected "
966 			    "request, gnn_rsp:\n", ha->host_no));
967 			DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.gnn_data, 16));
968 			rval = QLA_FUNCTION_FAILED;
969 		} else {
970 			/* Save nodename */
971 			memcpy(list[i].node_name, &sns_cmd->p.gnn_data[16],
972 			    WWN_SIZE);
973 
974 			DEBUG2_3(printk("scsi(%ld): GID_PT entry - "
975 			    "nn %02x%02x%02x%02x%02x%02x%02x%02x "
976 			    "pn %02x%02x%02x%02x%02x%02x%02x%02x "
977 			    "portid=%02x%02x%02x.\n",
978 			    ha->host_no,
979 			    list[i].node_name[0], list[i].node_name[1],
980 			    list[i].node_name[2], list[i].node_name[3],
981 			    list[i].node_name[4], list[i].node_name[5],
982 			    list[i].node_name[6], list[i].node_name[7],
983 			    list[i].port_name[0], list[i].port_name[1],
984 			    list[i].port_name[2], list[i].port_name[3],
985 			    list[i].port_name[4], list[i].port_name[5],
986 			    list[i].port_name[6], list[i].port_name[7],
987 			    list[i].d_id.b.domain, list[i].d_id.b.area,
988 			    list[i].d_id.b.al_pa));
989 		}
990 
991 		/* Last device exit. */
992 		if (list[i].d_id.b.rsvd_1 != 0)
993 			break;
994 	}
995 
996 	return (rval);
997 }
998 
999 /**
1000  * qla2x00_snd_rft_id() - SNS Register FC-4 TYPEs (RFT_ID) supported by the HBA.
1001  * @ha: HA context
1002  *
1003  * This command uses the old Exectute SNS Command mailbox routine.
1004  *
1005  * Returns 0 on success.
1006  */
1007 static int
1008 qla2x00_sns_rft_id(scsi_qla_host_t *ha)
1009 {
1010 	int		rval;
1011 
1012 	struct sns_cmd_pkt	*sns_cmd;
1013 
1014 	/* Issue RFT_ID. */
1015 	/* Prepare SNS command request. */
1016 	sns_cmd = qla2x00_prep_sns_cmd(ha, RFT_ID_CMD, RFT_ID_SNS_SCMD_LEN,
1017 	    RFT_ID_SNS_DATA_SIZE);
1018 
1019 	/* Prepare SNS command arguments -- port_id, FC-4 types */
1020 	sns_cmd->p.cmd.param[0] = ha->d_id.b.al_pa;
1021 	sns_cmd->p.cmd.param[1] = ha->d_id.b.area;
1022 	sns_cmd->p.cmd.param[2] = ha->d_id.b.domain;
1023 
1024 	sns_cmd->p.cmd.param[5] = 0x01;			/* FCP-3 */
1025 
1026 	/* Execute SNS command. */
1027 	rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, RFT_ID_SNS_CMD_SIZE / 2,
1028 	    sizeof(struct sns_cmd_pkt));
1029 	if (rval != QLA_SUCCESS) {
1030 		/*EMPTY*/
1031 		DEBUG2_3(printk("scsi(%ld): RFT_ID Send SNS failed (%d).\n",
1032 		    ha->host_no, rval));
1033 	} else if (sns_cmd->p.rft_data[8] != 0x80 ||
1034 	    sns_cmd->p.rft_data[9] != 0x02) {
1035 		DEBUG2_3(printk("scsi(%ld): RFT_ID failed, rejected request, "
1036 		    "rft_rsp:\n", ha->host_no));
1037 		DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rft_data, 16));
1038 		rval = QLA_FUNCTION_FAILED;
1039 	} else {
1040 		DEBUG2(printk("scsi(%ld): RFT_ID exiting normally.\n",
1041 		    ha->host_no));
1042 	}
1043 
1044 	return (rval);
1045 }
1046 
1047 /**
1048  * qla2x00_sns_rnn_id() - SNS Register Node Name (RNN_ID) of the HBA.
1049  * HBA.
1050  * @ha: HA context
1051  *
1052  * This command uses the old Exectute SNS Command mailbox routine.
1053  *
1054  * Returns 0 on success.
1055  */
1056 static int
1057 qla2x00_sns_rnn_id(scsi_qla_host_t *ha)
1058 {
1059 	int		rval;
1060 
1061 	struct sns_cmd_pkt	*sns_cmd;
1062 
1063 	/* Issue RNN_ID. */
1064 	/* Prepare SNS command request. */
1065 	sns_cmd = qla2x00_prep_sns_cmd(ha, RNN_ID_CMD, RNN_ID_SNS_SCMD_LEN,
1066 	    RNN_ID_SNS_DATA_SIZE);
1067 
1068 	/* Prepare SNS command arguments -- port_id, nodename. */
1069 	sns_cmd->p.cmd.param[0] = ha->d_id.b.al_pa;
1070 	sns_cmd->p.cmd.param[1] = ha->d_id.b.area;
1071 	sns_cmd->p.cmd.param[2] = ha->d_id.b.domain;
1072 
1073 	sns_cmd->p.cmd.param[4] = ha->node_name[7];
1074 	sns_cmd->p.cmd.param[5] = ha->node_name[6];
1075 	sns_cmd->p.cmd.param[6] = ha->node_name[5];
1076 	sns_cmd->p.cmd.param[7] = ha->node_name[4];
1077 	sns_cmd->p.cmd.param[8] = ha->node_name[3];
1078 	sns_cmd->p.cmd.param[9] = ha->node_name[2];
1079 	sns_cmd->p.cmd.param[10] = ha->node_name[1];
1080 	sns_cmd->p.cmd.param[11] = ha->node_name[0];
1081 
1082 	/* Execute SNS command. */
1083 	rval = qla2x00_send_sns(ha, ha->sns_cmd_dma, RNN_ID_SNS_CMD_SIZE / 2,
1084 	    sizeof(struct sns_cmd_pkt));
1085 	if (rval != QLA_SUCCESS) {
1086 		/*EMPTY*/
1087 		DEBUG2_3(printk("scsi(%ld): RNN_ID Send SNS failed (%d).\n",
1088 		    ha->host_no, rval));
1089 	} else if (sns_cmd->p.rnn_data[8] != 0x80 ||
1090 	    sns_cmd->p.rnn_data[9] != 0x02) {
1091 		DEBUG2_3(printk("scsi(%ld): RNN_ID failed, rejected request, "
1092 		    "rnn_rsp:\n", ha->host_no));
1093 		DEBUG2_3(qla2x00_dump_buffer(sns_cmd->p.rnn_data, 16));
1094 		rval = QLA_FUNCTION_FAILED;
1095 	} else {
1096 		DEBUG2(printk("scsi(%ld): RNN_ID exiting normally.\n",
1097 		    ha->host_no));
1098 	}
1099 
1100 	return (rval);
1101 }
1102