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