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