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