1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /* Copyright 2009 QLogic Corporation */
23 
24 /*
25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 #pragma ident	"Copyright 2009 QLogic Corporation; ql_mbx.c"
30 
31 /*
32  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
33  *
34  * ***********************************************************************
35  * *									**
36  * *				NOTICE					**
37  * *		COPYRIGHT (C) 1996-2009 QLOGIC CORPORATION		**
38  * *			ALL RIGHTS RESERVED				**
39  * *									**
40  * ***********************************************************************
41  *
42  */
43 
44 #include <ql_apps.h>
45 #include <ql_api.h>
46 #include <ql_debug.h>
47 #include <ql_iocb.h>
48 #include <ql_isr.h>
49 #include <ql_mbx.h>
50 #include <ql_xioctl.h>
51 
52 /*
53  * Local data
54  */
55 
56 /*
57  * Local prototypes
58  */
59 static int ql_mailbox_command(ql_adapter_state_t *, mbx_cmd_t *);
60 static int ql_task_mgmt_iocb(ql_adapter_state_t *, ql_tgt_t *, uint16_t,
61     uint32_t, uint16_t);
62 static int ql_abort_cmd_iocb(ql_adapter_state_t *, ql_srb_t *);
63 static int ql_setup_mbox_dma_transfer(ql_adapter_state_t *, dma_mem_t *,
64     caddr_t, uint32_t);
65 static int ql_setup_mbox_dma_resources(ql_adapter_state_t *, dma_mem_t *,
66     uint32_t);
67 static void ql_setup_mbox_dma_data(dma_mem_t *, caddr_t);
68 static void ql_get_mbox_dma_data(dma_mem_t *, caddr_t);
69 
70 /*
71  * ql_mailbox_command
72  *	Issue mailbox command and waits for completion.
73  *
74  * Input:
75  *	ha = adapter state pointer.
76  *	mcp = mailbox command parameter structure pointer.
77  *
78  * Returns:
79  *	ql local function return status code.
80  *
81  * Context:
82  *	Kernel context.
83  */
84 static int
85 ql_mailbox_command(ql_adapter_state_t *vha, mbx_cmd_t *mcp)
86 {
87 	uint16_t		cnt;
88 	uint32_t		data;
89 	clock_t			timer, cv_stat;
90 	int			rval;
91 	uint32_t		set_flags = 0;
92 	uint32_t		reset_flags = 0;
93 	ql_adapter_state_t	*ha = vha->pha;
94 	int			mbx_cmd = mcp->mb[0];
95 
96 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
97 
98 	/* Acquire mailbox register lock. */
99 	MBX_REGISTER_LOCK(ha);
100 
101 	/* Check for mailbox available, if not wait for signal. */
102 	while (ha->mailbox_flags & MBX_BUSY_FLG) {
103 		ha->mailbox_flags = (uint8_t)
104 		    (ha->mailbox_flags | MBX_WANT_FLG);
105 
106 		if (ha->task_daemon_flags & TASK_DAEMON_POWERING_DOWN) {
107 			EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
108 			MBX_REGISTER_UNLOCK(ha);
109 			return (QL_LOCK_TIMEOUT);
110 		}
111 
112 		/* Set timeout after command that is running. */
113 		timer = ddi_get_lbolt();
114 		timer += (mcp->timeout + 20) * drv_usectohz(1000000);
115 		cv_stat = cv_timedwait_sig(&ha->cv_mbx_wait,
116 		    &ha->pha->mbx_mutex, timer);
117 		if (cv_stat == -1 || cv_stat == 0) {
118 			/*
119 			 * The timeout time 'timer' was
120 			 * reached without the condition
121 			 * being signaled.
122 			 */
123 			ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
124 			    ~MBX_WANT_FLG);
125 			cv_broadcast(&ha->cv_mbx_wait);
126 
127 			/* Release mailbox register lock. */
128 			MBX_REGISTER_UNLOCK(ha);
129 
130 			if (cv_stat == 0) {
131 				EL(vha, "waiting for availability aborted, "
132 				    "cmd=%xh\n", mcp->mb[0]);
133 				return (QL_ABORTED);
134 			}
135 			EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
136 			return (QL_LOCK_TIMEOUT);
137 		}
138 	}
139 
140 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_BUSY_FLG);
141 
142 	/* Structure pointer for return mailbox registers. */
143 	ha->mcp = mcp;
144 
145 	/* Load mailbox registers. */
146 	data = mcp->out_mb;
147 	for (cnt = 0; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
148 		if (data & MBX_0) {
149 			WRT16_IO_REG(ha, mailbox[cnt], mcp->mb[cnt]);
150 		}
151 		data >>= 1;
152 	}
153 
154 	/* Issue set host interrupt command. */
155 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & ~MBX_INTERRUPT);
156 	CFG_IST(ha, CFG_CTRL_242581) ?
157 	    WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT) :
158 	    WRT16_IO_REG(ha, hccr, HC_SET_HOST_INT);
159 
160 	/* Wait for command to complete. */
161 	if (ha->flags & INTERRUPTS_ENABLED &&
162 	    !(ha->task_daemon_flags & (TASK_THREAD_CALLED |
163 	    TASK_DAEMON_POWERING_DOWN)) &&
164 	    !ddi_in_panic()) {
165 		while (!(ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT)) &&
166 		    !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
167 
168 			/* 30 seconds from now */
169 			timer = ddi_get_lbolt();
170 			timer += mcp->timeout * drv_usectohz(1000000);
171 			if (cv_timedwait(&ha->cv_mbx_intr, &ha->pha->mbx_mutex,
172 			    timer) == -1) {
173 				/*
174 				 * The timeout time 'timer' was
175 				 * reached without the condition
176 				 * being signaled.
177 				 */
178 				break;
179 			}
180 		}
181 	} else {
182 		/* Release mailbox register lock. */
183 		MBX_REGISTER_UNLOCK(ha);
184 
185 		/* Acquire interrupt lock. */
186 		for (timer = mcp->timeout * 100; timer; timer--) {
187 			/* Check for pending interrupts. */
188 			while (RD16_IO_REG(ha, istatus) & RISC_INT) {
189 				(void) ql_isr((caddr_t)ha);
190 				INTR_LOCK(ha);
191 				ha->intr_claimed = B_TRUE;
192 				INTR_UNLOCK(ha);
193 				if (ha->mailbox_flags &
194 				    (MBX_INTERRUPT | MBX_ABORT) ||
195 				    ha->task_daemon_flags & ISP_ABORT_NEEDED) {
196 					break;
197 				}
198 			}
199 			if (ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT) ||
200 			    ha->task_daemon_flags & ISP_ABORT_NEEDED) {
201 				break;
202 			} else if (!ddi_in_panic() && timer % 101 == 0) {
203 				delay(drv_usectohz(10000));
204 			} else {
205 				drv_usecwait(10000);
206 			}
207 		}
208 
209 		/* Acquire mailbox register lock. */
210 		MBX_REGISTER_LOCK(ha);
211 	}
212 
213 	/* Mailbox command timeout? */
214 	if (ha->task_daemon_flags & ISP_ABORT_NEEDED ||
215 	    ha->mailbox_flags & MBX_ABORT) {
216 		rval = QL_ABORTED;
217 	} else if ((ha->mailbox_flags & MBX_INTERRUPT) == 0) {
218 		if (CFG_IST(ha, CFG_DUMP_MAILBOX_TIMEOUT)) {
219 			(void) ql_binary_fw_dump(ha, FALSE);
220 		}
221 		EL(vha, "command timeout, isp_abort_needed\n");
222 		set_flags |= ISP_ABORT_NEEDED;
223 		rval = QL_FUNCTION_TIMEOUT;
224 	} else {
225 		ha->mailbox_flags = (uint8_t)
226 		    (ha->mailbox_flags & ~MBX_INTERRUPT);
227 		/*
228 		 * This is the expected completion path so
229 		 * return the actual mbx cmd completion status.
230 		 */
231 		rval = mcp->mb[0];
232 	}
233 
234 	/*
235 	 * Clear outbound to risc mailbox registers per spec. The exception
236 	 * is on 2200 mailbox 4 and 5 affect the req and resp que indexes
237 	 * so avoid writing them.
238 	 */
239 	if (ha->cfg_flags & CFG_CTRL_2200) {
240 		data = ((mcp->out_mb & ~(MBX_4 | MBX_5)) >> 1);
241 	} else {
242 		data = (mcp->out_mb >> 1);
243 	}
244 	for (cnt = 1; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
245 		if (data & MBX_0) {
246 			WRT16_IO_REG(ha, mailbox[cnt], (uint16_t)0);
247 		}
248 		data >>= 1;
249 	}
250 
251 	/* Reset busy status. */
252 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
253 	    ~(MBX_BUSY_FLG | MBX_ABORT));
254 	ha->mcp = NULL;
255 
256 	/* If thread is waiting for mailbox go signal it to start. */
257 	if (ha->mailbox_flags & MBX_WANT_FLG) {
258 		ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
259 		    ~MBX_WANT_FLG);
260 		cv_broadcast(&ha->cv_mbx_wait);
261 	}
262 
263 	/* Release mailbox register lock. */
264 	MBX_REGISTER_UNLOCK(ha);
265 
266 	if (set_flags != 0 || reset_flags != 0) {
267 		ql_awaken_task_daemon(ha, NULL, set_flags, reset_flags);
268 	}
269 
270 	if (rval != QL_SUCCESS) {
271 		EL(vha, "%s failed, rval=%xh, mcp->mb[0]=%xh\n",
272 		    mbx_cmd_text(mbx_cmd), rval, mcp->mb[0]);
273 	} else {
274 		/*EMPTY*/
275 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
276 	}
277 
278 	return (rval);
279 }
280 
281 /*
282  * ql_setup_mbox_dma_resources
283  *	Prepare the data for a mailbox dma transfer.
284  *
285  * Input:
286  *	ha = adapter state pointer.
287  *	mem_desc = descriptor to contain the dma resource information.
288  *	data = pointer to the data.
289  *	size = size of the data in bytes.
290  *
291  * Returns:
292  *	ql local function return status code.
293  *
294  * Context:
295  *	Kernel context.
296  */
297 static int
298 ql_setup_mbox_dma_transfer(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
299     caddr_t data, uint32_t size)
300 {
301 	int rval = QL_SUCCESS;
302 
303 	if ((rval = ql_setup_mbox_dma_resources(ha, mem_desc, size)) ==
304 	    QL_SUCCESS) {
305 		ql_setup_mbox_dma_data(mem_desc, data);
306 	} else {
307 		EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
308 	}
309 
310 	return (rval);
311 }
312 
313 /*
314  * ql_setup_mbox_dma_resources
315  *	Prepare a dma buffer.
316  *
317  * Input:
318  *	ha = adapter state pointer.
319  *	mem_desc = descriptor to contain the dma resource information.
320  *	data = pointer to the data.
321  *	size = size of the data in bytes.
322  *
323  * Returns:
324  *	ql local function return status code.
325  *
326  * Context:
327  *	Kernel context.
328  */
329 static int
330 ql_setup_mbox_dma_resources(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
331     uint32_t size)
332 {
333 	int	rval = QL_SUCCESS;
334 
335 	if ((rval = ql_get_dma_mem(ha, mem_desc, size, LITTLE_ENDIAN_DMA,
336 	    QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
337 		EL(ha, "failed, ql_get_dma_mem FC_NOMEM\n");
338 		rval = QL_MEMORY_ALLOC_FAILED;
339 	}
340 
341 	return (rval);
342 }
343 
344 /*
345  * ql_setup_mbox_dma_data
346  *	Move data to the dma buffer.
347  *
348  * Input:
349  *	mem_desc = descriptor to contain the dma resource information.
350  *	data = pointer to the data.
351  *
352  * Returns:
353  *
354  * Context:
355  *	Kernel context.
356  */
357 static void
358 ql_setup_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
359 {
360 	/* Copy out going data to DMA buffer. */
361 	ddi_rep_put8(mem_desc->acc_handle, (uint8_t *)data,
362 	    (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
363 
364 	/* Sync DMA buffer. */
365 	(void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
366 	    DDI_DMA_SYNC_FORDEV);
367 }
368 
369 /*
370  * ql_get_mbox_dma_data
371  *	Recover data from the dma buffer.
372  *
373  * Input:
374  *	mem_desc = descriptor to contain the dma resource information.
375  *	data = pointer to the data.
376  *
377  * Returns:
378  *
379  * Context:
380  *	Kernel context.
381  */
382 static void
383 ql_get_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
384 {
385 	/* Sync in coming DMA buffer. */
386 	(void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
387 	    DDI_DMA_SYNC_FORKERNEL);
388 	/* Copy in coming DMA data. */
389 	ddi_rep_get8(mem_desc->acc_handle, (uint8_t *)data,
390 	    (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
391 }
392 
393 /*
394  * ql_initialize_ip
395  *	Initialize IP receive buffer queue.
396  *
397  * Input:
398  *	ha = adapter state pointer.
399  *	ha->ip_init_ctrl_blk = setup for transmit.
400  *
401  * Returns:
402  *	ql local function return status code.
403  *
404  * Context:
405  *	Kernel context.
406  */
407 int
408 ql_initialize_ip(ql_adapter_state_t *ha)
409 {
410 	ql_link_t	*link;
411 	ql_tgt_t	*tq;
412 	uint16_t	index;
413 	int		rval;
414 	dma_mem_t	mem_desc;
415 	mbx_cmd_t	mc = {0};
416 	mbx_cmd_t	*mcp = &mc;
417 
418 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
419 
420 	if (CFG_IST(ha, (CFG_CTRL_6322 | CFG_CTRL_2581)) ||
421 	    ha->vp_index != 0) {
422 		ha->flags &= ~IP_INITIALIZED;
423 		EL(ha, "HBA does not support IP\n");
424 		return (QL_FUNCTION_FAILED);
425 	}
426 
427 	ha->rcvbuf_ring_ptr = ha->rcvbuf_ring_bp;
428 	ha->rcvbuf_ring_index = 0;
429 
430 	/* Reset all sequence counts. */
431 	for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
432 		for (link = ha->dev[index].first; link != NULL;
433 		    link = link->next) {
434 			tq = link->base_address;
435 			tq->ub_total_seg_cnt = 0;
436 		}
437 	}
438 
439 	rval = ql_setup_mbox_dma_transfer(ha, &mem_desc,
440 	    (caddr_t)&ha->ip_init_ctrl_blk, sizeof (ql_comb_ip_init_cb_t));
441 	if (rval != QL_SUCCESS) {
442 		EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
443 		return (rval);
444 	}
445 
446 	mcp->mb[0] = MBC_INITIALIZE_IP;
447 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
448 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
449 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
450 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
451 	mcp->mb[8] = 0;
452 	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
453 	mcp->in_mb = MBX_8|MBX_0;
454 	mcp->timeout = MAILBOX_TOV;
455 	rval = ql_mailbox_command(ha, mcp);
456 
457 	ql_free_dma_resource(ha, &mem_desc);
458 
459 	if (rval == QL_SUCCESS) {
460 		ADAPTER_STATE_LOCK(ha);
461 		ha->flags |= IP_INITIALIZED;
462 		ADAPTER_STATE_UNLOCK(ha);
463 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
464 	} else {
465 		ha->flags &= ~IP_INITIALIZED;
466 		EL(ha, "failed, rval = %xh\n", rval);
467 	}
468 	return (rval);
469 }
470 
471 /*
472  * ql_shutdown_ip
473  *	Disconnects firmware IP from system buffers.
474  *
475  * Input:
476  *	ha = adapter state pointer.
477  *
478  * Returns:
479  *	ql local function return status code.
480  *
481  * Context:
482  *	Kernel context.
483  */
484 int
485 ql_shutdown_ip(ql_adapter_state_t *ha)
486 {
487 	int		rval;
488 	mbx_cmd_t	mc = {0};
489 	mbx_cmd_t	*mcp = &mc;
490 	fc_unsol_buf_t	*ubp;
491 	ql_srb_t	*sp;
492 	uint16_t	index;
493 
494 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
495 
496 	mcp->mb[0] = MBC_UNLOAD_IP;
497 	mcp->out_mb = MBX_0;
498 	mcp->in_mb = MBX_0;
499 	mcp->timeout = MAILBOX_TOV;
500 	rval = ql_mailbox_command(ha, mcp);
501 
502 	ADAPTER_STATE_LOCK(ha);
503 	QL_UB_LOCK(ha);
504 	/* Return all unsolicited buffers that ISP-IP has. */
505 	for (index = 0; index < QL_UB_LIMIT; index++) {
506 		ubp = ha->ub_array[index];
507 		if (ubp != NULL) {
508 			sp = ubp->ub_fca_private;
509 			sp->flags &= ~SRB_UB_IN_ISP;
510 		}
511 	}
512 
513 	ha->ub_outcnt = 0;
514 	QL_UB_UNLOCK(ha);
515 	ha->flags &= ~IP_INITIALIZED;
516 	ADAPTER_STATE_UNLOCK(ha);
517 
518 	if (rval == QL_SUCCESS) {
519 		/* EMPTY - no need to check return value of MBC_SHUTDOWN_IP */
520 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
521 	} else {
522 		EL(ha, "failed, rval = %xh\n", rval);
523 	}
524 	return (rval);
525 }
526 
527 /*
528  * ql_online_selftest
529  *	Issue online self test mailbox command.
530  *
531  * Input:
532  *	ha = adapter state pointer.
533  *
534  * Returns:
535  *	ql local function return status code.
536  *
537  * Context:
538  *	Kernel context.
539  */
540 int
541 ql_online_selftest(ql_adapter_state_t *ha)
542 {
543 	int		rval;
544 	mbx_cmd_t	mc = {0};
545 	mbx_cmd_t	*mcp = &mc;
546 
547 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
548 
549 	mcp->mb[0] = MBC_ONLINE_SELF_TEST;
550 	mcp->out_mb = MBX_0;
551 	mcp->in_mb = MBX_0 | MBX_1 | MBX_2 | MBX_3;
552 	mcp->timeout = MAILBOX_TOV;
553 	rval = ql_mailbox_command(ha, mcp);
554 
555 	if (rval != QL_SUCCESS) {
556 		EL(ha, "failed, rval = %xh, mb1=%xh, mb2=%xh, mb3=%xh\n",
557 		    rval, mcp->mb[1], mcp->mb[2], mcp->mb[3]);
558 	} else {
559 		/*EMPTY*/
560 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
561 	}
562 	return (rval);
563 }
564 
565 /*
566  * ql_loop_back
567  *	Issue diagnostic loop back frame mailbox command.
568  *
569  * Input:
570  *	ha:	adapter state pointer.
571  *	findex:	FCF index.
572  *	lb:	loop back parameter structure pointer.
573  *
574  * Returns:
575  *	ql local function return status code.
576  *
577  * Context:
578  *	Kernel context.
579  */
580 #ifndef apps_64bit
581 int
582 ql_loop_back(ql_adapter_state_t *ha, uint16_t findex, lbp_t *lb,
583     uint32_t h_xmit, uint32_t h_rcv)
584 {
585 	int		rval;
586 	mbx_cmd_t	mc = {0};
587 	mbx_cmd_t	*mcp = &mc;
588 
589 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
590 
591 	mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
592 	mcp->mb[1] = lb->options;
593 	mcp->mb[2] = findex;
594 	mcp->mb[6] = LSW(h_rcv);
595 	mcp->mb[7] = MSW(h_rcv);
596 	mcp->mb[10] = LSW(lb->transfer_count);
597 	mcp->mb[11] = MSW(lb->transfer_count);
598 	mcp->mb[12] = lb->transfer_segment_count;
599 	mcp->mb[13] = lb->receive_segment_count;
600 	mcp->mb[14] = LSW(lb->transfer_data_address);
601 	mcp->mb[15] = MSW(lb->transfer_data_address);
602 	mcp->mb[16] = LSW(lb->receive_data_address);
603 	mcp->mb[17] = MSW(lb->receive_data_address);
604 	mcp->mb[18] = LSW(lb->iteration_count);
605 	mcp->mb[19] = MSW(lb->iteration_count);
606 	mcp->mb[20] = LSW(h_xmit);
607 	mcp->mb[21] = MSW(h_xmit);
608 	mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
609 	    MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
610 	mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
611 	mcp->timeout = lb->iteration_count / 300;
612 
613 	if (mcp->timeout < MAILBOX_TOV) {
614 		mcp->timeout = MAILBOX_TOV;
615 	}
616 
617 	rval = ql_mailbox_command(ha, mcp);
618 
619 	if (rval != QL_SUCCESS) {
620 		EL(ha, "failed, rval = %xh\n", rval);
621 	} else {
622 		/*EMPTY*/
623 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
624 	}
625 
626 	return (rval);
627 }
628 #else
629 int
630 ql_loop_back(ql_adapter_state_t *ha, uint16_t findex, lbp_t *lb)
631 {
632 	int		rval;
633 	mbx_cmd_t	mc = {0};
634 	mbx_cmd_t	*mcp = &mc;
635 
636 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
637 
638 	mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
639 	mcp->mb[1] = lb->options;
640 	mcp->mb[2] = findex;
641 	mcp->mb[6] = LSW(h_rcv);
642 	mcp->mb[7] = MSW(h_rcv);
643 	mcp->mb[6] = LSW(MSD(lb->receive_data_address));
644 	mcp->mb[7] = MSW(MSD(lb->receive_data_address));
645 	mcp->mb[10] = LSW(lb->transfer_count);
646 	mcp->mb[11] = MSW(lb->transfer_count);
647 	mcp->mb[12] = lb->transfer_segment_count;
648 	mcp->mb[13] = lb->receive_segment_count;
649 	mcp->mb[14] = LSW(lb->transfer_data_address);
650 	mcp->mb[15] = MSW(lb->transfer_data_address);
651 	mcp->mb[14] = LSW(LSD(lb->transfer_data_address));
652 	mcp->mb[15] = MSW(LSD(lb->transfer_data_address));
653 	mcp->mb[16] = LSW(lb->receive_data_address);
654 	mcp->mb[17] = MSW(lb->receive_data_address);
655 	mcp->mb[16] = LSW(LSD(lb->receive_data_address));
656 	mcp->mb[17] = MSW(LSD(lb->receive_data_address));
657 	mcp->mb[18] = LSW(lb->iteration_count);
658 	mcp->mb[19] = MSW(lb->iteration_count);
659 	mcp->mb[20] = LSW(h_xmit);
660 	mcp->mb[21] = MSW(h_xmit);
661 	mcp->mb[20] = LSW(MSD(lb->transfer_data_address));
662 	mcp->mb[21] = MSW(MSD(lb->transfer_data_address));
663 	mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
664 	    MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
665 	mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
666 	mcp->timeout = lb->iteration_count / 300;
667 
668 	if (mcp->timeout < MAILBOX_TOV) {
669 		mcp->timeout = MAILBOX_TOV;
670 	}
671 
672 	rval = ql_mailbox_command(ha, mcp);
673 
674 	if (rval != QL_SUCCESS) {
675 		EL(ha, "failed, rval = %xh\n", rval);
676 	} else {
677 		/*EMPTY*/
678 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
679 	}
680 	return (rval);
681 }
682 #endif
683 
684 /*
685  * ql_echo
686  *	Issue an ELS echo using the user specified data to a user specified
687  *	destination
688  *
689  * Input:
690  *	ha:		adapter state pointer.
691  *	findex:		FCF index.
692  *	echo_pt:	echo parameter structure pointer.
693  *
694  * Returns:
695  *	ql local function return status code.
696  *
697  * Context:
698  *	Kernel context.
699  */
700 int
701 ql_echo(ql_adapter_state_t *ha, uint16_t findex, echo_t *echo_pt)
702 {
703 	int		rval;
704 	mbx_cmd_t	mc = {0};
705 	mbx_cmd_t	*mcp = &mc;
706 
707 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
708 
709 	mcp->mb[0] = MBC_ECHO;			/* ECHO command */
710 	mcp->mb[1] = echo_pt->options;		/* command options; 64 bit */
711 						/* addressing (bit 6) and */
712 						/* real echo (bit 15 */
713 	mcp->mb[2] = findex;
714 
715 	/*
716 	 * I know this looks strange, using a field labled "not used"
717 	 * The way the ddi_dma_cookie_t structure/union is defined
718 	 * is a union of one 64 bit entity with an array of two 32
719 	 * bit enititys.  Since we have routines to convert 32 bit
720 	 * entities into 16 bit entities it is easier to use
721 	 * both 32 bit union members then the one 64 bit union
722 	 * member
723 	 */
724 	if (echo_pt->options & BIT_6) {
725 		/* 64 bit addressing */
726 		/* Receive data dest add in system memory bits 47-32 */
727 		mcp->mb[6] = LSW(echo_pt->receive_data_address.dmac_notused);
728 
729 		/* Receive data dest add in system memory bits 63-48 */
730 		mcp->mb[7] = MSW(echo_pt->receive_data_address.dmac_notused);
731 
732 		/* Transmit data source address in system memory bits 47-32 */
733 		mcp->mb[20] = LSW(echo_pt->transfer_data_address.dmac_notused);
734 
735 		/* Transmit data source address in system memory bits 63-48 */
736 		mcp->mb[21] = MSW(echo_pt->transfer_data_address.dmac_notused);
737 	}
738 
739 	/* transfer count bits 15-0 */
740 	mcp->mb[10] = LSW(echo_pt->transfer_count);
741 
742 	/* Transmit data source address in system memory bits 15-0 */
743 	mcp->mb[14] = LSW(echo_pt->transfer_data_address.dmac_address);
744 
745 	/*  Transmit data source address in system memory bits 31-16 */
746 	mcp->mb[15] = MSW(echo_pt->transfer_data_address.dmac_address);
747 
748 	/* Receive data destination address in system memory bits 15-0 */
749 	mcp->mb[16] = LSW(echo_pt->receive_data_address.dmac_address);
750 
751 	/*  Receive data destination address in system memory bits 31-16 */
752 	mcp->mb[17] = MSW(echo_pt->receive_data_address.dmac_address);
753 
754 	mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|MBX_14|MBX_10|
755 	    MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
756 	mcp->in_mb = MBX_3|MBX_1|MBX_0;
757 	mcp->timeout = MAILBOX_TOV;
758 
759 	rval = ql_mailbox_command(ha, mcp);
760 
761 	if (rval != QL_SUCCESS) {
762 		EL(ha, "failed, rval = %xh\n", rval);
763 	} else {
764 		/*EMPTY*/
765 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
766 	}
767 	return (rval);
768 }
769 
770 /*
771  * ql_send_change_request
772  *	Issue send change request mailbox command.
773  *
774  * Input:
775  *	ha:	adapter state pointer.
776  *	fmt:	Registration format.
777  *
778  * Returns:
779  *	ql local function return status code.
780  *
781  * Context:
782  *	Kernel context.
783  */
784 int
785 ql_send_change_request(ql_adapter_state_t *ha, uint16_t fmt)
786 {
787 	int		rval;
788 	mbx_cmd_t	mc = {0};
789 	mbx_cmd_t	*mcp = &mc;
790 
791 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
792 
793 	mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
794 	mcp->mb[1] = fmt;
795 	mcp->out_mb = MBX_1|MBX_0;
796 	if (ha->flags & VP_ENABLED) {
797 		mcp->mb[9] = ha->vp_index;
798 		mcp->out_mb |= MBX_9;
799 	}
800 	mcp->in_mb = MBX_0;
801 	mcp->timeout = MAILBOX_TOV;
802 	rval = ql_mailbox_command(ha, mcp);
803 
804 	if (rval != QL_SUCCESS) {
805 		EL(ha, "failed=%xh\n", rval);
806 	} else {
807 		/*EMPTY*/
808 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
809 	}
810 	return (rval);
811 }
812 
813 /*
814  * ql_send_lfa
815  *	Send a Loop Fabric Address mailbox command.
816  *
817  * Input:
818  *	ha:	adapter state pointer.
819  *	lfa:	LFA command structure pointer.
820  *
821  * Returns:
822  *	ql local function return status code.
823  *
824  * Context:
825  *	Kernel context.
826  */
827 int
828 ql_send_lfa(ql_adapter_state_t *ha, lfa_cmd_t *lfa)
829 {
830 	int		rval;
831 	uint16_t	size;
832 	dma_mem_t	mem_desc;
833 	mbx_cmd_t	mc = {0};
834 	mbx_cmd_t	*mcp = &mc;
835 
836 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
837 
838 	/* LFA_CB sz = 4 16bit words subcommand + 10 16bit words header. */
839 	size = (uint16_t)((lfa->subcommand_length[0] + 10) << 1);
840 
841 	rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, (caddr_t)lfa, size);
842 	if (rval != QL_SUCCESS) {
843 		EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
844 		return (rval);
845 	}
846 
847 	mcp->mb[0] = MBC_SEND_LFA_COMMAND;
848 	mcp->mb[1] = (uint16_t)(size >> 1);
849 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
850 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
851 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
852 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
853 	mcp->in_mb = MBX_0;
854 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
855 	if (ha->flags & VP_ENABLED) {
856 		mcp->mb[9] = ha->vp_index;
857 		mcp->out_mb |= MBX_9;
858 	}
859 	mcp->timeout = MAILBOX_TOV;
860 	rval = ql_mailbox_command(ha, mcp);
861 
862 	ql_free_dma_resource(ha, &mem_desc);
863 
864 	if (rval != QL_SUCCESS) {
865 		EL(ha, "failed, rval = %xh\n", rval);
866 	} else {
867 		/*EMPTY*/
868 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
869 	}
870 
871 	return (rval);
872 }
873 
874 /*
875  * ql_clear_aca
876  *	Issue clear ACA mailbox command.
877  *
878  * Input:
879  *	ha:	adapter state pointer.
880  *	tq:	target queue pointer.
881  *	lun:	LUN.
882  *
883  * Returns:
884  *	ql local function return status code.
885  *
886  * Context:
887  *	Kernel context.
888  */
889 int
890 ql_clear_aca(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
891 {
892 	int		rval;
893 	mbx_cmd_t	mc = {0};
894 	mbx_cmd_t	*mcp = &mc;
895 
896 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
897 
898 	if (CFG_IST(ha, CFG_CTRL_242581)) {
899 		rval = ql_task_mgmt_iocb(ha, tq, lun, CF_CLEAR_ACA, 0);
900 	} else {
901 		mcp->mb[0] = MBC_CLEAR_ACA;
902 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
903 			mcp->mb[1] = tq->loop_id;
904 		} else {
905 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
906 		}
907 		mcp->mb[2] = lun;
908 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
909 		mcp->in_mb = MBX_0;
910 		mcp->timeout = MAILBOX_TOV;
911 		rval = ql_mailbox_command(ha, mcp);
912 	}
913 
914 	(void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
915 
916 	if (rval != QL_SUCCESS) {
917 		EL(ha, "failed, rval = %xh\n", rval);
918 	} else {
919 		/*EMPTY*/
920 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
921 	}
922 
923 	return (rval);
924 }
925 
926 /*
927  * ql_target_reset
928  *	Issue target reset mailbox command.
929  *
930  * Input:
931  *	ha:	adapter state pointer.
932  *	tq:	target queue pointer.
933  *	delay:	seconds.
934  *
935  * Returns:
936  *	ql local function return status code.
937  *
938  * Context:
939  *	Kernel context.
940  */
941 int
942 ql_target_reset(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t delay)
943 {
944 	ql_link_t	*link;
945 	uint16_t	index;
946 	int		rval;
947 	mbx_cmd_t	mc = {0};
948 	mbx_cmd_t	*mcp = &mc;
949 
950 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
951 
952 	if (CFG_IST(ha, CFG_CTRL_242581)) {
953 		/* queue = NULL, all targets. */
954 		if (tq == NULL) {
955 			for (index = 0; index < DEVICE_HEAD_LIST_SIZE;
956 			    index++) {
957 				for (link = ha->dev[index].first; link !=
958 				    NULL; link = link->next) {
959 					tq = link->base_address;
960 					if (!VALID_DEVICE_ID(ha,
961 					    tq->loop_id)) {
962 						continue;
963 					}
964 					rval = ql_task_mgmt_iocb(ha, tq, 0,
965 					    CF_TARGET_RESET, delay);
966 
967 					if (rval != QL_SUCCESS) {
968 						break;
969 					}
970 				}
971 
972 				if (link != NULL) {
973 					break;
974 				}
975 			}
976 			tq = NULL;
977 		} else {
978 			rval = ql_task_mgmt_iocb(ha, tq, 0, CF_TARGET_RESET,
979 			    delay);
980 		}
981 	} else {
982 		/* queue = NULL, all targets. */
983 		if (tq == NULL) {
984 			mcp->mb[0] = MBC_RESET;
985 			mcp->mb[1] = delay;
986 			mcp->out_mb = MBX_1|MBX_0;
987 		} else {
988 			mcp->mb[0] = MBC_TARGET_RESET;
989 			if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
990 				mcp->mb[1] = tq->loop_id;
991 			} else {
992 				mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
993 			}
994 			mcp->mb[2] = delay;
995 			mcp->out_mb = MBX_2|MBX_1|MBX_0;
996 		}
997 		mcp->in_mb = MBX_0;
998 		mcp->timeout = MAILBOX_TOV;
999 		rval = ql_mailbox_command(ha, mcp);
1000 	}
1001 
1002 	tq == NULL ? (void) ql_marker(ha, 0, 0, MK_SYNC_ALL) :
1003 	    (void) ql_marker(ha, tq->loop_id, 0, MK_SYNC_ID);
1004 
1005 	if (rval != QL_SUCCESS) {
1006 		EL(ha, "failed, rval = %xh\n", rval);
1007 	} else {
1008 		/*EMPTY*/
1009 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1010 	}
1011 
1012 	return (rval);
1013 }
1014 
1015 /*
1016  * ql_abort_target
1017  *	Issue abort target mailbox command.
1018  *
1019  * Input:
1020  *	ha:	adapter state pointer.
1021  *	tq:	target queue pointer.
1022  *	delay:	in seconds.
1023  *
1024  * Returns:
1025  *	ql local function return status code.
1026  *
1027  * Context:
1028  *	Kernel context.
1029  */
1030 int
1031 ql_abort_target(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t delay)
1032 {
1033 	int		rval;
1034 	mbx_cmd_t	mc = {0};
1035 	mbx_cmd_t	*mcp = &mc;
1036 
1037 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1038 
1039 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1040 		rval = ql_task_mgmt_iocb(ha, tq, 0,
1041 		    CF_DO_NOT_SEND | CF_TARGET_RESET, delay);
1042 	} else {
1043 		mcp->mb[0] = MBC_ABORT_TARGET;
1044 		/* Don't send Task Mgt */
1045 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1046 			mcp->mb[1] = tq->loop_id;
1047 			mcp->mb[10] = BIT_0;
1048 			mcp->out_mb = MBX_10|MBX_2|MBX_1|MBX_0;
1049 		} else {
1050 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | BIT_0);
1051 			mcp->out_mb = MBX_2|MBX_1|MBX_0;
1052 		}
1053 		mcp->mb[2] = delay;
1054 		mcp->in_mb = MBX_0;
1055 		mcp->timeout = MAILBOX_TOV;
1056 		rval = ql_mailbox_command(ha, mcp);
1057 	}
1058 
1059 	(void) ql_marker(ha, tq->loop_id, 0, MK_SYNC_ID);
1060 
1061 	if (rval != QL_SUCCESS) {
1062 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1063 	} else {
1064 		/*EMPTY*/
1065 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1066 	}
1067 	return (rval);
1068 }
1069 
1070 /*
1071  * ql_lun_reset
1072  *	Issue LUN reset task management mailbox command.
1073  *
1074  * Input:
1075  *	ha:	adapter state pointer.
1076  *	tq:	target queue pointer.
1077  *	lun:	LUN.
1078  *
1079  * Returns:
1080  *	ql local function return status code.
1081  *
1082  * Context:
1083  *	Kernel context.
1084  */
1085 int
1086 ql_lun_reset(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1087 {
1088 	int		rval;
1089 	mbx_cmd_t	mc = {0};
1090 	mbx_cmd_t	*mcp = &mc;
1091 
1092 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1093 
1094 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1095 		rval = ql_task_mgmt_iocb(ha, tq, lun, CF_LUN_RESET, 0);
1096 	} else {
1097 		mcp->mb[0] = MBC_LUN_RESET;
1098 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1099 			mcp->mb[1] = tq->loop_id;
1100 		} else {
1101 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1102 		}
1103 		mcp->mb[2] = lun;
1104 		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1105 		mcp->in_mb = MBX_0;
1106 		mcp->timeout = MAILBOX_TOV;
1107 		rval = ql_mailbox_command(ha, mcp);
1108 	}
1109 
1110 	(void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1111 
1112 	if (rval != QL_SUCCESS) {
1113 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1114 	} else {
1115 		/*EMPTY*/
1116 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1117 	}
1118 	return (rval);
1119 }
1120 
1121 /*
1122  * ql_clear_task_set
1123  *	Issue clear task set mailbox command.
1124  *
1125  * Input:
1126  *	ha:	adapter state pointer.
1127  *	tq:	target queue pointer.
1128  *	lun:	LUN.
1129  *
1130  * Returns:
1131  *	ql local function return status code.
1132  *
1133  * Context:
1134  *	Kernel context.
1135  */
1136 int
1137 ql_clear_task_set(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1138 {
1139 	int		rval;
1140 	mbx_cmd_t	mc = {0};
1141 	mbx_cmd_t	*mcp = &mc;
1142 
1143 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1144 
1145 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1146 		rval = ql_task_mgmt_iocb(ha, tq, lun, CF_CLEAR_TASK_SET, 0);
1147 	} else {
1148 		mcp->mb[0] = MBC_CLEAR_TASK_SET;
1149 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1150 			mcp->mb[1] = tq->loop_id;
1151 		} else {
1152 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1153 		}
1154 		mcp->mb[2] = lun;
1155 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
1156 		mcp->in_mb = MBX_0;
1157 		mcp->timeout = MAILBOX_TOV;
1158 		rval = ql_mailbox_command(ha, mcp);
1159 	}
1160 
1161 	(void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1162 
1163 	if (rval != QL_SUCCESS) {
1164 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1165 	} else {
1166 		/*EMPTY*/
1167 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1168 	}
1169 
1170 	return (rval);
1171 }
1172 
1173 /*
1174  * ql_abort_task_set
1175  *	Issue abort task set mailbox command.
1176  *
1177  * Input:
1178  *	ha:	adapter state pointer.
1179  *	tq:	target queue pointer.
1180  *	lun:	LUN.
1181  *
1182  * Returns:
1183  *	ql local function return status code.
1184  *
1185  * Context:
1186  *	Kernel context.
1187  */
1188 int
1189 ql_abort_task_set(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1190 {
1191 	int		rval;
1192 	mbx_cmd_t	mc = {0};
1193 	mbx_cmd_t	*mcp = &mc;
1194 
1195 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1196 
1197 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1198 		rval = ql_task_mgmt_iocb(ha, tq, lun, CF_ABORT_TASK_SET, 0);
1199 	} else {
1200 		mcp->mb[0] = MBC_ABORT_TASK_SET;
1201 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1202 			mcp->mb[1] = tq->loop_id;
1203 		} else {
1204 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1205 		}
1206 		mcp->mb[2] = lun;
1207 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
1208 		mcp->in_mb = MBX_0;
1209 		mcp->timeout = MAILBOX_TOV;
1210 		rval = ql_mailbox_command(ha, mcp);
1211 	}
1212 
1213 	(void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1214 
1215 	if (rval != QL_SUCCESS) {
1216 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1217 	} else {
1218 		/*EMPTY*/
1219 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1220 	}
1221 
1222 	return (rval);
1223 }
1224 
1225 /*
1226  * ql_task_mgmt_iocb
1227  *	Function issues task management IOCB.
1228  *
1229  * Input:
1230  *	ha:	adapter state pointer.
1231  *	tq:	target queue pointer.
1232  *	lun:	LUN.
1233  *	flags:	control flags.
1234  *	delay:	seconds.
1235  *
1236  * Returns:
1237  *	ql local function return status code.
1238  *
1239  * Context:
1240  *	Kernel context
1241  */
1242 static int
1243 ql_task_mgmt_iocb(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun,
1244     uint32_t flags, uint16_t delay)
1245 {
1246 	ql_mbx_iocb_t	*pkt;
1247 	int		rval;
1248 	uint32_t	pkt_size;
1249 
1250 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1251 
1252 	pkt_size = sizeof (ql_mbx_iocb_t);
1253 	pkt = kmem_zalloc(pkt_size, KM_SLEEP);
1254 	if (pkt == NULL) {
1255 		EL(ha, "failed, kmem_zalloc\n");
1256 		return (QL_MEMORY_ALLOC_FAILED);
1257 	}
1258 
1259 	pkt->mgmt.entry_type = TASK_MGMT_TYPE;
1260 	pkt->mgmt.entry_count = 1;
1261 
1262 	pkt->mgmt.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
1263 	pkt->mgmt.delay = (uint16_t)LE_16(delay);
1264 	pkt->mgmt.timeout = LE_16(MAILBOX_TOV);
1265 	pkt->mgmt.fcp_lun[2] = LSB(lun);
1266 	pkt->mgmt.fcp_lun[3] = MSB(lun);
1267 	pkt->mgmt.control_flags = LE_32(flags);
1268 	pkt->mgmt.target_id[0] = tq->d_id.b.al_pa;
1269 	pkt->mgmt.target_id[1] = tq->d_id.b.area;
1270 	pkt->mgmt.target_id[2] = tq->d_id.b.domain;
1271 	pkt->mgmt.vp_index = ha->vp_index;
1272 
1273 	rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
1274 	if (rval == QL_SUCCESS && (pkt->sts24.entry_status & 0x3c) != 0) {
1275 		EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
1276 		    pkt->sts24.entry_status, tq->d_id.b24);
1277 		rval = QL_FUNCTION_PARAMETER_ERROR;
1278 	}
1279 
1280 	LITTLE_ENDIAN_16(&pkt->sts24.comp_status);
1281 
1282 	if (rval == QL_SUCCESS && pkt->sts24.comp_status != CS_COMPLETE) {
1283 		EL(ha, "failed, comp_status=%xh, d_id=%xh\n",
1284 		    pkt->sts24.comp_status, tq->d_id.b24);
1285 		rval = QL_FUNCTION_FAILED;
1286 	}
1287 
1288 	kmem_free(pkt, pkt_size);
1289 
1290 	if (rval != QL_SUCCESS) {
1291 		EL(ha, "failed, rval = %xh\n", rval);
1292 	} else {
1293 		/*EMPTY*/
1294 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1295 	}
1296 
1297 	return (rval);
1298 }
1299 
1300 /*
1301  * ql_loop_port_bypass
1302  *	Issue loop port bypass mailbox command.
1303  *
1304  * Input:
1305  *	ha:	adapter state pointer.
1306  *	tq:	target queue pointer.
1307  *
1308  * Returns:
1309  *	ql local function return status code.
1310  *
1311  * Context:
1312  *	Kernel context.
1313  */
1314 int
1315 ql_loop_port_bypass(ql_adapter_state_t *ha, ql_tgt_t *tq)
1316 {
1317 	int		rval;
1318 	mbx_cmd_t	mc = {0};
1319 	mbx_cmd_t	*mcp = &mc;
1320 
1321 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1322 
1323 	mcp->mb[0] = MBC_LOOP_PORT_BYPASS;
1324 
1325 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1326 		mcp->mb[1] = tq->d_id.b.al_pa;
1327 	} else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1328 		mcp->mb[1] = tq->loop_id;
1329 	} else {
1330 		mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1331 	}
1332 
1333 	mcp->out_mb = MBX_1|MBX_0;
1334 	mcp->in_mb = MBX_0;
1335 	mcp->timeout = MAILBOX_TOV;
1336 	rval = ql_mailbox_command(ha, mcp);
1337 
1338 	if (rval != QL_SUCCESS) {
1339 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1340 	} else {
1341 		/*EMPTY*/
1342 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1343 	}
1344 
1345 	return (rval);
1346 }
1347 
1348 /*
1349  * ql_loop_port_enable
1350  *	Issue loop port enable mailbox command.
1351  *
1352  * Input:
1353  *	ha:	adapter state pointer.
1354  *	tq:	target queue pointer.
1355  *
1356  * Returns:
1357  *	ql local function return status code.
1358  *
1359  * Context:
1360  *	Kernel context.
1361  */
1362 int
1363 ql_loop_port_enable(ql_adapter_state_t *ha, ql_tgt_t *tq)
1364 {
1365 	int		rval;
1366 	mbx_cmd_t	mc = {0};
1367 	mbx_cmd_t	*mcp = &mc;
1368 
1369 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1370 
1371 	mcp->mb[0] = MBC_LOOP_PORT_ENABLE;
1372 
1373 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1374 		mcp->mb[1] = tq->d_id.b.al_pa;
1375 	} else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1376 		mcp->mb[1] = tq->loop_id;
1377 	} else {
1378 		mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1379 	}
1380 	mcp->out_mb = MBX_1|MBX_0;
1381 	mcp->in_mb = MBX_0;
1382 	mcp->timeout = MAILBOX_TOV;
1383 	rval = ql_mailbox_command(ha, mcp);
1384 
1385 	if (rval != QL_SUCCESS) {
1386 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1387 	} else {
1388 		/*EMPTY*/
1389 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1390 	}
1391 
1392 	return (rval);
1393 }
1394 
1395 /*
1396  * ql_login_lport
1397  *	Issue login loop port mailbox command.
1398  *
1399  * Input:
1400  *	ha:		adapter state pointer.
1401  *	tq:		target queue pointer.
1402  *	loop_id:	FC loop id.
1403  *	opt:		options.
1404  *			LLF_NONE, LLF_PLOGI
1405  *
1406  * Returns:
1407  *	ql local function return status code.
1408  *
1409  * Context:
1410  *	Kernel context.
1411  */
1412 int
1413 ql_login_lport(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1414     uint16_t opt)
1415 {
1416 	int		rval;
1417 	uint16_t	flags;
1418 	ql_mbx_data_t	mr;
1419 	mbx_cmd_t	mc = {0};
1420 	mbx_cmd_t	*mcp = &mc;
1421 
1422 	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh, loop_id=%xh\n",
1423 	    ha->instance, tq->d_id.b24, loop_id);
1424 
1425 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1426 		flags = CF_CMD_PLOGI;
1427 		if ((opt & LLF_PLOGI) == 0) {
1428 			flags = (uint16_t)(flags | CFO_COND_PLOGI);
1429 		}
1430 		rval = ql_log_iocb(ha, tq, loop_id, flags, &mr);
1431 	} else {
1432 		mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
1433 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1434 			mcp->mb[1] = loop_id;
1435 		} else {
1436 			mcp->mb[1] = (uint16_t)(loop_id << 8);
1437 		}
1438 		mcp->mb[2] = opt;
1439 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
1440 		mcp->in_mb = MBX_0;
1441 		mcp->timeout = MAILBOX_TOV;
1442 		rval = ql_mailbox_command(ha, mcp);
1443 	}
1444 
1445 	if (rval != QL_SUCCESS) {
1446 		EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", tq->d_id.b24,
1447 		    loop_id, rval);
1448 	} else {
1449 		/*EMPTY*/
1450 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1451 	}
1452 
1453 	return (rval);
1454 }
1455 
1456 /*
1457  * ql_login_fport
1458  *	Issue login fabric port mailbox command.
1459  *
1460  * Input:
1461  *	ha:		adapter state pointer.
1462  *	tq:		target queue pointer.
1463  *	loop_id:	FC loop id.
1464  *	opt:		options.
1465  *			LFF_NONE, LFF_NO_PLOGI, LFF_NO_PRLI
1466  *	mr:		pointer for mailbox data.
1467  *
1468  * Returns:
1469  *	ql local function return status code.
1470  *
1471  * Context:
1472  *	Kernel context.
1473  */
1474 int
1475 ql_login_fport(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1476     uint16_t opt, ql_mbx_data_t *mr)
1477 {
1478 	int		rval;
1479 	uint16_t	flags;
1480 	mbx_cmd_t	mc = {0};
1481 	mbx_cmd_t	*mcp = &mc;
1482 
1483 	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh, loop_id=%xh\n",
1484 	    ha->instance, tq->d_id.b24, loop_id);
1485 
1486 	if ((tq->d_id.b24 & 0xffffff) == 0xfffffa) {
1487 		opt = (uint16_t)(opt | LFF_NO_PRLI);
1488 	}
1489 
1490 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1491 		flags = CF_CMD_PLOGI;
1492 		if (opt & LFF_NO_PLOGI) {
1493 			flags = (uint16_t)(flags | CFO_COND_PLOGI);
1494 		}
1495 		if (opt & LFF_NO_PRLI) {
1496 			flags = (uint16_t)(flags | CFO_SKIP_PRLI);
1497 		}
1498 		rval = ql_log_iocb(ha, tq, loop_id, flags, mr);
1499 	} else {
1500 		mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
1501 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1502 			mcp->mb[1] = loop_id;
1503 			mcp->mb[10] = opt;
1504 			mcp->out_mb = MBX_10|MBX_3|MBX_2|MBX_1|MBX_0;
1505 		} else {
1506 			mcp->mb[1] = (uint16_t)(loop_id << 8 | opt);
1507 			mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1508 		}
1509 		mcp->mb[2] = MSW(tq->d_id.b24);
1510 		mcp->mb[3] = LSW(tq->d_id.b24);
1511 		mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
1512 		mcp->timeout = MAILBOX_TOV;
1513 		rval = ql_mailbox_command(ha, mcp);
1514 
1515 		/* Return mailbox data. */
1516 		if (mr != NULL) {
1517 			mr->mb[0] = mcp->mb[0];
1518 			mr->mb[1] = mcp->mb[1];
1519 			mr->mb[2] = mcp->mb[2];
1520 			mr->mb[6] = mcp->mb[6];
1521 			mr->mb[7] = mcp->mb[7];
1522 		}
1523 	}
1524 
1525 	if (rval != QL_SUCCESS) {
1526 		EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh, mb1=%02xh, "
1527 		    "mb2=%04x\n", tq->d_id.b24, loop_id, rval, mr->mb[1],
1528 		    mr->mb[2]);
1529 	} else {
1530 		/*EMPTY*/
1531 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1532 	}
1533 
1534 	return (rval);
1535 }
1536 
1537 /*
1538  * ql_logout_fabric_port
1539  *	Issue logout fabric port mailbox command.
1540  *
1541  * Input:
1542  *	ha:	adapter state pointer.
1543  *	tq:	target queue pointer.
1544  *
1545  * Returns:
1546  *	ql local function return status code.
1547  *
1548  * Context:
1549  *	Kernel context.
1550  */
1551 int
1552 ql_logout_fabric_port(ql_adapter_state_t *ha, ql_tgt_t *tq)
1553 {
1554 	int		rval;
1555 	uint16_t	flag;
1556 	ql_mbx_data_t	mr;
1557 	mbx_cmd_t	mc = {0};
1558 	mbx_cmd_t	*mcp = &mc;
1559 
1560 	QL_PRINT_3(CE_CONT, "(%d): started, loop_id=%xh d_id=%xh\n",
1561 	    ha->instance, tq->loop_id, tq->d_id.b24);
1562 
1563 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1564 		flag = (uint16_t)(RESERVED_LOOP_ID(ha, tq->loop_id) ?
1565 		    CFO_EXPLICIT_LOGO |CF_CMD_LOGO | CFO_FREE_N_PORT_HANDLE :
1566 		    CFO_IMPLICIT_LOGO |CF_CMD_LOGO | CFO_FREE_N_PORT_HANDLE);
1567 		rval = ql_log_iocb(ha, tq, tq->loop_id, flag, &mr);
1568 	} else {
1569 		flag = (uint16_t)(RESERVED_LOOP_ID(ha, tq->loop_id) ?  1 : 0);
1570 		mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
1571 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1572 			mcp->mb[1] = tq->loop_id;
1573 			mcp->mb[10] = flag;
1574 			mcp->out_mb = MBX_10|MBX_1|MBX_0;
1575 		} else {
1576 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | flag);
1577 			mcp->out_mb = MBX_1|MBX_0;
1578 		}
1579 		mcp->in_mb = MBX_0;
1580 		mcp->timeout = MAILBOX_TOV;
1581 		rval = ql_mailbox_command(ha, mcp);
1582 	}
1583 
1584 	if (rval != QL_SUCCESS) {
1585 		EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", rval,
1586 		    tq->d_id.b24, tq->loop_id);
1587 	} else {
1588 		/*EMPTY*/
1589 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1590 	}
1591 
1592 	return (rval);
1593 }
1594 
1595 /*
1596  * ql_log_iocb
1597  *	Function issues login/logout IOCB.
1598  *
1599  * Input:
1600  *	ha:		adapter state pointer.
1601  *	tq:		target queue pointer.
1602  *	loop_id:	FC Loop ID.
1603  *	flags:		control flags.
1604  *	mr:		pointer for mailbox data.
1605  *
1606  * Returns:
1607  *	ql local function return status code.
1608  *
1609  * Context:
1610  *	Kernel context.
1611  */
1612 int
1613 ql_log_iocb(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1614     uint16_t flags, ql_mbx_data_t *mr)
1615 {
1616 	ql_mbx_iocb_t	*pkt;
1617 	int		rval;
1618 	uint32_t	pkt_size;
1619 
1620 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1621 
1622 	pkt_size = sizeof (ql_mbx_iocb_t);
1623 	pkt = kmem_zalloc(pkt_size, KM_SLEEP);
1624 	if (pkt == NULL) {
1625 		EL(ha, "failed, kmem_zalloc\n");
1626 		return (QL_MEMORY_ALLOC_FAILED);
1627 	}
1628 
1629 	pkt->log.entry_type = LOG_TYPE;
1630 	pkt->log.entry_count = 1;
1631 	pkt->log.n_port_hdl = (uint16_t)LE_16(loop_id);
1632 	pkt->log.control_flags = (uint16_t)LE_16(flags);
1633 	pkt->log.port_id[0] = tq->d_id.b.al_pa;
1634 	pkt->log.port_id[1] = tq->d_id.b.area;
1635 	pkt->log.port_id[2] = tq->d_id.b.domain;
1636 	pkt->log.vp_index = ha->vp_index;
1637 
1638 	rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
1639 	if (rval == QL_SUCCESS && (pkt->log.entry_status & 0x3c) != 0) {
1640 		EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
1641 		    pkt->log.entry_status, tq->d_id.b24);
1642 		rval = QL_FUNCTION_PARAMETER_ERROR;
1643 	}
1644 
1645 	if (rval == QL_SUCCESS) {
1646 		if (pkt->log.rsp_size == 0xB) {
1647 			LITTLE_ENDIAN_32(&pkt->log.io_param[5]);
1648 			tq->cmn_features = MSW(pkt->log.io_param[5]);
1649 			LITTLE_ENDIAN_32(&pkt->log.io_param[6]);
1650 			tq->conc_sequences = MSW(pkt->log.io_param[6]);
1651 			tq->relative_offset = LSW(pkt->log.io_param[6]);
1652 			LITTLE_ENDIAN_32(&pkt->log.io_param[9]);
1653 			tq->class3_recipient_ctl = MSW(pkt->log.io_param[9]);
1654 			tq->class3_conc_sequences = LSW(pkt->log.io_param[9]);
1655 			LITTLE_ENDIAN_32(&pkt->log.io_param[10]);
1656 			tq->class3_open_sequences_per_exch =
1657 			    MSW(pkt->log.io_param[10]);
1658 			tq->prli_payload_length = 0x14;
1659 		}
1660 		if (mr != NULL) {
1661 			LITTLE_ENDIAN_16(&pkt->log.status);
1662 			LITTLE_ENDIAN_32(&pkt->log.io_param[0]);
1663 			LITTLE_ENDIAN_32(&pkt->log.io_param[1]);
1664 
1665 			if (pkt->log.status != CS_COMPLETE) {
1666 				EL(ha, "failed, status=%xh, iop0=%xh, iop1="
1667 				    "%xh\n", pkt->log.status,
1668 				    pkt->log.io_param[0],
1669 				    pkt->log.io_param[1]);
1670 
1671 				switch (pkt->log.io_param[0]) {
1672 				case CS0_NO_LINK:
1673 				case CS0_FIRMWARE_NOT_READY:
1674 					mr->mb[0] = MBS_COMMAND_ERROR;
1675 					mr->mb[1] = 1;
1676 					break;
1677 				case CS0_NO_IOCB:
1678 				case CS0_NO_PCB_ALLOCATED:
1679 					mr->mb[0] = MBS_COMMAND_ERROR;
1680 					mr->mb[1] = 2;
1681 					break;
1682 				case CS0_NO_EXCH_CTRL_BLK:
1683 					mr->mb[0] = MBS_COMMAND_ERROR;
1684 					mr->mb[1] = 3;
1685 					break;
1686 				case CS0_COMMAND_FAILED:
1687 					mr->mb[0] = MBS_COMMAND_ERROR;
1688 					mr->mb[1] = 4;
1689 					switch (LSB(pkt->log.io_param[1])) {
1690 					case CS1_PLOGI_RESPONSE_FAILED:
1691 						mr->mb[2] = 3;
1692 						break;
1693 					case CS1_PRLI_FAILED:
1694 						mr->mb[2] = 4;
1695 						break;
1696 					case CS1_PRLI_RESPONSE_FAILED:
1697 						mr->mb[2] = 5;
1698 						break;
1699 					case CS1_COMMAND_LOGGED_OUT:
1700 						mr->mb[2] = 7;
1701 						break;
1702 					case CS1_PLOGI_FAILED:
1703 					default:
1704 						EL(ha, "log iop1 = %xh\n",
1705 						    LSB(pkt->log.io_param[1]))
1706 						mr->mb[2] = 2;
1707 						break;
1708 					}
1709 					break;
1710 				case CS0_PORT_NOT_LOGGED_IN:
1711 					mr->mb[0] = MBS_COMMAND_ERROR;
1712 					mr->mb[1] = 4;
1713 					mr->mb[2] = 7;
1714 					break;
1715 				case CS0_NO_FLOGI_ACC:
1716 				case CS0_NO_FABRIC_PRESENT:
1717 					mr->mb[0] = MBS_COMMAND_ERROR;
1718 					mr->mb[1] = 5;
1719 					break;
1720 				case CS0_ELS_REJECT_RECEIVED:
1721 					mr->mb[0] = MBS_COMMAND_ERROR;
1722 					mr->mb[1] = 0xd;
1723 					break;
1724 				case CS0_PORT_ID_USED:
1725 					mr->mb[0] = MBS_PORT_ID_USED;
1726 					mr->mb[1] = LSW(pkt->log.io_param[1]);
1727 					break;
1728 				case CS0_N_PORT_HANDLE_USED:
1729 					mr->mb[0] = MBS_LOOP_ID_USED;
1730 					mr->mb[1] = MSW(pkt->log.io_param[1]);
1731 					mr->mb[2] = LSW(pkt->log.io_param[1]);
1732 					break;
1733 				case CS0_NO_N_PORT_HANDLE_AVAILABLE:
1734 					mr->mb[0] = MBS_ALL_IDS_IN_USE;
1735 					break;
1736 				case CS0_CMD_PARAMETER_ERROR:
1737 				default:
1738 					EL(ha, "pkt->log iop[0]=%xh\n",
1739 					    pkt->log.io_param[0]);
1740 					mr->mb[0] =
1741 					    MBS_COMMAND_PARAMETER_ERROR;
1742 					break;
1743 				}
1744 			} else {
1745 				QL_PRINT_3(CE_CONT, "(%d): status=%xh\n",
1746 				    ha->instance, pkt->log.status);
1747 
1748 				mr->mb[0] = MBS_COMMAND_COMPLETE;
1749 				mr->mb[1] = (uint16_t)
1750 				    (pkt->log.io_param[0] & BIT_4 ? 0 : BIT_0);
1751 				if (pkt->log.io_param[0] & BIT_8) {
1752 					mr->mb[1] = (uint16_t)
1753 					    (mr->mb[1] | BIT_1);
1754 				}
1755 			}
1756 			rval = mr->mb[0];
1757 		}
1758 
1759 	}
1760 
1761 	kmem_free(pkt, pkt_size);
1762 
1763 	if (rval != QL_SUCCESS) {
1764 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1765 	} else {
1766 		/*EMPTY*/
1767 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1768 	}
1769 
1770 	return (rval);
1771 }
1772 
1773 /*
1774  * ql_get_port_database
1775  *	Issue get port database mailbox command
1776  *	and copy context to device queue.
1777  *
1778  * Input:
1779  *	ha:	adapter state pointer.
1780  *	tq:	target queue pointer.
1781  *	opt:	options.
1782  *		PDF_NONE, PDF_PLOGI, PDF_ADISC
1783  * Returns:
1784  *	ql local function return status code.
1785  *
1786  * Context:
1787  *	Kernel context.
1788  */
1789 int
1790 ql_get_port_database(ql_adapter_state_t *ha, ql_tgt_t *tq, uint8_t opt)
1791 {
1792 	int			rval;
1793 	dma_mem_t		mem_desc;
1794 	mbx_cmd_t		mc = {0};
1795 	mbx_cmd_t		*mcp = &mc;
1796 	port_database_23_t	*pd23;
1797 
1798 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1799 
1800 	pd23 = (port_database_23_t *)kmem_zalloc(PORT_DATABASE_SIZE, KM_SLEEP);
1801 	if (pd23 == NULL) {
1802 		rval = QL_MEMORY_ALLOC_FAILED;
1803 		EL(ha, "failed, rval = %xh\n", rval);
1804 		return (rval);
1805 	}
1806 
1807 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
1808 	    PORT_DATABASE_SIZE)) != QL_SUCCESS) {
1809 		return (QL_MEMORY_ALLOC_FAILED);
1810 	}
1811 
1812 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1813 		mcp->mb[0] = MBC_GET_PORT_DATABASE;
1814 		mcp->mb[1] = tq->loop_id;
1815 		mcp->mb[4] = CHAR_TO_SHORT(tq->d_id.b.al_pa, tq->d_id.b.area);
1816 		mcp->mb[5] = (uint16_t)tq->d_id.b.domain;
1817 		mcp->mb[9] = ha->vp_index;
1818 		mcp->mb[10] = (uint16_t)(opt | PDF_ADISC);
1819 		mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|
1820 		    MBX_2|MBX_1|MBX_0;
1821 	} else {
1822 		mcp->mb[0] = (uint16_t)(opt == PDF_NONE ?
1823 		    MBC_GET_PORT_DATABASE : MBC_ENHANCED_GET_PORT_DATABASE);
1824 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1825 			mcp->mb[1] = tq->loop_id;
1826 			mcp->mb[10] = opt;
1827 			mcp->out_mb = MBX_10|MBX_7|MBX_6|MBX_3|
1828 			    MBX_2|MBX_1|MBX_0;
1829 		} else {
1830 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | opt);
1831 			mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1832 		}
1833 	}
1834 
1835 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
1836 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
1837 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
1838 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
1839 	mcp->in_mb = MBX_0;
1840 	mcp->timeout = MAILBOX_TOV;
1841 	rval = ql_mailbox_command(ha, mcp);
1842 
1843 	if (rval == QL_SUCCESS) {
1844 		ql_get_mbox_dma_data(&mem_desc, (caddr_t)pd23);
1845 	}
1846 
1847 	ql_free_dma_resource(ha, &mem_desc);
1848 
1849 	if (rval == QL_SUCCESS) {
1850 		if (CFG_IST(ha, CFG_CTRL_242581)) {
1851 			port_database_24_t *pd24 = (port_database_24_t *)pd23;
1852 
1853 			tq->master_state = pd24->current_login_state;
1854 			tq->slave_state = pd24->last_stable_login_state;
1855 			if (PD_PORT_LOGIN(tq)) {
1856 				/* Names are big endian. */
1857 				bcopy((void *)&pd24->port_name[0],
1858 				    (void *)&tq->port_name[0], 8);
1859 				bcopy((void *)&pd24->node_name[0],
1860 				    (void *)&tq->node_name[0], 8);
1861 				tq->hard_addr.b.al_pa = pd24->hard_address[2];
1862 				tq->hard_addr.b.area = pd24->hard_address[1];
1863 				tq->hard_addr.b.domain = pd24->hard_address[0];
1864 				tq->class3_rcv_data_size =
1865 				    pd24->receive_data_size;
1866 				LITTLE_ENDIAN_16(&tq->class3_rcv_data_size);
1867 				tq->prli_svc_param_word_0 =
1868 				    pd24->PRLI_service_parameter_word_0;
1869 				LITTLE_ENDIAN_16(&tq->prli_svc_param_word_0);
1870 				tq->prli_svc_param_word_3 =
1871 				    pd24->PRLI_service_parameter_word_3;
1872 				LITTLE_ENDIAN_16(&tq->prli_svc_param_word_3);
1873 			}
1874 		} else {
1875 			tq->master_state = pd23->master_state;
1876 			tq->slave_state = pd23->slave_state;
1877 			if (PD_PORT_LOGIN(tq)) {
1878 				/* Names are big endian. */
1879 				bcopy((void *)&pd23->port_name[0],
1880 				    (void *)&tq->port_name[0], 8);
1881 				bcopy((void *)&pd23->node_name[0],
1882 				    (void *)&tq->node_name[0], 8);
1883 				tq->hard_addr.b.al_pa = pd23->hard_address[2];
1884 				tq->hard_addr.b.area = pd23->hard_address[1];
1885 				tq->hard_addr.b.domain = pd23->hard_address[0];
1886 				tq->cmn_features = pd23->common_features;
1887 				LITTLE_ENDIAN_16(&tq->cmn_features);
1888 				tq->conc_sequences =
1889 				    pd23->total_concurrent_sequences;
1890 				LITTLE_ENDIAN_16(&tq->conc_sequences);
1891 				tq->relative_offset =
1892 				    pd23->RO_by_information_category;
1893 				LITTLE_ENDIAN_16(&tq->relative_offset);
1894 				tq->class3_recipient_ctl = pd23->recipient;
1895 				LITTLE_ENDIAN_16(&tq->class3_recipient_ctl);
1896 				tq->class3_rcv_data_size =
1897 				    pd23->receive_data_size;
1898 				LITTLE_ENDIAN_16(&tq->class3_rcv_data_size);
1899 				tq->class3_conc_sequences =
1900 				    pd23->concurrent_sequences;
1901 				LITTLE_ENDIAN_16(&tq->class3_conc_sequences);
1902 				tq->class3_open_sequences_per_exch =
1903 				    pd23->open_sequences_per_exchange;
1904 				LITTLE_ENDIAN_16(
1905 				    &tq->class3_open_sequences_per_exch);
1906 				tq->prli_payload_length =
1907 				    pd23->PRLI_payload_length;
1908 				LITTLE_ENDIAN_16(&tq->prli_payload_length);
1909 				tq->prli_svc_param_word_0 =
1910 				    pd23->PRLI_service_parameter_word_0;
1911 				LITTLE_ENDIAN_16(&tq->prli_svc_param_word_0);
1912 				tq->prli_svc_param_word_3 =
1913 				    pd23->PRLI_service_parameter_word_3;
1914 				LITTLE_ENDIAN_16(&tq->prli_svc_param_word_3);
1915 			}
1916 		}
1917 
1918 		if (!PD_PORT_LOGIN(tq)) {
1919 			EL(ha, "d_id=%xh, loop_id=%xh, not logged in "
1920 			    "master=%xh, slave=%xh\n", tq->d_id.b24,
1921 			    tq->loop_id, tq->master_state, tq->slave_state);
1922 			rval = QL_NOT_LOGGED_IN;
1923 		} else {
1924 			tq->flags = tq->prli_svc_param_word_3 &
1925 			    PRLI_W3_TARGET_FUNCTION ?
1926 			    tq->flags & ~TQF_INITIATOR_DEVICE :
1927 			    tq->flags | TQF_INITIATOR_DEVICE;
1928 
1929 			if ((tq->flags & TQF_INITIATOR_DEVICE) == 0) {
1930 				tq->flags = tq->prli_svc_param_word_3 &
1931 				    PRLI_W3_RETRY ?
1932 				    tq->flags | TQF_TAPE_DEVICE :
1933 				    tq->flags & ~TQF_TAPE_DEVICE;
1934 			} else {
1935 				tq->flags &= ~TQF_TAPE_DEVICE;
1936 			}
1937 		}
1938 	}
1939 
1940 	kmem_free(pd23, PORT_DATABASE_SIZE);
1941 
1942 	if ((rval != QL_SUCCESS) && (rval != QL_PARAMETER_ERROR)) {
1943 		EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", tq->d_id.b24,
1944 		    tq->loop_id, rval);
1945 	} else {
1946 		/*EMPTY*/
1947 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1948 	}
1949 
1950 	return (rval);
1951 }
1952 
1953 /*
1954  * ql_get_loop_position_map
1955  *	Issue get loop position map mailbox command.
1956  *
1957  * Input:
1958  *	ha:	adapter state pointer.
1959  *	size:	size of data buffer.
1960  *	bufp:	data pointer for DMA data.
1961  *
1962  * Returns:
1963  *	ql local function return status code.
1964  *
1965  * Context:
1966  *	Kernel context.
1967  */
1968 int
1969 ql_get_loop_position_map(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
1970 {
1971 	int		rval;
1972 	dma_mem_t	mem_desc;
1973 	mbx_cmd_t	mc = {0};
1974 	mbx_cmd_t	*mcp = &mc;
1975 
1976 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1977 
1978 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
1979 	    (uint32_t)size)) != QL_SUCCESS) {
1980 		EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
1981 		return (QL_MEMORY_ALLOC_FAILED);
1982 	}
1983 
1984 	mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP;
1985 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
1986 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
1987 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
1988 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
1989 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
1990 	mcp->in_mb = MBX_1|MBX_0;
1991 	mcp->timeout = MAILBOX_TOV;
1992 	rval = ql_mailbox_command(ha, mcp);
1993 
1994 	if (rval == QL_SUCCESS) {
1995 		ql_get_mbox_dma_data(&mem_desc, bufp);
1996 	}
1997 
1998 	ql_free_dma_resource(ha, &mem_desc);
1999 
2000 	if (rval != QL_SUCCESS) {
2001 		EL(ha, "failed=%xh\n", rval);
2002 	} else {
2003 		/*EMPTY*/
2004 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2005 	}
2006 
2007 	return (rval);
2008 }
2009 
2010 /*
2011  * ql_set_rnid_params
2012  *	Issue set RNID parameters mailbox command.
2013  *
2014  * Input:
2015  *	ha:		adapter state pointer.
2016  *	size:		size of data buffer.
2017  *	bufp:		data pointer for DMA data.
2018  *
2019  * Returns:
2020  *	ql local function return status code.
2021  *
2022  * Context:
2023  *	Kernel context.
2024  */
2025 int
2026 ql_set_rnid_params(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
2027 {
2028 	int		rval;
2029 	dma_mem_t	mem_desc;
2030 	mbx_cmd_t	mc = {0};
2031 	mbx_cmd_t	*mcp = &mc;
2032 
2033 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2034 
2035 	if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bufp,
2036 	    (uint32_t)size)) != QL_SUCCESS) {
2037 		EL(ha, "failed, setup_mbox_dma_transfer: %x\n", rval);
2038 		return (rval);
2039 	}
2040 
2041 	mcp->mb[0] = MBC_SET_PARAMETERS;
2042 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2043 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2044 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2045 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2046 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2047 	mcp->in_mb = MBX_0;
2048 	mcp->timeout = MAILBOX_TOV;
2049 	rval = ql_mailbox_command(ha, mcp);
2050 
2051 	ql_free_dma_resource(ha, &mem_desc);
2052 
2053 	if (rval != QL_SUCCESS) {
2054 		EL(ha, "failed, rval = %xh\n", rval);
2055 	} else {
2056 		/*EMPTY*/
2057 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2058 	}
2059 
2060 	return (rval);
2061 }
2062 
2063 /*
2064  * ql_send_rnid_els
2065  *	Issue a send node identfication data mailbox command.
2066  *
2067  * Input:
2068  *	ha:		adapter state pointer.
2069  *	loop_id:	FC loop id.
2070  *	opt:		options.
2071  *	size:		size of data buffer.
2072  *	bufp:		data pointer for DMA data.
2073  *
2074  * Returns:
2075  *	ql local function return status code.
2076  *
2077  * Context:
2078  *	Kernel context.
2079  */
2080 int
2081 ql_send_rnid_els(ql_adapter_state_t *ha, uint16_t loop_id, uint8_t opt,
2082     size_t size, caddr_t bufp)
2083 {
2084 	int		rval;
2085 	dma_mem_t	mem_desc;
2086 	mbx_cmd_t	mc = {0};
2087 	mbx_cmd_t	*mcp = &mc;
2088 
2089 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2090 
2091 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2092 	    (uint32_t)size)) != QL_SUCCESS) {
2093 		return (QL_MEMORY_ALLOC_FAILED);
2094 	}
2095 
2096 	mcp->mb[0] = MBC_SEND_RNID_ELS;
2097 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2098 		mcp->mb[1] = loop_id;
2099 		mcp->mb[9] = ha->vp_index;
2100 		mcp->mb[10] = opt;
2101 		mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2102 	} else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2103 		mcp->mb[1] = loop_id;
2104 		mcp->mb[10] = opt;
2105 		mcp->out_mb = MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2106 	} else {
2107 		mcp->mb[1] = (uint16_t)(loop_id << 8 | opt);
2108 		mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2109 	}
2110 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2111 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2112 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2113 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2114 	mcp->in_mb = MBX_0;
2115 	mcp->timeout = MAILBOX_TOV;
2116 	rval = ql_mailbox_command(ha, mcp);
2117 
2118 	if (rval == QL_SUCCESS) {
2119 		ql_get_mbox_dma_data(&mem_desc, bufp);
2120 	}
2121 
2122 	ql_free_dma_resource(ha, &mem_desc);
2123 
2124 	if (rval != QL_SUCCESS) {
2125 		EL(ha, "failed, rval = %xh\n", rval);
2126 	} else {
2127 		/*EMPTY*/
2128 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2129 	}
2130 
2131 	return (rval);
2132 }
2133 
2134 /*
2135  * ql_get_rnid_params
2136  *	Issue get RNID parameters mailbox command.
2137  *
2138  * Input:
2139  *	ha:	adapter state pointer.
2140  *	size:	size of data buffer.
2141  *	bufp:	data pointer for DMA data.
2142  *
2143  * Returns:
2144  *	ql local function return status code.
2145  *
2146  * Context:
2147  *	Kernel context.
2148  */
2149 int
2150 ql_get_rnid_params(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
2151 {
2152 	int		rval;
2153 	dma_mem_t	mem_desc;
2154 	mbx_cmd_t	mc = {0};
2155 	mbx_cmd_t	*mcp = &mc;
2156 
2157 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2158 
2159 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2160 	    (uint32_t)size)) != QL_SUCCESS) {
2161 		return (QL_MEMORY_ALLOC_FAILED);
2162 	}
2163 
2164 	mcp->mb[0] = MBC_GET_PARAMETERS;
2165 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2166 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2167 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2168 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2169 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2170 	mcp->in_mb = MBX_0;
2171 	mcp->timeout = MAILBOX_TOV;
2172 	rval = ql_mailbox_command(ha, mcp);
2173 
2174 	if (rval == QL_SUCCESS) {
2175 		ql_get_mbox_dma_data(&mem_desc, bufp);
2176 	}
2177 
2178 	ql_free_dma_resource(ha, &mem_desc);
2179 
2180 	if (rval != QL_SUCCESS) {
2181 		EL(ha, "failed=%xh\n", rval);
2182 	} else {
2183 		/*EMPTY*/
2184 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2185 	}
2186 
2187 	return (rval);
2188 }
2189 
2190 /*
2191  * ql_get_link_status
2192  *	Issue get link status mailbox command.
2193  *
2194  * Input:
2195  *	ha:		adapter state pointer.
2196  *	loop_id:	FC loop id or n_port_hdl.
2197  *	size:		size of data buffer.
2198  *	bufp:		data pointer for DMA data.
2199  *	port_no:	port number to query.
2200  *
2201  * Returns:
2202  *	ql local function return status code.
2203  *
2204  * Context:
2205  *	Kernel context.
2206  */
2207 int
2208 ql_get_link_status(ql_adapter_state_t *ha, uint16_t loop_id, size_t size,
2209     caddr_t bufp, uint8_t port_no)
2210 {
2211 	dma_mem_t	mem_desc;
2212 	mbx_cmd_t	mc = {0};
2213 	mbx_cmd_t	*mcp = &mc;
2214 	int		rval = QL_SUCCESS;
2215 	int		retry = 0;
2216 
2217 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2218 
2219 	do {
2220 		if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2221 		    (uint32_t)size)) != QL_SUCCESS) {
2222 			EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
2223 			return (QL_MEMORY_ALLOC_FAILED);
2224 		}
2225 
2226 		mcp->mb[0] = MBC_GET_LINK_STATUS;
2227 		if (CFG_IST(ha, CFG_CTRL_242581)) {
2228 			if (loop_id == ha->loop_id) {
2229 				mcp->mb[0] = MBC_GET_STATUS_COUNTS;
2230 				mcp->mb[8] = (uint16_t)(size >> 2);
2231 				mcp->out_mb = MBX_10|MBX_8;
2232 			} else {
2233 				mcp->mb[1] = loop_id;
2234 				mcp->mb[4] = port_no;
2235 				mcp->mb[10] = (uint16_t)(retry ? BIT_3 : 0);
2236 				mcp->out_mb = MBX_10|MBX_4;
2237 			}
2238 		} else {
2239 			if (retry) {
2240 				port_no = (uint8_t)(port_no | BIT_3);
2241 			}
2242 			if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2243 				mcp->mb[1] = loop_id;
2244 				mcp->mb[10] = port_no;
2245 				mcp->out_mb = MBX_10;
2246 			} else {
2247 				mcp->mb[1] = (uint16_t)((loop_id << 8) |
2248 				    port_no);
2249 				mcp->out_mb = 0;
2250 			}
2251 		}
2252 		mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2253 		mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2254 		mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2255 		mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2256 		mcp->in_mb = MBX_1|MBX_0;
2257 		mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2258 		mcp->timeout = MAILBOX_TOV;
2259 
2260 		rval = ql_mailbox_command(ha, mcp);
2261 
2262 		if (rval == QL_SUCCESS) {
2263 			ql_get_mbox_dma_data(&mem_desc, bufp);
2264 		}
2265 
2266 		ql_free_dma_resource(ha, &mem_desc);
2267 
2268 		if (rval != QL_SUCCESS) {
2269 			EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
2270 		}
2271 
2272 		/*
2273 		 * Some of the devices want d_id in the payload,
2274 		 * strictly as per standard. Let's retry.
2275 		 */
2276 
2277 	} while (rval == QL_COMMAND_ERROR && !retry++);
2278 
2279 	if (rval != QL_SUCCESS) {
2280 		EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
2281 	} else {
2282 		/*EMPTY*/
2283 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2284 	}
2285 
2286 	return (rval);
2287 }
2288 
2289 /*
2290  * ql_get_status_counts
2291  *	Issue get adapter link status counts mailbox command.
2292  *
2293  * Input:
2294  *	ha:		adapter state pointer.
2295  *	loop_id:	FC loop id or n_port_hdl.
2296  *	size:		size of data buffer.
2297  *	bufp:		data pointer for DMA data.
2298  *	port_no:	port number to query.
2299  *
2300  * Returns:
2301  *	ql local function return status code.
2302  *
2303  * Context:
2304  *	Kernel context.
2305  */
2306 int
2307 ql_get_status_counts(ql_adapter_state_t *ha, uint16_t loop_id, size_t size,
2308     caddr_t bufp, uint8_t port_no)
2309 {
2310 	dma_mem_t	mem_desc;
2311 	mbx_cmd_t	mc = {0};
2312 	mbx_cmd_t	*mcp = &mc;
2313 	int		rval = QL_SUCCESS;
2314 
2315 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2316 
2317 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2318 	    (uint32_t)size)) != QL_SUCCESS) {
2319 		EL(ha, "setup_mbox_dma_resources failed: %x\n", rval);
2320 		return (QL_MEMORY_ALLOC_FAILED);
2321 	}
2322 
2323 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2324 		mcp->mb[0] = MBC_GET_STATUS_COUNTS;
2325 		mcp->mb[8] = (uint16_t)(size / 4);
2326 		mcp->out_mb = MBX_10|MBX_8;
2327 	} else {
2328 		mcp->mb[0] = MBC_GET_LINK_STATUS;
2329 
2330 		/* allows reporting when link is down */
2331 		if (CFG_IST(ha, CFG_CTRL_2200) == 0) {
2332 			port_no = (uint8_t)(port_no | BIT_6);
2333 		}
2334 
2335 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2336 			mcp->mb[1] = loop_id;
2337 			mcp->mb[10] = port_no;
2338 			mcp->out_mb = MBX_10|MBX_1;
2339 		} else {
2340 			mcp->mb[1] = (uint16_t)((loop_id << 8) |
2341 			    port_no);
2342 			mcp->out_mb = MBX_1;
2343 		}
2344 	}
2345 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2346 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2347 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2348 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2349 	mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2350 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
2351 	mcp->timeout = MAILBOX_TOV;
2352 	rval = ql_mailbox_command(ha, mcp);
2353 
2354 	if (rval == QL_SUCCESS) {
2355 		ql_get_mbox_dma_data(&mem_desc, bufp);
2356 	}
2357 
2358 	ql_free_dma_resource(ha, &mem_desc);
2359 
2360 	if (rval != QL_SUCCESS) {
2361 		EL(ha, "failed=%xh, mbx1=%xh, mbx2=%xh\n", rval,
2362 		    mcp->mb[1], mcp->mb[2]);
2363 	} else {
2364 		/*EMPTY*/
2365 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2366 	}
2367 
2368 	return (rval);
2369 }
2370 
2371 /*
2372  * ql_reset_link_status
2373  *	Issue Reset Link Error Status mailbox command
2374  *
2375  * Input:
2376  *	ha:	adapter state pointer.
2377  *
2378  * Returns:
2379  *	ql local function return status code.
2380  *
2381  * Context:
2382  *	Kernel context.
2383  */
2384 int
2385 ql_reset_link_status(ql_adapter_state_t *ha)
2386 {
2387 	int		rval;
2388 	mbx_cmd_t	mc = {0};
2389 	mbx_cmd_t	*mcp = &mc;
2390 
2391 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2392 
2393 	mcp->mb[0] = MBC_RESET_LINK_STATUS;
2394 	mcp->out_mb = MBX_0;
2395 	mcp->in_mb = MBX_0;
2396 	mcp->timeout = MAILBOX_TOV;
2397 	rval = ql_mailbox_command(ha, mcp);
2398 
2399 	if (rval != QL_SUCCESS) {
2400 		EL(ha, "failed=%xh\n", rval);
2401 	} else {
2402 		/*EMPTY*/
2403 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2404 	}
2405 
2406 	return (rval);
2407 }
2408 
2409 /*
2410  * ql_loop_reset
2411  *	Issue loop reset.
2412  *
2413  * Input:
2414  *	ha:	adapter state pointer.
2415  *
2416  * Returns:
2417  *	ql local function return status code.
2418  *
2419  * Context:
2420  *	Kernel context.
2421  */
2422 int
2423 ql_loop_reset(ql_adapter_state_t *ha)
2424 {
2425 	int	rval;
2426 
2427 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2428 
2429 	if (CFG_IST(ha, CFG_ENABLE_LIP_RESET)) {
2430 		rval = ql_lip_reset(ha, 0xff);
2431 	} else if (CFG_IST(ha, CFG_ENABLE_FULL_LIP_LOGIN)) {
2432 		rval = ql_full_login_lip(ha);
2433 	} else if (CFG_IST(ha, CFG_ENABLE_TARGET_RESET)) {
2434 		rval = ql_target_reset(ha, NULL, ha->loop_reset_delay);
2435 	} else {
2436 		rval = ql_initiate_lip(ha);
2437 	}
2438 
2439 	if (rval != QL_SUCCESS) {
2440 		EL(ha, "failed, rval = %xh\n", rval);
2441 	} else {
2442 		/*EMPTY*/
2443 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2444 	}
2445 
2446 	return (rval);
2447 }
2448 
2449 /*
2450  * ql_initiate_lip
2451  *	Initiate LIP mailbox command.
2452  *
2453  * Input:
2454  *	ha:	adapter state pointer.
2455  *
2456  * Returns:
2457  *	ql local function return status code.
2458  *
2459  * Context:
2460  *	Kernel context.
2461  */
2462 int
2463 ql_initiate_lip(ql_adapter_state_t *ha)
2464 {
2465 	int		rval;
2466 	mbx_cmd_t	mc = {0};
2467 	mbx_cmd_t	*mcp = &mc;
2468 
2469 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2470 
2471 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2472 		mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2473 		mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_81XX) ?
2474 		    BIT_1 : BIT_4);
2475 		mcp->mb[3] = ha->loop_reset_delay;
2476 		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2477 	} else {
2478 		mcp->mb[0] = MBC_INITIATE_LIP;
2479 		mcp->out_mb = MBX_0;
2480 	}
2481 	mcp->in_mb = MBX_0;
2482 	mcp->timeout = MAILBOX_TOV;
2483 	rval = ql_mailbox_command(ha, mcp);
2484 
2485 	if (rval != QL_SUCCESS) {
2486 		EL(ha, "failed, rval = %xh\n", rval);
2487 	} else {
2488 		/*EMPTY*/
2489 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2490 	}
2491 
2492 	return (rval);
2493 }
2494 
2495 /*
2496  * ql_full_login_lip
2497  *	Issue full login LIP mailbox command.
2498  *
2499  * Input:
2500  *	ha:	adapter state pointer.
2501  *
2502  * Returns:
2503  *	ql local function return status code.
2504  *
2505  * Context:
2506  *	Kernel context.
2507  */
2508 int
2509 ql_full_login_lip(ql_adapter_state_t *ha)
2510 {
2511 	int		rval;
2512 	mbx_cmd_t	mc = {0};
2513 	mbx_cmd_t	*mcp = &mc;
2514 
2515 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2516 
2517 	mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2518 	if (CFG_IST(ha, CFG_CTRL_2425)) {
2519 		mcp->mb[1] = BIT_3;
2520 	} else if (CFG_IST(ha, CFG_CTRL_81XX)) {
2521 		mcp->mb[1] = BIT_1;
2522 	}
2523 	mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2524 	mcp->in_mb = MBX_0;
2525 	mcp->timeout = MAILBOX_TOV;
2526 	rval = ql_mailbox_command(ha, mcp);
2527 
2528 	if (rval != QL_SUCCESS) {
2529 		EL(ha, "failed, rval = %xh\n", rval);
2530 	} else {
2531 		/*EMPTY*/
2532 		QL_PRINT_3(CE_CONT, "(%d): done", ha->instance);
2533 	}
2534 
2535 	return (rval);
2536 }
2537 
2538 /*
2539  * ql_lip_reset
2540  *	Issue lip reset to a port.
2541  *
2542  * Input:
2543  *	ha:		adapter state pointer.
2544  *	loop_id:	FC loop id.
2545  *
2546  * Returns:
2547  *	ql local function return status code.
2548  *
2549  * Context:
2550  *	Kernel context.
2551  */
2552 int
2553 ql_lip_reset(ql_adapter_state_t *ha, uint16_t loop_id)
2554 {
2555 	int		rval;
2556 	mbx_cmd_t	mc = {0};
2557 	mbx_cmd_t	*mcp = &mc;
2558 
2559 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2560 
2561 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2562 		mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2563 		mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_81XX) ?
2564 		    BIT_1 : BIT_6);
2565 		mcp->mb[3] = ha->loop_reset_delay;
2566 		mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2567 	} else {
2568 		mcp->mb[0] = MBC_LIP_RESET;
2569 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2570 			mcp->mb[1] = loop_id;
2571 			mcp->out_mb = MBX_10|MBX_3|MBX_2|MBX_1|MBX_0;
2572 		} else {
2573 			mcp->mb[1] = (uint16_t)(loop_id << 8);
2574 			mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2575 		}
2576 		mcp->mb[2] = ha->loop_reset_delay;
2577 	}
2578 	mcp->in_mb = MBX_0;
2579 	mcp->timeout = MAILBOX_TOV;
2580 	rval = ql_mailbox_command(ha, mcp);
2581 
2582 	if (rval != QL_SUCCESS) {
2583 		EL(ha, "failed, rval = %xh\n", rval);
2584 	} else {
2585 		/*EMPTY*/
2586 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2587 	}
2588 
2589 	return (rval);
2590 }
2591 
2592 /*
2593  * ql_abort_command
2594  *	Abort command aborts a specified IOCB.
2595  *
2596  * Input:
2597  *	ha:	adapter state pointer.
2598  *	sp:	SRB structure pointer.
2599  *
2600  * Returns:
2601  *	ql local function return status code.
2602  *
2603  * Context:
2604  *	Kernel context.
2605  */
2606 int
2607 ql_abort_command(ql_adapter_state_t *ha, ql_srb_t *sp)
2608 {
2609 	int		rval;
2610 	mbx_cmd_t	mc = {0};
2611 	mbx_cmd_t	*mcp = &mc;
2612 	ql_tgt_t	*tq = sp->lun_queue->target_queue;
2613 
2614 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2615 
2616 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2617 		rval = ql_abort_cmd_iocb(ha, sp);
2618 	} else {
2619 		mcp->mb[0] = MBC_ABORT_COMMAND_IOCB;
2620 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2621 			mcp->mb[1] = tq->loop_id;
2622 		} else {
2623 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
2624 		}
2625 		mcp->mb[2] = LSW(sp->handle);
2626 		mcp->mb[3] = MSW(sp->handle);
2627 		mcp->mb[6] = (uint16_t)(sp->flags & SRB_FCP_CMD_PKT ?
2628 		    sp->lun_queue->lun_no : 0);
2629 		mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2630 		mcp->in_mb = MBX_0;
2631 		mcp->timeout = MAILBOX_TOV;
2632 		rval = ql_mailbox_command(ha, mcp);
2633 	}
2634 
2635 	if (rval != QL_SUCCESS) {
2636 		EL(ha, "failed=%xh, d_id=%xh, handle=%xh\n", rval,
2637 		    tq->d_id.b24, sp->handle);
2638 	} else {
2639 		/*EMPTY*/
2640 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2641 	}
2642 
2643 	return (rval);
2644 }
2645 
2646 /*
2647  * ql_abort_cmd_iocb
2648  *	Function issues abort command IOCB.
2649  *
2650  * Input:
2651  *	ha:	adapter state pointer.
2652  *	sp:	SRB structure pointer.
2653  *
2654  * Returns:
2655  *	ql local function return status code.
2656  *
2657  * Context:
2658  *	Interrupt or Kernel context, no mailbox commands allowed.
2659  */
2660 static int
2661 ql_abort_cmd_iocb(ql_adapter_state_t *ha, ql_srb_t *sp)
2662 {
2663 	ql_mbx_iocb_t	*pkt;
2664 	int		rval;
2665 	uint32_t	pkt_size;
2666 	uint16_t	comp_status;
2667 	ql_tgt_t	*tq = sp->lun_queue->target_queue;
2668 
2669 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2670 
2671 	pkt_size = sizeof (ql_mbx_iocb_t);
2672 	if ((pkt = kmem_zalloc(pkt_size, KM_SLEEP)) == NULL) {
2673 		EL(ha, "failed, kmem_zalloc\n");
2674 		return (QL_MEMORY_ALLOC_FAILED);
2675 	}
2676 
2677 	pkt->abo.entry_type = ABORT_CMD_TYPE;
2678 	pkt->abo.entry_count = 1;
2679 	pkt->abo.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
2680 	pkt->abo.options = AF_NO_ABTS;
2681 	pkt->abo.cmd_handle = LE_32(sp->handle);
2682 	pkt->abo.target_id[0] = tq->d_id.b.al_pa;
2683 	pkt->abo.target_id[1] = tq->d_id.b.area;
2684 	pkt->abo.target_id[2] = tq->d_id.b.domain;
2685 	pkt->abo.vp_index = ha->vp_index;
2686 
2687 	rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
2688 
2689 	if (rval == QL_SUCCESS && (pkt->abo.entry_status  & 0x3c) != 0) {
2690 		EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
2691 		    pkt->abo.entry_status, tq->d_id.b24);
2692 		rval = QL_FUNCTION_PARAMETER_ERROR;
2693 	}
2694 
2695 	comp_status = (uint16_t)LE_16(pkt->abo.n_port_hdl);
2696 	if (rval == QL_SUCCESS && comp_status != CS_COMPLETE) {
2697 		EL(ha, "failed, comp_status=%xh, d_id=%xh\n",
2698 		    comp_status, tq->d_id.b24);
2699 		rval = QL_FUNCTION_FAILED;
2700 	}
2701 
2702 	kmem_free(pkt, pkt_size);
2703 
2704 	if (rval != QL_SUCCESS) {
2705 		EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
2706 	} else {
2707 		/*EMPTY*/
2708 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2709 	}
2710 
2711 	return (rval);
2712 }
2713 
2714 /*
2715  * ql_verify_checksum
2716  *	Verify loaded RISC firmware.
2717  *
2718  * Input:
2719  *	ha = adapter state pointer.
2720  *
2721  * Returns:
2722  *	ql local function return status code.
2723  *
2724  * Context:
2725  *	Kernel context.
2726  */
2727 int
2728 ql_verify_checksum(ql_adapter_state_t *ha)
2729 {
2730 	int		rval;
2731 	mbx_cmd_t	mc = {0};
2732 	mbx_cmd_t	*mcp = &mc;
2733 
2734 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2735 
2736 	mcp->mb[0] = MBC_VERIFY_CHECKSUM;
2737 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2738 		mcp->mb[1] = MSW(ha->risc_fw[0].addr);
2739 		mcp->mb[2] = LSW(ha->risc_fw[0].addr);
2740 	} else {
2741 		mcp->mb[1] = LSW(ha->risc_fw[0].addr);
2742 	}
2743 	mcp->out_mb = MBX_2|MBX_1|MBX_0;
2744 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
2745 	mcp->timeout = MAILBOX_TOV;
2746 	rval = ql_mailbox_command(ha, mcp);
2747 
2748 	if (rval != QL_SUCCESS) {
2749 		EL(ha, "failed, rval = %xh\n", rval);
2750 	} else {
2751 		/*EMPTY*/
2752 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2753 	}
2754 
2755 	return (rval);
2756 }
2757 
2758 /*
2759  * ql_get_id_list
2760  *	Get d_id and loop ID list.
2761  *
2762  * Input:
2763  *	ha:	adapter state pointer.
2764  *	bp:	data pointer for DMA data.
2765  *	size:	size of data buffer.
2766  *	mr:	pointer for mailbox data.
2767  *
2768  * Returns:
2769  *	ql local function return status code.
2770  *
2771  * Context:
2772  *	Kernel context.
2773  */
2774 int
2775 ql_get_id_list(ql_adapter_state_t *ha, caddr_t bp, uint32_t size,
2776     ql_mbx_data_t *mr)
2777 {
2778 	int		rval;
2779 	dma_mem_t	mem_desc;
2780 	mbx_cmd_t	mc = {0};
2781 	mbx_cmd_t	*mcp = &mc;
2782 
2783 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2784 
2785 	if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2786 	    (uint32_t)size)) != QL_SUCCESS) {
2787 		EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
2788 		return (QL_MEMORY_ALLOC_FAILED);
2789 	}
2790 
2791 	mcp->mb[0] = MBC_GET_ID_LIST;
2792 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2793 		mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2794 		mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2795 		mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2796 		mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2797 		mcp->mb[8] = (uint16_t)size;
2798 		mcp->mb[9] = ha->vp_index;
2799 		mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2800 	} else {
2801 		mcp->mb[1] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2802 		mcp->mb[2] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2803 		mcp->mb[3] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2804 		mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2805 		mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2806 	}
2807 	mcp->in_mb = MBX_1|MBX_0;
2808 	mcp->timeout = MAILBOX_TOV;
2809 	rval = ql_mailbox_command(ha, mcp);
2810 
2811 	if (rval == QL_SUCCESS) {
2812 		ql_get_mbox_dma_data(&mem_desc, bp);
2813 	}
2814 
2815 	ql_free_dma_resource(ha, &mem_desc);
2816 
2817 	/* Return mailbox data. */
2818 	if (mr != NULL) {
2819 		mr->mb[0] = mcp->mb[0];
2820 		mr->mb[1] = mcp->mb[1];
2821 	}
2822 
2823 	if (rval != QL_SUCCESS) {
2824 		EL(ha, "failed, rval = %xh\n", rval);
2825 	} else {
2826 		/*EMPTY*/
2827 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2828 	}
2829 
2830 	return (rval);
2831 }
2832 
2833 /*
2834  * ql_wrt_risc_ram
2835  *	Load RISC RAM.
2836  *
2837  * Input:
2838  *	ha:		adapter state pointer.
2839  *	risc_address:	risc ram word address.
2840  *	bp:		DMA pointer.
2841  *	word_count:	16/32bit word count.
2842  *
2843  * Returns:
2844  *	ql local function return status code.
2845  *
2846  * Context:
2847  *	Kernel context.
2848  */
2849 int
2850 ql_wrt_risc_ram(ql_adapter_state_t *ha, uint32_t risc_address, uint64_t bp,
2851     uint32_t word_count)
2852 {
2853 	int		rval;
2854 	mbx_cmd_t	mc = {0};
2855 	mbx_cmd_t	*mcp = &mc;
2856 
2857 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2858 
2859 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2860 		mcp->mb[0] = MBC_LOAD_RAM_EXTENDED;
2861 		mcp->mb[4] = MSW(word_count);
2862 		mcp->mb[5] = LSW(word_count);
2863 		mcp->mb[6] = MSW(MSD(bp));
2864 		mcp->mb[7] = LSW(MSD(bp));
2865 		mcp->mb[8] = MSW(risc_address);
2866 		mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
2867 		    MBX_0;
2868 	} else {
2869 		mcp->mb[0] = MBC_LOAD_RAM;
2870 		mcp->mb[4] = LSW(word_count);
2871 		mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2872 	}
2873 	mcp->mb[1] = LSW(risc_address);
2874 	mcp->mb[2] = MSW(LSD(bp));
2875 	mcp->mb[3] = LSW(LSD(bp));
2876 	mcp->in_mb = MBX_0;
2877 	mcp->timeout = MAILBOX_TOV;
2878 
2879 	rval = ql_mailbox_command(ha, mcp);
2880 
2881 	if (rval != QL_SUCCESS) {
2882 		EL(ha, "failed, rval = %xh\n", rval);
2883 	} else {
2884 		/*EMPTY*/
2885 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2886 	}
2887 
2888 	return (rval);
2889 }
2890 
2891 /*
2892  * ql_rd_risc_ram
2893  *	Get RISC RAM.
2894  *
2895  * Input:
2896  *	ha:		adapter state pointer.
2897  *	risc_address:	risc ram word address.
2898  *	bp:		direct data pointer.
2899  *	word_count:	16/32bit word count.
2900  *
2901  * Returns:
2902  *	ql local function return status code.
2903  *
2904  * Context:
2905  *	Kernel context.
2906  */
2907 int
2908 ql_rd_risc_ram(ql_adapter_state_t *ha, uint32_t risc_address, uint64_t bp,
2909     uint32_t word_count)
2910 {
2911 	int		rval;
2912 	mbx_cmd_t	mc = {0};
2913 	mbx_cmd_t	*mcp = &mc;
2914 
2915 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2916 
2917 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2918 		mcp->mb[0] = MBC_DUMP_RAM_EXTENDED;
2919 		mcp->mb[1] = LSW(risc_address);
2920 		mcp->mb[2] = MSW(LSD(bp));
2921 		mcp->mb[3] = LSW(LSD(bp));
2922 		mcp->mb[4] = MSW(word_count);
2923 		mcp->mb[5] = LSW(word_count);
2924 		mcp->mb[6] = MSW(MSD(bp));
2925 		mcp->mb[7] = LSW(MSD(bp));
2926 		mcp->mb[8] = MSW(risc_address);
2927 		mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
2928 		    MBX_0;
2929 	} else {
2930 		mcp->mb[0] = MBC_DUMP_RAM;	/* doesn't support 64bit addr */
2931 		mcp->mb[1] = LSW(risc_address);
2932 		mcp->mb[2] = MSW(LSD(bp));
2933 		mcp->mb[3] = LSW(LSD(bp));
2934 		mcp->mb[4] = LSW(word_count);
2935 		mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2936 	}
2937 	mcp->in_mb = MBX_0;
2938 	mcp->timeout = MAILBOX_TOV;
2939 	rval = ql_mailbox_command(ha, mcp);
2940 
2941 	if (rval != QL_SUCCESS) {
2942 		EL(ha, "failed, rval = %xh\n", rval);
2943 	} else {
2944 		/*EMPTY*/
2945 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2946 	}
2947 
2948 	return (rval);
2949 }
2950 
2951 /*
2952  * ql_wrt_risc_ram_word
2953  *	Write RISC RAM word.
2954  *
2955  * Input:
2956  *	ha:		adapter state pointer.
2957  *	risc_address:	risc ram word address.
2958  *	data:		data.
2959  *
2960  * Returns:
2961  *	ql local function return status code.
2962  *
2963  * Context:
2964  *	Kernel context.
2965  */
2966 int
2967 ql_wrt_risc_ram_word(ql_adapter_state_t *ha, uint32_t risc_address,
2968     uint32_t data)
2969 {
2970 	int		rval;
2971 	mbx_cmd_t	mc = {0};
2972 	mbx_cmd_t	*mcp = &mc;
2973 
2974 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2975 
2976 	mcp->mb[0] = MBC_WRITE_RAM_EXTENDED;
2977 	mcp->mb[1] = LSW(risc_address);
2978 	mcp->mb[2] = LSW(data);
2979 	mcp->mb[3] = MSW(data);
2980 	mcp->mb[8] = MSW(risc_address);
2981 	mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0;
2982 	mcp->in_mb = MBX_0;
2983 	mcp->timeout = MAILBOX_TOV;
2984 
2985 	rval = ql_mailbox_command(ha, mcp);
2986 
2987 	if (rval != QL_SUCCESS) {
2988 		EL(ha, "failed, rval = %xh\n", rval);
2989 	} else {
2990 		/*EMPTY*/
2991 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2992 	}
2993 
2994 	return (rval);
2995 }
2996 
2997 /*
2998  * ql_rd_risc_ram_word
2999  *	Read RISC RAM word.
3000  *
3001  * Input:
3002  *	ha:		adapter state pointer.
3003  *	risc_address:	risc ram word address.
3004  *	data:		data pointer.
3005  *
3006  * Returns:
3007  *	ql local function return status code.
3008  *
3009  * Context:
3010  *	Kernel context.
3011  */
3012 int
3013 ql_rd_risc_ram_word(ql_adapter_state_t *ha, uint32_t risc_address,
3014     uint32_t *data)
3015 {
3016 	int		rval;
3017 	mbx_cmd_t	mc = {0};
3018 	mbx_cmd_t	*mcp = &mc;
3019 
3020 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3021 
3022 	mcp->mb[0] = MBC_READ_RAM_EXTENDED;
3023 	mcp->mb[1] = LSW(risc_address);
3024 	mcp->mb[8] = MSW(risc_address);
3025 	mcp->out_mb = MBX_8|MBX_1|MBX_0;
3026 	mcp->in_mb = MBX_3|MBX_2|MBX_0;
3027 	mcp->timeout = MAILBOX_TOV;
3028 
3029 	rval = ql_mailbox_command(ha, mcp);
3030 
3031 	if (rval != QL_SUCCESS) {
3032 		EL(ha, "failed, rval = %xh\n", rval);
3033 	} else {
3034 		*data = mcp->mb[2];
3035 		if (CFG_IST(ha, CFG_CTRL_242581)) {
3036 			*data |= mcp->mb[3] << 16;
3037 		}
3038 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3039 	}
3040 
3041 	return (rval);
3042 }
3043 
3044 /*
3045  * ql_issue_mbx_iocb
3046  *	Issue IOCB using mailbox command
3047  *
3048  * Input:
3049  *	ha:	adapter state pointer.
3050  *	bp:	buffer pointer.
3051  *	size:	buffer size.
3052  *
3053  * Returns:
3054  *	ql local function return status code.
3055  *
3056  * Context:
3057  *	Kernel context.
3058  */
3059 int
3060 ql_issue_mbx_iocb(ql_adapter_state_t *ha, caddr_t bp, uint32_t size)
3061 {
3062 	int		rval;
3063 	dma_mem_t	mem_desc;
3064 	mbx_cmd_t	mc = {0};
3065 	mbx_cmd_t	*mcp = &mc;
3066 
3067 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3068 
3069 	if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
3070 	    QL_SUCCESS) {
3071 		EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
3072 		return (rval);
3073 	}
3074 
3075 	mcp->mb[0] = MBC_EXECUTE_IOCB;
3076 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3077 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3078 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3079 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3080 	mcp->out_mb = MBX_7|