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