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