1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22c1fad183SDaniel Beauregard /* Copyright 2010 QLogic Corporation */
23fcf3ce44SJohn Forte 
24fcf3ce44SJohn Forte /*
25*f885d00fSDaniel Beauregard  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26fcf3ce44SJohn Forte  */
27fcf3ce44SJohn Forte 
28c1fad183SDaniel Beauregard #pragma ident	"Copyright 2010 QLogic Corporation; ql_mbx.c"
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /*
31fcf3ce44SJohn Forte  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
32fcf3ce44SJohn Forte  *
33fcf3ce44SJohn Forte  * ***********************************************************************
34fcf3ce44SJohn Forte  * *									**
35fcf3ce44SJohn Forte  * *				NOTICE					**
36c1fad183SDaniel Beauregard  * *		COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION		**
37fcf3ce44SJohn Forte  * *			ALL RIGHTS RESERVED				**
38fcf3ce44SJohn Forte  * *									**
39fcf3ce44SJohn Forte  * ***********************************************************************
40fcf3ce44SJohn Forte  *
41fcf3ce44SJohn Forte  */
42fcf3ce44SJohn Forte 
43fcf3ce44SJohn Forte #include <ql_apps.h>
44fcf3ce44SJohn Forte #include <ql_api.h>
45fcf3ce44SJohn Forte #include <ql_debug.h>
46fcf3ce44SJohn Forte #include <ql_iocb.h>
47fcf3ce44SJohn Forte #include <ql_isr.h>
48fcf3ce44SJohn Forte #include <ql_mbx.h>
49fcf3ce44SJohn Forte #include <ql_xioctl.h>
50fcf3ce44SJohn Forte 
51fcf3ce44SJohn Forte /*
52fcf3ce44SJohn Forte  * Local data
53fcf3ce44SJohn Forte  */
54fcf3ce44SJohn Forte 
55fcf3ce44SJohn Forte /*
56fcf3ce44SJohn Forte  * Local prototypes
57fcf3ce44SJohn Forte  */
58fcf3ce44SJohn Forte static int ql_mailbox_command(ql_adapter_state_t *, mbx_cmd_t *);
59fcf3ce44SJohn Forte static int ql_task_mgmt_iocb(ql_adapter_state_t *, ql_tgt_t *, uint16_t,
60fcf3ce44SJohn Forte     uint32_t, uint16_t);
61fcf3ce44SJohn Forte static int ql_abort_cmd_iocb(ql_adapter_state_t *, ql_srb_t *);
62fcf3ce44SJohn Forte static int ql_setup_mbox_dma_transfer(ql_adapter_state_t *, dma_mem_t *,
63fcf3ce44SJohn Forte     caddr_t, uint32_t);
64fcf3ce44SJohn Forte static int ql_setup_mbox_dma_resources(ql_adapter_state_t *, dma_mem_t *,
65fcf3ce44SJohn Forte     uint32_t);
66fcf3ce44SJohn Forte static void ql_setup_mbox_dma_data(dma_mem_t *, caddr_t);
67fcf3ce44SJohn Forte static void ql_get_mbox_dma_data(dma_mem_t *, caddr_t);
68fcf3ce44SJohn Forte 
69fcf3ce44SJohn Forte /*
70fcf3ce44SJohn Forte  * ql_mailbox_command
71fcf3ce44SJohn Forte  *	Issue mailbox command and waits for completion.
72fcf3ce44SJohn Forte  *
73fcf3ce44SJohn Forte  * Input:
74fcf3ce44SJohn Forte  *	ha = adapter state pointer.
75fcf3ce44SJohn Forte  *	mcp = mailbox command parameter structure pointer.
76fcf3ce44SJohn Forte  *
77fcf3ce44SJohn Forte  * Returns:
78fcf3ce44SJohn Forte  *	ql local function return status code.
79fcf3ce44SJohn Forte  *
80fcf3ce44SJohn Forte  * Context:
81fcf3ce44SJohn Forte  *	Kernel context.
82fcf3ce44SJohn Forte  */
83fcf3ce44SJohn Forte static int
ql_mailbox_command(ql_adapter_state_t * vha,mbx_cmd_t * mcp)84fcf3ce44SJohn Forte ql_mailbox_command(ql_adapter_state_t *vha, mbx_cmd_t *mcp)
85fcf3ce44SJohn Forte {
86fcf3ce44SJohn Forte 	uint16_t		cnt;
87fcf3ce44SJohn Forte 	uint32_t		data;
88fcf3ce44SJohn Forte 	clock_t			timer, cv_stat;
89fcf3ce44SJohn Forte 	int			rval;
90fcf3ce44SJohn Forte 	uint32_t		set_flags = 0;
91fcf3ce44SJohn Forte 	uint32_t		reset_flags = 0;
92fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = vha->pha;
9316dd44c2SDaniel Beauregard 	int			mbx_cmd = mcp->mb[0];
94fcf3ce44SJohn Forte 
95*f885d00fSDaniel Beauregard 	QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n", ha->instance, mbx_cmd);
96fcf3ce44SJohn Forte 
97fcf3ce44SJohn Forte 	/* Acquire mailbox register lock. */
98fcf3ce44SJohn Forte 	MBX_REGISTER_LOCK(ha);
99fcf3ce44SJohn Forte 
100fcf3ce44SJohn Forte 	/* Check for mailbox available, if not wait for signal. */
101eb82ff87SDaniel Beauregard 	while (ha->mailbox_flags & MBX_BUSY_FLG ||
102eb82ff87SDaniel Beauregard 	    (CFG_IST(ha, CFG_CTRL_8021) &&
103eb82ff87SDaniel Beauregard 	    RD32_IO_REG(ha, nx_host_int) & NX_MBX_CMD)) {
104fcf3ce44SJohn Forte 		ha->mailbox_flags = (uint8_t)
105fcf3ce44SJohn Forte 		    (ha->mailbox_flags | MBX_WANT_FLG);
106fcf3ce44SJohn Forte 
107fcf3ce44SJohn Forte 		if (ha->task_daemon_flags & TASK_DAEMON_POWERING_DOWN) {
108fcf3ce44SJohn Forte 			EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
109fcf3ce44SJohn Forte 			MBX_REGISTER_UNLOCK(ha);
110fcf3ce44SJohn Forte 			return (QL_LOCK_TIMEOUT);
111fcf3ce44SJohn Forte 		}
112fcf3ce44SJohn Forte 
113fcf3ce44SJohn Forte 		/* Set timeout after command that is running. */
114d3d50737SRafael Vanoni 		timer = (mcp->timeout + 20) * drv_usectohz(1000000);
115d3d50737SRafael Vanoni 		cv_stat = cv_reltimedwait_sig(&ha->cv_mbx_wait,
116d3d50737SRafael Vanoni 		    &ha->pha->mbx_mutex, timer, TR_CLOCK_TICK);
117fcf3ce44SJohn Forte 		if (cv_stat == -1 || cv_stat == 0) {
118fcf3ce44SJohn Forte 			/*
119fcf3ce44SJohn Forte 			 * The timeout time 'timer' was
120fcf3ce44SJohn Forte 			 * reached without the condition
121fcf3ce44SJohn Forte 			 * being signaled.
122fcf3ce44SJohn Forte 			 */
123fcf3ce44SJohn Forte 			ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
124fcf3ce44SJohn Forte 			    ~MBX_WANT_FLG);
125fcf3ce44SJohn Forte 			cv_broadcast(&ha->cv_mbx_wait);
126fcf3ce44SJohn Forte 
127fcf3ce44SJohn Forte 			/* Release mailbox register lock. */
128fcf3ce44SJohn Forte 			MBX_REGISTER_UNLOCK(ha);
129fcf3ce44SJohn Forte 
130fcf3ce44SJohn Forte 			if (cv_stat == 0) {
131fcf3ce44SJohn Forte 				EL(vha, "waiting for availability aborted, "
132fcf3ce44SJohn Forte 				    "cmd=%xh\n", mcp->mb[0]);
133fcf3ce44SJohn Forte 				return (QL_ABORTED);
134fcf3ce44SJohn Forte 			}
135fcf3ce44SJohn Forte 			EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
136fcf3ce44SJohn Forte 			return (QL_LOCK_TIMEOUT);
137fcf3ce44SJohn Forte 		}
138fcf3ce44SJohn Forte 	}
139fcf3ce44SJohn Forte 
140fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_BUSY_FLG);
141fcf3ce44SJohn Forte 
142fcf3ce44SJohn Forte 	/* Structure pointer for return mailbox registers. */
143fcf3ce44SJohn Forte 	ha->mcp = mcp;
144fcf3ce44SJohn Forte 
145fcf3ce44SJohn Forte 	/* Load mailbox registers. */
146fcf3ce44SJohn Forte 	data = mcp->out_mb;
147fcf3ce44SJohn Forte 	for (cnt = 0; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
148fcf3ce44SJohn Forte 		if (data & MBX_0) {
149eb82ff87SDaniel Beauregard 			WRT16_IO_REG(ha, mailbox_in[cnt], mcp->mb[cnt]);
150fcf3ce44SJohn Forte 		}
151fcf3ce44SJohn Forte 		data >>= 1;
152fcf3ce44SJohn Forte 	}
153fcf3ce44SJohn Forte 
154fcf3ce44SJohn Forte 	/* Issue set host interrupt command. */
155fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & ~MBX_INTERRUPT);
156eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_8021)) {
157eb82ff87SDaniel Beauregard 		WRT32_IO_REG(ha, nx_host_int, NX_MBX_CMD);
158eb82ff87SDaniel Beauregard 	} else if (CFG_IST(ha, CFG_CTRL_242581)) {
159eb82ff87SDaniel Beauregard 		WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
160eb82ff87SDaniel Beauregard 	} else {
161eb82ff87SDaniel Beauregard 		WRT16_IO_REG(ha, hccr, HC_SET_HOST_INT);
162eb82ff87SDaniel Beauregard 	}
163fcf3ce44SJohn Forte 
164fcf3ce44SJohn Forte 	/* Wait for command to complete. */
165fcf3ce44SJohn Forte 	if (ha->flags & INTERRUPTS_ENABLED &&
166fcf3ce44SJohn Forte 	    !(ha->task_daemon_flags & (TASK_THREAD_CALLED |
167fcf3ce44SJohn Forte 	    TASK_DAEMON_POWERING_DOWN)) &&
168fcf3ce44SJohn Forte 	    !ddi_in_panic()) {
169d3d50737SRafael Vanoni 		timer = mcp->timeout * drv_usectohz(1000000);
170fcf3ce44SJohn Forte 		while (!(ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT)) &&
171fcf3ce44SJohn Forte 		    !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
172fcf3ce44SJohn Forte 
173d3d50737SRafael Vanoni 			if (cv_reltimedwait(&ha->cv_mbx_intr,
174d3d50737SRafael Vanoni 			    &ha->pha->mbx_mutex, timer, TR_CLOCK_TICK) == -1) {
175fcf3ce44SJohn Forte 				/*
176fcf3ce44SJohn Forte 				 * The timeout time 'timer' was
177fcf3ce44SJohn Forte 				 * reached without the condition
178fcf3ce44SJohn Forte 				 * being signaled.
179fcf3ce44SJohn Forte 				 */
180*f885d00fSDaniel Beauregard 				MBX_REGISTER_UNLOCK(ha);
181*f885d00fSDaniel Beauregard 				while (INTERRUPT_PENDING(ha)) {
182*f885d00fSDaniel Beauregard 					(void) ql_isr((caddr_t)ha);
183*f885d00fSDaniel Beauregard 					INTR_LOCK(ha);
184*f885d00fSDaniel Beauregard 					ha->intr_claimed = B_TRUE;
185*f885d00fSDaniel Beauregard 					INTR_UNLOCK(ha);
186*f885d00fSDaniel Beauregard 				}
187*f885d00fSDaniel Beauregard 				MBX_REGISTER_LOCK(ha);
188fcf3ce44SJohn Forte 				break;
189fcf3ce44SJohn Forte 			}
190fcf3ce44SJohn Forte 		}
191fcf3ce44SJohn Forte 	} else {
192fcf3ce44SJohn Forte 		/* Release mailbox register lock. */
193fcf3ce44SJohn Forte 		MBX_REGISTER_UNLOCK(ha);
194fcf3ce44SJohn Forte 
195fcf3ce44SJohn Forte 		/* Acquire interrupt lock. */
196fcf3ce44SJohn Forte 		for (timer = mcp->timeout * 100; timer; timer--) {
197fcf3ce44SJohn Forte 			/* Check for pending interrupts. */
198eb82ff87SDaniel Beauregard 			while (INTERRUPT_PENDING(ha)) {
199fcf3ce44SJohn Forte 				(void) ql_isr((caddr_t)ha);
200fcf3ce44SJohn Forte 				INTR_LOCK(ha);
201fcf3ce44SJohn Forte 				ha->intr_claimed = B_TRUE;
202fcf3ce44SJohn Forte 				INTR_UNLOCK(ha);
203fcf3ce44SJohn Forte 				if (ha->mailbox_flags &
204fcf3ce44SJohn Forte 				    (MBX_INTERRUPT | MBX_ABORT) ||
205fcf3ce44SJohn Forte 				    ha->task_daemon_flags & ISP_ABORT_NEEDED) {
206fcf3ce44SJohn Forte 					break;
207fcf3ce44SJohn Forte 				}
208fcf3ce44SJohn Forte 			}
209fcf3ce44SJohn Forte 			if (ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT) ||
210fcf3ce44SJohn Forte 			    ha->task_daemon_flags & ISP_ABORT_NEEDED) {
211fcf3ce44SJohn Forte 				break;
212fcf3ce44SJohn Forte 			} else if (!ddi_in_panic() && timer % 101 == 0) {
213fcf3ce44SJohn Forte 				delay(drv_usectohz(10000));
214fcf3ce44SJohn Forte 			} else {
215fcf3ce44SJohn Forte 				drv_usecwait(10000);
216fcf3ce44SJohn Forte 			}
217fcf3ce44SJohn Forte 		}
218fcf3ce44SJohn Forte 
219fcf3ce44SJohn Forte 		/* Acquire mailbox register lock. */
220fcf3ce44SJohn Forte 		MBX_REGISTER_LOCK(ha);
221fcf3ce44SJohn Forte 	}
222fcf3ce44SJohn Forte 
223fcf3ce44SJohn Forte 	/* Mailbox command timeout? */
224fcf3ce44SJohn Forte 	if (ha->task_daemon_flags & ISP_ABORT_NEEDED ||
225fcf3ce44SJohn Forte 	    ha->mailbox_flags & MBX_ABORT) {
226fcf3ce44SJohn Forte 		rval = QL_ABORTED;
227fcf3ce44SJohn Forte 	} else if ((ha->mailbox_flags & MBX_INTERRUPT) == 0) {
228*f885d00fSDaniel Beauregard 		if (!CFG_IST(ha, CFG_CTRL_8021)) {
229*f885d00fSDaniel Beauregard 			if (CFG_IST(ha, CFG_DUMP_MAILBOX_TIMEOUT)) {
230*f885d00fSDaniel Beauregard 				(void) ql_binary_fw_dump(ha, FALSE);
231*f885d00fSDaniel Beauregard 			}
232*f885d00fSDaniel Beauregard 			EL(vha, "command timeout, isp_abort_needed\n");
233*f885d00fSDaniel Beauregard 			set_flags |= ISP_ABORT_NEEDED;
234fcf3ce44SJohn Forte 		}
235fcf3ce44SJohn Forte 		rval = QL_FUNCTION_TIMEOUT;
236fcf3ce44SJohn Forte 	} else {
237fcf3ce44SJohn Forte 		ha->mailbox_flags = (uint8_t)
238fcf3ce44SJohn Forte 		    (ha->mailbox_flags & ~MBX_INTERRUPT);
23916dd44c2SDaniel Beauregard 		/*
24016dd44c2SDaniel Beauregard 		 * This is the expected completion path so
24116dd44c2SDaniel Beauregard 		 * return the actual mbx cmd completion status.
24216dd44c2SDaniel Beauregard 		 */
243fcf3ce44SJohn Forte 		rval = mcp->mb[0];
244fcf3ce44SJohn Forte 	}
245fcf3ce44SJohn Forte 
24616dd44c2SDaniel Beauregard 	/*
24716dd44c2SDaniel Beauregard 	 * Clear outbound to risc mailbox registers per spec. The exception
24816dd44c2SDaniel Beauregard 	 * is on 2200 mailbox 4 and 5 affect the req and resp que indexes
24916dd44c2SDaniel Beauregard 	 * so avoid writing them.
25016dd44c2SDaniel Beauregard 	 */
25116dd44c2SDaniel Beauregard 	if (ha->cfg_flags & CFG_CTRL_2200) {
25216dd44c2SDaniel Beauregard 		data = ((mcp->out_mb & ~(MBX_4 | MBX_5)) >> 1);
25316dd44c2SDaniel Beauregard 	} else {
25416dd44c2SDaniel Beauregard 		data = (mcp->out_mb >> 1);
25516dd44c2SDaniel Beauregard 	}
256fcf3ce44SJohn Forte 	for (cnt = 1; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
257fcf3ce44SJohn Forte 		if (data & MBX_0) {
258eb82ff87SDaniel Beauregard 			WRT16_IO_REG(ha, mailbox_in[cnt], (uint16_t)0);
259fcf3ce44SJohn Forte 		}
260fcf3ce44SJohn Forte 		data >>= 1;
261fcf3ce44SJohn Forte 	}
262fcf3ce44SJohn Forte 
263fcf3ce44SJohn Forte 	/* Reset busy status. */
264fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
265fcf3ce44SJohn Forte 	    ~(MBX_BUSY_FLG | MBX_ABORT));
266fcf3ce44SJohn Forte 	ha->mcp = NULL;
267fcf3ce44SJohn Forte 
268fcf3ce44SJohn Forte 	/* If thread is waiting for mailbox go signal it to start. */
269fcf3ce44SJohn Forte 	if (ha->mailbox_flags & MBX_WANT_FLG) {
270fcf3ce44SJohn Forte 		ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
271fcf3ce44SJohn Forte 		    ~MBX_WANT_FLG);
272fcf3ce44SJohn Forte 		cv_broadcast(&ha->cv_mbx_wait);
273fcf3ce44SJohn Forte 	}
274fcf3ce44SJohn Forte 
275fcf3ce44SJohn Forte 	/* Release mailbox register lock. */
276fcf3ce44SJohn Forte 	MBX_REGISTER_UNLOCK(ha);
277fcf3ce44SJohn Forte 
278fcf3ce44SJohn Forte 	if (set_flags != 0 || reset_flags != 0) {
279fcf3ce44SJohn Forte 		ql_awaken_task_daemon(ha, NULL, set_flags, reset_flags);
280fcf3ce44SJohn Forte 	}
281fcf3ce44SJohn Forte 
282fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
28316dd44c2SDaniel Beauregard 		EL(vha, "%s failed, rval=%xh, mcp->mb[0]=%xh\n",
28416dd44c2SDaniel Beauregard 		    mbx_cmd_text(mbx_cmd), rval, mcp->mb[0]);
285fcf3ce44SJohn Forte 	} else {
286fcf3ce44SJohn Forte 		/*EMPTY*/
287fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
288fcf3ce44SJohn Forte 	}
289fcf3ce44SJohn Forte 
290fcf3ce44SJohn Forte 	return (rval);
291fcf3ce44SJohn Forte }
292fcf3ce44SJohn Forte 
293fcf3ce44SJohn Forte /*
294fcf3ce44SJohn Forte  * ql_setup_mbox_dma_resources
295fcf3ce44SJohn Forte  *	Prepare the data for a mailbox dma transfer.
296fcf3ce44SJohn Forte  *
297fcf3ce44SJohn Forte  * Input:
298fcf3ce44SJohn Forte  *	ha = adapter state pointer.
299fcf3ce44SJohn Forte  *	mem_desc = descriptor to contain the dma resource information.
300fcf3ce44SJohn Forte  *	data = pointer to the data.
301fcf3ce44SJohn Forte  *	size = size of the data in bytes.
302fcf3ce44SJohn Forte  *
303fcf3ce44SJohn Forte  * Returns:
304fcf3ce44SJohn Forte  *	ql local function return status code.
305fcf3ce44SJohn Forte  *
306fcf3ce44SJohn Forte  * Context:
307fcf3ce44SJohn Forte  *	Kernel context.
308fcf3ce44SJohn Forte  */
309fcf3ce44SJohn Forte static int
ql_setup_mbox_dma_transfer(ql_adapter_state_t * ha,dma_mem_t * mem_desc,caddr_t data,uint32_t size)310fcf3ce44SJohn Forte ql_setup_mbox_dma_transfer(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
311fcf3ce44SJohn Forte     caddr_t data, uint32_t size)
312fcf3ce44SJohn Forte {
313fcf3ce44SJohn Forte 	int rval = QL_SUCCESS;
314fcf3ce44SJohn Forte 
315fcf3ce44SJohn Forte 	if ((rval = ql_setup_mbox_dma_resources(ha, mem_desc, size)) ==
316fcf3ce44SJohn Forte 	    QL_SUCCESS) {
317fcf3ce44SJohn Forte 		ql_setup_mbox_dma_data(mem_desc, data);
318fcf3ce44SJohn Forte 	} else {
319fcf3ce44SJohn Forte 		EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
320fcf3ce44SJohn Forte 	}
321fcf3ce44SJohn Forte 
322fcf3ce44SJohn Forte 	return (rval);
323fcf3ce44SJohn Forte }
324fcf3ce44SJohn Forte 
325fcf3ce44SJohn Forte /*
326fcf3ce44SJohn Forte  * ql_setup_mbox_dma_resources
327fcf3ce44SJohn Forte  *	Prepare a dma buffer.
328fcf3ce44SJohn Forte  *
329fcf3ce44SJohn Forte  * Input:
330fcf3ce44SJohn Forte  *	ha = adapter state pointer.
331fcf3ce44SJohn Forte  *	mem_desc = descriptor to contain the dma resource information.
332fcf3ce44SJohn Forte  *	data = pointer to the data.
333fcf3ce44SJohn Forte  *	size = size of the data in bytes.
334fcf3ce44SJohn Forte  *
335fcf3ce44SJohn Forte  * Returns:
336fcf3ce44SJohn Forte  *	ql local function return status code.
337fcf3ce44SJohn Forte  *
338fcf3ce44SJohn Forte  * Context:
339fcf3ce44SJohn Forte  *	Kernel context.
340fcf3ce44SJohn Forte  */
341fcf3ce44SJohn Forte static int
ql_setup_mbox_dma_resources(ql_adapter_state_t * ha,dma_mem_t * mem_desc,uint32_t size)342fcf3ce44SJohn Forte ql_setup_mbox_dma_resources(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
343fcf3ce44SJohn Forte     uint32_t size)
344fcf3ce44SJohn Forte {
345fcf3ce44SJohn Forte 	int	rval = QL_SUCCESS;
346fcf3ce44SJohn Forte 
347fcf3ce44SJohn Forte 	if ((rval = ql_get_dma_mem(ha, mem_desc, size, LITTLE_ENDIAN_DMA,
34816dd44c2SDaniel Beauregard 	    QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
349fcf3ce44SJohn Forte 		EL(ha, "failed, ql_get_dma_mem FC_NOMEM\n");
350fcf3ce44SJohn Forte 		rval = QL_MEMORY_ALLOC_FAILED;
351fcf3ce44SJohn Forte 	}
352fcf3ce44SJohn Forte 
353fcf3ce44SJohn Forte 	return (rval);
354fcf3ce44SJohn Forte }
355fcf3ce44SJohn Forte 
356fcf3ce44SJohn Forte /*
357fcf3ce44SJohn Forte  * ql_setup_mbox_dma_data
358fcf3ce44SJohn Forte  *	Move data to the dma buffer.
359fcf3ce44SJohn Forte  *
360fcf3ce44SJohn Forte  * Input:
361fcf3ce44SJohn Forte  *	mem_desc = descriptor to contain the dma resource information.
362fcf3ce44SJohn Forte  *	data = pointer to the data.
363fcf3ce44SJohn Forte  *
364fcf3ce44SJohn Forte  * Returns:
365fcf3ce44SJohn Forte  *
366fcf3ce44SJohn Forte  * Context:
367fcf3ce44SJohn Forte  *	Kernel context.
368fcf3ce44SJohn Forte  */
369fcf3ce44SJohn Forte static void
ql_setup_mbox_dma_data(dma_mem_t * mem_desc,caddr_t data)370fcf3ce44SJohn Forte ql_setup_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
371fcf3ce44SJohn Forte {
372fcf3ce44SJohn Forte 	/* Copy out going data to DMA buffer. */
373fcf3ce44SJohn Forte 	ddi_rep_put8(mem_desc->acc_handle, (uint8_t *)data,
374fcf3ce44SJohn Forte 	    (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
375fcf3ce44SJohn Forte 
376fcf3ce44SJohn Forte 	/* Sync DMA buffer. */
377fcf3ce44SJohn Forte 	(void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
378fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORDEV);
379fcf3ce44SJohn Forte }
380fcf3ce44SJohn Forte 
381fcf3ce44SJohn Forte /*
382fcf3ce44SJohn Forte  * ql_get_mbox_dma_data
383fcf3ce44SJohn Forte  *	Recover data from the dma buffer.
384fcf3ce44SJohn Forte  *
385fcf3ce44SJohn Forte  * Input:
386fcf3ce44SJohn Forte  *	mem_desc = descriptor to contain the dma resource information.
387fcf3ce44SJohn Forte  *	data = pointer to the data.
388fcf3ce44SJohn Forte  *
389fcf3ce44SJohn Forte  * Returns:
390fcf3ce44SJohn Forte  *
391fcf3ce44SJohn Forte  * Context:
392fcf3ce44SJohn Forte  *	Kernel context.
393fcf3ce44SJohn Forte  */
394fcf3ce44SJohn Forte static void
ql_get_mbox_dma_data(dma_mem_t * mem_desc,caddr_t data)395fcf3ce44SJohn Forte ql_get_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
396fcf3ce44SJohn Forte {
397fcf3ce44SJohn Forte 	/* Sync in coming DMA buffer. */
398fcf3ce44SJohn Forte 	(void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
399fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORKERNEL);
400fcf3ce44SJohn Forte 	/* Copy in coming DMA data. */
401fcf3ce44SJohn Forte 	ddi_rep_get8(mem_desc->acc_handle, (uint8_t *)data,
402fcf3ce44SJohn Forte 	    (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
403fcf3ce44SJohn Forte }
404fcf3ce44SJohn Forte 
405fcf3ce44SJohn Forte /*
406fcf3ce44SJohn Forte  * ql_initialize_ip
407fcf3ce44SJohn Forte  *	Initialize IP receive buffer queue.
408fcf3ce44SJohn Forte  *
409fcf3ce44SJohn Forte  * Input:
410fcf3ce44SJohn Forte  *	ha = adapter state pointer.
411fcf3ce44SJohn Forte  *	ha->ip_init_ctrl_blk = setup for transmit.
412fcf3ce44SJohn Forte  *
413fcf3ce44SJohn Forte  * Returns:
414fcf3ce44SJohn Forte  *	ql local function return status code.
415fcf3ce44SJohn Forte  *
416fcf3ce44SJohn Forte  * Context:
417fcf3ce44SJohn Forte  *	Kernel context.
418fcf3ce44SJohn Forte  */
419fcf3ce44SJohn Forte int
ql_initialize_ip(ql_adapter_state_t * ha)420fcf3ce44SJohn Forte ql_initialize_ip(ql_adapter_state_t *ha)
421fcf3ce44SJohn Forte {
422fcf3ce44SJohn Forte 	ql_link_t	*link;
423fcf3ce44SJohn Forte 	ql_tgt_t	*tq;
424fcf3ce44SJohn Forte 	uint16_t	index;
425fcf3ce44SJohn Forte 	int		rval;
426fcf3ce44SJohn Forte 	dma_mem_t	mem_desc;
427fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
428fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
429fcf3ce44SJohn Forte 
430fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
431fcf3ce44SJohn Forte 
432eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, (CFG_CTRL_6322 | CFG_CTRL_258081)) ||
433fcf3ce44SJohn Forte 	    ha->vp_index != 0) {
434fcf3ce44SJohn Forte 		ha->flags &= ~IP_INITIALIZED;
435fcf3ce44SJohn Forte 		EL(ha, "HBA does not support IP\n");
436fcf3ce44SJohn Forte 		return (QL_FUNCTION_FAILED);
437fcf3ce44SJohn Forte 	}
438fcf3ce44SJohn Forte 
439fcf3ce44SJohn Forte 	ha->rcvbuf_ring_ptr = ha->rcvbuf_ring_bp;
440fcf3ce44SJohn Forte 	ha->rcvbuf_ring_index = 0;
441fcf3ce44SJohn Forte 
442fcf3ce44SJohn Forte 	/* Reset all sequence counts. */
443fcf3ce44SJohn Forte 	for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
444fcf3ce44SJohn Forte 		for (link = ha->dev[index].first; link != NULL;
445fcf3ce44SJohn Forte 		    link = link->next) {
446fcf3ce44SJohn Forte 			tq = link->base_address;
447fcf3ce44SJohn Forte 			tq->ub_total_seg_cnt = 0;
448fcf3ce44SJohn Forte 		}
449fcf3ce44SJohn Forte 	}
450fcf3ce44SJohn Forte 
451fcf3ce44SJohn Forte 	rval = ql_setup_mbox_dma_transfer(ha, &mem_desc,
452fcf3ce44SJohn Forte 	    (caddr_t)&ha->ip_init_ctrl_blk, sizeof (ql_comb_ip_init_cb_t));
453fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
454fcf3ce44SJohn Forte 		EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
455fcf3ce44SJohn Forte 		return (rval);
456fcf3ce44SJohn Forte 	}
457fcf3ce44SJohn Forte 
458fcf3ce44SJohn Forte 	mcp->mb[0] = MBC_INITIALIZE_IP;
459fcf3ce44SJohn Forte 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
460fcf3ce44SJohn Forte 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
461fcf3ce44SJohn Forte 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
462fcf3ce44SJohn Forte 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
463fcf3ce44SJohn Forte 	mcp->mb[8] = 0;
464fcf3ce44SJohn Forte 	mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
465fcf3ce44SJohn Forte 	mcp->in_mb = MBX_8|MBX_0;
466fcf3ce44SJohn Forte 	mcp->timeout = MAILBOX_TOV;
467fcf3ce44SJohn Forte 	rval = ql_mailbox_command(ha, mcp);
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte 	ql_free_dma_resource(ha, &mem_desc);
470fcf3ce44SJohn Forte 
471fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
472fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
473fcf3ce44SJohn Forte 		ha->flags |= IP_INITIALIZED;
474fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
475fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
476fcf3ce44SJohn Forte 	} else {
477fcf3ce44SJohn Forte 		ha->flags &= ~IP_INITIALIZED;
478fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
479fcf3ce44SJohn Forte 	}
480fcf3ce44SJohn Forte 	return (rval);
481fcf3ce44SJohn Forte }
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte /*
484fcf3ce44SJohn Forte  * ql_shutdown_ip
485fcf3ce44SJohn Forte  *	Disconnects firmware IP from system buffers.
486fcf3ce44SJohn Forte  *
487fcf3ce44SJohn Forte  * Input:
488fcf3ce44SJohn Forte  *	ha = adapter state pointer.
489fcf3ce44SJohn Forte  *
490fcf3ce44SJohn Forte  * Returns:
491fcf3ce44SJohn Forte  *	ql local function return status code.
492fcf3ce44SJohn Forte  *
493fcf3ce44SJohn Forte  * Context:
494fcf3ce44SJohn Forte  *	Kernel context.
495fcf3ce44SJohn Forte  */
496fcf3ce44SJohn Forte int
ql_shutdown_ip(ql_adapter_state_t * ha)497fcf3ce44SJohn Forte ql_shutdown_ip(ql_adapter_state_t *ha)
498fcf3ce44SJohn Forte {
499fcf3ce44SJohn Forte 	int		rval;
500fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
501fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
502fcf3ce44SJohn Forte 	fc_unsol_buf_t	*ubp;
503fcf3ce44SJohn Forte 	ql_srb_t	*sp;
504fcf3ce44SJohn Forte 	uint16_t	index;
505fcf3ce44SJohn Forte 
506fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
507fcf3ce44SJohn Forte 
508fcf3ce44SJohn Forte 	mcp->mb[0] = MBC_UNLOAD_IP;
509fcf3ce44SJohn Forte 	mcp->out_mb = MBX_0;
510fcf3ce44SJohn Forte 	mcp->in_mb = MBX_0;
511fcf3ce44SJohn Forte 	mcp->timeout = MAILBOX_TOV;
512fcf3ce44SJohn Forte 	rval = ql_mailbox_command(ha, mcp);
513fcf3ce44SJohn Forte 
514fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
515fcf3ce44SJohn Forte 	QL_UB_LOCK(ha);
516fcf3ce44SJohn Forte 	/* Return all unsolicited buffers that ISP-IP has. */
517fcf3ce44SJohn Forte 	for (index = 0; index < QL_UB_LIMIT; index++) {
518fcf3ce44SJohn Forte 		ubp = ha->ub_array[index];
519fcf3ce44SJohn Forte 		if (ubp != NULL) {
520fcf3ce44SJohn Forte 			sp = ubp->ub_fca_private;
521fcf3ce44SJohn Forte 			sp->flags &= ~SRB_UB_IN_ISP;
522fcf3ce44SJohn Forte 		}
523fcf3ce44SJohn Forte 	}
524fcf3ce44SJohn Forte 
525fcf3ce44SJohn Forte 	ha->ub_outcnt = 0;
526fcf3ce44SJohn Forte 	QL_UB_UNLOCK(ha);
527fcf3ce44SJohn Forte 	ha->flags &= ~IP_INITIALIZED;
528fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
529fcf3ce44SJohn Forte 
530fcf3ce44SJohn Forte 	if (rval == QL_SUCCESS) {
531fcf3ce44SJohn Forte 		/* EMPTY - no need to check return value of MBC_SHUTDOWN_IP */
532fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
533fcf3ce44SJohn Forte 	} else {
534fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
535fcf3ce44SJohn Forte 	}
536fcf3ce44SJohn Forte 	return (rval);
537fcf3ce44SJohn Forte }
538fcf3ce44SJohn Forte 
539fcf3ce44SJohn Forte /*
540fcf3ce44SJohn Forte  * ql_online_selftest
541fcf3ce44SJohn Forte  *	Issue online self test mailbox command.
542fcf3ce44SJohn Forte  *
543fcf3ce44SJohn Forte  * Input:
544fcf3ce44SJohn Forte  *	ha = adapter state pointer.
545fcf3ce44SJohn Forte  *
546fcf3ce44SJohn Forte  * Returns:
547fcf3ce44SJohn Forte  *	ql local function return status code.
548fcf3ce44SJohn Forte  *
549fcf3ce44SJohn Forte  * Context:
550fcf3ce44SJohn Forte  *	Kernel context.
551fcf3ce44SJohn Forte  */
552fcf3ce44SJohn Forte int
ql_online_selftest(ql_adapter_state_t * ha)553fcf3ce44SJohn Forte ql_online_selftest(ql_adapter_state_t *ha)
554fcf3ce44SJohn Forte {
555fcf3ce44SJohn Forte 	int		rval;
556fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
557fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
558fcf3ce44SJohn Forte 
559fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
560fcf3ce44SJohn Forte 
561fcf3ce44SJohn Forte 	mcp->mb[0] = MBC_ONLINE_SELF_TEST;
562fcf3ce44SJohn Forte 	mcp->out_mb = MBX_0;
563fcf3ce44SJohn Forte 	mcp->in_mb = MBX_0 | MBX_1 | MBX_2 | MBX_3;
564fcf3ce44SJohn Forte 	mcp->timeout = MAILBOX_TOV;
565fcf3ce44SJohn Forte 	rval = ql_mailbox_command(ha, mcp);
566fcf3ce44SJohn Forte 
567fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
568fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh, mb1=%xh, mb2=%xh, mb3=%xh\n",
569fcf3ce44SJohn Forte 		    rval, mcp->mb[1], mcp->mb[2], mcp->mb[3]);
570fcf3ce44SJohn Forte 	} else {
571fcf3ce44SJohn Forte 		/*EMPTY*/
572fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
573fcf3ce44SJohn Forte 	}
574fcf3ce44SJohn Forte 	return (rval);
575fcf3ce44SJohn Forte }
576fcf3ce44SJohn Forte 
577fcf3ce44SJohn Forte /*
578fcf3ce44SJohn Forte  * ql_loop_back
579fcf3ce44SJohn Forte  *	Issue diagnostic loop back frame mailbox command.
580fcf3ce44SJohn Forte  *
581fcf3ce44SJohn Forte  * Input:
5824f8b8adcSDaniel Beauregard  *	ha:	adapter state pointer.
5834f8b8adcSDaniel Beauregard  *	findex:	FCF index.
5844f8b8adcSDaniel Beauregard  *	lb:	loop back parameter structure pointer.
585fcf3ce44SJohn Forte  *
586fcf3ce44SJohn Forte  * Returns:
587fcf3ce44SJohn Forte  *	ql local function return status code.
588fcf3ce44SJohn Forte  *
589fcf3ce44SJohn Forte  * Context:
590fcf3ce44SJohn Forte  *	Kernel context.
591fcf3ce44SJohn Forte  */
592fcf3ce44SJohn Forte #ifndef apps_64bit
593fcf3ce44SJohn Forte int
ql_loop_back(ql_adapter_state_t * ha,uint16_t findex,lbp_t * lb,uint32_t h_xmit,uint32_t h_rcv)5944f8b8adcSDaniel Beauregard ql_loop_back(ql_adapter_state_t *ha, uint16_t findex, lbp_t *lb,
5954f8b8adcSDaniel Beauregard     uint32_t h_xmit, uint32_t h_rcv)
596fcf3ce44SJohn Forte {
597fcf3ce44SJohn Forte 	int		rval;
598fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
599fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
600fcf3ce44SJohn Forte 
601fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
602fcf3ce44SJohn Forte 
603fcf3ce44SJohn Forte 	mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
604fcf3ce44SJohn Forte 	mcp->mb[1] = lb->options;
6054f8b8adcSDaniel Beauregard 	mcp->mb[2] = findex;
606fcf3ce44SJohn Forte 	mcp->mb[6] = LSW(h_rcv);
607fcf3ce44SJohn Forte 	mcp->mb[7] = MSW(h_rcv);
608fcf3ce44SJohn Forte 	mcp->mb[10] = LSW(lb->transfer_count);
609fcf3ce44SJohn Forte 	mcp->mb[11] = MSW(lb->transfer_count);
610fcf3ce44SJohn Forte 	mcp->mb[12] = lb->transfer_segment_count;
611fcf3ce44SJohn Forte 	mcp->mb[13] = lb->receive_segment_count;
612fcf3ce44SJohn Forte 	mcp->mb[14] = LSW(lb->transfer_data_address);
613fcf3ce44SJohn Forte 	mcp->mb[15] = MSW(lb->transfer_data_address);
614fcf3ce44SJohn Forte 	mcp->mb[16] = LSW(lb->receive_data_address);
615fcf3ce44SJohn Forte 	mcp->mb[17] = MSW(lb->receive_data_address);
616fcf3ce44SJohn Forte 	mcp->mb[18] = LSW(lb->iteration_count);
617fcf3ce44SJohn Forte 	mcp->mb[19] = MSW(lb->iteration_count);
618fcf3ce44SJohn Forte 	mcp->mb[20] = LSW(h_xmit);
619fcf3ce44SJohn Forte 	mcp->mb[21] = MSW(h_xmit);
620fcf3ce44SJohn Forte 	mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
6214f8b8adcSDaniel Beauregard 	    MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
622fcf3ce44SJohn Forte 	mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
623fcf3ce44SJohn Forte 	mcp->timeout = lb->iteration_count / 300;
624fcf3ce44SJohn Forte 
625fcf3ce44SJohn Forte 	if (mcp->timeout < MAILBOX_TOV) {
626fcf3ce44SJohn Forte 		mcp->timeout = MAILBOX_TOV;
627fcf3ce44SJohn Forte 	}
628fcf3ce44SJohn Forte 
629fcf3ce44SJohn Forte 	rval = ql_mailbox_command(ha, mcp);
630fcf3ce44SJohn Forte 
631fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
632eb82ff87SDaniel Beauregard 		EL(ha, "failed, rval = %xh, mb1=%xh, mb2=%xh, mb3=%xh\n",
633eb82ff87SDaniel Beauregard 		    rval, mcp->mb[1], mcp->mb[2], mcp->mb[3]);
634fcf3ce44SJohn Forte 	} else {
635fcf3ce44SJohn Forte 		/*EMPTY*/
636fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
637fcf3ce44SJohn Forte 	}
638fcf3ce44SJohn Forte 	return (rval);
639fcf3ce44SJohn Forte }
640fcf3ce44SJohn Forte #else
641fcf3ce44SJohn Forte int
ql_loop_back(ql_adapter_state_t * ha,uint16_t findex,lbp_t * lb)6424f8b8adcSDaniel Beauregard ql_loop_back(ql_adapter_state_t *ha, uint16_t findex, lbp_t *lb)
643fcf3ce44SJohn Forte {
644fcf3ce44SJohn Forte 	int		rval;
645fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
646fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
647fcf3ce44SJohn Forte 
648fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
649fcf3ce44SJohn Forte 
650fcf3ce44SJohn Forte 	mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
651fcf3ce44SJohn Forte 	mcp->mb[1] = lb->options;
6524f8b8adcSDaniel Beauregard 	mcp->mb[2] = findex;
653fcf3ce44SJohn Forte 	mcp->mb[6] = LSW(h_rcv);
654fcf3ce44SJohn Forte 	mcp->mb[7] = MSW(h_rcv);
655fcf3ce44SJohn Forte 	mcp->mb[6] = LSW(MSD(lb->receive_data_address));
656fcf3ce44SJohn Forte 	mcp->mb[7] = MSW(MSD(lb->receive_data_address));
657fcf3ce44SJohn Forte 	mcp->mb[10] = LSW(lb->transfer_count);
658fcf3ce44SJohn Forte 	mcp->mb[11] = MSW(lb->transfer_count);
659fcf3ce44SJohn Forte 	mcp->mb[12] = lb->transfer_segment_count;
660fcf3ce44SJohn Forte 	mcp->mb[13] = lb->receive_segment_count;
661fcf3ce44SJohn Forte 	mcp->mb[14] = LSW(lb->transfer_data_address);
662fcf3ce44SJohn Forte 	mcp->mb[15] = MSW(lb->transfer_data_address);
663fcf3ce44SJohn Forte 	mcp->mb[14] = LSW(LSD(lb->transfer_data_address));
664fcf3ce44SJohn Forte 	mcp->mb[15] = MSW(LSD(lb->transfer_data_address));
665fcf3ce44SJohn Forte 	mcp->mb[16] = LSW(lb->receive_data_address);
666fcf3ce44SJohn Forte 	mcp->mb[17] = MSW(lb->receive_data_address);
667fcf3ce44SJohn Forte 	mcp->mb[16] = LSW(LSD(lb->receive_data_address));
668fcf3ce44SJohn Forte 	mcp->mb[17] = MSW(LSD(lb->receive_data_address));
669fcf3ce44SJohn Forte 	mcp->mb[18] = LSW(lb->iteration_count);
670fcf3ce44SJohn Forte 	mcp->mb[19] = MSW(lb->iteration_count);
671fcf3ce44SJohn Forte 	mcp->mb[20] = LSW(h_xmit);
672fcf3ce44SJohn Forte 	mcp->mb[21] = MSW(h_xmit);
673fcf3ce44SJohn Forte 	mcp->mb[20] = LSW(MSD(lb->transfer_data_address));
674fcf3ce44SJohn Forte 	mcp->mb[21] = MSW(MSD(lb->transfer_data_address));
675fcf3ce44SJohn Forte 	mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
6764f8b8adcSDaniel Beauregard 	    MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
677fcf3ce44SJohn Forte 	mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
678fcf3ce44SJohn Forte 	mcp->timeout = lb->iteration_count / 300;
679fcf3ce44SJohn Forte 
680fcf3ce44SJohn Forte 	if (mcp->timeout < MAILBOX_TOV) {
681fcf3ce44SJohn Forte 		mcp->timeout = MAILBOX_TOV;
682fcf3ce44SJohn Forte 	}
683fcf3ce44SJohn Forte 
684fcf3ce44SJohn Forte 	rval = ql_mailbox_command(ha, mcp);
685fcf3ce44SJohn Forte 
686fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
687fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
688fcf3ce44SJohn Forte 	} else {
689fcf3ce44SJohn Forte 		/*EMPTY*/
690fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
691fcf3ce44SJohn Forte 	}
692fcf3ce44SJohn Forte 	return (rval);
693fcf3ce44SJohn Forte }
694fcf3ce44SJohn Forte #endif
695fcf3ce44SJohn Forte 
696fcf3ce44SJohn Forte /*
697fcf3ce44SJohn Forte  * ql_echo
698fcf3ce44SJohn Forte  *	Issue an ELS echo using the user specified data to a user specified
699fcf3ce44SJohn Forte  *	destination
700fcf3ce44SJohn Forte  *
701fcf3ce44SJohn Forte  * Input:
702fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
7034f8b8adcSDaniel Beauregard  *	findex:		FCF index.
704fcf3ce44SJohn Forte  *	echo_pt:	echo parameter structure pointer.
705fcf3ce44SJohn Forte  *
706fcf3ce44SJohn Forte  * Returns:
707fcf3ce44SJohn Forte  *	ql local function return status code.
708fcf3ce44SJohn Forte  *
709fcf3ce44SJohn Forte  * Context:
710fcf3ce44SJohn Forte  *	Kernel context.
711fcf3ce44SJohn Forte  */
712fcf3ce44SJohn Forte int
ql_echo(ql_adapter_state_t * ha,uint16_t findex,echo_t * echo_pt)7134f8b8adcSDaniel Beauregard ql_echo(ql_adapter_state_t *ha, uint16_t findex, echo_t *echo_pt)
714fcf3ce44SJohn Forte {
715fcf3ce44SJohn Forte 	int		rval;
716fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
717fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
718fcf3ce44SJohn Forte 
719fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
720fcf3ce44SJohn Forte 
721fcf3ce44SJohn Forte 	mcp->mb[0] = MBC_ECHO;			/* ECHO command */
722fcf3ce44SJohn Forte 	mcp->mb[1] = echo_pt->options;		/* command options; 64 bit */
723fcf3ce44SJohn Forte 						/* addressing (bit 6) and */
724fcf3ce44SJohn Forte 						/* real echo (bit 15 */
7254f8b8adcSDaniel Beauregard 	mcp->mb[2] = findex;
726fcf3ce44SJohn Forte 
727fcf3ce44SJohn Forte 	/*
728fcf3ce44SJohn Forte 	 * I know this looks strange, using a field labled "not used"
729fcf3ce44SJohn Forte 	 * The way the ddi_dma_cookie_t structure/union is defined
730fcf3ce44SJohn Forte 	 * is a union of one 64 bit entity with an array of two 32
731fcf3ce44SJohn Forte 	 * bit enititys.  Since we have routines to convert 32 bit
732fcf3ce44SJohn Forte 	 * entities into 16 bit entities it is easier to use
733fcf3ce44SJohn Forte 	 * both 32 bit union members then the one 64 bit union
734fcf3ce44SJohn Forte 	 * member
735fcf3ce44SJohn Forte 	 */
736fcf3ce44SJohn Forte 	if (echo_pt->options & BIT_6) {
737fcf3ce44SJohn Forte 		/* 64 bit addressing */
738fcf3ce44SJohn Forte 		/* Receive data dest add in system memory bits 47-32 */
739fcf3ce44SJohn Forte 		mcp->mb[6] = LSW(echo_pt->receive_data_address.dmac_notused);
740fcf3ce44SJohn Forte 
741fcf3ce44SJohn Forte 		/* Receive data dest add in system memory bits 63-48 */
742fcf3ce44SJohn Forte 		mcp->mb[7] = MSW(echo_pt->receive_data_address.dmac_notused);
743fcf3ce44SJohn Forte 
744fcf3ce44SJohn Forte 		/* Transmit data source address in system memory bits 47-32 */
745fcf3ce44SJohn Forte 		mcp->mb[20] = LSW(echo_pt->transfer_data_address.dmac_notused);
746fcf3ce44SJohn Forte 
747fcf3ce44SJohn Forte 		/* Transmit data source address in system memory bits 63-48 */
748fcf3ce44SJohn Forte 		mcp->mb[21] = MSW(echo_pt->transfer_data_address.dmac_notused);
749fcf3ce44SJohn Forte 	}
750fcf3ce44SJohn Forte 
751fcf3ce44SJohn Forte 	/* transfer count bits 15-0 */
752fcf3ce44SJohn Forte 	mcp->mb[10] = LSW(echo_pt->transfer_count);
753fcf3ce44SJohn Forte 
754fcf3ce44SJohn Forte 	/* Transmit data source address in system memory bits 15-0 */
755fcf3ce44SJohn Forte 	mcp->mb[14] = LSW(echo_pt->transfer_data_address.dmac_address);
756fcf3ce44SJohn Forte 
757fcf3ce44SJohn Forte 	/*  Transmit data source address in system memory bits 31-16 */
758fcf3ce44SJohn Forte 	mcp->mb[15] = MSW(echo_pt->transfer_data_address.dmac_address);
759fcf3ce44SJohn Forte 
760fcf3ce44SJohn Forte 	/* Receive data destination address in system memory bits 15-0 */
761fcf3ce44SJohn Forte 	mcp->mb[16] = LSW(echo_pt->receive_data_address.dmac_address);
762fcf3ce44SJohn Forte 
763fcf3ce44SJohn Forte 	/*  Receive data destination address in system memory bits 31-16 */
764fcf3ce44SJohn Forte 	mcp->mb[17] = MSW(echo_pt->receive_data_address.dmac_address);
765fcf3ce44SJohn Forte 
766fcf3ce44SJohn Forte 	mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|MBX_14|MBX_10|
7674f8b8adcSDaniel Beauregard 	    MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
7684f8b8adcSDaniel Beauregard 	mcp->in_mb = MBX_3|MBX_1|MBX_0;
769fcf3ce44SJohn Forte 	mcp->timeout = MAILBOX_TOV;
770fcf3ce44SJohn Forte 
771fcf3ce44SJohn Forte 	rval = ql_mailbox_command(ha, mcp);
772fcf3ce44SJohn Forte 
773fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
774fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
775fcf3ce44SJohn Forte 	} else {
776fcf3ce44SJohn Forte 		/*EMPTY*/
777fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
778fcf3ce44SJohn Forte 	}
779fcf3ce44SJohn Forte 	return (rval);
780fcf3ce44SJohn Forte }
781fcf3ce44SJohn Forte 
782fcf3ce44SJohn Forte /*
783fcf3ce44SJohn Forte  * ql_send_change_request
784fcf3ce44SJohn Forte  *	Issue send change request mailbox command.
785fcf3ce44SJohn Forte  *
786fcf3ce44SJohn Forte  * Input:
787fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
788fcf3ce44SJohn Forte  *	fmt:	Registration format.
789fcf3ce44SJohn Forte  *
790fcf3ce44SJohn Forte  * Returns:
791fcf3ce44SJohn Forte  *	ql local function return status code.
792fcf3ce44SJohn Forte  *
793fcf3ce44SJohn Forte  * Context:
794fcf3ce44SJohn Forte  *	Kernel context.
795fcf3ce44SJohn Forte  */
796fcf3ce44SJohn Forte int
ql_send_change_request(ql_adapter_state_t * ha,uint16_t fmt)797fcf3ce44SJohn Forte ql_send_change_request(ql_adapter_state_t *ha, uint16_t fmt)
798fcf3ce44SJohn Forte {
799fcf3ce44SJohn Forte 	int		rval;
800fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
801fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
802fcf3ce44SJohn Forte 
803fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
804fcf3ce44SJohn Forte 
805fcf3ce44SJohn Forte 	mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
806fcf3ce44SJohn Forte 	mcp->mb[1] = fmt;
807fcf3ce44SJohn Forte 	mcp->out_mb = MBX_1|MBX_0;
808fcf3ce44SJohn Forte 	if (ha->flags & VP_ENABLED) {
809fcf3ce44SJohn Forte 		mcp->mb[9] = ha->vp_index;
810fcf3ce44SJohn Forte 		mcp->out_mb |= MBX_9;
811fcf3ce44SJohn Forte 	}
812fcf3ce44SJohn Forte 	mcp->in_mb = MBX_0;
813fcf3ce44SJohn Forte 	mcp->timeout = MAILBOX_TOV;
814fcf3ce44SJohn Forte 	rval = ql_mailbox_command(ha, mcp);
815fcf3ce44SJohn Forte 
816fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
817fcf3ce44SJohn Forte 		EL(ha, "failed=%xh\n", rval);
818fcf3ce44SJohn Forte 	} else {
819fcf3ce44SJohn Forte 		/*EMPTY*/
820fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
821fcf3ce44SJohn Forte 	}
822fcf3ce44SJohn Forte 	return (rval);
823fcf3ce44SJohn Forte }
824fcf3ce44SJohn Forte 
825fcf3ce44SJohn Forte /*
826fcf3ce44SJohn Forte  * ql_send_lfa
827fcf3ce44SJohn Forte  *	Send a Loop Fabric Address mailbox command.
828fcf3ce44SJohn Forte  *
829fcf3ce44SJohn Forte  * Input:
830fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
831fcf3ce44SJohn Forte  *	lfa:	LFA command structure pointer.
832fcf3ce44SJohn Forte  *
833fcf3ce44SJohn Forte  * Returns:
834fcf3ce44SJohn Forte  *	ql local function return status code.
835fcf3ce44SJohn Forte  *
836fcf3ce44SJohn Forte  * Context:
837fcf3ce44SJohn Forte  *	Kernel context.
838fcf3ce44SJohn Forte  */
839fcf3ce44SJohn Forte int
ql_send_lfa(ql_adapter_state_t * ha,lfa_cmd_t * lfa)840fcf3ce44SJohn Forte ql_send_lfa(ql_adapter_state_t *ha, lfa_cmd_t *lfa)
841fcf3ce44SJohn Forte {
842fcf3ce44SJohn Forte 	int		rval;
843fcf3ce44SJohn Forte 	uint16_t	size;
844fcf3ce44SJohn Forte 	dma_mem_t	mem_desc;
845fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
846fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
847fcf3ce44SJohn Forte 
848fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
849fcf3ce44SJohn Forte 
850fcf3ce44SJohn Forte 	/* LFA_CB sz = 4 16bit words subcommand + 10 16bit words header. */
851fcf3ce44SJohn Forte 	size = (uint16_t)((lfa->subcommand_length[0] + 10) << 1);
852fcf3ce44SJohn Forte 
853fcf3ce44SJohn Forte 	rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, (caddr_t)lfa, size);
854fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
855fcf3ce44SJohn Forte 		EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
856fcf3ce44SJohn Forte 		return (rval);
857fcf3ce44SJohn Forte 	}
858fcf3ce44SJohn Forte 
859fcf3ce44SJohn Forte 	mcp->mb[0] = MBC_SEND_LFA_COMMAND;
860fcf3ce44SJohn Forte 	mcp->mb[1] = (uint16_t)(size >> 1);
861fcf3ce44SJohn Forte 	mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
862fcf3ce44SJohn Forte 	mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
863fcf3ce44SJohn Forte 	mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
864fcf3ce44SJohn Forte 	mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
865fcf3ce44SJohn Forte 	mcp->in_mb = MBX_0;
866fcf3ce44SJohn Forte 	mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
867fcf3ce44SJohn Forte 	if (ha->flags & VP_ENABLED) {
868fcf3ce44SJohn Forte 		mcp->mb[9] = ha->vp_index;
869fcf3ce44SJohn Forte 		mcp->out_mb |= MBX_9;
870fcf3ce44SJohn Forte 	}
871fcf3ce44SJohn Forte 	mcp->timeout = MAILBOX_TOV;
872fcf3ce44SJohn Forte 	rval = ql_mailbox_command(ha, mcp);
873fcf3ce44SJohn Forte 
874fcf3ce44SJohn Forte 	ql_free_dma_resource(ha, &mem_desc);
875fcf3ce44SJohn Forte 
876fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
877fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
878fcf3ce44SJohn Forte 	} else {
879fcf3ce44SJohn Forte 		/*EMPTY*/
880fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
881fcf3ce44SJohn Forte 	}
882fcf3ce44SJohn Forte 
883fcf3ce44SJohn Forte 	return (rval);
884fcf3ce44SJohn Forte }
885fcf3ce44SJohn Forte 
886fcf3ce44SJohn Forte /*
887fcf3ce44SJohn Forte  * ql_clear_aca
888fcf3ce44SJohn Forte  *	Issue clear ACA mailbox command.
889fcf3ce44SJohn Forte  *
890fcf3ce44SJohn Forte  * Input:
891fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
892fcf3ce44SJohn Forte  *	tq:	target queue pointer.
893fcf3ce44SJohn Forte  *	lun:	LUN.
894fcf3ce44SJohn Forte  *
895fcf3ce44SJohn Forte  * Returns:
896fcf3ce44SJohn Forte  *	ql local function return status code.
897fcf3ce44SJohn Forte  *
898fcf3ce44SJohn Forte  * Context:
899fcf3ce44SJohn Forte  *	Kernel context.
900fcf3ce44SJohn Forte  */
901fcf3ce44SJohn Forte int
ql_clear_aca(ql_adapter_state_t * ha,ql_tgt_t * tq,uint16_t lun)902fcf3ce44SJohn Forte ql_clear_aca(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
903fcf3ce44SJohn Forte {
904fcf3ce44SJohn Forte 	int		rval;
905fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
906fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
907fcf3ce44SJohn Forte 
908fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
909fcf3ce44SJohn Forte 
910eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_24258081)) {
911fcf3ce44SJohn Forte 		rval = ql_task_mgmt_iocb(ha, tq, lun, CF_CLEAR_ACA, 0);
912fcf3ce44SJohn Forte 	} else {
913fcf3ce44SJohn Forte 		mcp->mb[0] = MBC_CLEAR_ACA;
914fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
915fcf3ce44SJohn Forte 			mcp->mb[1] = tq->loop_id;
916fcf3ce44SJohn Forte 		} else {
917fcf3ce44SJohn Forte 			mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
918fcf3ce44SJohn Forte 		}
919fcf3ce44SJohn Forte 		mcp->mb[2] = lun;
920fcf3ce44SJohn Forte 		mcp->out_mb = MBX_2|MBX_1|MBX_0;
921fcf3ce44SJohn Forte 		mcp->in_mb = MBX_0;
922fcf3ce44SJohn Forte 		mcp->timeout = MAILBOX_TOV;
923fcf3ce44SJohn Forte 		rval = ql_mailbox_command(ha, mcp);
924fcf3ce44SJohn Forte 	}
925fcf3ce44SJohn Forte 
926fcf3ce44SJohn Forte 	(void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
927fcf3ce44SJohn Forte 
928fcf3ce44SJohn Forte 	if (rval != QL_SUCCESS) {
929fcf3ce44SJohn Forte 		EL(ha, "failed, rval = %xh\n", rval);
930fcf3ce44SJohn Forte 	} else {
931fcf3ce44SJohn Forte 		/*EMPTY*/
932fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
933fcf3ce44SJohn Forte 	}
934fcf3ce44SJohn Forte 
935fcf3ce44SJohn Forte 	return (rval);
936fcf3ce44SJohn Forte }
937fcf3ce44SJohn Forte 
938fcf3ce44SJohn Forte /*
939fcf3ce44SJohn Forte  * ql_target_reset
940fcf3ce44SJohn Forte  *	Issue target reset mailbox command.
941fcf3ce44SJohn Forte  *
942fcf3ce44SJohn Forte  * Input:
943fcf3ce44SJohn Forte  *	ha:	adapter state pointer.
944fcf3ce44SJohn Forte  *	tq:	target queue pointer.
945fcf3ce44SJohn Forte  *	delay:	seconds.
946fcf3ce44SJohn Forte  *
947fcf3ce44SJohn Forte  * Returns:
948fcf3ce44SJohn Forte  *	ql local function return status code.
949fcf3ce44SJohn Forte  *
950fcf3ce44SJohn Forte  * Context:
951fcf3ce44SJohn Forte  *	Kernel context.
952fcf3ce44SJohn Forte  */
953fcf3ce44SJohn Forte int
ql_target_reset(ql_adapter_state_t * ha,ql_tgt_t * tq,uint16_t delay)954fcf3ce44SJohn Forte ql_target_reset(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t delay)
955fcf3ce44SJohn Forte {
956fcf3ce44SJohn Forte 	ql_link_t	*link;
957fcf3ce44SJohn Forte 	uint16_t	index;
958fcf3ce44SJohn Forte 	int		rval;
959fcf3ce44SJohn Forte 	mbx_cmd_t	mc = {0};
960fcf3ce44SJohn Forte 	mbx_cmd_t	*mcp = &mc;
961fcf3ce44SJohn Forte 
962fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
963fcf3ce44SJohn Forte 
964eb82ff87SDaniel Beauregard 	if (CFG_IST(ha, CFG_CTRL_24258081)) {
965fcf3ce44SJohn Forte 		/* queue = NULL, all targets. */
966fcf3ce44SJohn Forte 		if (tq == NULL) {
967fcf3ce44SJohn Forte 			for (index = 0; index < DEVICE_HEAD_LIST_SIZE;
968fcf3ce44SJohn Forte 			    index++) {
969fcf3ce44SJohn Forte 				for (link = ha->dev[index].first; link !=
970fcf3ce44SJohn Forte 				    NULL; link = link->next) {
971fcf3ce44SJohn Forte 					tq = link->base_address;
972fcf3ce44SJohn Forte 					if (!VALID_DEVICE_ID(ha,
973fcf3ce44SJohn Forte 					    tq->loop_id)) {
974fcf3ce44SJohn Forte 						continue;
975fcf3ce44SJohn Forte 					}
976c1fad183SDaniel Beauregard 
977c1fad183SDaniel Beauregard 					if (CFG_IST(ha, CFG_FAST_TIMEOUT)) {
978c1fad183SDaniel Beauregard 						rval = ql_task_mgmt_iocb(ha,
979c1fad183SDaniel Beauregard 						    tq, 0, CF_DO_NOT_SEND |
980c1fad183SDaniel Beauregard 						    CF_TARGET_RESET, delay);
981c1fad183SDaniel Beauregard 					} else {
982c1fad183SDaniel Beauregard 						rval = ql_task_mgmt_iocb(ha,
983c1fad183SDaniel Beauregard 						    tq, 0, CF_TARGET_RESET,
984c1fad183SDaniel Beauregard 						    delay);
985c1fad183SDaniel Beauregard 					}
986fcf3ce44SJohn Forte 
987fcf3ce44SJohn Forte 					if (rval != QL_SUCCESS) {
988fcf3ce44SJohn Forte 						break;
989fcf3ce44SJohn Forte 					}
990fcf3ce44SJohn Forte 				}
991fcf3ce44SJohn Forte 
992fcf3ce44SJohn Forte 				if (link != NULL) {
993fcf3ce44SJohn Forte 					break;
994fcf3ce44SJohn Forte 				}
995fcf3ce44SJohn Forte 			}
996fcf3ce44SJohn Forte 			tq = NULL;
997fcf3ce44SJohn Forte 		} else {
998c1fad183SDaniel Beauregard 
999c1fad183SDaniel Beauregard 			if (CFG_IST(ha, CFG_FAST_TIMEOUT)) {
1000c1fad183SDaniel Beauregard 				rval = ql_task_mgmt_iocb(ha, tq, 0,
1001c1fad183SDaniel Beauregard 				    CF_TARGET_RESET | CF_DO_NOT_SEND, delay);
1002c1fad183SDaniel Beauregard 			} else {
1003c1fad183SDaniel Beauregard 				rval = ql_task_mgmt_iocb(ha, tq, 0,
1004c1fad183SDaniel Beauregard 				    CF_TARGET_RESET, delay);
1005c1fad183SDaniel Beauregard 			}
1006fcf3ce44SJohn Forte 		}
1007fcf3ce44SJohn Forte 	} else {
1008fcf3ce44SJohn Forte 		/* queue = NULL, all targets. */
1009fcf3ce44SJohn Forte 		if (tq == NULL) {
1010fcf3ce44SJohn Forte 			mcp->mb[0] = MBC_RESET;
1011fcf3ce44SJohn Forte 			mcp->mb[1] = delay;
1012fcf3ce44SJohn Forte 			mcp->out_mb = MBX_1|MBX_0;
1013fcf3ce44SJohn Forte 		} else {
1014fcf3ce44SJohn Forte 			mcp->