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