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