xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_mbx.c (revision 7e322df5ee63a00c1c57398abec50fc1dc54b67a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /* Copyright 2009 QLogic Corporation */
23 
24 /*
25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 #pragma ident	"Copyright 2009 QLogic Corporation; ql_mbx.c"
30 
31 /*
32  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
33  *
34  * ***********************************************************************
35  * *									**
36  * *				NOTICE					**
37  * *		COPYRIGHT (C) 1996-2009 QLOGIC CORPORATION		**
38  * *			ALL RIGHTS RESERVED				**
39  * *									**
40  * ***********************************************************************
41  *
42  */
43 
44 #include <ql_apps.h>
45 #include <ql_api.h>
46 #include <ql_debug.h>
47 #include <ql_iocb.h>
48 #include <ql_isr.h>
49 #include <ql_mbx.h>
50 #include <ql_xioctl.h>
51 
52 /*
53  * Local data
54  */
55 
56 /*
57  * Local prototypes
58  */
59 static int ql_mailbox_command(ql_adapter_state_t *, mbx_cmd_t *);
60 static int ql_task_mgmt_iocb(ql_adapter_state_t *, ql_tgt_t *, uint16_t,
61     uint32_t, uint16_t);
62 static int ql_abort_cmd_iocb(ql_adapter_state_t *, ql_srb_t *);
63 static int ql_setup_mbox_dma_transfer(ql_adapter_state_t *, dma_mem_t *,
64     caddr_t, uint32_t);
65 static int ql_setup_mbox_dma_resources(ql_adapter_state_t *, dma_mem_t *,
66     uint32_t);
67 static void ql_setup_mbox_dma_data(dma_mem_t *, caddr_t);
68 static void ql_get_mbox_dma_data(dma_mem_t *, caddr_t);
69 
70 /*
71  * ql_mailbox_command
72  *	Issue mailbox command and waits for completion.
73  *
74  * Input:
75  *	ha = adapter state pointer.
76  *	mcp = mailbox command parameter structure pointer.
77  *
78  * Returns:
79  *	ql local function return status code.
80  *
81  * Context:
82  *	Kernel context.
83  */
84 static int
85 ql_mailbox_command(ql_adapter_state_t *vha, mbx_cmd_t *mcp)
86 {
87 	uint16_t		cnt;
88 	uint32_t		data;
89 	clock_t			timer, cv_stat;
90 	int			rval;
91 	uint32_t		set_flags = 0;
92 	uint32_t		reset_flags = 0;
93 	ql_adapter_state_t	*ha = vha->pha;
94 	int			mbx_cmd = mcp->mb[0];
95 
96 	ASSERT(!MUTEX_HELD(&ha->mutex));
97 
98 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
99 
100 	/* Acquire mailbox register lock. */
101 	MBX_REGISTER_LOCK(ha);
102 
103 	/* Check for mailbox available, if not wait for signal. */
104 	while (ha->mailbox_flags & MBX_BUSY_FLG) {
105 		ha->mailbox_flags = (uint8_t)
106 		    (ha->mailbox_flags | MBX_WANT_FLG);
107 
108 		if (ha->task_daemon_flags & TASK_DAEMON_POWERING_DOWN) {
109 			EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
110 			MBX_REGISTER_UNLOCK(ha);
111 			return (QL_LOCK_TIMEOUT);
112 		}
113 
114 		/* Set timeout after command that is running. */
115 		timer = ddi_get_lbolt();
116 		timer += (mcp->timeout + 20) * drv_usectohz(1000000);
117 		cv_stat = cv_timedwait_sig(&ha->cv_mbx_wait,
118 		    &ha->pha->mbx_mutex, timer);
119 		if (cv_stat == -1 || cv_stat == 0) {
120 			/*
121 			 * The timeout time 'timer' was
122 			 * reached without the condition
123 			 * being signaled.
124 			 */
125 			ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
126 			    ~MBX_WANT_FLG);
127 			cv_broadcast(&ha->cv_mbx_wait);
128 
129 			/* Release mailbox register lock. */
130 			MBX_REGISTER_UNLOCK(ha);
131 
132 			if (cv_stat == 0) {
133 				EL(vha, "waiting for availability aborted, "
134 				    "cmd=%xh\n", mcp->mb[0]);
135 				return (QL_ABORTED);
136 			}
137 			EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
138 			return (QL_LOCK_TIMEOUT);
139 		}
140 	}
141 
142 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_BUSY_FLG);
143 
144 	/* Structure pointer for return mailbox registers. */
145 	ha->mcp = mcp;
146 
147 	/* Load mailbox registers. */
148 	data = mcp->out_mb;
149 	for (cnt = 0; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
150 		if (data & MBX_0) {
151 			WRT16_IO_REG(ha, mailbox[cnt], mcp->mb[cnt]);
152 		}
153 		data >>= 1;
154 	}
155 
156 	/* Issue set host interrupt command. */
157 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & ~MBX_INTERRUPT);
158 	CFG_IST(ha, CFG_CTRL_242581) ?
159 	    WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT) :
160 	    WRT16_IO_REG(ha, hccr, HC_SET_HOST_INT);
161 
162 	/* Wait for command to complete. */
163 	if (ha->flags & INTERRUPTS_ENABLED &&
164 	    !(ha->task_daemon_flags & (TASK_THREAD_CALLED |
165 	    TASK_DAEMON_POWERING_DOWN)) &&
166 	    !ddi_in_panic()) {
167 		while (!(ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT)) &&
168 		    !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
169 
170 			/* 30 seconds from now */
171 			timer = ddi_get_lbolt();
172 			timer += mcp->timeout * drv_usectohz(1000000);
173 			if (cv_timedwait(&ha->cv_mbx_intr, &ha->pha->mbx_mutex,
174 			    timer) == -1) {
175 				/*
176 				 * The timeout time 'timer' was
177 				 * reached without the condition
178 				 * being signaled.
179 				 */
180 				break;
181 			}
182 		}
183 	} else {
184 		/* Release mailbox register lock. */
185 		MBX_REGISTER_UNLOCK(ha);
186 
187 		/* Acquire interrupt lock. */
188 		for (timer = mcp->timeout * 100; timer; timer--) {
189 			/* Check for pending interrupts. */
190 			while (RD16_IO_REG(ha, istatus) & RISC_INT) {
191 				(void) ql_isr((caddr_t)ha);
192 				INTR_LOCK(ha);
193 				ha->intr_claimed = B_TRUE;
194 				INTR_UNLOCK(ha);
195 				if (ha->mailbox_flags &
196 				    (MBX_INTERRUPT | MBX_ABORT) ||
197 				    ha->task_daemon_flags & ISP_ABORT_NEEDED) {
198 					break;
199 				}
200 			}
201 			if (ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT) ||
202 			    ha->task_daemon_flags & ISP_ABORT_NEEDED) {
203 				break;
204 			} else if (!ddi_in_panic() && timer % 101 == 0) {
205 				delay(drv_usectohz(10000));
206 			} else {
207 				drv_usecwait(10000);
208 			}
209 		}
210 
211 		/* Acquire mailbox register lock. */
212 		MBX_REGISTER_LOCK(ha);
213 	}
214 
215 	/* Mailbox command timeout? */
216 	if (ha->task_daemon_flags & ISP_ABORT_NEEDED ||
217 	    ha->mailbox_flags & MBX_ABORT) {
218 		rval = QL_ABORTED;
219 	} else if ((ha->mailbox_flags & MBX_INTERRUPT) == 0) {
220 		if (CFG_IST(ha, CFG_DUMP_MAILBOX_TIMEOUT)) {
221 			(void) ql_binary_fw_dump(ha, FALSE);
222 		}
223 		EL(vha, "command timeout, isp_abort_needed\n");
224 		set_flags |= ISP_ABORT_NEEDED;
225 		rval = QL_FUNCTION_TIMEOUT;
226 	} else {
227 		ha->mailbox_flags = (uint8_t)
228 		    (ha->mailbox_flags & ~MBX_INTERRUPT);
229 		/*
230 		 * This is the expected completion path so
231 		 * return the actual mbx cmd completion status.
232 		 */
233 		rval = mcp->mb[0];
234 	}
235 
236 	/*
237 	 * Clear outbound to risc mailbox registers per spec. The exception
238 	 * is on 2200 mailbox 4 and 5 affect the req and resp que indexes
239 	 * so avoid writing them.
240 	 */
241 	if (ha->cfg_flags & CFG_CTRL_2200) {
242 		data = ((mcp->out_mb & ~(MBX_4 | MBX_5)) >> 1);
243 	} else {
244 		data = (mcp->out_mb >> 1);
245 	}
246 	for (cnt = 1; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
247 		if (data & MBX_0) {
248 			WRT16_IO_REG(ha, mailbox[cnt], (uint16_t)0);
249 		}
250 		data >>= 1;
251 	}
252 
253 	/* Reset busy status. */
254 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
255 	    ~(MBX_BUSY_FLG | MBX_ABORT));
256 	ha->mcp = NULL;
257 
258 	/* If thread is waiting for mailbox go signal it to start. */
259 	if (ha->mailbox_flags & MBX_WANT_FLG) {
260 		ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
261 		    ~MBX_WANT_FLG);
262 		cv_broadcast(&ha->cv_mbx_wait);
263 	}
264 
265 	/* Release mailbox register lock. */
266 	MBX_REGISTER_UNLOCK(ha);
267 
268 	if (set_flags != 0 || reset_flags != 0) {
269 		ql_awaken_task_daemon(ha, NULL, set_flags, reset_flags);
270 	}
271 
272 	if (rval != QL_SUCCESS) {
273 		EL(vha, "%s failed, rval=%xh, mcp->mb[0]=%xh\n",
274 		    mbx_cmd_text(mbx_cmd), rval, mcp->mb[0]);
275 	} else {
276 		/*EMPTY*/
277 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
278 	}
279 
280 	return (rval);
281 }
282 
283 /*
284  * ql_setup_mbox_dma_resources
285  *	Prepare the data for a mailbox dma transfer.
286  *
287  * Input:
288  *	ha = adapter state pointer.
289  *	mem_desc = descriptor to contain the dma resource information.
290  *	data = pointer to the data.
291  *	size = size of the data in bytes.
292  *
293  * Returns:
294  *	ql local function return status code.
295  *
296  * Context:
297  *	Kernel context.
298  */
299 static int
300 ql_setup_mbox_dma_transfer(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
301     caddr_t data, uint32_t size)
302 {
303 	int rval = QL_SUCCESS;
304 
305 	if ((rval = ql_setup_mbox_dma_resources(ha, mem_desc, size)) ==
306 	    QL_SUCCESS) {
307 		ql_setup_mbox_dma_data(mem_desc, data);
308 	} else {
309 		EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
310 	}
311 
312 	return (rval);
313 }
314 
315 /*
316  * ql_setup_mbox_dma_resources
317  *	Prepare a dma buffer.
318  *
319  * Input:
320  *	ha = adapter state pointer.
321  *	mem_desc = descriptor to contain the dma resource information.
322  *	data = pointer to the data.
323  *	size = size of the data in bytes.
324  *
325  * Returns:
326  *	ql local function return status code.
327  *
328  * Context:
329  *	Kernel context.
330  */
331 static int
332 ql_setup_mbox_dma_resources(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
333     uint32_t size)
334 {
335 	int	rval = QL_SUCCESS;
336 
337 	if ((rval = ql_get_dma_mem(ha, mem_desc, size, LITTLE_ENDIAN_DMA,
338 	    QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
339 		EL(ha, "failed, ql_get_dma_mem FC_NOMEM\n");
340 		rval = QL_MEMORY_ALLOC_FAILED;
341 	}
342 
343 	return (rval);
344 }
345 
346 /*
347  * ql_setup_mbox_dma_data
348  *	Move data to the dma buffer.
349  *
350  * Input:
351  *	mem_desc = descriptor to contain the dma resource information.
352  *	data = pointer to the data.
353  *
354  * Returns:
355  *
356  * Context:
357  *	Kernel context.
358  */
359 static void
360 ql_setup_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
361 {
362 	/* Copy out going data to DMA buffer. */
363 	ddi_rep_put8(mem_desc->acc_handle, (uint8_t *)data,
364 	    (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
365 
366 	/* Sync DMA buffer. */
367 	(void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
368 	    DDI_DMA_SYNC_FORDEV);
369 }
370 
371 /*
372  * ql_get_mbox_dma_data
373  *	Recover data from the dma buffer.
374  *
375  * Input:
376  *	mem_desc = descriptor to contain the dma resource information.
377  *	data = pointer to the data.
378  *
379  * Returns:
380  *
381  * Context:
382  *	Kernel context.
383  */
384 static void
385 ql_get_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
386 {
387 	/* Sync in coming DMA buffer. */
388 	(void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
389 	    DDI_DMA_SYNC_FORKERNEL);
390 	/* Copy in coming DMA data. */
391 	ddi_rep_get8(mem_desc->acc_handle, (uint8_t *)data,
392 	    (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
393 }
394 
395 /*
396  * ql_initialize_ip
397  *	Initialize IP receive buffer queue.
398  *
399  * Input:
400  *	ha = adapter state pointer.
401  *	ha->ip_init_ctrl_blk = setup for transmit.
402  *
403  * Returns:
404  *	ql local function return status code.
405  *
406  * Context:
407  *	Kernel context.
408  */
409 int
410 ql_initialize_ip(ql_adapter_state_t *ha)
411 {
412 	ql_link_t	*link;
413 	ql_tgt_t	*tq;
414 	uint16_t	index;
415 	int		rval;
416 	dma_mem_t	mem_desc;
417 	mbx_cmd_t	mc = {0};
418 	mbx_cmd_t	*mcp = &mc;
419 
420 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
421 
422 	if (CFG_IST(ha, (CFG_CTRL_6322 | CFG_CTRL_2581)) ||
423 	    ha->vp_index != 0) {
424 		ha->flags &= ~IP_INITIALIZED;
425 		EL(ha, "HBA does not support IP\n");
426 		return (QL_FUNCTION_FAILED);
427 	}
428 
429 	ha->rcvbuf_ring_ptr = ha->rcvbuf_ring_bp;
430 	ha->rcvbuf_ring_index = 0;
431 
432 	/* Reset all sequence counts. */
433 	for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
434 		for (link = ha->dev[index].first; link != NULL;
435 		    link = link->next) {
436 			tq = link->base_address;
437 			tq->ub_total_seg_cnt = 0;
438 		}
439 	}
440 
441 	rval = ql_setup_mbox_dma_transfer(ha, &mem_desc,
442 	    (caddr_t)&ha->ip_init_ctrl_blk, sizeof (ql_comb_ip_init_cb_t));
443 	if (rval != QL_SUCCESS) {
444 		EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
445 		return (rval);
446 	}
447 
448 	mcp->mb[0] = MBC_INITIALIZE_IP;
449 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
450 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
451 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
452 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
453 	mcp->mb[8] = 0;
454 	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
455 	mcp->in_mb = MBX_8|MBX_0;
456 	mcp->timeout = MAILBOX_TOV;
457 	rval = ql_mailbox_command(ha, mcp);
458 
459 	ql_free_dma_resource(ha, &mem_desc);
460 
461 	if (rval == QL_SUCCESS) {
462 		ADAPTER_STATE_LOCK(ha);
463 		ha->flags |= IP_INITIALIZED;
464 		ADAPTER_STATE_UNLOCK(ha);
465 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
466 	} else {
467 		ha->flags &= ~IP_INITIALIZED;
468 		EL(ha, "failed, rval = %xh\n", rval);
469 	}
470 	return (rval);
471 }
472 
473 /*
474  * ql_shutdown_ip
475  *	Disconnects firmware IP from system buffers.
476  *
477  * Input:
478  *	ha = adapter state pointer.
479  *
480  * Returns:
481  *	ql local function return status code.
482  *
483  * Context:
484  *	Kernel context.
485  */
486 int
487 ql_shutdown_ip(ql_adapter_state_t *ha)
488 {
489 	int		rval;
490 	mbx_cmd_t	mc = {0};
491 	mbx_cmd_t	*mcp = &mc;
492 	fc_unsol_buf_t	*ubp;
493 	ql_srb_t	*sp;
494 	uint16_t	index;
495 
496 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
497 
498 	mcp->mb[0] = MBC_UNLOAD_IP;
499 	mcp->out_mb = MBX_0;
500 	mcp->in_mb = MBX_0;
501 	mcp->timeout = MAILBOX_TOV;
502 	rval = ql_mailbox_command(ha, mcp);
503 
504 	ADAPTER_STATE_LOCK(ha);
505 	QL_UB_LOCK(ha);
506 	/* Return all unsolicited buffers that ISP-IP has. */
507 	for (index = 0; index < QL_UB_LIMIT; index++) {
508 		ubp = ha->ub_array[index];
509 		if (ubp != NULL) {
510 			sp = ubp->ub_fca_private;
511 			sp->flags &= ~SRB_UB_IN_ISP;
512 		}
513 	}
514 
515 	ha->ub_outcnt = 0;
516 	QL_UB_UNLOCK(ha);
517 	ha->flags &= ~IP_INITIALIZED;
518 	ADAPTER_STATE_UNLOCK(ha);
519 
520 	if (rval == QL_SUCCESS) {
521 		/* EMPTY - no need to check return value of MBC_SHUTDOWN_IP */
522 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
523 	} else {
524 		EL(ha, "failed, rval = %xh\n", rval);
525 	}
526 	return (rval);
527 }
528 
529 /*
530  * ql_online_selftest
531  *	Issue online self test mailbox command.
532  *
533  * Input:
534  *	ha = adapter state pointer.
535  *
536  * Returns:
537  *	ql local function return status code.
538  *
539  * Context:
540  *	Kernel context.
541  */
542 int
543 ql_online_selftest(ql_adapter_state_t *ha)
544 {
545 	int		rval;
546 	mbx_cmd_t	mc = {0};
547 	mbx_cmd_t	*mcp = &mc;
548 
549 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
550 
551 	mcp->mb[0] = MBC_ONLINE_SELF_TEST;
552 	mcp->out_mb = MBX_0;
553 	mcp->in_mb = MBX_0 | MBX_1 | MBX_2 | MBX_3;
554 	mcp->timeout = MAILBOX_TOV;
555 	rval = ql_mailbox_command(ha, mcp);
556 
557 	if (rval != QL_SUCCESS) {
558 		EL(ha, "failed, rval = %xh, mb1=%xh, mb2=%xh, mb3=%xh\n",
559 		    rval, mcp->mb[1], mcp->mb[2], mcp->mb[3]);
560 	} else {
561 		/*EMPTY*/
562 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
563 	}
564 	return (rval);
565 }
566 
567 /*
568  * ql_loop_back
569  *	Issue diagnostic loop back frame mailbox command.
570  *
571  * Input:
572  *	ha = adapter state pointer.
573  *	lb = loop back parameter structure pointer.
574  *
575  * Returns:
576  *	ql local function return status code.
577  *
578  * Context:
579  *	Kernel context.
580  */
581 #ifndef apps_64bit
582 int
583 ql_loop_back(ql_adapter_state_t *ha, lbp_t *lb, uint32_t h_xmit,
584     uint32_t h_rcv)
585 {
586 	int		rval;
587 	mbx_cmd_t	mc = {0};
588 	mbx_cmd_t	*mcp = &mc;
589 
590 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
591 
592 	mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
593 	mcp->mb[1] = lb->options;
594 	mcp->mb[6] = LSW(h_rcv);
595 	mcp->mb[7] = MSW(h_rcv);
596 	mcp->mb[10] = LSW(lb->transfer_count);
597 	mcp->mb[11] = MSW(lb->transfer_count);
598 	mcp->mb[12] = lb->transfer_segment_count;
599 	mcp->mb[13] = lb->receive_segment_count;
600 	mcp->mb[14] = LSW(lb->transfer_data_address);
601 	mcp->mb[15] = MSW(lb->transfer_data_address);
602 	mcp->mb[16] = LSW(lb->receive_data_address);
603 	mcp->mb[17] = MSW(lb->receive_data_address);
604 	mcp->mb[18] = LSW(lb->iteration_count);
605 	mcp->mb[19] = MSW(lb->iteration_count);
606 	mcp->mb[20] = LSW(h_xmit);
607 	mcp->mb[21] = MSW(h_xmit);
608 	mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
609 	    MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
610 	mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
611 	mcp->timeout = lb->iteration_count / 300;
612 
613 	if (mcp->timeout < MAILBOX_TOV) {
614 		mcp->timeout = MAILBOX_TOV;
615 	}
616 
617 	rval = ql_mailbox_command(ha, mcp);
618 
619 	if (rval != QL_SUCCESS) {
620 		EL(ha, "failed, rval = %xh\n", rval);
621 	} else {
622 		/*EMPTY*/
623 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
624 	}
625 
626 	return (rval);
627 }
628 #else
629 int
630 ql_loop_back(ql_adapter_state_t *ha, lbp_t *lb)
631 {
632 	int		rval;
633 	mbx_cmd_t	mc = {0};
634 	mbx_cmd_t	*mcp = &mc;
635 
636 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
637 
638 	mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
639 	mcp->mb[1] = lb->options;
640 	mcp->mb[6] = LSW(h_rcv);
641 	mcp->mb[7] = MSW(h_rcv);
642 	mcp->mb[6] = LSW(MSD(lb->receive_data_address));
643 	mcp->mb[7] = MSW(MSD(lb->receive_data_address));
644 	mcp->mb[10] = LSW(lb->transfer_count);
645 	mcp->mb[11] = MSW(lb->transfer_count);
646 	mcp->mb[12] = lb->transfer_segment_count;
647 	mcp->mb[13] = lb->receive_segment_count;
648 	mcp->mb[14] = LSW(lb->transfer_data_address);
649 	mcp->mb[15] = MSW(lb->transfer_data_address);
650 	mcp->mb[14] = LSW(LSD(lb->transfer_data_address));
651 	mcp->mb[15] = MSW(LSD(lb->transfer_data_address));
652 	mcp->mb[16] = LSW(lb->receive_data_address);
653 	mcp->mb[17] = MSW(lb->receive_data_address);
654 	mcp->mb[16] = LSW(LSD(lb->receive_data_address));
655 	mcp->mb[17] = MSW(LSD(lb->receive_data_address));
656 	mcp->mb[18] = LSW(lb->iteration_count);
657 	mcp->mb[19] = MSW(lb->iteration_count);
658 	mcp->mb[20] = LSW(h_xmit);
659 	mcp->mb[21] = MSW(h_xmit);
660 	mcp->mb[20] = LSW(MSD(lb->transfer_data_address));
661 	mcp->mb[21] = MSW(MSD(lb->transfer_data_address));
662 	mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
663 	    MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
664 	mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
665 	mcp->timeout = lb->iteration_count / 300;
666 
667 	if (mcp->timeout < MAILBOX_TOV) {
668 		mcp->timeout = MAILBOX_TOV;
669 	}
670 
671 	rval = ql_mailbox_command(ha, mcp);
672 
673 	if (rval != QL_SUCCESS) {
674 		EL(ha, "failed, rval = %xh\n", rval);
675 	} else {
676 		/*EMPTY*/
677 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
678 	}
679 	return (rval);
680 }
681 #endif
682 
683 /*
684  * ql_echo
685  *	Issue an ELS echo using the user specified data to a user specified
686  *	destination
687  *
688  * Input:
689  *	ha:		adapter state pointer.
690  *	echo_pt:	echo parameter structure pointer.
691  *
692  * Returns:
693  *	ql local function return status code.
694  *
695  * Context:
696  *	Kernel context.
697  */
698 int
699 ql_echo(ql_adapter_state_t *ha, echo_t *echo_pt)
700 {
701 	int		rval;
702 	mbx_cmd_t	mc = {0};
703 	mbx_cmd_t	*mcp = &mc;
704 
705 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
706 
707 	mcp->mb[0] = MBC_ECHO;			/* ECHO command */
708 	mcp->mb[1] = echo_pt->options;		/* command options; 64 bit */
709 						/* addressing (bit 6) and */
710 						/* real echo (bit 15 */
711 
712 	/*
713 	 * I know this looks strange, using a field labled "not used"
714 	 * The way the ddi_dma_cookie_t structure/union is defined
715 	 * is a union of one 64 bit entity with an array of two 32
716 	 * bit enititys.  Since we have routines to convert 32 bit
717 	 * entities into 16 bit entities it is easier to use
718 	 * both 32 bit union members then the one 64 bit union
719 	 * member
720 	 */
721 	if (echo_pt->options & BIT_6) {
722 		/* 64 bit addressing */
723 		/* Receive data dest add in system memory bits 47-32 */
724 		mcp->mb[6] = LSW(echo_pt->receive_data_address.dmac_notused);
725 
726 		/* Receive data dest add in system memory bits 63-48 */
727 		mcp->mb[7] = MSW(echo_pt->receive_data_address.dmac_notused);
728 
729 		/* Transmit data source address in system memory bits 47-32 */
730 		mcp->mb[20] = LSW(echo_pt->transfer_data_address.dmac_notused);
731 
732 		/* Transmit data source address in system memory bits 63-48 */
733 		mcp->mb[21] = MSW(echo_pt->transfer_data_address.dmac_notused);
734 	}
735 
736 	/* transfer count bits 15-0 */
737 	mcp->mb[10] = LSW(echo_pt->transfer_count);
738 
739 	/* Transmit data source address in system memory bits 15-0 */
740 	mcp->mb[14] = LSW(echo_pt->transfer_data_address.dmac_address);
741 
742 	/*  Transmit data source address in system memory bits 31-16 */
743 	mcp->mb[15] = MSW(echo_pt->transfer_data_address.dmac_address);
744 
745 	/* Receive data destination address in system memory bits 15-0 */
746 	mcp->mb[16] = LSW(echo_pt->receive_data_address.dmac_address);
747 
748 	/*  Receive data destination address in system memory bits 31-16 */
749 	mcp->mb[17] = MSW(echo_pt->receive_data_address.dmac_address);
750 
751 	mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|MBX_14|MBX_10|
752 	    MBX_7|MBX_6|MBX_1|MBX_0;
753 	mcp->in_mb = MBX_1|MBX_0;
754 	mcp->timeout = MAILBOX_TOV;
755 
756 	rval = ql_mailbox_command(ha, mcp);
757 
758 	if (rval != QL_SUCCESS) {
759 		EL(ha, "failed, rval = %xh\n", rval);
760 	} else {
761 		/*EMPTY*/
762 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
763 	}
764 	return (rval);
765 }
766 
767 /*
768  * ql_send_change_request
769  *	Issue send change request mailbox command.
770  *
771  * Input:
772  *	ha:	adapter state pointer.
773  *	fmt:	Registration format.
774  *
775  * Returns:
776  *	ql local function return status code.
777  *
778  * Context:
779  *	Kernel context.
780  */
781 int
782 ql_send_change_request(ql_adapter_state_t *ha, uint16_t fmt)
783 {
784 	int		rval;
785 	mbx_cmd_t	mc = {0};
786 	mbx_cmd_t	*mcp = &mc;
787 
788 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
789 
790 	mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
791 	mcp->mb[1] = fmt;
792 	mcp->out_mb = MBX_1|MBX_0;
793 	if (ha->flags & VP_ENABLED) {
794 		mcp->mb[9] = ha->vp_index;
795 		mcp->out_mb |= MBX_9;
796 	}
797 	mcp->in_mb = MBX_0;
798 	mcp->timeout = MAILBOX_TOV;
799 	rval = ql_mailbox_command(ha, mcp);
800 
801 	if (rval != QL_SUCCESS) {
802 		EL(ha, "failed=%xh\n", rval);
803 	} else {
804 		/*EMPTY*/
805 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
806 	}
807 	return (rval);
808 }
809 
810 /*
811  * ql_send_lfa
812  *	Send a Loop Fabric Address mailbox command.
813  *
814  * Input:
815  *	ha:	adapter state pointer.
816  *	lfa:	LFA command structure pointer.
817  *
818  * Returns:
819  *	ql local function return status code.
820  *
821  * Context:
822  *	Kernel context.
823  */
824 int
825 ql_send_lfa(ql_adapter_state_t *ha, lfa_cmd_t *lfa)
826 {
827 	int		rval;
828 	uint16_t	size;
829 	dma_mem_t	mem_desc;
830 	mbx_cmd_t	mc = {0};
831 	mbx_cmd_t	*mcp = &mc;
832 
833 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
834 
835 	/* LFA_CB sz = 4 16bit words subcommand + 10 16bit words header. */
836 	size = (uint16_t)((lfa->subcommand_length[0] + 10) << 1);
837 
838 	rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, (caddr_t)lfa, size);
839 	if (rval != QL_SUCCESS) {
840 		EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
841 		return (rval);
842 	}
843 
844 	mcp->mb[0] = MBC_SEND_LFA_COMMAND;
845 	mcp->mb[1] = (uint16_t)(size >> 1);
846 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
847 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
848 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
849 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
850 	mcp->in_mb = MBX_0;
851 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
852 	if (ha->flags & VP_ENABLED) {
853 		mcp->mb[9] = ha->vp_index;
854 		mcp->out_mb |= MBX_9;
855 	}
856 	mcp->timeout = MAILBOX_TOV;
857 	rval = ql_mailbox_command(ha, mcp);
858 
859 	ql_free_dma_resource(ha, &mem_desc);
860 
861 	if (rval != QL_SUCCESS) {
862 		EL(ha, "failed, rval = %xh\n", rval);
863 	} else {
864 		/*EMPTY*/
865 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
866 	}
867 
868 	return (rval);
869 }
870 
871 /*
872  * ql_clear_aca
873  *	Issue clear ACA mailbox command.
874  *
875  * Input:
876  *	ha:	adapter state pointer.
877  *	tq:	target queue pointer.
878  *	lun:	LUN.
879  *
880  * Returns:
881  *	ql local function return status code.
882  *
883  * Context:
884  *	Kernel context.
885  */
886 int
887 ql_clear_aca(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
888 {
889 	int		rval;
890 	mbx_cmd_t	mc = {0};
891 	mbx_cmd_t	*mcp = &mc;
892 
893 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
894 
895 	if (CFG_IST(ha, CFG_CTRL_242581)) {
896 		rval = ql_task_mgmt_iocb(ha, tq, lun, CF_CLEAR_ACA, 0);
897 	} else {
898 		mcp->mb[0] = MBC_CLEAR_ACA;
899 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
900 			mcp->mb[1] = tq->loop_id;
901 		} else {
902 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
903 		}
904 		mcp->mb[2] = lun;
905 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
906 		mcp->in_mb = MBX_0;
907 		mcp->timeout = MAILBOX_TOV;
908 		rval = ql_mailbox_command(ha, mcp);
909 	}
910 
911 	(void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
912 
913 	if (rval != QL_SUCCESS) {
914 		EL(ha, "failed, rval = %xh\n", rval);
915 	} else {
916 		/*EMPTY*/
917 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
918 	}
919 
920 	return (rval);
921 }
922 
923 /*
924  * ql_target_reset
925  *	Issue target reset mailbox command.
926  *
927  * Input:
928  *	ha:	adapter state pointer.
929  *	tq:	target queue pointer.
930  *	delay:	seconds.
931  *
932  * Returns:
933  *	ql local function return status code.
934  *
935  * Context:
936  *	Kernel context.
937  */
938 int
939 ql_target_reset(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t delay)
940 {
941 	ql_link_t	*link;
942 	uint16_t	index;
943 	int		rval;
944 	mbx_cmd_t	mc = {0};
945 	mbx_cmd_t	*mcp = &mc;
946 
947 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
948 
949 	if (CFG_IST(ha, CFG_CTRL_242581)) {
950 		/* queue = NULL, all targets. */
951 		if (tq == NULL) {
952 			for (index = 0; index < DEVICE_HEAD_LIST_SIZE;
953 			    index++) {
954 				for (link = ha->dev[index].first; link !=
955 				    NULL; link = link->next) {
956 					tq = link->base_address;
957 					if (!VALID_DEVICE_ID(ha,
958 					    tq->loop_id)) {
959 						continue;
960 					}
961 					rval = ql_task_mgmt_iocb(ha, tq, 0,
962 					    CF_TARGET_RESET, delay);
963 
964 					if (rval != QL_SUCCESS) {
965 						break;
966 					}
967 				}
968 
969 				if (link != NULL) {
970 					break;
971 				}
972 			}
973 			tq = NULL;
974 		} else {
975 			rval = ql_task_mgmt_iocb(ha, tq, 0, CF_TARGET_RESET,
976 			    delay);
977 		}
978 	} else {
979 		/* queue = NULL, all targets. */
980 		if (tq == NULL) {
981 			mcp->mb[0] = MBC_RESET;
982 			mcp->mb[1] = delay;
983 			mcp->out_mb = MBX_1|MBX_0;
984 		} else {
985 			mcp->mb[0] = MBC_TARGET_RESET;
986 			if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
987 				mcp->mb[1] = tq->loop_id;
988 			} else {
989 				mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
990 			}
991 			mcp->mb[2] = delay;
992 			mcp->out_mb = MBX_2|MBX_1|MBX_0;
993 		}
994 		mcp->in_mb = MBX_0;
995 		mcp->timeout = MAILBOX_TOV;
996 		rval = ql_mailbox_command(ha, mcp);
997 	}
998 
999 	tq == NULL ? (void) ql_marker(ha, 0, 0, MK_SYNC_ALL) :
1000 	    (void) ql_marker(ha, tq->loop_id, 0, MK_SYNC_ID);
1001 
1002 	if (rval != QL_SUCCESS) {
1003 		EL(ha, "failed, rval = %xh\n", rval);
1004 	} else {
1005 		/*EMPTY*/
1006 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1007 	}
1008 
1009 	return (rval);
1010 }
1011 
1012 /*
1013  * ql_abort_target
1014  *	Issue abort target mailbox command.
1015  *
1016  * Input:
1017  *	ha:	adapter state pointer.
1018  *	tq:	target queue pointer.
1019  *	delay:	in seconds.
1020  *
1021  * Returns:
1022  *	ql local function return status code.
1023  *
1024  * Context:
1025  *	Kernel context.
1026  */
1027 int
1028 ql_abort_target(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t delay)
1029 {
1030 	int		rval;
1031 	mbx_cmd_t	mc = {0};
1032 	mbx_cmd_t	*mcp = &mc;
1033 
1034 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1035 
1036 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1037 		rval = ql_task_mgmt_iocb(ha, tq, 0,
1038 		    CF_DO_NOT_SEND | CF_TARGET_RESET, delay);
1039 	} else {
1040 		mcp->mb[0] = MBC_ABORT_TARGET;
1041 		/* Don't send Task Mgt */
1042 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1043 			mcp->mb[1] = tq->loop_id;
1044 			mcp->mb[10] = BIT_0;
1045 			mcp->out_mb = MBX_10|MBX_2|MBX_1|MBX_0;
1046 		} else {
1047 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | BIT_0);
1048 			mcp->out_mb = MBX_2|MBX_1|MBX_0;
1049 		}
1050 		mcp->mb[2] = delay;
1051 		mcp->in_mb = MBX_0;
1052 		mcp->timeout = MAILBOX_TOV;
1053 		rval = ql_mailbox_command(ha, mcp);
1054 	}
1055 
1056 	(void) ql_marker(ha, tq->loop_id, 0, MK_SYNC_ID);
1057 
1058 	if (rval != QL_SUCCESS) {
1059 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1060 	} else {
1061 		/*EMPTY*/
1062 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1063 	}
1064 	return (rval);
1065 }
1066 
1067 /*
1068  * ql_lun_reset
1069  *	Issue LUN reset task management mailbox command.
1070  *
1071  * Input:
1072  *	ha:	adapter state pointer.
1073  *	tq:	target queue pointer.
1074  *	lun:	LUN.
1075  *
1076  * Returns:
1077  *	ql local function return status code.
1078  *
1079  * Context:
1080  *	Kernel context.
1081  */
1082 int
1083 ql_lun_reset(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1084 {
1085 	int		rval;
1086 	mbx_cmd_t	mc = {0};
1087 	mbx_cmd_t	*mcp = &mc;
1088 
1089 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1090 
1091 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1092 		rval = ql_task_mgmt_iocb(ha, tq, lun, CF_LUN_RESET, 0);
1093 	} else {
1094 		mcp->mb[0] = MBC_LUN_RESET;
1095 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1096 			mcp->mb[1] = tq->loop_id;
1097 		} else {
1098 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1099 		}
1100 		mcp->mb[2] = lun;
1101 		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1102 		mcp->in_mb = MBX_0;
1103 		mcp->timeout = MAILBOX_TOV;
1104 		rval = ql_mailbox_command(ha, mcp);
1105 	}
1106 
1107 	(void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1108 
1109 	if (rval != QL_SUCCESS) {
1110 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1111 	} else {
1112 		/*EMPTY*/
1113 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1114 	}
1115 	return (rval);
1116 }
1117 
1118 /*
1119  * ql_clear_task_set
1120  *	Issue clear task set mailbox command.
1121  *
1122  * Input:
1123  *	ha:	adapter state pointer.
1124  *	tq:	target queue pointer.
1125  *	lun:	LUN.
1126  *
1127  * Returns:
1128  *	ql local function return status code.
1129  *
1130  * Context:
1131  *	Kernel context.
1132  */
1133 int
1134 ql_clear_task_set(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1135 {
1136 	int		rval;
1137 	mbx_cmd_t	mc = {0};
1138 	mbx_cmd_t	*mcp = &mc;
1139 
1140 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1141 
1142 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1143 		rval = ql_task_mgmt_iocb(ha, tq, lun, CF_CLEAR_TASK_SET, 0);
1144 	} else {
1145 		mcp->mb[0] = MBC_CLEAR_TASK_SET;
1146 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1147 			mcp->mb[1] = tq->loop_id;
1148 		} else {
1149 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1150 		}
1151 		mcp->mb[2] = lun;
1152 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
1153 		mcp->in_mb = MBX_0;
1154 		mcp->timeout = MAILBOX_TOV;
1155 		rval = ql_mailbox_command(ha, mcp);
1156 	}
1157 
1158 	(void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1159 
1160 	if (rval != QL_SUCCESS) {
1161 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1162 	} else {
1163 		/*EMPTY*/
1164 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1165 	}
1166 
1167 	return (rval);
1168 }
1169 
1170 /*
1171  * ql_abort_task_set
1172  *	Issue abort task set mailbox command.
1173  *
1174  * Input:
1175  *	ha:	adapter state pointer.
1176  *	tq:	target queue pointer.
1177  *	lun:	LUN.
1178  *
1179  * Returns:
1180  *	ql local function return status code.
1181  *
1182  * Context:
1183  *	Kernel context.
1184  */
1185 int
1186 ql_abort_task_set(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1187 {
1188 	int		rval;
1189 	mbx_cmd_t	mc = {0};
1190 	mbx_cmd_t	*mcp = &mc;
1191 
1192 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1193 
1194 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1195 		rval = ql_task_mgmt_iocb(ha, tq, lun, CF_ABORT_TASK_SET, 0);
1196 	} else {
1197 		mcp->mb[0] = MBC_ABORT_TASK_SET;
1198 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1199 			mcp->mb[1] = tq->loop_id;
1200 		} else {
1201 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1202 		}
1203 		mcp->mb[2] = lun;
1204 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
1205 		mcp->in_mb = MBX_0;
1206 		mcp->timeout = MAILBOX_TOV;
1207 		rval = ql_mailbox_command(ha, mcp);
1208 	}
1209 
1210 	(void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1211 
1212 	if (rval != QL_SUCCESS) {
1213 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1214 	} else {
1215 		/*EMPTY*/
1216 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1217 	}
1218 
1219 	return (rval);
1220 }
1221 
1222 /*
1223  * ql_task_mgmt_iocb
1224  *	Function issues task management IOCB.
1225  *
1226  * Input:
1227  *	ha:	adapter state pointer.
1228  *	tq:	target queue pointer.
1229  *	lun:	LUN.
1230  *	flags:	control flags.
1231  *	delay:	seconds.
1232  *
1233  * Returns:
1234  *	ql local function return status code.
1235  *
1236  * Context:
1237  *	Kernel context
1238  */
1239 static int
1240 ql_task_mgmt_iocb(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun,
1241     uint32_t flags, uint16_t delay)
1242 {
1243 	ql_mbx_iocb_t	*pkt;
1244 	int		rval;
1245 	uint32_t	pkt_size;
1246 
1247 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1248 
1249 	pkt_size = sizeof (ql_mbx_iocb_t);
1250 	pkt = kmem_zalloc(pkt_size, KM_SLEEP);
1251 	if (pkt == NULL) {
1252 		EL(ha, "failed, kmem_zalloc\n");
1253 		return (QL_MEMORY_ALLOC_FAILED);
1254 	}
1255 
1256 	pkt->mgmt.entry_type = TASK_MGMT_TYPE;
1257 	pkt->mgmt.entry_count = 1;
1258 
1259 	pkt->mgmt.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
1260 	pkt->mgmt.delay = (uint16_t)LE_16(delay);
1261 	pkt->mgmt.timeout = LE_16(MAILBOX_TOV);
1262 	pkt->mgmt.fcp_lun[2] = LSB(lun);
1263 	pkt->mgmt.fcp_lun[3] = MSB(lun);
1264 	pkt->mgmt.control_flags = LE_32(flags);
1265 	pkt->mgmt.target_id[0] = tq->d_id.b.al_pa;
1266 	pkt->mgmt.target_id[1] = tq->d_id.b.area;
1267 	pkt->mgmt.target_id[2] = tq->d_id.b.domain;
1268 	pkt->mgmt.vp_index = ha->vp_index;
1269 
1270 	rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
1271 	if (rval == QL_SUCCESS && (pkt->sts24.entry_status & 0x3c) != 0) {
1272 		EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
1273 		    pkt->sts24.entry_status, tq->d_id.b24);
1274 		rval = QL_FUNCTION_PARAMETER_ERROR;
1275 	}
1276 
1277 	LITTLE_ENDIAN_16(&pkt->sts24.comp_status);
1278 
1279 	if (rval == QL_SUCCESS && pkt->sts24.comp_status != CS_COMPLETE) {
1280 		EL(ha, "failed, comp_status=%xh, d_id=%xh\n",
1281 		    pkt->sts24.comp_status, tq->d_id.b24);
1282 		rval = QL_FUNCTION_FAILED;
1283 	}
1284 
1285 	kmem_free(pkt, pkt_size);
1286 
1287 	if (rval != QL_SUCCESS) {
1288 		EL(ha, "failed, rval = %xh\n", rval);
1289 	} else {
1290 		/*EMPTY*/
1291 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1292 	}
1293 
1294 	return (rval);
1295 }
1296 
1297 /*
1298  * ql_loop_port_bypass
1299  *	Issue loop port bypass mailbox command.
1300  *
1301  * Input:
1302  *	ha:	adapter state pointer.
1303  *	tq:	target queue pointer.
1304  *
1305  * Returns:
1306  *	ql local function return status code.
1307  *
1308  * Context:
1309  *	Kernel context.
1310  */
1311 int
1312 ql_loop_port_bypass(ql_adapter_state_t *ha, ql_tgt_t *tq)
1313 {
1314 	int		rval;
1315 	mbx_cmd_t	mc = {0};
1316 	mbx_cmd_t	*mcp = &mc;
1317 
1318 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1319 
1320 	mcp->mb[0] = MBC_LOOP_PORT_BYPASS;
1321 
1322 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1323 		mcp->mb[1] = tq->d_id.b.al_pa;
1324 	} else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1325 		mcp->mb[1] = tq->loop_id;
1326 	} else {
1327 		mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1328 	}
1329 
1330 	mcp->out_mb = MBX_1|MBX_0;
1331 	mcp->in_mb = MBX_0;
1332 	mcp->timeout = MAILBOX_TOV;
1333 	rval = ql_mailbox_command(ha, mcp);
1334 
1335 	if (rval != QL_SUCCESS) {
1336 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1337 	} else {
1338 		/*EMPTY*/
1339 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1340 	}
1341 
1342 	return (rval);
1343 }
1344 
1345 /*
1346  * ql_loop_port_enable
1347  *	Issue loop port enable mailbox command.
1348  *
1349  * Input:
1350  *	ha:	adapter state pointer.
1351  *	tq:	target queue pointer.
1352  *
1353  * Returns:
1354  *	ql local function return status code.
1355  *
1356  * Context:
1357  *	Kernel context.
1358  */
1359 int
1360 ql_loop_port_enable(ql_adapter_state_t *ha, ql_tgt_t *tq)
1361 {
1362 	int		rval;
1363 	mbx_cmd_t	mc = {0};
1364 	mbx_cmd_t	*mcp = &mc;
1365 
1366 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1367 
1368 	mcp->mb[0] = MBC_LOOP_PORT_ENABLE;
1369 
1370 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1371 		mcp->mb[1] = tq->d_id.b.al_pa;
1372 	} else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1373 		mcp->mb[1] = tq->loop_id;
1374 	} else {
1375 		mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1376 	}
1377 	mcp->out_mb = MBX_1|MBX_0;
1378 	mcp->in_mb = MBX_0;
1379 	mcp->timeout = MAILBOX_TOV;
1380 	rval = ql_mailbox_command(ha, mcp);
1381 
1382 	if (rval != QL_SUCCESS) {
1383 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1384 	} else {
1385 		/*EMPTY*/
1386 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1387 	}
1388 
1389 	return (rval);
1390 }
1391 
1392 /*
1393  * ql_login_lport
1394  *	Issue login loop port mailbox command.
1395  *
1396  * Input:
1397  *	ha:		adapter state pointer.
1398  *	tq:		target queue pointer.
1399  *	loop_id:	FC loop id.
1400  *	opt:		options.
1401  *			LLF_NONE, LLF_PLOGI
1402  *
1403  * Returns:
1404  *	ql local function return status code.
1405  *
1406  * Context:
1407  *	Kernel context.
1408  */
1409 int
1410 ql_login_lport(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1411     uint16_t opt)
1412 {
1413 	int		rval;
1414 	uint16_t	flags;
1415 	ql_mbx_data_t	mr;
1416 	mbx_cmd_t	mc = {0};
1417 	mbx_cmd_t	*mcp = &mc;
1418 
1419 	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh, loop_id=%xh\n",
1420 	    ha->instance, tq->d_id.b24, loop_id);
1421 
1422 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1423 		flags = CF_CMD_PLOGI;
1424 		if ((opt & LLF_PLOGI) == 0) {
1425 			flags = (uint16_t)(flags | CFO_COND_PLOGI);
1426 		}
1427 		rval = ql_log_iocb(ha, tq, loop_id, flags, &mr);
1428 	} else {
1429 		mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
1430 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1431 			mcp->mb[1] = loop_id;
1432 		} else {
1433 			mcp->mb[1] = (uint16_t)(loop_id << 8);
1434 		}
1435 		mcp->mb[2] = opt;
1436 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
1437 		mcp->in_mb = MBX_0;
1438 		mcp->timeout = MAILBOX_TOV;
1439 		rval = ql_mailbox_command(ha, mcp);
1440 	}
1441 
1442 	if (rval != QL_SUCCESS) {
1443 		EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", tq->d_id.b24,
1444 		    loop_id, rval);
1445 	} else {
1446 		/*EMPTY*/
1447 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1448 	}
1449 
1450 	return (rval);
1451 }
1452 
1453 /*
1454  * ql_login_fport
1455  *	Issue login fabric port mailbox command.
1456  *
1457  * Input:
1458  *	ha:		adapter state pointer.
1459  *	tq:		target queue pointer.
1460  *	loop_id:	FC loop id.
1461  *	opt:		options.
1462  *			LFF_NONE, LFF_NO_PLOGI, LFF_NO_PRLI
1463  *	mr:		pointer for mailbox data.
1464  *
1465  * Returns:
1466  *	ql local function return status code.
1467  *
1468  * Context:
1469  *	Kernel context.
1470  */
1471 int
1472 ql_login_fport(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1473     uint16_t opt, ql_mbx_data_t *mr)
1474 {
1475 	int		rval;
1476 	uint16_t	flags;
1477 	mbx_cmd_t	mc = {0};
1478 	mbx_cmd_t	*mcp = &mc;
1479 
1480 	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh, loop_id=%xh\n",
1481 	    ha->instance, tq->d_id.b24, loop_id);
1482 
1483 	if ((tq->d_id.b24 & 0xffffff) == 0xfffffa) {
1484 		opt = (uint16_t)(opt | LFF_NO_PRLI);
1485 	}
1486 
1487 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1488 		flags = CF_CMD_PLOGI;
1489 		if (opt & LFF_NO_PLOGI) {
1490 			flags = (uint16_t)(flags | CFO_COND_PLOGI);
1491 		}
1492 		if (opt & LFF_NO_PRLI) {
1493 			flags = (uint16_t)(flags | CFO_SKIP_PRLI);
1494 		}
1495 		rval = ql_log_iocb(ha, tq, loop_id, flags, mr);
1496 	} else {
1497 		mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
1498 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1499 			mcp->mb[1] = loop_id;
1500 			mcp->mb[10] = opt;
1501 			mcp->out_mb = MBX_10|MBX_3|MBX_2|MBX_1|MBX_0;
1502 		} else {
1503 			mcp->mb[1] = (uint16_t)(loop_id << 8 | opt);
1504 			mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1505 		}
1506 		mcp->mb[2] = MSW(tq->d_id.b24);
1507 		mcp->mb[3] = LSW(tq->d_id.b24);
1508 		mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
1509 		mcp->timeout = MAILBOX_TOV;
1510 		rval = ql_mailbox_command(ha, mcp);
1511 
1512 		/* Return mailbox data. */
1513 		if (mr != NULL) {
1514 			mr->mb[0] = mcp->mb[0];
1515 			mr->mb[1] = mcp->mb[1];
1516 			mr->mb[2] = mcp->mb[2];
1517 			mr->mb[6] = mcp->mb[6];
1518 			mr->mb[7] = mcp->mb[7];
1519 		}
1520 	}
1521 
1522 	if (rval != QL_SUCCESS) {
1523 		EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh, mb1=%02xh, "
1524 		    "mb2=%04x\n", tq->d_id.b24, loop_id, rval, mr->mb[1],
1525 		    mr->mb[2]);
1526 	} else {
1527 		/*EMPTY*/
1528 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1529 	}
1530 
1531 	return (rval);
1532 }
1533 
1534 /*
1535  * ql_logout_fabric_port
1536  *	Issue logout fabric port mailbox command.
1537  *
1538  * Input:
1539  *	ha:	adapter state pointer.
1540  *	tq:	target queue pointer.
1541  *
1542  * Returns:
1543  *	ql local function return status code.
1544  *
1545  * Context:
1546  *	Kernel context.
1547  */
1548 int
1549 ql_logout_fabric_port(ql_adapter_state_t *ha, ql_tgt_t *tq)
1550 {
1551 	int		rval;
1552 	uint16_t	flag;
1553 	ql_mbx_data_t	mr;
1554 	mbx_cmd_t	mc = {0};
1555 	mbx_cmd_t	*mcp = &mc;
1556 
1557 	QL_PRINT_3(CE_CONT, "(%d): started, loop_id=%xh d_id=%xh\n",
1558 	    ha->instance, tq->loop_id, tq->d_id.b24);
1559 
1560 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1561 		flag = (uint16_t)(RESERVED_LOOP_ID(ha, tq->loop_id) ?
1562 		    CFO_EXPLICIT_LOGO |CF_CMD_LOGO | CFO_FREE_N_PORT_HANDLE :
1563 		    CFO_IMPLICIT_LOGO |CF_CMD_LOGO | CFO_FREE_N_PORT_HANDLE);
1564 		rval = ql_log_iocb(ha, tq, tq->loop_id, flag, &mr);
1565 	} else {
1566 		flag = (uint16_t)(RESERVED_LOOP_ID(ha, tq->loop_id) ?  1 : 0);
1567 		mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
1568 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1569 			mcp->mb[1] = tq->loop_id;
1570 			mcp->mb[10] = flag;
1571 			mcp->out_mb = MBX_10|MBX_1|MBX_0;
1572 		} else {
1573 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | flag);
1574 			mcp->out_mb = MBX_1|MBX_0;
1575 		}
1576 		mcp->in_mb = MBX_0;
1577 		mcp->timeout = MAILBOX_TOV;
1578 		rval = ql_mailbox_command(ha, mcp);
1579 	}
1580 
1581 	if (rval != QL_SUCCESS) {
1582 		EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", rval,
1583 		    tq->d_id.b24, tq->loop_id);
1584 	} else {
1585 		/*EMPTY*/
1586 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1587 	}
1588 
1589 	return (rval);
1590 }
1591 
1592 /*
1593  * ql_log_iocb
1594  *	Function issues login/logout IOCB.
1595  *
1596  * Input:
1597  *	ha:		adapter state pointer.
1598  *	tq:		target queue pointer.
1599  *	loop_id:	FC Loop ID.
1600  *	flags:		control flags.
1601  *	mr:		pointer for mailbox data.
1602  *
1603  * Returns:
1604  *	ql local function return status code.
1605  *
1606  * Context:
1607  *	Kernel context.
1608  */
1609 int
1610 ql_log_iocb(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1611     uint16_t flags, ql_mbx_data_t *mr)
1612 {
1613 	ql_mbx_iocb_t	*pkt;
1614 	int		rval;
1615 	uint32_t	pkt_size;
1616 
1617 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1618 
1619 	pkt_size = sizeof (ql_mbx_iocb_t);
1620 	pkt = kmem_zalloc(pkt_size, KM_SLEEP);
1621 	if (pkt == NULL) {
1622 		EL(ha, "failed, kmem_zalloc\n");
1623 		return (QL_MEMORY_ALLOC_FAILED);
1624 	}
1625 
1626 	pkt->log.entry_type = LOG_TYPE;
1627 	pkt->log.entry_count = 1;
1628 	pkt->log.n_port_hdl = (uint16_t)LE_16(loop_id);
1629 	pkt->log.control_flags = (uint16_t)LE_16(flags);
1630 	pkt->log.port_id[0] = tq->d_id.b.al_pa;
1631 	pkt->log.port_id[1] = tq->d_id.b.area;
1632 	pkt->log.port_id[2] = tq->d_id.b.domain;
1633 	pkt->log.vp_index = ha->vp_index;
1634 
1635 	rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
1636 	if (rval == QL_SUCCESS && (pkt->log.entry_status & 0x3c) != 0) {
1637 		EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
1638 		    pkt->log.entry_status, tq->d_id.b24);
1639 		rval = QL_FUNCTION_PARAMETER_ERROR;
1640 	}
1641 
1642 	if (rval == QL_SUCCESS) {
1643 		if (pkt->log.rsp_size == 0xB) {
1644 			LITTLE_ENDIAN_32(&pkt->log.io_param[5]);
1645 			tq->cmn_features = MSW(pkt->log.io_param[5]);
1646 			LITTLE_ENDIAN_32(&pkt->log.io_param[6]);
1647 			tq->conc_sequences = MSW(pkt->log.io_param[6]);
1648 			tq->relative_offset = LSW(pkt->log.io_param[6]);
1649 			LITTLE_ENDIAN_32(&pkt->log.io_param[9]);
1650 			tq->class3_recipient_ctl = MSW(pkt->log.io_param[9]);
1651 			tq->class3_conc_sequences = LSW(pkt->log.io_param[9]);
1652 			LITTLE_ENDIAN_32(&pkt->log.io_param[10]);
1653 			tq->class3_open_sequences_per_exch =
1654 			    MSW(pkt->log.io_param[10]);
1655 			tq->prli_payload_length = 0x14;
1656 		}
1657 		if (mr != NULL) {
1658 			LITTLE_ENDIAN_16(&pkt->log.status);
1659 			LITTLE_ENDIAN_32(&pkt->log.io_param[0]);
1660 			LITTLE_ENDIAN_32(&pkt->log.io_param[1]);
1661 
1662 			if (pkt->log.status != CS_COMPLETE) {
1663 				EL(ha, "failed, status=%xh, iop0=%xh, iop1="
1664 				    "%xh\n", pkt->log.status,
1665 				    pkt->log.io_param[0],
1666 				    pkt->log.io_param[1]);
1667 
1668 				switch (pkt->log.io_param[0]) {
1669 				case CS0_NO_LINK:
1670 				case CS0_FIRMWARE_NOT_READY:
1671 					mr->mb[0] = MBS_COMMAND_ERROR;
1672 					mr->mb[1] = 1;
1673 					break;
1674 				case CS0_NO_IOCB:
1675 				case CS0_NO_PCB_ALLOCATED:
1676 					mr->mb[0] = MBS_COMMAND_ERROR;
1677 					mr->mb[1] = 2;
1678 					break;
1679 				case CS0_NO_EXCH_CTRL_BLK:
1680 					mr->mb[0] = MBS_COMMAND_ERROR;
1681 					mr->mb[1] = 3;
1682 					break;
1683 				case CS0_COMMAND_FAILED:
1684 					mr->mb[0] = MBS_COMMAND_ERROR;
1685 					mr->mb[1] = 4;
1686 					switch (LSB(pkt->log.io_param[1])) {
1687 					case CS1_PLOGI_RESPONSE_FAILED:
1688 						mr->mb[2] = 3;
1689 						break;
1690 					case CS1_PRLI_FAILED:
1691 						mr->mb[2] = 4;
1692 						break;
1693 					case CS1_PRLI_RESPONSE_FAILED:
1694 						mr->mb[2] = 5;
1695 						break;
1696 					case CS1_COMMAND_LOGGED_OUT:
1697 						mr->mb[2] = 7;
1698 						break;
1699 					case CS1_PLOGI_FAILED:
1700 					default:
1701 						EL(ha, "log iop1 = %xh\n",
1702 						    LSB(pkt->log.io_param[1]))
1703 						mr->mb[2] = 2;
1704 						break;
1705 					}
1706 					break;
1707 				case CS0_PORT_NOT_LOGGED_IN:
1708 					mr->mb[0] = MBS_COMMAND_ERROR;
1709 					mr->mb[1] = 4;
1710 					mr->mb[2] = 7;
1711 					break;
1712 				case CS0_NO_FLOGI_ACC:
1713 				case CS0_NO_FABRIC_PRESENT:
1714 					mr->mb[0] = MBS_COMMAND_ERROR;
1715 					mr->mb[1] = 5;
1716 					break;
1717 				case CS0_ELS_REJECT_RECEIVED:
1718 					mr->mb[0] = MBS_COMMAND_ERROR;
1719 					mr->mb[1] = 0xd;
1720 					break;
1721 				case CS0_PORT_ID_USED:
1722 					mr->mb[0] = MBS_PORT_ID_USED;
1723 					mr->mb[1] = LSW(pkt->log.io_param[1]);
1724 					break;
1725 				case CS0_N_PORT_HANDLE_USED:
1726 					mr->mb[0] = MBS_LOOP_ID_USED;
1727 					mr->mb[1] = MSW(pkt->log.io_param[1]);
1728 					mr->mb[2] = LSW(pkt->log.io_param[1]);
1729 					break;
1730 				case CS0_NO_N_PORT_HANDLE_AVAILABLE:
1731 					mr->mb[0] = MBS_ALL_IDS_IN_USE;
1732 					break;
1733 				case CS0_CMD_PARAMETER_ERROR:
1734 				default:
1735 					EL(ha, "pkt->log iop[0]=%xh\n",
1736 					    pkt->log.io_param[0]);
1737 					mr->mb[0] =
1738 					    MBS_COMMAND_PARAMETER_ERROR;
1739 					break;
1740 				}
1741 			} else {
1742 				QL_PRINT_3(CE_CONT, "(%d): status=%xh\n",
1743 				    ha->instance, pkt->log.status);
1744 
1745 				mr->mb[0] = MBS_COMMAND_COMPLETE;
1746 				mr->mb[1] = (uint16_t)
1747 				    (pkt->log.io_param[0] & BIT_4 ? 0 : BIT_0);
1748 				if (pkt->log.io_param[0] & BIT_8) {
1749 					mr->mb[1] = (uint16_t)
1750 					    (mr->mb[1] | BIT_1);
1751 				}
1752 			}
1753 			rval = mr->mb[0];
1754 		}
1755 
1756 	}
1757 
1758 	kmem_free(pkt, pkt_size);
1759 
1760 	if (rval != QL_SUCCESS) {
1761 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1762 	} else {
1763 		/*EMPTY*/
1764 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1765 	}
1766 
1767 	return (rval);
1768 }
1769 
1770 /*
1771  * ql_get_port_database
1772  *	Issue get port database mailbox command
1773  *	and copy context to device queue.
1774  *
1775  * Input:
1776  *	ha:	adapter state pointer.
1777  *	tq:	target queue pointer.
1778  *	opt:	options.
1779  *		PDF_NONE, PDF_PLOGI, PDF_ADISC
1780  * Returns:
1781  *	ql local function return status code.
1782  *
1783  * Context:
1784  *	Kernel context.
1785  */
1786 int
1787 ql_get_port_database(ql_adapter_state_t *ha, ql_tgt_t *tq, uint8_t opt)
1788 {
1789 	int			rval;
1790 	dma_mem_t		mem_desc;
1791 	mbx_cmd_t		mc = {0};
1792 	mbx_cmd_t		*mcp = &mc;
1793 	port_database_23_t	*pd23;
1794 
1795 	ASSERT(!MUTEX_HELD(&ha->mutex));
1796 
1797 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1798 
1799 	pd23 = (port_database_23_t *)kmem_zalloc(PORT_DATABASE_SIZE, KM_SLEEP);
1800 	if (pd23 == NULL) {
1801 		rval = QL_MEMORY_ALLOC_FAILED;
1802 		EL(ha, "failed, rval = %xh\n", rval);
1803 		return (rval);
1804 	}
1805 
1806 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
1807 	    PORT_DATABASE_SIZE)) != QL_SUCCESS) {
1808 		return (QL_MEMORY_ALLOC_FAILED);
1809 	}
1810 
1811 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1812 		mcp->mb[0] = MBC_GET_PORT_DATABASE;
1813 		mcp->mb[1] = tq->loop_id;
1814 		mcp->mb[4] = CHAR_TO_SHORT(tq->d_id.b.al_pa, tq->d_id.b.area);
1815 		mcp->mb[5] = (uint16_t)tq->d_id.b.domain;
1816 		mcp->mb[9] = ha->vp_index;
1817 		mcp->mb[10] = (uint16_t)(opt | PDF_ADISC);
1818 		mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|
1819 		    MBX_2|MBX_1|MBX_0;
1820 	} else {
1821 		mcp->mb[0] = (uint16_t)(opt == PDF_NONE ?
1822 		    MBC_GET_PORT_DATABASE : MBC_ENHANCED_GET_PORT_DATABASE);
1823 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1824 			mcp->mb[1] = tq->loop_id;
1825 			mcp->mb[10] = opt;
1826 			mcp->out_mb = MBX_10|MBX_7|MBX_6|MBX_3|
1827 			    MBX_2|MBX_1|MBX_0;
1828 		} else {
1829 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | opt);
1830 			mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1831 		}
1832 	}
1833 
1834 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
1835 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
1836 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
1837 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
1838 	mcp->in_mb = MBX_0;
1839 	mcp->timeout = MAILBOX_TOV;
1840 	rval = ql_mailbox_command(ha, mcp);
1841 
1842 	if (rval == QL_SUCCESS) {
1843 		ql_get_mbox_dma_data(&mem_desc, (caddr_t)pd23);
1844 	}
1845 
1846 	ql_free_dma_resource(ha, &mem_desc);
1847 
1848 	if (rval == QL_SUCCESS) {
1849 		if (CFG_IST(ha, CFG_CTRL_242581)) {
1850 			port_database_24_t *pd24 = (port_database_24_t *)pd23;
1851 
1852 			tq->master_state = pd24->current_login_state;
1853 			tq->slave_state = pd24->last_stable_login_state;
1854 			if (PD_PORT_LOGIN(tq)) {
1855 				/* Names are big endian. */
1856 				bcopy((void *)&pd24->port_name[0],
1857 				    (void *)&tq->port_name[0], 8);
1858 				bcopy((void *)&pd24->node_name[0],
1859 				    (void *)&tq->node_name[0], 8);
1860 				tq->hard_addr.b.al_pa = pd24->hard_address[2];
1861 				tq->hard_addr.b.area = pd24->hard_address[1];
1862 				tq->hard_addr.b.domain = pd24->hard_address[0];
1863 				tq->class3_rcv_data_size =
1864 				    pd24->receive_data_size;
1865 				LITTLE_ENDIAN_16(&tq->class3_rcv_data_size);
1866 				tq->prli_svc_param_word_0 =
1867 				    pd24->PRLI_service_parameter_word_0;
1868 				LITTLE_ENDIAN_16(&tq->prli_svc_param_word_0);
1869 				tq->prli_svc_param_word_3 =
1870 				    pd24->PRLI_service_parameter_word_3;
1871 				LITTLE_ENDIAN_16(&tq->prli_svc_param_word_3);
1872 			}
1873 		} else {
1874 			tq->master_state = pd23->master_state;
1875 			tq->slave_state = pd23->slave_state;
1876 			if (PD_PORT_LOGIN(tq)) {
1877 				/* Names are big endian. */
1878 				bcopy((void *)&pd23->port_name[0],
1879 				    (void *)&tq->port_name[0], 8);
1880 				bcopy((void *)&pd23->node_name[0],
1881 				    (void *)&tq->node_name[0], 8);
1882 				tq->hard_addr.b.al_pa = pd23->hard_address[2];
1883 				tq->hard_addr.b.area = pd23->hard_address[1];
1884 				tq->hard_addr.b.domain = pd23->hard_address[0];
1885 				tq->cmn_features = pd23->common_features;
1886 				LITTLE_ENDIAN_16(&tq->cmn_features);
1887 				tq->conc_sequences =
1888 				    pd23->total_concurrent_sequences;
1889 				LITTLE_ENDIAN_16(&tq->conc_sequences);
1890 				tq->relative_offset =
1891 				    pd23->RO_by_information_category;
1892 				LITTLE_ENDIAN_16(&tq->relative_offset);
1893 				tq->class3_recipient_ctl = pd23->recipient;
1894 				LITTLE_ENDIAN_16(&tq->class3_recipient_ctl);
1895 				tq->class3_rcv_data_size =
1896 				    pd23->receive_data_size;
1897 				LITTLE_ENDIAN_16(&tq->class3_rcv_data_size);
1898 				tq->class3_conc_sequences =
1899 				    pd23->concurrent_sequences;
1900 				LITTLE_ENDIAN_16(&tq->class3_conc_sequences);
1901 				tq->class3_open_sequences_per_exch =
1902 				    pd23->open_sequences_per_exchange;
1903 				LITTLE_ENDIAN_16(
1904 				    &tq->class3_open_sequences_per_exch);
1905 				tq->prli_payload_length =
1906 				    pd23->PRLI_payload_length;
1907 				LITTLE_ENDIAN_16(&tq->prli_payload_length);
1908 				tq->prli_svc_param_word_0 =
1909 				    pd23->PRLI_service_parameter_word_0;
1910 				LITTLE_ENDIAN_16(&tq->prli_svc_param_word_0);
1911 				tq->prli_svc_param_word_3 =
1912 				    pd23->PRLI_service_parameter_word_3;
1913 				LITTLE_ENDIAN_16(&tq->prli_svc_param_word_3);
1914 			}
1915 		}
1916 
1917 		if (!PD_PORT_LOGIN(tq)) {
1918 			EL(ha, "d_id=%xh, loop_id=%xh, not logged in "
1919 			    "master=%xh, slave=%xh\n", tq->d_id.b24,
1920 			    tq->loop_id, tq->master_state, tq->slave_state);
1921 			rval = QL_NOT_LOGGED_IN;
1922 		} else {
1923 			tq->flags = tq->prli_svc_param_word_3 &
1924 			    PRLI_W3_TARGET_FUNCTION ?
1925 			    tq->flags & ~TQF_INITIATOR_DEVICE :
1926 			    tq->flags | TQF_INITIATOR_DEVICE;
1927 
1928 			if ((tq->flags & TQF_INITIATOR_DEVICE) == 0) {
1929 				tq->flags = tq->prli_svc_param_word_3 &
1930 				    PRLI_W3_RETRY ?
1931 				    tq->flags | TQF_TAPE_DEVICE :
1932 				    tq->flags & ~TQF_TAPE_DEVICE;
1933 			} else {
1934 				tq->flags &= ~TQF_TAPE_DEVICE;
1935 			}
1936 		}
1937 	}
1938 
1939 	kmem_free(pd23, PORT_DATABASE_SIZE);
1940 
1941 	if ((rval != QL_SUCCESS) && (rval != QL_PARAMETER_ERROR)) {
1942 		EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", tq->d_id.b24,
1943 		    tq->loop_id, rval);
1944 	} else {
1945 		/*EMPTY*/
1946 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1947 	}
1948 
1949 	return (rval);
1950 }
1951 
1952 /*
1953  * ql_get_loop_position_map
1954  *	Issue get loop position map mailbox command.
1955  *
1956  * Input:
1957  *	ha:	adapter state pointer.
1958  *	size:	size of data buffer.
1959  *	bufp:	data pointer for DMA data.
1960  *
1961  * Returns:
1962  *	ql local function return status code.
1963  *
1964  * Context:
1965  *	Kernel context.
1966  */
1967 int
1968 ql_get_loop_position_map(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
1969 {
1970 	int		rval;
1971 	dma_mem_t	mem_desc;
1972 	mbx_cmd_t	mc = {0};
1973 	mbx_cmd_t	*mcp = &mc;
1974 
1975 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1976 
1977 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
1978 	    (uint32_t)size)) != QL_SUCCESS) {
1979 		EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
1980 		return (QL_MEMORY_ALLOC_FAILED);
1981 	}
1982 
1983 	mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP;
1984 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
1985 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
1986 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
1987 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
1988 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
1989 	mcp->in_mb = MBX_1|MBX_0;
1990 	mcp->timeout = MAILBOX_TOV;
1991 	rval = ql_mailbox_command(ha, mcp);
1992 
1993 	if (rval == QL_SUCCESS) {
1994 		ql_get_mbox_dma_data(&mem_desc, bufp);
1995 	}
1996 
1997 	ql_free_dma_resource(ha, &mem_desc);
1998 
1999 	if (rval != QL_SUCCESS) {
2000 		EL(ha, "failed=%xh\n", rval);
2001 	} else {
2002 		/*EMPTY*/
2003 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2004 	}
2005 
2006 	return (rval);
2007 }
2008 
2009 /*
2010  * ql_set_rnid_params
2011  *	Issue set RNID parameters mailbox command.
2012  *
2013  * Input:
2014  *	ha:		adapter state pointer.
2015  *	size:		size of data buffer.
2016  *	bufp:		data pointer for DMA data.
2017  *
2018  * Returns:
2019  *	ql local function return status code.
2020  *
2021  * Context:
2022  *	Kernel context.
2023  */
2024 int
2025 ql_set_rnid_params(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
2026 {
2027 	int		rval;
2028 	dma_mem_t	mem_desc;
2029 	mbx_cmd_t	mc = {0};
2030 	mbx_cmd_t	*mcp = &mc;
2031 
2032 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2033 
2034 	if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bufp,
2035 	    (uint32_t)size)) != QL_SUCCESS) {
2036 		EL(ha, "failed, setup_mbox_dma_transfer: %x\n", rval);
2037 		return (rval);
2038 	}
2039 
2040 	mcp->mb[0] = MBC_SET_PARAMETERS;
2041 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2042 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2043 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2044 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2045 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2046 	mcp->in_mb = MBX_0;
2047 	mcp->timeout = MAILBOX_TOV;
2048 	rval = ql_mailbox_command(ha, mcp);
2049 
2050 	ql_free_dma_resource(ha, &mem_desc);
2051 
2052 	if (rval != QL_SUCCESS) {
2053 		EL(ha, "failed, rval = %xh\n", rval);
2054 	} else {
2055 		/*EMPTY*/
2056 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2057 	}
2058 
2059 	return (rval);
2060 }
2061 
2062 /*
2063  * ql_send_rnid_els
2064  *	Issue a send node identfication data mailbox command.
2065  *
2066  * Input:
2067  *	ha:		adapter state pointer.
2068  *	loop_id:	FC loop id.
2069  *	opt:		options.
2070  *	size:		size of data buffer.
2071  *	bufp:		data pointer for DMA data.
2072  *
2073  * Returns:
2074  *	ql local function return status code.
2075  *
2076  * Context:
2077  *	Kernel context.
2078  */
2079 int
2080 ql_send_rnid_els(ql_adapter_state_t *ha, uint16_t loop_id, uint8_t opt,
2081     size_t size, caddr_t bufp)
2082 {
2083 	int		rval;
2084 	dma_mem_t	mem_desc;
2085 	mbx_cmd_t	mc = {0};
2086 	mbx_cmd_t	*mcp = &mc;
2087 
2088 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2089 
2090 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2091 	    (uint32_t)size)) != QL_SUCCESS) {
2092 		return (QL_MEMORY_ALLOC_FAILED);
2093 	}
2094 
2095 	mcp->mb[0] = MBC_SEND_RNID_ELS;
2096 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2097 		mcp->mb[1] = loop_id;
2098 		mcp->mb[9] = ha->vp_index;
2099 		mcp->mb[10] = opt;
2100 		mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2101 	} else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2102 		mcp->mb[1] = loop_id;
2103 		mcp->mb[10] = opt;
2104 		mcp->out_mb = MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2105 	} else {
2106 		mcp->mb[1] = (uint16_t)(loop_id << 8 | opt);
2107 		mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2108 	}
2109 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2110 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2111 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2112 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2113 	mcp->in_mb = MBX_0;
2114 	mcp->timeout = MAILBOX_TOV;
2115 	rval = ql_mailbox_command(ha, mcp);
2116 
2117 	if (rval == QL_SUCCESS) {
2118 		ql_get_mbox_dma_data(&mem_desc, bufp);
2119 	}
2120 
2121 	ql_free_dma_resource(ha, &mem_desc);
2122 
2123 	if (rval != QL_SUCCESS) {
2124 		EL(ha, "failed, rval = %xh\n", rval);
2125 	} else {
2126 		/*EMPTY*/
2127 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2128 	}
2129 
2130 	return (rval);
2131 }
2132 
2133 /*
2134  * ql_get_rnid_params
2135  *	Issue get RNID parameters mailbox command.
2136  *
2137  * Input:
2138  *	ha:	adapter state pointer.
2139  *	size:	size of data buffer.
2140  *	bufp:	data pointer for DMA data.
2141  *
2142  * Returns:
2143  *	ql local function return status code.
2144  *
2145  * Context:
2146  *	Kernel context.
2147  */
2148 int
2149 ql_get_rnid_params(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
2150 {
2151 	int		rval;
2152 	dma_mem_t	mem_desc;
2153 	mbx_cmd_t	mc = {0};
2154 	mbx_cmd_t	*mcp = &mc;
2155 
2156 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2157 
2158 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2159 	    (uint32_t)size)) != QL_SUCCESS) {
2160 		return (QL_MEMORY_ALLOC_FAILED);
2161 	}
2162 
2163 	mcp->mb[0] = MBC_GET_PARAMETERS;
2164 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2165 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2166 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2167 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2168 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2169 	mcp->in_mb = MBX_0;
2170 	mcp->timeout = MAILBOX_TOV;
2171 	rval = ql_mailbox_command(ha, mcp);
2172 
2173 	if (rval == QL_SUCCESS) {
2174 		ql_get_mbox_dma_data(&mem_desc, bufp);
2175 	}
2176 
2177 	ql_free_dma_resource(ha, &mem_desc);
2178 
2179 	if (rval != QL_SUCCESS) {
2180 		EL(ha, "failed=%xh\n", rval);
2181 	} else {
2182 		/*EMPTY*/
2183 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2184 	}
2185 
2186 	return (rval);
2187 }
2188 
2189 /*
2190  * ql_get_link_status
2191  *	Issue get link status mailbox command.
2192  *
2193  * Input:
2194  *	ha:		adapter state pointer.
2195  *	loop_id:	FC loop id or n_port_hdl.
2196  *	size:		size of data buffer.
2197  *	bufp:		data pointer for DMA data.
2198  *	port_no:	port number to query.
2199  *
2200  * Returns:
2201  *	ql local function return status code.
2202  *
2203  * Context:
2204  *	Kernel context.
2205  */
2206 int
2207 ql_get_link_status(ql_adapter_state_t *ha, uint16_t loop_id, size_t size,
2208     caddr_t bufp, uint8_t port_no)
2209 {
2210 	dma_mem_t	mem_desc;
2211 	mbx_cmd_t	mc = {0};
2212 	mbx_cmd_t	*mcp = &mc;
2213 	int		rval = QL_SUCCESS;
2214 	int		retry = 0;
2215 
2216 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2217 
2218 	do {
2219 		if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2220 		    (uint32_t)size)) != QL_SUCCESS) {
2221 			EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
2222 			return (QL_MEMORY_ALLOC_FAILED);
2223 		}
2224 
2225 		mcp->mb[0] = MBC_GET_LINK_STATUS;
2226 		if (CFG_IST(ha, CFG_CTRL_242581)) {
2227 			if (loop_id == ha->loop_id) {
2228 				mcp->mb[0] = MBC_GET_STATUS_COUNTS;
2229 				mcp->mb[8] = (uint16_t)(size >> 2);
2230 				mcp->out_mb = MBX_10|MBX_8;
2231 			} else {
2232 				mcp->mb[1] = loop_id;
2233 				mcp->mb[4] = port_no;
2234 				mcp->mb[10] = (uint16_t)(retry ? BIT_3 : 0);
2235 				mcp->out_mb = MBX_10|MBX_4;
2236 			}
2237 		} else {
2238 			if (retry) {
2239 				port_no = (uint8_t)(port_no | BIT_3);
2240 			}
2241 			if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2242 				mcp->mb[1] = loop_id;
2243 				mcp->mb[10] = port_no;
2244 				mcp->out_mb = MBX_10;
2245 			} else {
2246 				mcp->mb[1] = (uint16_t)((loop_id << 8) |
2247 				    port_no);
2248 				mcp->out_mb = 0;
2249 			}
2250 		}
2251 		mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2252 		mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2253 		mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2254 		mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2255 		mcp->in_mb = MBX_1|MBX_0;
2256 		mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2257 		mcp->timeout = MAILBOX_TOV;
2258 
2259 		rval = ql_mailbox_command(ha, mcp);
2260 
2261 		if (rval == QL_SUCCESS) {
2262 			ql_get_mbox_dma_data(&mem_desc, bufp);
2263 		}
2264 
2265 		ql_free_dma_resource(ha, &mem_desc);
2266 
2267 		if (rval != QL_SUCCESS) {
2268 			EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
2269 		}
2270 
2271 		/*
2272 		 * Some of the devices want d_id in the payload,
2273 		 * strictly as per standard. Let's retry.
2274 		 */
2275 
2276 	} while (rval == QL_COMMAND_ERROR && !retry++);
2277 
2278 	if (rval != QL_SUCCESS) {
2279 		EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
2280 	} else {
2281 		/*EMPTY*/
2282 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2283 	}
2284 
2285 	return (rval);
2286 }
2287 
2288 /*
2289  * ql_get_status_counts
2290  *	Issue get adapter link status counts mailbox command.
2291  *
2292  * Input:
2293  *	ha:		adapter state pointer.
2294  *	loop_id:	FC loop id or n_port_hdl.
2295  *	size:		size of data buffer.
2296  *	bufp:		data pointer for DMA data.
2297  *	port_no:	port number to query.
2298  *
2299  * Returns:
2300  *	ql local function return status code.
2301  *
2302  * Context:
2303  *	Kernel context.
2304  */
2305 int
2306 ql_get_status_counts(ql_adapter_state_t *ha, uint16_t loop_id, size_t size,
2307     caddr_t bufp, uint8_t port_no)
2308 {
2309 	dma_mem_t	mem_desc;
2310 	mbx_cmd_t	mc = {0};
2311 	mbx_cmd_t	*mcp = &mc;
2312 	int		rval = QL_SUCCESS;
2313 
2314 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2315 
2316 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2317 	    (uint32_t)size)) != QL_SUCCESS) {
2318 		EL(ha, "setup_mbox_dma_resources failed: %x\n", rval);
2319 		return (QL_MEMORY_ALLOC_FAILED);
2320 	}
2321 
2322 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2323 		mcp->mb[0] = MBC_GET_STATUS_COUNTS;
2324 		mcp->mb[8] = (uint16_t)(size / 4);
2325 		mcp->out_mb = MBX_10|MBX_8;
2326 	} else {
2327 		mcp->mb[0] = MBC_GET_LINK_STATUS;
2328 
2329 		/* allows reporting when link is down */
2330 		if (CFG_IST(ha, CFG_CTRL_2200) == 0) {
2331 			port_no = (uint8_t)(port_no | BIT_6);
2332 		}
2333 
2334 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2335 			mcp->mb[1] = loop_id;
2336 			mcp->mb[10] = port_no;
2337 			mcp->out_mb = MBX_10|MBX_1;
2338 		} else {
2339 			mcp->mb[1] = (uint16_t)((loop_id << 8) |
2340 			    port_no);
2341 			mcp->out_mb = MBX_1;
2342 		}
2343 	}
2344 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2345 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2346 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2347 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2348 	mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2349 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
2350 	mcp->timeout = MAILBOX_TOV;
2351 	rval = ql_mailbox_command(ha, mcp);
2352 
2353 	if (rval == QL_SUCCESS) {
2354 		ql_get_mbox_dma_data(&mem_desc, bufp);
2355 	}
2356 
2357 	ql_free_dma_resource(ha, &mem_desc);
2358 
2359 	if (rval != QL_SUCCESS) {
2360 		EL(ha, "failed=%xh, mbx1=%xh, mbx2=%xh\n", rval,
2361 		    mcp->mb[1], mcp->mb[2]);
2362 	} else {
2363 		/*EMPTY*/
2364 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2365 	}
2366 
2367 	return (rval);
2368 }
2369 
2370 /*
2371  * ql_reset_link_status
2372  *	Issue Reset Link Error Status mailbox command
2373  *
2374  * Input:
2375  *	ha:	adapter state pointer.
2376  *
2377  * Returns:
2378  *	ql local function return status code.
2379  *
2380  * Context:
2381  *	Kernel context.
2382  */
2383 int
2384 ql_reset_link_status(ql_adapter_state_t *ha)
2385 {
2386 	int		rval;
2387 	mbx_cmd_t	mc = {0};
2388 	mbx_cmd_t	*mcp = &mc;
2389 
2390 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2391 
2392 	mcp->mb[0] = MBC_RESET_LINK_STATUS;
2393 	mcp->out_mb = MBX_0;
2394 	mcp->in_mb = MBX_0;
2395 	mcp->timeout = MAILBOX_TOV;
2396 	rval = ql_mailbox_command(ha, mcp);
2397 
2398 	if (rval != QL_SUCCESS) {
2399 		EL(ha, "failed=%xh\n", rval);
2400 	} else {
2401 		/*EMPTY*/
2402 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2403 	}
2404 
2405 	return (rval);
2406 }
2407 
2408 /*
2409  * ql_loop_reset
2410  *	Issue loop reset.
2411  *
2412  * Input:
2413  *	ha:	adapter state pointer.
2414  *
2415  * Returns:
2416  *	ql local function return status code.
2417  *
2418  * Context:
2419  *	Kernel context.
2420  */
2421 int
2422 ql_loop_reset(ql_adapter_state_t *ha)
2423 {
2424 	int	rval;
2425 
2426 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2427 
2428 	if (CFG_IST(ha, CFG_ENABLE_LIP_RESET)) {
2429 		rval = ql_lip_reset(ha, 0xff);
2430 	} else if (CFG_IST(ha, CFG_ENABLE_FULL_LIP_LOGIN)) {
2431 		rval = ql_full_login_lip(ha);
2432 	} else if (CFG_IST(ha, CFG_ENABLE_TARGET_RESET)) {
2433 		rval = ql_target_reset(ha, NULL, ha->loop_reset_delay);
2434 	} else {
2435 		rval = ql_initiate_lip(ha);
2436 	}
2437 
2438 	if (rval != QL_SUCCESS) {
2439 		EL(ha, "failed, rval = %xh\n", rval);
2440 	} else {
2441 		/*EMPTY*/
2442 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2443 	}
2444 
2445 	return (rval);
2446 }
2447 
2448 /*
2449  * ql_initiate_lip
2450  *	Initiate LIP mailbox command.
2451  *
2452  * Input:
2453  *	ha:	adapter state pointer.
2454  *
2455  * Returns:
2456  *	ql local function return status code.
2457  *
2458  * Context:
2459  *	Kernel context.
2460  */
2461 int
2462 ql_initiate_lip(ql_adapter_state_t *ha)
2463 {
2464 	int		rval;
2465 	mbx_cmd_t	mc = {0};
2466 	mbx_cmd_t	*mcp = &mc;
2467 
2468 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2469 
2470 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2471 		mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2472 		mcp->mb[1] = BIT_4;
2473 		mcp->mb[3] = ha->loop_reset_delay;
2474 		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2475 	} else {
2476 		mcp->mb[0] = MBC_INITIATE_LIP;
2477 		mcp->out_mb = MBX_0;
2478 	}
2479 	mcp->in_mb = MBX_0;
2480 	mcp->timeout = MAILBOX_TOV;
2481 	rval = ql_mailbox_command(ha, mcp);
2482 
2483 	if (rval != QL_SUCCESS) {
2484 		EL(ha, "failed, rval = %xh\n", rval);
2485 	} else {
2486 		/*EMPTY*/
2487 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2488 	}
2489 
2490 	return (rval);
2491 }
2492 
2493 /*
2494  * ql_full_login_lip
2495  *	Issue full login LIP mailbox command.
2496  *
2497  * Input:
2498  *	ha:	adapter state pointer.
2499  *
2500  * Returns:
2501  *	ql local function return status code.
2502  *
2503  * Context:
2504  *	Kernel context.
2505  */
2506 int
2507 ql_full_login_lip(ql_adapter_state_t *ha)
2508 {
2509 	int		rval;
2510 	mbx_cmd_t	mc = {0};
2511 	mbx_cmd_t	*mcp = &mc;
2512 
2513 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2514 
2515 	mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2516 	if (CFG_IST(ha, CFG_CTRL_2425)) {
2517 		mcp->mb[1] = BIT_3;
2518 	} else if (CFG_IST(ha, CFG_CTRL_81XX)) {
2519 		mcp->mb[1] = BIT_1;
2520 	}
2521 	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2522 	mcp->in_mb = MBX_0;
2523 	mcp->timeout = MAILBOX_TOV;
2524 	rval = ql_mailbox_command(ha, mcp);
2525 
2526 	if (rval != QL_SUCCESS) {
2527 		EL(ha, "failed, rval = %xh\n", rval);
2528 	} else {
2529 		/*EMPTY*/
2530 		QL_PRINT_3(CE_CONT, "(%d): done", ha->instance);
2531 	}
2532 
2533 	return (rval);
2534 }
2535 
2536 /*
2537  * ql_lip_reset
2538  *	Issue lip reset to a port.
2539  *
2540  * Input:
2541  *	ha:		adapter state pointer.
2542  *	loop_id:	FC loop id.
2543  *
2544  * Returns:
2545  *	ql local function return status code.
2546  *
2547  * Context:
2548  *	Kernel context.
2549  */
2550 int
2551 ql_lip_reset(ql_adapter_state_t *ha, uint16_t loop_id)
2552 {
2553 	int		rval;
2554 	mbx_cmd_t	mc = {0};
2555 	mbx_cmd_t	*mcp = &mc;
2556 
2557 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2558 
2559 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2560 		mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2561 		mcp->mb[1] = BIT_6;
2562 		mcp->mb[3] = ha->loop_reset_delay;
2563 		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2564 	} else {
2565 		mcp->mb[0] = MBC_LIP_RESET;
2566 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2567 			mcp->mb[1] = loop_id;
2568 			mcp->out_mb = MBX_10|MBX_3|MBX_2|MBX_1|MBX_0;
2569 		} else {
2570 			mcp->mb[1] = (uint16_t)(loop_id << 8);
2571 			mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2572 		}
2573 		mcp->mb[2] = ha->loop_reset_delay;
2574 	}
2575 	mcp->in_mb = MBX_0;
2576 	mcp->timeout = MAILBOX_TOV;
2577 	rval = ql_mailbox_command(ha, mcp);
2578 
2579 	if (rval != QL_SUCCESS) {
2580 		EL(ha, "failed, rval = %xh\n", rval);
2581 	} else {
2582 		/*EMPTY*/
2583 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2584 	}
2585 
2586 	return (rval);
2587 }
2588 
2589 /*
2590  * ql_abort_command
2591  *	Abort command aborts a specified IOCB.
2592  *
2593  * Input:
2594  *	ha:	adapter state pointer.
2595  *	sp:	SRB structure pointer.
2596  *
2597  * Returns:
2598  *	ql local function return status code.
2599  *
2600  * Context:
2601  *	Kernel context.
2602  */
2603 int
2604 ql_abort_command(ql_adapter_state_t *ha, ql_srb_t *sp)
2605 {
2606 	int		rval;
2607 	mbx_cmd_t	mc = {0};
2608 	mbx_cmd_t	*mcp = &mc;
2609 	ql_tgt_t	*tq = sp->lun_queue->target_queue;
2610 
2611 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2612 
2613 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2614 		rval = ql_abort_cmd_iocb(ha, sp);
2615 	} else {
2616 		mcp->mb[0] = MBC_ABORT_COMMAND_IOCB;
2617 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2618 			mcp->mb[1] = tq->loop_id;
2619 		} else {
2620 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
2621 		}
2622 		mcp->mb[2] = LSW(sp->handle);
2623 		mcp->mb[3] = MSW(sp->handle);
2624 		mcp->mb[6] = (uint16_t)(sp->flags & SRB_FCP_CMD_PKT ?
2625 		    sp->lun_queue->lun_no : 0);
2626 		mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2627 		mcp->in_mb = MBX_0;
2628 		mcp->timeout = MAILBOX_TOV;
2629 		rval = ql_mailbox_command(ha, mcp);
2630 	}
2631 
2632 	if (rval != QL_SUCCESS) {
2633 		EL(ha, "failed=%xh, d_id=%xh, handle=%xh\n", rval,
2634 		    tq->d_id.b24, sp->handle);
2635 	} else {
2636 		/*EMPTY*/
2637 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2638 	}
2639 
2640 	return (rval);
2641 }
2642 
2643 /*
2644  * ql_abort_cmd_iocb
2645  *	Function issues abort command IOCB.
2646  *
2647  * Input:
2648  *	ha:	adapter state pointer.
2649  *	sp:	SRB structure pointer.
2650  *
2651  * Returns:
2652  *	ql local function return status code.
2653  *
2654  * Context:
2655  *	Interrupt or Kernel context, no mailbox commands allowed.
2656  */
2657 static int
2658 ql_abort_cmd_iocb(ql_adapter_state_t *ha, ql_srb_t *sp)
2659 {
2660 	ql_mbx_iocb_t	*pkt;
2661 	int		rval;
2662 	uint32_t	pkt_size;
2663 	uint16_t	comp_status;
2664 	ql_tgt_t	*tq = sp->lun_queue->target_queue;
2665 
2666 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2667 
2668 	pkt_size = sizeof (ql_mbx_iocb_t);
2669 	if ((pkt = kmem_zalloc(pkt_size, KM_SLEEP)) == NULL) {
2670 		EL(ha, "failed, kmem_zalloc\n");
2671 		return (QL_MEMORY_ALLOC_FAILED);
2672 	}
2673 
2674 	pkt->abo.entry_type = ABORT_CMD_TYPE;
2675 	pkt->abo.entry_count = 1;
2676 	pkt->abo.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
2677 	pkt->abo.options = AF_NO_ABTS;
2678 	pkt->abo.cmd_handle = LE_32(sp->handle);
2679 	pkt->abo.target_id[0] = tq->d_id.b.al_pa;
2680 	pkt->abo.target_id[1] = tq->d_id.b.area;
2681 	pkt->abo.target_id[2] = tq->d_id.b.domain;
2682 	pkt->abo.vp_index = ha->vp_index;
2683 
2684 	rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
2685 
2686 	if (rval == QL_SUCCESS && (pkt->abo.entry_status  & 0x3c) != 0) {
2687 		EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
2688 		    pkt->abo.entry_status, tq->d_id.b24);
2689 		rval = QL_FUNCTION_PARAMETER_ERROR;
2690 	}
2691 
2692 	comp_status = (uint16_t)LE_16(pkt->abo.n_port_hdl);
2693 	if (rval == QL_SUCCESS && comp_status != CS_COMPLETE) {
2694 		EL(ha, "failed, comp_status=%xh, d_id=%xh\n",
2695 		    comp_status, tq->d_id.b24);
2696 		rval = QL_FUNCTION_FAILED;
2697 	}
2698 
2699 	kmem_free(pkt, pkt_size);
2700 
2701 	if (rval != QL_SUCCESS) {
2702 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
2703 	} else {
2704 		/*EMPTY*/
2705 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2706 	}
2707 
2708 	return (rval);
2709 }
2710 
2711 /*
2712  * ql_verify_checksum
2713  *	Verify loaded RISC firmware.
2714  *
2715  * Input:
2716  *	ha = adapter state pointer.
2717  *
2718  * Returns:
2719  *	ql local function return status code.
2720  *
2721  * Context:
2722  *	Kernel context.
2723  */
2724 int
2725 ql_verify_checksum(ql_adapter_state_t *ha)
2726 {
2727 	int		rval;
2728 	mbx_cmd_t	mc = {0};
2729 	mbx_cmd_t	*mcp = &mc;
2730 
2731 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2732 
2733 	mcp->mb[0] = MBC_VERIFY_CHECKSUM;
2734 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2735 		mcp->mb[1] = MSW(ha->risc_fw[0].addr);
2736 		mcp->mb[2] = LSW(ha->risc_fw[0].addr);
2737 	} else {
2738 		mcp->mb[1] = LSW(ha->risc_fw[0].addr);
2739 	}
2740 	mcp->out_mb = MBX_2|MBX_1|MBX_0;
2741 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
2742 	mcp->timeout = MAILBOX_TOV;
2743 	rval = ql_mailbox_command(ha, mcp);
2744 
2745 	if (rval != QL_SUCCESS) {
2746 		EL(ha, "failed, rval = %xh\n", rval);
2747 	} else {
2748 		/*EMPTY*/
2749 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2750 	}
2751 
2752 	return (rval);
2753 }
2754 
2755 /*
2756  * ql_get_id_list
2757  *	Get d_id and loop ID list.
2758  *
2759  * Input:
2760  *	ha:	adapter state pointer.
2761  *	bp:	data pointer for DMA data.
2762  *	size:	size of data buffer.
2763  *	mr:	pointer for mailbox data.
2764  *
2765  * Returns:
2766  *	ql local function return status code.
2767  *
2768  * Context:
2769  *	Kernel context.
2770  */
2771 int
2772 ql_get_id_list(ql_adapter_state_t *ha, caddr_t bp, uint32_t size,
2773     ql_mbx_data_t *mr)
2774 {
2775 	int		rval;
2776 	dma_mem_t	mem_desc;
2777 	mbx_cmd_t	mc = {0};
2778 	mbx_cmd_t	*mcp = &mc;
2779 
2780 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2781 
2782 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2783 	    (uint32_t)size)) != QL_SUCCESS) {
2784 		EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
2785 		return (QL_MEMORY_ALLOC_FAILED);
2786 	}
2787 
2788 	mcp->mb[0] = MBC_GET_ID_LIST;
2789 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2790 		mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2791 		mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2792 		mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2793 		mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2794 		mcp->mb[8] = (uint16_t)size;
2795 		mcp->mb[9] = ha->vp_index;
2796 		mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2797 	} else {
2798 		mcp->mb[1] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2799 		mcp->mb[2] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2800 		mcp->mb[3] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2801 		mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2802 		mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2803 	}
2804 	mcp->in_mb = MBX_1|MBX_0;
2805 	mcp->timeout = MAILBOX_TOV;
2806 	rval = ql_mailbox_command(ha, mcp);
2807 
2808 	if (rval == QL_SUCCESS) {
2809 		ql_get_mbox_dma_data(&mem_desc, bp);
2810 	}
2811 
2812 	ql_free_dma_resource(ha, &mem_desc);
2813 
2814 	/* Return mailbox data. */
2815 	if (mr != NULL) {
2816 		mr->mb[0] = mcp->mb[0];
2817 		mr->mb[1] = mcp->mb[1];
2818 	}
2819 
2820 	if (rval != QL_SUCCESS) {
2821 		EL(ha, "failed, rval = %xh\n", rval);
2822 	} else {
2823 		/*EMPTY*/
2824 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2825 	}
2826 
2827 	return (rval);
2828 }
2829 
2830 /*
2831  * ql_wrt_risc_ram
2832  *	Load RISC RAM.
2833  *
2834  * Input:
2835  *	ha:		adapter state pointer.
2836  *	risc_address:	risc ram word address.
2837  *	bp:		DMA pointer.
2838  *	word_count:	16/32bit word count.
2839  *
2840  * Returns:
2841  *	ql local function return status code.
2842  *
2843  * Context:
2844  *	Kernel context.
2845  */
2846 int
2847 ql_wrt_risc_ram(ql_adapter_state_t *ha, uint32_t risc_address, uint64_t bp,
2848     uint32_t word_count)
2849 {
2850 	int		rval;
2851 	mbx_cmd_t	mc = {0};
2852 	mbx_cmd_t	*mcp = &mc;
2853 
2854 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2855 
2856 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2857 		mcp->mb[0] = MBC_LOAD_RAM_EXTENDED;
2858 		mcp->mb[4] = MSW(word_count);
2859 		mcp->mb[5] = LSW(word_count);
2860 		mcp->mb[6] = MSW(MSD(bp));
2861 		mcp->mb[7] = LSW(MSD(bp));
2862 		mcp->mb[8] = MSW(risc_address);
2863 		mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
2864 		    MBX_0;
2865 	} else {
2866 		mcp->mb[0] = MBC_LOAD_RAM;
2867 		mcp->mb[4] = LSW(word_count);
2868 		mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2869 	}
2870 	mcp->mb[1] = LSW(risc_address);
2871 	mcp->mb[2] = MSW(LSD(bp));
2872 	mcp->mb[3] = LSW(LSD(bp));
2873 	mcp->in_mb = MBX_0;
2874 	mcp->timeout = MAILBOX_TOV;
2875 
2876 	rval = ql_mailbox_command(ha, mcp);
2877 
2878 	if (rval != QL_SUCCESS) {
2879 		EL(ha, "failed, rval = %xh\n", rval);
2880 	} else {
2881 		/*EMPTY*/
2882 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2883 	}
2884 
2885 	return (rval);
2886 }
2887 
2888 /*
2889  * ql_rd_risc_ram
2890  *	Get RISC RAM.
2891  *
2892  * Input:
2893  *	ha:		adapter state pointer.
2894  *	risc_address:	risc ram word address.
2895  *	bp:		direct data pointer.
2896  *	word_count:	16/32bit word count.
2897  *
2898  * Returns:
2899  *	ql local function return status code.
2900  *
2901  * Context:
2902  *	Kernel context.
2903  */
2904 int
2905 ql_rd_risc_ram(ql_adapter_state_t *ha, uint32_t risc_address, uint64_t bp,
2906     uint32_t word_count)
2907 {
2908 	int		rval;
2909 	mbx_cmd_t	mc = {0};
2910 	mbx_cmd_t	*mcp = &mc;
2911 
2912 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2913 
2914 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2915 		mcp->mb[0] = MBC_DUMP_RAM_EXTENDED;
2916 		mcp->mb[1] = LSW(risc_address);
2917 		mcp->mb[2] = MSW(LSD(bp));
2918 		mcp->mb[3] = LSW(LSD(bp));
2919 		mcp->mb[4] = MSW(word_count);
2920 		mcp->mb[5] = LSW(word_count);
2921 		mcp->mb[6] = MSW(MSD(bp));
2922 		mcp->mb[7] = LSW(MSD(bp));
2923 		mcp->mb[8] = MSW(risc_address);
2924 		mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
2925 		    MBX_0;
2926 	} else {
2927 		mcp->mb[0] = MBC_DUMP_RAM;	/* doesn't support 64bit addr */
2928 		mcp->mb[1] = LSW(risc_address);
2929 		mcp->mb[2] = MSW(LSD(bp));
2930 		mcp->mb[3] = LSW(LSD(bp));
2931 		mcp->mb[4] = LSW(word_count);
2932 		mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2933 	}
2934 	mcp->in_mb = MBX_0;
2935 	mcp->timeout = MAILBOX_TOV;
2936 	rval = ql_mailbox_command(ha, mcp);
2937 
2938 	if (rval != QL_SUCCESS) {
2939 		EL(ha, "failed, rval = %xh\n", rval);
2940 	} else {
2941 		/*EMPTY*/
2942 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2943 	}
2944 
2945 	return (rval);
2946 }
2947 
2948 /*
2949  * ql_issue_mbx_iocb
2950  *	Issue IOCB using mailbox command
2951  *
2952  * Input:
2953  *	ha:	adapter state pointer.
2954  *	bp:	buffer pointer.
2955  *	size:	buffer size.
2956  *
2957  * Returns:
2958  *	ql local function return status code.
2959  *
2960  * Context:
2961  *	Kernel context.
2962  */
2963 int
2964 ql_issue_mbx_iocb(ql_adapter_state_t *ha, caddr_t bp, uint32_t size)
2965 {
2966 	int		rval;
2967 	dma_mem_t	mem_desc;
2968 	mbx_cmd_t	mc = {0};
2969 	mbx_cmd_t	*mcp = &mc;
2970 
2971 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2972 
2973 	if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
2974 	    QL_SUCCESS) {
2975 		EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
2976 		return (rval);
2977 	}
2978 
2979 	mcp->mb[0] = MBC_EXECUTE_IOCB;
2980 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2981 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2982 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2983 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2984 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2985 	mcp->in_mb = MBX_1|MBX_0;
2986 	mcp->timeout = MAILBOX_TOV + 5;
2987 	rval = ql_mailbox_command(ha, mcp);
2988 
2989 	if (rval == QL_SUCCESS) {
2990 		ql_get_mbox_dma_data(&mem_desc, bp);
2991 	}
2992 
2993 	ql_free_dma_resource(ha, &mem_desc);
2994 
2995 	if (rval != QL_SUCCESS) {
2996 		EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
2997 	} else {
2998 		/*EMPTY*/
2999 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3000 	}
3001 
3002 	return (rval);
3003 }
3004 
3005 /*
3006  * ql_mbx_wrap_test
3007  *	Mailbox register wrap test.
3008  *
3009  * Input:
3010  *	ha:	adapter state pointer.
3011  *	mr:	pointer for in/out mailbox data.
3012  *
3013  * Returns:
3014  *	ql local function return status code.
3015  *
3016  * Context:
3017  *	Kernel context.
3018  */
3019 int
3020 ql_mbx_wrap_test(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3021 {
3022 	int		rval;
3023 	mbx_cmd_t	mc = {0};
3024 	mbx_cmd_t	*mcp = &mc;
3025 
3026 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3027 
3028 	if (mr != NULL) {
3029 		mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
3030 		mcp->mb[1] = mr->mb[1];
3031 		mcp->mb[2] = mr->mb[2];
3032 		mcp->mb[3] = mr->mb[3];
3033 		mcp->mb[4] = mr->mb[4];
3034 		mcp->mb[5] = mr->mb[5];
3035 		mcp->mb[6] = mr->mb[6];
3036 		mcp->mb[7] = mr->mb[7];
3037 		mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3038 		mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3039 		mcp->timeout = MAILBOX_TOV;
3040 		rval = ql_mailbox_command(ha, mcp);
3041 		if (rval == QL_SUCCESS) {
3042 			mr->mb[1] = mcp->mb[1];
3043 			mr->mb[2] = mcp->mb[2];
3044 			mr->mb[3] = mcp->mb[3];
3045 			mr->mb[4] = mcp->mb[4];
3046 			mr->mb[5] = mcp->mb[5];
3047 			mr->mb[6] = mcp->mb[6];
3048 			mr->mb[7] = mcp->mb[7];
3049 		}
3050 	} else {
3051 		rval = QL_FUNCTION_PARAMETER_ERROR;
3052 	}
3053 
3054 	if (rval != QL_SUCCESS) {
3055 		EL(ha, "failed=%xh\n", rval);
3056 	} else {
3057 		/*EMPTY*/
3058 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3059 	}
3060 
3061 	return (rval);
3062 }
3063 
3064 /*
3065  * ql_execute_fw
3066  *	Start adapter firmware.
3067  *
3068  * Input:
3069  *	ha:	adapter state pointer.
3070  *
3071  * Returns:
3072  *	ql local function return status code.
3073  *
3074  * Context:
3075  *	Kernel context.
3076  */
3077 int
3078 ql_execute_fw(ql_adapter_state_t *ha)
3079 {
3080 	int		rval;
3081 	mbx_cmd_t	mc = {0};
3082 	mbx_cmd_t	*mcp = &mc;
3083 
3084 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3085 
3086 	mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
3087 	if (CFG_IST(ha, CFG_CTRL_242581)) {
3088 		mcp->mb[1] = MSW(ha->risc_fw[0].addr);
3089 		mcp->mb[2] = LSW(ha->risc_fw[0].addr);
3090 	} else {
3091 		mcp->mb[1] = LSW(ha->risc_fw[0].addr);
3092 	}
3093 	mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3094 	mcp->in_mb = MBX_0;
3095 	mcp->timeout = MAILBOX_TOV;
3096 	rval = ql_mailbox_command(ha, mcp);
3097 
3098 	if (CFG_IST(ha, CFG_CTRL_2200)) {
3099 		rval = QL_SUCCESS;
3100 	}
3101 
3102 	if (rval != QL_SUCCESS) {
3103 		EL(ha, "failed=%xh\n", rval);
3104 	} else {
3105 		/*EMPTY*/
3106 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3107 	}
3108 
3109 	return (rval);
3110 }
3111 
3112 /*
3113  * ql_get_firmware_option
3114  *	 Get Firmware Options Mailbox Command.
3115  *
3116  * Input:
3117  *	ha:	adapter state pointer.
3118  *	mr:	pointer for mailbox data.
3119  *
3120  * Returns:
3121  *	ql local function return status code.
3122  *
3123  * Context:
3124  *	Kernel context.
3125  */
3126 int
3127 ql_get_firmware_option(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3128 {
3129 	int		rval;
3130 	mbx_cmd_t	mc = {0};
3131 	mbx_cmd_t	*mcp = &mc;
3132 
3133 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3134 
3135 	mcp->mb[0] = MBC_GET_FIRMWARE_OPTIONS;
3136 	mcp->out_mb = MBX_0;
3137 	mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
3138 	mcp->timeout = MAILBOX_TOV;
3139 	rval = ql_mailbox_command(ha, mcp);
3140 
3141 	/* Return mailbox data. */
3142 	if (mr != NULL) {
3143 		mr->mb[0] = mcp->mb[0];
3144 		mr->mb[1] = mcp->mb[1];
3145 		mr->mb[2] = mcp->mb[2];
3146 		mr->mb[3] = mcp->mb[3];
3147 	}
3148 
3149 	if (rval != QL_SUCCESS) {
3150 		EL(ha, "failed=%xh\n", rval);
3151 	} else {
3152 		/*EMPTY*/
3153 		QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3154 	}
3155 
3156 	return (rval);
3157 }
3158 
3159 /*
3160  * ql_set_firmware_option
3161  *	 Set Firmware Options Mailbox Command.
3162  *
3163  * Input:
3164  *	ha:	adapter state pointer.
3165  *	mr:	pointer for mailbox data.
3166  *
3167  * Returns:
3168  *	ql local function return status code.
3169  *
3170  * Context:
3171  *	Kernel context.
3172  */
3173 int
3174 ql_set_firmware_option(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3175 {
3176 	int		rval;
3177 	mbx_cmd_t	mc = {0};
3178 	mbx_cmd_t	*mcp = &mc;
3179 
3180 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3181 
3182 	if (mr != NULL) {
3183 		mcp->mb[0] = MBC_SET_FIRMWARE_OPTIONS;
3184 		mcp->mb[1] = mr->mb[1];
3185 		mcp->mb[2] = mr->mb[2];
3186 		mcp->mb[3] = mr->mb[3];
3187 		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
3188 		mcp->in_mb = MBX_0;
3189 		mcp->timeout = MAILBOX_TOV;
3190 		rval = ql_mailbox_command(ha, mcp);
3191 	} else {
3192 		rval = QL_FUNCTION_PARAMETER_ERROR;
3193 	}
3194 
3195 	if (rval != QL_SUCCESS) {
3196 		EL(ha, "failed=%xh\n", rval);
3197 	} else {
3198 		/*EMPTY*/
3199 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3200 	}
3201 
3202 	return (rval);
3203 }
3204 
3205 /*
3206  * ql_init_firmware
3207  *	 Initialize firmware mailbox command.
3208  *
3209  * Input:
3210  *	ha:	adapter state pointer.
3211  *	ha->init_ctrl_blk = setup for transmit.
3212  *
3213  * Returns:
3214  *	ql local function return status code.
3215  *
3216  * Context:
3217  *	Kernel context.
3218  */
3219 int
3220 ql_init_firmware(ql_adapter_state_t *ha)
3221 {
3222 	int		rval;
3223 	dma_mem_t	mem_desc;
3224 	mbx_cmd_t	mc = {0};
3225 	mbx_cmd_t	*mcp = &mc;
3226 
3227 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3228 
3229 	if (CFG_IST(ha, CFG_CTRL_242581)) {
3230 		WRT32_IO_REG(ha, req_in, 0);
3231 		WRT32_IO_REG(ha, resp_out, 0);
3232 		WRT32_IO_REG(ha, pri_req_in, 0);
3233 		WRT32_IO_REG(ha, atio_req_out, 0);
3234 	} else {
3235 		WRT16_IO_REG(ha, req_in, 0);
3236 		WRT16_IO_REG(ha, resp_out, 0);
3237 	}
3238 
3239 	if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc,
3240 	    (caddr_t)&ha->init_ctrl_blk, sizeof (ql_comb_init_cb_t))) !=
3241 	    QL_SUCCESS) {
3242 		EL(ha, "dma setup failed=%xh\n", rval);
3243 		return (rval);
3244 	}
3245 
3246 	mcp->mb[0] = (uint16_t)(ha->flags & VP_ENABLED ?
3247 	    MBC_INITIALIZE_MULTI_ID_FW : MBC_INITIALIZE_FIRMWARE);
3248 
3249 	if (CFG_IST(ha, CFG_SBUS_CARD)) {
3250 		mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_2200) ?
3251 		    0x204c : 0x52);
3252 	}
3253 
3254 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3255 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3256 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3257 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3258 	if (CFG_IST(ha, CFG_CTRL_81XX)) {
3259 		uint64_t		ofst, addr;
3260 		ql_init_24xx_cb_t	*icb = (ql_init_24xx_cb_t *)
3261 		    &ha->init_ctrl_blk.cb24;
3262 
3263 		mcp->mb[0] = MBC_INITIALIZE_MULTI_ID_FW;
3264 		if (icb->ext_blk.version[0] | icb->ext_blk.version[1]) {
3265 			ofst = (uintptr_t)&icb->ext_blk - (uintptr_t)icb;
3266 			addr = mem_desc.cookie.dmac_laddress + ofst;
3267 			mcp->mb[10] = MSW(LSD(addr));
3268 			mcp->mb[11] = LSW(LSD(addr));
3269 			mcp->mb[12] = MSW(MSD(addr));
3270 			mcp->mb[13] = LSW(MSD(addr));
3271 			mcp->mb[14] = sizeof (ql_ext_icb_8100_t);
3272 		}
3273 		mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|
3274 		    MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3275 	} else {
3276 		mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3277 	}
3278 	mcp->in_mb = MBX_5|MBX_4|MBX_2|MBX_0;
3279 	mcp->timeout = MAILBOX_TOV;
3280 	rval = ql_mailbox_command(ha, mcp);
3281 
3282 	if (rval == QL_SUCCESS) {
3283 		ha->sfp_stat = mcp->mb[2];
3284 	}
3285 	ql_free_dma_resource(ha, &mem_desc);
3286 
3287 	if (rval != QL_SUCCESS) {
3288 		EL(ha, "failed=%xh\n", rval);
3289 	} else {
3290 		/*EMPTY*/
3291 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3292 	}
3293 
3294 	return (rval);
3295 }
3296 
3297 /*
3298  * ql_get_firmware_state
3299  *	Get adapter firmware state.
3300  *
3301  * Input:
3302  *	ha:	adapter state pointer.
3303  *	mr:	pointer for mailbox data.
3304  *
3305  * Returns:
3306  *	ql local function return status code.
3307  *
3308  * Context:
3309  *	Kernel context.
3310  */
3311 int
3312 ql_get_firmware_state(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3313 {
3314 	int		rval;
3315 	mbx_cmd_t	mc = {0};
3316 	mbx_cmd_t	*mcp = &mc;
3317 
3318 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3319 
3320 	mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
3321 	mcp->out_mb = MBX_0;
3322 	mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
3323 	mcp->timeout = MAILBOX_TOV;
3324 	rval = ql_mailbox_command(ha, mcp);
3325 
3326 	/* Return mailbox data. */
3327 	if (mr != NULL) {
3328 		mr->mb[1] = mcp->mb[1];
3329 		mr->mb[2] = mcp->mb[2];
3330 		mr->mb[3] = mcp->mb[3];
3331 	}
3332 
3333 	ha->sfp_stat = mcp->mb[2];
3334 
3335 	if (rval != QL_SUCCESS) {
3336 		EL(ha, "failed=%xh\n", rval);
3337 	} else {
3338 		/*EMPTY*/
3339 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3340 	}
3341 
3342 	return (rval);
3343 }
3344 
3345 /*
3346  * ql_get_adapter_id
3347  *	Get adapter ID and topology.
3348  *
3349  * Input:
3350  *	ha:	adapter state pointer.
3351  *	mr:	pointer for mailbox data.
3352  *
3353  * Returns:
3354  *	ql local function return status code.
3355  *
3356  * Context:
3357  *	Kernel context.
3358  */
3359 int
3360 ql_get_adapter_id(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3361 {
3362 	int		rval;
3363 	mbx_cmd_t	mc = {0};
3364 	mbx_cmd_t	*mcp = &mc;
3365 
3366 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3367 
3368 	mcp->mb[0] = MBC_GET_ID;
3369 	if (ha->flags & VP_ENABLED) {
3370 		mcp->mb[9] = ha->vp_index;
3371 	}
3372 	mcp->out_mb = MBX_9|MBX_0;
3373 	mcp->in_mb = MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|
3374 	    MBX_3|MBX_2|MBX_1|MBX_0;
3375 	mcp->timeout = MAILBOX_TOV;
3376 
3377 	rval = ql_mailbox_command(ha, mcp);
3378 
3379 	/* Return mailbox data. */
3380 	if (mr != NULL) {
3381 		mr->mb[1] = mcp->mb[1];
3382 		mr->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_242581) ?
3383 		    0xffff : mcp->mb[1]);
3384 		mr->mb[2] = mcp->mb[2];
3385 		mr->mb[3] = mcp->mb[3];
3386 		mr->mb[6] = mcp->mb[6];
3387 		mr->mb[7] = mcp->mb[7];
3388 		mr->mb[8] = mcp->mb[8];
3389 		mr->mb[9] = mcp->mb[9];
3390 		mr->mb[10] = mcp->mb[10];
3391 		mr->mb[11] = mcp->mb[11];
3392 		mr->mb[12] = mcp->mb[12];
3393 		mr->mb[13] = mcp->mb[13];
3394 	}
3395 
3396 	if (rval != QL_SUCCESS) {
3397 		EL(ha, "failed=%xh\n", rval);
3398 	} else {
3399 		/*EMPTY*/
3400 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3401 	}
3402 
3403 	return (rval);
3404 }
3405 
3406 /*
3407  * ql_get_fw_version
3408  *	Get firmware version.
3409  *
3410  * Input:
3411  *	ha:	adapter state pointer.
3412  *	mr:	pointer for mailbox data.
3413  *
3414  * Returns:
3415  *	ql local function return status code.
3416  *
3417  * Context:
3418  *	Kernel context.
3419  */
3420 int
3421 ql_get_fw_version(ql_adapter_state_t *ha,  ql_mbx_data_t *mr)
3422 {
3423 	int		rval;
3424 	mbx_cmd_t	mc = {0};
3425 	mbx_cmd_t	*mcp = &mc;
3426 
3427 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3428 
3429 	mcp->mb[0] = MBC_ABOUT_FIRMWARE;
3430 	mcp->out_mb = MBX_0;
3431 	mcp->in_mb = MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_6|MBX_5|
3432 	    MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3433 	mcp->timeout = MAILBOX_TOV;
3434 	rval = ql_mailbox_command(ha, mcp);
3435 
3436 	/* Return mailbox data. */
3437 	if (mr != NULL) {
3438 		mr->mb[1] = mcp->mb[1];
3439 		mr->mb[2] = mcp->mb[2];
3440 		mr->mb[3] = mcp->mb[3];
3441 		mr->mb[4] = mcp->mb[4];
3442 		mr->mb[5] = mcp->mb[5];
3443 		mr->mb[6] = mcp->mb[6];
3444 		mr->mb[8] = mcp->mb[8];
3445 		mr->mb[9] = mcp->mb[9];
3446 		mr->mb[10] = mcp->mb[10];
3447 		mr->mb[11] = mcp->mb[11];
3448 		mr->mb[12] = mcp->mb[12];
3449 		mr->mb[13] = mcp->mb[13];
3450 	}
3451 
3452 	if (rval != QL_SUCCESS) {
3453 		EL(ha, "failed=%xh\n", rval);
3454 	} else {
3455 		/*EMPTY*/
3456 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3457 	}
3458 
3459 	return (rval);
3460 }
3461 
3462 /*
3463  * ql_data_rate
3464  *	 Issue data rate Mailbox Command.
3465  *
3466  * Input:
3467  *	ha:	adapter state pointer.
3468  *	mr:	pointer for mailbox data.
3469  *
3470  * Returns:
3471  *	ql local function return status code.
3472  *
3473  * Context:
3474  *	Kernel context.
3475  */
3476 int
3477 ql_data_rate(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3478 {
3479 	int		rval;
3480 	mbx_cmd_t	mc = {0};
3481 	mbx_cmd_t	*mcp = &mc;
3482 
3483 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3484 
3485 	if (mr != NULL) {
3486 		mcp->mb[0] = MBC_DATA_RATE;
3487 		mcp->mb[1] = mr->mb[1];
3488 		mcp->mb[2] = mr->mb[2];
3489 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
3490 		mcp->in_mb = MBX_2|MBX_1|MBX_0;
3491 		mcp->timeout = MAILBOX_TOV;
3492 		rval = ql_mailbox_command(ha, mcp);
3493 
3494 		/* Return mailbox data. */
3495 		mr->mb[1] = mcp->mb[1];
3496 		mr->mb[2] = mcp->mb[2];
3497 	} else {
3498 		rval = QL_FUNCTION_PARAMETER_ERROR;
3499 	}
3500 
3501 	ha->sfp_stat = mcp->mb[2];
3502 
3503 	if (rval != QL_SUCCESS) {
3504 		EL(ha, "failed=%xh\n", rval);
3505 	} else {
3506 		/*EMPTY*/
3507 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3508 	}
3509 
3510 	return (rval);
3511 }
3512 
3513 /*
3514  * ql_Diag_Loopback
3515  *	Issue Reset Link Status mailbox command
3516  *
3517  * Input:
3518  *	ha:	adapter state pointer.
3519  *	bp:	buffer pointer.
3520  *	size:	buffer size.
3521  *	opt:	command options.
3522  *	it_cnt:	iteration count.
3523  *	mr:	pointer for mailbox data.
3524  *
3525  * Returns:
3526  *	ql local function return status code.
3527  *
3528  * Context:
3529  *	Kernel context.
3530  */
3531 int
3532 ql_diag_loopback(ql_adapter_state_t *ha, caddr_t bp, uint32_t size,
3533     uint16_t opt, uint32_t it_cnt, ql_mbx_data_t *mr)
3534 {
3535 	int		rval;
3536 	dma_mem_t	mem_desc;
3537 	mbx_cmd_t	mc = {0};
3538 	mbx_cmd_t	*mcp = &mc;
3539 
3540 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3541 
3542 	if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
3543 	    QL_SUCCESS) {
3544 		EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
3545 		return (rval);
3546 	}
3547 
3548 	mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
3549 	mcp->mb[1] = opt;
3550 	mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3551 	mcp->mb[7] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3552 	mcp->mb[10] = LSW(size);
3553 	mcp->mb[11] = MSW(size);
3554 	mcp->mb[14] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3555 	mcp->mb[15] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3556 	mcp->mb[16] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3557 	mcp->mb[17] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3558 	mcp->mb[18] = LSW(it_cnt);
3559 	mcp->mb[19] = MSW(it_cnt);
3560 	mcp->mb[20] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3561 	mcp->mb[21] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3562 	mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
3563 	    MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_3|MBX_2|MBX_1|MBX_0;
3564 	mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
3565 	mcp->timeout = it_cnt / 300;
3566 	if (mcp->timeout < MAILBOX_TOV) {
3567 		mcp->timeout = MAILBOX_TOV;
3568 	}
3569 	rval = ql_mailbox_command(ha, mcp);
3570 
3571 	if (rval == QL_SUCCESS) {
3572 		ql_get_mbox_dma_data(&mem_desc, bp);
3573 	}
3574 
3575 	ql_free_dma_resource(ha, &mem_desc);
3576 
3577 	/* Return mailbox data. */
3578 	if (mr != NULL) {
3579 		mr->mb[0] = mcp->mb[0];
3580 		mr->mb[1] = mcp->mb[1];
3581 		mr->mb[2] = mcp->mb[2];
3582 		mr->mb[3] = mcp->mb[3];
3583 		mr->mb[18] = mcp->mb[18];
3584 		mr->mb[19] = mcp->mb[19];
3585 	}
3586 
3587 	if (rval != QL_SUCCESS) {
3588 		EL(ha, "failed=%xh, mb1=%xh\n", rval,
3589 		    mcp->mb[1]);
3590 	} else {
3591 		/*EMPTY*/
3592 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3593 	}
3594 
3595 	return (rval);
3596 }
3597 
3598 /*
3599  * ql_diag_echo
3600  *	Issue Diag echo mailbox command.  Valid for qla23xx HBA's.
3601  *
3602  * Input:
3603  *	ha:	adapter state pointer.
3604  *	bp:	buffer pointer.
3605  *	size:	buffer size.
3606  *	opt:	command options.
3607  *	mr:	pointer to mailbox status.
3608  *
3609  * Returns:
3610  *	ql local function return status code.
3611  *
3612  * Context:
3613  *	Kernel context.
3614  */
3615 int
3616 ql_diag_echo(ql_adapter_state_t *ha, caddr_t bp, uint32_t size, uint16_t opt,
3617     ql_mbx_data_t *mr)
3618 {
3619 	int		rval;
3620 	dma_mem_t	mem_desc;
3621 	mbx_cmd_t	mc = {0};
3622 	mbx_cmd_t	*mcp = &mc;
3623 
3624 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3625 
3626 	if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
3627 	    QL_SUCCESS) {
3628 		EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
3629 		return (rval);
3630 	}
3631 
3632 	mcp->mb[0] = MBC_ECHO;
3633 	mcp->mb[1] = opt;
3634 	mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3635 	mcp->mb[7] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3636 	mcp->mb[10] = LSW(size);
3637 	mcp->mb[14] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3638 	mcp->mb[15] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3639 	mcp->mb[16] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3640 	mcp->mb[17] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3641 	mcp->mb[20] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3642 	mcp->mb[21] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3643 	mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|
3644 	    MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0;
3645 	mcp->in_mb = MBX_1|MBX_0;
3646 	mcp->timeout = MAILBOX_TOV;
3647 	rval = ql_mailbox_command(ha, mcp);
3648 
3649 	if (rval == QL_SUCCESS) {
3650 		ql_get_mbox_dma_data(&mem_desc, bp);
3651 	}
3652 
3653 	ql_free_dma_resource(ha, &mem_desc);
3654 
3655 	if (mr != NULL) {
3656 		mr->mb[0] = mcp->mb[0];
3657 	}
3658 
3659 	if (rval != QL_SUCCESS) {
3660 		EL(ha, "failed=%xh, mb1=%xh\n", rval,
3661 		    mcp->mb[1]);
3662 	} else {
3663 		/*EMPTY*/
3664 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3665 	}
3666 
3667 	return (rval);
3668 }
3669 
3670 /*
3671  * ql_serdes_param
3672  *	Set/Get serdes transmit parameters mailbox command.
3673  *
3674  * Input:
3675  *	ha:	adapter state pointer.
3676  *	mr:	pointer to mailbox in/out parameters.
3677  *
3678  * Returns:
3679  *	ql local function return status code.
3680  *
3681  * Context:
3682  *	Kernel context.
3683  */
3684 int
3685 ql_serdes_param(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3686 {
3687 	int		rval;
3688 	mbx_cmd_t	mc = {0};
3689 	mbx_cmd_t	*mcp = &mc;
3690 
3691 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3692 
3693 	mcp->mb[0] = MBC_SERDES_TRANSMIT_PARAMETERS;
3694 	mcp->mb[1] = mr->mb[1];
3695 	mcp->mb[2] = mr->mb[2];
3696 	mcp->mb[3] = mr->mb[3];
3697 	mcp->mb[4] = mr->mb[4];
3698 	mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3699 	mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_0;
3700 	mcp->timeout = MAILBOX_TOV;
3701 	rval = ql_mailbox_command(ha, mcp);
3702 
3703 	/* Return mailbox data. */
3704 	if (mr != NULL) {
3705 		mr->mb[0] = mcp->mb[0];
3706 		mr->mb[2] = mcp->mb[2];
3707 		mr->mb[3] = mcp->mb[3];
3708 		mr->mb[4] = mcp->mb[4];
3709 	}
3710 
3711 	if (rval != QL_SUCCESS) {
3712 		EL(ha, "failed=%xh\n", rval);
3713 	} else {
3714 		/*EMPTY*/
3715 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3716 	}
3717 
3718 	return (rval);
3719 }
3720 
3721 /*
3722  * ql_get_timeout_parameters
3723  *	Issue get timeout parameters mailbox command.
3724  *
3725  * Input:
3726  *	ha:	adapter state pointer.
3727  *	mr:	pointer to mailbox in/out parameters.
3728  *
3729  * Returns:
3730  *	ql local function return status code.
3731  *
3732  * Context:
3733  *	Kernel context.
3734  */
3735 int
3736 ql_get_timeout_parameters(ql_adapter_state_t *ha, uint16_t *tov)
3737 {
3738 	int		rval;
3739 	mbx_cmd_t	mc = {0};
3740 	mbx_cmd_t	*mcp = &mc;
3741 
3742 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3743 
3744 	mcp->mb[0] = MBC_GET_TIMEOUT_PARAMETERS;
3745 	mcp->out_mb = MBX_0;
3746 	mcp->in_mb = MBX_3|MBX_0;
3747 	mcp->timeout = MAILBOX_TOV;
3748 	rval = ql_mailbox_command(ha, mcp);
3749 	if (rval == QL_SUCCESS) {
3750 		/* Get 2 * R_A_TOV in seconds */
3751 		if (CFG_IST(ha, CFG_CTRL_2200) || mcp->mb[3] == 0) {
3752 			*tov = R_A_TOV_DEFAULT;
3753 		} else {
3754 			*tov = (uint16_t)(mcp->mb[3] / 10);
3755 			if (mcp->mb[3] % 10 != 0) {
3756 				*tov = (uint16_t)(*tov + 1);
3757 			}
3758 			/*
3759 			 * Adjust value to prevent driver timeout at the same
3760 			 * time as device.
3761 			 */
3762 			*tov = (uint16_t)(*tov + 5);
3763 		}
3764 	} else {
3765 		*tov = R_A_TOV_DEFAULT;
3766 	}
3767 
3768 	if (rval != QL_SUCCESS) {
3769 		EL(ha, "failed=%xh\n", rval);
3770 	} else {
3771 		/*EMPTY*/
3772 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3773 	}
3774 
3775 	return (rval);
3776 }
3777 
3778 /*
3779  * ql_stop_firmware
3780  *	 Issue stop firmware Mailbox Command.
3781  *
3782  * Input:
3783  *	ha:	adapter state pointer.
3784  *
3785  * Returns:
3786  *	ql local function return status code.
3787  *
3788  * Context:
3789  *	Kernel context.
3790  */
3791 int
3792 ql_stop_firmware(ql_adapter_state_t *ha)
3793 {
3794 	int		rval;
3795 	mbx_cmd_t	mc = {0};
3796 	mbx_cmd_t	*mcp = &mc;
3797 
3798 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3799 
3800 	mcp->mb[0] = MBC_STOP_FIRMWARE;
3801 	mcp->out_mb = MBX_0;
3802 	mcp->in_mb = MBX_0;
3803 	mcp->timeout = MAILBOX_TOV;
3804 	rval = ql_mailbox_command(ha, mcp);
3805 
3806 	if (rval != QL_SUCCESS) {
3807 		EL(ha, "failed=%xh\n", rval);
3808 	} else {
3809 		/*EMPTY*/
3810 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3811 	}
3812 
3813 	return (rval);
3814 }
3815 
3816 /*
3817  * ql_read_sfp
3818  *	Issue Read SFP Mailbox command
3819  *
3820  * Input:
3821  *	ha:	adapter state pointer.
3822  *	mem:	pointer to dma memory object for command.
3823  *	dev:	Device address (A0h or A2h).
3824  *	addr:	Data address on SFP EEPROM (0�255).
3825  *
3826  * Returns:
3827  *	ql local function return status code.
3828  *
3829  * Context:
3830  *	Kernel context.
3831  */
3832 int
3833 ql_read_sfp(ql_adapter_state_t *ha, dma_mem_t *mem, uint16_t dev,
3834     uint16_t addr)
3835 {
3836 	int		rval;
3837 	mbx_cmd_t	mc = {0};
3838 	mbx_cmd_t	*mcp = &mc;
3839 
3840 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3841 
3842 	mcp->mb[0] = MBC_READ_SFP;
3843 	mcp->mb[1] = dev;
3844 	mcp->mb[2] = MSW(mem->cookies->dmac_address);
3845 	mcp->mb[3] = LSW(mem->cookies->dmac_address);
3846 	mcp->mb[6] = MSW(mem->cookies->dmac_notused);
3847 	mcp->mb[7] = LSW(mem->cookies->dmac_notused);
3848 	mcp->mb[8] = LSW(mem->size);
3849 	mcp->mb[9] = addr;
3850 	mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
3851 	mcp->in_mb = MBX_1|MBX_0;
3852 	mcp->timeout = MAILBOX_TOV;
3853 	rval = ql_mailbox_command(ha, mcp);
3854 
3855 	(void) ddi_dma_sync(mem->dma_handle, 0, mem->size,
3856 	    DDI_DMA_SYNC_FORKERNEL);
3857 
3858 	if (rval != QL_SUCCESS) {
3859 		EL(ha, "failed=%xh\n", rval);
3860 	} else {
3861 		/*EMPTY*/
3862 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3863 	}
3864 
3865 	return (rval);
3866 }
3867 
3868 /*
3869  * ql_iidma_rate
3870  *	Issue get/set iidma rate command
3871  *
3872  * Input:
3873  *	ha:		adapter state pointer.
3874  *	loop_id:	n-port handle to set/get iidma rate.
3875  *	idma_rate:	Pointer to iidma rate.
3876  *	option:		iidma firmware option (set or get data).
3877  *				0 --> Get iidma rate
3878  *				1 --> Set iidma rate
3879  *
3880  * Returns:
3881  *	ql local function return status code.
3882  *
3883  * Context:
3884  *	Kernel context.
3885  */
3886 int
3887 ql_iidma_rate(ql_adapter_state_t *ha, uint16_t loop_id, uint32_t *idma_rate,
3888     uint32_t option)
3889 {
3890 	int		rval;
3891 	mbx_cmd_t	mc = {0};
3892 	mbx_cmd_t	*mcp = &mc;
3893 
3894 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3895 
3896 	mcp->mb[0] = MBC_PORT_PARAM;
3897 	mcp->mb[1] = loop_id;
3898 	mcp->mb[2] = (uint16_t)option;
3899 	mcp->out_mb = MBX_0|MBX_1|MBX_2;
3900 	mcp->in_mb = MBX_0|MBX_1;
3901 
3902 	if (option & BIT_0) {
3903 		mcp->mb[3] = (uint16_t)*idma_rate;
3904 		mcp->out_mb |= MBX_3;
3905 	} else {
3906 		mcp->in_mb |= MBX_3;
3907 	}
3908 
3909 	mcp->timeout = MAILBOX_TOV;
3910 	rval = ql_mailbox_command(ha, mcp);
3911 
3912 	if (rval != QL_SUCCESS) {
3913 		EL(ha, "failed=%xh, mb1=%xh\n", rval, mcp->mb[1]);
3914 	} else {
3915 		if (option == 0) {
3916 			*idma_rate = mcp->mb[3];
3917 		}
3918 
3919 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3920 	}
3921 
3922 	return (rval);
3923 }
3924 
3925 /*
3926  * ql_set_xmit_parms
3927  *	Set transmit parameters
3928  *
3929  * Input:
3930  *	ha:	adapter state pointer.
3931  *
3932  * Returns:
3933  *	ql local function return status code.
3934  *
3935  * Context:
3936  *	Kernel context.
3937  */
3938 int
3939 ql_set_xmit_parms(ql_adapter_state_t *ha)
3940 {
3941 	int		rval;
3942 	mbx_cmd_t	mc = {0};
3943 	mbx_cmd_t	*mcp = &mc;
3944 
3945 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3946 
3947 	mcp->mb[0] = MBC_XMIT_PARM;
3948 	mcp->mb[1] = BIT_1;
3949 	mcp->out_mb = MBX_1|MBX_0;
3950 	mcp->in_mb = MBX_0;
3951 	mcp->timeout = MAILBOX_TOV;
3952 	rval = ql_mailbox_command(ha, mcp);
3953 
3954 	if (rval != QL_SUCCESS) {
3955 		EL(ha, "failed=%xh\n", rval);
3956 	} else {
3957 		/*EMPTY*/
3958 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3959 	}
3960 	return (rval);
3961 }
3962 
3963 /*
3964  * ql_fw_etrace
3965  *	Firmware extended tracing.
3966  *
3967  * Input:
3968  *	ha:	adapter state pointer.
3969  *	mem:	pointer to dma memory object for command.
3970  *	opt:	options and opcode.
3971  *
3972  * Returns:
3973  *	ql local function return status code.
3974  *
3975  * Context:
3976  *	Kernel context.
3977  */
3978 int
3979 ql_fw_etrace(ql_adapter_state_t *ha, dma_mem_t *mem, uint16_t opt)
3980 {
3981 	int		rval = QL_SUCCESS;
3982 	mbx_cmd_t	mc = {0};
3983 	mbx_cmd_t	*mcp = &mc;
3984 	uint16_t	op_code;
3985 	uint64_t	time;
3986 
3987 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3988 
3989 	/* currently no supported options */
3990 	op_code = (uint16_t)(opt & ~0xFF00);
3991 
3992 	mcp->mb[0] = MBC_TRACE_CONTROL;
3993 	mcp->mb[1] = op_code;
3994 	mcp->in_mb = MBX_0;
3995 	mcp->timeout = MAILBOX_TOV;
3996 
3997 	switch (op_code) {
3998 	case FTO_INSERT_TIME_STAMP:
3999 
4000 		(void) drv_getparm(TIME, &time);
4001 
4002 		EL(ha, "insert time: %x %xh\n", MSD(time), LSD(time));
4003 
4004 		mcp->mb[2] = LSW(LSD(time));
4005 		mcp->mb[3] = MSW(LSD(time));
4006 		mcp->mb[4] = LSW(MSD(time));
4007 		mcp->mb[5] = MSW(MSD(time));
4008 		mcp->out_mb = MBX_0_THRU_5;
4009 		break;
4010 
4011 	case FTO_FCE_TRACE_ENABLE:
4012 		/* Firmware Fibre Channel Event Trace Buffer */
4013 		mcp->mb[2] = LSW(mem->cookies->dmac_address);
4014 		mcp->mb[3] = MSW(mem->cookies->dmac_address);
4015 		mcp->mb[4] = LSW(mem->cookies->dmac_notused);
4016 		mcp->mb[5] = MSW(mem->cookies->dmac_notused);
4017 		mcp->mb[6] = (uint16_t)(mem->size / 0x4000);	/* 16kb blks */
4018 		mcp->mb[8] = (uint16_t)ha->fwfcetraceopt;
4019 		mcp->mb[9] = FTO_FCEMAXTRACEBUF;
4020 		mcp->mb[10] = FTO_FCEMAXTRACEBUF;
4021 		mcp->out_mb = MBX_0_THRU_10;
4022 		break;
4023 
4024 	case FTO_EXT_TRACE_ENABLE:
4025 		/* Firmware Extended Trace Buffer */
4026 		mcp->mb[2] = LSW(mem->cookies->dmac_address);
4027 		mcp->mb[3] = MSW(mem->cookies->dmac_address);
4028 		mcp->mb[4] = LSW(mem->cookies->dmac_notused);
4029 		mcp->mb[5] = MSW(mem->cookies->dmac_notused);
4030 		mcp->mb[6] = (uint16_t)(mem->size / 0x4000);	/* 16kb blks */
4031 		mcp->out_mb = MBX_0_THRU_7;
4032 		break;
4033 
4034 	case FTO_FCE_TRACE_DISABLE:
4035 		/* also causes ISP25xx to flush its internal FCE buffer. */
4036 		mcp->mb[2] = BIT_0;
4037 		mcp->out_mb = MBX_0_THRU_2;
4038 		break;
4039 
4040 	case FTO_EXT_TRACE_DISABLE:
4041 		/* just sending the opcode disables it */
4042 		break;
4043 
4044 	default:
4045 		EL(ha, "invalid option: %xh\n", opt);
4046 		rval = QL_PARAMETER_ERROR;
4047 		break;
4048 	}
4049 
4050 	if (rval == QL_SUCCESS) {
4051 		rval = ql_mailbox_command(ha, mcp);
4052 	}
4053 
4054 	if (rval != QL_SUCCESS) {
4055 		EL(ha, "failed=%xh\n", rval);
4056 	} else {
4057 		/*EMPTY*/
4058 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4059 	}
4060 
4061 	return (rval);
4062 }
4063 
4064 /*
4065  * ql_reset_menlo
4066  *	 Reset Menlo Mailbox Command.
4067  *
4068  * Input:
4069  *	ha:	adapter state pointer.
4070  *	mr:	pointer to mailbox in/out parameters.
4071  *	opt:	options.
4072  *
4073  * Returns:
4074  *	ql local function return status code.
4075  *
4076  * Context:
4077  *	Kernel context.
4078  */
4079 int
4080 ql_reset_menlo(ql_adapter_state_t *ha, ql_mbx_data_t *mr, uint16_t opt)
4081 {
4082 	int		rval;
4083 	mbx_cmd_t	mc = {0};
4084 	mbx_cmd_t	*mcp = &mc;
4085 
4086 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4087 
4088 	mcp->mb[0] = MBC_RESET_MENLO;
4089 	mcp->mb[1] = opt;
4090 	mcp->out_mb = MBX_1|MBX_0;
4091 	mcp->in_mb = MBX_1|MBX_0;
4092 	mcp->timeout = MAILBOX_TOV;
4093 	rval = ql_mailbox_command(ha, mcp);
4094 
4095 	/* Return mailbox data. */
4096 	if (mr != NULL) {
4097 		mr->mb[0] = mcp->mb[0];
4098 		mr->mb[1] = mcp->mb[1];
4099 	}
4100 
4101 	if (rval != QL_SUCCESS) {
4102 		EL(ha, "failed=%xh\n", rval);
4103 	} else {
4104 		/*EMPTY*/
4105 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4106 	}
4107 
4108 	return (rval);
4109 }
4110 
4111 /*
4112  * ql_restart_mpi
4113  *	The Restart MPI Firmware Mailbox Command will reset the MPI RISC,
4114  *	reload MPI firmware from Flash, and execute the firmware.
4115  *
4116  * Input:
4117  *	ha:	adapter state pointer.
4118  *
4119  * Returns:
4120  *	ql local function return status code.
4121  *
4122  * Context:
4123  *	Kernel context.
4124  */
4125 int
4126 ql_restart_mpi(ql_adapter_state_t *ha)
4127 {
4128 	int		rval;
4129 	mbx_cmd_t	mc = {0};
4130 	mbx_cmd_t	*mcp = &mc;
4131 
4132 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4133 
4134 	mcp->mb[0] = MBC_RESTART_MPI;
4135 	mcp->out_mb = MBX_0;
4136 	mcp->in_mb = MBX_1|MBX_0;
4137 	mcp->timeout = MAILBOX_TOV;
4138 	rval = ql_mailbox_command(ha, mcp);
4139 
4140 	/* Return mailbox data. */
4141 	if (rval != QL_SUCCESS) {
4142 		EL(ha, "status=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
4143 	} else {
4144 		/*EMPTY*/
4145 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4146 	}
4147 
4148 	return (rval);
4149 }
4150 
4151 /*
4152  * ql_idc_request
4153  *	Inter-Driver Communication Request.
4154  *
4155  * Input:
4156  *	ha:	adapter state pointer.
4157  *	mr:	pointer for mailbox data.
4158  *
4159  * Returns:
4160  *	ql local function return status code.
4161  *
4162  * Context:
4163  *	Kernel context.
4164  */
4165 int
4166 ql_idc_request(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4167 {
4168 	int		rval;
4169 	mbx_cmd_t	mc = {0};
4170 	mbx_cmd_t	*mcp = &mc;
4171 
4172 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4173 
4174 	mcp->mb[0] = MBC_IDC_REQUEST;
4175 	mcp->mb[1] = mr->mb[1];
4176 	mcp->mb[2] = mr->mb[2];
4177 	mcp->mb[3] = mr->mb[3];
4178 	mcp->mb[4] = mr->mb[4];
4179 	mcp->mb[5] = mr->mb[5];
4180 	mcp->mb[6] = mr->mb[6];
4181 	mcp->mb[7] = mr->mb[7];
4182 	mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4183 	mcp->in_mb = MBX_2|MBX_0;
4184 	mcp->timeout = MAILBOX_TOV;
4185 	rval = ql_mailbox_command(ha, mcp);
4186 
4187 	if (rval == QL_SUCCESS) {
4188 		if (mr != NULL) {
4189 			mr->mb[2] = mcp->mb[2];
4190 		}
4191 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4192 	} else {
4193 		EL(ha, "status=%xh, mbx2=%xh\n", rval, mcp->mb[2]);
4194 	}
4195 
4196 	return (rval);
4197 }
4198 
4199 /*
4200  * ql_idc_ack
4201  *	Inter-Driver Communication Acknowledgement.
4202  *
4203  * Input:
4204  *	ha:	adapter state pointer.
4205  *
4206  * Returns:
4207  *	ql local function return status code.
4208  *
4209  * Context:
4210  *	Kernel context.
4211  */
4212 int
4213 ql_idc_ack(ql_adapter_state_t *ha)
4214 {
4215 	int		rval;
4216 	mbx_cmd_t	mc = {0};
4217 	mbx_cmd_t	*mcp = &mc;
4218 
4219 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4220 
4221 	mcp->mb[0] = MBC_IDC_ACK;
4222 	mcp->mb[1] = ha->idc_mb[1];
4223 	mcp->mb[2] = ha->idc_mb[2];
4224 	mcp->mb[3] = ha->idc_mb[3];
4225 	mcp->mb[4] = ha->idc_mb[4];
4226 	mcp->mb[5] = ha->idc_mb[5];
4227 	mcp->mb[6] = ha->idc_mb[6];
4228 	mcp->mb[7] = ha->idc_mb[7];
4229 	mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4230 	mcp->in_mb = MBX_0;
4231 	mcp->timeout = MAILBOX_TOV;
4232 	rval = ql_mailbox_command(ha, mcp);
4233 
4234 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4235 
4236 	return (rval);
4237 }
4238 
4239 /*
4240  * ql_idc_time_extend
4241  *	Inter-Driver Communication Time Extend
4242  *
4243  * Input:
4244  *	ha:	adapter state pointer.
4245  *	mr:	pointer for mailbox data.
4246  *
4247  * Returns:
4248  *	ql local function return status code.
4249  *
4250  * Context:
4251  *	Kernel context.
4252  */
4253 int
4254 ql_idc_time_extend(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4255 {
4256 	int		rval;
4257 	mbx_cmd_t	mc = {0};
4258 	mbx_cmd_t	*mcp = &mc;
4259 
4260 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4261 
4262 	mcp->mb[0] = MBC_IDC_TIME_EXTEND;
4263 	mcp->mb[1] = mr->mb[1];
4264 	mcp->mb[2] = mr->mb[2];
4265 	mcp->out_mb = MBX_2|MBX_1|MBX_0;
4266 	mcp->in_mb = MBX_0;
4267 	mcp->timeout = MAILBOX_TOV;
4268 	rval = ql_mailbox_command(ha, mcp);
4269 
4270 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4271 
4272 	return (rval);
4273 }
4274 
4275 /*
4276  * ql_set_port_config
4277  *	The Set Port Configuration command sets the configuration for the
4278  *      external 10G port associated with this function
4279  *
4280  * Input:
4281  *	ha:	adapter state pointer.
4282  *	mr:	pointer for mailbox data.
4283  *
4284  * Returns:
4285  *	ql local function return status code.
4286  *
4287  * Context:
4288  *	Kernel context.
4289  */
4290 int
4291 ql_set_port_config(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4292 {
4293 	int		rval;
4294 	mbx_cmd_t	mc = {0};
4295 	mbx_cmd_t	*mcp = &mc;
4296 
4297 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4298 
4299 	mcp->mb[0] = MBC_SET_PORT_CONFIG;
4300 	mcp->mb[1] = mr->mb[1];
4301 	mcp->mb[2] = mr->mb[2];
4302 	mcp->out_mb = MBX_2|MBX_1|MBX_0;
4303 	mcp->in_mb = MBX_0;
4304 	mcp->timeout = MAILBOX_TOV;
4305 	rval = ql_mailbox_command(ha, mcp);
4306 
4307 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4308 
4309 	return (rval);
4310 }
4311 
4312 /*
4313  * ql_get_port_config
4314  *	The Get Port Configuration command retrieves the current configuration
4315  *      for the external 10G port associated with this function
4316  *
4317  * Input:
4318  *	ha:	adapter state pointer.
4319  *	mr:	pointer for mailbox data.
4320  *
4321  * Returns:
4322  *	ql local function return status code.
4323  *
4324  * Context:
4325  *	Kernel context.
4326  */
4327 int
4328 ql_get_port_config(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4329 {
4330 	int		rval;
4331 	mbx_cmd_t	mc = {0};
4332 	mbx_cmd_t	*mcp = &mc;
4333 
4334 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4335 
4336 	mcp->mb[0] = MBC_GET_PORT_CONFIG;
4337 	mcp->out_mb = MBX_0;
4338 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
4339 	mcp->timeout = MAILBOX_TOV;
4340 	rval = ql_mailbox_command(ha, mcp);
4341 
4342 	if (rval == QL_SUCCESS) {
4343 		if (mr != NULL) {
4344 			mr->mb[1] = mcp->mb[1];
4345 			mr->mb[2] = mcp->mb[2];
4346 		}
4347 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4348 	} else {
4349 		EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh\n", rval, mcp->mb[1],
4350 		    mcp->mb[2]);
4351 	}
4352 
4353 	return (rval);
4354 }
4355 
4356 /*
4357  * ql_flash_access
4358  *	The Get Port Configuration command retrieves the current configuration
4359  *      for the external 10G port associated with this function
4360  *
4361  * Input:
4362  *	ha:	adapter state pointer.
4363  *	cmd:	command.
4364  *	start:	32bit word address.
4365  *	end:	32bit word address.
4366  *	dp:	32bit word pointer.
4367  *
4368  * Returns:
4369  *	ql local function return status code.
4370  *
4371  * Context:
4372  *	Kernel context.
4373  */
4374 int
4375 ql_flash_access(ql_adapter_state_t *ha, uint16_t cmd, uint32_t start,
4376     uint32_t end, uint32_t *dp)
4377 {
4378 	int		rval;
4379 	mbx_cmd_t	mc = {0};
4380 	mbx_cmd_t	*mcp = &mc;
4381 
4382 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4383 
4384 	mcp->mb[0] = MBC_FLASH_ACCESS;
4385 	if (cmd > 0 && cmd < 4) {
4386 		mcp->mb[1] = (uint16_t)(FAC_FORCE_SEMA_LOCK | cmd);
4387 	} else {
4388 		mcp->mb[1] = cmd;
4389 	}
4390 	mcp->mb[2] = LSW(start);
4391 	mcp->mb[3] = MSW(start);
4392 	mcp->mb[4] = LSW(end);
4393 	mcp->mb[5] = MSW(end);
4394 
4395 	EL(ha, "mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh\n",
4396 	    mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[4], mcp->mb[5]);
4397 
4398 	mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4399 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
4400 	mcp->timeout = MAILBOX_TOV;
4401 	rval = ql_mailbox_command(ha, mcp);
4402 
4403 	if (rval != QL_SUCCESS) {
4404 		EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh\n", rval, mcp->mb[1],
4405 		    mcp->mb[2]);
4406 	} else {
4407 		if (dp != NULL) {
4408 			*dp = (uint32_t)mcp->mb[1];
4409 		}
4410 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4411 	}
4412 
4413 	return (rval);
4414 }
4415 
4416 /*
4417  * ql_get_xgmac_stats
4418  *	Issue et XGMAC Statistics Mailbox command
4419  *
4420  * Input:
4421  *	ha:	adapter state pointer.
4422  *	size:	size of data buffer.
4423  *	bufp:	data pointer for DMA data.
4424  *
4425  * Returns:
4426  *	ql local function return status code.
4427  *
4428  * Context:
4429  *	Kernel context.
4430  */
4431 int
4432 ql_get_xgmac_stats(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
4433 {
4434 	int		rval;
4435 	dma_mem_t	mem_desc;
4436 	mbx_cmd_t	mc = {0};
4437 	mbx_cmd_t	*mcp = &mc;
4438 
4439 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4440 
4441 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
4442 	    (uint32_t)size)) != QL_SUCCESS) {
4443 		EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
4444 		return (QL_MEMORY_ALLOC_FAILED);
4445 	}
4446 
4447 	mcp->mb[0] = MBC_GET_XGMAC_STATS;
4448 	mcp->mb[2] = MSW(mem_desc.cookie.dmac_address);
4449 	mcp->mb[3] = LSW(mem_desc.cookie.dmac_address);
4450 	mcp->mb[6] = MSW(mem_desc.cookie.dmac_notused);
4451 	mcp->mb[7] = LSW(mem_desc.cookie.dmac_notused);
4452 	mcp->mb[8] = (uint16_t)(size >> 2);
4453 	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
4454 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
4455 	mcp->timeout = MAILBOX_TOV;
4456 	rval = ql_mailbox_command(ha, mcp);
4457 
4458 	if (rval == QL_SUCCESS) {
4459 		ql_get_mbox_dma_data(&mem_desc, bufp);
4460 	}
4461 	ql_free_dma_resource(ha, &mem_desc);
4462 
4463 	if (rval != QL_SUCCESS) {
4464 		EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh\n", rval, mcp->mb[1],
4465 		    mcp->mb[2]);
4466 	} else {
4467 		/*EMPTY*/
4468 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4469 	}
4470 
4471 	return (rval);
4472 }
4473