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 
22*16dd44c2SDaniel Beauregard /* Copyright 2009 QLogic Corporation */
23fcf3ce44SJohn Forte 
24fcf3ce44SJohn Forte /*
25*16dd44c2SDaniel Beauregard  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
26fcf3ce44SJohn Forte  * Use is subject to license terms.
27fcf3ce44SJohn Forte  */
28fcf3ce44SJohn Forte 
29*16dd44c2SDaniel Beauregard #pragma ident	"Copyright 2009 QLogic Corporation; ql_isr.c"
30fcf3ce44SJohn Forte 
31fcf3ce44SJohn Forte /*
32fcf3ce44SJohn Forte  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
33fcf3ce44SJohn Forte  *
34fcf3ce44SJohn Forte  * ***********************************************************************
35fcf3ce44SJohn Forte  * *									**
36fcf3ce44SJohn Forte  * *				NOTICE					**
37*16dd44c2SDaniel Beauregard  * *		COPYRIGHT (C) 1996-2009 QLOGIC CORPORATION		**
38fcf3ce44SJohn Forte  * *			ALL RIGHTS RESERVED				**
39fcf3ce44SJohn Forte  * *									**
40fcf3ce44SJohn Forte  * ***********************************************************************
41fcf3ce44SJohn Forte  *
42fcf3ce44SJohn Forte  */
43fcf3ce44SJohn Forte 
44fcf3ce44SJohn Forte #include <ql_apps.h>
45fcf3ce44SJohn Forte #include <ql_api.h>
46fcf3ce44SJohn Forte #include <ql_debug.h>
47fcf3ce44SJohn Forte #include <ql_iocb.h>
48fcf3ce44SJohn Forte #include <ql_isr.h>
49fcf3ce44SJohn Forte #include <ql_init.h>
50fcf3ce44SJohn Forte #include <ql_mbx.h>
51fcf3ce44SJohn Forte #include <ql_xioctl.h>
52fcf3ce44SJohn Forte 
53fcf3ce44SJohn Forte /*
54fcf3ce44SJohn Forte  * Local Function Prototypes.
55fcf3ce44SJohn Forte  */
56*16dd44c2SDaniel Beauregard static void ql_handle_uncommon_risc_intr(ql_adapter_state_t *, uint32_t,
57*16dd44c2SDaniel Beauregard     uint32_t *);
58fcf3ce44SJohn Forte static void ql_spurious_intr(ql_adapter_state_t *, int);
59fcf3ce44SJohn Forte static void ql_mbx_completion(ql_adapter_state_t *, uint16_t, uint32_t *,
60fcf3ce44SJohn Forte     uint32_t *, int);
61fcf3ce44SJohn Forte static void ql_async_event(ql_adapter_state_t *, uint32_t, ql_head_t *,
62fcf3ce44SJohn Forte     uint32_t *, uint32_t *, int);
63fcf3ce44SJohn Forte static void ql_fast_fcp_post(ql_srb_t *);
64fcf3ce44SJohn Forte static void ql_response_pkt(ql_adapter_state_t *, ql_head_t *, uint32_t *,
65fcf3ce44SJohn Forte     uint32_t *, int);
66fcf3ce44SJohn Forte static void ql_error_entry(ql_adapter_state_t *, response_t *, ql_head_t *,
67fcf3ce44SJohn Forte     uint32_t *, uint32_t *);
68fcf3ce44SJohn Forte static int ql_status_entry(ql_adapter_state_t *, sts_entry_t *, ql_head_t *,
69fcf3ce44SJohn Forte     uint32_t *, uint32_t *);
70fcf3ce44SJohn Forte static int ql_24xx_status_entry(ql_adapter_state_t *, sts_24xx_entry_t *,
71fcf3ce44SJohn Forte     ql_head_t *, uint32_t *, uint32_t *);
72fcf3ce44SJohn Forte static int ql_status_error(ql_adapter_state_t *, ql_srb_t *, sts_entry_t *,
73fcf3ce44SJohn Forte     ql_head_t *, uint32_t *, uint32_t *);
74fcf3ce44SJohn Forte static void ql_status_cont_entry(ql_adapter_state_t *, sts_cont_entry_t *,
75fcf3ce44SJohn Forte     ql_head_t *, uint32_t *, uint32_t *);
76fcf3ce44SJohn Forte static void ql_immediate_notify_entry(ql_adapter_state_t *,
77fcf3ce44SJohn Forte     immediate_notify_entry_t *, ql_head_t *, uint32_t *, uint32_t *);
78fcf3ce44SJohn Forte static void ql_notify_acknowledge_entry(ql_adapter_state_t *,
79fcf3ce44SJohn Forte     notify_acknowledge_entry_t *, ql_head_t *, uint32_t *, uint32_t *);
80fcf3ce44SJohn Forte static void ql_accept_target_io_entry(ql_adapter_state_t *,
81fcf3ce44SJohn Forte     atio_entry_t *, ql_head_t *, uint32_t *, uint32_t *);
82fcf3ce44SJohn Forte static void ql_continue_target_io_entry(ql_adapter_state_t *,
83fcf3ce44SJohn Forte     ctio_entry_t *, ql_head_t *, uint32_t *, uint32_t *);
84fcf3ce44SJohn Forte static void ql_ip_entry(ql_adapter_state_t *, ip_entry_t *, ql_head_t *,
85fcf3ce44SJohn Forte     uint32_t *, uint32_t *);
86fcf3ce44SJohn Forte static void ql_ip_rcv_entry(ql_adapter_state_t *, ip_rcv_entry_t *,
87fcf3ce44SJohn Forte     ql_head_t *, uint32_t *, uint32_t *);
88fcf3ce44SJohn Forte static void ql_ip_rcv_cont_entry(ql_adapter_state_t *,
89fcf3ce44SJohn Forte     ip_rcv_cont_entry_t *, ql_head_t *, uint32_t *, uint32_t *);
90fcf3ce44SJohn Forte static void ql_ip_24xx_rcv_entry(ql_adapter_state_t *, ip_rcv_24xx_entry_t *,
91fcf3ce44SJohn Forte     ql_head_t *, uint32_t *, uint32_t *);
92fcf3ce44SJohn Forte static void ql_ms_entry(ql_adapter_state_t *, ms_entry_t *, ql_head_t *,
93fcf3ce44SJohn Forte     uint32_t *, uint32_t *);
94fcf3ce44SJohn Forte static void ql_report_id_entry(ql_adapter_state_t *, report_id_1_t *,
95fcf3ce44SJohn Forte     ql_head_t *, uint32_t *, uint32_t *);
96fcf3ce44SJohn Forte 
97fcf3ce44SJohn Forte /* TODO: temporary define until defined in LV */
98fcf3ce44SJohn Forte #ifndef FC_STATE_8GBIT_SPEED
99fcf3ce44SJohn Forte #define	FC_STATE_8GBIT_SPEED		0x0700	/* 8 Gbit/sec */
100fcf3ce44SJohn Forte #endif
101fcf3ce44SJohn Forte 
102fcf3ce44SJohn Forte /*
103fcf3ce44SJohn Forte  * ql_isr
104fcf3ce44SJohn Forte  *	Process all INTX intr types.
105fcf3ce44SJohn Forte  *
106fcf3ce44SJohn Forte  * Input:
107fcf3ce44SJohn Forte  *	arg1:	adapter state pointer.
108fcf3ce44SJohn Forte  *
109fcf3ce44SJohn Forte  * Returns:
110fcf3ce44SJohn Forte  *	DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
111fcf3ce44SJohn Forte  *
112fcf3ce44SJohn Forte  * Context:
113fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
114fcf3ce44SJohn Forte  */
115fcf3ce44SJohn Forte /* ARGSUSED */
116fcf3ce44SJohn Forte uint_t
117fcf3ce44SJohn Forte ql_isr(caddr_t arg1)
118fcf3ce44SJohn Forte {
119fcf3ce44SJohn Forte 	return (ql_isr_aif(arg1, 0));
120fcf3ce44SJohn Forte }
121fcf3ce44SJohn Forte 
122fcf3ce44SJohn Forte /*
123fcf3ce44SJohn Forte  * ql_isr_default
124fcf3ce44SJohn Forte  *	Process unknown/unvectored intr types
125fcf3ce44SJohn Forte  *
126fcf3ce44SJohn Forte  * Input:
127fcf3ce44SJohn Forte  *	arg1:	adapter state pointer.
128fcf3ce44SJohn Forte  *	arg2:	interrupt vector.
129fcf3ce44SJohn Forte  *
130fcf3ce44SJohn Forte  * Returns:
131fcf3ce44SJohn Forte  *	DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
132fcf3ce44SJohn Forte  *
133fcf3ce44SJohn Forte  * Context:
134fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
135fcf3ce44SJohn Forte  */
136fcf3ce44SJohn Forte /* ARGSUSED */
137fcf3ce44SJohn Forte uint_t
138fcf3ce44SJohn Forte ql_isr_default(caddr_t arg1, caddr_t arg2)
139fcf3ce44SJohn Forte {
140fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = (void *)arg1;
141fcf3ce44SJohn Forte 
142fcf3ce44SJohn Forte 	EL(ha, "isr_default called: idx=%x\n", arg2);
143fcf3ce44SJohn Forte 	return (ql_isr_aif(arg1, arg2));
144fcf3ce44SJohn Forte }
145fcf3ce44SJohn Forte 
146fcf3ce44SJohn Forte /*
147fcf3ce44SJohn Forte  * ql_isr_aif
148fcf3ce44SJohn Forte  *	Process mailbox and I/O command completions.
149fcf3ce44SJohn Forte  *
150fcf3ce44SJohn Forte  * Input:
151fcf3ce44SJohn Forte  *	arg:	adapter state pointer.
152fcf3ce44SJohn Forte  *	intvec:	interrupt vector.
153fcf3ce44SJohn Forte  *
154fcf3ce44SJohn Forte  * Returns:
155fcf3ce44SJohn Forte  *	DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
156fcf3ce44SJohn Forte  *
157fcf3ce44SJohn Forte  * Context:
158fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
159fcf3ce44SJohn Forte  */
160fcf3ce44SJohn Forte /* ARGSUSED */
161fcf3ce44SJohn Forte uint_t
162fcf3ce44SJohn Forte ql_isr_aif(caddr_t arg, caddr_t intvec)
163fcf3ce44SJohn Forte {
164fcf3ce44SJohn Forte 	uint16_t		mbx;
165fcf3ce44SJohn Forte 	uint32_t		stat;
166fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = (void *)arg;
167fcf3ce44SJohn Forte 	uint32_t		set_flags = 0;
168fcf3ce44SJohn Forte 	uint32_t		reset_flags = 0;
169fcf3ce44SJohn Forte 	ql_head_t		isr_done_q = {NULL, NULL};
170fcf3ce44SJohn Forte 	uint_t			rval = DDI_INTR_UNCLAIMED;
171fcf3ce44SJohn Forte 	int			spurious_intr = 0;
172fcf3ce44SJohn Forte 	boolean_t		intr = B_FALSE, daemon = B_FALSE;
173fcf3ce44SJohn Forte 	int			intr_loop = 4;
174fcf3ce44SJohn Forte 
175fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
176fcf3ce44SJohn Forte 
177fcf3ce44SJohn Forte 	QL_PM_LOCK(ha);
178fcf3ce44SJohn Forte 	if (ha->power_level != PM_LEVEL_D0) {
179fcf3ce44SJohn Forte 		/*
180fcf3ce44SJohn Forte 		 * Looks like we are about to go down soon, exit early.
181fcf3ce44SJohn Forte 		 */
182fcf3ce44SJohn Forte 		QL_PM_UNLOCK(ha);
183fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): power down exit\n", ha->instance);
184fcf3ce44SJohn Forte 		return (DDI_INTR_UNCLAIMED);
185fcf3ce44SJohn Forte 	}
186fcf3ce44SJohn Forte 	ha->busy++;
187fcf3ce44SJohn Forte 	QL_PM_UNLOCK(ha);
188fcf3ce44SJohn Forte 
189fcf3ce44SJohn Forte 	/* Acquire interrupt lock. */
190fcf3ce44SJohn Forte 	INTR_LOCK(ha);
191fcf3ce44SJohn Forte 
192fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_CTRL_2200)) {
193fcf3ce44SJohn Forte 		while (RD16_IO_REG(ha, istatus) & RISC_INT) {
194fcf3ce44SJohn Forte 			/* Reset idle timer. */
195fcf3ce44SJohn Forte 			ha->idle_timer = 0;
196fcf3ce44SJohn Forte 			rval = DDI_INTR_CLAIMED;
197fcf3ce44SJohn Forte 			if (intr_loop) {
198fcf3ce44SJohn Forte 				intr_loop--;
199fcf3ce44SJohn Forte 			}
200fcf3ce44SJohn Forte 
201fcf3ce44SJohn Forte 			/* Special Fast Post 2200. */
202fcf3ce44SJohn Forte 			stat = 0;
203fcf3ce44SJohn Forte 			if (ha->task_daemon_flags & FIRMWARE_LOADED &&
204fcf3ce44SJohn Forte 			    ha->flags & ONLINE) {
205fcf3ce44SJohn Forte 				ql_srb_t	*sp;
206fcf3ce44SJohn Forte 
207fcf3ce44SJohn Forte 				mbx = RD16_IO_REG(ha, mailbox[23]);
208fcf3ce44SJohn Forte 
209fcf3ce44SJohn Forte 				if ((mbx & 3) == MBX23_SCSI_COMPLETION) {
210fcf3ce44SJohn Forte 					/* Release mailbox registers. */
211fcf3ce44SJohn Forte 					WRT16_IO_REG(ha, semaphore, 0);
212fcf3ce44SJohn Forte 
213fcf3ce44SJohn Forte 					if (intr_loop) {
214fcf3ce44SJohn Forte 						WRT16_IO_REG(ha, hccr,
215fcf3ce44SJohn Forte 						    HC_CLR_RISC_INT);
216fcf3ce44SJohn Forte 					}
217fcf3ce44SJohn Forte 
218fcf3ce44SJohn Forte 					/* Get handle. */
219fcf3ce44SJohn Forte 					mbx >>= 4;
220fcf3ce44SJohn Forte 					stat = mbx & OSC_INDEX_MASK;
221fcf3ce44SJohn Forte 
222fcf3ce44SJohn Forte 					/* Validate handle. */
223fcf3ce44SJohn Forte 					sp = stat < MAX_OUTSTANDING_COMMANDS ?
224fcf3ce44SJohn Forte 					    ha->outstanding_cmds[stat] : NULL;
225fcf3ce44SJohn Forte 
226fcf3ce44SJohn Forte 					if (sp != NULL && (sp->handle & 0xfff)
227fcf3ce44SJohn Forte 					    == mbx) {
228fcf3ce44SJohn Forte 						ha->outstanding_cmds[stat] =
229fcf3ce44SJohn Forte 						    NULL;
230fcf3ce44SJohn Forte 						sp->handle = 0;
231fcf3ce44SJohn Forte 						sp->flags &=
232fcf3ce44SJohn Forte 						    ~SRB_IN_TOKEN_ARRAY;
233fcf3ce44SJohn Forte 
234fcf3ce44SJohn Forte 						/* Set completed status. */
235fcf3ce44SJohn Forte 						sp->flags |= SRB_ISP_COMPLETED;
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte 						/* Set completion status */
238fcf3ce44SJohn Forte 						sp->pkt->pkt_reason =
239fcf3ce44SJohn Forte 						    CS_COMPLETE;
240fcf3ce44SJohn Forte 
241fcf3ce44SJohn Forte 						ql_fast_fcp_post(sp);
242fcf3ce44SJohn Forte 					} else if (mbx !=
243fcf3ce44SJohn Forte 					    (QL_FCA_BRAND & 0xfff)) {
244fcf3ce44SJohn Forte 						if (sp == NULL) {
245fcf3ce44SJohn Forte 							EL(ha, "unknown IOCB"
246fcf3ce44SJohn Forte 							    " handle=%xh\n",
247fcf3ce44SJohn Forte 							    mbx);
248fcf3ce44SJohn Forte 						} else {
249fcf3ce44SJohn Forte 							EL(ha, "mismatch IOCB"
250fcf3ce44SJohn Forte 							    " handle pkt=%xh, "
251fcf3ce44SJohn Forte 							    "sp=%xh\n", mbx,
252fcf3ce44SJohn Forte 							    sp->handle & 0xfff);
253fcf3ce44SJohn Forte 						}
254fcf3ce44SJohn Forte 
255fcf3ce44SJohn Forte 						(void) ql_binary_fw_dump(ha,
256fcf3ce44SJohn Forte 						    FALSE);
257fcf3ce44SJohn Forte 
258fcf3ce44SJohn Forte 						if (!(ha->task_daemon_flags &
259fcf3ce44SJohn Forte 						    (ISP_ABORT_NEEDED |
260fcf3ce44SJohn Forte 						    ABORT_ISP_ACTIVE))) {
261fcf3ce44SJohn Forte 							EL(ha, "ISP Invalid "
262fcf3ce44SJohn Forte 							    "handle, "
263fcf3ce44SJohn Forte 							    "isp_abort_needed"
264fcf3ce44SJohn Forte 							    "\n");
265fcf3ce44SJohn Forte 							set_flags |=
266fcf3ce44SJohn Forte 							    ISP_ABORT_NEEDED;
267fcf3ce44SJohn Forte 						}
268fcf3ce44SJohn Forte 					}
269fcf3ce44SJohn Forte 				}
270fcf3ce44SJohn Forte 			}
271fcf3ce44SJohn Forte 
272fcf3ce44SJohn Forte 			if (stat == 0) {
273fcf3ce44SJohn Forte 				/* Check for mailbox interrupt. */
274fcf3ce44SJohn Forte 				mbx = RD16_IO_REG(ha, semaphore);
275fcf3ce44SJohn Forte 				if (mbx & BIT_0) {
276fcf3ce44SJohn Forte 					/* Release mailbox registers. */
277fcf3ce44SJohn Forte 					WRT16_IO_REG(ha, semaphore, 0);
278fcf3ce44SJohn Forte 
279fcf3ce44SJohn Forte 					/* Get mailbox data. */
280fcf3ce44SJohn Forte 					mbx = RD16_IO_REG(ha, mailbox[0]);
281fcf3ce44SJohn Forte 					if (mbx > 0x3fff && mbx < 0x8000) {
282fcf3ce44SJohn Forte 						ql_mbx_completion(ha, mbx,
283fcf3ce44SJohn Forte 						    &set_flags, &reset_flags,
284fcf3ce44SJohn Forte 						    intr_loop);
285fcf3ce44SJohn Forte 					} else if (mbx > 0x7fff &&
286fcf3ce44SJohn Forte 					    mbx < 0xc000) {
287fcf3ce44SJohn Forte 						ql_async_event(ha, mbx,
288fcf3ce44SJohn Forte 						    &isr_done_q, &set_flags,
289fcf3ce44SJohn Forte 						    &reset_flags, intr_loop);
290fcf3ce44SJohn Forte 					} else {
291fcf3ce44SJohn Forte 						EL(ha, "UNKNOWN interrupt "
292fcf3ce44SJohn Forte 						    "type\n");
293fcf3ce44SJohn Forte 						intr = B_TRUE;
294fcf3ce44SJohn Forte 					}
295fcf3ce44SJohn Forte 				} else {
296fcf3ce44SJohn Forte 					ha->isp_rsp_index = RD16_IO_REG(ha,
297fcf3ce44SJohn Forte 					    resp_in);
298fcf3ce44SJohn Forte 
299fcf3ce44SJohn Forte 					if (ha->isp_rsp_index !=
300fcf3ce44SJohn Forte 					    ha->rsp_ring_index) {
301fcf3ce44SJohn Forte 						ql_response_pkt(ha,
302fcf3ce44SJohn Forte 						    &isr_done_q, &set_flags,
303fcf3ce44SJohn Forte 						    &reset_flags, intr_loop);
304fcf3ce44SJohn Forte 					} else if (++spurious_intr ==
305fcf3ce44SJohn Forte 					    MAX_SPURIOUS_INTR) {
306fcf3ce44SJohn Forte 						/*
307fcf3ce44SJohn Forte 						 * Process excessive
308fcf3ce44SJohn Forte 						 * spurious intrrupts
309fcf3ce44SJohn Forte 						 */
310fcf3ce44SJohn Forte 						ql_spurious_intr(ha,
311fcf3ce44SJohn Forte 						    intr_loop);
312fcf3ce44SJohn Forte 						EL(ha, "excessive spurious "
313fcf3ce44SJohn Forte 						    "interrupts, "
314fcf3ce44SJohn Forte 						    "isp_abort_needed\n");
315fcf3ce44SJohn Forte 						set_flags |= ISP_ABORT_NEEDED;
316fcf3ce44SJohn Forte 					} else {
317fcf3ce44SJohn Forte 						intr = B_TRUE;
318fcf3ce44SJohn Forte 					}
319fcf3ce44SJohn Forte 				}
320fcf3ce44SJohn Forte 			}
321fcf3ce44SJohn Forte 
322fcf3ce44SJohn Forte 			/* Clear RISC interrupt */
323fcf3ce44SJohn Forte 			if (intr || intr_loop == 0) {
324fcf3ce44SJohn Forte 				intr = B_FALSE;
325fcf3ce44SJohn Forte 				WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
326fcf3ce44SJohn Forte 			}
327fcf3ce44SJohn Forte 
328fcf3ce44SJohn Forte 			if (set_flags != 0 || reset_flags != 0) {
329fcf3ce44SJohn Forte 				TASK_DAEMON_LOCK(ha);
330fcf3ce44SJohn Forte 				ha->task_daemon_flags |= set_flags;
331fcf3ce44SJohn Forte 				ha->task_daemon_flags &= ~reset_flags;
332fcf3ce44SJohn Forte 				TASK_DAEMON_UNLOCK(ha);
333fcf3ce44SJohn Forte 				set_flags = 0;
334fcf3ce44SJohn Forte 				reset_flags = 0;
335fcf3ce44SJohn Forte 				daemon = B_TRUE;
336fcf3ce44SJohn Forte 			}
337fcf3ce44SJohn Forte 		}
338fcf3ce44SJohn Forte 	} else {
339*16dd44c2SDaniel Beauregard 		while ((stat = RD32_IO_REG(ha, intr_info_lo)) & RH_RISC_INT) {
340*16dd44c2SDaniel Beauregard 			/* Capture FW defined interrupt info */
341fcf3ce44SJohn Forte 			mbx = MSW(stat);
342fcf3ce44SJohn Forte 
343fcf3ce44SJohn Forte 			/* Reset idle timer. */
344fcf3ce44SJohn Forte 			ha->idle_timer = 0;
345fcf3ce44SJohn Forte 			rval = DDI_INTR_CLAIMED;
346fcf3ce44SJohn Forte 			if (intr_loop) {
347fcf3ce44SJohn Forte 				intr_loop--;
348fcf3ce44SJohn Forte 			}
349fcf3ce44SJohn Forte 
350fcf3ce44SJohn Forte 			switch (stat & 0x1ff) {
351fcf3ce44SJohn Forte 			case ROM_MBX_SUCCESS:
352fcf3ce44SJohn Forte 			case ROM_MBX_ERR:
353fcf3ce44SJohn Forte 				ql_mbx_completion(ha, mbx, &set_flags,
354fcf3ce44SJohn Forte 				    &reset_flags, intr_loop);
355fcf3ce44SJohn Forte 
356fcf3ce44SJohn Forte 				/* Release mailbox registers. */
357fcf3ce44SJohn Forte 				if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) {
358fcf3ce44SJohn Forte 					WRT16_IO_REG(ha, semaphore, 0);
359fcf3ce44SJohn Forte 				}
360fcf3ce44SJohn Forte 				break;
361fcf3ce44SJohn Forte 
362fcf3ce44SJohn Forte 			case MBX_SUCCESS:
363fcf3ce44SJohn Forte 			case MBX_ERR:
364fcf3ce44SJohn Forte 				/* Sun FW, Release mailbox registers. */
365fcf3ce44SJohn Forte 				if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) {
366fcf3ce44SJohn Forte 					WRT16_IO_REG(ha, semaphore, 0);
367fcf3ce44SJohn Forte 				}
368fcf3ce44SJohn Forte 				ql_mbx_completion(ha, mbx, &set_flags,
369fcf3ce44SJohn Forte 				    &reset_flags, intr_loop);
370fcf3ce44SJohn Forte 				break;
371fcf3ce44SJohn Forte 
372fcf3ce44SJohn Forte 			case ASYNC_EVENT:
373fcf3ce44SJohn Forte 				/* Sun FW, Release mailbox registers. */
374fcf3ce44SJohn Forte 				if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) {
375fcf3ce44SJohn Forte 					WRT16_IO_REG(ha, semaphore, 0);
376fcf3ce44SJohn Forte 				}
377fcf3ce44SJohn Forte 				ql_async_event(ha, (uint32_t)mbx, &isr_done_q,
378fcf3ce44SJohn Forte 				    &set_flags, &reset_flags, intr_loop);
379fcf3ce44SJohn Forte 				break;
380fcf3ce44SJohn Forte 
381fcf3ce44SJohn Forte 			case RESP_UPDATE:
382fcf3ce44SJohn Forte 				if (mbx != ha->rsp_ring_index) {
383fcf3ce44SJohn Forte 					ha->isp_rsp_index = mbx;
384fcf3ce44SJohn Forte 					ql_response_pkt(ha, &isr_done_q,
385fcf3ce44SJohn Forte 					    &set_flags, &reset_flags,
386fcf3ce44SJohn Forte 					    intr_loop);
387fcf3ce44SJohn Forte 				} else if (++spurious_intr ==
388fcf3ce44SJohn Forte 				    MAX_SPURIOUS_INTR) {
389fcf3ce44SJohn Forte 					/* Process excessive spurious intr. */
390fcf3ce44SJohn Forte 					ql_spurious_intr(ha, intr_loop);
391fcf3ce44SJohn Forte 					EL(ha, "excessive spurious "
392fcf3ce44SJohn Forte 					    "interrupts, isp_abort_needed\n");
393fcf3ce44SJohn Forte 					set_flags |= ISP_ABORT_NEEDED;
394fcf3ce44SJohn Forte 				} else {
395fcf3ce44SJohn Forte 					intr = B_TRUE;
396fcf3ce44SJohn Forte 				}
397fcf3ce44SJohn Forte 				break;
398fcf3ce44SJohn Forte 
399fcf3ce44SJohn Forte 			case SCSI_FAST_POST_16:
400fcf3ce44SJohn Forte 				stat = (stat & 0xffff0000) | MBA_CMPLT_1_16BIT;
401fcf3ce44SJohn Forte 				ql_async_event(ha, stat, &isr_done_q,
402fcf3ce44SJohn Forte 				    &set_flags, &reset_flags, intr_loop);
403fcf3ce44SJohn Forte 				break;
404fcf3ce44SJohn Forte 
405fcf3ce44SJohn Forte 			case SCSI_FAST_POST_32:
406fcf3ce44SJohn Forte 				stat = (stat & 0xffff0000) | MBA_CMPLT_1_32BIT;
407fcf3ce44SJohn Forte 				ql_async_event(ha, stat, &isr_done_q,
408fcf3ce44SJohn Forte 				    &set_flags, &reset_flags, intr_loop);
409fcf3ce44SJohn Forte 				break;
410fcf3ce44SJohn Forte 
411fcf3ce44SJohn Forte 			case CTIO_FAST_POST:
412fcf3ce44SJohn Forte 				stat = (stat & 0xffff0000) |
413fcf3ce44SJohn Forte 				    MBA_CTIO_COMPLETION;
414fcf3ce44SJohn Forte 				ql_async_event(ha, stat, &isr_done_q,
415fcf3ce44SJohn Forte 				    &set_flags, &reset_flags, intr_loop);
416fcf3ce44SJohn Forte 				break;
417fcf3ce44SJohn Forte 
418fcf3ce44SJohn Forte 			case IP_FAST_POST_XMT:
419fcf3ce44SJohn Forte 				stat = (stat & 0xffff0000) | MBA_IP_COMPLETION;
420fcf3ce44SJohn Forte 				ql_async_event(ha, stat, &isr_done_q,
421fcf3ce44SJohn Forte 				    &set_flags, &reset_flags, intr_loop);
422fcf3ce44SJohn Forte 				break;
423fcf3ce44SJohn Forte 
424fcf3ce44SJohn Forte 			case IP_FAST_POST_RCV:
425fcf3ce44SJohn Forte 				stat = (stat & 0xffff0000) | MBA_IP_RECEIVE;
426fcf3ce44SJohn Forte 				ql_async_event(ha, stat, &isr_done_q,
427fcf3ce44SJohn Forte 				    &set_flags, &reset_flags, intr_loop);
428fcf3ce44SJohn Forte 				break;
429fcf3ce44SJohn Forte 
430fcf3ce44SJohn Forte 			case IP_FAST_POST_BRD:
431fcf3ce44SJohn Forte 				stat = (stat & 0xffff0000) | MBA_IP_BROADCAST;
432fcf3ce44SJohn Forte 				ql_async_event(ha, stat, &isr_done_q,
433fcf3ce44SJohn Forte 				    &set_flags, &reset_flags, intr_loop);
434fcf3ce44SJohn Forte 				break;
435fcf3ce44SJohn Forte 
436fcf3ce44SJohn Forte 			case IP_FAST_POST_RCV_ALN:
437fcf3ce44SJohn Forte 				stat = (stat & 0xffff0000) |
438fcf3ce44SJohn Forte 				    MBA_IP_HDR_DATA_SPLIT;
439fcf3ce44SJohn Forte 				ql_async_event(ha, stat, &isr_done_q,
440fcf3ce44SJohn Forte 				    &set_flags, &reset_flags, intr_loop);
441fcf3ce44SJohn Forte 				break;
442fcf3ce44SJohn Forte 
443fcf3ce44SJohn Forte 			case ATIO_UPDATE:
444fcf3ce44SJohn Forte 				EL(ha, "unsupported ATIO queue update"
445fcf3ce44SJohn Forte 				    " interrupt, status=%xh\n", stat);
446fcf3ce44SJohn Forte 				intr = B_TRUE;
447fcf3ce44SJohn Forte 				break;
448fcf3ce44SJohn Forte 
449fcf3ce44SJohn Forte 			case ATIO_RESP_UPDATE:
450fcf3ce44SJohn Forte 				EL(ha, "unsupported ATIO response queue "
451fcf3ce44SJohn Forte 				    "update interrupt, status=%xh\n", stat);
452fcf3ce44SJohn Forte 				intr = B_TRUE;
453fcf3ce44SJohn Forte 				break;
454fcf3ce44SJohn Forte 
455fcf3ce44SJohn Forte 			default:
456*16dd44c2SDaniel Beauregard 				ql_handle_uncommon_risc_intr(ha, stat,
457*16dd44c2SDaniel Beauregard 				    &set_flags);
458fcf3ce44SJohn Forte 				intr = B_TRUE;
459fcf3ce44SJohn Forte 				break;
460fcf3ce44SJohn Forte 			}
461fcf3ce44SJohn Forte 
462fcf3ce44SJohn Forte 			/* Clear RISC interrupt */
463fcf3ce44SJohn Forte 			if (intr || intr_loop == 0) {
464fcf3ce44SJohn Forte 				intr = B_FALSE;
465fcf3ce44SJohn Forte 				CFG_IST(ha, CFG_CTRL_2425) ?
466fcf3ce44SJohn Forte 				    WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) :
467fcf3ce44SJohn Forte 				    WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
468fcf3ce44SJohn Forte 			}
469fcf3ce44SJohn Forte 
470fcf3ce44SJohn Forte 			if (set_flags != 0 || reset_flags != 0) {
471fcf3ce44SJohn Forte 				TASK_DAEMON_LOCK(ha);
472fcf3ce44SJohn Forte 				ha->task_daemon_flags |= set_flags;
473fcf3ce44SJohn Forte 				ha->task_daemon_flags &= ~reset_flags;
474fcf3ce44SJohn Forte 				TASK_DAEMON_UNLOCK(ha);
475fcf3ce44SJohn Forte 				set_flags = 0;
476fcf3ce44SJohn Forte 				reset_flags = 0;
477fcf3ce44SJohn Forte 				daemon = B_TRUE;
478fcf3ce44SJohn Forte 			}
479fcf3ce44SJohn Forte 
480fcf3ce44SJohn Forte 			if (ha->flags & PARITY_ERROR) {
481fcf3ce44SJohn Forte 				EL(ha, "parity/pause exit\n");
482fcf3ce44SJohn Forte 				mbx = RD16_IO_REG(ha, hccr); /* PCI posting */
483fcf3ce44SJohn Forte 				break;
484fcf3ce44SJohn Forte 			}
485fcf3ce44SJohn Forte 		}
486fcf3ce44SJohn Forte 	}
487fcf3ce44SJohn Forte 
488fcf3ce44SJohn Forte 	/* Process claimed interrupts during polls. */
489fcf3ce44SJohn Forte 	if (rval == DDI_INTR_UNCLAIMED && ha->intr_claimed == B_TRUE) {
490fcf3ce44SJohn Forte 		ha->intr_claimed = B_FALSE;
491fcf3ce44SJohn Forte 		rval = DDI_INTR_CLAIMED;
492fcf3ce44SJohn Forte 	}
493fcf3ce44SJohn Forte 
494fcf3ce44SJohn Forte 	/* Release interrupt lock. */
495fcf3ce44SJohn Forte 	INTR_UNLOCK(ha);
496fcf3ce44SJohn Forte 
497fcf3ce44SJohn Forte 	if (daemon) {
498fcf3ce44SJohn Forte 		ql_awaken_task_daemon(ha, NULL, 0, 0);
499fcf3ce44SJohn Forte 	}
500fcf3ce44SJohn Forte 
501fcf3ce44SJohn Forte 	if (isr_done_q.first != NULL) {
502fcf3ce44SJohn Forte 		ql_done(isr_done_q.first);
503fcf3ce44SJohn Forte 	}
504fcf3ce44SJohn Forte 
505fcf3ce44SJohn Forte 	if (rval == DDI_INTR_CLAIMED) {
506fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
507fcf3ce44SJohn Forte 		ha->xioctl->TotalInterrupts++;
508fcf3ce44SJohn Forte 	} else {
509fcf3ce44SJohn Forte 		/*EMPTY*/
510fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): interrupt not claimed\n",
511fcf3ce44SJohn Forte 		    ha->instance);
512fcf3ce44SJohn Forte 	}
513fcf3ce44SJohn Forte 
514fcf3ce44SJohn Forte 	QL_PM_LOCK(ha);
515fcf3ce44SJohn Forte 	ha->busy--;
516fcf3ce44SJohn Forte 	QL_PM_UNLOCK(ha);
517fcf3ce44SJohn Forte 
518fcf3ce44SJohn Forte 	return (rval);
519fcf3ce44SJohn Forte }
520fcf3ce44SJohn Forte 
521*16dd44c2SDaniel Beauregard /*
522*16dd44c2SDaniel Beauregard  * ql_handle_uncommon_risc_intr
523*16dd44c2SDaniel Beauregard  *	Handle an uncommon RISC interrupt.
524*16dd44c2SDaniel Beauregard  *
525*16dd44c2SDaniel Beauregard  * Input:
526*16dd44c2SDaniel Beauregard  *	ha:		adapter state pointer.
527*16dd44c2SDaniel Beauregard  *	stat:		interrupt status
528*16dd44c2SDaniel Beauregard  *
529*16dd44c2SDaniel Beauregard  * Context:
530*16dd44c2SDaniel Beauregard  *	Interrupt or Kernel context, no mailbox commands allowed.
531*16dd44c2SDaniel Beauregard  */
532*16dd44c2SDaniel Beauregard static void
533*16dd44c2SDaniel Beauregard ql_handle_uncommon_risc_intr(ql_adapter_state_t *ha, uint32_t stat,
534*16dd44c2SDaniel Beauregard     uint32_t *set_flags)
535*16dd44c2SDaniel Beauregard {
536*16dd44c2SDaniel Beauregard 	uint16_t	hccr_reg;
537*16dd44c2SDaniel Beauregard 
538*16dd44c2SDaniel Beauregard 	hccr_reg = RD16_IO_REG(ha, hccr);
539*16dd44c2SDaniel Beauregard 
540*16dd44c2SDaniel Beauregard 	if (stat & RH_RISC_PAUSED ||
541*16dd44c2SDaniel Beauregard 	    (hccr_reg & (BIT_15 | BIT_13 | BIT_11 | BIT_8))) {
542*16dd44c2SDaniel Beauregard 
543*16dd44c2SDaniel Beauregard 		ADAPTER_STATE_LOCK(ha);
544*16dd44c2SDaniel Beauregard 		ha->flags |= PARITY_ERROR;
545*16dd44c2SDaniel Beauregard 		ADAPTER_STATE_UNLOCK(ha);
546*16dd44c2SDaniel Beauregard 
547*16dd44c2SDaniel Beauregard 		if (ha->parity_pause_errors == 0 ||
548*16dd44c2SDaniel Beauregard 		    ha->parity_hccr_err != hccr_reg ||
549*16dd44c2SDaniel Beauregard 		    ha->parity_stat_err != stat) {
550*16dd44c2SDaniel Beauregard 			cmn_err(CE_WARN, "qlc(%d): isr, Internal Parity/"
551*16dd44c2SDaniel Beauregard 			    "Pause Error - hccr=%xh, stat=%xh, count=%d",
552*16dd44c2SDaniel Beauregard 			    ha->instance, hccr_reg, stat,
553*16dd44c2SDaniel Beauregard 			    ha->parity_pause_errors);
554*16dd44c2SDaniel Beauregard 			ha->parity_hccr_err = hccr_reg;
555*16dd44c2SDaniel Beauregard 			ha->parity_stat_err = stat;
556*16dd44c2SDaniel Beauregard 		}
557*16dd44c2SDaniel Beauregard 
558*16dd44c2SDaniel Beauregard 		EL(ha, "parity/pause error, isp_abort_needed\n");
559*16dd44c2SDaniel Beauregard 
560*16dd44c2SDaniel Beauregard 		if (ql_binary_fw_dump(ha, FALSE) != QL_SUCCESS) {
561*16dd44c2SDaniel Beauregard 			ql_reset_chip(ha);
562*16dd44c2SDaniel Beauregard 		}
563*16dd44c2SDaniel Beauregard 
564*16dd44c2SDaniel Beauregard 		if (ha->parity_pause_errors == 0) {
565*16dd44c2SDaniel Beauregard 			(void) ql_flash_errlog(ha, FLASH_ERRLOG_PARITY_ERR,
566*16dd44c2SDaniel Beauregard 			    0, MSW(stat), LSW(stat));
567*16dd44c2SDaniel Beauregard 		}
568*16dd44c2SDaniel Beauregard 
569*16dd44c2SDaniel Beauregard 		if (ha->parity_pause_errors < 0xffffffff) {
570*16dd44c2SDaniel Beauregard 			ha->parity_pause_errors++;
571*16dd44c2SDaniel Beauregard 		}
572*16dd44c2SDaniel Beauregard 
573*16dd44c2SDaniel Beauregard 		*set_flags |= ISP_ABORT_NEEDED;
574*16dd44c2SDaniel Beauregard 
575*16dd44c2SDaniel Beauregard 		/* Disable ISP interrupts. */
576*16dd44c2SDaniel Beauregard 		WRT16_IO_REG(ha, ictrl, 0);
577*16dd44c2SDaniel Beauregard 		ADAPTER_STATE_LOCK(ha);
578*16dd44c2SDaniel Beauregard 		ha->flags &= ~INTERRUPTS_ENABLED;
579*16dd44c2SDaniel Beauregard 		ADAPTER_STATE_UNLOCK(ha);
580*16dd44c2SDaniel Beauregard 	} else {
581*16dd44c2SDaniel Beauregard 		EL(ha, "UNKNOWN interrupt status=%xh, hccr=%xh\n",
582*16dd44c2SDaniel Beauregard 		    stat, hccr_reg);
583*16dd44c2SDaniel Beauregard 	}
584*16dd44c2SDaniel Beauregard }
585*16dd44c2SDaniel Beauregard 
586fcf3ce44SJohn Forte /*
587fcf3ce44SJohn Forte  * ql_spurious_intr
588fcf3ce44SJohn Forte  *	Inform Solaris of spurious interrupts.
589fcf3ce44SJohn Forte  *
590fcf3ce44SJohn Forte  * Input:
591fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
592fcf3ce44SJohn Forte  *	intr_clr:	early interrupt clear
593fcf3ce44SJohn Forte  *
594fcf3ce44SJohn Forte  * Context:
595fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
596fcf3ce44SJohn Forte  */
597fcf3ce44SJohn Forte static void
598fcf3ce44SJohn Forte ql_spurious_intr(ql_adapter_state_t *ha, int intr_clr)
599fcf3ce44SJohn Forte {
600fcf3ce44SJohn Forte 	ddi_devstate_t	state;
601fcf3ce44SJohn Forte 
602fcf3ce44SJohn Forte 	EL(ha, "Spurious interrupt\n");
603fcf3ce44SJohn Forte 
604fcf3ce44SJohn Forte 	/* Disable ISP interrupts. */
605fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, ictrl, 0);
606fcf3ce44SJohn Forte 	ADAPTER_STATE_LOCK(ha);
607fcf3ce44SJohn Forte 	ha->flags &= ~INTERRUPTS_ENABLED;
608fcf3ce44SJohn Forte 	ADAPTER_STATE_UNLOCK(ha);
609fcf3ce44SJohn Forte 
610fcf3ce44SJohn Forte 	/* Clear RISC interrupt */
611fcf3ce44SJohn Forte 	if (intr_clr) {
612fcf3ce44SJohn Forte 		CFG_IST(ha, CFG_CTRL_2425) ?
613fcf3ce44SJohn Forte 		    WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) :
614fcf3ce44SJohn Forte 		    WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
615fcf3ce44SJohn Forte 	}
616fcf3ce44SJohn Forte 
617fcf3ce44SJohn Forte 	state = ddi_get_devstate(ha->dip);
618fcf3ce44SJohn Forte 	if (state == DDI_DEVSTATE_UP) {
619fcf3ce44SJohn Forte 		/*EMPTY*/
620fcf3ce44SJohn Forte 		ddi_dev_report_fault(ha->dip, DDI_SERVICE_DEGRADED,
621fcf3ce44SJohn Forte 		    DDI_DEVICE_FAULT, "spurious interrupts");
622fcf3ce44SJohn Forte 	}
623fcf3ce44SJohn Forte }
624fcf3ce44SJohn Forte 
625fcf3ce44SJohn Forte /*
626fcf3ce44SJohn Forte  * ql_mbx_completion
627fcf3ce44SJohn Forte  *	Processes mailbox completions.
628fcf3ce44SJohn Forte  *
629fcf3ce44SJohn Forte  * Input:
630fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
631fcf3ce44SJohn Forte  *	mb0:		Mailbox 0 contents.
632fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
633fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
634fcf3ce44SJohn Forte  *	intr_clr:	early interrupt clear
635fcf3ce44SJohn Forte  *
636fcf3ce44SJohn Forte  * Context:
637fcf3ce44SJohn Forte  *	Interrupt context.
638fcf3ce44SJohn Forte  */
639fcf3ce44SJohn Forte /* ARGSUSED */
640fcf3ce44SJohn Forte static void
641fcf3ce44SJohn Forte ql_mbx_completion(ql_adapter_state_t *ha, uint16_t mb0, uint32_t *set_flags,
642fcf3ce44SJohn Forte     uint32_t *reset_flags, int intr_clr)
643fcf3ce44SJohn Forte {
644fcf3ce44SJohn Forte 	uint32_t	index;
645fcf3ce44SJohn Forte 	uint16_t	cnt;
646fcf3ce44SJohn Forte 
647fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
648fcf3ce44SJohn Forte 
649fcf3ce44SJohn Forte 	/* Load return mailbox registers. */
650fcf3ce44SJohn Forte 	MBX_REGISTER_LOCK(ha);
651fcf3ce44SJohn Forte 
652fcf3ce44SJohn Forte 	if (ha->mcp != NULL) {
653fcf3ce44SJohn Forte 		ha->mcp->mb[0] = mb0;
654fcf3ce44SJohn Forte 		index = ha->mcp->in_mb & ~MBX_0;
655fcf3ce44SJohn Forte 
656fcf3ce44SJohn Forte 		for (cnt = 1; cnt < MAX_MBOX_COUNT && index != 0; cnt++) {
657fcf3ce44SJohn Forte 			index >>= 1;
658fcf3ce44SJohn Forte 			if (index & MBX_0) {
659fcf3ce44SJohn Forte 				ha->mcp->mb[cnt] = RD16_IO_REG(ha,
660fcf3ce44SJohn Forte 				    mailbox[cnt]);
661fcf3ce44SJohn Forte 			}
662fcf3ce44SJohn Forte 		}
663fcf3ce44SJohn Forte 
664fcf3ce44SJohn Forte 	} else {
665fcf3ce44SJohn Forte 		EL(ha, "mcp == NULL\n");
666fcf3ce44SJohn Forte 	}
667fcf3ce44SJohn Forte 
668fcf3ce44SJohn Forte 	if (intr_clr) {
669fcf3ce44SJohn Forte 		/* Clear RISC interrupt. */
670fcf3ce44SJohn Forte 		CFG_IST(ha, CFG_CTRL_2425) ?
671fcf3ce44SJohn Forte 		    WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) :
672fcf3ce44SJohn Forte 		    WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
673fcf3ce44SJohn Forte 	}
674fcf3ce44SJohn Forte 
675fcf3ce44SJohn Forte 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_INTERRUPT);
676fcf3ce44SJohn Forte 	if (ha->flags & INTERRUPTS_ENABLED) {
677fcf3ce44SJohn Forte 		cv_broadcast(&ha->cv_mbx_intr);
678fcf3ce44SJohn Forte 	}
679fcf3ce44SJohn Forte 
680fcf3ce44SJohn Forte 	MBX_REGISTER_UNLOCK(ha);
681fcf3ce44SJohn Forte 
682fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
683fcf3ce44SJohn Forte }
684fcf3ce44SJohn Forte 
685fcf3ce44SJohn Forte /*
686fcf3ce44SJohn Forte  * ql_async_event
687fcf3ce44SJohn Forte  *	Processes asynchronous events.
688fcf3ce44SJohn Forte  *
689fcf3ce44SJohn Forte  * Input:
690fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
691fcf3ce44SJohn Forte  *	mbx:		Mailbox 0 register.
692fcf3ce44SJohn Forte  *	done_q:		head pointer to done queue.
693fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
694fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
695fcf3ce44SJohn Forte  *	intr_clr:	early interrupt clear
696fcf3ce44SJohn Forte  *
697fcf3ce44SJohn Forte  * Context:
698fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
699fcf3ce44SJohn Forte  */
700fcf3ce44SJohn Forte static void
701fcf3ce44SJohn Forte ql_async_event(ql_adapter_state_t *ha, uint32_t mbx, ql_head_t *done_q,
702fcf3ce44SJohn Forte     uint32_t *set_flags, uint32_t *reset_flags, int intr_clr)
703fcf3ce44SJohn Forte {
704fcf3ce44SJohn Forte 	uint32_t		handle;
705fcf3ce44SJohn Forte 	uint32_t		index;
706fcf3ce44SJohn Forte 	uint16_t		cnt;
707fcf3ce44SJohn Forte 	uint16_t		mb[MAX_MBOX_COUNT];
708fcf3ce44SJohn Forte 	ql_srb_t		*sp;
709fcf3ce44SJohn Forte 	port_id_t		s_id;
710fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
711fcf3ce44SJohn Forte 	boolean_t		intr = B_TRUE;
712fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
713fcf3ce44SJohn Forte 
714fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
715fcf3ce44SJohn Forte 
716fcf3ce44SJohn Forte 	/* Setup to process fast completion. */
717fcf3ce44SJohn Forte 	mb[0] = LSW(mbx);
718fcf3ce44SJohn Forte 	switch (mb[0]) {
719fcf3ce44SJohn Forte 	case MBA_SCSI_COMPLETION:
720fcf3ce44SJohn Forte 		handle = SHORT_TO_LONG(RD16_IO_REG(ha, mailbox[1]),
721fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[2]));
722fcf3ce44SJohn Forte 		break;
723fcf3ce44SJohn Forte 
724fcf3ce44SJohn Forte 	case MBA_CMPLT_1_16BIT:
725fcf3ce44SJohn Forte 		handle = MSW(mbx);
726fcf3ce44SJohn Forte 		mb[0] = MBA_SCSI_COMPLETION;
727fcf3ce44SJohn Forte 		break;
728fcf3ce44SJohn Forte 
729fcf3ce44SJohn Forte 	case MBA_CMPLT_1_32BIT:
730fcf3ce44SJohn Forte 		handle = SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox[2]));
731fcf3ce44SJohn Forte 		mb[0] = MBA_SCSI_COMPLETION;
732fcf3ce44SJohn Forte 		break;
733fcf3ce44SJohn Forte 
734fcf3ce44SJohn Forte 	case MBA_CTIO_COMPLETION:
735fcf3ce44SJohn Forte 	case MBA_IP_COMPLETION:
736fcf3ce44SJohn Forte 		handle = CFG_IST(ha, CFG_CTRL_2200) ? SHORT_TO_LONG(
737fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[1]), RD16_IO_REG(ha, mailbox[2])) :
738fcf3ce44SJohn Forte 		    SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox[2]));
739fcf3ce44SJohn Forte 		mb[0] = MBA_SCSI_COMPLETION;
740fcf3ce44SJohn Forte 		break;
741fcf3ce44SJohn Forte 
742fcf3ce44SJohn Forte 	default:
743fcf3ce44SJohn Forte 		break;
744fcf3ce44SJohn Forte 	}
745fcf3ce44SJohn Forte 
746fcf3ce44SJohn Forte 	/* Handle asynchronous event */
747fcf3ce44SJohn Forte 	switch (mb[0]) {
748fcf3ce44SJohn Forte 	case MBA_SCSI_COMPLETION:
749fcf3ce44SJohn Forte 		QL_PRINT_5(CE_CONT, "(%d): Fast post completion\n",
750fcf3ce44SJohn Forte 		    ha->instance);
751fcf3ce44SJohn Forte 
752fcf3ce44SJohn Forte 		if (intr_clr) {
753fcf3ce44SJohn Forte 			/* Clear RISC interrupt */
754fcf3ce44SJohn Forte 			CFG_IST(ha, CFG_CTRL_2425) ?
755fcf3ce44SJohn Forte 			    WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) :
756fcf3ce44SJohn Forte 			    WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
757fcf3ce44SJohn Forte 			intr = B_FALSE;
758fcf3ce44SJohn Forte 		}
759fcf3ce44SJohn Forte 
760fcf3ce44SJohn Forte 		if ((ha->flags & ONLINE) == 0) {
761fcf3ce44SJohn Forte 			break;
762fcf3ce44SJohn Forte 		}
763fcf3ce44SJohn Forte 
764fcf3ce44SJohn Forte 		/* Get handle. */
765fcf3ce44SJohn Forte 		index = handle & OSC_INDEX_MASK;
766fcf3ce44SJohn Forte 
767fcf3ce44SJohn Forte 		/* Validate handle. */
768fcf3ce44SJohn Forte 		sp = index < MAX_OUTSTANDING_COMMANDS ?
769fcf3ce44SJohn Forte 		    ha->outstanding_cmds[index] : NULL;
770fcf3ce44SJohn Forte 
771fcf3ce44SJohn Forte 		if (sp != NULL && sp->handle == handle) {
772fcf3ce44SJohn Forte 			ha->outstanding_cmds[index] = NULL;
773fcf3ce44SJohn Forte 			sp->handle = 0;
774fcf3ce44SJohn Forte 			sp->flags &= ~SRB_IN_TOKEN_ARRAY;
775fcf3ce44SJohn Forte 
776fcf3ce44SJohn Forte 			/* Set completed status. */
777fcf3ce44SJohn Forte 			sp->flags |= SRB_ISP_COMPLETED;
778fcf3ce44SJohn Forte 
779fcf3ce44SJohn Forte 			/* Set completion status */
780fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_COMPLETE;
781fcf3ce44SJohn Forte 
782fcf3ce44SJohn Forte 			if (!(sp->flags & SRB_FCP_CMD_PKT)) {
783fcf3ce44SJohn Forte 				/* Place block on done queue */
784fcf3ce44SJohn Forte 				ql_add_link_b(done_q, &sp->cmd);
785fcf3ce44SJohn Forte 			} else {
786fcf3ce44SJohn Forte 				ql_fast_fcp_post(sp);
787fcf3ce44SJohn Forte 			}
788fcf3ce44SJohn Forte 		} else if (handle != QL_FCA_BRAND) {
789fcf3ce44SJohn Forte 			if (sp == NULL) {
790fcf3ce44SJohn Forte 				EL(ha, "%xh unknown IOCB handle=%xh\n",
791fcf3ce44SJohn Forte 				    mb[0], handle);
792fcf3ce44SJohn Forte 			} else {
793fcf3ce44SJohn Forte 				EL(ha, "%xh mismatch IOCB handle pkt=%xh, "
794fcf3ce44SJohn Forte 				    "sp=%xh\n", mb[0], handle, sp->handle);
795fcf3ce44SJohn Forte 			}
796fcf3ce44SJohn Forte 
797fcf3ce44SJohn Forte 			EL(ha, "%xh Fast post, mbx1=%xh, mbx2=%xh, mbx3=%xh,"
798fcf3ce44SJohn Forte 			    "mbx6=%xh, mbx7=%xh\n", mb[0],
799fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[1]),
800fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[2]),
801fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[3]),
802fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[6]),
803fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[7]));
804fcf3ce44SJohn Forte 
805fcf3ce44SJohn Forte 			(void) ql_binary_fw_dump(ha, FALSE);
806fcf3ce44SJohn Forte 
807fcf3ce44SJohn Forte 			if (!(ha->task_daemon_flags &
808fcf3ce44SJohn Forte 			    (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) {
809fcf3ce44SJohn Forte 				EL(ha, "%xh ISP Invalid handle, "
810fcf3ce44SJohn Forte 				    "isp_abort_needed\n", mb[0]);
811fcf3ce44SJohn Forte 				*set_flags |= ISP_ABORT_NEEDED;
812fcf3ce44SJohn Forte 			}
813fcf3ce44SJohn Forte 		}
814fcf3ce44SJohn Forte 		break;
815fcf3ce44SJohn Forte 
816fcf3ce44SJohn Forte 	case MBA_RESET:		/* Reset */
817fcf3ce44SJohn Forte 		EL(ha, "%xh Reset received\n", mb[0]);
818fcf3ce44SJohn Forte 		*set_flags |= RESET_MARKER_NEEDED;
819fcf3ce44SJohn Forte 		break;
820fcf3ce44SJohn Forte 
821fcf3ce44SJohn Forte 	case MBA_SYSTEM_ERR:		/* System Error */
822fcf3ce44SJohn Forte 		mb[1] = RD16_IO_REG(ha, mailbox[1]);
823fcf3ce44SJohn Forte 		mb[2] = RD16_IO_REG(ha, mailbox[2]);
824fcf3ce44SJohn Forte 		mb[3] = RD16_IO_REG(ha, mailbox[3]);
825fcf3ce44SJohn Forte 
826fcf3ce44SJohn Forte 		EL(ha, "%xh ISP System Error, isp_abort_needed\n mbx1=%xh, "
827fcf3ce44SJohn Forte 		    "mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh, mbx6=%xh,\n "
828fcf3ce44SJohn Forte 		    "mbx7=%xh, mbx8=%xh, mbx9=%xh, mbx10=%xh, mbx11=%xh, "
829fcf3ce44SJohn Forte 		    "mbx12=%xh,\n", mb[0], mb[1], mb[2], mb[3],
830fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[4]), RD16_IO_REG(ha, mailbox[5]),
831fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[6]), RD16_IO_REG(ha, mailbox[7]),
832fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[8]), RD16_IO_REG(ha, mailbox[9]),
833fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[10]), RD16_IO_REG(ha, mailbox[11]),
834fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[12]));
835fcf3ce44SJohn Forte 
836fcf3ce44SJohn Forte 		EL(ha, "%xh ISP System Error, isp_abort_needed\n mbx13=%xh, "
837fcf3ce44SJohn Forte 		    "mbx14=%xh, mbx15=%xh, mbx16=%xh, mbx17=%xh, mbx18=%xh,\n"
838fcf3ce44SJohn Forte 		    "mbx19=%xh, mbx20=%xh, mbx21=%xh, mbx22=%xh, mbx23=%xh\n",
839fcf3ce44SJohn Forte 		    mb[0], RD16_IO_REG(ha, mailbox[13]),
840fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[14]), RD16_IO_REG(ha, mailbox[15]),
841fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[16]), RD16_IO_REG(ha, mailbox[17]),
842fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[18]), RD16_IO_REG(ha, mailbox[19]),
843fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[20]), RD16_IO_REG(ha, mailbox[21]),
844fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[22]),
845fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[23]));
846fcf3ce44SJohn Forte 
847fcf3ce44SJohn Forte 		if (ha->reg_off->mbox_cnt > 24) {
848fcf3ce44SJohn Forte 			EL(ha, "%xh ISP System Error, mbx24=%xh, mbx25=%xh, "
849fcf3ce44SJohn Forte 			    "mbx26=%xh,\n mbx27=%xh, mbx28=%xh, mbx29=%xh, "
850fcf3ce44SJohn Forte 			    "mbx30=%xh, mbx31=%xh\n", mb[0],
851fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[24]),
852fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[25]),
853fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[26]),
854fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[27]),
855fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[28]),
856fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[29]),
857fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[30]),
858fcf3ce44SJohn Forte 			    RD16_IO_REG(ha, mailbox[31]));
859fcf3ce44SJohn Forte 		}
860fcf3ce44SJohn Forte 
861fcf3ce44SJohn Forte 		(void) ql_binary_fw_dump(ha, FALSE);
862fcf3ce44SJohn Forte 
863fcf3ce44SJohn Forte 		(void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8002, mb[1],
864fcf3ce44SJohn Forte 		    mb[2], mb[3]);
865fcf3ce44SJohn Forte 
866fcf3ce44SJohn Forte 		*set_flags |= ISP_ABORT_NEEDED;
867fcf3ce44SJohn Forte 		ha->xioctl->ControllerErrorCount++;
868fcf3ce44SJohn Forte 		break;
869fcf3ce44SJohn Forte 
870fcf3ce44SJohn Forte 	case MBA_REQ_TRANSFER_ERR:  /* Request Transfer Error */
871fcf3ce44SJohn Forte 		EL(ha, "%xh Request Transfer Error received, "
872fcf3ce44SJohn Forte 		    "isp_abort_needed\n", mb[0]);
873fcf3ce44SJohn Forte 
874fcf3ce44SJohn Forte 		(void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8003,
875fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[1]), RD16_IO_REG(ha, mailbox[2]),
876fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[3]));
877fcf3ce44SJohn Forte 
878fcf3ce44SJohn Forte 		*set_flags |= ISP_ABORT_NEEDED;
879fcf3ce44SJohn Forte 		ha->xioctl->ControllerErrorCount++;
880fcf3ce44SJohn Forte 		break;
881fcf3ce44SJohn Forte 
882fcf3ce44SJohn Forte 	case MBA_RSP_TRANSFER_ERR:  /* Response Xfer Err */
883fcf3ce44SJohn Forte 		EL(ha, "%xh Response Transfer Error received,"
884fcf3ce44SJohn Forte 		    " isp_abort_needed\n", mb[0]);
885fcf3ce44SJohn Forte 
886fcf3ce44SJohn Forte 		(void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8004,
887fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[1]), RD16_IO_REG(ha, mailbox[2]),
888fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[3]));
889fcf3ce44SJohn Forte 
890fcf3ce44SJohn Forte 		*set_flags |= ISP_ABORT_NEEDED;
891fcf3ce44SJohn Forte 		ha->xioctl->ControllerErrorCount++;
892fcf3ce44SJohn Forte 		break;
893fcf3ce44SJohn Forte 
894fcf3ce44SJohn Forte 	case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
895fcf3ce44SJohn Forte 		EL(ha, "%xh Request Queue Wake-up received\n",
896fcf3ce44SJohn Forte 		    mb[0]);
897fcf3ce44SJohn Forte 		break;
898fcf3ce44SJohn Forte 
899fcf3ce44SJohn Forte 	case MBA_MENLO_ALERT:	/* Menlo Alert Notification */
900fcf3ce44SJohn Forte 		mb[1] = RD16_IO_REG(ha, mailbox[1]);
901fcf3ce44SJohn Forte 		mb[2] = RD16_IO_REG(ha, mailbox[2]);
902fcf3ce44SJohn Forte 		mb[3] = RD16_IO_REG(ha, mailbox[3]);
903fcf3ce44SJohn Forte 
904fcf3ce44SJohn Forte 		EL(ha, "%xh Menlo Alert Notification received, mbx1=%xh,"
905fcf3ce44SJohn Forte 		    " mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]);
906fcf3ce44SJohn Forte 
907fcf3ce44SJohn Forte 		switch (mb[1]) {
908fcf3ce44SJohn Forte 		case MLA_LOGIN_OPERATIONAL_FW:
909fcf3ce44SJohn Forte 			ADAPTER_STATE_LOCK(ha);
910fcf3ce44SJohn Forte 			ha->flags |= MENLO_LOGIN_OPERATIONAL;
911fcf3ce44SJohn Forte 			ADAPTER_STATE_UNLOCK(ha);
912fcf3ce44SJohn Forte 			break;
913fcf3ce44SJohn Forte 		case MLA_PANIC_RECOVERY:
914fcf3ce44SJohn Forte 		case MLA_LOGIN_DIAGNOSTIC_FW:
915fcf3ce44SJohn Forte 		case MLA_LOGIN_GOLDEN_FW:
916fcf3ce44SJohn Forte 		case MLA_REJECT_RESPONSE:
917fcf3ce44SJohn Forte 		default:
918fcf3ce44SJohn Forte 			break;
919fcf3ce44SJohn Forte 		}
920fcf3ce44SJohn Forte 		break;
921fcf3ce44SJohn Forte 
922fcf3ce44SJohn Forte 	case MBA_LIP_F8:	/* Received a LIP F8. */
923fcf3ce44SJohn Forte 	case MBA_LIP_RESET:	/* LIP reset occurred. */
924fcf3ce44SJohn Forte 	case MBA_LIP_OCCURRED:	/* Loop Initialization Procedure */
925fcf3ce44SJohn Forte 		EL(ha, "%xh LIP received\n", mb[0]);
926fcf3ce44SJohn Forte 
927fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
928fcf3ce44SJohn Forte 		ha->flags &= ~POINT_TO_POINT;
929fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
930fcf3ce44SJohn Forte 
931fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & LOOP_DOWN)) {
932fcf3ce44SJohn Forte 			*set_flags |= LOOP_DOWN;
933fcf3ce44SJohn Forte 		}
934fcf3ce44SJohn Forte 		ql_port_state(ha, FC_STATE_OFFLINE,
935fcf3ce44SJohn Forte 		    FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN);
936fcf3ce44SJohn Forte 
937fcf3ce44SJohn Forte 		if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
938fcf3ce44SJohn Forte 			ha->loop_down_timer = LOOP_DOWN_TIMER_START;
939fcf3ce44SJohn Forte 		}
940fcf3ce44SJohn Forte 
941fcf3ce44SJohn Forte 		ha->adapter_stats->lip_count++;
942fcf3ce44SJohn Forte 
943fcf3ce44SJohn Forte 		/* Update AEN queue. */
944fcf3ce44SJohn Forte 		ha->xioctl->TotalLipResets++;
945fcf3ce44SJohn Forte 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
946fcf3ce44SJohn Forte 			ql_enqueue_aen(ha, mb[0], NULL);
947fcf3ce44SJohn Forte 		}
948fcf3ce44SJohn Forte 		break;
949fcf3ce44SJohn Forte 
950fcf3ce44SJohn Forte 	case MBA_LOOP_UP:
951fcf3ce44SJohn Forte 		if (CFG_IST(ha, (CFG_CTRL_2300|CFG_CTRL_6322|CFG_CTRL_2425))) {
952fcf3ce44SJohn Forte 			mb[1] = RD16_IO_REG(ha, mailbox[1]);
953fcf3ce44SJohn Forte 			if (mb[1] == 0) {		/* 1GB */
954fcf3ce44SJohn Forte 				ha->state = FC_PORT_STATE_MASK(
955fcf3ce44SJohn Forte 				    ha->state) | FC_STATE_1GBIT_SPEED;
956fcf3ce44SJohn Forte 				index = 1;
957fcf3ce44SJohn Forte 			} else if (mb[1] == 1) {	/* 2GB */
958fcf3ce44SJohn Forte 				ha->state = FC_PORT_STATE_MASK(
959fcf3ce44SJohn Forte 				    ha->state) | FC_STATE_2GBIT_SPEED;
960fcf3ce44SJohn Forte 				index = 2;
961fcf3ce44SJohn Forte 			} else if (mb[1] == 3) {	/* 4GB */
962fcf3ce44SJohn Forte 				ha->state = FC_PORT_STATE_MASK(
963fcf3ce44SJohn Forte 				    ha->state) | FC_STATE_4GBIT_SPEED;
964fcf3ce44SJohn Forte 				index = 4;
965fcf3ce44SJohn Forte 			} else if (mb[1] == 4) {	/* 8GB */
966fcf3ce44SJohn Forte 				ha->state = FC_PORT_STATE_MASK(
967fcf3ce44SJohn Forte 				    ha->state) | FC_STATE_8GBIT_SPEED;
968fcf3ce44SJohn Forte 				index = 8;
969fcf3ce44SJohn Forte 			} else {
970fcf3ce44SJohn Forte 				ha->state = FC_PORT_STATE_MASK(
971fcf3ce44SJohn Forte 				    ha->state);
972fcf3ce44SJohn Forte 				index = 0;
973fcf3ce44SJohn Forte 			}
974fcf3ce44SJohn Forte 		} else {
975fcf3ce44SJohn Forte 			ha->state = FC_PORT_STATE_MASK(ha->state) |
976fcf3ce44SJohn Forte 			    FC_STATE_FULL_SPEED;
977fcf3ce44SJohn Forte 			index = 1;
978fcf3ce44SJohn Forte 		}
979fcf3ce44SJohn Forte 
980fcf3ce44SJohn Forte 		for (vha = ha; vha != NULL; vha = vha->vp_next) {
981fcf3ce44SJohn Forte 			vha->state = FC_PORT_STATE_MASK(vha->state) |
982fcf3ce44SJohn Forte 			    FC_PORT_SPEED_MASK(ha->state);
983fcf3ce44SJohn Forte 		}
984fcf3ce44SJohn Forte 		EL(ha, "%d GB %xh Loop Up received\n", index, mb[0]);
985fcf3ce44SJohn Forte 
986fcf3ce44SJohn Forte 		/* Update AEN queue. */
987fcf3ce44SJohn Forte 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
988fcf3ce44SJohn Forte 			ql_enqueue_aen(ha, mb[0], NULL);
989fcf3ce44SJohn Forte 		}
990fcf3ce44SJohn Forte 		break;
991fcf3ce44SJohn Forte 
992fcf3ce44SJohn Forte 	case MBA_LOOP_DOWN:
993fcf3ce44SJohn Forte 		EL(ha, "%xh Loop Down received, mbx1=%xh, mbx2=%xh, "
994fcf3ce44SJohn Forte 		    "mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox[1]),
995fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[2]), RD16_IO_REG(ha, mailbox[3]));
996fcf3ce44SJohn Forte 
997fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & LOOP_DOWN)) {
998fcf3ce44SJohn Forte 			*set_flags |= LOOP_DOWN;
999fcf3ce44SJohn Forte 		}
1000fcf3ce44SJohn Forte 		ql_port_state(ha, FC_STATE_OFFLINE,
1001fcf3ce44SJohn Forte 		    FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN);
1002fcf3ce44SJohn Forte 
1003fcf3ce44SJohn Forte 		if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
1004fcf3ce44SJohn Forte 			ha->loop_down_timer = LOOP_DOWN_TIMER_START;
1005fcf3ce44SJohn Forte 		}
1006fcf3ce44SJohn Forte 
1007fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_CTRL_25XX)) {
1008fcf3ce44SJohn Forte 			ha->sfp_stat = RD16_IO_REG(ha, mailbox[2]);
1009fcf3ce44SJohn Forte 		}
1010fcf3ce44SJohn Forte 
1011fcf3ce44SJohn Forte 		/* Update AEN queue. */
1012fcf3ce44SJohn Forte 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
1013fcf3ce44SJohn Forte 			ql_enqueue_aen(ha, mb[0], NULL);
1014fcf3ce44SJohn Forte 		}
1015fcf3ce44SJohn Forte 		break;
1016fcf3ce44SJohn Forte 
1017fcf3ce44SJohn Forte 	case MBA_PORT_UPDATE:
1018fcf3ce44SJohn Forte 		mb[1] = RD16_IO_REG(ha, mailbox[1]);
1019fcf3ce44SJohn Forte 		mb[2] = RD16_IO_REG(ha, mailbox[2]);
1020fcf3ce44SJohn Forte 		mb[3] = (uint16_t)(ha->flags & VP_ENABLED ?
1021fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[3]) : 0);
1022fcf3ce44SJohn Forte 
1023fcf3ce44SJohn Forte 		/* Locate port state structure. */
1024fcf3ce44SJohn Forte 		for (vha = ha; vha != NULL; vha = vha->vp_next) {
1025fcf3ce44SJohn Forte 			if (vha->vp_index == LSB(mb[3])) {
1026fcf3ce44SJohn Forte 				break;
1027fcf3ce44SJohn Forte 			}
1028fcf3ce44SJohn Forte 		}
1029fcf3ce44SJohn Forte 		if (vha == NULL) {
1030fcf3ce44SJohn Forte 			break;
1031fcf3ce44SJohn Forte 		}
1032fcf3ce44SJohn Forte 		if (FC_PORT_STATE_MASK(vha->state) != FC_STATE_OFFLINE ||
1033*16dd44c2SDaniel Beauregard 		    (CFG_IST(ha, CFG_CTRL_2425) &&
1034*16dd44c2SDaniel Beauregard 		    (mb[1] != 0xffff || mb[2] != 6 || mb[3] != 0))) {
1035fcf3ce44SJohn Forte 			EL(ha, "%xh Port Database Update, Login/Logout "
1036fcf3ce44SJohn Forte 			    "received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
1037fcf3ce44SJohn Forte 			    mb[0], mb[1], mb[2], mb[3]);
1038fcf3ce44SJohn Forte 		} else {
1039fcf3ce44SJohn Forte 			EL(ha, "%xh Port Database Update received, mbx1=%xh,"
1040fcf3ce44SJohn Forte 			    " mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2],
1041fcf3ce44SJohn Forte 			    mb[3]);
1042fcf3ce44SJohn Forte 			*set_flags |= LOOP_RESYNC_NEEDED;
1043fcf3ce44SJohn Forte 			*set_flags &= ~LOOP_DOWN;
1044fcf3ce44SJohn Forte 			*reset_flags |= LOOP_DOWN;
1045fcf3ce44SJohn Forte 			*reset_flags &= ~LOOP_RESYNC_NEEDED;
1046fcf3ce44SJohn Forte 			vha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
1047fcf3ce44SJohn Forte 			TASK_DAEMON_LOCK(ha);
1048fcf3ce44SJohn Forte 			vha->task_daemon_flags |= LOOP_RESYNC_NEEDED;
1049fcf3ce44SJohn Forte 			vha->task_daemon_flags &= ~LOOP_DOWN;
1050fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
1051fcf3ce44SJohn Forte 			ADAPTER_STATE_LOCK(ha);
1052*16dd44c2SDaniel Beauregard 			vha->flags &= ~ABORT_CMDS_LOOP_DOWN_TMO;
1053fcf3ce44SJohn Forte 			ADAPTER_STATE_UNLOCK(ha);
1054fcf3ce44SJohn Forte 		}
1055fcf3ce44SJohn Forte 
1056fcf3ce44SJohn Forte 		/* Update AEN queue. */
1057fcf3ce44SJohn Forte 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
1058fcf3ce44SJohn Forte 			ql_enqueue_aen(ha, mb[0], NULL);
1059fcf3ce44SJohn Forte 		}
1060fcf3ce44SJohn Forte 		break;
1061fcf3ce44SJohn Forte 
1062fcf3ce44SJohn Forte 	case MBA_RSCN_UPDATE:
1063fcf3ce44SJohn Forte 		mb[1] = RD16_IO_REG(ha, mailbox[1]);
1064fcf3ce44SJohn Forte 		mb[2] = RD16_IO_REG(ha, mailbox[2]);
1065fcf3ce44SJohn Forte 		mb[3] = (uint16_t)(ha->flags & VP_ENABLED ?
1066fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[3]) : 0);
1067fcf3ce44SJohn Forte 
1068fcf3ce44SJohn Forte 		/* Locate port state structure. */
1069fcf3ce44SJohn Forte 		for (vha = ha; vha != NULL; vha = vha->vp_next) {
1070fcf3ce44SJohn Forte 			if (vha->vp_index == LSB(mb[3])) {
1071fcf3ce44SJohn Forte 				break;
1072fcf3ce44SJohn Forte 			}
1073fcf3ce44SJohn Forte 		}
1074fcf3ce44SJohn Forte 
1075fcf3ce44SJohn Forte 		if (vha == NULL) {
1076fcf3ce44SJohn Forte 			break;
1077fcf3ce44SJohn Forte 		}
1078fcf3ce44SJohn Forte 
1079fcf3ce44SJohn Forte 		if (LSB(mb[1]) == vha->d_id.b.domain &&
1080fcf3ce44SJohn Forte 		    MSB(mb[2]) == vha->d_id.b.area &&
1081fcf3ce44SJohn Forte 		    LSB(mb[2]) == vha->d_id.b.al_pa) {
1082fcf3ce44SJohn Forte 			EL(ha, "%xh RSCN match adapter, mbx1=%xh, mbx2=%xh, "
1083fcf3ce44SJohn Forte 			    "mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]);
1084fcf3ce44SJohn Forte 		} else {
1085fcf3ce44SJohn Forte 			EL(ha, "%xh RSCN received, mbx1=%xh, mbx2=%xh, "
1086fcf3ce44SJohn Forte 			    "mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]);
1087fcf3ce44SJohn Forte 			if (FC_PORT_STATE_MASK(vha->state) !=
1088fcf3ce44SJohn Forte 			    FC_STATE_OFFLINE) {
1089fcf3ce44SJohn Forte 				ql_rcv_rscn_els(vha, &mb[0], done_q);
1090fcf3ce44SJohn Forte 				TASK_DAEMON_LOCK(ha);
1091fcf3ce44SJohn Forte 				vha->task_daemon_flags |= RSCN_UPDATE_NEEDED;
1092fcf3ce44SJohn Forte 				TASK_DAEMON_UNLOCK(ha);
1093fcf3ce44SJohn Forte 				*set_flags |= RSCN_UPDATE_NEEDED;
1094fcf3ce44SJohn Forte 			}
1095fcf3ce44SJohn Forte 		}
1096fcf3ce44SJohn Forte 
1097fcf3ce44SJohn Forte 		/* Update AEN queue. */
1098fcf3ce44SJohn Forte 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
1099fcf3ce44SJohn Forte 			ql_enqueue_aen(ha, mb[0], NULL);
1100fcf3ce44SJohn Forte 		}
1101fcf3ce44SJohn Forte 		break;
1102fcf3ce44SJohn Forte 
1103fcf3ce44SJohn Forte 	case MBA_LIP_ERROR:	/* Loop initialization errors. */
1104fcf3ce44SJohn Forte 		EL(ha, "%xh LIP error received, mbx1=%xh\n", mb[0],
1105fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[1]));
1106fcf3ce44SJohn Forte 		break;
1107fcf3ce44SJohn Forte 
1108fcf3ce44SJohn Forte 	case MBA_IP_RECEIVE:
1109fcf3ce44SJohn Forte 	case MBA_IP_BROADCAST:
1110fcf3ce44SJohn Forte 		mb[1] = RD16_IO_REG(ha, mailbox[1]);
1111fcf3ce44SJohn Forte 		mb[2] = RD16_IO_REG(ha, mailbox[2]);
1112fcf3ce44SJohn Forte 		mb[3] = RD16_IO_REG(ha, mailbox[3]);
1113fcf3ce44SJohn Forte 
1114fcf3ce44SJohn Forte 		EL(ha, "%xh IP packet/broadcast received, mbx1=%xh, "
1115fcf3ce44SJohn Forte 		    "mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]);
1116fcf3ce44SJohn Forte 
1117fcf3ce44SJohn Forte 		/* Locate device queue. */
1118fcf3ce44SJohn Forte 		s_id.b.al_pa = LSB(mb[2]);
1119fcf3ce44SJohn Forte 		s_id.b.area = MSB(mb[2]);
1120fcf3ce44SJohn Forte 		s_id.b.domain = LSB(mb[1]);
1121fcf3ce44SJohn Forte 		if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
1122fcf3ce44SJohn Forte 			EL(ha, "Unknown IP device=%xh\n", s_id.b24);
1123fcf3ce44SJohn Forte 			break;
1124fcf3ce44SJohn Forte 		}
1125fcf3ce44SJohn Forte 
1126fcf3ce44SJohn Forte 		cnt = (uint16_t)(CFG_IST(ha, CFG_CTRL_2425) ?
1127fcf3ce44SJohn Forte 		    CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb24.buf_size[0],
1128fcf3ce44SJohn Forte 		    ha->ip_init_ctrl_blk.cb24.buf_size[1]) :
1129fcf3ce44SJohn Forte 		    CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb.buf_size[0],
1130fcf3ce44SJohn Forte 		    ha->ip_init_ctrl_blk.cb.buf_size[1]));
1131fcf3ce44SJohn Forte 
1132fcf3ce44SJohn Forte 		tq->ub_sequence_length = mb[3];
1133fcf3ce44SJohn Forte 		tq->ub_total_seg_cnt = (uint8_t)(mb[3] / cnt);
1134fcf3ce44SJohn Forte 		if (mb[3] % cnt) {
1135fcf3ce44SJohn Forte 			tq->ub_total_seg_cnt++;
1136fcf3ce44SJohn Forte 		}
1137fcf3ce44SJohn Forte 		cnt = (uint16_t)(tq->ub_total_seg_cnt + 10);
1138fcf3ce44SJohn Forte 
1139fcf3ce44SJohn Forte 		for (index = 10; index < ha->reg_off->mbox_cnt && index < cnt;
1140fcf3ce44SJohn Forte 		    index++) {
1141fcf3ce44SJohn Forte 			mb[index] = RD16_IO_REG(ha, mailbox[index]);
1142fcf3ce44SJohn Forte 		}
1143fcf3ce44SJohn Forte 
1144fcf3ce44SJohn Forte 		tq->ub_seq_id = ++ha->ub_seq_id;
1145fcf3ce44SJohn Forte 		tq->ub_seq_cnt = 0;
1146fcf3ce44SJohn Forte 		tq->ub_frame_ro = 0;
1147fcf3ce44SJohn Forte 		tq->ub_loop_id = (uint16_t)(mb[0] == MBA_IP_BROADCAST ?
1148fcf3ce44SJohn Forte 		    (CFG_IST(ha, CFG_CTRL_2425) ? BROADCAST_24XX_HDL :
1149fcf3ce44SJohn Forte 		    IP_BROADCAST_LOOP_ID) : tq->loop_id);
1150fcf3ce44SJohn Forte 		ha->rcv_dev_q = tq;
1151fcf3ce44SJohn Forte 
1152fcf3ce44SJohn Forte 		for (cnt = 10; cnt < ha->reg_off->mbox_cnt &&
1153fcf3ce44SJohn Forte 		    tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
1154fcf3ce44SJohn Forte 			if (ql_ub_frame_hdr(ha, tq, mb[cnt], done_q) !=
1155fcf3ce44SJohn Forte 			    QL_SUCCESS) {
1156fcf3ce44SJohn Forte 				EL(ha, "ql_ub_frame_hdr failed, "
1157fcf3ce44SJohn Forte 				    "isp_abort_needed\n");
1158fcf3ce44SJohn Forte 				*set_flags |= ISP_ABORT_NEEDED;
1159fcf3ce44SJohn Forte 				break;
1160fcf3ce44SJohn Forte 			}
1161fcf3ce44SJohn Forte 		}
1162fcf3ce44SJohn Forte 		break;
1163fcf3ce44SJohn Forte 
1164fcf3ce44SJohn Forte 	case MBA_IP_LOW_WATER_MARK:
1165fcf3ce44SJohn Forte 	case MBA_IP_RCV_BUFFER_EMPTY:
1166fcf3ce44SJohn Forte 		EL(ha, "%xh IP low water mark / RCV buffer empty received\n",
1167fcf3ce44SJohn Forte 		    mb[0]);
1168fcf3ce44SJohn Forte 		*set_flags |= NEED_UNSOLICITED_BUFFERS;
1169fcf3ce44SJohn Forte 		break;
1170fcf3ce44SJohn Forte 
1171fcf3ce44SJohn Forte 	case MBA_IP_HDR_DATA_SPLIT:
1172fcf3ce44SJohn Forte 		EL(ha, "%xh IP HDR data split received\n", mb[0]);
1173fcf3ce44SJohn Forte 		break;
1174fcf3ce44SJohn Forte 
1175fcf3ce44SJohn Forte 	case MBA_POINT_TO_POINT:
1176fcf3ce44SJohn Forte 		EL(ha, "%xh Point to Point Mode received\n", mb[0]);
1177fcf3ce44SJohn Forte 		ADAPTER_STATE_LOCK(ha);
1178fcf3ce44SJohn Forte 		ha->flags |= POINT_TO_POINT;
1179fcf3ce44SJohn Forte 		ADAPTER_STATE_UNLOCK(ha);
1180fcf3ce44SJohn Forte 
1181fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & LOOP_DOWN)) {
1182fcf3ce44SJohn Forte 			*set_flags |= LOOP_DOWN;
1183fcf3ce44SJohn Forte 		}
1184fcf3ce44SJohn Forte 		ql_port_state(ha, FC_STATE_OFFLINE,
1185fcf3ce44SJohn Forte 		    FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN);
1186fcf3ce44SJohn Forte 
1187fcf3ce44SJohn Forte 		if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
1188fcf3ce44SJohn Forte 			ha->loop_down_timer = LOOP_DOWN_TIMER_START;
1189fcf3ce44SJohn Forte 		}
1190fcf3ce44SJohn Forte 		break;
1191fcf3ce44SJohn Forte 
1192fcf3ce44SJohn Forte 	case MBA_CHG_IN_CONNECTION:
1193fcf3ce44SJohn Forte 		mb[1] = RD16_IO_REG(ha, mailbox[1]);
1194fcf3ce44SJohn Forte 		if (mb[1] == 2) {
1195fcf3ce44SJohn Forte 			EL(ha, "%xh Change In Connection received, "
1196fcf3ce44SJohn Forte 			    "mbx1=%xh\n",  mb[0], mb[1]);
1197fcf3ce44SJohn Forte 			ADAPTER_STATE_LOCK(ha);
1198fcf3ce44SJohn Forte 			ha->flags &= ~POINT_TO_POINT;
1199fcf3ce44SJohn Forte 			ADAPTER_STATE_UNLOCK(ha);
1200fcf3ce44SJohn Forte 			if (ha->topology & QL_N_PORT) {
1201fcf3ce44SJohn Forte 				ha->topology = (uint8_t)(ha->topology &
1202fcf3ce44SJohn Forte 				    ~QL_N_PORT);
1203fcf3ce44SJohn Forte 				ha->topology = (uint8_t)(ha->topology |
1204fcf3ce44SJohn Forte 				    QL_NL_PORT);
1205fcf3ce44SJohn Forte 			}
1206fcf3ce44SJohn Forte 		} else {
1207fcf3ce44SJohn Forte 			EL(ha, "%xh Change In Connection received, "
1208fcf3ce44SJohn Forte 			    "mbx1=%xh, isp_abort_needed\n", mb[0], mb[1]);
1209fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
1210fcf3ce44SJohn Forte 		}
1211fcf3ce44SJohn Forte 		break;
1212fcf3ce44SJohn Forte 
1213fcf3ce44SJohn Forte 	case MBA_ZIO_UPDATE:
1214fcf3ce44SJohn Forte 		EL(ha, "%xh ZIO response received\n", mb[0]);
1215fcf3ce44SJohn Forte 
1216fcf3ce44SJohn Forte 		ha->isp_rsp_index = RD16_IO_REG(ha, resp_in);
1217fcf3ce44SJohn Forte 		ql_response_pkt(ha, done_q, set_flags, reset_flags, intr_clr);
1218fcf3ce44SJohn Forte 		intr = B_FALSE;
1219fcf3ce44SJohn Forte 		break;
1220fcf3ce44SJohn Forte 
1221fcf3ce44SJohn Forte 	case MBA_PORT_BYPASS_CHANGED:
1222fcf3ce44SJohn Forte 		EL(ha, "%xh Port Bypass Changed received, mbx1=%xh\n",
1223fcf3ce44SJohn Forte 		    mb[0], RD16_IO_REG(ha, mailbox[1]));
1224fcf3ce44SJohn Forte 		/*
1225fcf3ce44SJohn Forte 		 * Event generated when there is a transition on
1226fcf3ce44SJohn Forte 		 * port bypass of crystal+.
1227fcf3ce44SJohn Forte 		 * Mailbox 1:	Bit 0 - External.
1228fcf3ce44SJohn Forte 		 *		Bit 2 - Internal.
1229fcf3ce44SJohn Forte 		 * When the bit is 0, the port is bypassed.
1230fcf3ce44SJohn Forte 		 *
1231fcf3ce44SJohn Forte 		 * For now we will generate a LIP for all cases.
1232fcf3ce44SJohn Forte 		 */
1233fcf3ce44SJohn Forte 		*set_flags |= HANDLE_PORT_BYPASS_CHANGE;
1234fcf3ce44SJohn Forte 		break;
1235fcf3ce44SJohn Forte 
1236fcf3ce44SJohn Forte 	case MBA_RECEIVE_ERROR:
1237fcf3ce44SJohn Forte 		EL(ha, "%xh Receive Error received, mbx1=%xh, mbx2=%xh\n",
1238fcf3ce44SJohn Forte 		    mb[0], RD16_IO_REG(ha, mailbox[1]),
1239fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[2]));
1240fcf3ce44SJohn Forte 		break;
1241fcf3ce44SJohn Forte 
1242fcf3ce44SJohn Forte 	case MBA_LS_RJT_SENT:
1243fcf3ce44SJohn Forte 		EL(ha, "%xh LS_RJT Response Sent ELS=%xh\n", mb[0],
1244fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[1]));
1245fcf3ce44SJohn Forte 		break;
1246fcf3ce44SJohn Forte 
1247fcf3ce44SJohn Forte 	case MBA_FW_RESTART_COMP:
1248fcf3ce44SJohn Forte 		EL(ha, "%xh firmware restart complete received mb1=%xh\n",
1249fcf3ce44SJohn Forte 		    mb[0], RD16_IO_REG(ha, mailbox[1]));
1250fcf3ce44SJohn Forte 		break;
1251fcf3ce44SJohn Forte 
1252fcf3ce44SJohn Forte 	default:
1253fcf3ce44SJohn Forte 		EL(ha, "%xh UNKNOWN event received, mbx1=%xh, mbx2=%xh, "
1254fcf3ce44SJohn Forte 		    "mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox[1]),
1255fcf3ce44SJohn Forte 		    RD16_IO_REG(ha, mailbox[2]), RD16_IO_REG(ha, mailbox[3]));
1256fcf3ce44SJohn Forte 		break;
1257fcf3ce44SJohn Forte 	}
1258fcf3ce44SJohn Forte 
1259fcf3ce44SJohn Forte 	/* Clear RISC interrupt */
1260fcf3ce44SJohn Forte 	if (intr && intr_clr) {
1261fcf3ce44SJohn Forte 		CFG_IST(ha, CFG_CTRL_2425) ?
1262fcf3ce44SJohn Forte 		    WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) :
1263fcf3ce44SJohn Forte 		    WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
1264fcf3ce44SJohn Forte 	}
1265fcf3ce44SJohn Forte 
1266fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1267fcf3ce44SJohn Forte }
1268fcf3ce44SJohn Forte 
1269fcf3ce44SJohn Forte /*
1270fcf3ce44SJohn Forte  * ql_fast_fcp_post
1271fcf3ce44SJohn Forte  *	Fast path for good SCSI I/O completion.
1272fcf3ce44SJohn Forte  *
1273fcf3ce44SJohn Forte  * Input:
1274fcf3ce44SJohn Forte  *	sp:	SRB pointer.
1275fcf3ce44SJohn Forte  *
1276fcf3ce44SJohn Forte  * Context:
1277fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1278fcf3ce44SJohn Forte  */
1279fcf3ce44SJohn Forte static void
1280fcf3ce44SJohn Forte ql_fast_fcp_post(ql_srb_t *sp)
1281fcf3ce44SJohn Forte {
1282fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = sp->ha;
1283fcf3ce44SJohn Forte 	ql_lun_t		*lq = sp->lun_queue;
1284fcf3ce44SJohn Forte 	ql_tgt_t		*tq = lq->target_queue;
1285fcf3ce44SJohn Forte 
1286fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1287fcf3ce44SJohn Forte 
1288fcf3ce44SJohn Forte 	ASSERT(sp->flags & SRB_FCP_CMD_PKT && ha &&
1289fcf3ce44SJohn Forte 	    sp->pkt->pkt_reason == CS_COMPLETE);
1290fcf3ce44SJohn Forte 
1291fcf3ce44SJohn Forte 	/* Acquire device queue lock. */
1292fcf3ce44SJohn Forte 	DEVICE_QUEUE_LOCK(tq);
1293fcf3ce44SJohn Forte 
1294fcf3ce44SJohn Forte 	/* Decrement outstanding commands on device. */
1295fcf3ce44SJohn Forte 	if (tq->outcnt != 0) {
1296fcf3ce44SJohn Forte 		tq->outcnt--;
1297fcf3ce44SJohn Forte 	}
1298fcf3ce44SJohn Forte 
1299fcf3ce44SJohn Forte 	if (sp->flags & SRB_FCP_CMD_PKT) {
1300fcf3ce44SJohn Forte 		if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_UNTAGGED) {
1301fcf3ce44SJohn Forte 			/*
1302fcf3ce44SJohn Forte 			 * Clear the flag for this LUN so that
1303fcf3ce44SJohn Forte 			 * untagged commands can be submitted
1304fcf3ce44SJohn Forte 			 * for it.
1305fcf3ce44SJohn Forte 			 */
1306fcf3ce44SJohn Forte 			lq->flags &= ~LQF_UNTAGGED_PENDING;
1307fcf3ce44SJohn Forte 		}
1308fcf3ce44SJohn Forte 
1309fcf3ce44SJohn Forte 		if (lq->lun_outcnt != 0) {
1310fcf3ce44SJohn Forte 			lq->lun_outcnt--;
1311fcf3ce44SJohn Forte 		}
1312fcf3ce44SJohn Forte 	}
1313fcf3ce44SJohn Forte 
1314fcf3ce44SJohn Forte 	/* Reset port down retry count on good completion. */
1315fcf3ce44SJohn Forte 	tq->port_down_retry_count = ha->port_down_retry_count;
1316fcf3ce44SJohn Forte 	tq->qfull_retry_count = ha->qfull_retry_count;
1317fcf3ce44SJohn Forte 
1318fcf3ce44SJohn Forte 	/* Remove command from watchdog queue. */
1319fcf3ce44SJohn Forte 	if (sp->flags & SRB_WATCHDOG_ENABLED) {
1320fcf3ce44SJohn Forte 		ql_remove_link(&tq->wdg, &sp->wdg);
1321fcf3ce44SJohn Forte 		sp->flags &= ~SRB_WATCHDOG_ENABLED;
1322fcf3ce44SJohn Forte 	}
1323fcf3ce44SJohn Forte 
1324fcf3ce44SJohn Forte 	if (lq->cmd.first != NULL) {
1325fcf3ce44SJohn Forte 		ql_next(ha, lq);
1326fcf3ce44SJohn Forte 	} else {
1327fcf3ce44SJohn Forte 		/* Release LU queue specific lock. */
1328fcf3ce44SJohn Forte 		DEVICE_QUEUE_UNLOCK(tq);
1329fcf3ce44SJohn Forte 		if (ha->pha->pending_cmds.first != NULL) {
1330fcf3ce44SJohn Forte 			ql_start_iocb(ha, NULL);
1331fcf3ce44SJohn Forte 		}
1332fcf3ce44SJohn Forte 	}
1333fcf3ce44SJohn Forte 
1334fcf3ce44SJohn Forte 	/* Sync buffers if required.  */
1335fcf3ce44SJohn Forte 	if (sp->flags & SRB_MS_PKT) {
1336fcf3ce44SJohn Forte 		(void) ddi_dma_sync(sp->pkt->pkt_resp_dma, 0, 0,
1337fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORCPU);
1338fcf3ce44SJohn Forte 	}
1339fcf3ce44SJohn Forte 
1340fcf3ce44SJohn Forte 	/* Map ISP completion codes. */
1341fcf3ce44SJohn Forte 	sp->pkt->pkt_expln = FC_EXPLN_NONE;
1342fcf3ce44SJohn Forte 	sp->pkt->pkt_action = FC_ACTION_RETRYABLE;
1343fcf3ce44SJohn Forte 	sp->pkt->pkt_state = FC_PKT_SUCCESS;
1344fcf3ce44SJohn Forte 
1345fcf3ce44SJohn Forte 	/* Now call the pkt completion callback */
1346fcf3ce44SJohn Forte 	if (sp->flags & SRB_POLL) {
1347fcf3ce44SJohn Forte 		sp->flags &= ~SRB_POLL;
1348fcf3ce44SJohn Forte 	} else if (sp->pkt->pkt_comp) {
1349fcf3ce44SJohn Forte 		INTR_UNLOCK(ha);
1350fcf3ce44SJohn Forte 		(*sp->pkt->pkt_comp)(sp->pkt);
1351fcf3ce44SJohn Forte 		INTR_LOCK(ha);
1352fcf3ce44SJohn Forte 	}
1353fcf3ce44SJohn Forte 
1354fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1355fcf3ce44SJohn Forte }
1356fcf3ce44SJohn Forte 
1357fcf3ce44SJohn Forte /*
1358fcf3ce44SJohn Forte  * ql_response_pkt
1359fcf3ce44SJohn Forte  *	Processes response entry.
1360fcf3ce44SJohn Forte  *
1361fcf3ce44SJohn Forte  * Input:
1362fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
1363fcf3ce44SJohn Forte  *	done_q:		head pointer to done queue.
1364fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
1365fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
1366fcf3ce44SJohn Forte  *	intr_clr:	early interrupt clear
1367fcf3ce44SJohn Forte  *
1368fcf3ce44SJohn Forte  * Context:
1369fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1370fcf3ce44SJohn Forte  */
1371fcf3ce44SJohn Forte static void
1372fcf3ce44SJohn Forte ql_response_pkt(ql_adapter_state_t *ha, ql_head_t *done_q, uint32_t *set_flags,
1373fcf3ce44SJohn Forte     uint32_t *reset_flags, int intr_clr)
1374fcf3ce44SJohn Forte {
1375fcf3ce44SJohn Forte 	response_t	*pkt;
1376fcf3ce44SJohn Forte 	uint32_t	dma_sync_size_1 = 0;
1377fcf3ce44SJohn Forte 	uint32_t	dma_sync_size_2 = 0;
1378fcf3ce44SJohn Forte 	int		status = 0;
1379fcf3ce44SJohn Forte 
1380fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1381fcf3ce44SJohn Forte 
1382fcf3ce44SJohn Forte 	/* Clear RISC interrupt */
1383fcf3ce44SJohn Forte 	if (intr_clr) {
1384fcf3ce44SJohn Forte 		CFG_IST(ha, CFG_CTRL_2425) ?
1385fcf3ce44SJohn Forte 		    WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) :
1386fcf3ce44SJohn Forte 		    WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
1387fcf3ce44SJohn Forte 	}
1388fcf3ce44SJohn Forte 
1389fcf3ce44SJohn Forte 	if (ha->isp_rsp_index >= RESPONSE_ENTRY_CNT) {
1390fcf3ce44SJohn Forte 		EL(ha, "index error = %xh, isp_abort_needed",
1391fcf3ce44SJohn Forte 		    ha->isp_rsp_index);
1392fcf3ce44SJohn Forte 		*set_flags |= ISP_ABORT_NEEDED;
1393fcf3ce44SJohn Forte 		return;
1394fcf3ce44SJohn Forte 	}
1395fcf3ce44SJohn Forte 
1396fcf3ce44SJohn Forte 	if ((ha->flags & ONLINE) == 0) {
1397fcf3ce44SJohn Forte 		QL_PRINT_3(CE_CONT, "(%d): not onlne, done\n", ha->instance);
1398fcf3ce44SJohn Forte 		return;
1399fcf3ce44SJohn Forte 	}
1400fcf3ce44SJohn Forte 
1401fcf3ce44SJohn Forte 	/* Calculate size of response queue entries to sync. */
1402fcf3ce44SJohn Forte 	if (ha->isp_rsp_index > ha->rsp_ring_index) {
1403fcf3ce44SJohn Forte 		dma_sync_size_1 = (uint32_t)
1404fcf3ce44SJohn Forte 		    ((uint32_t)(ha->isp_rsp_index - ha->rsp_ring_index) *
1405fcf3ce44SJohn Forte 		    RESPONSE_ENTRY_SIZE);
1406fcf3ce44SJohn Forte 	} else if (ha->isp_rsp_index == 0) {
1407fcf3ce44SJohn Forte 		dma_sync_size_1 = (uint32_t)
1408fcf3ce44SJohn Forte 		    ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) *
1409fcf3ce44SJohn Forte 		    RESPONSE_ENTRY_SIZE);
1410fcf3ce44SJohn Forte 	} else {
1411fcf3ce44SJohn Forte 		/* Responses wrap around the Q */
1412fcf3ce44SJohn Forte 		dma_sync_size_1 = (uint32_t)
1413fcf3ce44SJohn Forte 		    ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) *
1414fcf3ce44SJohn Forte 		    RESPONSE_ENTRY_SIZE);
1415fcf3ce44SJohn Forte 		dma_sync_size_2 = (uint32_t)
1416fcf3ce44SJohn Forte 		    (ha->isp_rsp_index * RESPONSE_ENTRY_SIZE);
1417fcf3ce44SJohn Forte 	}
1418fcf3ce44SJohn Forte 
1419fcf3ce44SJohn Forte 	/* Sync DMA buffer. */
1420fcf3ce44SJohn Forte 	(void) ddi_dma_sync(ha->hba_buf.dma_handle,
1421fcf3ce44SJohn Forte 	    (off_t)(ha->rsp_ring_index * RESPONSE_ENTRY_SIZE +
1422fcf3ce44SJohn Forte 	    RESPONSE_Q_BUFFER_OFFSET), dma_sync_size_1,
1423fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORKERNEL);
1424fcf3ce44SJohn Forte 	if (dma_sync_size_2) {
1425fcf3ce44SJohn Forte 		(void) ddi_dma_sync(ha->hba_buf.dma_handle,
1426fcf3ce44SJohn Forte 		    RESPONSE_Q_BUFFER_OFFSET, dma_sync_size_2,
1427fcf3ce44SJohn Forte 		    DDI_DMA_SYNC_FORKERNEL);
1428fcf3ce44SJohn Forte 	}
1429fcf3ce44SJohn Forte 
1430fcf3ce44SJohn Forte 	while (ha->rsp_ring_index != ha->isp_rsp_index) {
1431fcf3ce44SJohn Forte 		pkt = ha->response_ring_ptr;
1432fcf3ce44SJohn Forte 
1433fcf3ce44SJohn Forte 		QL_PRINT_5(CE_CONT, "(%d): ha->rsp_rg_idx=%xh, mbx[5]=%xh\n",
1434fcf3ce44SJohn Forte 		    ha->instance, ha->rsp_ring_index, ha->isp_rsp_index);
1435fcf3ce44SJohn Forte 		QL_DUMP_5((uint8_t *)ha->response_ring_ptr, 8,
1436fcf3ce44SJohn Forte 		    RESPONSE_ENTRY_SIZE);
1437fcf3ce44SJohn Forte 
1438fcf3ce44SJohn Forte 		/* Adjust ring index. */
1439fcf3ce44SJohn Forte 		ha->rsp_ring_index++;
1440fcf3ce44SJohn Forte 		if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) {
1441fcf3ce44SJohn Forte 			ha->rsp_ring_index = 0;
1442fcf3ce44SJohn Forte 			ha->response_ring_ptr = ha->response_ring_bp;
1443fcf3ce44SJohn Forte 		} else {
1444fcf3ce44SJohn Forte 			ha->response_ring_ptr++;
1445fcf3ce44SJohn Forte 		}
1446fcf3ce44SJohn Forte 
1447fcf3ce44SJohn Forte 		/* Process packet. */
1448fcf3ce44SJohn Forte 		if (ha->status_srb != NULL && pkt->entry_type !=
1449fcf3ce44SJohn Forte 		    STATUS_CONT_TYPE) {
1450fcf3ce44SJohn Forte 			ql_add_link_b(done_q, &ha->status_srb->cmd);
1451fcf3ce44SJohn Forte 			ha->status_srb = NULL;
1452fcf3ce44SJohn Forte 		}
1453fcf3ce44SJohn Forte 
1454fcf3ce44SJohn Forte 		pkt->entry_status = (uint8_t)(CFG_IST(ha, CFG_CTRL_2425) ?
1455fcf3ce44SJohn Forte 		    pkt->entry_status & 0x3c : pkt->entry_status & 0x7e);
1456fcf3ce44SJohn Forte 
1457fcf3ce44SJohn Forte 		if (pkt->entry_status != 0) {
1458fcf3ce44SJohn Forte 			ql_error_entry(ha, pkt, done_q, set_flags,
1459fcf3ce44SJohn Forte 			    reset_flags);
1460fcf3ce44SJohn Forte 		} else {
1461fcf3ce44SJohn Forte 			switch (pkt->entry_type) {
1462fcf3ce44SJohn Forte 			case STATUS_TYPE:
1463fcf3ce44SJohn Forte 				status |= CFG_IST(ha, CFG_CTRL_2425) ?
1464fcf3ce44SJohn Forte 				    ql_24xx_status_entry(ha,
1465fcf3ce44SJohn Forte 				    (sts_24xx_entry_t *)pkt, done_q, set_flags,
1466fcf3ce44SJohn Forte 				    reset_flags) :
1467fcf3ce44SJohn Forte 				    ql_status_entry(ha, (sts_entry_t *)pkt,
1468fcf3ce44SJohn Forte 				    done_q, set_flags, reset_flags);
1469fcf3ce44SJohn Forte 				break;
1470fcf3ce44SJohn Forte 
1471fcf3ce44SJohn Forte 			case STATUS_CONT_TYPE:
1472fcf3ce44SJohn Forte 				ql_status_cont_entry(ha,
1473fcf3ce44SJohn Forte 				    (sts_cont_entry_t *)pkt, done_q, set_flags,
1474fcf3ce44SJohn Forte 				    reset_flags);
1475fcf3ce44SJohn Forte 				break;
1476fcf3ce44SJohn Forte 
1477fcf3ce44SJohn Forte 			case IMMEDIATE_NOTIFY_TYPE:
1478fcf3ce44SJohn Forte 				if (CFG_IST(ha, CFG_ENABLE_TARGET_MODE)) {
1479fcf3ce44SJohn Forte 					ql_immediate_notify_entry(ha,
1480fcf3ce44SJohn Forte 					    (immediate_notify_entry_t *)pkt,
1481fcf3ce44SJohn Forte 					    done_q, set_flags, reset_flags);
1482fcf3ce44SJohn Forte 				}
1483fcf3ce44SJohn Forte 				break;
1484fcf3ce44SJohn Forte 
1485fcf3ce44SJohn Forte 			case NOTIFY_ACKNOWLEDGE_TYPE:
1486fcf3ce44SJohn Forte 				if (CFG_IST(ha, CFG_ENABLE_TARGET_MODE)) {
1487fcf3ce44SJohn Forte 					ql_notify_acknowledge_entry(ha,
1488fcf3ce44SJohn Forte 					    (notify_acknowledge_entry_t *)pkt,
1489fcf3ce44SJohn Forte 					    done_q, set_flags, reset_flags);
1490fcf3ce44SJohn Forte 				}
1491fcf3ce44SJohn Forte 				break;
1492fcf3ce44SJohn Forte 
1493fcf3ce44SJohn Forte 			case ATIO_TYPE:
1494fcf3ce44SJohn Forte 				if (CFG_IST(ha, CFG_ENABLE_TARGET_MODE)) {
1495fcf3ce44SJohn Forte 					ql_accept_target_io_entry(ha,
1496fcf3ce44SJohn Forte 					    (atio_entry_t *)pkt, done_q,
1497fcf3ce44SJohn Forte 					    set_flags, reset_flags);
1498fcf3ce44SJohn Forte 				}
1499fcf3ce44SJohn Forte 				break;
1500fcf3ce44SJohn Forte 
1501fcf3ce44SJohn Forte 			case CTIO_TYPE_2:
1502fcf3ce44SJohn Forte 			case CTIO_TYPE_3:
1503fcf3ce44SJohn Forte 				if (CFG_IST(ha, CFG_ENABLE_TARGET_MODE)) {
1504fcf3ce44SJohn Forte 					ql_continue_target_io_entry(ha,
1505fcf3ce44SJohn Forte 					    (ctio_entry_t *)pkt, done_q,
1506fcf3ce44SJohn Forte 					    set_flags, reset_flags);
1507fcf3ce44SJohn Forte 				}
1508fcf3ce44SJohn Forte 				break;
1509fcf3ce44SJohn Forte 
1510fcf3ce44SJohn Forte 			case IP_TYPE:
1511fcf3ce44SJohn Forte 			case IP_A64_TYPE:
1512fcf3ce44SJohn Forte 			case IP_CMD_TYPE:
1513fcf3ce44SJohn Forte 				ql_ip_entry(ha, (ip_entry_t *)pkt, done_q,
1514fcf3ce44SJohn Forte 				    set_flags, reset_flags);
1515fcf3ce44SJohn Forte 				break;
1516fcf3ce44SJohn Forte 			case IP_RECEIVE_TYPE:
1517fcf3ce44SJohn Forte 				ql_ip_rcv_entry(ha,
1518fcf3ce44SJohn Forte 				    (ip_rcv_entry_t *)pkt, done_q, set_flags,
1519fcf3ce44SJohn Forte 				    reset_flags);
1520fcf3ce44SJohn Forte 				break;
1521fcf3ce44SJohn Forte 			case IP_RECEIVE_CONT_TYPE:
1522fcf3ce44SJohn Forte 				ql_ip_rcv_cont_entry(ha,
1523fcf3ce44SJohn Forte 				    (ip_rcv_cont_entry_t *)pkt,	done_q,
1524fcf3ce44SJohn Forte 				    set_flags, reset_flags);
1525fcf3ce44SJohn Forte 				break;
1526fcf3ce44SJohn Forte 			case IP_24XX_RECEIVE_TYPE:
1527fcf3ce44SJohn Forte 				ql_ip_24xx_rcv_entry(ha,
1528fcf3ce44SJohn Forte 				    (ip_rcv_24xx_entry_t *)pkt, done_q,
1529fcf3ce44SJohn Forte 				    set_flags, reset_flags);
1530fcf3ce44SJohn Forte 				break;
1531fcf3ce44SJohn Forte 			case MS_TYPE:
1532fcf3ce44SJohn Forte 				ql_ms_entry(ha, (ms_entry_t *)pkt, done_q,
1533fcf3ce44SJohn Forte 				    set_flags, reset_flags);
1534fcf3ce44SJohn Forte 				break;
1535fcf3ce44SJohn Forte 			case REPORT_ID_TYPE:
1536fcf3ce44SJohn Forte 				ql_report_id_entry(ha, (report_id_1_t *)pkt,
1537fcf3ce44SJohn Forte 				    done_q, set_flags, reset_flags);
1538fcf3ce44SJohn Forte 				break;
1539fcf3ce44SJohn Forte 			case IP_BUF_POOL_TYPE:
1540fcf3ce44SJohn Forte 			case MARKER_TYPE:
1541fcf3ce44SJohn Forte 			case VP_MODIFY_TYPE:
1542fcf3ce44SJohn Forte 			case VP_CONTROL_TYPE:
1543fcf3ce44SJohn Forte 				break;
1544fcf3ce44SJohn Forte 			default:
1545fcf3ce44SJohn Forte 				EL(ha, "Unknown IOCB entry type=%xh\n",
1546fcf3ce44SJohn Forte 				    pkt->entry_type);
1547fcf3ce44SJohn Forte 				break;
1548fcf3ce44SJohn Forte 			}
1549fcf3ce44SJohn Forte 		}
1550fcf3ce44SJohn Forte 	}
1551fcf3ce44SJohn Forte 
1552fcf3ce44SJohn Forte 	/* Inform RISC of processed responses. */
1553fcf3ce44SJohn Forte 	WRT16_IO_REG(ha, resp_out, ha->rsp_ring_index);
1554fcf3ce44SJohn Forte 
1555fcf3ce44SJohn Forte 	/* RESET packet received delay for possible async event. */
1556fcf3ce44SJohn Forte 	if (status & BIT_0) {
1557fcf3ce44SJohn Forte 		drv_usecwait(500000);
1558fcf3ce44SJohn Forte 	}
1559fcf3ce44SJohn Forte 
1560fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1561fcf3ce44SJohn Forte }
1562fcf3ce44SJohn Forte 
1563fcf3ce44SJohn Forte /*
1564fcf3ce44SJohn Forte  * ql_error_entry
1565fcf3ce44SJohn Forte  *	Processes error entry.
1566fcf3ce44SJohn Forte  *
1567fcf3ce44SJohn Forte  * Input:
1568fcf3ce44SJohn Forte  *	ha = adapter state pointer.
1569fcf3ce44SJohn Forte  *	pkt = entry pointer.
1570fcf3ce44SJohn Forte  *	done_q = head pointer to done queue.
1571fcf3ce44SJohn Forte  *	set_flags = task daemon flags to set.
1572fcf3ce44SJohn Forte  *	reset_flags = task daemon flags to reset.
1573fcf3ce44SJohn Forte  *
1574fcf3ce44SJohn Forte  * Context:
1575fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1576fcf3ce44SJohn Forte  */
1577fcf3ce44SJohn Forte /* ARGSUSED */
1578fcf3ce44SJohn Forte static void
1579fcf3ce44SJohn Forte ql_error_entry(ql_adapter_state_t *ha, response_t *pkt, ql_head_t *done_q,
1580fcf3ce44SJohn Forte     uint32_t *set_flags, uint32_t *reset_flags)
1581fcf3ce44SJohn Forte {
1582fcf3ce44SJohn Forte 	ql_srb_t	*sp;
1583fcf3ce44SJohn Forte 	uint32_t	index, cnt;
1584fcf3ce44SJohn Forte 
1585fcf3ce44SJohn Forte 	if (pkt->entry_type == INVALID_ENTRY_TYPE) {
1586fcf3ce44SJohn Forte 		EL(ha, "Aborted command\n");
1587fcf3ce44SJohn Forte 		return;
1588fcf3ce44SJohn Forte 	}
1589fcf3ce44SJohn Forte 
1590fcf3ce44SJohn Forte 	QL_PRINT_2(CE_CONT, "(%d): started, packet:\n", ha->instance);
1591fcf3ce44SJohn Forte 	QL_DUMP_2((uint8_t *)pkt, 8, RESPONSE_ENTRY_SIZE);
1592fcf3ce44SJohn Forte 
1593fcf3ce44SJohn Forte 	if (pkt->entry_status & BIT_6) {
1594fcf3ce44SJohn Forte 		EL(ha, "Request Queue DMA error\n");
1595fcf3ce44SJohn Forte 	} else if (pkt->entry_status & BIT_5) {
1596fcf3ce44SJohn Forte 		EL(ha, "Invalid Entry Order\n");
1597fcf3ce44SJohn Forte 	} else if (pkt->entry_status & BIT_4) {
1598fcf3ce44SJohn Forte 		EL(ha, "Invalid Entry Count\n");
1599fcf3ce44SJohn Forte 	} else if (pkt->entry_status & BIT_3) {
1600fcf3ce44SJohn Forte 		EL(ha, "Invalid Entry Parameter\n");
1601fcf3ce44SJohn Forte 	} else if (pkt->entry_status & BIT_2) {
1602fcf3ce44SJohn Forte 		EL(ha, "Invalid Entry Type\n");
1603fcf3ce44SJohn Forte 	} else if (pkt->entry_status & BIT_1) {
1604fcf3ce44SJohn Forte 		EL(ha, "Busy\n");
1605fcf3ce44SJohn Forte 	} else {
1606fcf3ce44SJohn Forte 		EL(ha, "UNKNOWN flag = %xh error\n", pkt->entry_status);
1607fcf3ce44SJohn Forte 	}
1608fcf3ce44SJohn Forte 
1609fcf3ce44SJohn Forte 	/* Get handle. */
1610fcf3ce44SJohn Forte 	cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
1611fcf3ce44SJohn Forte 	index = cnt & OSC_INDEX_MASK;
1612fcf3ce44SJohn Forte 
1613fcf3ce44SJohn Forte 	/* Validate handle. */
1614fcf3ce44SJohn Forte 	sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] :
1615fcf3ce44SJohn Forte 	    NULL;
1616fcf3ce44SJohn Forte 
1617fcf3ce44SJohn Forte 	if (sp != NULL && sp->handle == cnt) {
1618fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
1619fcf3ce44SJohn Forte 		sp->handle = 0;
1620fcf3ce44SJohn Forte 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
1621fcf3ce44SJohn Forte 
1622fcf3ce44SJohn Forte 		/* Bad payload or header */
1623fcf3ce44SJohn Forte 		if (pkt->entry_status & (BIT_5 + BIT_4 + BIT_3 + BIT_2)) {
1624fcf3ce44SJohn Forte 			/* Bad payload or header, set error status. */
1625fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_BAD_PAYLOAD;
1626fcf3ce44SJohn Forte 		} else if (pkt->entry_status & BIT_1) /* FULL flag */ {
1627fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_QUEUE_FULL;
1628fcf3ce44SJohn Forte 		} else {
1629fcf3ce44SJohn Forte 			/* Set error status. */
1630fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_UNKNOWN;
1631fcf3ce44SJohn Forte 		}
1632fcf3ce44SJohn Forte 
1633fcf3ce44SJohn Forte 		/* Set completed status. */
1634fcf3ce44SJohn Forte 		sp->flags |= SRB_ISP_COMPLETED;
1635fcf3ce44SJohn Forte 
1636fcf3ce44SJohn Forte 		/* Place command on done queue. */
1637fcf3ce44SJohn Forte 		ql_add_link_b(done_q, &sp->cmd);
1638fcf3ce44SJohn Forte 
1639fcf3ce44SJohn Forte 	} else {
1640fcf3ce44SJohn Forte 		if (sp == NULL) {
1641fcf3ce44SJohn Forte 			EL(ha, "unknown IOCB handle=%xh\n", cnt);
1642fcf3ce44SJohn Forte 		} else {
1643fcf3ce44SJohn Forte 			EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n",
1644fcf3ce44SJohn Forte 			    cnt, sp->handle);
1645fcf3ce44SJohn Forte 		}
1646fcf3ce44SJohn Forte 
1647fcf3ce44SJohn Forte 		(void) ql_binary_fw_dump(ha, FALSE);
1648fcf3ce44SJohn Forte 
1649fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED |
1650fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE))) {
1651fcf3ce44SJohn Forte 			EL(ha, "ISP Invalid handle, isp_abort_needed\n");
1652fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
1653fcf3ce44SJohn Forte 		}
1654fcf3ce44SJohn Forte 	}
1655fcf3ce44SJohn Forte 
1656fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1657fcf3ce44SJohn Forte }
1658fcf3ce44SJohn Forte 
1659fcf3ce44SJohn Forte /*
1660fcf3ce44SJohn Forte  * ql_status_entry
1661fcf3ce44SJohn Forte  *	Processes received ISP2200-2300 status entry.
1662fcf3ce44SJohn Forte  *
1663fcf3ce44SJohn Forte  * Input:
1664fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
1665fcf3ce44SJohn Forte  *	pkt:		entry pointer.
1666fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
1667fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
1668fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
1669fcf3ce44SJohn Forte  *
1670fcf3ce44SJohn Forte  * Returns:
1671fcf3ce44SJohn Forte  *	BIT_0 = CS_RESET status received.
1672fcf3ce44SJohn Forte  *
1673fcf3ce44SJohn Forte  * Context:
1674fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1675fcf3ce44SJohn Forte  */
1676fcf3ce44SJohn Forte /* ARGSUSED */
1677fcf3ce44SJohn Forte static int
1678fcf3ce44SJohn Forte ql_status_entry(ql_adapter_state_t *ha, sts_entry_t *pkt,
1679fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
1680fcf3ce44SJohn Forte {
1681fcf3ce44SJohn Forte 	ql_srb_t		*sp;
1682fcf3ce44SJohn Forte 	uint32_t		index, cnt;
1683fcf3ce44SJohn Forte 	uint16_t		comp_status;
1684fcf3ce44SJohn Forte 	int			rval = 0;
1685fcf3ce44SJohn Forte 
1686fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1687fcf3ce44SJohn Forte 
1688fcf3ce44SJohn Forte 	/* Get handle. */
1689fcf3ce44SJohn Forte 	cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
1690fcf3ce44SJohn Forte 	index = cnt & OSC_INDEX_MASK;
1691fcf3ce44SJohn Forte 
1692fcf3ce44SJohn Forte 	/* Validate handle. */
1693fcf3ce44SJohn Forte 	sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] :
1694fcf3ce44SJohn Forte 	    NULL;
1695fcf3ce44SJohn Forte 
1696fcf3ce44SJohn Forte 	if (sp != NULL && sp->handle == cnt) {
1697fcf3ce44SJohn Forte 		comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
1698fcf3ce44SJohn Forte 		    &pkt->comp_status);
1699fcf3ce44SJohn Forte 
1700fcf3ce44SJohn Forte 		/*
1701fcf3ce44SJohn Forte 		 * We dont care about SCSI QFULLs.
1702fcf3ce44SJohn Forte 		 */
1703fcf3ce44SJohn Forte 		if (comp_status == CS_QUEUE_FULL) {
1704fcf3ce44SJohn Forte 			EL(ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n",
1705fcf3ce44SJohn Forte 			    sp->lun_queue->target_queue->d_id.b24,
1706fcf3ce44SJohn Forte 			    sp->lun_queue->lun_no);
1707fcf3ce44SJohn Forte 			comp_status = CS_COMPLETE;
1708fcf3ce44SJohn Forte 		}
1709fcf3ce44SJohn Forte 
1710fcf3ce44SJohn Forte 		/*
1711fcf3ce44SJohn Forte 		 * 2300 firmware marks completion status as data underrun
1712fcf3ce44SJohn Forte 		 * for scsi qfulls. Make it transport complete.
1713fcf3ce44SJohn Forte 		 */
1714fcf3ce44SJohn Forte 		if ((CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) &&
1715fcf3ce44SJohn Forte 		    (comp_status == CS_DATA_UNDERRUN) &&
1716fcf3ce44SJohn Forte 		    (pkt->scsi_status_l != 0)) {
1717fcf3ce44SJohn Forte 			comp_status = CS_COMPLETE;
1718fcf3ce44SJohn Forte 		}
1719fcf3ce44SJohn Forte 
1720fcf3ce44SJohn Forte 		/*
1721fcf3ce44SJohn Forte 		 * Workaround T3 issue where we do not get any data xferred
1722fcf3ce44SJohn Forte 		 * but get back a good status.
1723fcf3ce44SJohn Forte 		 */
1724fcf3ce44SJohn Forte 		if ((pkt->state_flags_h & SF_XFERRED_DATA) == 0 &&
1725fcf3ce44SJohn Forte 		    comp_status == CS_COMPLETE &&
1726fcf3ce44SJohn Forte 		    pkt->scsi_status_l == 0 &&
1727fcf3ce44SJohn Forte 		    (pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
1728fcf3ce44SJohn Forte 		    pkt->residual_length == 0 &&
1729fcf3ce44SJohn Forte 		    sp->fcp &&
1730fcf3ce44SJohn Forte 		    sp->fcp->fcp_data_len != 0 &&
1731fcf3ce44SJohn Forte 		    (pkt->state_flags_l & (SF_DATA_OUT | SF_DATA_IN)) ==
1732fcf3ce44SJohn Forte 		    SF_DATA_OUT) {
1733fcf3ce44SJohn Forte 			comp_status = CS_ABORTED;
1734fcf3ce44SJohn Forte 		}
1735fcf3ce44SJohn Forte 
1736fcf3ce44SJohn Forte 		if (sp->flags & SRB_MS_PKT) {
1737fcf3ce44SJohn Forte 			/*
1738fcf3ce44SJohn Forte 			 * Ideally it should never be true. But there
1739fcf3ce44SJohn Forte 			 * is a bug in FW which upon receiving invalid
1740fcf3ce44SJohn Forte 			 * parameters in MS IOCB returns it as
1741fcf3ce44SJohn Forte 			 * status entry and not as ms entry type.
1742fcf3ce44SJohn Forte 			 */
1743fcf3ce44SJohn Forte 			ql_ms_entry(ha, (ms_entry_t *)pkt, done_q,
1744fcf3ce44SJohn Forte 			    set_flags, reset_flags);
1745fcf3ce44SJohn Forte 			QL_PRINT_3(CE_CONT, "(%d): ql_ms_entry done\n",
1746fcf3ce44SJohn Forte 			    ha->instance);
1747fcf3ce44SJohn Forte 			return (0);
1748fcf3ce44SJohn Forte 		}
1749fcf3ce44SJohn Forte 
1750fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
1751fcf3ce44SJohn Forte 		sp->handle = 0;
1752fcf3ce44SJohn Forte 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
1753fcf3ce44SJohn Forte 
1754fcf3ce44SJohn Forte 		/*
1755fcf3ce44SJohn Forte 		 * Fast path to good SCSI I/O completion
1756fcf3ce44SJohn Forte 		 */
1757fcf3ce44SJohn Forte 		if ((comp_status == CS_COMPLETE) &
1758fcf3ce44SJohn Forte 		    (!pkt->scsi_status_l) &
1759fcf3ce44SJohn Forte 		    (!(pkt->scsi_status_h & FCP_RSP_MASK))) {
1760fcf3ce44SJohn Forte 			/* Set completed status. */
1761fcf3ce44SJohn Forte 			sp->flags |= SRB_ISP_COMPLETED;
1762fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = comp_status;
1763fcf3ce44SJohn Forte 			ql_fast_fcp_post(sp);
1764fcf3ce44SJohn Forte 			QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n",
1765fcf3ce44SJohn Forte 			    ha->instance);
1766fcf3ce44SJohn Forte 			return (0);
1767fcf3ce44SJohn Forte 		}
1768fcf3ce44SJohn Forte 		rval = ql_status_error(ha, sp, pkt, done_q, set_flags,
1769fcf3ce44SJohn Forte 		    reset_flags);
1770fcf3ce44SJohn Forte 	} else {
1771fcf3ce44SJohn Forte 		if (sp == NULL) {
1772fcf3ce44SJohn Forte 			EL(ha, "unknown IOCB handle=%xh\n", cnt);
1773fcf3ce44SJohn Forte 		} else {
1774fcf3ce44SJohn Forte 			EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n",
1775fcf3ce44SJohn Forte 			    cnt, sp->handle);
1776fcf3ce44SJohn Forte 		}
1777fcf3ce44SJohn Forte 
1778fcf3ce44SJohn Forte 		(void) ql_binary_fw_dump(ha, FALSE);
1779fcf3ce44SJohn Forte 
1780fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED |
1781fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE))) {
1782fcf3ce44SJohn Forte 			EL(ha, "ISP Invalid handle, isp_abort_needed\n");
1783fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
1784fcf3ce44SJohn Forte 		}
1785fcf3ce44SJohn Forte 	}
1786fcf3ce44SJohn Forte 
1787fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1788fcf3ce44SJohn Forte 
1789fcf3ce44SJohn Forte 	return (rval);
1790fcf3ce44SJohn Forte }
1791fcf3ce44SJohn Forte 
1792fcf3ce44SJohn Forte /*
1793fcf3ce44SJohn Forte  * ql_24xx_status_entry
1794fcf3ce44SJohn Forte  *	Processes received ISP24xx status entry.
1795fcf3ce44SJohn Forte  *
1796fcf3ce44SJohn Forte  * Input:
1797fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
1798fcf3ce44SJohn Forte  *	pkt:		entry pointer.
1799fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
1800fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
1801fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
1802fcf3ce44SJohn Forte  *
1803fcf3ce44SJohn Forte  * Returns:
1804fcf3ce44SJohn Forte  *	BIT_0 = CS_RESET status received.
1805fcf3ce44SJohn Forte  *
1806fcf3ce44SJohn Forte  * Context:
1807fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1808fcf3ce44SJohn Forte  */
1809fcf3ce44SJohn Forte /* ARGSUSED */
1810fcf3ce44SJohn Forte static int
1811fcf3ce44SJohn Forte ql_24xx_status_entry(ql_adapter_state_t *ha, sts_24xx_entry_t *pkt,
1812fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
1813fcf3ce44SJohn Forte {
1814fcf3ce44SJohn Forte 	ql_srb_t		*sp;
1815*16dd44c2SDaniel Beauregard 	uint32_t		index;
1816*16dd44c2SDaniel Beauregard 	uint32_t		resp_identifier;
1817fcf3ce44SJohn Forte 	uint16_t		comp_status;
1818fcf3ce44SJohn Forte 	int			rval = 0;
1819fcf3ce44SJohn Forte 
1820fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1821fcf3ce44SJohn Forte 
1822*16dd44c2SDaniel Beauregard 	/* Get the response identifier. */
1823*16dd44c2SDaniel Beauregard 	resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
1824fcf3ce44SJohn Forte 
1825*16dd44c2SDaniel Beauregard 	/* extract the outstanding cmds index */
1826*16dd44c2SDaniel Beauregard 	index = resp_identifier & OSC_INDEX_MASK;
1827*16dd44c2SDaniel Beauregard 
1828*16dd44c2SDaniel Beauregard 	/* Validate the index and get the associated srb pointer */
1829fcf3ce44SJohn Forte 	sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] :
1830fcf3ce44SJohn Forte 	    NULL;
1831fcf3ce44SJohn Forte 
1832*16dd44c2SDaniel Beauregard 	if (sp != NULL && sp->handle == resp_identifier) {
1833fcf3ce44SJohn Forte 		comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
1834fcf3ce44SJohn Forte 		    &pkt->comp_status);
1835fcf3ce44SJohn Forte 
1836fcf3ce44SJohn Forte 		/*
1837fcf3ce44SJohn Forte 		 * We dont care about SCSI QFULLs.
1838fcf3ce44SJohn Forte 		 */
1839fcf3ce44SJohn Forte 		if (comp_status == CS_QUEUE_FULL) {
1840fcf3ce44SJohn Forte 			EL(sp->ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n",
1841fcf3ce44SJohn Forte 			    sp->lun_queue->target_queue->d_id.b24,
1842fcf3ce44SJohn Forte 			    sp->lun_queue->lun_no);
1843fcf3ce44SJohn Forte 			comp_status = CS_COMPLETE;
1844fcf3ce44SJohn Forte 		}
1845fcf3ce44SJohn Forte 
1846fcf3ce44SJohn Forte 		/*
1847fcf3ce44SJohn Forte 		 * 2300 firmware marks completion status as data underrun
1848fcf3ce44SJohn Forte 		 * for scsi qfulls. Make it transport complete.
1849fcf3ce44SJohn Forte 		 */
1850fcf3ce44SJohn Forte 		if ((comp_status == CS_DATA_UNDERRUN) &&
1851fcf3ce44SJohn Forte 		    (pkt->scsi_status_l != 0)) {
1852fcf3ce44SJohn Forte 			comp_status = CS_COMPLETE;
1853fcf3ce44SJohn Forte 		}
1854fcf3ce44SJohn Forte 
1855fcf3ce44SJohn Forte 		/*
1856fcf3ce44SJohn Forte 		 * Workaround T3 issue where we do not get any data xferred
1857fcf3ce44SJohn Forte 		 * but get back a good status.
1858fcf3ce44SJohn Forte 		 */
1859fcf3ce44SJohn Forte 		if (comp_status == CS_COMPLETE &&
1860fcf3ce44SJohn Forte 		    pkt->scsi_status_l == 0 &&
1861fcf3ce44SJohn Forte 		    (pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
1862fcf3ce44SJohn Forte 		    pkt->residual_length != 0 &&
1863fcf3ce44SJohn Forte 		    sp->fcp &&
1864fcf3ce44SJohn Forte 		    sp->fcp->fcp_data_len != 0 &&
1865fcf3ce44SJohn Forte 		    sp->fcp->fcp_cntl.cntl_write_data) {
1866fcf3ce44SJohn Forte 			comp_status = CS_ABORTED;
1867fcf3ce44SJohn Forte 		}
1868fcf3ce44SJohn Forte 
1869fcf3ce44SJohn Forte 		if (sp->flags & SRB_MS_PKT) {
1870fcf3ce44SJohn Forte 			/*
1871fcf3ce44SJohn Forte 			 * Ideally it should never be true. But there
1872fcf3ce44SJohn Forte 			 * is a bug in FW which upon receiving invalid
1873fcf3ce44SJohn Forte 			 * parameters in MS IOCB returns it as
1874fcf3ce44SJohn Forte 			 * status entry and not as ms entry type.
1875fcf3ce44SJohn Forte 			 */
1876fcf3ce44SJohn Forte 			ql_ms_entry(ha, (ms_entry_t *)pkt, done_q,
1877fcf3ce44SJohn Forte 			    set_flags, reset_flags);
1878fcf3ce44SJohn Forte 			QL_PRINT_3(CE_CONT, "(%d): ql_ms_entry done\n",
1879fcf3ce44SJohn Forte 			    ha->instance);
1880fcf3ce44SJohn Forte 			return (0);
1881fcf3ce44SJohn Forte 		}
1882fcf3ce44SJohn Forte 
1883fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
1884fcf3ce44SJohn Forte 		sp->handle = 0;
1885fcf3ce44SJohn Forte 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
1886fcf3ce44SJohn Forte 
1887fcf3ce44SJohn Forte 		/*
1888fcf3ce44SJohn Forte 		 * Fast path to good SCSI I/O completion
1889fcf3ce44SJohn Forte 		 */
1890fcf3ce44SJohn Forte 		if ((comp_status == CS_COMPLETE) &
1891fcf3ce44SJohn Forte 		    (!pkt->scsi_status_l) &
1892fcf3ce44SJohn Forte 		    (!(pkt->scsi_status_h & FCP_RSP_MASK))) {
1893fcf3ce44SJohn Forte 			/* Set completed status. */
1894fcf3ce44SJohn Forte 			sp->flags |= SRB_ISP_COMPLETED;
1895fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = comp_status;
1896fcf3ce44SJohn Forte 			ql_fast_fcp_post(sp);
1897fcf3ce44SJohn Forte 			QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n",
1898fcf3ce44SJohn Forte 			    ha->instance);
1899fcf3ce44SJohn Forte 			return (0);
1900fcf3ce44SJohn Forte 		}
1901fcf3ce44SJohn Forte 		rval = ql_status_error(ha, sp, (sts_entry_t *)pkt, done_q,
1902fcf3ce44SJohn Forte 		    set_flags, reset_flags);
1903fcf3ce44SJohn Forte 	} else {
1904fcf3ce44SJohn Forte 		if (sp == NULL) {
1905*16dd44c2SDaniel Beauregard 			EL(ha, "unknown IOCB handle=%xh\n", resp_identifier);
1906fcf3ce44SJohn Forte 		} else {
1907fcf3ce44SJohn Forte 			EL(sp->ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n",
1908*16dd44c2SDaniel Beauregard 			    resp_identifier, sp->handle);
1909fcf3ce44SJohn Forte 		}
1910fcf3ce44SJohn Forte 
1911fcf3ce44SJohn Forte 		(void) ql_binary_fw_dump(ha, FALSE);
1912fcf3ce44SJohn Forte 
1913fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED |
1914fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE))) {
1915fcf3ce44SJohn Forte 			EL(ha, "ISP Invalid handle, isp_abort_needed\n");
1916fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
1917fcf3ce44SJohn Forte 		}
1918fcf3ce44SJohn Forte 	}
1919fcf3ce44SJohn Forte 
1920fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1921fcf3ce44SJohn Forte 
1922fcf3ce44SJohn Forte 	return (rval);
1923fcf3ce44SJohn Forte }
1924fcf3ce44SJohn Forte 
1925fcf3ce44SJohn Forte /*
1926fcf3ce44SJohn Forte  * ql_status_error
1927fcf3ce44SJohn Forte  *	Processes received ISP status entry error.
1928fcf3ce44SJohn Forte  *
1929fcf3ce44SJohn Forte  * Input:
1930fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
1931fcf3ce44SJohn Forte  *	sp:		SRB pointer.
1932fcf3ce44SJohn Forte  *	pkt:		entry pointer.
1933fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
1934fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
1935fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
1936fcf3ce44SJohn Forte  *
1937fcf3ce44SJohn Forte  * Returns:
1938fcf3ce44SJohn Forte  *	BIT_0 = CS_RESET status received.
1939fcf3ce44SJohn Forte  *
1940fcf3ce44SJohn Forte  * Context:
1941fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
1942fcf3ce44SJohn Forte  */
1943fcf3ce44SJohn Forte /* ARGSUSED */
1944fcf3ce44SJohn Forte static int
1945fcf3ce44SJohn Forte ql_status_error(ql_adapter_state_t *ha, ql_srb_t *sp, sts_entry_t *pkt23,
1946fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
1947fcf3ce44SJohn Forte {
1948fcf3ce44SJohn Forte 	uint32_t		sense_sz = 0;
1949fcf3ce44SJohn Forte 	uint32_t		cnt;
1950fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
1951fcf3ce44SJohn Forte 	fcp_rsp_t		*fcpr;
1952fcf3ce44SJohn Forte 	struct fcp_rsp_info	*rsp;
1953fcf3ce44SJohn Forte 	int			rval = 0;
1954fcf3ce44SJohn Forte 
1955fcf3ce44SJohn Forte 	struct {
1956fcf3ce44SJohn Forte 		uint8_t		*rsp_info;
1957fcf3ce44SJohn Forte 		uint8_t		*req_sense_data;
1958fcf3ce44SJohn Forte 		uint32_t	residual_length;
1959fcf3ce44SJohn Forte 		uint32_t	fcp_residual_length;
1960fcf3ce44SJohn Forte 		uint32_t	rsp_info_length;
1961fcf3ce44SJohn Forte 		uint32_t	req_sense_length;
1962fcf3ce44SJohn Forte 		uint16_t	comp_status;
1963fcf3ce44SJohn Forte 		uint8_t		state_flags_l;
1964fcf3ce44SJohn Forte 		uint8_t		state_flags_h;
1965fcf3ce44SJohn Forte 		uint8_t		scsi_status_l;
1966fcf3ce44SJohn Forte 		uint8_t		scsi_status_h;
1967fcf3ce44SJohn Forte 	} sts;
1968fcf3ce44SJohn Forte 
1969fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1970fcf3ce44SJohn Forte 
1971fcf3ce44SJohn Forte 	if (CFG_IST(ha, CFG_CTRL_2425)) {
1972fcf3ce44SJohn Forte 		sts_24xx_entry_t *pkt24 = (sts_24xx_entry_t *)pkt23;
1973fcf3ce44SJohn Forte 
1974fcf3ce44SJohn Forte 		/* Setup status. */
1975fcf3ce44SJohn Forte 		sts.comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
1976fcf3ce44SJohn Forte 		    &pkt24->comp_status);
1977fcf3ce44SJohn Forte 		sts.scsi_status_l = pkt24->scsi_status_l;
1978fcf3ce44SJohn Forte 		sts.scsi_status_h = pkt24->scsi_status_h;
1979fcf3ce44SJohn Forte 
1980fcf3ce44SJohn Forte 		/* Setup firmware residuals. */
1981fcf3ce44SJohn Forte 		sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
1982fcf3ce44SJohn Forte 		    ddi_get32(ha->hba_buf.acc_handle,
1983fcf3ce44SJohn Forte 		    (uint32_t *)&pkt24->residual_length) : 0;
1984fcf3ce44SJohn Forte 
1985fcf3ce44SJohn Forte 		/* Setup FCP residuals. */
1986fcf3ce44SJohn Forte 		sts.fcp_residual_length = sts.scsi_status_h &
1987fcf3ce44SJohn Forte 		    (FCP_RESID_UNDER | FCP_RESID_OVER) ?
1988fcf3ce44SJohn Forte 		    ddi_get32(ha->hba_buf.acc_handle,
1989fcf3ce44SJohn Forte 		    (uint32_t *)&pkt24->fcp_rsp_residual_count) : 0;
1990fcf3ce44SJohn Forte 
1991fcf3ce44SJohn Forte 		if ((sts.comp_status == CS_DATA_UNDERRUN) &&
1992fcf3ce44SJohn Forte 		    (sts.scsi_status_h & FCP_RESID_UNDER) &&
1993fcf3ce44SJohn Forte 		    (sts.residual_length != pkt24->fcp_rsp_residual_count)) {
1994fcf3ce44SJohn Forte 
1995fcf3ce44SJohn Forte 			EL(sp->ha, "mismatch resid's: fw=%xh, pkt=%xh\n",
1996fcf3ce44SJohn Forte 			    sts.residual_length,
1997fcf3ce44SJohn Forte 			    pkt24->fcp_rsp_residual_count);
1998fcf3ce44SJohn Forte 			sts.scsi_status_h = (uint8_t)
1999fcf3ce44SJohn Forte 			    (sts.scsi_status_h & ~FCP_RESID_UNDER);
2000fcf3ce44SJohn Forte 		}
2001fcf3ce44SJohn Forte 
2002fcf3ce44SJohn Forte 		/* Setup state flags. */
2003fcf3ce44SJohn Forte 		sts.state_flags_l = pkt24->state_flags_l;
2004fcf3ce44SJohn Forte 		sts.state_flags_h = pkt24->state_flags_h;
2005fcf3ce44SJohn Forte 
2006fcf3ce44SJohn Forte 		if (sp->fcp->fcp_data_len &&
2007fcf3ce44SJohn Forte 		    (sts.comp_status != CS_DATA_UNDERRUN ||
2008fcf3ce44SJohn Forte 		    sts.residual_length != sp->fcp->fcp_data_len)) {
2009fcf3ce44SJohn Forte 			sts.state_flags_h = (uint8_t)
2010fcf3ce44SJohn Forte 			    (sts.state_flags_h | SF_GOT_BUS |
2011fcf3ce44SJohn Forte 			    SF_GOT_TARGET | SF_SENT_CMD |
2012fcf3ce44SJohn Forte 			    SF_XFERRED_DATA | SF_GOT_STATUS);
2013fcf3ce44SJohn Forte 		} else {
2014fcf3ce44SJohn Forte 			sts.state_flags_h = (uint8_t)
2015fcf3ce44SJohn Forte 			    (sts.state_flags_h | SF_GOT_BUS |
2016fcf3ce44SJohn Forte 			    SF_GOT_TARGET | SF_SENT_CMD |
2017fcf3ce44SJohn Forte 			    SF_GOT_STATUS);
2018fcf3ce44SJohn Forte 		}
2019fcf3ce44SJohn Forte 		if (sp->fcp->fcp_cntl.cntl_write_data) {
2020fcf3ce44SJohn Forte 			sts.state_flags_l = (uint8_t)
2021fcf3ce44SJohn Forte 			    (sts.state_flags_l | SF_DATA_OUT);
2022fcf3ce44SJohn Forte 		} else if (sp->fcp->fcp_cntl.cntl_read_data) {
2023fcf3ce44SJohn Forte 			sts.state_flags_l = (uint8_t)
2024fcf3ce44SJohn Forte 			    (sts.state_flags_l | SF_DATA_IN);
2025fcf3ce44SJohn Forte 		}
2026fcf3ce44SJohn Forte 		if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) {
2027fcf3ce44SJohn Forte 			sts.state_flags_l = (uint8_t)
2028fcf3ce44SJohn Forte 			    (sts.state_flags_l | SF_HEAD_OF_Q);
2029fcf3ce44SJohn Forte 		} else if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) {
2030fcf3ce44SJohn Forte 			sts.state_flags_l = (uint8_t)
2031fcf3ce44SJohn Forte 			    (sts.state_flags_l | SF_ORDERED_Q);
2032fcf3ce44SJohn Forte 		} else if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) {
2033fcf3ce44SJohn Forte 			sts.state_flags_l = (uint8_t)
2034fcf3ce44SJohn Forte 			    (sts.state_flags_l | SF_SIMPLE_Q);
2035fcf3ce44SJohn Forte 		}
2036fcf3ce44SJohn Forte 
2037fcf3ce44SJohn Forte 		/* Setup FCP response info. */
2038fcf3ce44SJohn Forte 		sts.rsp_info = &pkt24->rsp_sense_data[0];
2039fcf3ce44SJohn Forte 		if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
2040fcf3ce44SJohn Forte 			sts.rsp_info_length = ddi_get32(ha->hba_buf.acc_handle,
2041fcf3ce44SJohn Forte 			    (uint32_t *)&pkt24->fcp_rsp_data_length);
2042fcf3ce44SJohn Forte 			if (sts.rsp_info_length >
2043fcf3ce44SJohn Forte 			    sizeof (struct fcp_rsp_info)) {
2044fcf3ce44SJohn Forte 				sts.rsp_info_length =
2045fcf3ce44SJohn Forte 				    sizeof (struct fcp_rsp_info);
2046fcf3ce44SJohn Forte 			}
2047fcf3ce44SJohn Forte 			for (cnt = 0; cnt < sts.rsp_info_length; cnt += 4) {
2048fcf3ce44SJohn Forte 				ql_chg_endian(sts.rsp_info + cnt, 4);
2049fcf3ce44SJohn Forte 			}
2050fcf3ce44SJohn Forte 		} else {
2051fcf3ce44SJohn Forte 			sts.rsp_info_length = 0;
2052fcf3ce44SJohn Forte 		}
2053fcf3ce44SJohn Forte 
2054fcf3ce44SJohn Forte 		/* Setup sense data. */
2055fcf3ce44SJohn Forte 		sts.req_sense_data =
2056fcf3ce44SJohn Forte 		    &pkt24->rsp_sense_data[sts.rsp_info_length];
2057fcf3ce44SJohn Forte 		if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
2058fcf3ce44SJohn Forte 			sts.req_sense_length =
2059fcf3ce44SJohn Forte 			    ddi_get32(ha->hba_buf.acc_handle,
2060fcf3ce44SJohn Forte 			    (uint32_t *)&pkt24->fcp_sense_length);
2061fcf3ce44SJohn Forte 			sts.state_flags_h = (uint8_t)
2062fcf3ce44SJohn Forte 			    (sts.state_flags_h | SF_ARQ_DONE);
2063fcf3ce44SJohn Forte 			sense_sz = (uint32_t)
2064fcf3ce44SJohn Forte 			    (((uintptr_t)pkt24 + sizeof (sts_24xx_entry_t)) -
2065fcf3ce44SJohn Forte 			    (uintptr_t)sts.req_sense_data);
2066fcf3ce44SJohn Forte 			for (cnt = 0; cnt < sense_sz; cnt += 4) {
2067fcf3ce44SJohn Forte 				ql_chg_endian(sts.req_sense_data + cnt, 4);
2068fcf3ce44SJohn Forte 			}
2069fcf3ce44SJohn Forte 		} else {
2070fcf3ce44SJohn Forte 			sts.req_sense_length = 0;
2071fcf3ce44SJohn Forte 		}
2072fcf3ce44SJohn Forte 	} else {
2073fcf3ce44SJohn Forte 		/* Setup status. */
2074fcf3ce44SJohn Forte 		sts.comp_status = (uint16_t)ddi_get16(
2075fcf3ce44SJohn Forte 		    ha->hba_buf.acc_handle, &pkt23->comp_status);
2076fcf3ce44SJohn Forte 		sts.scsi_status_l = pkt23->scsi_status_l;
2077fcf3ce44SJohn Forte 		sts.scsi_status_h = pkt23->scsi_status_h;
2078fcf3ce44SJohn Forte 
2079fcf3ce44SJohn Forte 		/* Setup firmware residuals. */
2080fcf3ce44SJohn Forte 		sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
2081fcf3ce44SJohn Forte 		    ddi_get32(ha->hba_buf.acc_handle,
2082fcf3ce44SJohn Forte 		    (uint32_t *)&pkt23->residual_length) : 0;
2083fcf3ce44SJohn Forte 
2084fcf3ce44SJohn Forte 		/* Setup FCP residuals. */
2085fcf3ce44SJohn Forte 		sts.fcp_residual_length = sts.scsi_status_h &
2086fcf3ce44SJohn Forte 		    (FCP_RESID_UNDER | FCP_RESID_OVER) ?
2087fcf3ce44SJohn Forte 		    sts.residual_length : 0;
2088fcf3ce44SJohn Forte 
2089fcf3ce44SJohn Forte 		/* Setup state flags. */
2090fcf3ce44SJohn Forte 		sts.state_flags_l = pkt23->state_flags_l;
2091fcf3ce44SJohn Forte 		sts.state_flags_h = pkt23->state_flags_h;
2092fcf3ce44SJohn Forte 
2093fcf3ce44SJohn Forte 		/* Setup FCP response info. */
2094fcf3ce44SJohn Forte 		sts.rsp_info = &pkt23->rsp_info[0];
2095fcf3ce44SJohn Forte 		if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
2096fcf3ce44SJohn Forte 			sts.rsp_info_length = ddi_get16(
2097fcf3ce44SJohn Forte 			    ha->hba_buf.acc_handle,
2098fcf3ce44SJohn Forte 			    (uint16_t *)&pkt23->rsp_info_length);
2099fcf3ce44SJohn Forte 			if (sts.rsp_info_length >
2100fcf3ce44SJohn Forte 			    sizeof (struct fcp_rsp_info)) {
2101fcf3ce44SJohn Forte 				sts.rsp_info_length =
2102fcf3ce44SJohn Forte 				    sizeof (struct fcp_rsp_info);
2103fcf3ce44SJohn Forte 			}
2104fcf3ce44SJohn Forte 		} else {
2105fcf3ce44SJohn Forte 			sts.rsp_info_length = 0;
2106fcf3ce44SJohn Forte 		}
2107fcf3ce44SJohn Forte 
2108fcf3ce44SJohn Forte 		/* Setup sense data. */
2109fcf3ce44SJohn Forte 		sts.req_sense_data = &pkt23->req_sense_data[0];
2110fcf3ce44SJohn Forte 		sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ?
2111fcf3ce44SJohn Forte 		    ddi_get16(ha->hba_buf.acc_handle,
2112fcf3ce44SJohn Forte 		    (uint16_t *)&pkt23->req_sense_length) : 0;
2113fcf3ce44SJohn Forte 	}
2114fcf3ce44SJohn Forte 
2115fcf3ce44SJohn Forte 	bzero(sp->pkt->pkt_resp, sp->pkt->pkt_rsplen);
2116fcf3ce44SJohn Forte 
2117fcf3ce44SJohn Forte 	fcpr = (fcp_rsp_t *)sp->pkt->pkt_resp;
2118fcf3ce44SJohn Forte 	rsp = (struct fcp_rsp_info *)(sp->pkt->pkt_resp +
2119fcf3ce44SJohn Forte 	    sizeof (fcp_rsp_t));
2120fcf3ce44SJohn Forte 
2121fcf3ce44SJohn Forte 	tq = sp->lun_queue->target_queue;
2122fcf3ce44SJohn Forte 
2123fcf3ce44SJohn Forte 	fcpr->fcp_u.fcp_status.scsi_status = sts.scsi_status_l;
2124fcf3ce44SJohn Forte 	if (sts.scsi_status_h & FCP_RSP_LEN_VALID) {
2125fcf3ce44SJohn Forte 		fcpr->fcp_u.fcp_status.rsp_len_set = 1;
2126fcf3ce44SJohn Forte 	}
2127fcf3ce44SJohn Forte 	if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
2128fcf3ce44SJohn Forte 		fcpr->fcp_u.fcp_status.sense_len_set = 1;
2129fcf3ce44SJohn Forte 	}
2130fcf3ce44SJohn Forte 	if (sts.scsi_status_h & FCP_RESID_OVER) {
2131fcf3ce44SJohn Forte 		fcpr->fcp_u.fcp_status.resid_over = 1;
2132fcf3ce44SJohn Forte 	}
2133fcf3ce44SJohn Forte 	if (sts.scsi_status_h & FCP_RESID_UNDER) {
2134fcf3ce44SJohn Forte 		fcpr->fcp_u.fcp_status.resid_under = 1;
2135fcf3ce44SJohn Forte 	}
2136fcf3ce44SJohn Forte 	fcpr->fcp_u.fcp_status.reserved_1 = 0;
2137fcf3ce44SJohn Forte 
2138fcf3ce44SJohn Forte 	/* Set ISP completion status */
2139fcf3ce44SJohn Forte 	sp->pkt->pkt_reason = sts.comp_status;
2140fcf3ce44SJohn Forte 
2141fcf3ce44SJohn Forte 	/* Update statistics. */
2142fcf3ce44SJohn Forte 	if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) &&
2143fcf3ce44SJohn Forte 	    (sp->pkt->pkt_rsplen > sizeof (fcp_rsp_t))) {
2144fcf3ce44SJohn Forte 
2145fcf3ce44SJohn Forte 		sense_sz = sp->pkt->pkt_rsplen - (uint32_t)sizeof (fcp_rsp_t);
2146fcf3ce44SJohn Forte 		if (sense_sz > sts.rsp_info_length) {
2147fcf3ce44SJohn Forte 			sense_sz = sts.rsp_info_length;
2148fcf3ce44SJohn Forte 		}
2149fcf3ce44SJohn Forte 
2150fcf3ce44SJohn Forte 		/* copy response information data. */
2151fcf3ce44SJohn Forte 		if (sense_sz) {
2152fcf3ce44SJohn Forte 			ddi_rep_get8(ha->hba_buf.acc_handle, (uint8_t *)rsp,
2153fcf3ce44SJohn Forte 			    sts.rsp_info, sense_sz, DDI_DEV_AUTOINCR);
2154fcf3ce44SJohn Forte 		}
2155fcf3ce44SJohn Forte 		fcpr->fcp_response_len = sense_sz;
2156fcf3ce44SJohn Forte 
2157fcf3ce44SJohn Forte 		rsp = (struct fcp_rsp_info *)((caddr_t)rsp +
2158fcf3ce44SJohn Forte 		    fcpr->fcp_response_len);
2159fcf3ce44SJohn Forte 
2160fcf3ce44SJohn Forte 		switch (*(sts.rsp_info + 3)) {
2161fcf3ce44SJohn Forte 		case FCP_NO_FAILURE:
2162fcf3ce44SJohn Forte 			break;
2163fcf3ce44SJohn Forte 		case FCP_DL_LEN_MISMATCH:
2164fcf3ce44SJohn Forte 			ha->adapter_stats->d_stats[lobyte(
2165fcf3ce44SJohn Forte 			    tq->loop_id)].dl_len_mismatches++;
2166fcf3ce44SJohn Forte 			break;
2167fcf3ce44SJohn Forte 		case FCP_CMND_INVALID:
2168fcf3ce44SJohn Forte 			break;
2169fcf3ce44SJohn Forte 		case FCP_DATA_RO_MISMATCH:
2170fcf3ce44SJohn Forte 			ha->adapter_stats->d_stats[lobyte(
2171fcf3ce44SJohn Forte 			    tq->loop_id)].data_ro_mismatches++;
2172fcf3ce44SJohn Forte 			break;
2173fcf3ce44SJohn Forte 		case FCP_TASK_MGMT_NOT_SUPPTD:
2174fcf3ce44SJohn Forte 			break;
2175fcf3ce44SJohn Forte 		case FCP_TASK_MGMT_FAILED:
2176fcf3ce44SJohn Forte 			ha->adapter_stats->d_stats[lobyte(
2177fcf3ce44SJohn Forte 			    tq->loop_id)].task_mgmt_failures++;
2178fcf3ce44SJohn Forte 			break;
2179fcf3ce44SJohn Forte 		default:
2180fcf3ce44SJohn Forte 			break;
2181fcf3ce44SJohn Forte 		}
2182fcf3ce44SJohn Forte 	} else {
2183fcf3ce44SJohn Forte 		/*
2184fcf3ce44SJohn Forte 		 * EL(sp->ha, "scsi_h=%xh, pkt_rsplen=%xh\n",
2185fcf3ce44SJohn Forte 		 *   sts.scsi_status_h, sp->pkt->pkt_rsplen);
2186fcf3ce44SJohn Forte 		 */
2187fcf3ce44SJohn Forte 		fcpr->fcp_response_len = 0;
2188fcf3ce44SJohn Forte 	}
2189fcf3ce44SJohn Forte 
2190fcf3ce44SJohn Forte 	/* Set reset status received. */
2191fcf3ce44SJohn Forte 	if (sts.comp_status == CS_RESET && LOOP_READY(ha)) {
2192fcf3ce44SJohn Forte 		rval |= BIT_0;
2193fcf3ce44SJohn Forte 	}
2194fcf3ce44SJohn Forte 
2195fcf3ce44SJohn Forte 	if (!(tq->flags & TQF_TAPE_DEVICE) &&
2196fcf3ce44SJohn Forte 	    (!(CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) ||
2197fcf3ce44SJohn Forte 	    ha->loop_down_abort_time < LOOP_DOWN_TIMER_START) &&
2198fcf3ce44SJohn Forte 	    ha->task_daemon_flags & LOOP_DOWN) {
2199fcf3ce44SJohn Forte 		EL(sp->ha, "Loop Not Ready Retry, d_id=%xh, lun=%xh\n",
2200fcf3ce44SJohn Forte 		    tq->d_id.b24, sp->lun_queue->lun_no);
2201fcf3ce44SJohn Forte 
2202fcf3ce44SJohn Forte 		/* Set retry status. */
2203fcf3ce44SJohn Forte 		sp->flags |= SRB_RETRY;
2204fcf3ce44SJohn Forte 	} else if (!(tq->flags & TQF_TAPE_DEVICE) &&
2205fcf3ce44SJohn Forte 	    tq->port_down_retry_count != 0 &&
2206fcf3ce44SJohn Forte 	    (sts.comp_status == CS_INCOMPLETE ||
2207fcf3ce44SJohn Forte 	    sts.comp_status == CS_PORT_UNAVAILABLE ||
2208fcf3ce44SJohn Forte 	    sts.comp_status == CS_PORT_LOGGED_OUT ||
2209fcf3ce44SJohn Forte 	    sts.comp_status == CS_PORT_CONFIG_CHG ||
2210fcf3ce44SJohn Forte 	    sts.comp_status == CS_PORT_BUSY)) {
2211fcf3ce44SJohn Forte 		EL(sp->ha, "Port Down Retry=%xh, d_id=%xh, lun=%xh, count=%d"
2212fcf3ce44SJohn Forte 		    "\n", sts.comp_status, tq->d_id.b24, sp->lun_queue->lun_no,
2213fcf3ce44SJohn Forte 		    tq->port_down_retry_count);
2214fcf3ce44SJohn Forte 
2215fcf3ce44SJohn Forte 		/* Set retry status. */
2216fcf3ce44SJohn Forte 		sp->flags |= SRB_RETRY;
2217fcf3ce44SJohn Forte 
2218fcf3ce44SJohn Forte 		if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) {
2219fcf3ce44SJohn Forte 			/* Acquire device queue lock. */
2220fcf3ce44SJohn Forte 			DEVICE_QUEUE_LOCK(tq);
2221fcf3ce44SJohn Forte 
2222fcf3ce44SJohn Forte 			tq->flags |= TQF_QUEUE_SUSPENDED;
2223fcf3ce44SJohn Forte 
2224fcf3ce44SJohn Forte 			/* Decrement port down count. */
2225fcf3ce44SJohn Forte 			if (CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) {
2226fcf3ce44SJohn Forte 				tq->port_down_retry_count--;
2227fcf3ce44SJohn Forte 			}
2228fcf3ce44SJohn Forte 
2229fcf3ce44SJohn Forte 			DEVICE_QUEUE_UNLOCK(tq);
2230fcf3ce44SJohn Forte 
2231fcf3ce44SJohn Forte 			if ((ha->task_daemon_flags & ABORT_ISP_ACTIVE)
2232fcf3ce44SJohn Forte 			    == 0 &&
2233fcf3ce44SJohn Forte 			    (sts.comp_status == CS_PORT_LOGGED_OUT ||
2234fcf3ce44SJohn Forte 			    sts.comp_status == CS_PORT_UNAVAILABLE)) {
2235fcf3ce44SJohn Forte 				sp->ha->adapter_stats->d_stats[lobyte(
2236fcf3ce44SJohn Forte 				    tq->loop_id)].logouts_recvd++;
2237fcf3ce44SJohn Forte 				ql_send_logo(sp->ha, tq, done_q);
2238fcf3ce44SJohn Forte 			}
2239fcf3ce44SJohn Forte 
2240fcf3ce44SJohn Forte 			ADAPTER_STATE_LOCK(ha);
2241fcf3ce44SJohn Forte 			if (ha->port_retry_timer == 0) {
2242fcf3ce44SJohn Forte 				if ((ha->port_retry_timer =
2243fcf3ce44SJohn Forte 				    ha->port_down_retry_delay) == 0) {
2244fcf3ce44SJohn Forte 					*set_flags |=
2245fcf3ce44SJohn Forte 					    PORT_RETRY_NEEDED;
2246fcf3ce44SJohn Forte 				}
2247fcf3ce44SJohn Forte 			}
2248fcf3ce44SJohn Forte 			ADAPTER_STATE_UNLOCK(ha);
2249fcf3ce44SJohn Forte 		}
2250fcf3ce44SJohn Forte 	} else if (!(tq->flags & TQF_TAPE_DEVICE) &&
2251fcf3ce44SJohn Forte 	    (sts.comp_status == CS_RESET ||
2252fcf3ce44SJohn Forte 	    (sts.comp_status == CS_QUEUE_FULL && tq->qfull_retry_count != 0) ||
2253fcf3ce44SJohn Forte 	    (sts.comp_status == CS_ABORTED && !(sp->flags & SRB_ABORTING)))) {
2254fcf3ce44SJohn Forte 		if (sts.comp_status == CS_RESET) {
2255fcf3ce44SJohn Forte 			EL(sp->ha, "Reset Retry, d_id=%xh, lun=%xh\n",
2256fcf3ce44SJohn Forte 			    tq->d_id.b24, sp->lun_queue->lun_no);
2257fcf3ce44SJohn Forte 		} else if (sts.comp_status == CS_QUEUE_FULL) {
2258fcf3ce44SJohn Forte 			EL(sp->ha, "Queue Full Retry, d_id=%xh, lun=%xh, "
2259fcf3ce44SJohn Forte 			    "cnt=%d\n", tq->d_id.b24, sp->lun_queue->lun_no,
2260fcf3ce44SJohn Forte 			    tq->qfull_retry_count);
2261fcf3ce44SJohn Forte 			if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) {
2262fcf3ce44SJohn Forte 				tq->flags |= TQF_QUEUE_SUSPENDED;
2263fcf3ce44SJohn Forte 
2264fcf3ce44SJohn Forte 				tq->qfull_retry_count--;
2265fcf3ce44SJohn Forte 
2266fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
2267fcf3ce44SJohn Forte 				if (ha->port_retry_timer == 0) {
2268fcf3ce44SJohn Forte 					if ((ha->port_retry_timer =
2269fcf3ce44SJohn Forte 					    ha->qfull_retry_delay) ==
2270fcf3ce44SJohn Forte 					    0) {
2271fcf3ce44SJohn Forte 						*set_flags |=
2272fcf3ce44SJohn Forte 						    PORT_RETRY_NEEDED;
2273fcf3ce44SJohn Forte 					}
2274fcf3ce44SJohn Forte 				}
2275fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
2276fcf3ce44SJohn Forte 			}
2277fcf3ce44SJohn Forte 		} else {
2278fcf3ce44SJohn Forte 			EL(sp->ha, "Abort Retry, d_id=%xh, lun=%xh\n",
2279fcf3ce44SJohn Forte 			    tq->d_id.b24, sp->lun_queue->lun_no);
2280fcf3ce44SJohn Forte 		}
2281fcf3ce44SJohn Forte 
2282fcf3ce44SJohn Forte 		/* Set retry status. */
2283fcf3ce44SJohn Forte 		sp->flags |= SRB_RETRY;
2284fcf3ce44SJohn Forte 	} else {
2285fcf3ce44SJohn Forte 		fcpr->fcp_resid =
2286fcf3ce44SJohn Forte 		    sts.fcp_residual_length > sp->fcp->fcp_data_len ?
2287fcf3ce44SJohn Forte 		    sp->fcp->fcp_data_len : sts.fcp_residual_length;
2288fcf3ce44SJohn Forte 
2289fcf3ce44SJohn Forte 		if ((sts.comp_status == CS_DATA_UNDERRUN) &&
2290fcf3ce44SJohn Forte 		    (sts.scsi_status_h & FCP_RESID_UNDER) == 0) {
2291fcf3ce44SJohn Forte 
2292fcf3ce44SJohn Forte 			if (sts.scsi_status_l == STATUS_CHECK) {
2293fcf3ce44SJohn Forte 				sp->pkt->pkt_reason = CS_COMPLETE;
2294fcf3ce44SJohn Forte 			} else {
2295fcf3ce44SJohn Forte 				EL(ha, "transport error - "
2296fcf3ce44SJohn Forte 				    "underrun & invalid resid\n");
2297fcf3ce44SJohn Forte 				EL(ha, "ssh=%xh, ssl=%xh\n",
2298fcf3ce44SJohn Forte 				    sts.scsi_status_h, sts.scsi_status_l);
2299fcf3ce44SJohn Forte 				sp->pkt->pkt_reason = CS_FCP_RESPONSE_ERROR;
2300fcf3ce44SJohn Forte 			}
2301fcf3ce44SJohn Forte 		}
2302fcf3ce44SJohn Forte 
2303fcf3ce44SJohn Forte 		/* Ignore firmware underrun error. */
2304fcf3ce44SJohn Forte 		if (sts.comp_status == CS_DATA_UNDERRUN &&
2305fcf3ce44SJohn Forte 		    (sts.scsi_status_h & FCP_RESID_UNDER ||
2306fcf3ce44SJohn Forte 		    (sts.scsi_status_l != STATUS_CHECK &&
2307fcf3ce44SJohn Forte 		    sts.scsi_status_l != STATUS_GOOD))) {
2308fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_COMPLETE;
2309fcf3ce44SJohn Forte 		}
2310fcf3ce44SJohn Forte 
2311fcf3ce44SJohn Forte 		if (sp->pkt->pkt_reason != CS_COMPLETE) {
2312fcf3ce44SJohn Forte 			ha->xioctl->DeviceErrorCount++;
2313fcf3ce44SJohn Forte 			EL(sp->ha, "Cmplt status err = %xh, d_id=%xh, lun=%xh"
2314fcf3ce44SJohn Forte 			    "\n", sts.comp_status, tq->d_id.b24,
2315fcf3ce44SJohn Forte 			    sp->lun_queue->lun_no);
2316fcf3ce44SJohn Forte 		}
2317fcf3ce44SJohn Forte 
2318fcf3ce44SJohn Forte 		/* Set target request sense data. */
2319fcf3ce44SJohn Forte 		if (sts.scsi_status_l == STATUS_CHECK) {
2320fcf3ce44SJohn Forte 			if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
2321fcf3ce44SJohn Forte 
2322fcf3ce44SJohn Forte 				if (sp->pkt->pkt_reason == CS_COMPLETE &&
2323fcf3ce44SJohn Forte 				    sts.req_sense_data[2] != KEY_NO_SENSE &&
2324fcf3ce44SJohn Forte 				    sts.req_sense_data[2] !=
2325fcf3ce44SJohn Forte 				    KEY_UNIT_ATTENTION) {
2326fcf3ce44SJohn Forte 					ha->xioctl->DeviceErrorCount++;
2327fcf3ce44SJohn Forte 				}
2328fcf3ce44SJohn Forte 
2329fcf3ce44SJohn Forte 				sense_sz = sts.req_sense_length;
2330fcf3ce44SJohn Forte 
2331fcf3ce44SJohn Forte 				/* Insure data does not exceed buf. */
2332fcf3ce44SJohn Forte 				if (sp->pkt->pkt_rsplen <=
2333fcf3ce44SJohn Forte 				    (uint32_t)sizeof (fcp_rsp_t) +
2334fcf3ce44SJohn Forte 				    fcpr->fcp_response_len) {
2335fcf3ce44SJohn Forte 					sp->request_sense_length = 0;
2336fcf3ce44SJohn Forte 				} else {
2337fcf3ce44SJohn Forte 					sp->request_sense_length = (uint32_t)
2338fcf3ce44SJohn Forte 					    (sp->pkt->pkt_rsplen -
2339fcf3ce44SJohn Forte 					    sizeof (fcp_rsp_t) -
2340fcf3ce44SJohn Forte 					    fcpr->fcp_response_len);
2341fcf3ce44SJohn Forte 				}
2342fcf3ce44SJohn Forte 
2343fcf3ce44SJohn Forte 				if (sense_sz <
2344fcf3ce44SJohn Forte 				    sp->request_sense_length) {
2345fcf3ce44SJohn Forte 					sp->request_sense_length =
2346fcf3ce44SJohn Forte 					    sense_sz;
2347fcf3ce44SJohn Forte 				}
2348fcf3ce44SJohn Forte 
2349fcf3ce44SJohn Forte 				sp->request_sense_ptr = (caddr_t)rsp;
2350fcf3ce44SJohn Forte 
2351fcf3ce44SJohn Forte 				sense_sz = (uint32_t)
2352fcf3ce44SJohn Forte 				    (((uintptr_t)pkt23 +
2353fcf3ce44SJohn Forte 				    sizeof (sts_entry_t)) -
2354fcf3ce44SJohn Forte 				    (uintptr_t)sts.req_sense_data);
2355fcf3ce44SJohn Forte 				if (sp->request_sense_length <
2356fcf3ce44SJohn Forte 				    sense_sz) {
2357fcf3ce44SJohn Forte 					sense_sz =
2358fcf3ce44SJohn Forte 					    sp->request_sense_length;
2359fcf3ce44SJohn Forte 				}
2360fcf3ce44SJohn Forte 
2361fcf3ce44SJohn Forte 				fcpr->fcp_sense_len = sense_sz;
2362fcf3ce44SJohn Forte 
2363fcf3ce44SJohn Forte 				/* Move sense data. */
2364fcf3ce44SJohn Forte 				ddi_rep_get8(ha->hba_buf.acc_handle,
2365fcf3ce44SJohn Forte 				    (uint8_t *)sp->request_sense_ptr,
2366fcf3ce44SJohn Forte 				    sts.req_sense_data,
2367fcf3ce44SJohn Forte 				    (size_t)sense_sz,
2368fcf3ce44SJohn Forte 				    DDI_DEV_AUTOINCR);
2369fcf3ce44SJohn Forte 
2370fcf3ce44SJohn Forte 				sp->request_sense_ptr += sense_sz;
2371fcf3ce44SJohn Forte 				sp->request_sense_length -= sense_sz;
2372fcf3ce44SJohn Forte 				if (sp->request_sense_length != 0) {
2373fcf3ce44SJohn Forte 					ha->status_srb = sp;
2374fcf3ce44SJohn Forte 				}
2375fcf3ce44SJohn Forte 			}
2376fcf3ce44SJohn Forte 
2377fcf3ce44SJohn Forte 			if (sense_sz != 0) {
2378fcf3ce44SJohn Forte 				EL(sp->ha, "check condition sense data, "
2379fcf3ce44SJohn Forte 				    "d_id=%xh, lun=%xh\n%2xh%3xh%3xh%3xh"
2380fcf3ce44SJohn Forte 				    "%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh"
2381fcf3ce44SJohn Forte 				    "%3xh%3xh%3xh%3xh%3xh\n", tq->d_id.b24,
2382fcf3ce44SJohn Forte 				    sp->lun_queue->lun_no,
2383fcf3ce44SJohn Forte 				    sts.req_sense_data[0],
2384fcf3ce44SJohn Forte 				    sts.req_sense_data[1],
2385fcf3ce44SJohn Forte 				    sts.req_sense_data[2],
2386fcf3ce44SJohn Forte 				    sts.req_sense_data[3],
2387fcf3ce44SJohn Forte 				    sts.req_sense_data[4],
2388fcf3ce44SJohn Forte 				    sts.req_sense_data[5],
2389fcf3ce44SJohn Forte 				    sts.req_sense_data[6],
2390fcf3ce44SJohn Forte 				    sts.req_sense_data[7],
2391fcf3ce44SJohn Forte 				    sts.req_sense_data[8],
2392fcf3ce44SJohn Forte 				    sts.req_sense_data[9],
2393fcf3ce44SJohn Forte 				    sts.req_sense_data[10],
2394fcf3ce44SJohn Forte 				    sts.req_sense_data[11],
2395fcf3ce44SJohn Forte 				    sts.req_sense_data[12],
2396fcf3ce44SJohn Forte 				    sts.req_sense_data[13],
2397fcf3ce44SJohn Forte 				    sts.req_sense_data[14],
2398fcf3ce44SJohn Forte 				    sts.req_sense_data[15],
2399fcf3ce44SJohn Forte 				    sts.req_sense_data[16],
2400fcf3ce44SJohn Forte 				    sts.req_sense_data[17]);
2401fcf3ce44SJohn Forte 			} else {
2402fcf3ce44SJohn Forte 				EL(sp->ha, "check condition, d_id=%xh, lun=%xh"
2403fcf3ce44SJohn Forte 				    "\n", tq->d_id.b24, sp->lun_queue->lun_no);
2404fcf3ce44SJohn Forte 			}
2405fcf3ce44SJohn Forte 		}
2406fcf3ce44SJohn Forte 	}
2407fcf3ce44SJohn Forte 
2408fcf3ce44SJohn Forte 	/* Set completed status. */
2409fcf3ce44SJohn Forte 	sp->flags |= SRB_ISP_COMPLETED;
2410fcf3ce44SJohn Forte 
2411fcf3ce44SJohn Forte 	/* Place command on done queue. */
2412fcf3ce44SJohn Forte 	if (ha->status_srb == NULL) {
2413fcf3ce44SJohn Forte 		ql_add_link_b(done_q, &sp->cmd);
2414fcf3ce44SJohn Forte 	}
2415fcf3ce44SJohn Forte 
2416fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2417fcf3ce44SJohn Forte 
2418fcf3ce44SJohn Forte 	return (rval);
2419fcf3ce44SJohn Forte }
2420fcf3ce44SJohn Forte 
2421fcf3ce44SJohn Forte /*
2422fcf3ce44SJohn Forte  * ql_status_cont_entry
2423fcf3ce44SJohn Forte  *	Processes status continuation entry.
2424fcf3ce44SJohn Forte  *
2425fcf3ce44SJohn Forte  * Input:
2426fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
2427fcf3ce44SJohn Forte  *	pkt:		entry pointer.
2428fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
2429fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
2430fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
2431fcf3ce44SJohn Forte  *
2432fcf3ce44SJohn Forte  * Context:
2433fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
2434fcf3ce44SJohn Forte  */
2435fcf3ce44SJohn Forte /* ARGSUSED */
2436fcf3ce44SJohn Forte static void
2437fcf3ce44SJohn Forte ql_status_cont_entry(ql_adapter_state_t *ha, sts_cont_entry_t *pkt,
2438fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
2439fcf3ce44SJohn Forte {
2440fcf3ce44SJohn Forte 	uint32_t	sense_sz, index;
2441fcf3ce44SJohn Forte 	ql_srb_t	*sp = ha->status_srb;
2442fcf3ce44SJohn Forte 
2443fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2444fcf3ce44SJohn Forte 
2445fcf3ce44SJohn Forte 	if (sp != NULL && sp->request_sense_length) {
2446fcf3ce44SJohn Forte 		if (sp->request_sense_length > sizeof (pkt->req_sense_data)) {
2447fcf3ce44SJohn Forte 			sense_sz = sizeof (pkt->req_sense_data);
2448fcf3ce44SJohn Forte 		} else {
2449fcf3ce44SJohn Forte 			sense_sz = sp->request_sense_length;
2450fcf3ce44SJohn Forte 		}
2451fcf3ce44SJohn Forte 
2452fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_CTRL_2425)) {
2453fcf3ce44SJohn Forte 			for (index = 0; index < sense_sz; index += 4) {
2454fcf3ce44SJohn Forte 				ql_chg_endian((uint8_t *)
2455fcf3ce44SJohn Forte 				    &pkt->req_sense_data[0] + index, 4);
2456fcf3ce44SJohn Forte 			}
2457fcf3ce44SJohn Forte 		}
2458fcf3ce44SJohn Forte 
2459fcf3ce44SJohn Forte 		/* Move sense data. */
2460fcf3ce44SJohn Forte 		ddi_rep_get8(ha->hba_buf.acc_handle,
2461fcf3ce44SJohn Forte 		    (uint8_t *)sp->request_sense_ptr,
2462fcf3ce44SJohn Forte 		    (uint8_t *)&pkt->req_sense_data[0], (size_t)sense_sz,
2463fcf3ce44SJohn Forte 		    DDI_DEV_AUTOINCR);
2464fcf3ce44SJohn Forte 
2465fcf3ce44SJohn Forte 		sp->request_sense_ptr += sense_sz;
2466fcf3ce44SJohn Forte 		sp->request_sense_length -= sense_sz;
2467fcf3ce44SJohn Forte 
2468fcf3ce44SJohn Forte 		/* Place command on done queue. */
2469fcf3ce44SJohn Forte 		if (sp->request_sense_length == 0) {
2470fcf3ce44SJohn Forte 			ql_add_link_b(done_q, &sp->cmd);
2471fcf3ce44SJohn Forte 			ha->status_srb = NULL;
2472fcf3ce44SJohn Forte 		}
2473fcf3ce44SJohn Forte 	}
2474fcf3ce44SJohn Forte 
2475fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2476fcf3ce44SJohn Forte }
2477fcf3ce44SJohn Forte 
2478fcf3ce44SJohn Forte /*
2479fcf3ce44SJohn Forte  * ql_immediate_notify_entry
2480fcf3ce44SJohn Forte  *	Processes immediate notify entry.
2481fcf3ce44SJohn Forte  *
2482fcf3ce44SJohn Forte  * Input:
2483fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
2484fcf3ce44SJohn Forte  *	pkt:		entry pointer.
2485fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
2486fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
2487fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
2488fcf3ce44SJohn Forte  *
2489fcf3ce44SJohn Forte  * Context:
2490fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
2491fcf3ce44SJohn Forte  */
2492fcf3ce44SJohn Forte /* ARGSUSED */
2493fcf3ce44SJohn Forte static void
2494fcf3ce44SJohn Forte ql_immediate_notify_entry(ql_adapter_state_t *ha,
2495fcf3ce44SJohn Forte     immediate_notify_entry_t *pkt, ql_head_t *done_q, uint32_t *set_flags,
2496fcf3ce44SJohn Forte     uint32_t *reset_flags)
2497fcf3ce44SJohn Forte {
2498fcf3ce44SJohn Forte 	notify_acknowledge_entry_t *nack;
2499fcf3ce44SJohn Forte 	ql_srb_t		*sp;
2500fcf3ce44SJohn Forte 	fcp_cmd_t		*fcp;
2501fcf3ce44SJohn Forte 	tgt_cmd_t		*cmd, *nackcmd;
2502fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
2503fcf3ce44SJohn Forte 	fc_unsol_buf_t		*ubp = NULL;
2504fcf3ce44SJohn Forte 	int			use_ubuffer;
2505fcf3ce44SJohn Forte 	uint16_t		loop_id;
2506fcf3ce44SJohn Forte 
2507fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2508fcf3ce44SJohn Forte 
2509fcf3ce44SJohn Forte 	cmd = (tgt_cmd_t *)kmem_zalloc(sizeof (tgt_cmd_t), KM_NOSLEEP);
2510fcf3ce44SJohn Forte 	if (cmd != NULL) {
2511fcf3ce44SJohn Forte 		cmd->cmd.base_address = cmd;
2512fcf3ce44SJohn Forte 
2513fcf3ce44SJohn Forte 		/* Save command context. */
2514fcf3ce44SJohn Forte 		cmd->type = pkt->entry_type;
2515fcf3ce44SJohn Forte 		cmd->initiator_id_l = pkt->initiator_id_l;
2516fcf3ce44SJohn Forte 		cmd->initiator_id_h = pkt->initiator_id_h;
2517fcf3ce44SJohn Forte 		cmd->rx_id = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
2518fcf3ce44SJohn Forte 		    &pkt->sequence_id);
2519fcf3ce44SJohn Forte 		cmd->status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
2520fcf3ce44SJohn Forte 		    &pkt->status);
2521fcf3ce44SJohn Forte 		cmd->task_flags_l = pkt->task_flags_l;
2522fcf3ce44SJohn Forte 		cmd->task_flags_h = pkt->task_flags_h;
2523fcf3ce44SJohn Forte 
2524fcf3ce44SJohn Forte 		/*
2525fcf3ce44SJohn Forte 		 * TODO: flushing in case of pkt_status_l of 0x34
2526fcf3ce44SJohn Forte 		 * needs to be handled properly.
2527fcf3ce44SJohn Forte 		 */
2528fcf3ce44SJohn Forte 
2529fcf3ce44SJohn Forte 		EL(ha, "status = %xh\n", cmd->status);
2530fcf3ce44SJohn Forte 
2531fcf3ce44SJohn Forte 		/*
2532fcf3ce44SJohn Forte 		 * For immediate notify situations that need attention,
2533fcf3ce44SJohn Forte 		 * we attempt to put the command in the array of notify
2534fcf3ce44SJohn Forte 		 * acknowledge slots for future handling.  A LIP RESET
2535fcf3ce44SJohn Forte 		 * always gets slot 0, since we have to ensure that there's
2536fcf3ce44SJohn Forte 		 * always a slot available and we can't do any other
2537fcf3ce44SJohn Forte 		 * processsing if a LIP RESET is pending.
2538fcf3ce44SJohn Forte 		 *
2539fcf3ce44SJohn Forte 		 * Otherwise, immediate notifies take the next open slot.
2540fcf3ce44SJohn Forte 		 */
2541fcf3ce44SJohn Forte 		use_ubuffer = 0;
2542fcf3ce44SJohn Forte 		nackcmd = NULL;
2543fcf3ce44SJohn Forte 		mutex_enter(&ha->ql_nack_mtx);
2544fcf3ce44SJohn Forte 		switch (cmd->status) {
2545fcf3ce44SJohn Forte 		case 0x0E:
2546fcf3ce44SJohn Forte 			if (ha->ql_nack != NULL) {
2547fcf3ce44SJohn Forte 				/*
2548fcf3ce44SJohn Forte 				 * We're in the sticky situation of receiving
2549fcf3ce44SJohn Forte 				 * LIP reset while one is pending.  What appears
2550fcf3ce44SJohn Forte 				 * to work is to drop the old request and
2551fcf3ce44SJohn Forte 				 * replace it with the new.  We send a NACK
2552fcf3ce44SJohn Forte 				 * for the old to replenish the IOCB.
2553fcf3ce44SJohn Forte 				 */
2554fcf3ce44SJohn Forte 				nackcmd = ha->ql_nack;
2555fcf3ce44SJohn Forte 			}
2556fcf3ce44SJohn Forte 			ha->ql_nack = cmd;
2557fcf3ce44SJohn Forte 			break;
2558fcf3ce44SJohn Forte 		case 0x20:
2559fcf3ce44SJohn Forte 		case 0x29:
2560fcf3ce44SJohn Forte 		case 0x36:
2561fcf3ce44SJohn Forte 			/* If this isn't NULL, a LIP RESET is outstanding */
2562fcf3ce44SJohn Forte 			if (ha->ql_nack == NULL) {
2563fcf3ce44SJohn Forte 				use_ubuffer++;
2564fcf3ce44SJohn Forte 			}
2565fcf3ce44SJohn Forte 			break;
2566fcf3ce44SJohn Forte 		default:
2567fcf3ce44SJohn Forte 			EL(ha, "unknown status=%xh\n",
2568fcf3ce44SJohn Forte 			    cmd->status);
2569fcf3ce44SJohn Forte 			break;
2570fcf3ce44SJohn Forte 		}
2571fcf3ce44SJohn Forte 		mutex_exit(&ha->ql_nack_mtx);
2572fcf3ce44SJohn Forte 
2573fcf3ce44SJohn Forte 		if (use_ubuffer) {
2574fcf3ce44SJohn Forte 			/*
2575fcf3ce44SJohn Forte 			 * Get an unsolicited buffer to send the message up in
2576fcf3ce44SJohn Forte 			 */
2577fcf3ce44SJohn Forte 
2578fcf3ce44SJohn Forte 			/* Locate a buffer to use. */
2579fcf3ce44SJohn Forte 			loop_id = (uint16_t)
2580fcf3ce44SJohn Forte 			    (CFG_IST(ha, CFG_EXT_FW_INTERFACE) ?
2581fcf3ce44SJohn Forte 			    CHAR_TO_SHORT(pkt->initiator_id_l,
2582fcf3ce44SJohn Forte 			    pkt->initiator_id_h) : pkt->initiator_id_h);
2583fcf3ce44SJohn Forte 			if ((tq = ql_loop_id_to_queue(ha, loop_id)) != NULL) {
2584fcf3ce44SJohn Forte 				ubp = ql_get_unsolicited_buffer(ha,
2585fcf3ce44SJohn Forte 				    FC_TYPE_SCSI_FCP);
2586fcf3ce44SJohn Forte 			}
2587fcf3ce44SJohn Forte 			if (ubp != NULL) {
2588fcf3ce44SJohn Forte 				ubp->ub_resp_flags = FC_UB_FCP_CDB_FLAG;
2589fcf3ce44SJohn Forte 				ubp->ub_resp_token = tq;
2590fcf3ce44SJohn Forte 				sp = ubp->ub_fca_private;
2591fcf3ce44SJohn Forte 
2592fcf3ce44SJohn Forte 				fcp = (fcp_cmd_t *)ubp->ub_buffer;
2593fcf3ce44SJohn Forte 
2594fcf3ce44SJohn Forte 				/* Set header. */
2595fcf3ce44SJohn Forte 				ubp->ub_frame.d_id = ha->d_id.b24;
2596fcf3ce44SJohn Forte 				/* Set 0x06 for R_CTL_COMMAND */
2597fcf3ce44SJohn Forte 				ubp->ub_frame.r_ctl = R_CTL_COMMAND;
2598fcf3ce44SJohn Forte 				ubp->ub_frame.s_id = tq->d_id.b24;
2599fcf3ce44SJohn Forte 				ubp->ub_frame.rsvd = 0;
2600fcf3ce44SJohn Forte 				ubp->ub_frame.f_ctl = F_CTL_FIRST_SEQ |
2601fcf3ce44SJohn Forte 				    F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
2602fcf3ce44SJohn Forte 				ubp->ub_frame.type = FC_TYPE_SCSI_FCP;
2603fcf3ce44SJohn Forte 				ubp->ub_frame.seq_cnt = 0;
2604fcf3ce44SJohn Forte 				ubp->ub_frame.df_ctl = 0;
2605fcf3ce44SJohn Forte 				ubp->ub_frame.seq_id = 0;
2606fcf3ce44SJohn Forte 				ubp->ub_frame.rx_id = cmd->rx_id;
2607fcf3ce44SJohn Forte 				ubp->ub_frame.ox_id = (uint16_t)ddi_get16(
2608fcf3ce44SJohn Forte 				    ha->hba_buf.acc_handle, &pkt->ox_id);
2609fcf3ce44SJohn Forte 				ubp->ub_frame.ro = 0;
2610fcf3ce44SJohn Forte 
2611fcf3ce44SJohn Forte 				/* Set command in buffer. */
2612fcf3ce44SJohn Forte 				bzero((void *)fcp, sizeof (fcp_cmd_t));
2613fcf3ce44SJohn Forte 
2614fcf3ce44SJohn Forte 				lobyte(fcp->fcp_ent_addr.ent_addr_0) =
2615fcf3ce44SJohn Forte 				    pkt->lun_l;
2616fcf3ce44SJohn Forte 				hibyte(fcp->fcp_ent_addr.ent_addr_0) =
2617fcf3ce44SJohn Forte 				    pkt->lun_h;
2618fcf3ce44SJohn Forte 
2619fcf3ce44SJohn Forte 				switch (cmd->status) {
2620fcf3ce44SJohn Forte 				case 0x29:
2621fcf3ce44SJohn Forte 					ubp->ub_resp_flags = (uint16_t)
2622fcf3ce44SJohn Forte 					    (ubp->ub_resp_flags |
2623fcf3ce44SJohn Forte 					    FC_UB_FCP_PORT_LOGOUT);
2624fcf3ce44SJohn Forte 					break;
2625fcf3ce44SJohn Forte 				case 0x20:
2626fcf3ce44SJohn Forte 					ubp->ub_resp_flags = (uint16_t)
2627fcf3ce44SJohn Forte 					    (ubp->ub_resp_flags |
2628fcf3ce44SJohn Forte 					    FC_UB_FCP_ABORT_TASK);
2629fcf3ce44SJohn Forte 					break;
2630fcf3ce44SJohn Forte 				case 0x36:
2631fcf3ce44SJohn Forte 					if (pkt->task_flags_h & BIT_7) {
2632fcf3ce44SJohn Forte 						fcp->fcp_cntl.cntl_kill_tsk =
2633fcf3ce44SJohn Forte 						    1;
2634fcf3ce44SJohn Forte 					}
2635fcf3ce44SJohn Forte 					if (pkt->task_flags_h & BIT_6) {
2636fcf3ce44SJohn Forte 						fcp->fcp_cntl.cntl_clr_aca = 1;
2637fcf3ce44SJohn Forte 					}
2638fcf3ce44SJohn Forte 					if (pkt->task_flags_h & BIT_5) {
2639fcf3ce44SJohn Forte 						fcp->fcp_cntl.cntl_reset_tgt =
2640fcf3ce44SJohn Forte 						    1;
2641fcf3ce44SJohn Forte 					}
2642fcf3ce44SJohn Forte 					if (pkt->task_flags_h & BIT_4) {
2643fcf3ce44SJohn Forte 						fcp->fcp_cntl.cntl_reset_lun =
2644fcf3ce44SJohn Forte 						    1;
2645fcf3ce44SJohn Forte 					}
2646fcf3ce44SJohn Forte 					if (pkt->task_flags_h & BIT_2) {
2647fcf3ce44SJohn Forte 						fcp->fcp_cntl.cntl_clr_tsk = 1;
2648fcf3ce44SJohn Forte 					}
2649fcf3ce44SJohn Forte 					if (pkt->task_flags_h & BIT_1) {
2650fcf3ce44SJohn Forte 						fcp->fcp_cntl.cntl_abort_tsk =
2651fcf3ce44SJohn Forte 						    1;
2652fcf3ce44SJohn Forte 					}
2653fcf3ce44SJohn Forte 					break;
2654fcf3ce44SJohn Forte 				default:
2655fcf3ce44SJohn Forte 					EL(ha, "default, no action\n");
2656fcf3ce44SJohn Forte 					break;
2657fcf3ce44SJohn Forte 				}
2658fcf3ce44SJohn Forte 
2659fcf3ce44SJohn Forte 				QL_UB_LOCK(ha);
2660fcf3ce44SJohn Forte 				sp->flags |= SRB_UB_CALLBACK | SRB_UB_FCP;
2661fcf3ce44SJohn Forte 				QL_UB_UNLOCK(ha);
2662fcf3ce44SJohn Forte 				QL_PRINT_3(CE_CONT, "(%d): Sent Up status = "
2663fcf3ce44SJohn Forte 				    "%xh\n", ha->instance, cmd->status);
2664fcf3ce44SJohn Forte 				ql_add_link_b(done_q, &sp->cmd);
2665fcf3ce44SJohn Forte 			}
2666fcf3ce44SJohn Forte 		}
2667fcf3ce44SJohn Forte 
2668fcf3ce44SJohn Forte 		if (nackcmd) {
2669fcf3ce44SJohn Forte 			if (ql_req_pkt(ha, (request_t **)&nack) ==
2670fcf3ce44SJohn Forte 			    QL_SUCCESS) {
2671fcf3ce44SJohn Forte 
2672fcf3ce44SJohn Forte 				ql_notify_acknowledge_iocb(ha, nackcmd, nack);
2673fcf3ce44SJohn Forte 
2674fcf3ce44SJohn Forte 				nack->flags_l = 0;
2675fcf3ce44SJohn Forte 				QL_PRINT_3(CE_CONT, "(%d): send clear "
2676fcf3ce44SJohn Forte 				    "notify_ack: status=%xh, flag=%xh\n",
2677fcf3ce44SJohn Forte 				    ha->instance, ddi_get16(
2678fcf3ce44SJohn Forte 				    ha->hba_buf.acc_handle, &nack->status),
2679fcf3ce44SJohn Forte 				    nack->flags_l);
2680fcf3ce44SJohn Forte 
2681fcf3ce44SJohn Forte 				/* Issue command to ISP */
2682fcf3ce44SJohn Forte 				ql_isp_cmd(ha);
2683fcf3ce44SJohn Forte 			}
2684fcf3ce44SJohn Forte 			kmem_free(nackcmd, sizeof (tgt_cmd_t));
2685fcf3ce44SJohn Forte 		}
2686fcf3ce44SJohn Forte 
2687fcf3ce44SJohn Forte 		/*
2688fcf3ce44SJohn Forte 		 * ql_nack can only be non-NULL if we got a LIP RESET and
2689fcf3ce44SJohn Forte 		 * are processing it.  In that case, we don't want to send
2690fcf3ce44SJohn Forte 		 * a notify acknowledge right now.
2691fcf3ce44SJohn Forte 		 */
2692fcf3ce44SJohn Forte 		if (cmd->status != 0x0E) {
2693fcf3ce44SJohn Forte 			if (ql_req_pkt(ha, (request_t **)&nack) ==
2694fcf3ce44SJohn Forte 			    QL_SUCCESS) {
2695fcf3ce44SJohn Forte 				ql_notify_acknowledge_iocb(ha, cmd, nack);
2696fcf3ce44SJohn Forte 
2697fcf3ce44SJohn Forte 				EL(ha, "send notify_ack: status=%xh "
2698fcf3ce44SJohn Forte 				    "flag=%xh\n", cmd->status, nack->flags_l);
2699fcf3ce44SJohn Forte 
2700fcf3ce44SJohn Forte 				/* Issue command to ISP */
2701fcf3ce44SJohn Forte 				ql_isp_cmd(ha);
2702fcf3ce44SJohn Forte 			}
2703fcf3ce44SJohn Forte 			kmem_free(cmd, sizeof (tgt_cmd_t));
2704fcf3ce44SJohn Forte 		} else {
2705fcf3ce44SJohn Forte 			ql_awaken_task_daemon(ha, NULL,
2706fcf3ce44SJohn Forte 			    LIP_RESET_PENDING, 0);
2707fcf3ce44SJohn Forte 		}
2708fcf3ce44SJohn Forte 	}
2709fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2710fcf3ce44SJohn Forte }
2711fcf3ce44SJohn Forte 
2712fcf3ce44SJohn Forte /*
2713fcf3ce44SJohn Forte  * ql_notify_acknowledge_entry
2714fcf3ce44SJohn Forte  *	Processes notify acknowledge entry.
2715fcf3ce44SJohn Forte  *
2716fcf3ce44SJohn Forte  * Input:
2717fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
2718fcf3ce44SJohn Forte  *	pkt:		entry pointer.
2719fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
2720fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
2721fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
2722fcf3ce44SJohn Forte  *
2723fcf3ce44SJohn Forte  * Context:
2724fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
2725fcf3ce44SJohn Forte  */
2726fcf3ce44SJohn Forte /* ARGSUSED */
2727fcf3ce44SJohn Forte static void
2728fcf3ce44SJohn Forte ql_notify_acknowledge_entry(ql_adapter_state_t *ha,
2729fcf3ce44SJohn Forte     notify_acknowledge_entry_t *pkt, ql_head_t *done_q, uint32_t *set_flags,
2730fcf3ce44SJohn Forte     uint32_t *reset_flags)
2731fcf3ce44SJohn Forte {
2732fcf3ce44SJohn Forte 	ql_srb_t	*sp;
2733fcf3ce44SJohn Forte 	uint32_t	index, cnt;
2734fcf3ce44SJohn Forte 
2735fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2736fcf3ce44SJohn Forte 
2737fcf3ce44SJohn Forte 	/* Get handle. */
2738fcf3ce44SJohn Forte 	cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
2739fcf3ce44SJohn Forte 	index = cnt & OSC_INDEX_MASK;
2740fcf3ce44SJohn Forte 
2741fcf3ce44SJohn Forte 	/* Validate handle. */
2742fcf3ce44SJohn Forte 	sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] :
2743fcf3ce44SJohn Forte 	    NULL;
2744fcf3ce44SJohn Forte 
2745fcf3ce44SJohn Forte 	if (sp != NULL && sp->handle == cnt) {
2746fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
2747fcf3ce44SJohn Forte 		sp->handle = 0;
2748fcf3ce44SJohn Forte 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
2749fcf3ce44SJohn Forte 
2750fcf3ce44SJohn Forte 		/* Set completion status */
2751fcf3ce44SJohn Forte 		sp->pkt->pkt_reason = ddi_get16(ha->hba_buf.acc_handle,
2752fcf3ce44SJohn Forte 		    &pkt->status) == 1 ? CS_COMPLETE : CS_PORT_UNAVAILABLE;
2753fcf3ce44SJohn Forte 
2754fcf3ce44SJohn Forte 		/* Set completed status. */
2755fcf3ce44SJohn Forte 		sp->flags |= SRB_ISP_COMPLETED;
2756fcf3ce44SJohn Forte 
2757fcf3ce44SJohn Forte 		/* Place command on done queue. */
2758fcf3ce44SJohn Forte 		ql_add_link_b(done_q, &sp->cmd);
2759fcf3ce44SJohn Forte 
2760fcf3ce44SJohn Forte 	} else if (cnt != QL_FCA_BRAND) {
2761fcf3ce44SJohn Forte 		if (sp == NULL) {
2762fcf3ce44SJohn Forte 			EL(ha, "unknown IOCB handle=%xh\n", cnt);
2763fcf3ce44SJohn Forte 		} else {
2764fcf3ce44SJohn Forte 			EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n",
2765fcf3ce44SJohn Forte 			    cnt, sp->handle);
2766fcf3ce44SJohn Forte 		}
2767fcf3ce44SJohn Forte 
2768fcf3ce44SJohn Forte 		(void) ql_binary_fw_dump(ha, FALSE);
2769fcf3ce44SJohn Forte 
2770fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED |
2771fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE))) {
2772fcf3ce44SJohn Forte 			EL(ha, "ISP Invalid handle, isp_abort_needed\n");
2773fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
2774fcf3ce44SJohn Forte 		}
2775fcf3ce44SJohn Forte 	}
2776fcf3ce44SJohn Forte 
2777fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2778fcf3ce44SJohn Forte }
2779fcf3ce44SJohn Forte 
2780fcf3ce44SJohn Forte /*
2781fcf3ce44SJohn Forte  * ql_accept_target_io_entry
2782fcf3ce44SJohn Forte  *	Processes accept target I/O entry.
2783fcf3ce44SJohn Forte  *
2784fcf3ce44SJohn Forte  * Input:
2785fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
2786fcf3ce44SJohn Forte  *	pkt:		entry pointer.
2787fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
2788fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
2789fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
2790fcf3ce44SJohn Forte  *
2791fcf3ce44SJohn Forte  * Context:
2792fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
2793fcf3ce44SJohn Forte  */
2794fcf3ce44SJohn Forte /* ARGSUSED */
2795fcf3ce44SJohn Forte static void
2796fcf3ce44SJohn Forte ql_accept_target_io_entry(ql_adapter_state_t *ha, atio_entry_t *pkt,
2797fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
2798fcf3ce44SJohn Forte {
2799fcf3ce44SJohn Forte 	ctio_entry_t	*ctio;
2800fcf3ce44SJohn Forte 	atio_entry_t	*atio;
2801fcf3ce44SJohn Forte 	ql_srb_t	*sp;
2802fcf3ce44SJohn Forte 	fcp_cmd_t	*fcp;
2803fcf3ce44SJohn Forte 	ql_tgt_t	*tq;
2804fcf3ce44SJohn Forte 	uint16_t	loop_id;
2805fcf3ce44SJohn Forte 	fc_unsol_buf_t	*ubp = NULL;
2806fcf3ce44SJohn Forte 
2807fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2808fcf3ce44SJohn Forte 
2809fcf3ce44SJohn Forte 	/* Locate a buffer to use. */
2810fcf3ce44SJohn Forte 	loop_id = (uint16_t)(CFG_IST(ha, CFG_EXT_FW_INTERFACE) ?
2811fcf3ce44SJohn Forte 	    CHAR_TO_SHORT(pkt->initiator_id_l, pkt->initiator_id_h) :
2812fcf3ce44SJohn Forte 	    pkt->initiator_id_h);
2813fcf3ce44SJohn Forte 	if ((tq = ql_loop_id_to_queue(ha, loop_id)) != NULL) {
2814fcf3ce44SJohn Forte 		ubp = ql_get_unsolicited_buffer(ha,
2815fcf3ce44SJohn Forte 		    FC_TYPE_SCSI_FCP);
2816fcf3ce44SJohn Forte 	}
2817fcf3ce44SJohn Forte 	if (ubp != NULL) {
2818fcf3ce44SJohn Forte 		ubp->ub_resp_flags = FC_UB_FCP_CDB_FLAG;
2819fcf3ce44SJohn Forte 		ubp->ub_resp_token = tq;
2820fcf3ce44SJohn Forte 		sp = ubp->ub_fca_private;
2821fcf3ce44SJohn Forte 		fcp = (fcp_cmd_t *)ubp->ub_buffer;
2822fcf3ce44SJohn Forte 
2823fcf3ce44SJohn Forte 		/* Set header. */
2824fcf3ce44SJohn Forte 		ubp->ub_frame.d_id = ha->d_id.b24;
2825fcf3ce44SJohn Forte 		ubp->ub_frame.r_ctl = R_CTL_COMMAND;
2826fcf3ce44SJohn Forte 		ubp->ub_frame.s_id = tq->d_id.b24;
2827fcf3ce44SJohn Forte 		ubp->ub_frame.rsvd = 0;
2828fcf3ce44SJohn Forte 		ubp->ub_frame.f_ctl = F_CTL_FIRST_SEQ |
2829fcf3ce44SJohn Forte 		    F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
2830fcf3ce44SJohn Forte 		ubp->ub_frame.type = FC_TYPE_SCSI_FCP;
2831fcf3ce44SJohn Forte 		ubp->ub_frame.seq_cnt = 0;
2832fcf3ce44SJohn Forte 		ubp->ub_frame.df_ctl = 0;
2833fcf3ce44SJohn Forte 		ubp->ub_frame.seq_id = 0;
2834fcf3ce44SJohn Forte 		ubp->ub_frame.rx_id = (uint16_t)ddi_get16(
2835fcf3ce44SJohn Forte 		    ha->hba_buf.acc_handle, &pkt->rx_id);
2836fcf3ce44SJohn Forte 		ubp->ub_frame.ox_id = (uint16_t)ddi_get16(
2837fcf3ce44SJohn Forte 		    ha->hba_buf.acc_handle, &pkt->ox_id);
2838fcf3ce44SJohn Forte 		ubp->ub_frame.ro = 0;
2839fcf3ce44SJohn Forte 
2840fcf3ce44SJohn Forte 		/* Set command in buffer. */
2841fcf3ce44SJohn Forte 
2842fcf3ce44SJohn Forte 		bzero((void *)fcp, sizeof (fcp_cmd_t));
2843fcf3ce44SJohn Forte 
2844fcf3ce44SJohn Forte 		lobyte(fcp->fcp_ent_addr.ent_addr_0) = pkt->lun_l;
2845fcf3ce44SJohn Forte 		hibyte(fcp->fcp_ent_addr.ent_addr_0) = pkt->lun_h;
2846fcf3ce44SJohn Forte 
2847fcf3ce44SJohn Forte 		fcp->fcp_cntl.cntl_qtype = pkt->task_codes;
2848fcf3ce44SJohn Forte 
2849fcf3ce44SJohn Forte 		if (pkt->execution_codes & BIT_1)
2850fcf3ce44SJohn Forte 			fcp->fcp_cntl.cntl_read_data = 1;
2851fcf3ce44SJohn Forte 		if (pkt->execution_codes & BIT_0)
2852fcf3ce44SJohn Forte 			fcp->fcp_cntl.cntl_write_data = 1;
2853fcf3ce44SJohn Forte 
2854fcf3ce44SJohn Forte 		ddi_rep_put8(ha->hba_buf.acc_handle, (uint8_t *)&pkt->cdb[0],
2855fcf3ce44SJohn Forte 		    (uint8_t *)&fcp->fcp_cdb[0], FCP_CDB_SIZE,
2856fcf3ce44SJohn Forte 		    DDI_DEV_AUTOINCR);
2857fcf3ce44SJohn Forte 
2858fcf3ce44SJohn Forte 		fcp->fcp_data_len = (int)ddi_get32(
2859fcf3ce44SJohn Forte 		    ha->hba_buf.acc_handle, (uint32_t *)&pkt->data_length);
2860fcf3ce44SJohn Forte 		QL_UB_LOCK(ha);
2861fcf3ce44SJohn Forte 		sp->flags |= SRB_UB_CALLBACK | SRB_UB_FCP;
2862fcf3ce44SJohn Forte 		QL_UB_UNLOCK(ha);
2863fcf3ce44SJohn Forte 		ql_add_link_b(done_q, &sp->cmd);
2864fcf3ce44SJohn Forte 	}
2865fcf3ce44SJohn Forte 
2866fcf3ce44SJohn Forte 	/* If command not sent to transport layer. */
2867fcf3ce44SJohn Forte 	if (ubp == NULL) {
2868fcf3ce44SJohn Forte 
2869fcf3ce44SJohn Forte 		if (ql_req_pkt(ha, (request_t **)&ctio) == QL_SUCCESS) {
2870fcf3ce44SJohn Forte 			ctio->entry_type = CTIO_TYPE_2;
2871fcf3ce44SJohn Forte 			ctio->initiator_id_l = pkt->initiator_id_l;
2872fcf3ce44SJohn Forte 			ctio->initiator_id_h = pkt->initiator_id_h;
2873fcf3ce44SJohn Forte 			ddi_put16(ha->hba_buf.acc_handle, &ctio->rx_id,
2874fcf3ce44SJohn Forte 			    (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
2875fcf3ce44SJohn Forte 			    &pkt->rx_id));
2876fcf3ce44SJohn Forte 			ctio->flags_l = BIT_7 | BIT_6;
2877fcf3ce44SJohn Forte 			ctio->flags_h = BIT_7 | BIT_1 | BIT_0;
2878fcf3ce44SJohn Forte 			ctio->timeout = 0xffff;
2879fcf3ce44SJohn Forte 			ctio->type.s0_32bit.scsi_status_l = STATUS_BUSY;
2880fcf3ce44SJohn Forte 
2881fcf3ce44SJohn Forte 			/* Issue command to ISP */
2882fcf3ce44SJohn Forte 			ql_isp_cmd(ha);
2883fcf3ce44SJohn Forte 		}
2884fcf3ce44SJohn Forte 	} else {
2885fcf3ce44SJohn Forte 		if (ql_req_pkt(ha, (request_t **)&atio) == QL_SUCCESS) {
2886fcf3ce44SJohn Forte 			atio->entry_type = ATIO_TYPE;
2887fcf3ce44SJohn Forte 			atio->initiator_id_l = pkt->initiator_id_l;
2888fcf3ce44SJohn Forte 			atio->initiator_id_h = pkt->initiator_id_h;
2889fcf3ce44SJohn Forte 			ddi_put16(ha->hba_buf.acc_handle, &atio->rx_id,
2890fcf3ce44SJohn Forte 			    (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
2891fcf3ce44SJohn Forte 			    &pkt->rx_id));
2892fcf3ce44SJohn Forte 			atio->lun_l = pkt->lun_l;
2893fcf3ce44SJohn Forte 			atio->lun_h = pkt->lun_h;
2894fcf3ce44SJohn Forte 
2895fcf3ce44SJohn Forte 			/* Issue command to ISP */
2896fcf3ce44SJohn Forte 			ql_isp_cmd(ha);
2897fcf3ce44SJohn Forte 		}
2898fcf3ce44SJohn Forte 	}
2899fcf3ce44SJohn Forte 
2900fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2901fcf3ce44SJohn Forte }
2902fcf3ce44SJohn Forte 
2903fcf3ce44SJohn Forte /*
2904fcf3ce44SJohn Forte  * ql_continue_target_io_entry
2905fcf3ce44SJohn Forte  *	Processes continue target IO entry.
2906fcf3ce44SJohn Forte  *
2907fcf3ce44SJohn Forte  * Input:
2908fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
2909fcf3ce44SJohn Forte  *	pkt:		entry pointer.
2910fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
2911fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
2912fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
2913fcf3ce44SJohn Forte  *
2914fcf3ce44SJohn Forte  * Context:
2915fcf3ce44SJohn Forte  *	Interrupt context, no mailbox commands allowed.
2916fcf3ce44SJohn Forte  */
2917fcf3ce44SJohn Forte /* ARGSUSED */
2918fcf3ce44SJohn Forte static void
2919fcf3ce44SJohn Forte ql_continue_target_io_entry(ql_adapter_state_t *ha, ctio_entry_t *pkt,
2920fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
2921fcf3ce44SJohn Forte {
2922fcf3ce44SJohn Forte 	ql_srb_t	*sp;
2923fcf3ce44SJohn Forte 	uint32_t	index, cnt;
2924fcf3ce44SJohn Forte 	uint16_t	status;
2925fcf3ce44SJohn Forte 
2926fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2927fcf3ce44SJohn Forte 
2928fcf3ce44SJohn Forte 	/* Get handle. */
2929fcf3ce44SJohn Forte 	cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
2930fcf3ce44SJohn Forte 	index = cnt & OSC_INDEX_MASK;
2931fcf3ce44SJohn Forte 
2932fcf3ce44SJohn Forte 	/* Validate handle. */
2933fcf3ce44SJohn Forte 	sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] :
2934fcf3ce44SJohn Forte 	    NULL;
2935fcf3ce44SJohn Forte 
2936fcf3ce44SJohn Forte 	if (sp != NULL && sp->handle == cnt) {
2937fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
2938fcf3ce44SJohn Forte 		sp->handle = 0;
2939fcf3ce44SJohn Forte 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
2940fcf3ce44SJohn Forte 
2941fcf3ce44SJohn Forte 		/* Set completion status */
2942fcf3ce44SJohn Forte 		status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
2943fcf3ce44SJohn Forte 		    &pkt->status);
2944fcf3ce44SJohn Forte 
2945fcf3ce44SJohn Forte 		switch (status) {
2946fcf3ce44SJohn Forte 		case 1:
2947fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_COMPLETE;
2948fcf3ce44SJohn Forte 			break;
2949fcf3ce44SJohn Forte 		case 2:
2950fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_ABORTED;
2951fcf3ce44SJohn Forte 			break;
2952fcf3ce44SJohn Forte 		case 9:
2953fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_DATA_OVERRUN;
2954fcf3ce44SJohn Forte 			break;
2955fcf3ce44SJohn Forte 		case 0xa:
2956fcf3ce44SJohn Forte 		case 0xb:
2957fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_TIMEOUT;
2958fcf3ce44SJohn Forte 			break;
2959fcf3ce44SJohn Forte 		case 0xe:
2960fcf3ce44SJohn Forte 		case 0x17:
2961fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_RESET;
2962fcf3ce44SJohn Forte 			break;
2963fcf3ce44SJohn Forte 		case 0x10:
2964fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_DMA_ERROR;
2965fcf3ce44SJohn Forte 			break;
2966fcf3ce44SJohn Forte 		case 0x15:
2967fcf3ce44SJohn Forte 		case 0x28:
2968fcf3ce44SJohn Forte 		case 0x29:
2969fcf3ce44SJohn Forte 		case 0x2A:
2970fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = status;
2971fcf3ce44SJohn Forte 			break;
2972fcf3ce44SJohn Forte 		default:
2973fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = CS_PORT_UNAVAILABLE;
2974fcf3ce44SJohn Forte 			break;
2975fcf3ce44SJohn Forte 		}
2976fcf3ce44SJohn Forte 
2977fcf3ce44SJohn Forte 		/* Set completed status. */
2978fcf3ce44SJohn Forte 		sp->flags |= SRB_ISP_COMPLETED;
2979fcf3ce44SJohn Forte 
2980fcf3ce44SJohn Forte 		/* Place command on done queue. */
2981fcf3ce44SJohn Forte 		ql_add_link_b(done_q, &sp->cmd);
2982fcf3ce44SJohn Forte 
2983fcf3ce44SJohn Forte 	} else if (cnt != QL_FCA_BRAND) {
2984fcf3ce44SJohn Forte 		if (sp == NULL) {
2985fcf3ce44SJohn Forte 			EL(ha, "unknown IOCB handle=%xh\n", cnt);
2986fcf3ce44SJohn Forte 		} else {
2987fcf3ce44SJohn Forte 			EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n",
2988fcf3ce44SJohn Forte 			    cnt, sp->handle);
2989fcf3ce44SJohn Forte 		}
2990fcf3ce44SJohn Forte 
2991fcf3ce44SJohn Forte 		(void) ql_binary_fw_dump(ha, FALSE);
2992fcf3ce44SJohn Forte 
2993fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED |
2994fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE))) {
2995fcf3ce44SJohn Forte 			EL(ha, "ISP Invalid handle, isp_abort_needed\n");
2996fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
2997fcf3ce44SJohn Forte 		}
2998fcf3ce44SJohn Forte 	}
2999fcf3ce44SJohn Forte 
3000fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3001fcf3ce44SJohn Forte }
3002fcf3ce44SJohn Forte 
3003fcf3ce44SJohn Forte /*
3004fcf3ce44SJohn Forte  * ql_ip_entry
3005fcf3ce44SJohn Forte  *	Processes received ISP IP entry.
3006fcf3ce44SJohn Forte  *
3007fcf3ce44SJohn Forte  * Input:
3008fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
3009fcf3ce44SJohn Forte  *	pkt:		entry pointer.
3010fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
3011fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
3012fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
3013fcf3ce44SJohn Forte  *
3014fcf3ce44SJohn Forte  * Context:
3015fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3016fcf3ce44SJohn Forte  */
3017fcf3ce44SJohn Forte /* ARGSUSED */
3018fcf3ce44SJohn Forte static void
3019fcf3ce44SJohn Forte ql_ip_entry(ql_adapter_state_t *ha, ip_entry_t *pkt23, ql_head_t *done_q,
3020fcf3ce44SJohn Forte     uint32_t *set_flags, uint32_t *reset_flags)
3021fcf3ce44SJohn Forte {
3022fcf3ce44SJohn Forte 	ql_srb_t	*sp;
3023fcf3ce44SJohn Forte 	uint32_t	index, cnt;
3024fcf3ce44SJohn Forte 	ql_tgt_t	*tq;
3025fcf3ce44SJohn Forte 
3026fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3027fcf3ce44SJohn Forte 
3028fcf3ce44SJohn Forte 	/* Get handle. */
3029fcf3ce44SJohn Forte 	cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle);
3030fcf3ce44SJohn Forte 	index = cnt & OSC_INDEX_MASK;
3031fcf3ce44SJohn Forte 
3032fcf3ce44SJohn Forte 	/* Validate handle. */
3033fcf3ce44SJohn Forte 	sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] :
3034fcf3ce44SJohn Forte 	    NULL;
3035fcf3ce44SJohn Forte 
3036fcf3ce44SJohn Forte 	if (sp != NULL && sp->handle == cnt) {
3037fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
3038fcf3ce44SJohn Forte 		sp->handle = 0;
3039fcf3ce44SJohn Forte 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
3040fcf3ce44SJohn Forte 		tq = sp->lun_queue->target_queue;
3041fcf3ce44SJohn Forte 
3042fcf3ce44SJohn Forte 		/* Set ISP completion status */
3043fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_CTRL_2425)) {
3044fcf3ce44SJohn Forte 			ip_cmd_entry_t	*pkt24 = (ip_cmd_entry_t *)pkt23;
3045fcf3ce44SJohn Forte 
3046fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = ddi_get16(
3047fcf3ce44SJohn Forte 			    ha->hba_buf.acc_handle, &pkt24->hdl_status);
3048fcf3ce44SJohn Forte 		} else {
3049fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = ddi_get16(
3050fcf3ce44SJohn Forte 			    ha->hba_buf.acc_handle, &pkt23->comp_status);
3051fcf3ce44SJohn Forte 		}
3052fcf3ce44SJohn Forte 
3053fcf3ce44SJohn Forte 		if (ha->task_daemon_flags & LOOP_DOWN) {
3054fcf3ce44SJohn Forte 			EL(ha, "Loop Not Ready Retry, d_id=%xh\n",
3055fcf3ce44SJohn Forte 			    tq->d_id.b24);
3056fcf3ce44SJohn Forte 
3057fcf3ce44SJohn Forte 			/* Set retry status. */
3058fcf3ce44SJohn Forte 			sp->flags |= SRB_RETRY;
3059fcf3ce44SJohn Forte 
3060fcf3ce44SJohn Forte 		} else if (tq->port_down_retry_count &&
3061fcf3ce44SJohn Forte 		    (sp->pkt->pkt_reason == CS_INCOMPLETE ||
3062fcf3ce44SJohn Forte 		    sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE ||
3063fcf3ce44SJohn Forte 		    sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT ||
3064fcf3ce44SJohn Forte 		    sp->pkt->pkt_reason == CS_PORT_CONFIG_CHG ||
3065fcf3ce44SJohn Forte 		    sp->pkt->pkt_reason == CS_PORT_BUSY)) {
3066fcf3ce44SJohn Forte 			EL(ha, "Port Down Retry=%xh, d_id=%xh, count=%d\n",
3067fcf3ce44SJohn Forte 			    sp->pkt->pkt_reason, tq->d_id.b24,
3068fcf3ce44SJohn Forte 			    tq->port_down_retry_count);
3069fcf3ce44SJohn Forte 
3070fcf3ce44SJohn Forte 			/* Set retry status. */
3071fcf3ce44SJohn Forte 			sp->flags |= SRB_RETRY;
3072fcf3ce44SJohn Forte 
3073fcf3ce44SJohn Forte 			if (sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT ||
3074fcf3ce44SJohn Forte 			    sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE) {
3075fcf3ce44SJohn Forte 				ha->adapter_stats->d_stats[lobyte(
3076fcf3ce44SJohn Forte 				    tq->loop_id)].logouts_recvd++;
3077fcf3ce44SJohn Forte 				ql_send_logo(ha, tq, done_q);
3078fcf3ce44SJohn Forte 			}
3079fcf3ce44SJohn Forte 
3080fcf3ce44SJohn Forte 			/* Acquire device queue lock. */
3081fcf3ce44SJohn Forte 			DEVICE_QUEUE_LOCK(tq);
3082fcf3ce44SJohn Forte 
3083fcf3ce44SJohn Forte 			if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) {
3084fcf3ce44SJohn Forte 				tq->flags |= TQF_QUEUE_SUSPENDED;
3085fcf3ce44SJohn Forte 
3086fcf3ce44SJohn Forte 				tq->port_down_retry_count--;
3087fcf3ce44SJohn Forte 
3088fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
3089fcf3ce44SJohn Forte 				if (ha->port_retry_timer == 0) {
3090fcf3ce44SJohn Forte 					if ((ha->port_retry_timer =
3091fcf3ce44SJohn Forte 					    ha->port_down_retry_delay) == 0) {
3092fcf3ce44SJohn Forte 						*set_flags |=
3093fcf3ce44SJohn Forte 						    PORT_RETRY_NEEDED;
3094fcf3ce44SJohn Forte 					}
3095fcf3ce44SJohn Forte 				}
3096fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
3097fcf3ce44SJohn Forte 			}
3098fcf3ce44SJohn Forte 
3099fcf3ce44SJohn Forte 			/* Release device queue specific lock. */
3100fcf3ce44SJohn Forte 			DEVICE_QUEUE_UNLOCK(tq);
3101fcf3ce44SJohn Forte 
3102fcf3ce44SJohn Forte 		} else if (sp->pkt->pkt_reason == CS_RESET) {
3103fcf3ce44SJohn Forte 			EL(ha, "Reset Retry, d_id=%xh\n", tq->d_id.b24);
3104fcf3ce44SJohn Forte 
3105fcf3ce44SJohn Forte 			/* Set retry status. */
3106fcf3ce44SJohn Forte 			sp->flags |= SRB_RETRY;
3107fcf3ce44SJohn Forte 		} else {
3108fcf3ce44SJohn Forte 			if (sp->pkt->pkt_reason != CS_COMPLETE) {
3109fcf3ce44SJohn Forte 				EL(ha, "Cmplt status err=%xh, d_id=%xh\n",
3110fcf3ce44SJohn Forte 				    sp->pkt->pkt_reason, tq->d_id.b24);
3111fcf3ce44SJohn Forte 			}
3112fcf3ce44SJohn Forte 		}
3113fcf3ce44SJohn Forte 
3114fcf3ce44SJohn Forte 		/* Set completed status. */
3115fcf3ce44SJohn Forte 		sp->flags |= SRB_ISP_COMPLETED;
3116fcf3ce44SJohn Forte 
3117fcf3ce44SJohn Forte 		ql_add_link_b(done_q, &sp->cmd);
3118fcf3ce44SJohn Forte 
3119fcf3ce44SJohn Forte 	} else {
3120fcf3ce44SJohn Forte 		if (sp == NULL) {
3121fcf3ce44SJohn Forte 			EL(ha, "unknown IOCB handle=%xh\n", cnt);
3122fcf3ce44SJohn Forte 		} else {
3123fcf3ce44SJohn Forte 			EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n",
3124fcf3ce44SJohn Forte 			    cnt, sp->handle);
3125fcf3ce44SJohn Forte 		}
3126fcf3ce44SJohn Forte 
3127fcf3ce44SJohn Forte 		(void) ql_binary_fw_dump(ha, FALSE);
3128fcf3ce44SJohn Forte 
3129fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED |
3130fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE))) {
3131fcf3ce44SJohn Forte 			EL(ha, "ISP Invalid handle, isp_abort_needed\n");
3132fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
3133fcf3ce44SJohn Forte 		}
3134fcf3ce44SJohn Forte 	}
3135fcf3ce44SJohn Forte 
3136fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3137fcf3ce44SJohn Forte }
3138fcf3ce44SJohn Forte 
3139fcf3ce44SJohn Forte /*
3140fcf3ce44SJohn Forte  * ql_ip_rcv_entry
3141fcf3ce44SJohn Forte  *	Processes received ISP IP buffers entry.
3142fcf3ce44SJohn Forte  *
3143fcf3ce44SJohn Forte  * Input:
3144fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
3145fcf3ce44SJohn Forte  *	pkt:		entry pointer.
3146fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
3147fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
3148fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
3149fcf3ce44SJohn Forte  *
3150fcf3ce44SJohn Forte  * Context:
3151fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3152fcf3ce44SJohn Forte  */
3153fcf3ce44SJohn Forte /* ARGSUSED */
3154fcf3ce44SJohn Forte static void
3155fcf3ce44SJohn Forte ql_ip_rcv_entry(ql_adapter_state_t *ha, ip_rcv_entry_t *pkt,
3156fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
3157fcf3ce44SJohn Forte {
3158fcf3ce44SJohn Forte 	port_id_t	s_id;
3159fcf3ce44SJohn Forte 	uint16_t	index;
3160fcf3ce44SJohn Forte 	uint8_t		cnt;
3161fcf3ce44SJohn Forte 	ql_tgt_t	*tq;
3162fcf3ce44SJohn Forte 
3163fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3164fcf3ce44SJohn Forte 
3165fcf3ce44SJohn Forte 	/* Locate device queue. */
3166fcf3ce44SJohn Forte 	s_id.b.al_pa = pkt->s_id[0];
3167fcf3ce44SJohn Forte 	s_id.b.area = pkt->s_id[1];
3168fcf3ce44SJohn Forte 	s_id.b.domain = pkt->s_id[2];
3169fcf3ce44SJohn Forte 	if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
3170fcf3ce44SJohn Forte 		EL(ha, "Unknown IP device ID=%xh\n", s_id.b24);
3171fcf3ce44SJohn Forte 		return;
3172fcf3ce44SJohn Forte 	}
3173fcf3ce44SJohn Forte 
3174fcf3ce44SJohn Forte 	tq->ub_sequence_length = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
3175fcf3ce44SJohn Forte 	    &pkt->seq_length);
3176fcf3ce44SJohn Forte 	tq->ub_total_seg_cnt = pkt->segment_count;
3177fcf3ce44SJohn Forte 	tq->ub_seq_id = ++ha->ub_seq_id;
3178fcf3ce44SJohn Forte 	tq->ub_seq_cnt = 0;
3179fcf3ce44SJohn Forte 	tq->ub_frame_ro = 0;
3180fcf3ce44SJohn Forte 	tq->ub_loop_id = pkt->loop_id;
3181fcf3ce44SJohn Forte 	ha->rcv_dev_q = tq;
3182fcf3ce44SJohn Forte 
3183fcf3ce44SJohn Forte 	for (cnt = 0; cnt < IP_RCVBUF_HANDLES && tq->ub_seq_cnt <
3184fcf3ce44SJohn Forte 	    tq->ub_total_seg_cnt; cnt++) {
3185fcf3ce44SJohn Forte 
3186fcf3ce44SJohn Forte 		index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
3187fcf3ce44SJohn Forte 		    &pkt->buffer_handle[cnt]);
3188fcf3ce44SJohn Forte 
3189fcf3ce44SJohn Forte 		if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
3190fcf3ce44SJohn Forte 			EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
3191fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
3192fcf3ce44SJohn Forte 			break;
3193fcf3ce44SJohn Forte 		}
3194fcf3ce44SJohn Forte 	}
3195fcf3ce44SJohn Forte 
3196fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3197fcf3ce44SJohn Forte }
3198fcf3ce44SJohn Forte 
3199fcf3ce44SJohn Forte /*
3200fcf3ce44SJohn Forte  * ql_ip_rcv_cont_entry
3201fcf3ce44SJohn Forte  *	Processes received ISP IP buffers continuation entry.
3202fcf3ce44SJohn Forte  *
3203fcf3ce44SJohn Forte  * Input:
3204fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
3205fcf3ce44SJohn Forte  *	pkt:		entry pointer.
3206fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
3207fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
3208fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
3209fcf3ce44SJohn Forte  *
3210fcf3ce44SJohn Forte  * Context:
3211fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3212fcf3ce44SJohn Forte  */
3213fcf3ce44SJohn Forte /* ARGSUSED */
3214fcf3ce44SJohn Forte static void
3215fcf3ce44SJohn Forte ql_ip_rcv_cont_entry(ql_adapter_state_t *ha, ip_rcv_cont_entry_t *pkt,
3216fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
3217fcf3ce44SJohn Forte {
3218fcf3ce44SJohn Forte 	uint16_t	index;
3219fcf3ce44SJohn Forte 	uint8_t		cnt;
3220fcf3ce44SJohn Forte 	ql_tgt_t	*tq;
3221fcf3ce44SJohn Forte 
3222fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3223fcf3ce44SJohn Forte 
3224fcf3ce44SJohn Forte 	if ((tq = ha->rcv_dev_q) == NULL) {
3225fcf3ce44SJohn Forte 		EL(ha, "No IP receive device\n");
3226fcf3ce44SJohn Forte 		return;
3227fcf3ce44SJohn Forte 	}
3228fcf3ce44SJohn Forte 
3229fcf3ce44SJohn Forte 	for (cnt = 0; cnt < IP_RCVBUF_CONT_HANDLES &&
3230fcf3ce44SJohn Forte 	    tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
3231fcf3ce44SJohn Forte 
3232fcf3ce44SJohn Forte 		index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
3233fcf3ce44SJohn Forte 		    &pkt->buffer_handle[cnt]);
3234fcf3ce44SJohn Forte 
3235fcf3ce44SJohn Forte 		if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
3236fcf3ce44SJohn Forte 			EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
3237fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
3238fcf3ce44SJohn Forte 			break;
3239fcf3ce44SJohn Forte 		}
3240fcf3ce44SJohn Forte 	}
3241fcf3ce44SJohn Forte 
3242fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3243fcf3ce44SJohn Forte }
3244fcf3ce44SJohn Forte 
3245fcf3ce44SJohn Forte /*
3246fcf3ce44SJohn Forte  * ip_rcv_24xx_entry_t
3247fcf3ce44SJohn Forte  *	Processes received ISP24xx IP buffers entry.
3248fcf3ce44SJohn Forte  *
3249fcf3ce44SJohn Forte  * Input:
3250fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
3251fcf3ce44SJohn Forte  *	pkt:		entry pointer.
3252fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
3253fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
3254fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
3255fcf3ce44SJohn Forte  *
3256fcf3ce44SJohn Forte  * Context:
3257fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3258fcf3ce44SJohn Forte  */
3259fcf3ce44SJohn Forte /* ARGSUSED */
3260fcf3ce44SJohn Forte static void
3261fcf3ce44SJohn Forte ql_ip_24xx_rcv_entry(ql_adapter_state_t *ha, ip_rcv_24xx_entry_t *pkt,
3262fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
3263fcf3ce44SJohn Forte {
3264fcf3ce44SJohn Forte 	port_id_t	s_id;
3265fcf3ce44SJohn Forte 	uint16_t	index;
3266fcf3ce44SJohn Forte 	uint8_t		cnt;
3267fcf3ce44SJohn Forte 	ql_tgt_t	*tq;
3268fcf3ce44SJohn Forte 
3269fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3270fcf3ce44SJohn Forte 
3271fcf3ce44SJohn Forte 	/* Locate device queue. */
3272fcf3ce44SJohn Forte 	s_id.b.al_pa = pkt->s_id[0];
3273fcf3ce44SJohn Forte 	s_id.b.area = pkt->s_id[1];
3274fcf3ce44SJohn Forte 	s_id.b.domain = pkt->s_id[2];
3275fcf3ce44SJohn Forte 	if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
3276fcf3ce44SJohn Forte 		EL(ha, "Unknown IP device ID=%xh\n", s_id.b24);
3277fcf3ce44SJohn Forte 		return;
3278fcf3ce44SJohn Forte 	}
3279fcf3ce44SJohn Forte 
3280fcf3ce44SJohn Forte 	if (tq->ub_total_seg_cnt == 0) {
3281fcf3ce44SJohn Forte 		tq->ub_sequence_length = (uint16_t)ddi_get16(
3282fcf3ce44SJohn Forte 		    ha->hba_buf.acc_handle, &pkt->seq_length);
3283fcf3ce44SJohn Forte 		tq->ub_total_seg_cnt = pkt->segment_count;
3284fcf3ce44SJohn Forte 		tq->ub_seq_id = ++ha->ub_seq_id;
3285fcf3ce44SJohn Forte 		tq->ub_seq_cnt = 0;
3286fcf3ce44SJohn Forte 		tq->ub_frame_ro = 0;
3287fcf3ce44SJohn Forte 		tq->ub_loop_id = (uint16_t)ddi_get16(
3288fcf3ce44SJohn Forte 		    ha->hba_buf.acc_handle, &pkt->n_port_hdl);
3289fcf3ce44SJohn Forte 	}
3290fcf3ce44SJohn Forte 
3291fcf3ce44SJohn Forte 	for (cnt = 0; cnt < IP_24XX_RCVBUF_HANDLES && tq->ub_seq_cnt <
3292fcf3ce44SJohn Forte 	    tq->ub_total_seg_cnt; cnt++) {
3293fcf3ce44SJohn Forte 
3294fcf3ce44SJohn Forte 		index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
3295fcf3ce44SJohn Forte 		    &pkt->buffer_handle[cnt]);
3296fcf3ce44SJohn Forte 
3297fcf3ce44SJohn Forte 		if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
3298fcf3ce44SJohn Forte 			EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
3299fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
3300fcf3ce44SJohn Forte 			break;
3301fcf3ce44SJohn Forte 		}
3302fcf3ce44SJohn Forte 	}
3303fcf3ce44SJohn Forte 
3304fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3305fcf3ce44SJohn Forte }
3306fcf3ce44SJohn Forte 
3307fcf3ce44SJohn Forte /*
3308fcf3ce44SJohn Forte  * ql_ms_entry
3309fcf3ce44SJohn Forte  *	Processes received Name/Management/CT Pass-Through entry.
3310fcf3ce44SJohn Forte  *
3311fcf3ce44SJohn Forte  * Input:
3312fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
3313fcf3ce44SJohn Forte  *	pkt23:		entry pointer.
3314fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
3315fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
3316fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
3317fcf3ce44SJohn Forte  *
3318fcf3ce44SJohn Forte  * Context:
3319fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3320fcf3ce44SJohn Forte  */
3321fcf3ce44SJohn Forte /* ARGSUSED */
3322fcf3ce44SJohn Forte static void
3323fcf3ce44SJohn Forte ql_ms_entry(ql_adapter_state_t *ha, ms_entry_t *pkt23, ql_head_t *done_q,
3324fcf3ce44SJohn Forte     uint32_t *set_flags, uint32_t *reset_flags)
3325fcf3ce44SJohn Forte {
3326fcf3ce44SJohn Forte 	ql_srb_t		*sp;
3327fcf3ce44SJohn Forte 	uint32_t		index, cnt;
3328fcf3ce44SJohn Forte 	ql_tgt_t		*tq;
3329fcf3ce44SJohn Forte 	ct_passthru_entry_t	*pkt24 = (ct_passthru_entry_t *)pkt23;
3330fcf3ce44SJohn Forte 
3331fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3332fcf3ce44SJohn Forte 
3333fcf3ce44SJohn Forte 	/* Get handle. */
3334fcf3ce44SJohn Forte 	cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle);
3335fcf3ce44SJohn Forte 	index = cnt & OSC_INDEX_MASK;
3336fcf3ce44SJohn Forte 
3337fcf3ce44SJohn Forte 	/* Validate handle. */
3338fcf3ce44SJohn Forte 	sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] :
3339fcf3ce44SJohn Forte 	    NULL;
3340fcf3ce44SJohn Forte 
3341fcf3ce44SJohn Forte 	if (sp != NULL && sp->handle == cnt) {
3342fcf3ce44SJohn Forte 		if (!(sp->flags & SRB_MS_PKT)) {
3343fcf3ce44SJohn Forte 			EL(ha, "Not SRB_MS_PKT flags=%xh, isp_abort_needed",
3344fcf3ce44SJohn Forte 			    sp->flags);
3345fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
3346fcf3ce44SJohn Forte 			return;
3347fcf3ce44SJohn Forte 		}
3348fcf3ce44SJohn Forte 
3349fcf3ce44SJohn Forte 		ha->outstanding_cmds[index] = NULL;
3350fcf3ce44SJohn Forte 		sp->handle = 0;
3351fcf3ce44SJohn Forte 		sp->flags &= ~SRB_IN_TOKEN_ARRAY;
3352fcf3ce44SJohn Forte 		tq = sp->lun_queue->target_queue;
3353fcf3ce44SJohn Forte 
3354fcf3ce44SJohn Forte 		/* Set ISP completion status */
3355fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_CTRL_2425)) {
3356fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = ddi_get16(
3357fcf3ce44SJohn Forte 			    ha->hba_buf.acc_handle, &pkt24->status);
3358fcf3ce44SJohn Forte 		} else {
3359fcf3ce44SJohn Forte 			sp->pkt->pkt_reason = ddi_get16(
3360fcf3ce44SJohn Forte 			    ha->hba_buf.acc_handle, &pkt23->comp_status);
3361fcf3ce44SJohn Forte 		}
3362fcf3ce44SJohn Forte 
3363fcf3ce44SJohn Forte 		if (sp->pkt->pkt_reason == CS_RESOUCE_UNAVAILABLE &&
3364fcf3ce44SJohn Forte 		    sp->retry_count) {
3365fcf3ce44SJohn Forte 			EL(ha, "Resouce Unavailable Retry = %d\n",
3366fcf3ce44SJohn Forte 			    sp->retry_count);
3367fcf3ce44SJohn Forte 
3368fcf3ce44SJohn Forte 			/* Set retry status. */
3369fcf3ce44SJohn Forte 			sp->retry_count--;
3370fcf3ce44SJohn Forte 			sp->flags |= SRB_RETRY;
3371fcf3ce44SJohn Forte 
3372fcf3ce44SJohn Forte 			/* Acquire device queue lock. */
3373fcf3ce44SJohn Forte 			DEVICE_QUEUE_LOCK(tq);
3374fcf3ce44SJohn Forte 
3375fcf3ce44SJohn Forte 			if (!(tq->flags & TQF_QUEUE_SUSPENDED)) {
3376fcf3ce44SJohn Forte 				tq->flags |= TQF_QUEUE_SUSPENDED;
3377fcf3ce44SJohn Forte 
3378fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
3379fcf3ce44SJohn Forte 				if (ha->port_retry_timer == 0) {
3380fcf3ce44SJohn Forte 					ha->port_retry_timer = 2;
3381fcf3ce44SJohn Forte 				}
3382fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
3383fcf3ce44SJohn Forte 			}
3384fcf3ce44SJohn Forte 
3385fcf3ce44SJohn Forte 			/* Release device queue specific lock. */
3386fcf3ce44SJohn Forte 			DEVICE_QUEUE_UNLOCK(tq);
3387fcf3ce44SJohn Forte 
3388fcf3ce44SJohn Forte 		} else if (tq->port_down_retry_count &&
3389fcf3ce44SJohn Forte 		    (sp->pkt->pkt_reason == CS_PORT_CONFIG_CHG ||
3390fcf3ce44SJohn Forte 		    sp->pkt->pkt_reason == CS_PORT_BUSY)) {
3391fcf3ce44SJohn Forte 			EL(ha, "Port Down Retry\n");
3392fcf3ce44SJohn Forte 
3393fcf3ce44SJohn Forte 			/* Set retry status. */
3394fcf3ce44SJohn Forte 			sp->flags |= SRB_RETRY;
3395fcf3ce44SJohn Forte 
3396fcf3ce44SJohn Forte 			/* Acquire device queue lock. */
3397fcf3ce44SJohn Forte 			DEVICE_QUEUE_LOCK(tq);
3398fcf3ce44SJohn Forte 
3399fcf3ce44SJohn Forte 			if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) {
3400fcf3ce44SJohn Forte 				tq->flags |= TQF_QUEUE_SUSPENDED;
3401fcf3ce44SJohn Forte 
3402fcf3ce44SJohn Forte 				tq->port_down_retry_count--;
3403fcf3ce44SJohn Forte 
3404fcf3ce44SJohn Forte 				ADAPTER_STATE_LOCK(ha);
3405fcf3ce44SJohn Forte 				if (ha->port_retry_timer == 0) {
3406fcf3ce44SJohn Forte 					if ((ha->port_retry_timer =
3407fcf3ce44SJohn Forte 					    ha->port_down_retry_delay) == 0) {
3408fcf3ce44SJohn Forte 						*set_flags |=
3409fcf3ce44SJohn Forte 						    PORT_RETRY_NEEDED;
3410fcf3ce44SJohn Forte 					}
3411fcf3ce44SJohn Forte 				}
3412fcf3ce44SJohn Forte 				ADAPTER_STATE_UNLOCK(ha);
3413fcf3ce44SJohn Forte 			}
3414fcf3ce44SJohn Forte 
3415fcf3ce44SJohn Forte 			/* Release device queue specific lock. */
3416fcf3ce44SJohn Forte 			DEVICE_QUEUE_UNLOCK(tq);
3417fcf3ce44SJohn Forte 
3418fcf3ce44SJohn Forte 		} else if (sp->pkt->pkt_reason == CS_RESET) {
3419fcf3ce44SJohn Forte 			EL(ha, "Reset Retry\n");
3420fcf3ce44SJohn Forte 
3421fcf3ce44SJohn Forte 			/* Set retry status. */
3422fcf3ce44SJohn Forte 			sp->flags |= SRB_RETRY;
3423fcf3ce44SJohn Forte 
3424fcf3ce44SJohn Forte 		} else if (CFG_IST(ha, CFG_CTRL_2425) &&
3425fcf3ce44SJohn Forte 		    sp->pkt->pkt_reason == CS_DATA_UNDERRUN) {
3426fcf3ce44SJohn Forte 			cnt = ddi_get32(ha->hba_buf.acc_handle,
3427fcf3ce44SJohn Forte 			    &pkt24->resp_byte_count);
3428fcf3ce44SJohn Forte 			if (cnt < sizeof (fc_ct_header_t)) {
3429*16dd44c2SDaniel Beauregard 				EL(ha, "Data underrun\n");
3430fcf3ce44SJohn Forte 			} else {
3431fcf3ce44SJohn Forte 				sp->pkt->pkt_reason = CS_COMPLETE;
3432fcf3ce44SJohn Forte 			}
3433fcf3ce44SJohn Forte 
3434fcf3ce44SJohn Forte 		} else if (sp->pkt->pkt_reason != CS_COMPLETE) {
3435fcf3ce44SJohn Forte 			EL(ha, "status err=%xh\n", sp->pkt->pkt_reason);
3436fcf3ce44SJohn Forte 		}
3437fcf3ce44SJohn Forte 
3438fcf3ce44SJohn Forte 		if (sp->pkt->pkt_reason == CS_COMPLETE) {
3439fcf3ce44SJohn Forte 			/*EMPTY*/
3440fcf3ce44SJohn Forte 			QL_PRINT_3(CE_CONT, "(%d): resp\n", ha->instance);
3441fcf3ce44SJohn Forte 			QL_DUMP_3(sp->pkt->pkt_resp, 8, sp->pkt->pkt_rsplen);
3442fcf3ce44SJohn Forte 		}
3443fcf3ce44SJohn Forte 
3444fcf3ce44SJohn Forte 		/* For nameserver restore command, management change header. */
3445fcf3ce44SJohn Forte 		if ((sp->flags & SRB_RETRY) == 0) {
3446fcf3ce44SJohn Forte 			tq->d_id.b24 == 0xfffffc ?
3447fcf3ce44SJohn Forte 			    ql_cthdr_endian(sp->pkt->pkt_cmd_acc,
3448fcf3ce44SJohn Forte 			    sp->pkt->pkt_cmd, B_TRUE) :
3449fcf3ce44SJohn Forte 			    ql_cthdr_endian(sp->pkt->pkt_resp_acc,
3450fcf3ce44SJohn Forte 			    sp->pkt->pkt_resp, B_TRUE);
3451fcf3ce44SJohn Forte 		}
3452fcf3ce44SJohn Forte 
3453fcf3ce44SJohn Forte 		/* Set completed status. */
3454fcf3ce44SJohn Forte 		sp->flags |= SRB_ISP_COMPLETED;
3455fcf3ce44SJohn Forte 
3456fcf3ce44SJohn Forte 		/* Place command on done queue. */
3457fcf3ce44SJohn Forte 		ql_add_link_b(done_q, &sp->cmd);
3458fcf3ce44SJohn Forte 
3459fcf3ce44SJohn Forte 	} else {
3460fcf3ce44SJohn Forte 		if (sp == NULL) {
3461fcf3ce44SJohn Forte 			EL(ha, "unknown IOCB handle=%xh\n", cnt);
3462fcf3ce44SJohn Forte 		} else {
3463fcf3ce44SJohn Forte 			EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n",
3464fcf3ce44SJohn Forte 			    cnt, sp->handle);
3465fcf3ce44SJohn Forte 		}
3466fcf3ce44SJohn Forte 
3467fcf3ce44SJohn Forte 		(void) ql_binary_fw_dump(ha, FALSE);
3468fcf3ce44SJohn Forte 
3469fcf3ce44SJohn Forte 		if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED |
3470fcf3ce44SJohn Forte 		    ABORT_ISP_ACTIVE))) {
3471fcf3ce44SJohn Forte 			EL(ha, "ISP Invalid handle, isp_abort_needed\n");
3472fcf3ce44SJohn Forte 			*set_flags |= ISP_ABORT_NEEDED;
3473fcf3ce44SJohn Forte 		}
3474fcf3ce44SJohn Forte 	}
3475fcf3ce44SJohn Forte 
3476fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3477fcf3ce44SJohn Forte }
3478fcf3ce44SJohn Forte 
3479fcf3ce44SJohn Forte /*
3480fcf3ce44SJohn Forte  * ql_report_id_entry
3481fcf3ce44SJohn Forte  *	Processes received Name/Management/CT Pass-Through entry.
3482fcf3ce44SJohn Forte  *
3483fcf3ce44SJohn Forte  * Input:
3484fcf3ce44SJohn Forte  *	ha:		adapter state pointer.
3485fcf3ce44SJohn Forte  *	pkt23:		entry pointer.
3486fcf3ce44SJohn Forte  *	done_q:		done queue pointer.
3487fcf3ce44SJohn Forte  *	set_flags:	task daemon flags to set.
3488fcf3ce44SJohn Forte  *	reset_flags:	task daemon flags to reset.
3489fcf3ce44SJohn Forte  *
3490fcf3ce44SJohn Forte  * Context:
3491fcf3ce44SJohn Forte  *	Interrupt or Kernel context, no mailbox commands allowed.
3492fcf3ce44SJohn Forte  */
3493fcf3ce44SJohn Forte /* ARGSUSED */
3494fcf3ce44SJohn Forte static void
3495fcf3ce44SJohn Forte ql_report_id_entry(ql_adapter_state_t *ha, report_id_1_t *pkt,
3496fcf3ce44SJohn Forte     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
3497fcf3ce44SJohn Forte {
3498fcf3ce44SJohn Forte 	ql_adapter_state_t	*vha;
3499fcf3ce44SJohn Forte 
3500fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3501fcf3ce44SJohn Forte 
3502fcf3ce44SJohn Forte 	EL(ha, "format=%d, vp=%d, status=%d\n",
3503fcf3ce44SJohn Forte 	    pkt->format, pkt->vp_index, pkt->status);
3504fcf3ce44SJohn Forte 
3505fcf3ce44SJohn Forte 	if (pkt->format == 1) {
3506fcf3ce44SJohn Forte 		/* Locate port state structure. */
3507fcf3ce44SJohn Forte 		for (vha = ha; vha != NULL; vha = vha->vp_next) {
3508fcf3ce44SJohn Forte 			if (vha->vp_index == pkt->vp_index) {
3509fcf3ce44SJohn Forte 				break;
3510fcf3ce44SJohn Forte 			}
3511fcf3ce44SJohn Forte 		}
3512fcf3ce44SJohn Forte 		if (vha != NULL && (pkt->status == CS_COMPLETE ||
3513fcf3ce44SJohn Forte 		    pkt->status == CS_PORT_ID_CHANGE)) {
3514fcf3ce44SJohn Forte 			*set_flags |= LOOP_RESYNC_NEEDED;
3515fcf3ce44SJohn Forte 			*reset_flags &= ~LOOP_RESYNC_NEEDED;
3516fcf3ce44SJohn Forte 			vha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
3517fcf3ce44SJohn Forte 			TASK_DAEMON_LOCK(ha);
3518fcf3ce44SJohn Forte 			vha->task_daemon_flags |= LOOP_RESYNC_NEEDED;
3519fcf3ce44SJohn Forte 			vha->task_daemon_flags &= ~LOOP_DOWN;
3520fcf3ce44SJohn Forte 			TASK_DAEMON_UNLOCK(ha);
3521fcf3ce44SJohn Forte 		}
3522fcf3ce44SJohn Forte 	}
3523fcf3ce44SJohn Forte 
3524fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3525fcf3ce44SJohn Forte }
3526