xref: /onnv-gate/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_isr.c (revision 12279:f13874aa8143)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM 
2211541SDaniel.Beauregard@Sun.COM /* Copyright 2010 QLogic Corporation */
237836SJohn.Forte@Sun.COM 
247836SJohn.Forte@Sun.COM /*
25*12279SDaniel.Beauregard@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
267836SJohn.Forte@Sun.COM  */
277836SJohn.Forte@Sun.COM 
2811541SDaniel.Beauregard@Sun.COM #pragma ident	"Copyright 2010 QLogic Corporation; ql_isr.c"
297836SJohn.Forte@Sun.COM 
307836SJohn.Forte@Sun.COM /*
317836SJohn.Forte@Sun.COM  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
327836SJohn.Forte@Sun.COM  *
337836SJohn.Forte@Sun.COM  * ***********************************************************************
347836SJohn.Forte@Sun.COM  * *									**
357836SJohn.Forte@Sun.COM  * *				NOTICE					**
3611541SDaniel.Beauregard@Sun.COM  * *		COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION		**
377836SJohn.Forte@Sun.COM  * *			ALL RIGHTS RESERVED				**
387836SJohn.Forte@Sun.COM  * *									**
397836SJohn.Forte@Sun.COM  * ***********************************************************************
407836SJohn.Forte@Sun.COM  *
417836SJohn.Forte@Sun.COM  */
427836SJohn.Forte@Sun.COM 
437836SJohn.Forte@Sun.COM #include <ql_apps.h>
447836SJohn.Forte@Sun.COM #include <ql_api.h>
457836SJohn.Forte@Sun.COM #include <ql_debug.h>
467836SJohn.Forte@Sun.COM #include <ql_iocb.h>
477836SJohn.Forte@Sun.COM #include <ql_isr.h>
487836SJohn.Forte@Sun.COM #include <ql_init.h>
497836SJohn.Forte@Sun.COM #include <ql_mbx.h>
5011924SDaniel.Beauregard@Sun.COM #include <ql_nx.h>
517836SJohn.Forte@Sun.COM #include <ql_xioctl.h>
527836SJohn.Forte@Sun.COM 
537836SJohn.Forte@Sun.COM /*
547836SJohn.Forte@Sun.COM  * Local Function Prototypes.
557836SJohn.Forte@Sun.COM  */
569156SDaniel.Beauregard@Sun.COM static void ql_handle_uncommon_risc_intr(ql_adapter_state_t *, uint32_t,
579156SDaniel.Beauregard@Sun.COM     uint32_t *);
587836SJohn.Forte@Sun.COM static void ql_spurious_intr(ql_adapter_state_t *, int);
597836SJohn.Forte@Sun.COM static void ql_mbx_completion(ql_adapter_state_t *, uint16_t, uint32_t *,
607836SJohn.Forte@Sun.COM     uint32_t *, int);
617836SJohn.Forte@Sun.COM static void ql_async_event(ql_adapter_state_t *, uint32_t, ql_head_t *,
627836SJohn.Forte@Sun.COM     uint32_t *, uint32_t *, int);
637836SJohn.Forte@Sun.COM static void ql_fast_fcp_post(ql_srb_t *);
647836SJohn.Forte@Sun.COM static void ql_response_pkt(ql_adapter_state_t *, ql_head_t *, uint32_t *,
657836SJohn.Forte@Sun.COM     uint32_t *, int);
667836SJohn.Forte@Sun.COM static void ql_error_entry(ql_adapter_state_t *, response_t *, ql_head_t *,
677836SJohn.Forte@Sun.COM     uint32_t *, uint32_t *);
687836SJohn.Forte@Sun.COM static int ql_status_entry(ql_adapter_state_t *, sts_entry_t *, ql_head_t *,
697836SJohn.Forte@Sun.COM     uint32_t *, uint32_t *);
707836SJohn.Forte@Sun.COM static int ql_24xx_status_entry(ql_adapter_state_t *, sts_24xx_entry_t *,
717836SJohn.Forte@Sun.COM     ql_head_t *, uint32_t *, uint32_t *);
727836SJohn.Forte@Sun.COM static int ql_status_error(ql_adapter_state_t *, ql_srb_t *, sts_entry_t *,
737836SJohn.Forte@Sun.COM     ql_head_t *, uint32_t *, uint32_t *);
747836SJohn.Forte@Sun.COM static void ql_status_cont_entry(ql_adapter_state_t *, sts_cont_entry_t *,
757836SJohn.Forte@Sun.COM     ql_head_t *, uint32_t *, uint32_t *);
767836SJohn.Forte@Sun.COM static void ql_ip_entry(ql_adapter_state_t *, ip_entry_t *, ql_head_t *,
777836SJohn.Forte@Sun.COM     uint32_t *, uint32_t *);
787836SJohn.Forte@Sun.COM static void ql_ip_rcv_entry(ql_adapter_state_t *, ip_rcv_entry_t *,
797836SJohn.Forte@Sun.COM     ql_head_t *, uint32_t *, uint32_t *);
807836SJohn.Forte@Sun.COM static void ql_ip_rcv_cont_entry(ql_adapter_state_t *,
817836SJohn.Forte@Sun.COM     ip_rcv_cont_entry_t *, ql_head_t *, uint32_t *, uint32_t *);
827836SJohn.Forte@Sun.COM static void ql_ip_24xx_rcv_entry(ql_adapter_state_t *, ip_rcv_24xx_entry_t *,
837836SJohn.Forte@Sun.COM     ql_head_t *, uint32_t *, uint32_t *);
847836SJohn.Forte@Sun.COM static void ql_ms_entry(ql_adapter_state_t *, ms_entry_t *, ql_head_t *,
857836SJohn.Forte@Sun.COM     uint32_t *, uint32_t *);
867836SJohn.Forte@Sun.COM static void ql_report_id_entry(ql_adapter_state_t *, report_id_1_t *,
877836SJohn.Forte@Sun.COM     ql_head_t *, uint32_t *, uint32_t *);
889446SDaniel.Beauregard@Sun.COM static void ql_els_passthru_entry(ql_adapter_state_t *,
899446SDaniel.Beauregard@Sun.COM     els_passthru_entry_rsp_t *, ql_head_t *, uint32_t *, uint32_t *);
9010240SDaniel.Beauregard@Sun.COM static ql_srb_t *ql_verify_preprocessed_cmd(ql_adapter_state_t *, uint32_t *,
9110240SDaniel.Beauregard@Sun.COM     uint32_t *, uint32_t *);
9210240SDaniel.Beauregard@Sun.COM static void ql_signal_abort(ql_adapter_state_t *ha, uint32_t *set_flags);
937836SJohn.Forte@Sun.COM 
947836SJohn.Forte@Sun.COM /*
95*12279SDaniel.Beauregard@Sun.COM  * Spurious interrupt counter
96*12279SDaniel.Beauregard@Sun.COM  */
97*12279SDaniel.Beauregard@Sun.COM uint32_t	ql_spurious_cnt = 4;
98*12279SDaniel.Beauregard@Sun.COM uint32_t	ql_max_intr_loop = 16;
99*12279SDaniel.Beauregard@Sun.COM 
100*12279SDaniel.Beauregard@Sun.COM /*
1017836SJohn.Forte@Sun.COM  * ql_isr
1027836SJohn.Forte@Sun.COM  *	Process all INTX intr types.
1037836SJohn.Forte@Sun.COM  *
1047836SJohn.Forte@Sun.COM  * Input:
1057836SJohn.Forte@Sun.COM  *	arg1:	adapter state pointer.
1067836SJohn.Forte@Sun.COM  *
1077836SJohn.Forte@Sun.COM  * Returns:
1087836SJohn.Forte@Sun.COM  *	DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
1097836SJohn.Forte@Sun.COM  *
1107836SJohn.Forte@Sun.COM  * Context:
1117836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
1127836SJohn.Forte@Sun.COM  */
1137836SJohn.Forte@Sun.COM /* ARGSUSED */
1147836SJohn.Forte@Sun.COM uint_t
ql_isr(caddr_t arg1)1157836SJohn.Forte@Sun.COM ql_isr(caddr_t arg1)
1167836SJohn.Forte@Sun.COM {
1177836SJohn.Forte@Sun.COM 	return (ql_isr_aif(arg1, 0));
1187836SJohn.Forte@Sun.COM }
1197836SJohn.Forte@Sun.COM 
1207836SJohn.Forte@Sun.COM /*
1217836SJohn.Forte@Sun.COM  * ql_isr_default
1227836SJohn.Forte@Sun.COM  *	Process unknown/unvectored intr types
1237836SJohn.Forte@Sun.COM  *
1247836SJohn.Forte@Sun.COM  * Input:
1257836SJohn.Forte@Sun.COM  *	arg1:	adapter state pointer.
1267836SJohn.Forte@Sun.COM  *	arg2:	interrupt vector.
1277836SJohn.Forte@Sun.COM  *
1287836SJohn.Forte@Sun.COM  * Returns:
1297836SJohn.Forte@Sun.COM  *	DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
1307836SJohn.Forte@Sun.COM  *
1317836SJohn.Forte@Sun.COM  * Context:
1327836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
1337836SJohn.Forte@Sun.COM  */
1347836SJohn.Forte@Sun.COM /* ARGSUSED */
1357836SJohn.Forte@Sun.COM uint_t
ql_isr_default(caddr_t arg1,caddr_t arg2)1367836SJohn.Forte@Sun.COM ql_isr_default(caddr_t arg1, caddr_t arg2)
1377836SJohn.Forte@Sun.COM {
1387836SJohn.Forte@Sun.COM 	ql_adapter_state_t	*ha = (void *)arg1;
1397836SJohn.Forte@Sun.COM 
1407836SJohn.Forte@Sun.COM 	EL(ha, "isr_default called: idx=%x\n", arg2);
1417836SJohn.Forte@Sun.COM 	return (ql_isr_aif(arg1, arg2));
1427836SJohn.Forte@Sun.COM }
1437836SJohn.Forte@Sun.COM 
1447836SJohn.Forte@Sun.COM /*
1457836SJohn.Forte@Sun.COM  * ql_isr_aif
1467836SJohn.Forte@Sun.COM  *	Process mailbox and I/O command completions.
1477836SJohn.Forte@Sun.COM  *
1487836SJohn.Forte@Sun.COM  * Input:
1497836SJohn.Forte@Sun.COM  *	arg:	adapter state pointer.
1507836SJohn.Forte@Sun.COM  *	intvec:	interrupt vector.
1517836SJohn.Forte@Sun.COM  *
1527836SJohn.Forte@Sun.COM  * Returns:
1537836SJohn.Forte@Sun.COM  *	DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED
1547836SJohn.Forte@Sun.COM  *
1557836SJohn.Forte@Sun.COM  * Context:
1567836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
1577836SJohn.Forte@Sun.COM  */
1587836SJohn.Forte@Sun.COM /* ARGSUSED */
1597836SJohn.Forte@Sun.COM uint_t
ql_isr_aif(caddr_t arg,caddr_t intvec)1607836SJohn.Forte@Sun.COM ql_isr_aif(caddr_t arg, caddr_t intvec)
1617836SJohn.Forte@Sun.COM {
1627836SJohn.Forte@Sun.COM 	uint16_t		mbx;
1637836SJohn.Forte@Sun.COM 	uint32_t		stat;
1647836SJohn.Forte@Sun.COM 	ql_adapter_state_t	*ha = (void *)arg;
1657836SJohn.Forte@Sun.COM 	uint32_t		set_flags = 0;
1667836SJohn.Forte@Sun.COM 	uint32_t		reset_flags = 0;
1677836SJohn.Forte@Sun.COM 	ql_head_t		isr_done_q = {NULL, NULL};
1687836SJohn.Forte@Sun.COM 	uint_t			rval = DDI_INTR_UNCLAIMED;
1697836SJohn.Forte@Sun.COM 	int			spurious_intr = 0;
1707836SJohn.Forte@Sun.COM 	boolean_t		intr = B_FALSE, daemon = B_FALSE;
1717836SJohn.Forte@Sun.COM 	int			intr_loop = 4;
172*12279SDaniel.Beauregard@Sun.COM 	boolean_t		clear_spurious = B_TRUE;
1737836SJohn.Forte@Sun.COM 
1747836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1757836SJohn.Forte@Sun.COM 
1767836SJohn.Forte@Sun.COM 	QL_PM_LOCK(ha);
1777836SJohn.Forte@Sun.COM 	if (ha->power_level != PM_LEVEL_D0) {
1787836SJohn.Forte@Sun.COM 		/*
1797836SJohn.Forte@Sun.COM 		 * Looks like we are about to go down soon, exit early.
1807836SJohn.Forte@Sun.COM 		 */
1817836SJohn.Forte@Sun.COM 		QL_PM_UNLOCK(ha);
1827836SJohn.Forte@Sun.COM 		QL_PRINT_3(CE_CONT, "(%d): power down exit\n", ha->instance);
1837836SJohn.Forte@Sun.COM 		return (DDI_INTR_UNCLAIMED);
1847836SJohn.Forte@Sun.COM 	}
1857836SJohn.Forte@Sun.COM 	ha->busy++;
1867836SJohn.Forte@Sun.COM 	QL_PM_UNLOCK(ha);
1877836SJohn.Forte@Sun.COM 
1887836SJohn.Forte@Sun.COM 	/* Acquire interrupt lock. */
1897836SJohn.Forte@Sun.COM 	INTR_LOCK(ha);
1907836SJohn.Forte@Sun.COM 
1917836SJohn.Forte@Sun.COM 	if (CFG_IST(ha, CFG_CTRL_2200)) {
1927836SJohn.Forte@Sun.COM 		while (RD16_IO_REG(ha, istatus) & RISC_INT) {
1937836SJohn.Forte@Sun.COM 			/* Reset idle timer. */
1947836SJohn.Forte@Sun.COM 			ha->idle_timer = 0;
1957836SJohn.Forte@Sun.COM 			rval = DDI_INTR_CLAIMED;
1967836SJohn.Forte@Sun.COM 			if (intr_loop) {
1977836SJohn.Forte@Sun.COM 				intr_loop--;
1987836SJohn.Forte@Sun.COM 			}
1997836SJohn.Forte@Sun.COM 
2007836SJohn.Forte@Sun.COM 			/* Special Fast Post 2200. */
2017836SJohn.Forte@Sun.COM 			stat = 0;
2027836SJohn.Forte@Sun.COM 			if (ha->task_daemon_flags & FIRMWARE_LOADED &&
2037836SJohn.Forte@Sun.COM 			    ha->flags & ONLINE) {
2047836SJohn.Forte@Sun.COM 				ql_srb_t	*sp;
2057836SJohn.Forte@Sun.COM 
20611924SDaniel.Beauregard@Sun.COM 				mbx = RD16_IO_REG(ha, mailbox_out[23]);
2077836SJohn.Forte@Sun.COM 
2087836SJohn.Forte@Sun.COM 				if ((mbx & 3) == MBX23_SCSI_COMPLETION) {
2097836SJohn.Forte@Sun.COM 					/* Release mailbox registers. */
2107836SJohn.Forte@Sun.COM 					WRT16_IO_REG(ha, semaphore, 0);
2117836SJohn.Forte@Sun.COM 
2127836SJohn.Forte@Sun.COM 					if (intr_loop) {
2137836SJohn.Forte@Sun.COM 						WRT16_IO_REG(ha, hccr,
2147836SJohn.Forte@Sun.COM 						    HC_CLR_RISC_INT);
2157836SJohn.Forte@Sun.COM 					}
2167836SJohn.Forte@Sun.COM 
2177836SJohn.Forte@Sun.COM 					/* Get handle. */
2187836SJohn.Forte@Sun.COM 					mbx >>= 4;
2197836SJohn.Forte@Sun.COM 					stat = mbx & OSC_INDEX_MASK;
2207836SJohn.Forte@Sun.COM 
2217836SJohn.Forte@Sun.COM 					/* Validate handle. */
2227836SJohn.Forte@Sun.COM 					sp = stat < MAX_OUTSTANDING_COMMANDS ?
2237836SJohn.Forte@Sun.COM 					    ha->outstanding_cmds[stat] : NULL;
2247836SJohn.Forte@Sun.COM 
2257836SJohn.Forte@Sun.COM 					if (sp != NULL && (sp->handle & 0xfff)
2267836SJohn.Forte@Sun.COM 					    == mbx) {
2277836SJohn.Forte@Sun.COM 						ha->outstanding_cmds[stat] =
2287836SJohn.Forte@Sun.COM 						    NULL;
2297836SJohn.Forte@Sun.COM 						sp->handle = 0;
2307836SJohn.Forte@Sun.COM 						sp->flags &=
2317836SJohn.Forte@Sun.COM 						    ~SRB_IN_TOKEN_ARRAY;
2327836SJohn.Forte@Sun.COM 
2337836SJohn.Forte@Sun.COM 						/* Set completed status. */
2347836SJohn.Forte@Sun.COM 						sp->flags |= SRB_ISP_COMPLETED;
2357836SJohn.Forte@Sun.COM 
2367836SJohn.Forte@Sun.COM 						/* Set completion status */
2377836SJohn.Forte@Sun.COM 						sp->pkt->pkt_reason =
2387836SJohn.Forte@Sun.COM 						    CS_COMPLETE;
2397836SJohn.Forte@Sun.COM 
2407836SJohn.Forte@Sun.COM 						ql_fast_fcp_post(sp);
2417836SJohn.Forte@Sun.COM 					} else if (mbx !=
2427836SJohn.Forte@Sun.COM 					    (QL_FCA_BRAND & 0xfff)) {
2437836SJohn.Forte@Sun.COM 						if (sp == NULL) {
2447836SJohn.Forte@Sun.COM 							EL(ha, "unknown IOCB"
2457836SJohn.Forte@Sun.COM 							    " handle=%xh\n",
2467836SJohn.Forte@Sun.COM 							    mbx);
2477836SJohn.Forte@Sun.COM 						} else {
2487836SJohn.Forte@Sun.COM 							EL(ha, "mismatch IOCB"
2497836SJohn.Forte@Sun.COM 							    " handle pkt=%xh, "
2507836SJohn.Forte@Sun.COM 							    "sp=%xh\n", mbx,
2517836SJohn.Forte@Sun.COM 							    sp->handle & 0xfff);
2527836SJohn.Forte@Sun.COM 						}
2537836SJohn.Forte@Sun.COM 
2547836SJohn.Forte@Sun.COM 						(void) ql_binary_fw_dump(ha,
2557836SJohn.Forte@Sun.COM 						    FALSE);
2567836SJohn.Forte@Sun.COM 
2577836SJohn.Forte@Sun.COM 						if (!(ha->task_daemon_flags &
2587836SJohn.Forte@Sun.COM 						    (ISP_ABORT_NEEDED |
2597836SJohn.Forte@Sun.COM 						    ABORT_ISP_ACTIVE))) {
2607836SJohn.Forte@Sun.COM 							EL(ha, "ISP Invalid "
2617836SJohn.Forte@Sun.COM 							    "handle, "
2627836SJohn.Forte@Sun.COM 							    "isp_abort_needed"
2637836SJohn.Forte@Sun.COM 							    "\n");
2647836SJohn.Forte@Sun.COM 							set_flags |=
2657836SJohn.Forte@Sun.COM 							    ISP_ABORT_NEEDED;
2667836SJohn.Forte@Sun.COM 						}
2677836SJohn.Forte@Sun.COM 					}
2687836SJohn.Forte@Sun.COM 				}
2697836SJohn.Forte@Sun.COM 			}
2707836SJohn.Forte@Sun.COM 
2717836SJohn.Forte@Sun.COM 			if (stat == 0) {
2727836SJohn.Forte@Sun.COM 				/* Check for mailbox interrupt. */
2737836SJohn.Forte@Sun.COM 				mbx = RD16_IO_REG(ha, semaphore);
2747836SJohn.Forte@Sun.COM 				if (mbx & BIT_0) {
2757836SJohn.Forte@Sun.COM 					/* Release mailbox registers. */
2767836SJohn.Forte@Sun.COM 					WRT16_IO_REG(ha, semaphore, 0);
2777836SJohn.Forte@Sun.COM 
2787836SJohn.Forte@Sun.COM 					/* Get mailbox data. */
27911924SDaniel.Beauregard@Sun.COM 					mbx = RD16_IO_REG(ha, mailbox_out[0]);
2807836SJohn.Forte@Sun.COM 					if (mbx > 0x3fff && mbx < 0x8000) {
2817836SJohn.Forte@Sun.COM 						ql_mbx_completion(ha, mbx,
2827836SJohn.Forte@Sun.COM 						    &set_flags, &reset_flags,
2837836SJohn.Forte@Sun.COM 						    intr_loop);
2847836SJohn.Forte@Sun.COM 					} else if (mbx > 0x7fff &&
2857836SJohn.Forte@Sun.COM 					    mbx < 0xc000) {
2867836SJohn.Forte@Sun.COM 						ql_async_event(ha, mbx,
2877836SJohn.Forte@Sun.COM 						    &isr_done_q, &set_flags,
2887836SJohn.Forte@Sun.COM 						    &reset_flags, intr_loop);
2897836SJohn.Forte@Sun.COM 					} else {
2907836SJohn.Forte@Sun.COM 						EL(ha, "UNKNOWN interrupt "
2917836SJohn.Forte@Sun.COM 						    "type\n");
2927836SJohn.Forte@Sun.COM 						intr = B_TRUE;
2937836SJohn.Forte@Sun.COM 					}
2947836SJohn.Forte@Sun.COM 				} else {
2957836SJohn.Forte@Sun.COM 					ha->isp_rsp_index = RD16_IO_REG(ha,
2967836SJohn.Forte@Sun.COM 					    resp_in);
2977836SJohn.Forte@Sun.COM 
2987836SJohn.Forte@Sun.COM 					if (ha->isp_rsp_index !=
2997836SJohn.Forte@Sun.COM 					    ha->rsp_ring_index) {
3007836SJohn.Forte@Sun.COM 						ql_response_pkt(ha,
3017836SJohn.Forte@Sun.COM 						    &isr_done_q, &set_flags,
3027836SJohn.Forte@Sun.COM 						    &reset_flags, intr_loop);
3037836SJohn.Forte@Sun.COM 					} else if (++spurious_intr ==
3047836SJohn.Forte@Sun.COM 					    MAX_SPURIOUS_INTR) {
3057836SJohn.Forte@Sun.COM 						/*
3067836SJohn.Forte@Sun.COM 						 * Process excessive
3077836SJohn.Forte@Sun.COM 						 * spurious intrrupts
3087836SJohn.Forte@Sun.COM 						 */
3097836SJohn.Forte@Sun.COM 						ql_spurious_intr(ha,
3107836SJohn.Forte@Sun.COM 						    intr_loop);
3117836SJohn.Forte@Sun.COM 						EL(ha, "excessive spurious "
3127836SJohn.Forte@Sun.COM 						    "interrupts, "
3137836SJohn.Forte@Sun.COM 						    "isp_abort_needed\n");
3147836SJohn.Forte@Sun.COM 						set_flags |= ISP_ABORT_NEEDED;
3157836SJohn.Forte@Sun.COM 					} else {
3167836SJohn.Forte@Sun.COM 						intr = B_TRUE;
3177836SJohn.Forte@Sun.COM 					}
3187836SJohn.Forte@Sun.COM 				}
3197836SJohn.Forte@Sun.COM 			}
3207836SJohn.Forte@Sun.COM 
3217836SJohn.Forte@Sun.COM 			/* Clear RISC interrupt */
3227836SJohn.Forte@Sun.COM 			if (intr || intr_loop == 0) {
3237836SJohn.Forte@Sun.COM 				intr = B_FALSE;
3247836SJohn.Forte@Sun.COM 				WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
3257836SJohn.Forte@Sun.COM 			}
3267836SJohn.Forte@Sun.COM 
3277836SJohn.Forte@Sun.COM 			if (set_flags != 0 || reset_flags != 0) {
3287836SJohn.Forte@Sun.COM 				TASK_DAEMON_LOCK(ha);
3297836SJohn.Forte@Sun.COM 				ha->task_daemon_flags |= set_flags;
3307836SJohn.Forte@Sun.COM 				ha->task_daemon_flags &= ~reset_flags;
3317836SJohn.Forte@Sun.COM 				TASK_DAEMON_UNLOCK(ha);
3327836SJohn.Forte@Sun.COM 				set_flags = 0;
3337836SJohn.Forte@Sun.COM 				reset_flags = 0;
3347836SJohn.Forte@Sun.COM 				daemon = B_TRUE;
3357836SJohn.Forte@Sun.COM 			}
3367836SJohn.Forte@Sun.COM 		}
3377836SJohn.Forte@Sun.COM 	} else {
338*12279SDaniel.Beauregard@Sun.COM 		uint32_t	ql_max_intr_loop_cnt = 0;
339*12279SDaniel.Beauregard@Sun.COM 
34011924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_8021)) {
34111924SDaniel.Beauregard@Sun.COM 			ql_8021_clr_hw_intr(ha);
342*12279SDaniel.Beauregard@Sun.COM 			intr_loop = 1;
34311924SDaniel.Beauregard@Sun.COM 		}
344*12279SDaniel.Beauregard@Sun.COM 		while (((stat = RD32_IO_REG(ha, risc2host)) & RH_RISC_INT) &&
345*12279SDaniel.Beauregard@Sun.COM 		    (++ql_max_intr_loop_cnt < ql_max_intr_loop)) {
346*12279SDaniel.Beauregard@Sun.COM 
347*12279SDaniel.Beauregard@Sun.COM 			clear_spurious = B_TRUE;	/* assume ok */
348*12279SDaniel.Beauregard@Sun.COM 
3499156SDaniel.Beauregard@Sun.COM 			/* Capture FW defined interrupt info */
3507836SJohn.Forte@Sun.COM 			mbx = MSW(stat);
3517836SJohn.Forte@Sun.COM 
3527836SJohn.Forte@Sun.COM 			/* Reset idle timer. */
3537836SJohn.Forte@Sun.COM 			ha->idle_timer = 0;
3547836SJohn.Forte@Sun.COM 			rval = DDI_INTR_CLAIMED;
35511924SDaniel.Beauregard@Sun.COM 
35611924SDaniel.Beauregard@Sun.COM 			if (CFG_IST(ha, CFG_CTRL_8021) &&
357*12279SDaniel.Beauregard@Sun.COM 			    (RD32_IO_REG(ha, nx_risc_int) == 0 ||
358*12279SDaniel.Beauregard@Sun.COM 			    intr_loop == 0)) {
35911924SDaniel.Beauregard@Sun.COM 				break;
36011924SDaniel.Beauregard@Sun.COM 			}
36111924SDaniel.Beauregard@Sun.COM 
3627836SJohn.Forte@Sun.COM 			if (intr_loop) {
3637836SJohn.Forte@Sun.COM 				intr_loop--;
3647836SJohn.Forte@Sun.COM 			}
3657836SJohn.Forte@Sun.COM 
3667836SJohn.Forte@Sun.COM 			switch (stat & 0x1ff) {
3677836SJohn.Forte@Sun.COM 			case ROM_MBX_SUCCESS:
3687836SJohn.Forte@Sun.COM 			case ROM_MBX_ERR:
3697836SJohn.Forte@Sun.COM 				ql_mbx_completion(ha, mbx, &set_flags,
3707836SJohn.Forte@Sun.COM 				    &reset_flags, intr_loop);
3717836SJohn.Forte@Sun.COM 
3727836SJohn.Forte@Sun.COM 				/* Release mailbox registers. */
37311924SDaniel.Beauregard@Sun.COM 				if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
3747836SJohn.Forte@Sun.COM 					WRT16_IO_REG(ha, semaphore, 0);
3757836SJohn.Forte@Sun.COM 				}
3767836SJohn.Forte@Sun.COM 				break;
3777836SJohn.Forte@Sun.COM 
3787836SJohn.Forte@Sun.COM 			case MBX_SUCCESS:
3797836SJohn.Forte@Sun.COM 			case MBX_ERR:
3807836SJohn.Forte@Sun.COM 				/* Sun FW, Release mailbox registers. */
38111924SDaniel.Beauregard@Sun.COM 				if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
3827836SJohn.Forte@Sun.COM 					WRT16_IO_REG(ha, semaphore, 0);
3837836SJohn.Forte@Sun.COM 				}
3847836SJohn.Forte@Sun.COM 				ql_mbx_completion(ha, mbx, &set_flags,
3857836SJohn.Forte@Sun.COM 				    &reset_flags, intr_loop);
3867836SJohn.Forte@Sun.COM 				break;
3877836SJohn.Forte@Sun.COM 
3887836SJohn.Forte@Sun.COM 			case ASYNC_EVENT:
3897836SJohn.Forte@Sun.COM 				/* Sun FW, Release mailbox registers. */
39011924SDaniel.Beauregard@Sun.COM 				if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
3917836SJohn.Forte@Sun.COM 					WRT16_IO_REG(ha, semaphore, 0);
3927836SJohn.Forte@Sun.COM 				}
3937836SJohn.Forte@Sun.COM 				ql_async_event(ha, (uint32_t)mbx, &isr_done_q,
3947836SJohn.Forte@Sun.COM 				    &set_flags, &reset_flags, intr_loop);
3957836SJohn.Forte@Sun.COM 				break;
3967836SJohn.Forte@Sun.COM 
3977836SJohn.Forte@Sun.COM 			case RESP_UPDATE:
3987836SJohn.Forte@Sun.COM 				if (mbx != ha->rsp_ring_index) {
3997836SJohn.Forte@Sun.COM 					ha->isp_rsp_index = mbx;
4007836SJohn.Forte@Sun.COM 					ql_response_pkt(ha, &isr_done_q,
4017836SJohn.Forte@Sun.COM 					    &set_flags, &reset_flags,
4027836SJohn.Forte@Sun.COM 					    intr_loop);
4037836SJohn.Forte@Sun.COM 				} else if (++spurious_intr ==
404*12279SDaniel.Beauregard@Sun.COM 				    ql_spurious_cnt) {
4057836SJohn.Forte@Sun.COM 					/* Process excessive spurious intr. */
4067836SJohn.Forte@Sun.COM 					ql_spurious_intr(ha, intr_loop);
4077836SJohn.Forte@Sun.COM 					EL(ha, "excessive spurious "
4087836SJohn.Forte@Sun.COM 					    "interrupts, isp_abort_needed\n");
4097836SJohn.Forte@Sun.COM 					set_flags |= ISP_ABORT_NEEDED;
410*12279SDaniel.Beauregard@Sun.COM 					clear_spurious = B_FALSE;
4117836SJohn.Forte@Sun.COM 				} else {
412*12279SDaniel.Beauregard@Sun.COM 					QL_PRINT_10(CE_CONT, "(%d): response "
413*12279SDaniel.Beauregard@Sun.COM 					    "ring index same as before\n",
414*12279SDaniel.Beauregard@Sun.COM 					    ha->instance);
4157836SJohn.Forte@Sun.COM 					intr = B_TRUE;
416*12279SDaniel.Beauregard@Sun.COM 					clear_spurious = B_FALSE;
4177836SJohn.Forte@Sun.COM 				}
4187836SJohn.Forte@Sun.COM 				break;
4197836SJohn.Forte@Sun.COM 
4207836SJohn.Forte@Sun.COM 			case SCSI_FAST_POST_16:
4217836SJohn.Forte@Sun.COM 				stat = (stat & 0xffff0000) | MBA_CMPLT_1_16BIT;
4227836SJohn.Forte@Sun.COM 				ql_async_event(ha, stat, &isr_done_q,
4237836SJohn.Forte@Sun.COM 				    &set_flags, &reset_flags, intr_loop);
4247836SJohn.Forte@Sun.COM 				break;
4257836SJohn.Forte@Sun.COM 
4267836SJohn.Forte@Sun.COM 			case SCSI_FAST_POST_32:
4277836SJohn.Forte@Sun.COM 				stat = (stat & 0xffff0000) | MBA_CMPLT_1_32BIT;
4287836SJohn.Forte@Sun.COM 				ql_async_event(ha, stat, &isr_done_q,
4297836SJohn.Forte@Sun.COM 				    &set_flags, &reset_flags, intr_loop);
4307836SJohn.Forte@Sun.COM 				break;
4317836SJohn.Forte@Sun.COM 
4327836SJohn.Forte@Sun.COM 			case CTIO_FAST_POST:
4337836SJohn.Forte@Sun.COM 				stat = (stat & 0xffff0000) |
4347836SJohn.Forte@Sun.COM 				    MBA_CTIO_COMPLETION;
4357836SJohn.Forte@Sun.COM 				ql_async_event(ha, stat, &isr_done_q,
4367836SJohn.Forte@Sun.COM 				    &set_flags, &reset_flags, intr_loop);
4377836SJohn.Forte@Sun.COM 				break;
4387836SJohn.Forte@Sun.COM 
4397836SJohn.Forte@Sun.COM 			case IP_FAST_POST_XMT:
4407836SJohn.Forte@Sun.COM 				stat = (stat & 0xffff0000) | MBA_IP_COMPLETION;
4417836SJohn.Forte@Sun.COM 				ql_async_event(ha, stat, &isr_done_q,
4427836SJohn.Forte@Sun.COM 				    &set_flags, &reset_flags, intr_loop);
4437836SJohn.Forte@Sun.COM 				break;
4447836SJohn.Forte@Sun.COM 
4457836SJohn.Forte@Sun.COM 			case IP_FAST_POST_RCV:
4467836SJohn.Forte@Sun.COM 				stat = (stat & 0xffff0000) | MBA_IP_RECEIVE;
4477836SJohn.Forte@Sun.COM 				ql_async_event(ha, stat, &isr_done_q,
4487836SJohn.Forte@Sun.COM 				    &set_flags, &reset_flags, intr_loop);
4497836SJohn.Forte@Sun.COM 				break;
4507836SJohn.Forte@Sun.COM 
4517836SJohn.Forte@Sun.COM 			case IP_FAST_POST_BRD:
4527836SJohn.Forte@Sun.COM 				stat = (stat & 0xffff0000) | MBA_IP_BROADCAST;
4537836SJohn.Forte@Sun.COM 				ql_async_event(ha, stat, &isr_done_q,
4547836SJohn.Forte@Sun.COM 				    &set_flags, &reset_flags, intr_loop);
4557836SJohn.Forte@Sun.COM 				break;
4567836SJohn.Forte@Sun.COM 
4577836SJohn.Forte@Sun.COM 			case IP_FAST_POST_RCV_ALN:
4587836SJohn.Forte@Sun.COM 				stat = (stat & 0xffff0000) |
4597836SJohn.Forte@Sun.COM 				    MBA_IP_HDR_DATA_SPLIT;
4607836SJohn.Forte@Sun.COM 				ql_async_event(ha, stat, &isr_done_q,
4617836SJohn.Forte@Sun.COM 				    &set_flags, &reset_flags, intr_loop);
4627836SJohn.Forte@Sun.COM 				break;
4637836SJohn.Forte@Sun.COM 
4647836SJohn.Forte@Sun.COM 			case ATIO_UPDATE:
4657836SJohn.Forte@Sun.COM 				EL(ha, "unsupported ATIO queue update"
4667836SJohn.Forte@Sun.COM 				    " interrupt, status=%xh\n", stat);
4677836SJohn.Forte@Sun.COM 				intr = B_TRUE;
4687836SJohn.Forte@Sun.COM 				break;
4697836SJohn.Forte@Sun.COM 
4707836SJohn.Forte@Sun.COM 			case ATIO_RESP_UPDATE:
4717836SJohn.Forte@Sun.COM 				EL(ha, "unsupported ATIO response queue "
4727836SJohn.Forte@Sun.COM 				    "update interrupt, status=%xh\n", stat);
4737836SJohn.Forte@Sun.COM 				intr = B_TRUE;
4747836SJohn.Forte@Sun.COM 				break;
4757836SJohn.Forte@Sun.COM 
4767836SJohn.Forte@Sun.COM 			default:
4779156SDaniel.Beauregard@Sun.COM 				ql_handle_uncommon_risc_intr(ha, stat,
4789156SDaniel.Beauregard@Sun.COM 				    &set_flags);
4797836SJohn.Forte@Sun.COM 				intr = B_TRUE;
4807836SJohn.Forte@Sun.COM 				break;
4817836SJohn.Forte@Sun.COM 			}
4827836SJohn.Forte@Sun.COM 
4837836SJohn.Forte@Sun.COM 			/* Clear RISC interrupt */
4847836SJohn.Forte@Sun.COM 			if (intr || intr_loop == 0) {
4857836SJohn.Forte@Sun.COM 				intr = B_FALSE;
48611924SDaniel.Beauregard@Sun.COM 				if (CFG_IST(ha, CFG_CTRL_8021)) {
48711924SDaniel.Beauregard@Sun.COM 					ql_8021_clr_fw_intr(ha);
48811924SDaniel.Beauregard@Sun.COM 				} else if (CFG_IST(ha, CFG_CTRL_242581)) {
48911924SDaniel.Beauregard@Sun.COM 					WRT32_IO_REG(ha, hccr,
49011924SDaniel.Beauregard@Sun.COM 					    HC24_CLR_RISC_INT);
49111924SDaniel.Beauregard@Sun.COM 				} else {
49211924SDaniel.Beauregard@Sun.COM 					WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
49311924SDaniel.Beauregard@Sun.COM 				}
4947836SJohn.Forte@Sun.COM 			}
4957836SJohn.Forte@Sun.COM 
4967836SJohn.Forte@Sun.COM 			if (set_flags != 0 || reset_flags != 0) {
4977836SJohn.Forte@Sun.COM 				TASK_DAEMON_LOCK(ha);
4987836SJohn.Forte@Sun.COM 				ha->task_daemon_flags |= set_flags;
4997836SJohn.Forte@Sun.COM 				ha->task_daemon_flags &= ~reset_flags;
5007836SJohn.Forte@Sun.COM 				TASK_DAEMON_UNLOCK(ha);
5017836SJohn.Forte@Sun.COM 				set_flags = 0;
5027836SJohn.Forte@Sun.COM 				reset_flags = 0;
5037836SJohn.Forte@Sun.COM 				daemon = B_TRUE;
5047836SJohn.Forte@Sun.COM 			}
5057836SJohn.Forte@Sun.COM 
5067836SJohn.Forte@Sun.COM 			if (ha->flags & PARITY_ERROR) {
5077836SJohn.Forte@Sun.COM 				EL(ha, "parity/pause exit\n");
5087836SJohn.Forte@Sun.COM 				mbx = RD16_IO_REG(ha, hccr); /* PCI posting */
5097836SJohn.Forte@Sun.COM 				break;
5107836SJohn.Forte@Sun.COM 			}
511*12279SDaniel.Beauregard@Sun.COM 
512*12279SDaniel.Beauregard@Sun.COM 			if (clear_spurious) {
513*12279SDaniel.Beauregard@Sun.COM 				spurious_intr = 0;
514*12279SDaniel.Beauregard@Sun.COM 			}
5157836SJohn.Forte@Sun.COM 		}
5167836SJohn.Forte@Sun.COM 	}
5177836SJohn.Forte@Sun.COM 
5187836SJohn.Forte@Sun.COM 	/* Process claimed interrupts during polls. */
5197836SJohn.Forte@Sun.COM 	if (rval == DDI_INTR_UNCLAIMED && ha->intr_claimed == B_TRUE) {
5207836SJohn.Forte@Sun.COM 		ha->intr_claimed = B_FALSE;
5217836SJohn.Forte@Sun.COM 		rval = DDI_INTR_CLAIMED;
5227836SJohn.Forte@Sun.COM 	}
5237836SJohn.Forte@Sun.COM 
5247836SJohn.Forte@Sun.COM 	/* Release interrupt lock. */
5257836SJohn.Forte@Sun.COM 	INTR_UNLOCK(ha);
5267836SJohn.Forte@Sun.COM 
5277836SJohn.Forte@Sun.COM 	if (daemon) {
5287836SJohn.Forte@Sun.COM 		ql_awaken_task_daemon(ha, NULL, 0, 0);
5297836SJohn.Forte@Sun.COM 	}
5307836SJohn.Forte@Sun.COM 
5317836SJohn.Forte@Sun.COM 	if (isr_done_q.first != NULL) {
5327836SJohn.Forte@Sun.COM 		ql_done(isr_done_q.first);
5337836SJohn.Forte@Sun.COM 	}
5347836SJohn.Forte@Sun.COM 
5357836SJohn.Forte@Sun.COM 	if (rval == DDI_INTR_CLAIMED) {
5367836SJohn.Forte@Sun.COM 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5377836SJohn.Forte@Sun.COM 		ha->xioctl->TotalInterrupts++;
5387836SJohn.Forte@Sun.COM 	} else {
5397836SJohn.Forte@Sun.COM 		/*EMPTY*/
5407836SJohn.Forte@Sun.COM 		QL_PRINT_3(CE_CONT, "(%d): interrupt not claimed\n",
5417836SJohn.Forte@Sun.COM 		    ha->instance);
5427836SJohn.Forte@Sun.COM 	}
5437836SJohn.Forte@Sun.COM 
5447836SJohn.Forte@Sun.COM 	QL_PM_LOCK(ha);
5457836SJohn.Forte@Sun.COM 	ha->busy--;
5467836SJohn.Forte@Sun.COM 	QL_PM_UNLOCK(ha);
5477836SJohn.Forte@Sun.COM 
5487836SJohn.Forte@Sun.COM 	return (rval);
5497836SJohn.Forte@Sun.COM }
5507836SJohn.Forte@Sun.COM 
5517836SJohn.Forte@Sun.COM /*
5529156SDaniel.Beauregard@Sun.COM  * ql_handle_uncommon_risc_intr
5539156SDaniel.Beauregard@Sun.COM  *	Handle an uncommon RISC interrupt.
5549156SDaniel.Beauregard@Sun.COM  *
5559156SDaniel.Beauregard@Sun.COM  * Input:
5569156SDaniel.Beauregard@Sun.COM  *	ha:		adapter state pointer.
5579156SDaniel.Beauregard@Sun.COM  *	stat:		interrupt status
5589156SDaniel.Beauregard@Sun.COM  *
5599156SDaniel.Beauregard@Sun.COM  * Context:
5609156SDaniel.Beauregard@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
5619156SDaniel.Beauregard@Sun.COM  */
5629156SDaniel.Beauregard@Sun.COM static void
ql_handle_uncommon_risc_intr(ql_adapter_state_t * ha,uint32_t stat,uint32_t * set_flags)5639156SDaniel.Beauregard@Sun.COM ql_handle_uncommon_risc_intr(ql_adapter_state_t *ha, uint32_t stat,
5649156SDaniel.Beauregard@Sun.COM     uint32_t *set_flags)
5659156SDaniel.Beauregard@Sun.COM {
5669156SDaniel.Beauregard@Sun.COM 	uint16_t	hccr_reg;
5679156SDaniel.Beauregard@Sun.COM 
5689156SDaniel.Beauregard@Sun.COM 	hccr_reg = RD16_IO_REG(ha, hccr);
5699156SDaniel.Beauregard@Sun.COM 
5709156SDaniel.Beauregard@Sun.COM 	if (stat & RH_RISC_PAUSED ||
5719156SDaniel.Beauregard@Sun.COM 	    (hccr_reg & (BIT_15 | BIT_13 | BIT_11 | BIT_8))) {
5729156SDaniel.Beauregard@Sun.COM 
5739156SDaniel.Beauregard@Sun.COM 		ADAPTER_STATE_LOCK(ha);
5749156SDaniel.Beauregard@Sun.COM 		ha->flags |= PARITY_ERROR;
5759156SDaniel.Beauregard@Sun.COM 		ADAPTER_STATE_UNLOCK(ha);
5769156SDaniel.Beauregard@Sun.COM 
5779156SDaniel.Beauregard@Sun.COM 		if (ha->parity_pause_errors == 0 ||
5789156SDaniel.Beauregard@Sun.COM 		    ha->parity_hccr_err != hccr_reg ||
5799156SDaniel.Beauregard@Sun.COM 		    ha->parity_stat_err != stat) {
5809156SDaniel.Beauregard@Sun.COM 			cmn_err(CE_WARN, "qlc(%d): isr, Internal Parity/"
5819156SDaniel.Beauregard@Sun.COM 			    "Pause Error - hccr=%xh, stat=%xh, count=%d",
5829156SDaniel.Beauregard@Sun.COM 			    ha->instance, hccr_reg, stat,
5839156SDaniel.Beauregard@Sun.COM 			    ha->parity_pause_errors);
5849156SDaniel.Beauregard@Sun.COM 			ha->parity_hccr_err = hccr_reg;
5859156SDaniel.Beauregard@Sun.COM 			ha->parity_stat_err = stat;
5869156SDaniel.Beauregard@Sun.COM 		}
5879156SDaniel.Beauregard@Sun.COM 
5889156SDaniel.Beauregard@Sun.COM 		EL(ha, "parity/pause error, isp_abort_needed\n");
5899156SDaniel.Beauregard@Sun.COM 
5909156SDaniel.Beauregard@Sun.COM 		if (ql_binary_fw_dump(ha, FALSE) != QL_SUCCESS) {
5919156SDaniel.Beauregard@Sun.COM 			ql_reset_chip(ha);
5929156SDaniel.Beauregard@Sun.COM 		}
5939156SDaniel.Beauregard@Sun.COM 
5949156SDaniel.Beauregard@Sun.COM 		if (ha->parity_pause_errors == 0) {
59511924SDaniel.Beauregard@Sun.COM 			ha->log_parity_pause = B_TRUE;
5969156SDaniel.Beauregard@Sun.COM 		}
5979156SDaniel.Beauregard@Sun.COM 
5989156SDaniel.Beauregard@Sun.COM 		if (ha->parity_pause_errors < 0xffffffff) {
5999156SDaniel.Beauregard@Sun.COM 			ha->parity_pause_errors++;
6009156SDaniel.Beauregard@Sun.COM 		}
6019156SDaniel.Beauregard@Sun.COM 
6029156SDaniel.Beauregard@Sun.COM 		*set_flags |= ISP_ABORT_NEEDED;
6039156SDaniel.Beauregard@Sun.COM 
6049156SDaniel.Beauregard@Sun.COM 		/* Disable ISP interrupts. */
60511924SDaniel.Beauregard@Sun.COM 		CFG_IST(ha, CFG_CTRL_8021) ? ql_8021_disable_intrs(ha) :
60611924SDaniel.Beauregard@Sun.COM 		    WRT16_IO_REG(ha, ictrl, 0);
6079156SDaniel.Beauregard@Sun.COM 		ADAPTER_STATE_LOCK(ha);
6089156SDaniel.Beauregard@Sun.COM 		ha->flags &= ~INTERRUPTS_ENABLED;
6099156SDaniel.Beauregard@Sun.COM 		ADAPTER_STATE_UNLOCK(ha);
6109156SDaniel.Beauregard@Sun.COM 	} else {
6119156SDaniel.Beauregard@Sun.COM 		EL(ha, "UNKNOWN interrupt status=%xh, hccr=%xh\n",
6129156SDaniel.Beauregard@Sun.COM 		    stat, hccr_reg);
6139156SDaniel.Beauregard@Sun.COM 	}
6149156SDaniel.Beauregard@Sun.COM }
6159156SDaniel.Beauregard@Sun.COM 
6169156SDaniel.Beauregard@Sun.COM /*
6177836SJohn.Forte@Sun.COM  * ql_spurious_intr
6187836SJohn.Forte@Sun.COM  *	Inform Solaris of spurious interrupts.
6197836SJohn.Forte@Sun.COM  *
6207836SJohn.Forte@Sun.COM  * Input:
6217836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
6227836SJohn.Forte@Sun.COM  *	intr_clr:	early interrupt clear
6237836SJohn.Forte@Sun.COM  *
6247836SJohn.Forte@Sun.COM  * Context:
6257836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
6267836SJohn.Forte@Sun.COM  */
6277836SJohn.Forte@Sun.COM static void
ql_spurious_intr(ql_adapter_state_t * ha,int intr_clr)6287836SJohn.Forte@Sun.COM ql_spurious_intr(ql_adapter_state_t *ha, int intr_clr)
6297836SJohn.Forte@Sun.COM {
6307836SJohn.Forte@Sun.COM 	ddi_devstate_t	state;
6317836SJohn.Forte@Sun.COM 
6327836SJohn.Forte@Sun.COM 	EL(ha, "Spurious interrupt\n");
6337836SJohn.Forte@Sun.COM 
6347836SJohn.Forte@Sun.COM 	/* Disable ISP interrupts. */
6357836SJohn.Forte@Sun.COM 	WRT16_IO_REG(ha, ictrl, 0);
6367836SJohn.Forte@Sun.COM 	ADAPTER_STATE_LOCK(ha);
6377836SJohn.Forte@Sun.COM 	ha->flags &= ~INTERRUPTS_ENABLED;
6387836SJohn.Forte@Sun.COM 	ADAPTER_STATE_UNLOCK(ha);
6397836SJohn.Forte@Sun.COM 
6407836SJohn.Forte@Sun.COM 	/* Clear RISC interrupt */
6417836SJohn.Forte@Sun.COM 	if (intr_clr) {
64211924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_8021)) {
64311924SDaniel.Beauregard@Sun.COM 			ql_8021_clr_fw_intr(ha);
64411924SDaniel.Beauregard@Sun.COM 		} else if (CFG_IST(ha, CFG_CTRL_242581)) {
64511924SDaniel.Beauregard@Sun.COM 			WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
64611924SDaniel.Beauregard@Sun.COM 		} else {
64711924SDaniel.Beauregard@Sun.COM 			WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
64811924SDaniel.Beauregard@Sun.COM 		}
6497836SJohn.Forte@Sun.COM 	}
6507836SJohn.Forte@Sun.COM 
6517836SJohn.Forte@Sun.COM 	state = ddi_get_devstate(ha->dip);
6527836SJohn.Forte@Sun.COM 	if (state == DDI_DEVSTATE_UP) {
6537836SJohn.Forte@Sun.COM 		/*EMPTY*/
6547836SJohn.Forte@Sun.COM 		ddi_dev_report_fault(ha->dip, DDI_SERVICE_DEGRADED,
6557836SJohn.Forte@Sun.COM 		    DDI_DEVICE_FAULT, "spurious interrupts");
6567836SJohn.Forte@Sun.COM 	}
6577836SJohn.Forte@Sun.COM }
6587836SJohn.Forte@Sun.COM 
6597836SJohn.Forte@Sun.COM /*
6607836SJohn.Forte@Sun.COM  * ql_mbx_completion
6617836SJohn.Forte@Sun.COM  *	Processes mailbox completions.
6627836SJohn.Forte@Sun.COM  *
6637836SJohn.Forte@Sun.COM  * Input:
6647836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
6657836SJohn.Forte@Sun.COM  *	mb0:		Mailbox 0 contents.
6667836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
6677836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
6687836SJohn.Forte@Sun.COM  *	intr_clr:	early interrupt clear
6697836SJohn.Forte@Sun.COM  *
6707836SJohn.Forte@Sun.COM  * Context:
6717836SJohn.Forte@Sun.COM  *	Interrupt context.
6727836SJohn.Forte@Sun.COM  */
6737836SJohn.Forte@Sun.COM /* ARGSUSED */
6747836SJohn.Forte@Sun.COM static void
ql_mbx_completion(ql_adapter_state_t * ha,uint16_t mb0,uint32_t * set_flags,uint32_t * reset_flags,int intr_clr)6757836SJohn.Forte@Sun.COM ql_mbx_completion(ql_adapter_state_t *ha, uint16_t mb0, uint32_t *set_flags,
6767836SJohn.Forte@Sun.COM     uint32_t *reset_flags, int intr_clr)
6777836SJohn.Forte@Sun.COM {
6787836SJohn.Forte@Sun.COM 	uint32_t	index;
6797836SJohn.Forte@Sun.COM 	uint16_t	cnt;
6807836SJohn.Forte@Sun.COM 
6817836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
6827836SJohn.Forte@Sun.COM 
6837836SJohn.Forte@Sun.COM 	/* Load return mailbox registers. */
6847836SJohn.Forte@Sun.COM 	MBX_REGISTER_LOCK(ha);
6857836SJohn.Forte@Sun.COM 
6867836SJohn.Forte@Sun.COM 	if (ha->mcp != NULL) {
6877836SJohn.Forte@Sun.COM 		ha->mcp->mb[0] = mb0;
6887836SJohn.Forte@Sun.COM 		index = ha->mcp->in_mb & ~MBX_0;
6897836SJohn.Forte@Sun.COM 
6907836SJohn.Forte@Sun.COM 		for (cnt = 1; cnt < MAX_MBOX_COUNT && index != 0; cnt++) {
6917836SJohn.Forte@Sun.COM 			index >>= 1;
6927836SJohn.Forte@Sun.COM 			if (index & MBX_0) {
6937836SJohn.Forte@Sun.COM 				ha->mcp->mb[cnt] = RD16_IO_REG(ha,
69411924SDaniel.Beauregard@Sun.COM 				    mailbox_out[cnt]);
6957836SJohn.Forte@Sun.COM 			}
6967836SJohn.Forte@Sun.COM 		}
6977836SJohn.Forte@Sun.COM 
6987836SJohn.Forte@Sun.COM 	} else {
6997836SJohn.Forte@Sun.COM 		EL(ha, "mcp == NULL\n");
7007836SJohn.Forte@Sun.COM 	}
7017836SJohn.Forte@Sun.COM 
7027836SJohn.Forte@Sun.COM 	if (intr_clr) {
7037836SJohn.Forte@Sun.COM 		/* Clear RISC interrupt. */
70411924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_8021)) {
70511924SDaniel.Beauregard@Sun.COM 			ql_8021_clr_fw_intr(ha);
70611924SDaniel.Beauregard@Sun.COM 		} else if (CFG_IST(ha, CFG_CTRL_242581)) {
70711924SDaniel.Beauregard@Sun.COM 			WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
70811924SDaniel.Beauregard@Sun.COM 		} else {
70911924SDaniel.Beauregard@Sun.COM 			WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
71011924SDaniel.Beauregard@Sun.COM 		}
7117836SJohn.Forte@Sun.COM 	}
7127836SJohn.Forte@Sun.COM 
7137836SJohn.Forte@Sun.COM 	ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_INTERRUPT);
7147836SJohn.Forte@Sun.COM 	if (ha->flags & INTERRUPTS_ENABLED) {
7157836SJohn.Forte@Sun.COM 		cv_broadcast(&ha->cv_mbx_intr);
7167836SJohn.Forte@Sun.COM 	}
7177836SJohn.Forte@Sun.COM 
7187836SJohn.Forte@Sun.COM 	MBX_REGISTER_UNLOCK(ha);
7197836SJohn.Forte@Sun.COM 
7207836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
7217836SJohn.Forte@Sun.COM }
7227836SJohn.Forte@Sun.COM 
7237836SJohn.Forte@Sun.COM /*
7247836SJohn.Forte@Sun.COM  * ql_async_event
7257836SJohn.Forte@Sun.COM  *	Processes asynchronous events.
7267836SJohn.Forte@Sun.COM  *
7277836SJohn.Forte@Sun.COM  * Input:
7287836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
7297836SJohn.Forte@Sun.COM  *	mbx:		Mailbox 0 register.
7307836SJohn.Forte@Sun.COM  *	done_q:		head pointer to done queue.
7317836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
7327836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
7337836SJohn.Forte@Sun.COM  *	intr_clr:	early interrupt clear
7347836SJohn.Forte@Sun.COM  *
7357836SJohn.Forte@Sun.COM  * Context:
7367836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
7377836SJohn.Forte@Sun.COM  */
7387836SJohn.Forte@Sun.COM static void
ql_async_event(ql_adapter_state_t * ha,uint32_t mbx,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags,int intr_clr)7397836SJohn.Forte@Sun.COM ql_async_event(ql_adapter_state_t *ha, uint32_t mbx, ql_head_t *done_q,
7407836SJohn.Forte@Sun.COM     uint32_t *set_flags, uint32_t *reset_flags, int intr_clr)
7417836SJohn.Forte@Sun.COM {
7427836SJohn.Forte@Sun.COM 	uint32_t		handle;
7437836SJohn.Forte@Sun.COM 	uint32_t		index;
7447836SJohn.Forte@Sun.COM 	uint16_t		cnt;
7457836SJohn.Forte@Sun.COM 	uint16_t		mb[MAX_MBOX_COUNT];
7467836SJohn.Forte@Sun.COM 	ql_srb_t		*sp;
7477836SJohn.Forte@Sun.COM 	port_id_t		s_id;
7487836SJohn.Forte@Sun.COM 	ql_tgt_t		*tq;
7497836SJohn.Forte@Sun.COM 	boolean_t		intr = B_TRUE;
7507836SJohn.Forte@Sun.COM 	ql_adapter_state_t	*vha;
7517836SJohn.Forte@Sun.COM 
7527836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
7537836SJohn.Forte@Sun.COM 
7547836SJohn.Forte@Sun.COM 	/* Setup to process fast completion. */
7557836SJohn.Forte@Sun.COM 	mb[0] = LSW(mbx);
7567836SJohn.Forte@Sun.COM 	switch (mb[0]) {
7577836SJohn.Forte@Sun.COM 	case MBA_SCSI_COMPLETION:
75811924SDaniel.Beauregard@Sun.COM 		handle = SHORT_TO_LONG(RD16_IO_REG(ha, mailbox_out[1]),
75911924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[2]));
7607836SJohn.Forte@Sun.COM 		break;
7617836SJohn.Forte@Sun.COM 
7627836SJohn.Forte@Sun.COM 	case MBA_CMPLT_1_16BIT:
7637836SJohn.Forte@Sun.COM 		handle = MSW(mbx);
7647836SJohn.Forte@Sun.COM 		mb[0] = MBA_SCSI_COMPLETION;
7657836SJohn.Forte@Sun.COM 		break;
7667836SJohn.Forte@Sun.COM 
7677836SJohn.Forte@Sun.COM 	case MBA_CMPLT_1_32BIT:
76811924SDaniel.Beauregard@Sun.COM 		handle = SHORT_TO_LONG(MSW(mbx),
76911924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[2]));
7707836SJohn.Forte@Sun.COM 		mb[0] = MBA_SCSI_COMPLETION;
7717836SJohn.Forte@Sun.COM 		break;
7727836SJohn.Forte@Sun.COM 
7737836SJohn.Forte@Sun.COM 	case MBA_CTIO_COMPLETION:
7747836SJohn.Forte@Sun.COM 	case MBA_IP_COMPLETION:
7757836SJohn.Forte@Sun.COM 		handle = CFG_IST(ha, CFG_CTRL_2200) ? SHORT_TO_LONG(
77611924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[1]),
77711924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[2])) :
77811924SDaniel.Beauregard@Sun.COM 		    SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox_out[2]));
7797836SJohn.Forte@Sun.COM 		mb[0] = MBA_SCSI_COMPLETION;
7807836SJohn.Forte@Sun.COM 		break;
7817836SJohn.Forte@Sun.COM 
7827836SJohn.Forte@Sun.COM 	default:
7837836SJohn.Forte@Sun.COM 		break;
7847836SJohn.Forte@Sun.COM 	}
7857836SJohn.Forte@Sun.COM 
7867836SJohn.Forte@Sun.COM 	/* Handle asynchronous event */
7877836SJohn.Forte@Sun.COM 	switch (mb[0]) {
7887836SJohn.Forte@Sun.COM 	case MBA_SCSI_COMPLETION:
7897836SJohn.Forte@Sun.COM 		QL_PRINT_5(CE_CONT, "(%d): Fast post completion\n",
7907836SJohn.Forte@Sun.COM 		    ha->instance);
7917836SJohn.Forte@Sun.COM 
7927836SJohn.Forte@Sun.COM 		if (intr_clr) {
7937836SJohn.Forte@Sun.COM 			/* Clear RISC interrupt */
79411924SDaniel.Beauregard@Sun.COM 			if (CFG_IST(ha, CFG_CTRL_8021)) {
79511924SDaniel.Beauregard@Sun.COM 				ql_8021_clr_fw_intr(ha);
79611924SDaniel.Beauregard@Sun.COM 			} else if (CFG_IST(ha, CFG_CTRL_242581)) {
79711924SDaniel.Beauregard@Sun.COM 				WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
79811924SDaniel.Beauregard@Sun.COM 			} else {
79911924SDaniel.Beauregard@Sun.COM 				WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
80011924SDaniel.Beauregard@Sun.COM 			}
8017836SJohn.Forte@Sun.COM 			intr = B_FALSE;
8027836SJohn.Forte@Sun.COM 		}
8037836SJohn.Forte@Sun.COM 
8047836SJohn.Forte@Sun.COM 		if ((ha->flags & ONLINE) == 0) {
8057836SJohn.Forte@Sun.COM 			break;
8067836SJohn.Forte@Sun.COM 		}
8077836SJohn.Forte@Sun.COM 
8087836SJohn.Forte@Sun.COM 		/* Get handle. */
8097836SJohn.Forte@Sun.COM 		index = handle & OSC_INDEX_MASK;
8107836SJohn.Forte@Sun.COM 
8117836SJohn.Forte@Sun.COM 		/* Validate handle. */
8127836SJohn.Forte@Sun.COM 		sp = index < MAX_OUTSTANDING_COMMANDS ?
8137836SJohn.Forte@Sun.COM 		    ha->outstanding_cmds[index] : NULL;
8147836SJohn.Forte@Sun.COM 
8157836SJohn.Forte@Sun.COM 		if (sp != NULL && sp->handle == handle) {
8167836SJohn.Forte@Sun.COM 			ha->outstanding_cmds[index] = NULL;
8177836SJohn.Forte@Sun.COM 			sp->handle = 0;
8187836SJohn.Forte@Sun.COM 			sp->flags &= ~SRB_IN_TOKEN_ARRAY;
8197836SJohn.Forte@Sun.COM 
8207836SJohn.Forte@Sun.COM 			/* Set completed status. */
8217836SJohn.Forte@Sun.COM 			sp->flags |= SRB_ISP_COMPLETED;
8227836SJohn.Forte@Sun.COM 
8237836SJohn.Forte@Sun.COM 			/* Set completion status */
8247836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = CS_COMPLETE;
8257836SJohn.Forte@Sun.COM 
8267836SJohn.Forte@Sun.COM 			if (!(sp->flags & SRB_FCP_CMD_PKT)) {
8277836SJohn.Forte@Sun.COM 				/* Place block on done queue */
8287836SJohn.Forte@Sun.COM 				ql_add_link_b(done_q, &sp->cmd);
8297836SJohn.Forte@Sun.COM 			} else {
8307836SJohn.Forte@Sun.COM 				ql_fast_fcp_post(sp);
8317836SJohn.Forte@Sun.COM 			}
8327836SJohn.Forte@Sun.COM 		} else if (handle != QL_FCA_BRAND) {
8337836SJohn.Forte@Sun.COM 			if (sp == NULL) {
8347836SJohn.Forte@Sun.COM 				EL(ha, "%xh unknown IOCB handle=%xh\n",
8357836SJohn.Forte@Sun.COM 				    mb[0], handle);
8367836SJohn.Forte@Sun.COM 			} else {
8377836SJohn.Forte@Sun.COM 				EL(ha, "%xh mismatch IOCB handle pkt=%xh, "
8387836SJohn.Forte@Sun.COM 				    "sp=%xh\n", mb[0], handle, sp->handle);
8397836SJohn.Forte@Sun.COM 			}
8407836SJohn.Forte@Sun.COM 
8417836SJohn.Forte@Sun.COM 			EL(ha, "%xh Fast post, mbx1=%xh, mbx2=%xh, mbx3=%xh,"
8427836SJohn.Forte@Sun.COM 			    "mbx6=%xh, mbx7=%xh\n", mb[0],
84311924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[1]),
84411924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[2]),
84511924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[3]),
84611924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[6]),
84711924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[7]));
8487836SJohn.Forte@Sun.COM 
8497836SJohn.Forte@Sun.COM 			(void) ql_binary_fw_dump(ha, FALSE);
8507836SJohn.Forte@Sun.COM 
8517836SJohn.Forte@Sun.COM 			if (!(ha->task_daemon_flags &
8527836SJohn.Forte@Sun.COM 			    (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) {
8537836SJohn.Forte@Sun.COM 				EL(ha, "%xh ISP Invalid handle, "
8547836SJohn.Forte@Sun.COM 				    "isp_abort_needed\n", mb[0]);
8557836SJohn.Forte@Sun.COM 				*set_flags |= ISP_ABORT_NEEDED;
8567836SJohn.Forte@Sun.COM 			}
8577836SJohn.Forte@Sun.COM 		}
8587836SJohn.Forte@Sun.COM 		break;
8597836SJohn.Forte@Sun.COM 
8607836SJohn.Forte@Sun.COM 	case MBA_RESET:		/* Reset */
8617836SJohn.Forte@Sun.COM 		EL(ha, "%xh Reset received\n", mb[0]);
8627836SJohn.Forte@Sun.COM 		*set_flags |= RESET_MARKER_NEEDED;
8637836SJohn.Forte@Sun.COM 		break;
8647836SJohn.Forte@Sun.COM 
8657836SJohn.Forte@Sun.COM 	case MBA_SYSTEM_ERR:		/* System Error */
86611924SDaniel.Beauregard@Sun.COM 		mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
86711924SDaniel.Beauregard@Sun.COM 		mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
86811924SDaniel.Beauregard@Sun.COM 		mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
86911924SDaniel.Beauregard@Sun.COM 		mb[7] = RD16_IO_REG(ha, mailbox_out[7]);
8707836SJohn.Forte@Sun.COM 
8717836SJohn.Forte@Sun.COM 		EL(ha, "%xh ISP System Error, isp_abort_needed\n mbx1=%xh, "
8727836SJohn.Forte@Sun.COM 		    "mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh, mbx6=%xh,\n "
8737836SJohn.Forte@Sun.COM 		    "mbx7=%xh, mbx8=%xh, mbx9=%xh, mbx10=%xh, mbx11=%xh, "
8747836SJohn.Forte@Sun.COM 		    "mbx12=%xh,\n", mb[0], mb[1], mb[2], mb[3],
87511924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[4]),
87611924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[5]),
87711924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[6]), mb[7],
87811924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[8]),
87911924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[9]),
88011924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[10]),
88111924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[11]),
88211924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[12]));
8837836SJohn.Forte@Sun.COM 
8847836SJohn.Forte@Sun.COM 		EL(ha, "%xh ISP System Error, isp_abort_needed\n mbx13=%xh, "
8857836SJohn.Forte@Sun.COM 		    "mbx14=%xh, mbx15=%xh, mbx16=%xh, mbx17=%xh, mbx18=%xh,\n"
8867836SJohn.Forte@Sun.COM 		    "mbx19=%xh, mbx20=%xh, mbx21=%xh, mbx22=%xh, mbx23=%xh\n",
88711924SDaniel.Beauregard@Sun.COM 		    mb[0], RD16_IO_REG(ha, mailbox_out[13]),
88811924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[14]),
88911924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[15]),
89011924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[16]),
89111924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[17]),
89211924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[18]),
89311924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[19]),
89411924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[20]),
89511924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[21]),
89611924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[22]),
89711924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[23]));
8987836SJohn.Forte@Sun.COM 
8997836SJohn.Forte@Sun.COM 		if (ha->reg_off->mbox_cnt > 24) {
9007836SJohn.Forte@Sun.COM 			EL(ha, "%xh ISP System Error, mbx24=%xh, mbx25=%xh, "
9017836SJohn.Forte@Sun.COM 			    "mbx26=%xh,\n mbx27=%xh, mbx28=%xh, mbx29=%xh, "
9027836SJohn.Forte@Sun.COM 			    "mbx30=%xh, mbx31=%xh\n", mb[0],
90311924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[24]),
90411924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[25]),
90511924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[26]),
90611924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[27]),
90711924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[28]),
90811924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[29]),
90911924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[30]),
91011924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[31]));
9117836SJohn.Forte@Sun.COM 		}
9127836SJohn.Forte@Sun.COM 
9137836SJohn.Forte@Sun.COM 		(void) ql_binary_fw_dump(ha, FALSE);
9147836SJohn.Forte@Sun.COM 
9157836SJohn.Forte@Sun.COM 		(void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8002, mb[1],
9167836SJohn.Forte@Sun.COM 		    mb[2], mb[3]);
9177836SJohn.Forte@Sun.COM 
9189611SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_81XX) && mb[7] & SE_MPI_RISC) {
9199611SDaniel.Beauregard@Sun.COM 			ADAPTER_STATE_LOCK(ha);
9209611SDaniel.Beauregard@Sun.COM 			ha->flags |= MPI_RESET_NEEDED;
9219611SDaniel.Beauregard@Sun.COM 			ADAPTER_STATE_UNLOCK(ha);
9229611SDaniel.Beauregard@Sun.COM 		}
9239611SDaniel.Beauregard@Sun.COM 
9247836SJohn.Forte@Sun.COM 		*set_flags |= ISP_ABORT_NEEDED;
9257836SJohn.Forte@Sun.COM 		ha->xioctl->ControllerErrorCount++;
9267836SJohn.Forte@Sun.COM 		break;
9277836SJohn.Forte@Sun.COM 
9287836SJohn.Forte@Sun.COM 	case MBA_REQ_TRANSFER_ERR:  /* Request Transfer Error */
9297836SJohn.Forte@Sun.COM 		EL(ha, "%xh Request Transfer Error received, "
9307836SJohn.Forte@Sun.COM 		    "isp_abort_needed\n", mb[0]);
9317836SJohn.Forte@Sun.COM 
9327836SJohn.Forte@Sun.COM 		(void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8003,
93311924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[1]),
93411924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[2]),
93511924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[3]));
9367836SJohn.Forte@Sun.COM 
9377836SJohn.Forte@Sun.COM 		*set_flags |= ISP_ABORT_NEEDED;
9387836SJohn.Forte@Sun.COM 		ha->xioctl->ControllerErrorCount++;
9397836SJohn.Forte@Sun.COM 		break;
9407836SJohn.Forte@Sun.COM 
9417836SJohn.Forte@Sun.COM 	case MBA_RSP_TRANSFER_ERR:  /* Response Xfer Err */
9427836SJohn.Forte@Sun.COM 		EL(ha, "%xh Response Transfer Error received,"
9437836SJohn.Forte@Sun.COM 		    " isp_abort_needed\n", mb[0]);
9447836SJohn.Forte@Sun.COM 
9457836SJohn.Forte@Sun.COM 		(void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8004,
94611924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[1]),
94711924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[2]),
94811924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[3]));
9497836SJohn.Forte@Sun.COM 
9507836SJohn.Forte@Sun.COM 		*set_flags |= ISP_ABORT_NEEDED;
9517836SJohn.Forte@Sun.COM 		ha->xioctl->ControllerErrorCount++;
9527836SJohn.Forte@Sun.COM 		break;
9537836SJohn.Forte@Sun.COM 
9547836SJohn.Forte@Sun.COM 	case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
9557836SJohn.Forte@Sun.COM 		EL(ha, "%xh Request Queue Wake-up received\n",
9567836SJohn.Forte@Sun.COM 		    mb[0]);
9577836SJohn.Forte@Sun.COM 		break;
9587836SJohn.Forte@Sun.COM 
9597836SJohn.Forte@Sun.COM 	case MBA_MENLO_ALERT:	/* Menlo Alert Notification */
96011924SDaniel.Beauregard@Sun.COM 		mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
96111924SDaniel.Beauregard@Sun.COM 		mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
96211924SDaniel.Beauregard@Sun.COM 		mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
9637836SJohn.Forte@Sun.COM 
9647836SJohn.Forte@Sun.COM 		EL(ha, "%xh Menlo Alert Notification received, mbx1=%xh,"
9657836SJohn.Forte@Sun.COM 		    " mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]);
9667836SJohn.Forte@Sun.COM 
9677836SJohn.Forte@Sun.COM 		switch (mb[1]) {
9687836SJohn.Forte@Sun.COM 		case MLA_LOGIN_OPERATIONAL_FW:
9697836SJohn.Forte@Sun.COM 			ADAPTER_STATE_LOCK(ha);
9707836SJohn.Forte@Sun.COM 			ha->flags |= MENLO_LOGIN_OPERATIONAL;
9717836SJohn.Forte@Sun.COM 			ADAPTER_STATE_UNLOCK(ha);
9727836SJohn.Forte@Sun.COM 			break;
9737836SJohn.Forte@Sun.COM 		case MLA_PANIC_RECOVERY:
9747836SJohn.Forte@Sun.COM 		case MLA_LOGIN_DIAGNOSTIC_FW:
9757836SJohn.Forte@Sun.COM 		case MLA_LOGIN_GOLDEN_FW:
9767836SJohn.Forte@Sun.COM 		case MLA_REJECT_RESPONSE:
9777836SJohn.Forte@Sun.COM 		default:
9787836SJohn.Forte@Sun.COM 			break;
9797836SJohn.Forte@Sun.COM 		}
9807836SJohn.Forte@Sun.COM 		break;
9817836SJohn.Forte@Sun.COM 
9827836SJohn.Forte@Sun.COM 	case MBA_LIP_F8:	/* Received a LIP F8. */
9837836SJohn.Forte@Sun.COM 	case MBA_LIP_RESET:	/* LIP reset occurred. */
9847836SJohn.Forte@Sun.COM 	case MBA_LIP_OCCURRED:	/* Loop Initialization Procedure */
98511924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_8081)) {
9869446SDaniel.Beauregard@Sun.COM 			EL(ha, "%xh DCBX_STARTED received, mbx1=%xh, mbx2=%xh"
98711924SDaniel.Beauregard@Sun.COM 			    "\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
98811924SDaniel.Beauregard@Sun.COM 			    RD16_IO_REG(ha, mailbox_out[2]));
9899446SDaniel.Beauregard@Sun.COM 		} else {
9909446SDaniel.Beauregard@Sun.COM 			EL(ha, "%xh LIP received\n", mb[0]);
9919446SDaniel.Beauregard@Sun.COM 		}
9927836SJohn.Forte@Sun.COM 
9937836SJohn.Forte@Sun.COM 		ADAPTER_STATE_LOCK(ha);
9947836SJohn.Forte@Sun.COM 		ha->flags &= ~POINT_TO_POINT;
9957836SJohn.Forte@Sun.COM 		ADAPTER_STATE_UNLOCK(ha);
9967836SJohn.Forte@Sun.COM 
9977836SJohn.Forte@Sun.COM 		if (!(ha->task_daemon_flags & LOOP_DOWN)) {
9987836SJohn.Forte@Sun.COM 			*set_flags |= LOOP_DOWN;
9997836SJohn.Forte@Sun.COM 		}
10007836SJohn.Forte@Sun.COM 		ql_port_state(ha, FC_STATE_OFFLINE,
10017836SJohn.Forte@Sun.COM 		    FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN);
10027836SJohn.Forte@Sun.COM 
10037836SJohn.Forte@Sun.COM 		if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
10047836SJohn.Forte@Sun.COM 			ha->loop_down_timer = LOOP_DOWN_TIMER_START;
10057836SJohn.Forte@Sun.COM 		}
10067836SJohn.Forte@Sun.COM 
10077836SJohn.Forte@Sun.COM 		ha->adapter_stats->lip_count++;
10087836SJohn.Forte@Sun.COM 
10097836SJohn.Forte@Sun.COM 		/* Update AEN queue. */
10107836SJohn.Forte@Sun.COM 		ha->xioctl->TotalLipResets++;
10117836SJohn.Forte@Sun.COM 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
10127836SJohn.Forte@Sun.COM 			ql_enqueue_aen(ha, mb[0], NULL);
10137836SJohn.Forte@Sun.COM 		}
10147836SJohn.Forte@Sun.COM 		break;
10157836SJohn.Forte@Sun.COM 
10167836SJohn.Forte@Sun.COM 	case MBA_LOOP_UP:
10179446SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322 |
101811924SDaniel.Beauregard@Sun.COM 		    CFG_CTRL_24258081))) {
1019*12279SDaniel.Beauregard@Sun.COM 			ha->iidma_rate = RD16_IO_REG(ha, mailbox_out[1]);
1020*12279SDaniel.Beauregard@Sun.COM 			if (ha->iidma_rate == IIDMA_RATE_1GB) {
10217836SJohn.Forte@Sun.COM 				ha->state = FC_PORT_STATE_MASK(
10227836SJohn.Forte@Sun.COM 				    ha->state) | FC_STATE_1GBIT_SPEED;
10237836SJohn.Forte@Sun.COM 				index = 1;
1024*12279SDaniel.Beauregard@Sun.COM 			} else if (ha->iidma_rate == IIDMA_RATE_2GB) {
10257836SJohn.Forte@Sun.COM 				ha->state = FC_PORT_STATE_MASK(
10267836SJohn.Forte@Sun.COM 				    ha->state) | FC_STATE_2GBIT_SPEED;
10277836SJohn.Forte@Sun.COM 				index = 2;
1028*12279SDaniel.Beauregard@Sun.COM 			} else if (ha->iidma_rate == IIDMA_RATE_4GB) {
10297836SJohn.Forte@Sun.COM 				ha->state = FC_PORT_STATE_MASK(
10307836SJohn.Forte@Sun.COM 				    ha->state) | FC_STATE_4GBIT_SPEED;
10317836SJohn.Forte@Sun.COM 				index = 4;
1032*12279SDaniel.Beauregard@Sun.COM 			} else if (ha->iidma_rate == IIDMA_RATE_8GB) {
10337836SJohn.Forte@Sun.COM 				ha->state = FC_PORT_STATE_MASK(
10347836SJohn.Forte@Sun.COM 				    ha->state) | FC_STATE_8GBIT_SPEED;
10357836SJohn.Forte@Sun.COM 				index = 8;
1036*12279SDaniel.Beauregard@Sun.COM 			} else if (ha->iidma_rate == IIDMA_RATE_10GB) {
10379446SDaniel.Beauregard@Sun.COM 				ha->state = FC_PORT_STATE_MASK(
10389446SDaniel.Beauregard@Sun.COM 				    ha->state) | FC_STATE_10GBIT_SPEED;
10399446SDaniel.Beauregard@Sun.COM 				index = 10;
10407836SJohn.Forte@Sun.COM 			} else {
10417836SJohn.Forte@Sun.COM 				ha->state = FC_PORT_STATE_MASK(
10427836SJohn.Forte@Sun.COM 				    ha->state);
10437836SJohn.Forte@Sun.COM 				index = 0;
10447836SJohn.Forte@Sun.COM 			}
10457836SJohn.Forte@Sun.COM 		} else {
1046*12279SDaniel.Beauregard@Sun.COM 			ha->iidma_rate = IIDMA_RATE_1GB;
10477836SJohn.Forte@Sun.COM 			ha->state = FC_PORT_STATE_MASK(ha->state) |
10487836SJohn.Forte@Sun.COM 			    FC_STATE_FULL_SPEED;
10497836SJohn.Forte@Sun.COM 			index = 1;
10507836SJohn.Forte@Sun.COM 		}
10517836SJohn.Forte@Sun.COM 
10527836SJohn.Forte@Sun.COM 		for (vha = ha; vha != NULL; vha = vha->vp_next) {
10537836SJohn.Forte@Sun.COM 			vha->state = FC_PORT_STATE_MASK(vha->state) |
10547836SJohn.Forte@Sun.COM 			    FC_PORT_SPEED_MASK(ha->state);
10557836SJohn.Forte@Sun.COM 		}
10567836SJohn.Forte@Sun.COM 		EL(ha, "%d GB %xh Loop Up received\n", index, mb[0]);
10577836SJohn.Forte@Sun.COM 
10587836SJohn.Forte@Sun.COM 		/* Update AEN queue. */
10597836SJohn.Forte@Sun.COM 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
10607836SJohn.Forte@Sun.COM 			ql_enqueue_aen(ha, mb[0], NULL);
10617836SJohn.Forte@Sun.COM 		}
10627836SJohn.Forte@Sun.COM 		break;
10637836SJohn.Forte@Sun.COM 
10647836SJohn.Forte@Sun.COM 	case MBA_LOOP_DOWN:
10659611SDaniel.Beauregard@Sun.COM 		EL(ha, "%xh Loop Down received, mbx1=%xh, mbx2=%xh, mbx3=%xh, "
106611924SDaniel.Beauregard@Sun.COM 		    "mbx4=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
106711924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[2]),
106811924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[3]),
106911924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[4]));
10707836SJohn.Forte@Sun.COM 
10717836SJohn.Forte@Sun.COM 		if (!(ha->task_daemon_flags & LOOP_DOWN)) {
10727836SJohn.Forte@Sun.COM 			*set_flags |= LOOP_DOWN;
10737836SJohn.Forte@Sun.COM 		}
10747836SJohn.Forte@Sun.COM 		ql_port_state(ha, FC_STATE_OFFLINE,
10757836SJohn.Forte@Sun.COM 		    FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN);
10767836SJohn.Forte@Sun.COM 
10777836SJohn.Forte@Sun.COM 		if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
10787836SJohn.Forte@Sun.COM 			ha->loop_down_timer = LOOP_DOWN_TIMER_START;
10797836SJohn.Forte@Sun.COM 		}
10807836SJohn.Forte@Sun.COM 
108111924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_258081)) {
108211924SDaniel.Beauregard@Sun.COM 			ha->sfp_stat = RD16_IO_REG(ha, mailbox_out[2]);
10837836SJohn.Forte@Sun.COM 		}
10847836SJohn.Forte@Sun.COM 
10857836SJohn.Forte@Sun.COM 		/* Update AEN queue. */
10867836SJohn.Forte@Sun.COM 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
10877836SJohn.Forte@Sun.COM 			ql_enqueue_aen(ha, mb[0], NULL);
10887836SJohn.Forte@Sun.COM 		}
10897836SJohn.Forte@Sun.COM 		break;
10907836SJohn.Forte@Sun.COM 
10917836SJohn.Forte@Sun.COM 	case MBA_PORT_UPDATE:
109211924SDaniel.Beauregard@Sun.COM 		mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
109311924SDaniel.Beauregard@Sun.COM 		mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
10947836SJohn.Forte@Sun.COM 		mb[3] = (uint16_t)(ha->flags & VP_ENABLED ?
109511924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[3]) : 0);
10967836SJohn.Forte@Sun.COM 
10977836SJohn.Forte@Sun.COM 		/* Locate port state structure. */
10987836SJohn.Forte@Sun.COM 		for (vha = ha; vha != NULL; vha = vha->vp_next) {
10997836SJohn.Forte@Sun.COM 			if (vha->vp_index == LSB(mb[3])) {
11007836SJohn.Forte@Sun.COM 				break;
11017836SJohn.Forte@Sun.COM 			}
11027836SJohn.Forte@Sun.COM 		}
11037836SJohn.Forte@Sun.COM 		if (vha == NULL) {
11047836SJohn.Forte@Sun.COM 			break;
11057836SJohn.Forte@Sun.COM 		}
110611924SDaniel.Beauregard@Sun.COM 
110711924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_8081) && mb[1] == 0xffff &&
110811924SDaniel.Beauregard@Sun.COM 		    mb[2] == 7 && (MSB(mb[3]) == 0xe || MSB(mb[3]) == 0x1a ||
110911924SDaniel.Beauregard@Sun.COM 		    MSB(mb[3]) == 0x1c || MSB(mb[3]) == 0x1d ||
111011924SDaniel.Beauregard@Sun.COM 		    MSB(mb[3]) == 0x1e)) {
111111924SDaniel.Beauregard@Sun.COM 			/*
111211924SDaniel.Beauregard@Sun.COM 			 * received FLOGI reject
111311924SDaniel.Beauregard@Sun.COM 			 * received FLOGO
111411924SDaniel.Beauregard@Sun.COM 			 * FCF configuration changed
111511924SDaniel.Beauregard@Sun.COM 			 * FIP Clear Virtual Link received
111611924SDaniel.Beauregard@Sun.COM 			 * FKA timeout
111711924SDaniel.Beauregard@Sun.COM 			 */
111811924SDaniel.Beauregard@Sun.COM 			if (!(ha->task_daemon_flags & LOOP_DOWN)) {
111911924SDaniel.Beauregard@Sun.COM 				*set_flags |= LOOP_DOWN;
112011924SDaniel.Beauregard@Sun.COM 			}
112111924SDaniel.Beauregard@Sun.COM 			ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE |
112211924SDaniel.Beauregard@Sun.COM 			    COMMAND_WAIT_NEEDED | LOOP_DOWN);
112311924SDaniel.Beauregard@Sun.COM 			if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) {
112411924SDaniel.Beauregard@Sun.COM 				ha->loop_down_timer = LOOP_DOWN_TIMER_START;
112511924SDaniel.Beauregard@Sun.COM 			}
11269446SDaniel.Beauregard@Sun.COM 		/*
11279446SDaniel.Beauregard@Sun.COM 		 * In N port 2 N port topology the FW provides a port
11289446SDaniel.Beauregard@Sun.COM 		 * database entry at loop_id 0x7fe which we use to
11299446SDaniel.Beauregard@Sun.COM 		 * acquire the Ports WWPN.
11309446SDaniel.Beauregard@Sun.COM 		 */
113111924SDaniel.Beauregard@Sun.COM 		} else if ((mb[1] != 0x7fe) &&
11329446SDaniel.Beauregard@Sun.COM 		    ((FC_PORT_STATE_MASK(vha->state) != FC_STATE_OFFLINE ||
113311924SDaniel.Beauregard@Sun.COM 		    (CFG_IST(ha, CFG_CTRL_24258081) &&
11349446SDaniel.Beauregard@Sun.COM 		    (mb[1] != 0xffff || mb[2] != 6 || mb[3] != 0))))) {
11357836SJohn.Forte@Sun.COM 			EL(ha, "%xh Port Database Update, Login/Logout "
11367836SJohn.Forte@Sun.COM 			    "received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
11377836SJohn.Forte@Sun.COM 			    mb[0], mb[1], mb[2], mb[3]);
11387836SJohn.Forte@Sun.COM 		} else {
11397836SJohn.Forte@Sun.COM 			EL(ha, "%xh Port Database Update received, mbx1=%xh,"
11407836SJohn.Forte@Sun.COM 			    " mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2],
11417836SJohn.Forte@Sun.COM 			    mb[3]);
11427836SJohn.Forte@Sun.COM 			*set_flags |= LOOP_RESYNC_NEEDED;
11437836SJohn.Forte@Sun.COM 			*set_flags &= ~LOOP_DOWN;
11447836SJohn.Forte@Sun.COM 			*reset_flags |= LOOP_DOWN;
11457836SJohn.Forte@Sun.COM 			*reset_flags &= ~LOOP_RESYNC_NEEDED;
11467836SJohn.Forte@Sun.COM 			vha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
11477836SJohn.Forte@Sun.COM 			TASK_DAEMON_LOCK(ha);
11487836SJohn.Forte@Sun.COM 			vha->task_daemon_flags |= LOOP_RESYNC_NEEDED;
11497836SJohn.Forte@Sun.COM 			vha->task_daemon_flags &= ~LOOP_DOWN;
11507836SJohn.Forte@Sun.COM 			TASK_DAEMON_UNLOCK(ha);
11517836SJohn.Forte@Sun.COM 			ADAPTER_STATE_LOCK(ha);
11529156SDaniel.Beauregard@Sun.COM 			vha->flags &= ~ABORT_CMDS_LOOP_DOWN_TMO;
11537836SJohn.Forte@Sun.COM 			ADAPTER_STATE_UNLOCK(ha);
11547836SJohn.Forte@Sun.COM 		}
11557836SJohn.Forte@Sun.COM 
11567836SJohn.Forte@Sun.COM 		/* Update AEN queue. */
11577836SJohn.Forte@Sun.COM 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
11587836SJohn.Forte@Sun.COM 			ql_enqueue_aen(ha, mb[0], NULL);
11597836SJohn.Forte@Sun.COM 		}
11607836SJohn.Forte@Sun.COM 		break;
11617836SJohn.Forte@Sun.COM 
11627836SJohn.Forte@Sun.COM 	case MBA_RSCN_UPDATE:
116311924SDaniel.Beauregard@Sun.COM 		mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
116411924SDaniel.Beauregard@Sun.COM 		mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
11657836SJohn.Forte@Sun.COM 		mb[3] = (uint16_t)(ha->flags & VP_ENABLED ?
116611924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[3]) : 0);
11677836SJohn.Forte@Sun.COM 
11687836SJohn.Forte@Sun.COM 		/* Locate port state structure. */
11697836SJohn.Forte@Sun.COM 		for (vha = ha; vha != NULL; vha = vha->vp_next) {
11707836SJohn.Forte@Sun.COM 			if (vha->vp_index == LSB(mb[3])) {
11717836SJohn.Forte@Sun.COM 				break;
11727836SJohn.Forte@Sun.COM 			}
11737836SJohn.Forte@Sun.COM 		}
11747836SJohn.Forte@Sun.COM 
11757836SJohn.Forte@Sun.COM 		if (vha == NULL) {
11767836SJohn.Forte@Sun.COM 			break;
11777836SJohn.Forte@Sun.COM 		}
11787836SJohn.Forte@Sun.COM 
11797836SJohn.Forte@Sun.COM 		if (LSB(mb[1]) == vha->d_id.b.domain &&
11807836SJohn.Forte@Sun.COM 		    MSB(mb[2]) == vha->d_id.b.area &&
11817836SJohn.Forte@Sun.COM 		    LSB(mb[2]) == vha->d_id.b.al_pa) {
11827836SJohn.Forte@Sun.COM 			EL(ha, "%xh RSCN match adapter, mbx1=%xh, mbx2=%xh, "
11837836SJohn.Forte@Sun.COM 			    "mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]);
11847836SJohn.Forte@Sun.COM 		} else {
11857836SJohn.Forte@Sun.COM 			EL(ha, "%xh RSCN received, mbx1=%xh, mbx2=%xh, "
11867836SJohn.Forte@Sun.COM 			    "mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]);
11877836SJohn.Forte@Sun.COM 			if (FC_PORT_STATE_MASK(vha->state) !=
11887836SJohn.Forte@Sun.COM 			    FC_STATE_OFFLINE) {
11897836SJohn.Forte@Sun.COM 				ql_rcv_rscn_els(vha, &mb[0], done_q);
11907836SJohn.Forte@Sun.COM 				TASK_DAEMON_LOCK(ha);
11917836SJohn.Forte@Sun.COM 				vha->task_daemon_flags |= RSCN_UPDATE_NEEDED;
11927836SJohn.Forte@Sun.COM 				TASK_DAEMON_UNLOCK(ha);
11937836SJohn.Forte@Sun.COM 				*set_flags |= RSCN_UPDATE_NEEDED;
11947836SJohn.Forte@Sun.COM 			}
11957836SJohn.Forte@Sun.COM 		}
11967836SJohn.Forte@Sun.COM 
11977836SJohn.Forte@Sun.COM 		/* Update AEN queue. */
11987836SJohn.Forte@Sun.COM 		if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
11997836SJohn.Forte@Sun.COM 			ql_enqueue_aen(ha, mb[0], NULL);
12007836SJohn.Forte@Sun.COM 		}
12017836SJohn.Forte@Sun.COM 		break;
12027836SJohn.Forte@Sun.COM 
12037836SJohn.Forte@Sun.COM 	case MBA_LIP_ERROR:	/* Loop initialization errors. */
12047836SJohn.Forte@Sun.COM 		EL(ha, "%xh LIP error received, mbx1=%xh\n", mb[0],
120511924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[1]));
12067836SJohn.Forte@Sun.COM 		break;
12077836SJohn.Forte@Sun.COM 
12087836SJohn.Forte@Sun.COM 	case MBA_IP_RECEIVE:
12097836SJohn.Forte@Sun.COM 	case MBA_IP_BROADCAST:
121011924SDaniel.Beauregard@Sun.COM 		mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
121111924SDaniel.Beauregard@Sun.COM 		mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
121211924SDaniel.Beauregard@Sun.COM 		mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
12137836SJohn.Forte@Sun.COM 
12147836SJohn.Forte@Sun.COM 		EL(ha, "%xh IP packet/broadcast received, mbx1=%xh, "
12157836SJohn.Forte@Sun.COM 		    "mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]);
12167836SJohn.Forte@Sun.COM 
12177836SJohn.Forte@Sun.COM 		/* Locate device queue. */
12187836SJohn.Forte@Sun.COM 		s_id.b.al_pa = LSB(mb[2]);
12197836SJohn.Forte@Sun.COM 		s_id.b.area = MSB(mb[2]);
12207836SJohn.Forte@Sun.COM 		s_id.b.domain = LSB(mb[1]);
12217836SJohn.Forte@Sun.COM 		if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
12227836SJohn.Forte@Sun.COM 			EL(ha, "Unknown IP device=%xh\n", s_id.b24);
12237836SJohn.Forte@Sun.COM 			break;
12247836SJohn.Forte@Sun.COM 		}
12257836SJohn.Forte@Sun.COM 
122611924SDaniel.Beauregard@Sun.COM 		cnt = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
12277836SJohn.Forte@Sun.COM 		    CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb24.buf_size[0],
12287836SJohn.Forte@Sun.COM 		    ha->ip_init_ctrl_blk.cb24.buf_size[1]) :
12297836SJohn.Forte@Sun.COM 		    CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb.buf_size[0],
12307836SJohn.Forte@Sun.COM 		    ha->ip_init_ctrl_blk.cb.buf_size[1]));
12317836SJohn.Forte@Sun.COM 
12327836SJohn.Forte@Sun.COM 		tq->ub_sequence_length = mb[3];
12337836SJohn.Forte@Sun.COM 		tq->ub_total_seg_cnt = (uint8_t)(mb[3] / cnt);
12347836SJohn.Forte@Sun.COM 		if (mb[3] % cnt) {
12357836SJohn.Forte@Sun.COM 			tq->ub_total_seg_cnt++;
12367836SJohn.Forte@Sun.COM 		}
12377836SJohn.Forte@Sun.COM 		cnt = (uint16_t)(tq->ub_total_seg_cnt + 10);
12387836SJohn.Forte@Sun.COM 
12397836SJohn.Forte@Sun.COM 		for (index = 10; index < ha->reg_off->mbox_cnt && index < cnt;
12407836SJohn.Forte@Sun.COM 		    index++) {
124111924SDaniel.Beauregard@Sun.COM 			mb[index] = RD16_IO_REG(ha, mailbox_out[index]);
12427836SJohn.Forte@Sun.COM 		}
12437836SJohn.Forte@Sun.COM 
12447836SJohn.Forte@Sun.COM 		tq->ub_seq_id = ++ha->ub_seq_id;
12457836SJohn.Forte@Sun.COM 		tq->ub_seq_cnt = 0;
12467836SJohn.Forte@Sun.COM 		tq->ub_frame_ro = 0;
12477836SJohn.Forte@Sun.COM 		tq->ub_loop_id = (uint16_t)(mb[0] == MBA_IP_BROADCAST ?
124811924SDaniel.Beauregard@Sun.COM 		    (CFG_IST(ha, CFG_CTRL_24258081) ? BROADCAST_24XX_HDL :
12497836SJohn.Forte@Sun.COM 		    IP_BROADCAST_LOOP_ID) : tq->loop_id);
12507836SJohn.Forte@Sun.COM 		ha->rcv_dev_q = tq;
12517836SJohn.Forte@Sun.COM 
12527836SJohn.Forte@Sun.COM 		for (cnt = 10; cnt < ha->reg_off->mbox_cnt &&
12537836SJohn.Forte@Sun.COM 		    tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
12547836SJohn.Forte@Sun.COM 			if (ql_ub_frame_hdr(ha, tq, mb[cnt], done_q) !=
12557836SJohn.Forte@Sun.COM 			    QL_SUCCESS) {
12567836SJohn.Forte@Sun.COM 				EL(ha, "ql_ub_frame_hdr failed, "
12577836SJohn.Forte@Sun.COM 				    "isp_abort_needed\n");
12587836SJohn.Forte@Sun.COM 				*set_flags |= ISP_ABORT_NEEDED;
12597836SJohn.Forte@Sun.COM 				break;
12607836SJohn.Forte@Sun.COM 			}
12617836SJohn.Forte@Sun.COM 		}
12627836SJohn.Forte@Sun.COM 		break;
12637836SJohn.Forte@Sun.COM 
12647836SJohn.Forte@Sun.COM 	case MBA_IP_LOW_WATER_MARK:
12657836SJohn.Forte@Sun.COM 	case MBA_IP_RCV_BUFFER_EMPTY:
12667836SJohn.Forte@Sun.COM 		EL(ha, "%xh IP low water mark / RCV buffer empty received\n",
12677836SJohn.Forte@Sun.COM 		    mb[0]);
12687836SJohn.Forte@Sun.COM 		*set_flags |= NEED_UNSOLICITED_BUFFERS;
12697836SJohn.Forte@Sun.COM 		break;
12707836SJohn.Forte@Sun.COM 
12717836SJohn.Forte@Sun.COM 	case MBA_IP_HDR_DATA_SPLIT:
12727836SJohn.Forte@Sun.COM 		EL(ha, "%xh IP HDR data split received\n", mb[0]);
12737836SJohn.Forte@Sun.COM 		break;
12747836SJohn.Forte@Sun.COM 
12759611SDaniel.Beauregard@Sun.COM 	case MBA_ERROR_LOGGING_DISABLED:
12769611SDaniel.Beauregard@Sun.COM 		EL(ha, "%xh error logging disabled received, "
127711924SDaniel.Beauregard@Sun.COM 		    "mbx1=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]));
12789611SDaniel.Beauregard@Sun.COM 		break;
12799611SDaniel.Beauregard@Sun.COM 
12807836SJohn.Forte@Sun.COM 	case MBA_POINT_TO_POINT:
12819446SDaniel.Beauregard@Sun.COM 	/* case MBA_DCBX_COMPLETED: */
128211924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_8081)) {
12839446SDaniel.Beauregard@Sun.COM 			EL(ha, "%xh DCBX completed received\n", mb[0]);
12849446SDaniel.Beauregard@Sun.COM 		} else {
12859446SDaniel.Beauregard@Sun.COM 			EL(ha, "%xh Point to Point Mode received\n", mb[0]);
12869446SDaniel.Beauregard@Sun.COM 		}
12877836SJohn.Forte@Sun.COM 		ADAPTER_STATE_LOCK(ha);
12887836SJohn.Forte@Sun.COM 		ha->flags |= POINT_TO_POINT;
12897836SJohn.Forte@Sun.COM 		ADAPTER_STATE_UNLOCK(ha);
12909446SDaniel.Beauregard@Sun.COM 		break;
12919446SDaniel.Beauregard@Sun.COM 
12929446SDaniel.Beauregard@Sun.COM 	case MBA_FCF_CONFIG_ERROR:
12939611SDaniel.Beauregard@Sun.COM 		EL(ha, "%xh FCF configuration Error received, mbx1=%xh\n",
129411924SDaniel.Beauregard@Sun.COM 		    mb[0], RD16_IO_REG(ha, mailbox_out[1]));
12959446SDaniel.Beauregard@Sun.COM 		break;
12969446SDaniel.Beauregard@Sun.COM 
12979611SDaniel.Beauregard@Sun.COM 	case MBA_DCBX_PARAM_CHANGED:
12989611SDaniel.Beauregard@Sun.COM 		EL(ha, "%xh DCBX parameters changed received, mbx1=%xh\n",
129911924SDaniel.Beauregard@Sun.COM 		    mb[0], RD16_IO_REG(ha, mailbox_out[1]));
13007836SJohn.Forte@Sun.COM 		break;
13017836SJohn.Forte@Sun.COM 
13027836SJohn.Forte@Sun.COM 	case MBA_CHG_IN_CONNECTION:
130311924SDaniel.Beauregard@Sun.COM 		mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
13047836SJohn.Forte@Sun.COM 		if (mb[1] == 2) {
13057836SJohn.Forte@Sun.COM 			EL(ha, "%xh Change In Connection received, "
13067836SJohn.Forte@Sun.COM 			    "mbx1=%xh\n",  mb[0], mb[1]);
13077836SJohn.Forte@Sun.COM 			ADAPTER_STATE_LOCK(ha);
13087836SJohn.Forte@Sun.COM 			ha->flags &= ~POINT_TO_POINT;
13097836SJohn.Forte@Sun.COM 			ADAPTER_STATE_UNLOCK(ha);
13107836SJohn.Forte@Sun.COM 			if (ha->topology & QL_N_PORT) {
13117836SJohn.Forte@Sun.COM 				ha->topology = (uint8_t)(ha->topology &
13127836SJohn.Forte@Sun.COM 				    ~QL_N_PORT);
13137836SJohn.Forte@Sun.COM 				ha->topology = (uint8_t)(ha->topology |
13147836SJohn.Forte@Sun.COM 				    QL_NL_PORT);
13157836SJohn.Forte@Sun.COM 			}
13167836SJohn.Forte@Sun.COM 		} else {
13177836SJohn.Forte@Sun.COM 			EL(ha, "%xh Change In Connection received, "
13187836SJohn.Forte@Sun.COM 			    "mbx1=%xh, isp_abort_needed\n", mb[0], mb[1]);
13197836SJohn.Forte@Sun.COM 			*set_flags |= ISP_ABORT_NEEDED;
13207836SJohn.Forte@Sun.COM 		}
13217836SJohn.Forte@Sun.COM 		break;
13227836SJohn.Forte@Sun.COM 
13237836SJohn.Forte@Sun.COM 	case MBA_ZIO_UPDATE:
13247836SJohn.Forte@Sun.COM 		EL(ha, "%xh ZIO response received\n", mb[0]);
13257836SJohn.Forte@Sun.COM 
13267836SJohn.Forte@Sun.COM 		ha->isp_rsp_index = RD16_IO_REG(ha, resp_in);
13277836SJohn.Forte@Sun.COM 		ql_response_pkt(ha, done_q, set_flags, reset_flags, intr_clr);
13287836SJohn.Forte@Sun.COM 		intr = B_FALSE;
13297836SJohn.Forte@Sun.COM 		break;
13307836SJohn.Forte@Sun.COM 
13317836SJohn.Forte@Sun.COM 	case MBA_PORT_BYPASS_CHANGED:
13327836SJohn.Forte@Sun.COM 		EL(ha, "%xh Port Bypass Changed received, mbx1=%xh\n",
133311924SDaniel.Beauregard@Sun.COM 		    mb[0], RD16_IO_REG(ha, mailbox_out[1]));
13347836SJohn.Forte@Sun.COM 		/*
13357836SJohn.Forte@Sun.COM 		 * Event generated when there is a transition on
13367836SJohn.Forte@Sun.COM 		 * port bypass of crystal+.
13377836SJohn.Forte@Sun.COM 		 * Mailbox 1:	Bit 0 - External.
13387836SJohn.Forte@Sun.COM 		 *		Bit 2 - Internal.
13397836SJohn.Forte@Sun.COM 		 * When the bit is 0, the port is bypassed.
13407836SJohn.Forte@Sun.COM 		 *
13417836SJohn.Forte@Sun.COM 		 * For now we will generate a LIP for all cases.
13427836SJohn.Forte@Sun.COM 		 */
13437836SJohn.Forte@Sun.COM 		*set_flags |= HANDLE_PORT_BYPASS_CHANGE;
13447836SJohn.Forte@Sun.COM 		break;
13457836SJohn.Forte@Sun.COM 
13467836SJohn.Forte@Sun.COM 	case MBA_RECEIVE_ERROR:
13477836SJohn.Forte@Sun.COM 		EL(ha, "%xh Receive Error received, mbx1=%xh, mbx2=%xh\n",
134811924SDaniel.Beauregard@Sun.COM 		    mb[0], RD16_IO_REG(ha, mailbox_out[1]),
134911924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[2]));
13507836SJohn.Forte@Sun.COM 		break;
13517836SJohn.Forte@Sun.COM 
13527836SJohn.Forte@Sun.COM 	case MBA_LS_RJT_SENT:
13537836SJohn.Forte@Sun.COM 		EL(ha, "%xh LS_RJT Response Sent ELS=%xh\n", mb[0],
135411924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[1]));
13557836SJohn.Forte@Sun.COM 		break;
13567836SJohn.Forte@Sun.COM 
13577836SJohn.Forte@Sun.COM 	case MBA_FW_RESTART_COMP:
13587836SJohn.Forte@Sun.COM 		EL(ha, "%xh firmware restart complete received mb1=%xh\n",
135911924SDaniel.Beauregard@Sun.COM 		    mb[0], RD16_IO_REG(ha, mailbox_out[1]));
13607836SJohn.Forte@Sun.COM 		break;
13617836SJohn.Forte@Sun.COM 
1362*12279SDaniel.Beauregard@Sun.COM 	/*
1363*12279SDaniel.Beauregard@Sun.COM 	 * MBA_IDC_COMPLETE &  MBA_IDC_NOTIFICATION: We won't get another
1364*12279SDaniel.Beauregard@Sun.COM 	 * IDC async event until we ACK the current one.
1365*12279SDaniel.Beauregard@Sun.COM 	 */
13669446SDaniel.Beauregard@Sun.COM 	case MBA_IDC_COMPLETE:
1367*12279SDaniel.Beauregard@Sun.COM 		ha->idc_mb[0] = mb[0];
1368*12279SDaniel.Beauregard@Sun.COM 		ha->idc_mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
1369*12279SDaniel.Beauregard@Sun.COM 		ha->idc_mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
1370*12279SDaniel.Beauregard@Sun.COM 		ha->idc_mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
1371*12279SDaniel.Beauregard@Sun.COM 		ha->idc_mb[4] = RD16_IO_REG(ha, mailbox_out[4]);
1372*12279SDaniel.Beauregard@Sun.COM 		ha->idc_mb[5] = RD16_IO_REG(ha, mailbox_out[5]);
1373*12279SDaniel.Beauregard@Sun.COM 		ha->idc_mb[6] = RD16_IO_REG(ha, mailbox_out[6]);
1374*12279SDaniel.Beauregard@Sun.COM 		ha->idc_mb[7] = RD16_IO_REG(ha, mailbox_out[7]);
13759446SDaniel.Beauregard@Sun.COM 		EL(ha, "%xh Inter-driver communication complete received, "
137611924SDaniel.Beauregard@Sun.COM 		    " mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh,"
1377*12279SDaniel.Beauregard@Sun.COM 		    " mbx6=%xh, mbx7=%xh\n", mb[0], ha->idc_mb[1],
1378*12279SDaniel.Beauregard@Sun.COM 		    ha->idc_mb[2], ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5],
1379*12279SDaniel.Beauregard@Sun.COM 		    ha->idc_mb[6], ha->idc_mb[7]);
1380*12279SDaniel.Beauregard@Sun.COM 		*set_flags |= IDC_EVENT;
13819446SDaniel.Beauregard@Sun.COM 		break;
13829446SDaniel.Beauregard@Sun.COM 
13839446SDaniel.Beauregard@Sun.COM 	case MBA_IDC_NOTIFICATION:
1384*12279SDaniel.Beauregard@Sun.COM 		ha->idc_mb[0] = mb[0];
138511924SDaniel.Beauregard@Sun.COM 		ha->idc_mb[1] = RD16_IO_REG(ha, mailbox_out[1]);
138611924SDaniel.Beauregard@Sun.COM 		ha->idc_mb[2] = RD16_IO_REG(ha, mailbox_out[2]);
138711924SDaniel.Beauregard@Sun.COM 		ha->idc_mb[3] = RD16_IO_REG(ha, mailbox_out[3]);
138811924SDaniel.Beauregard@Sun.COM 		ha->idc_mb[4] = RD16_IO_REG(ha, mailbox_out[4]);
138911924SDaniel.Beauregard@Sun.COM 		ha->idc_mb[5] = RD16_IO_REG(ha, mailbox_out[5]);
139011924SDaniel.Beauregard@Sun.COM 		ha->idc_mb[6] = RD16_IO_REG(ha, mailbox_out[6]);
139111924SDaniel.Beauregard@Sun.COM 		ha->idc_mb[7] = RD16_IO_REG(ha, mailbox_out[7]);
13929446SDaniel.Beauregard@Sun.COM 		EL(ha, "%xh Inter-driver communication request notification "
13939446SDaniel.Beauregard@Sun.COM 		    "received, mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh, "
13949446SDaniel.Beauregard@Sun.COM 		    "mbx5=%xh, mbx6=%xh, mbx7=%xh\n", mb[0], ha->idc_mb[1],
13959446SDaniel.Beauregard@Sun.COM 		    ha->idc_mb[2], ha->idc_mb[3], ha->idc_mb[4], ha->idc_mb[5],
13969446SDaniel.Beauregard@Sun.COM 		    ha->idc_mb[6], ha->idc_mb[7]);
1397*12279SDaniel.Beauregard@Sun.COM 		*set_flags |= IDC_EVENT;
13989446SDaniel.Beauregard@Sun.COM 		break;
13999446SDaniel.Beauregard@Sun.COM 
14009446SDaniel.Beauregard@Sun.COM 	case MBA_IDC_TIME_EXTENDED:
14019446SDaniel.Beauregard@Sun.COM 		EL(ha, "%xh Inter-driver communication time extended received,"
14029446SDaniel.Beauregard@Sun.COM 		    " mbx1=%xh, mbx2=%xh\n", mb[0],
140311924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[1]),
140411924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[2]));
14059446SDaniel.Beauregard@Sun.COM 		break;
14069446SDaniel.Beauregard@Sun.COM 
14077836SJohn.Forte@Sun.COM 	default:
14087836SJohn.Forte@Sun.COM 		EL(ha, "%xh UNKNOWN event received, mbx1=%xh, mbx2=%xh, "
140911924SDaniel.Beauregard@Sun.COM 		    "mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox_out[1]),
141011924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[2]),
141111924SDaniel.Beauregard@Sun.COM 		    RD16_IO_REG(ha, mailbox_out[3]));
14127836SJohn.Forte@Sun.COM 		break;
14137836SJohn.Forte@Sun.COM 	}
14147836SJohn.Forte@Sun.COM 
14157836SJohn.Forte@Sun.COM 	/* Clear RISC interrupt */
14167836SJohn.Forte@Sun.COM 	if (intr && intr_clr) {
141711924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_8021)) {
141811924SDaniel.Beauregard@Sun.COM 			ql_8021_clr_fw_intr(ha);
141911924SDaniel.Beauregard@Sun.COM 		} else if (CFG_IST(ha, CFG_CTRL_242581)) {
142011924SDaniel.Beauregard@Sun.COM 			WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
142111924SDaniel.Beauregard@Sun.COM 		} else {
142211924SDaniel.Beauregard@Sun.COM 			WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
142311924SDaniel.Beauregard@Sun.COM 		}
14247836SJohn.Forte@Sun.COM 	}
14257836SJohn.Forte@Sun.COM 
14267836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
14277836SJohn.Forte@Sun.COM }
14287836SJohn.Forte@Sun.COM 
14297836SJohn.Forte@Sun.COM /*
14307836SJohn.Forte@Sun.COM  * ql_fast_fcp_post
14317836SJohn.Forte@Sun.COM  *	Fast path for good SCSI I/O completion.
14327836SJohn.Forte@Sun.COM  *
14337836SJohn.Forte@Sun.COM  * Input:
14347836SJohn.Forte@Sun.COM  *	sp:	SRB pointer.
14357836SJohn.Forte@Sun.COM  *
14367836SJohn.Forte@Sun.COM  * Context:
14377836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
14387836SJohn.Forte@Sun.COM  */
14397836SJohn.Forte@Sun.COM static void
ql_fast_fcp_post(ql_srb_t * sp)14407836SJohn.Forte@Sun.COM ql_fast_fcp_post(ql_srb_t *sp)
14417836SJohn.Forte@Sun.COM {
14427836SJohn.Forte@Sun.COM 	ql_adapter_state_t	*ha = sp->ha;
14437836SJohn.Forte@Sun.COM 	ql_lun_t		*lq = sp->lun_queue;
14447836SJohn.Forte@Sun.COM 	ql_tgt_t		*tq = lq->target_queue;
14457836SJohn.Forte@Sun.COM 
14467836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
14477836SJohn.Forte@Sun.COM 
14487836SJohn.Forte@Sun.COM 	/* Acquire device queue lock. */
14497836SJohn.Forte@Sun.COM 	DEVICE_QUEUE_LOCK(tq);
14507836SJohn.Forte@Sun.COM 
14517836SJohn.Forte@Sun.COM 	/* Decrement outstanding commands on device. */
14527836SJohn.Forte@Sun.COM 	if (tq->outcnt != 0) {
14537836SJohn.Forte@Sun.COM 		tq->outcnt--;
14547836SJohn.Forte@Sun.COM 	}
14557836SJohn.Forte@Sun.COM 
14567836SJohn.Forte@Sun.COM 	if (sp->flags & SRB_FCP_CMD_PKT) {
14577836SJohn.Forte@Sun.COM 		if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_UNTAGGED) {
14587836SJohn.Forte@Sun.COM 			/*
14597836SJohn.Forte@Sun.COM 			 * Clear the flag for this LUN so that
14607836SJohn.Forte@Sun.COM 			 * untagged commands can be submitted
14617836SJohn.Forte@Sun.COM 			 * for it.
14627836SJohn.Forte@Sun.COM 			 */
14637836SJohn.Forte@Sun.COM 			lq->flags &= ~LQF_UNTAGGED_PENDING;
14647836SJohn.Forte@Sun.COM 		}
14657836SJohn.Forte@Sun.COM 
14667836SJohn.Forte@Sun.COM 		if (lq->lun_outcnt != 0) {
14677836SJohn.Forte@Sun.COM 			lq->lun_outcnt--;
14687836SJohn.Forte@Sun.COM 		}
14697836SJohn.Forte@Sun.COM 	}
14707836SJohn.Forte@Sun.COM 
14717836SJohn.Forte@Sun.COM 	/* Reset port down retry count on good completion. */
14727836SJohn.Forte@Sun.COM 	tq->port_down_retry_count = ha->port_down_retry_count;
14737836SJohn.Forte@Sun.COM 	tq->qfull_retry_count = ha->qfull_retry_count;
1474*12279SDaniel.Beauregard@Sun.COM 	ha->pha->timeout_cnt = 0;
14757836SJohn.Forte@Sun.COM 
14767836SJohn.Forte@Sun.COM 	/* Remove command from watchdog queue. */
14777836SJohn.Forte@Sun.COM 	if (sp->flags & SRB_WATCHDOG_ENABLED) {
14787836SJohn.Forte@Sun.COM 		ql_remove_link(&tq->wdg, &sp->wdg);
14797836SJohn.Forte@Sun.COM 		sp->flags &= ~SRB_WATCHDOG_ENABLED;
14807836SJohn.Forte@Sun.COM 	}
14817836SJohn.Forte@Sun.COM 
14827836SJohn.Forte@Sun.COM 	if (lq->cmd.first != NULL) {
14837836SJohn.Forte@Sun.COM 		ql_next(ha, lq);
14847836SJohn.Forte@Sun.COM 	} else {
14857836SJohn.Forte@Sun.COM 		/* Release LU queue specific lock. */
14867836SJohn.Forte@Sun.COM 		DEVICE_QUEUE_UNLOCK(tq);
14877836SJohn.Forte@Sun.COM 		if (ha->pha->pending_cmds.first != NULL) {
14887836SJohn.Forte@Sun.COM 			ql_start_iocb(ha, NULL);
14897836SJohn.Forte@Sun.COM 		}
14907836SJohn.Forte@Sun.COM 	}
14917836SJohn.Forte@Sun.COM 
14927836SJohn.Forte@Sun.COM 	/* Sync buffers if required.  */
14937836SJohn.Forte@Sun.COM 	if (sp->flags & SRB_MS_PKT) {
14947836SJohn.Forte@Sun.COM 		(void) ddi_dma_sync(sp->pkt->pkt_resp_dma, 0, 0,
14957836SJohn.Forte@Sun.COM 		    DDI_DMA_SYNC_FORCPU);
14967836SJohn.Forte@Sun.COM 	}
14977836SJohn.Forte@Sun.COM 
14987836SJohn.Forte@Sun.COM 	/* Map ISP completion codes. */
14997836SJohn.Forte@Sun.COM 	sp->pkt->pkt_expln = FC_EXPLN_NONE;
15007836SJohn.Forte@Sun.COM 	sp->pkt->pkt_action = FC_ACTION_RETRYABLE;
15017836SJohn.Forte@Sun.COM 	sp->pkt->pkt_state = FC_PKT_SUCCESS;
15027836SJohn.Forte@Sun.COM 
15037836SJohn.Forte@Sun.COM 	/* Now call the pkt completion callback */
15047836SJohn.Forte@Sun.COM 	if (sp->flags & SRB_POLL) {
15057836SJohn.Forte@Sun.COM 		sp->flags &= ~SRB_POLL;
15067836SJohn.Forte@Sun.COM 	} else if (sp->pkt->pkt_comp) {
15077836SJohn.Forte@Sun.COM 		INTR_UNLOCK(ha);
15087836SJohn.Forte@Sun.COM 		(*sp->pkt->pkt_comp)(sp->pkt);
15097836SJohn.Forte@Sun.COM 		INTR_LOCK(ha);
15107836SJohn.Forte@Sun.COM 	}
15117836SJohn.Forte@Sun.COM 
15127836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
15137836SJohn.Forte@Sun.COM }
15147836SJohn.Forte@Sun.COM 
15157836SJohn.Forte@Sun.COM /*
15167836SJohn.Forte@Sun.COM  * ql_response_pkt
15177836SJohn.Forte@Sun.COM  *	Processes response entry.
15187836SJohn.Forte@Sun.COM  *
15197836SJohn.Forte@Sun.COM  * Input:
15207836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
15217836SJohn.Forte@Sun.COM  *	done_q:		head pointer to done queue.
15227836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
15237836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
15247836SJohn.Forte@Sun.COM  *	intr_clr:	early interrupt clear
15257836SJohn.Forte@Sun.COM  *
15267836SJohn.Forte@Sun.COM  * Context:
15277836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
15287836SJohn.Forte@Sun.COM  */
15297836SJohn.Forte@Sun.COM static void
ql_response_pkt(ql_adapter_state_t * ha,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags,int intr_clr)15307836SJohn.Forte@Sun.COM ql_response_pkt(ql_adapter_state_t *ha, ql_head_t *done_q, uint32_t *set_flags,
15317836SJohn.Forte@Sun.COM     uint32_t *reset_flags, int intr_clr)
15327836SJohn.Forte@Sun.COM {
15337836SJohn.Forte@Sun.COM 	response_t	*pkt;
15347836SJohn.Forte@Sun.COM 	uint32_t	dma_sync_size_1 = 0;
15357836SJohn.Forte@Sun.COM 	uint32_t	dma_sync_size_2 = 0;
15367836SJohn.Forte@Sun.COM 	int		status = 0;
15377836SJohn.Forte@Sun.COM 
15387836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
15397836SJohn.Forte@Sun.COM 
15407836SJohn.Forte@Sun.COM 	/* Clear RISC interrupt */
15417836SJohn.Forte@Sun.COM 	if (intr_clr) {
154211924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_8021)) {
154311924SDaniel.Beauregard@Sun.COM 			ql_8021_clr_fw_intr(ha);
154411924SDaniel.Beauregard@Sun.COM 		} else if (CFG_IST(ha, CFG_CTRL_242581)) {
154511924SDaniel.Beauregard@Sun.COM 			WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
154611924SDaniel.Beauregard@Sun.COM 		} else {
154711924SDaniel.Beauregard@Sun.COM 			WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
154811924SDaniel.Beauregard@Sun.COM 		}
15497836SJohn.Forte@Sun.COM 	}
15507836SJohn.Forte@Sun.COM 
15517836SJohn.Forte@Sun.COM 	if (ha->isp_rsp_index >= RESPONSE_ENTRY_CNT) {
15527836SJohn.Forte@Sun.COM 		EL(ha, "index error = %xh, isp_abort_needed",
15537836SJohn.Forte@Sun.COM 		    ha->isp_rsp_index);
15547836SJohn.Forte@Sun.COM 		*set_flags |= ISP_ABORT_NEEDED;
15557836SJohn.Forte@Sun.COM 		return;
15567836SJohn.Forte@Sun.COM 	}
15577836SJohn.Forte@Sun.COM 
15587836SJohn.Forte@Sun.COM 	if ((ha->flags & ONLINE) == 0) {
15597836SJohn.Forte@Sun.COM 		QL_PRINT_3(CE_CONT, "(%d): not onlne, done\n", ha->instance);
15607836SJohn.Forte@Sun.COM 		return;
15617836SJohn.Forte@Sun.COM 	}
15627836SJohn.Forte@Sun.COM 
15637836SJohn.Forte@Sun.COM 	/* Calculate size of response queue entries to sync. */
15647836SJohn.Forte@Sun.COM 	if (ha->isp_rsp_index > ha->rsp_ring_index) {
15657836SJohn.Forte@Sun.COM 		dma_sync_size_1 = (uint32_t)
15667836SJohn.Forte@Sun.COM 		    ((uint32_t)(ha->isp_rsp_index - ha->rsp_ring_index) *
15677836SJohn.Forte@Sun.COM 		    RESPONSE_ENTRY_SIZE);
15687836SJohn.Forte@Sun.COM 	} else if (ha->isp_rsp_index == 0) {
15697836SJohn.Forte@Sun.COM 		dma_sync_size_1 = (uint32_t)
15707836SJohn.Forte@Sun.COM 		    ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) *
15717836SJohn.Forte@Sun.COM 		    RESPONSE_ENTRY_SIZE);
15727836SJohn.Forte@Sun.COM 	} else {
15737836SJohn.Forte@Sun.COM 		/* Responses wrap around the Q */
15747836SJohn.Forte@Sun.COM 		dma_sync_size_1 = (uint32_t)
15757836SJohn.Forte@Sun.COM 		    ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) *
15767836SJohn.Forte@Sun.COM 		    RESPONSE_ENTRY_SIZE);
15777836SJohn.Forte@Sun.COM 		dma_sync_size_2 = (uint32_t)
15787836SJohn.Forte@Sun.COM 		    (ha->isp_rsp_index * RESPONSE_ENTRY_SIZE);
15797836SJohn.Forte@Sun.COM 	}
15807836SJohn.Forte@Sun.COM 
15817836SJohn.Forte@Sun.COM 	/* Sync DMA buffer. */
15827836SJohn.Forte@Sun.COM 	(void) ddi_dma_sync(ha->hba_buf.dma_handle,
15837836SJohn.Forte@Sun.COM 	    (off_t)(ha->rsp_ring_index * RESPONSE_ENTRY_SIZE +
15847836SJohn.Forte@Sun.COM 	    RESPONSE_Q_BUFFER_OFFSET), dma_sync_size_1,
15857836SJohn.Forte@Sun.COM 	    DDI_DMA_SYNC_FORKERNEL);
15867836SJohn.Forte@Sun.COM 	if (dma_sync_size_2) {
15877836SJohn.Forte@Sun.COM 		(void) ddi_dma_sync(ha->hba_buf.dma_handle,
15887836SJohn.Forte@Sun.COM 		    RESPONSE_Q_BUFFER_OFFSET, dma_sync_size_2,
15897836SJohn.Forte@Sun.COM 		    DDI_DMA_SYNC_FORKERNEL);
15907836SJohn.Forte@Sun.COM 	}
15917836SJohn.Forte@Sun.COM 
15927836SJohn.Forte@Sun.COM 	while (ha->rsp_ring_index != ha->isp_rsp_index) {
15937836SJohn.Forte@Sun.COM 		pkt = ha->response_ring_ptr;
15947836SJohn.Forte@Sun.COM 
15957836SJohn.Forte@Sun.COM 		QL_PRINT_5(CE_CONT, "(%d): ha->rsp_rg_idx=%xh, mbx[5]=%xh\n",
15967836SJohn.Forte@Sun.COM 		    ha->instance, ha->rsp_ring_index, ha->isp_rsp_index);
15977836SJohn.Forte@Sun.COM 		QL_DUMP_5((uint8_t *)ha->response_ring_ptr, 8,
15987836SJohn.Forte@Sun.COM 		    RESPONSE_ENTRY_SIZE);
15997836SJohn.Forte@Sun.COM 
16007836SJohn.Forte@Sun.COM 		/* Adjust ring index. */
16017836SJohn.Forte@Sun.COM 		ha->rsp_ring_index++;
16027836SJohn.Forte@Sun.COM 		if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) {
16037836SJohn.Forte@Sun.COM 			ha->rsp_ring_index = 0;
16047836SJohn.Forte@Sun.COM 			ha->response_ring_ptr = ha->response_ring_bp;
16057836SJohn.Forte@Sun.COM 		} else {
16067836SJohn.Forte@Sun.COM 			ha->response_ring_ptr++;
16077836SJohn.Forte@Sun.COM 		}
16087836SJohn.Forte@Sun.COM 
16097836SJohn.Forte@Sun.COM 		/* Process packet. */
16107836SJohn.Forte@Sun.COM 		if (ha->status_srb != NULL && pkt->entry_type !=
16117836SJohn.Forte@Sun.COM 		    STATUS_CONT_TYPE) {
16127836SJohn.Forte@Sun.COM 			ql_add_link_b(done_q, &ha->status_srb->cmd);
16137836SJohn.Forte@Sun.COM 			ha->status_srb = NULL;
16147836SJohn.Forte@Sun.COM 		}
16157836SJohn.Forte@Sun.COM 
161611924SDaniel.Beauregard@Sun.COM 		pkt->entry_status = (uint8_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
16177836SJohn.Forte@Sun.COM 		    pkt->entry_status & 0x3c : pkt->entry_status & 0x7e);
16187836SJohn.Forte@Sun.COM 
16197836SJohn.Forte@Sun.COM 		if (pkt->entry_status != 0) {
16207836SJohn.Forte@Sun.COM 			ql_error_entry(ha, pkt, done_q, set_flags,
16217836SJohn.Forte@Sun.COM 			    reset_flags);
16227836SJohn.Forte@Sun.COM 		} else {
16237836SJohn.Forte@Sun.COM 			switch (pkt->entry_type) {
16247836SJohn.Forte@Sun.COM 			case STATUS_TYPE:
162511924SDaniel.Beauregard@Sun.COM 				status |= CFG_IST(ha, CFG_CTRL_24258081) ?
16267836SJohn.Forte@Sun.COM 				    ql_24xx_status_entry(ha,
16277836SJohn.Forte@Sun.COM 				    (sts_24xx_entry_t *)pkt, done_q, set_flags,
16287836SJohn.Forte@Sun.COM 				    reset_flags) :
16297836SJohn.Forte@Sun.COM 				    ql_status_entry(ha, (sts_entry_t *)pkt,
16307836SJohn.Forte@Sun.COM 				    done_q, set_flags, reset_flags);
16317836SJohn.Forte@Sun.COM 				break;
16327836SJohn.Forte@Sun.COM 			case STATUS_CONT_TYPE:
16337836SJohn.Forte@Sun.COM 				ql_status_cont_entry(ha,
16347836SJohn.Forte@Sun.COM 				    (sts_cont_entry_t *)pkt, done_q, set_flags,
16357836SJohn.Forte@Sun.COM 				    reset_flags);
16367836SJohn.Forte@Sun.COM 				break;
16377836SJohn.Forte@Sun.COM 			case IP_TYPE:
16387836SJohn.Forte@Sun.COM 			case IP_A64_TYPE:
16397836SJohn.Forte@Sun.COM 			case IP_CMD_TYPE:
16407836SJohn.Forte@Sun.COM 				ql_ip_entry(ha, (ip_entry_t *)pkt, done_q,
16417836SJohn.Forte@Sun.COM 				    set_flags, reset_flags);
16427836SJohn.Forte@Sun.COM 				break;
16437836SJohn.Forte@Sun.COM 			case IP_RECEIVE_TYPE:
16447836SJohn.Forte@Sun.COM 				ql_ip_rcv_entry(ha,
16457836SJohn.Forte@Sun.COM 				    (ip_rcv_entry_t *)pkt, done_q, set_flags,
16467836SJohn.Forte@Sun.COM 				    reset_flags);
16477836SJohn.Forte@Sun.COM 				break;
16487836SJohn.Forte@Sun.COM 			case IP_RECEIVE_CONT_TYPE:
16497836SJohn.Forte@Sun.COM 				ql_ip_rcv_cont_entry(ha,
16507836SJohn.Forte@Sun.COM 				    (ip_rcv_cont_entry_t *)pkt,	done_q,
16517836SJohn.Forte@Sun.COM 				    set_flags, reset_flags);
16527836SJohn.Forte@Sun.COM 				break;
16537836SJohn.Forte@Sun.COM 			case IP_24XX_RECEIVE_TYPE:
16547836SJohn.Forte@Sun.COM 				ql_ip_24xx_rcv_entry(ha,
16557836SJohn.Forte@Sun.COM 				    (ip_rcv_24xx_entry_t *)pkt, done_q,
16567836SJohn.Forte@Sun.COM 				    set_flags, reset_flags);
16577836SJohn.Forte@Sun.COM 				break;
16587836SJohn.Forte@Sun.COM 			case MS_TYPE:
16597836SJohn.Forte@Sun.COM 				ql_ms_entry(ha, (ms_entry_t *)pkt, done_q,
16607836SJohn.Forte@Sun.COM 				    set_flags, reset_flags);
16617836SJohn.Forte@Sun.COM 				break;
16627836SJohn.Forte@Sun.COM 			case REPORT_ID_TYPE:
16637836SJohn.Forte@Sun.COM 				ql_report_id_entry(ha, (report_id_1_t *)pkt,
16647836SJohn.Forte@Sun.COM 				    done_q, set_flags, reset_flags);
16657836SJohn.Forte@Sun.COM 				break;
16669446SDaniel.Beauregard@Sun.COM 			case ELS_PASSTHRU_TYPE:
16679446SDaniel.Beauregard@Sun.COM 				ql_els_passthru_entry(ha,
16689446SDaniel.Beauregard@Sun.COM 				    (els_passthru_entry_rsp_t *)pkt,
16699446SDaniel.Beauregard@Sun.COM 				    done_q, set_flags, reset_flags);
16709446SDaniel.Beauregard@Sun.COM 				break;
16717836SJohn.Forte@Sun.COM 			case IP_BUF_POOL_TYPE:
16727836SJohn.Forte@Sun.COM 			case MARKER_TYPE:
16737836SJohn.Forte@Sun.COM 			case VP_MODIFY_TYPE:
16747836SJohn.Forte@Sun.COM 			case VP_CONTROL_TYPE:
16757836SJohn.Forte@Sun.COM 				break;
16767836SJohn.Forte@Sun.COM 			default:
16777836SJohn.Forte@Sun.COM 				EL(ha, "Unknown IOCB entry type=%xh\n",
16787836SJohn.Forte@Sun.COM 				    pkt->entry_type);
16797836SJohn.Forte@Sun.COM 				break;
16807836SJohn.Forte@Sun.COM 			}
16817836SJohn.Forte@Sun.COM 		}
16827836SJohn.Forte@Sun.COM 	}
16837836SJohn.Forte@Sun.COM 
16847836SJohn.Forte@Sun.COM 	/* Inform RISC of processed responses. */
16857836SJohn.Forte@Sun.COM 	WRT16_IO_REG(ha, resp_out, ha->rsp_ring_index);
16867836SJohn.Forte@Sun.COM 
16877836SJohn.Forte@Sun.COM 	/* RESET packet received delay for possible async event. */
16887836SJohn.Forte@Sun.COM 	if (status & BIT_0) {
16897836SJohn.Forte@Sun.COM 		drv_usecwait(500000);
16907836SJohn.Forte@Sun.COM 	}
16917836SJohn.Forte@Sun.COM 
16927836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
16937836SJohn.Forte@Sun.COM }
16947836SJohn.Forte@Sun.COM 
16957836SJohn.Forte@Sun.COM /*
16967836SJohn.Forte@Sun.COM  * ql_error_entry
16977836SJohn.Forte@Sun.COM  *	Processes error entry.
16987836SJohn.Forte@Sun.COM  *
16997836SJohn.Forte@Sun.COM  * Input:
17007836SJohn.Forte@Sun.COM  *	ha = adapter state pointer.
17017836SJohn.Forte@Sun.COM  *	pkt = entry pointer.
17027836SJohn.Forte@Sun.COM  *	done_q = head pointer to done queue.
17037836SJohn.Forte@Sun.COM  *	set_flags = task daemon flags to set.
17047836SJohn.Forte@Sun.COM  *	reset_flags = task daemon flags to reset.
17057836SJohn.Forte@Sun.COM  *
17067836SJohn.Forte@Sun.COM  * Context:
17077836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
17087836SJohn.Forte@Sun.COM  */
17097836SJohn.Forte@Sun.COM /* ARGSUSED */
17107836SJohn.Forte@Sun.COM static void
ql_error_entry(ql_adapter_state_t * ha,response_t * pkt,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)17117836SJohn.Forte@Sun.COM ql_error_entry(ql_adapter_state_t *ha, response_t *pkt, ql_head_t *done_q,
17127836SJohn.Forte@Sun.COM     uint32_t *set_flags, uint32_t *reset_flags)
17137836SJohn.Forte@Sun.COM {
17147836SJohn.Forte@Sun.COM 	ql_srb_t	*sp;
171510240SDaniel.Beauregard@Sun.COM 	uint32_t	index, resp_identifier;
17167836SJohn.Forte@Sun.COM 
17177836SJohn.Forte@Sun.COM 	if (pkt->entry_type == INVALID_ENTRY_TYPE) {
17187836SJohn.Forte@Sun.COM 		EL(ha, "Aborted command\n");
17197836SJohn.Forte@Sun.COM 		return;
17207836SJohn.Forte@Sun.COM 	}
17217836SJohn.Forte@Sun.COM 
17227836SJohn.Forte@Sun.COM 	QL_PRINT_2(CE_CONT, "(%d): started, packet:\n", ha->instance);
17237836SJohn.Forte@Sun.COM 	QL_DUMP_2((uint8_t *)pkt, 8, RESPONSE_ENTRY_SIZE);
17247836SJohn.Forte@Sun.COM 
17257836SJohn.Forte@Sun.COM 	if (pkt->entry_status & BIT_6) {
17267836SJohn.Forte@Sun.COM 		EL(ha, "Request Queue DMA error\n");
17277836SJohn.Forte@Sun.COM 	} else if (pkt->entry_status & BIT_5) {
17287836SJohn.Forte@Sun.COM 		EL(ha, "Invalid Entry Order\n");
17297836SJohn.Forte@Sun.COM 	} else if (pkt->entry_status & BIT_4) {
17307836SJohn.Forte@Sun.COM 		EL(ha, "Invalid Entry Count\n");
17317836SJohn.Forte@Sun.COM 	} else if (pkt->entry_status & BIT_3) {
17327836SJohn.Forte@Sun.COM 		EL(ha, "Invalid Entry Parameter\n");
17337836SJohn.Forte@Sun.COM 	} else if (pkt->entry_status & BIT_2) {
17347836SJohn.Forte@Sun.COM 		EL(ha, "Invalid Entry Type\n");
17357836SJohn.Forte@Sun.COM 	} else if (pkt->entry_status & BIT_1) {
17367836SJohn.Forte@Sun.COM 		EL(ha, "Busy\n");
17377836SJohn.Forte@Sun.COM 	} else {
17387836SJohn.Forte@Sun.COM 		EL(ha, "UNKNOWN flag = %xh error\n", pkt->entry_status);
17397836SJohn.Forte@Sun.COM 	}
17407836SJohn.Forte@Sun.COM 
174110240SDaniel.Beauregard@Sun.COM 	/* Validate the response entry handle. */
174210240SDaniel.Beauregard@Sun.COM 	resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
174310240SDaniel.Beauregard@Sun.COM 	index = resp_identifier & OSC_INDEX_MASK;
174410240SDaniel.Beauregard@Sun.COM 	if (index < MAX_OUTSTANDING_COMMANDS) {
174510240SDaniel.Beauregard@Sun.COM 		/* the index seems reasonable */
174610240SDaniel.Beauregard@Sun.COM 		sp = ha->outstanding_cmds[index];
174710240SDaniel.Beauregard@Sun.COM 		if (sp != NULL) {
174810240SDaniel.Beauregard@Sun.COM 			if (sp->handle == resp_identifier) {
174910240SDaniel.Beauregard@Sun.COM 				/* Neo, you're the one... */
175010240SDaniel.Beauregard@Sun.COM 				ha->outstanding_cmds[index] = NULL;
175110240SDaniel.Beauregard@Sun.COM 				sp->handle = 0;
175210240SDaniel.Beauregard@Sun.COM 				sp->flags &= ~SRB_IN_TOKEN_ARRAY;
175310240SDaniel.Beauregard@Sun.COM 			} else {
175410240SDaniel.Beauregard@Sun.COM 				EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
175510240SDaniel.Beauregard@Sun.COM 				    resp_identifier, sp->handle);
175610240SDaniel.Beauregard@Sun.COM 				sp = NULL;
175710240SDaniel.Beauregard@Sun.COM 				ql_signal_abort(ha, set_flags);
175810240SDaniel.Beauregard@Sun.COM 			}
175910240SDaniel.Beauregard@Sun.COM 		} else {
176010240SDaniel.Beauregard@Sun.COM 			sp = ql_verify_preprocessed_cmd(ha,
176110240SDaniel.Beauregard@Sun.COM 			    (uint32_t *)&pkt->handle, set_flags, reset_flags);
176210240SDaniel.Beauregard@Sun.COM 		}
176310240SDaniel.Beauregard@Sun.COM 	} else {
176410240SDaniel.Beauregard@Sun.COM 		EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
176510240SDaniel.Beauregard@Sun.COM 		    index, resp_identifier);
176610240SDaniel.Beauregard@Sun.COM 		ql_signal_abort(ha, set_flags);
176710240SDaniel.Beauregard@Sun.COM 	}
176810240SDaniel.Beauregard@Sun.COM 
176910240SDaniel.Beauregard@Sun.COM 	if (sp != NULL) {
17707836SJohn.Forte@Sun.COM 		/* Bad payload or header */
17717836SJohn.Forte@Sun.COM 		if (pkt->entry_status & (BIT_5 + BIT_4 + BIT_3 + BIT_2)) {
17727836SJohn.Forte@Sun.COM 			/* Bad payload or header, set error status. */
17737836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = CS_BAD_PAYLOAD;
17747836SJohn.Forte@Sun.COM 		} else if (pkt->entry_status & BIT_1) /* FULL flag */ {
17757836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = CS_QUEUE_FULL;
17767836SJohn.Forte@Sun.COM 		} else {
17777836SJohn.Forte@Sun.COM 			/* Set error status. */
17787836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = CS_UNKNOWN;
17797836SJohn.Forte@Sun.COM 		}
17807836SJohn.Forte@Sun.COM 
17817836SJohn.Forte@Sun.COM 		/* Set completed status. */
17827836SJohn.Forte@Sun.COM 		sp->flags |= SRB_ISP_COMPLETED;
17837836SJohn.Forte@Sun.COM 
17847836SJohn.Forte@Sun.COM 		/* Place command on done queue. */
17857836SJohn.Forte@Sun.COM 		ql_add_link_b(done_q, &sp->cmd);
17867836SJohn.Forte@Sun.COM 
17877836SJohn.Forte@Sun.COM 	}
17887836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
17897836SJohn.Forte@Sun.COM }
17907836SJohn.Forte@Sun.COM 
17917836SJohn.Forte@Sun.COM /*
17927836SJohn.Forte@Sun.COM  * ql_status_entry
17937836SJohn.Forte@Sun.COM  *	Processes received ISP2200-2300 status entry.
17947836SJohn.Forte@Sun.COM  *
17957836SJohn.Forte@Sun.COM  * Input:
17967836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
17977836SJohn.Forte@Sun.COM  *	pkt:		entry pointer.
17987836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
17997836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
18007836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
18017836SJohn.Forte@Sun.COM  *
18027836SJohn.Forte@Sun.COM  * Returns:
18037836SJohn.Forte@Sun.COM  *	BIT_0 = CS_RESET status received.
18047836SJohn.Forte@Sun.COM  *
18057836SJohn.Forte@Sun.COM  * Context:
18067836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
18077836SJohn.Forte@Sun.COM  */
18087836SJohn.Forte@Sun.COM /* ARGSUSED */
18097836SJohn.Forte@Sun.COM static int
ql_status_entry(ql_adapter_state_t * ha,sts_entry_t * pkt,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)18107836SJohn.Forte@Sun.COM ql_status_entry(ql_adapter_state_t *ha, sts_entry_t *pkt,
18117836SJohn.Forte@Sun.COM     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
18127836SJohn.Forte@Sun.COM {
18137836SJohn.Forte@Sun.COM 	ql_srb_t		*sp;
181410240SDaniel.Beauregard@Sun.COM 	uint32_t		index, resp_identifier;
18157836SJohn.Forte@Sun.COM 	uint16_t		comp_status;
18167836SJohn.Forte@Sun.COM 	int			rval = 0;
18177836SJohn.Forte@Sun.COM 
18187836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
18197836SJohn.Forte@Sun.COM 
182010240SDaniel.Beauregard@Sun.COM 	/* Validate the response entry handle. */
182110240SDaniel.Beauregard@Sun.COM 	resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
182210240SDaniel.Beauregard@Sun.COM 	index = resp_identifier & OSC_INDEX_MASK;
182310240SDaniel.Beauregard@Sun.COM 	if (index < MAX_OUTSTANDING_COMMANDS) {
182410240SDaniel.Beauregard@Sun.COM 		/* the index seems reasonable */
182510240SDaniel.Beauregard@Sun.COM 		sp = ha->outstanding_cmds[index];
182610240SDaniel.Beauregard@Sun.COM 		if (sp != NULL) {
182710240SDaniel.Beauregard@Sun.COM 			if (sp->handle == resp_identifier) {
182810240SDaniel.Beauregard@Sun.COM 				/* Neo, you're the one... */
182910240SDaniel.Beauregard@Sun.COM 				ha->outstanding_cmds[index] = NULL;
183010240SDaniel.Beauregard@Sun.COM 				sp->handle = 0;
183110240SDaniel.Beauregard@Sun.COM 				sp->flags &= ~SRB_IN_TOKEN_ARRAY;
183210240SDaniel.Beauregard@Sun.COM 			} else {
183310240SDaniel.Beauregard@Sun.COM 				EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
183410240SDaniel.Beauregard@Sun.COM 				    resp_identifier, sp->handle);
183510240SDaniel.Beauregard@Sun.COM 				sp = NULL;
183610240SDaniel.Beauregard@Sun.COM 				ql_signal_abort(ha, set_flags);
183710240SDaniel.Beauregard@Sun.COM 			}
183810240SDaniel.Beauregard@Sun.COM 		} else {
183910240SDaniel.Beauregard@Sun.COM 			sp = ql_verify_preprocessed_cmd(ha,
184010240SDaniel.Beauregard@Sun.COM 			    (uint32_t *)&pkt->handle, set_flags, reset_flags);
184110240SDaniel.Beauregard@Sun.COM 		}
184210240SDaniel.Beauregard@Sun.COM 	} else {
184310240SDaniel.Beauregard@Sun.COM 		EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
184410240SDaniel.Beauregard@Sun.COM 		    index, resp_identifier);
184510240SDaniel.Beauregard@Sun.COM 		ql_signal_abort(ha, set_flags);
184610240SDaniel.Beauregard@Sun.COM 	}
184710240SDaniel.Beauregard@Sun.COM 
184810240SDaniel.Beauregard@Sun.COM 	if (sp != NULL) {
18497836SJohn.Forte@Sun.COM 		comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
18507836SJohn.Forte@Sun.COM 		    &pkt->comp_status);
18517836SJohn.Forte@Sun.COM 
18527836SJohn.Forte@Sun.COM 		/*
18537836SJohn.Forte@Sun.COM 		 * We dont care about SCSI QFULLs.
18547836SJohn.Forte@Sun.COM 		 */
18557836SJohn.Forte@Sun.COM 		if (comp_status == CS_QUEUE_FULL) {
18567836SJohn.Forte@Sun.COM 			EL(ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n",
18577836SJohn.Forte@Sun.COM 			    sp->lun_queue->target_queue->d_id.b24,
18587836SJohn.Forte@Sun.COM 			    sp->lun_queue->lun_no);
18597836SJohn.Forte@Sun.COM 			comp_status = CS_COMPLETE;
18607836SJohn.Forte@Sun.COM 		}
18617836SJohn.Forte@Sun.COM 
18627836SJohn.Forte@Sun.COM 		/*
18637836SJohn.Forte@Sun.COM 		 * 2300 firmware marks completion status as data underrun
18647836SJohn.Forte@Sun.COM 		 * for scsi qfulls. Make it transport complete.
18657836SJohn.Forte@Sun.COM 		 */
18667836SJohn.Forte@Sun.COM 		if ((CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) &&
18677836SJohn.Forte@Sun.COM 		    (comp_status == CS_DATA_UNDERRUN) &&
18687836SJohn.Forte@Sun.COM 		    (pkt->scsi_status_l != 0)) {
18697836SJohn.Forte@Sun.COM 			comp_status = CS_COMPLETE;
18707836SJohn.Forte@Sun.COM 		}
18717836SJohn.Forte@Sun.COM 
18727836SJohn.Forte@Sun.COM 		/*
18737836SJohn.Forte@Sun.COM 		 * Workaround T3 issue where we do not get any data xferred
18747836SJohn.Forte@Sun.COM 		 * but get back a good status.
18757836SJohn.Forte@Sun.COM 		 */
18767836SJohn.Forte@Sun.COM 		if ((pkt->state_flags_h & SF_XFERRED_DATA) == 0 &&
18777836SJohn.Forte@Sun.COM 		    comp_status == CS_COMPLETE &&
18787836SJohn.Forte@Sun.COM 		    pkt->scsi_status_l == 0 &&
18797836SJohn.Forte@Sun.COM 		    (pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
18807836SJohn.Forte@Sun.COM 		    pkt->residual_length == 0 &&
18817836SJohn.Forte@Sun.COM 		    sp->fcp &&
18827836SJohn.Forte@Sun.COM 		    sp->fcp->fcp_data_len != 0 &&
18837836SJohn.Forte@Sun.COM 		    (pkt->state_flags_l & (SF_DATA_OUT | SF_DATA_IN)) ==
18847836SJohn.Forte@Sun.COM 		    SF_DATA_OUT) {
18857836SJohn.Forte@Sun.COM 			comp_status = CS_ABORTED;
18867836SJohn.Forte@Sun.COM 		}
18877836SJohn.Forte@Sun.COM 
18887836SJohn.Forte@Sun.COM 		if (sp->flags & SRB_MS_PKT) {
18897836SJohn.Forte@Sun.COM 			/*
18907836SJohn.Forte@Sun.COM 			 * Ideally it should never be true. But there
18917836SJohn.Forte@Sun.COM 			 * is a bug in FW which upon receiving invalid
18927836SJohn.Forte@Sun.COM 			 * parameters in MS IOCB returns it as
18937836SJohn.Forte@Sun.COM 			 * status entry and not as ms entry type.
18947836SJohn.Forte@Sun.COM 			 */
18957836SJohn.Forte@Sun.COM 			ql_ms_entry(ha, (ms_entry_t *)pkt, done_q,
18967836SJohn.Forte@Sun.COM 			    set_flags, reset_flags);
18977836SJohn.Forte@Sun.COM 			QL_PRINT_3(CE_CONT, "(%d): ql_ms_entry done\n",
18987836SJohn.Forte@Sun.COM 			    ha->instance);
18997836SJohn.Forte@Sun.COM 			return (0);
19007836SJohn.Forte@Sun.COM 		}
19017836SJohn.Forte@Sun.COM 
19027836SJohn.Forte@Sun.COM 		/*
19037836SJohn.Forte@Sun.COM 		 * Fast path to good SCSI I/O completion
19047836SJohn.Forte@Sun.COM 		 */
19057836SJohn.Forte@Sun.COM 		if ((comp_status == CS_COMPLETE) &
19067836SJohn.Forte@Sun.COM 		    (!pkt->scsi_status_l) &
19077836SJohn.Forte@Sun.COM 		    (!(pkt->scsi_status_h & FCP_RSP_MASK))) {
19087836SJohn.Forte@Sun.COM 			/* Set completed status. */
19097836SJohn.Forte@Sun.COM 			sp->flags |= SRB_ISP_COMPLETED;
19107836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = comp_status;
19117836SJohn.Forte@Sun.COM 			ql_fast_fcp_post(sp);
19127836SJohn.Forte@Sun.COM 			QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n",
19137836SJohn.Forte@Sun.COM 			    ha->instance);
19147836SJohn.Forte@Sun.COM 			return (0);
19157836SJohn.Forte@Sun.COM 		}
19167836SJohn.Forte@Sun.COM 		rval = ql_status_error(ha, sp, pkt, done_q, set_flags,
19177836SJohn.Forte@Sun.COM 		    reset_flags);
19187836SJohn.Forte@Sun.COM 	}
19197836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
19207836SJohn.Forte@Sun.COM 
19217836SJohn.Forte@Sun.COM 	return (rval);
19227836SJohn.Forte@Sun.COM }
19237836SJohn.Forte@Sun.COM 
19247836SJohn.Forte@Sun.COM /*
19257836SJohn.Forte@Sun.COM  * ql_24xx_status_entry
19267836SJohn.Forte@Sun.COM  *	Processes received ISP24xx status entry.
19277836SJohn.Forte@Sun.COM  *
19287836SJohn.Forte@Sun.COM  * Input:
19297836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
19307836SJohn.Forte@Sun.COM  *	pkt:		entry pointer.
19317836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
19327836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
19337836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
19347836SJohn.Forte@Sun.COM  *
19357836SJohn.Forte@Sun.COM  * Returns:
19367836SJohn.Forte@Sun.COM  *	BIT_0 = CS_RESET status received.
19377836SJohn.Forte@Sun.COM  *
19387836SJohn.Forte@Sun.COM  * Context:
19397836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
19407836SJohn.Forte@Sun.COM  */
19417836SJohn.Forte@Sun.COM /* ARGSUSED */
19427836SJohn.Forte@Sun.COM static int
ql_24xx_status_entry(ql_adapter_state_t * ha,sts_24xx_entry_t * pkt,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)19437836SJohn.Forte@Sun.COM ql_24xx_status_entry(ql_adapter_state_t *ha, sts_24xx_entry_t *pkt,
19447836SJohn.Forte@Sun.COM     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
19457836SJohn.Forte@Sun.COM {
194610240SDaniel.Beauregard@Sun.COM 	ql_srb_t		*sp = NULL;
19477836SJohn.Forte@Sun.COM 	uint16_t		comp_status;
194810240SDaniel.Beauregard@Sun.COM 	uint32_t		index, resp_identifier;
19497836SJohn.Forte@Sun.COM 	int			rval = 0;
19507836SJohn.Forte@Sun.COM 
19517836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
19527836SJohn.Forte@Sun.COM 
195310240SDaniel.Beauregard@Sun.COM 	/* Validate the response entry handle. */
19549156SDaniel.Beauregard@Sun.COM 	resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle);
19559156SDaniel.Beauregard@Sun.COM 	index = resp_identifier & OSC_INDEX_MASK;
195610240SDaniel.Beauregard@Sun.COM 	if (index < MAX_OUTSTANDING_COMMANDS) {
195710240SDaniel.Beauregard@Sun.COM 		/* the index seems reasonable */
195810240SDaniel.Beauregard@Sun.COM 		sp = ha->outstanding_cmds[index];
195910240SDaniel.Beauregard@Sun.COM 		if (sp != NULL) {
196010240SDaniel.Beauregard@Sun.COM 			if (sp->handle == resp_identifier) {
196110240SDaniel.Beauregard@Sun.COM 				/* Neo, you're the one... */
196210240SDaniel.Beauregard@Sun.COM 				ha->outstanding_cmds[index] = NULL;
196310240SDaniel.Beauregard@Sun.COM 				sp->handle = 0;
196410240SDaniel.Beauregard@Sun.COM 				sp->flags &= ~SRB_IN_TOKEN_ARRAY;
196510240SDaniel.Beauregard@Sun.COM 			} else {
196610240SDaniel.Beauregard@Sun.COM 				EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
196710240SDaniel.Beauregard@Sun.COM 				    resp_identifier, sp->handle);
196810240SDaniel.Beauregard@Sun.COM 				sp = NULL;
196910240SDaniel.Beauregard@Sun.COM 				ql_signal_abort(ha, set_flags);
197010240SDaniel.Beauregard@Sun.COM 			}
197110240SDaniel.Beauregard@Sun.COM 		} else {
197210240SDaniel.Beauregard@Sun.COM 			sp = ql_verify_preprocessed_cmd(ha,
197310240SDaniel.Beauregard@Sun.COM 			    (uint32_t *)&pkt->handle, set_flags, reset_flags);
197410240SDaniel.Beauregard@Sun.COM 		}
197510240SDaniel.Beauregard@Sun.COM 	} else {
197610240SDaniel.Beauregard@Sun.COM 		EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
197710240SDaniel.Beauregard@Sun.COM 		    index, resp_identifier);
197810240SDaniel.Beauregard@Sun.COM 		ql_signal_abort(ha, set_flags);
197910240SDaniel.Beauregard@Sun.COM 	}
198010240SDaniel.Beauregard@Sun.COM 
198110240SDaniel.Beauregard@Sun.COM 	if (sp != NULL) {
19827836SJohn.Forte@Sun.COM 		comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
19837836SJohn.Forte@Sun.COM 		    &pkt->comp_status);
19847836SJohn.Forte@Sun.COM 
198510240SDaniel.Beauregard@Sun.COM 		/* We dont care about SCSI QFULLs. */
19867836SJohn.Forte@Sun.COM 		if (comp_status == CS_QUEUE_FULL) {
19877836SJohn.Forte@Sun.COM 			EL(sp->ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n",
19887836SJohn.Forte@Sun.COM 			    sp->lun_queue->target_queue->d_id.b24,
19897836SJohn.Forte@Sun.COM 			    sp->lun_queue->lun_no);
19907836SJohn.Forte@Sun.COM 			comp_status = CS_COMPLETE;
19917836SJohn.Forte@Sun.COM 		}
19927836SJohn.Forte@Sun.COM 
19937836SJohn.Forte@Sun.COM 		/*
19947836SJohn.Forte@Sun.COM 		 * 2300 firmware marks completion status as data underrun
19957836SJohn.Forte@Sun.COM 		 * for scsi qfulls. Make it transport complete.
19967836SJohn.Forte@Sun.COM 		 */
19977836SJohn.Forte@Sun.COM 		if ((comp_status == CS_DATA_UNDERRUN) &&
19987836SJohn.Forte@Sun.COM 		    (pkt->scsi_status_l != 0)) {
19997836SJohn.Forte@Sun.COM 			comp_status = CS_COMPLETE;
20007836SJohn.Forte@Sun.COM 		}
20017836SJohn.Forte@Sun.COM 
20027836SJohn.Forte@Sun.COM 		/*
20037836SJohn.Forte@Sun.COM 		 * Workaround T3 issue where we do not get any data xferred
20047836SJohn.Forte@Sun.COM 		 * but get back a good status.
20057836SJohn.Forte@Sun.COM 		 */
20067836SJohn.Forte@Sun.COM 		if (comp_status == CS_COMPLETE &&
20077836SJohn.Forte@Sun.COM 		    pkt->scsi_status_l == 0 &&
20087836SJohn.Forte@Sun.COM 		    (pkt->scsi_status_h & FCP_RSP_MASK) == 0 &&
20097836SJohn.Forte@Sun.COM 		    pkt->residual_length != 0 &&
20107836SJohn.Forte@Sun.COM 		    sp->fcp &&
20117836SJohn.Forte@Sun.COM 		    sp->fcp->fcp_data_len != 0 &&
20127836SJohn.Forte@Sun.COM 		    sp->fcp->fcp_cntl.cntl_write_data) {
20137836SJohn.Forte@Sun.COM 			comp_status = CS_ABORTED;
20147836SJohn.Forte@Sun.COM 		}
20157836SJohn.Forte@Sun.COM 
20167836SJohn.Forte@Sun.COM 		/*
20177836SJohn.Forte@Sun.COM 		 * Fast path to good SCSI I/O completion
20187836SJohn.Forte@Sun.COM 		 */
20197836SJohn.Forte@Sun.COM 		if ((comp_status == CS_COMPLETE) &
20207836SJohn.Forte@Sun.COM 		    (!pkt->scsi_status_l) &
20217836SJohn.Forte@Sun.COM 		    (!(pkt->scsi_status_h & FCP_RSP_MASK))) {
20227836SJohn.Forte@Sun.COM 			/* Set completed status. */
20237836SJohn.Forte@Sun.COM 			sp->flags |= SRB_ISP_COMPLETED;
20247836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = comp_status;
20257836SJohn.Forte@Sun.COM 			ql_fast_fcp_post(sp);
20267836SJohn.Forte@Sun.COM 			QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n",
20277836SJohn.Forte@Sun.COM 			    ha->instance);
20287836SJohn.Forte@Sun.COM 			return (0);
20297836SJohn.Forte@Sun.COM 		}
20307836SJohn.Forte@Sun.COM 		rval = ql_status_error(ha, sp, (sts_entry_t *)pkt, done_q,
20317836SJohn.Forte@Sun.COM 		    set_flags, reset_flags);
20327836SJohn.Forte@Sun.COM 	}
20337836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
20347836SJohn.Forte@Sun.COM 
20357836SJohn.Forte@Sun.COM 	return (rval);
20367836SJohn.Forte@Sun.COM }
20377836SJohn.Forte@Sun.COM 
20387836SJohn.Forte@Sun.COM /*
203910240SDaniel.Beauregard@Sun.COM  * ql_verify_preprocessed_cmd
204010240SDaniel.Beauregard@Sun.COM  *	Handles preprocessed cmds..
204110240SDaniel.Beauregard@Sun.COM  *
204210240SDaniel.Beauregard@Sun.COM  * Input:
204310240SDaniel.Beauregard@Sun.COM  *	ha:		adapter state pointer.
204410240SDaniel.Beauregard@Sun.COM  *	pkt_handle:	handle pointer.
204510240SDaniel.Beauregard@Sun.COM  *	set_flags:	task daemon flags to set.
204610240SDaniel.Beauregard@Sun.COM  *	reset_flags:	task daemon flags to reset.
204710240SDaniel.Beauregard@Sun.COM  *
204810240SDaniel.Beauregard@Sun.COM  * Returns:
204910240SDaniel.Beauregard@Sun.COM  *	srb pointer or NULL
205010240SDaniel.Beauregard@Sun.COM  *
205110240SDaniel.Beauregard@Sun.COM  * Context:
205210240SDaniel.Beauregard@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
205310240SDaniel.Beauregard@Sun.COM  */
205410240SDaniel.Beauregard@Sun.COM /* ARGSUSED */
205510240SDaniel.Beauregard@Sun.COM ql_srb_t *
ql_verify_preprocessed_cmd(ql_adapter_state_t * ha,uint32_t * pkt_handle,uint32_t * set_flags,uint32_t * reset_flags)205610240SDaniel.Beauregard@Sun.COM ql_verify_preprocessed_cmd(ql_adapter_state_t *ha, uint32_t *pkt_handle,
205710240SDaniel.Beauregard@Sun.COM     uint32_t *set_flags, uint32_t *reset_flags)
205810240SDaniel.Beauregard@Sun.COM {
205910240SDaniel.Beauregard@Sun.COM 	ql_srb_t		*sp = NULL;
206010240SDaniel.Beauregard@Sun.COM 	uint32_t		index, resp_identifier;
206110240SDaniel.Beauregard@Sun.COM 	uint32_t		get_handle = 10;
206210240SDaniel.Beauregard@Sun.COM 
206310240SDaniel.Beauregard@Sun.COM 	while (get_handle) {
206410240SDaniel.Beauregard@Sun.COM 		/* Get handle. */
206510240SDaniel.Beauregard@Sun.COM 		resp_identifier = ddi_get32(ha->hba_buf.acc_handle, pkt_handle);
206610240SDaniel.Beauregard@Sun.COM 		index = resp_identifier & OSC_INDEX_MASK;
206710240SDaniel.Beauregard@Sun.COM 		/* Validate handle. */
206810240SDaniel.Beauregard@Sun.COM 		if (index < MAX_OUTSTANDING_COMMANDS) {
206910240SDaniel.Beauregard@Sun.COM 			sp = ha->outstanding_cmds[index];
207010240SDaniel.Beauregard@Sun.COM 		}
207110240SDaniel.Beauregard@Sun.COM 
207210240SDaniel.Beauregard@Sun.COM 		if (sp != NULL) {
207310736SDaniel.Beauregard@Sun.COM 			EL(ha, "sp=%xh, resp_id=%xh, get=%d, index=%xh\n", sp,
207410736SDaniel.Beauregard@Sun.COM 			    resp_identifier, get_handle, index);
207510240SDaniel.Beauregard@Sun.COM 			break;
207610240SDaniel.Beauregard@Sun.COM 		} else {
207710240SDaniel.Beauregard@Sun.COM 			get_handle -= 1;
207810240SDaniel.Beauregard@Sun.COM 			drv_usecwait(10000);
207910240SDaniel.Beauregard@Sun.COM 			if (get_handle == 1) {
208010240SDaniel.Beauregard@Sun.COM 				/* Last chance, Sync whole DMA buffer. */
208110240SDaniel.Beauregard@Sun.COM 				(void) ddi_dma_sync(ha->hba_buf.dma_handle,
208210240SDaniel.Beauregard@Sun.COM 				    RESPONSE_Q_BUFFER_OFFSET,
208310240SDaniel.Beauregard@Sun.COM 				    RESPONSE_QUEUE_SIZE,
208410240SDaniel.Beauregard@Sun.COM 				    DDI_DMA_SYNC_FORKERNEL);
208510736SDaniel.Beauregard@Sun.COM 				EL(ha, "last chance DMA sync, index=%xh\n",
208610736SDaniel.Beauregard@Sun.COM 				    index);
208710240SDaniel.Beauregard@Sun.COM 			}
208810240SDaniel.Beauregard@Sun.COM 		}
208910240SDaniel.Beauregard@Sun.COM 	}
209010240SDaniel.Beauregard@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
209110240SDaniel.Beauregard@Sun.COM 
209210240SDaniel.Beauregard@Sun.COM 	return (sp);
209310240SDaniel.Beauregard@Sun.COM }
209410240SDaniel.Beauregard@Sun.COM 
209510240SDaniel.Beauregard@Sun.COM 
209610240SDaniel.Beauregard@Sun.COM /*
20977836SJohn.Forte@Sun.COM  * ql_status_error
20987836SJohn.Forte@Sun.COM  *	Processes received ISP status entry error.
20997836SJohn.Forte@Sun.COM  *
21007836SJohn.Forte@Sun.COM  * Input:
21017836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
21027836SJohn.Forte@Sun.COM  *	sp:		SRB pointer.
21037836SJohn.Forte@Sun.COM  *	pkt:		entry pointer.
21047836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
21057836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
21067836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
21077836SJohn.Forte@Sun.COM  *
21087836SJohn.Forte@Sun.COM  * Returns:
21097836SJohn.Forte@Sun.COM  *	BIT_0 = CS_RESET status received.
21107836SJohn.Forte@Sun.COM  *
21117836SJohn.Forte@Sun.COM  * Context:
21127836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
21137836SJohn.Forte@Sun.COM  */
21147836SJohn.Forte@Sun.COM /* ARGSUSED */
21157836SJohn.Forte@Sun.COM static int
ql_status_error(ql_adapter_state_t * ha,ql_srb_t * sp,sts_entry_t * pkt23,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)21167836SJohn.Forte@Sun.COM ql_status_error(ql_adapter_state_t *ha, ql_srb_t *sp, sts_entry_t *pkt23,
21177836SJohn.Forte@Sun.COM     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
21187836SJohn.Forte@Sun.COM {
21197836SJohn.Forte@Sun.COM 	uint32_t		sense_sz = 0;
21207836SJohn.Forte@Sun.COM 	uint32_t		cnt;
21217836SJohn.Forte@Sun.COM 	ql_tgt_t		*tq;
21227836SJohn.Forte@Sun.COM 	fcp_rsp_t		*fcpr;
21237836SJohn.Forte@Sun.COM 	struct fcp_rsp_info	*rsp;
21247836SJohn.Forte@Sun.COM 	int			rval = 0;
21257836SJohn.Forte@Sun.COM 
21267836SJohn.Forte@Sun.COM 	struct {
21277836SJohn.Forte@Sun.COM 		uint8_t		*rsp_info;
21287836SJohn.Forte@Sun.COM 		uint8_t		*req_sense_data;
21297836SJohn.Forte@Sun.COM 		uint32_t	residual_length;
21307836SJohn.Forte@Sun.COM 		uint32_t	fcp_residual_length;
21317836SJohn.Forte@Sun.COM 		uint32_t	rsp_info_length;
21327836SJohn.Forte@Sun.COM 		uint32_t	req_sense_length;
21337836SJohn.Forte@Sun.COM 		uint16_t	comp_status;
21347836SJohn.Forte@Sun.COM 		uint8_t		state_flags_l;
21357836SJohn.Forte@Sun.COM 		uint8_t		state_flags_h;
21367836SJohn.Forte@Sun.COM 		uint8_t		scsi_status_l;
21377836SJohn.Forte@Sun.COM 		uint8_t		scsi_status_h;
21387836SJohn.Forte@Sun.COM 	} sts;
21397836SJohn.Forte@Sun.COM 
21407836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
21417836SJohn.Forte@Sun.COM 
214211924SDaniel.Beauregard@Sun.COM 	if (CFG_IST(ha, CFG_CTRL_24258081)) {
21437836SJohn.Forte@Sun.COM 		sts_24xx_entry_t *pkt24 = (sts_24xx_entry_t *)pkt23;
21447836SJohn.Forte@Sun.COM 
21457836SJohn.Forte@Sun.COM 		/* Setup status. */
21467836SJohn.Forte@Sun.COM 		sts.comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
21477836SJohn.Forte@Sun.COM 		    &pkt24->comp_status);
21487836SJohn.Forte@Sun.COM 		sts.scsi_status_l = pkt24->scsi_status_l;
21497836SJohn.Forte@Sun.COM 		sts.scsi_status_h = pkt24->scsi_status_h;
21507836SJohn.Forte@Sun.COM 
21517836SJohn.Forte@Sun.COM 		/* Setup firmware residuals. */
21527836SJohn.Forte@Sun.COM 		sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
21537836SJohn.Forte@Sun.COM 		    ddi_get32(ha->hba_buf.acc_handle,
21547836SJohn.Forte@Sun.COM 		    (uint32_t *)&pkt24->residual_length) : 0;
21557836SJohn.Forte@Sun.COM 
21567836SJohn.Forte@Sun.COM 		/* Setup FCP residuals. */
21577836SJohn.Forte@Sun.COM 		sts.fcp_residual_length = sts.scsi_status_h &
21587836SJohn.Forte@Sun.COM 		    (FCP_RESID_UNDER | FCP_RESID_OVER) ?
21597836SJohn.Forte@Sun.COM 		    ddi_get32(ha->hba_buf.acc_handle,
21607836SJohn.Forte@Sun.COM 		    (uint32_t *)&pkt24->fcp_rsp_residual_count) : 0;
21617836SJohn.Forte@Sun.COM 
21627836SJohn.Forte@Sun.COM 		if ((sts.comp_status == CS_DATA_UNDERRUN) &&
21637836SJohn.Forte@Sun.COM 		    (sts.scsi_status_h & FCP_RESID_UNDER) &&
21647836SJohn.Forte@Sun.COM 		    (sts.residual_length != pkt24->fcp_rsp_residual_count)) {
21657836SJohn.Forte@Sun.COM 
21667836SJohn.Forte@Sun.COM 			EL(sp->ha, "mismatch resid's: fw=%xh, pkt=%xh\n",
21677836SJohn.Forte@Sun.COM 			    sts.residual_length,
21687836SJohn.Forte@Sun.COM 			    pkt24->fcp_rsp_residual_count);
21697836SJohn.Forte@Sun.COM 			sts.scsi_status_h = (uint8_t)
21707836SJohn.Forte@Sun.COM 			    (sts.scsi_status_h & ~FCP_RESID_UNDER);
21717836SJohn.Forte@Sun.COM 		}
21727836SJohn.Forte@Sun.COM 
21737836SJohn.Forte@Sun.COM 		/* Setup state flags. */
21747836SJohn.Forte@Sun.COM 		sts.state_flags_l = pkt24->state_flags_l;
21757836SJohn.Forte@Sun.COM 		sts.state_flags_h = pkt24->state_flags_h;
21767836SJohn.Forte@Sun.COM 
21777836SJohn.Forte@Sun.COM 		if (sp->fcp->fcp_data_len &&
21787836SJohn.Forte@Sun.COM 		    (sts.comp_status != CS_DATA_UNDERRUN ||
21797836SJohn.Forte@Sun.COM 		    sts.residual_length != sp->fcp->fcp_data_len)) {
21807836SJohn.Forte@Sun.COM 			sts.state_flags_h = (uint8_t)
21817836SJohn.Forte@Sun.COM 			    (sts.state_flags_h | SF_GOT_BUS |
21827836SJohn.Forte@Sun.COM 			    SF_GOT_TARGET | SF_SENT_CMD |
21837836SJohn.Forte@Sun.COM 			    SF_XFERRED_DATA | SF_GOT_STATUS);
21847836SJohn.Forte@Sun.COM 		} else {
21857836SJohn.Forte@Sun.COM 			sts.state_flags_h = (uint8_t)
21867836SJohn.Forte@Sun.COM 			    (sts.state_flags_h | SF_GOT_BUS |
21877836SJohn.Forte@Sun.COM 			    SF_GOT_TARGET | SF_SENT_CMD |
21887836SJohn.Forte@Sun.COM 			    SF_GOT_STATUS);
21897836SJohn.Forte@Sun.COM 		}
21907836SJohn.Forte@Sun.COM 		if (sp->fcp->fcp_cntl.cntl_write_data) {
21917836SJohn.Forte@Sun.COM 			sts.state_flags_l = (uint8_t)
21927836SJohn.Forte@Sun.COM 			    (sts.state_flags_l | SF_DATA_OUT);
21937836SJohn.Forte@Sun.COM 		} else if (sp->fcp->fcp_cntl.cntl_read_data) {
21947836SJohn.Forte@Sun.COM 			sts.state_flags_l = (uint8_t)
21957836SJohn.Forte@Sun.COM 			    (sts.state_flags_l | SF_DATA_IN);
21967836SJohn.Forte@Sun.COM 		}
21977836SJohn.Forte@Sun.COM 		if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) {
21987836SJohn.Forte@Sun.COM 			sts.state_flags_l = (uint8_t)
21997836SJohn.Forte@Sun.COM 			    (sts.state_flags_l | SF_HEAD_OF_Q);
22007836SJohn.Forte@Sun.COM 		} else if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) {
22017836SJohn.Forte@Sun.COM 			sts.state_flags_l = (uint8_t)
22027836SJohn.Forte@Sun.COM 			    (sts.state_flags_l | SF_ORDERED_Q);
22037836SJohn.Forte@Sun.COM 		} else if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) {
22047836SJohn.Forte@Sun.COM 			sts.state_flags_l = (uint8_t)
22057836SJohn.Forte@Sun.COM 			    (sts.state_flags_l | SF_SIMPLE_Q);
22067836SJohn.Forte@Sun.COM 		}
22077836SJohn.Forte@Sun.COM 
22087836SJohn.Forte@Sun.COM 		/* Setup FCP response info. */
22097836SJohn.Forte@Sun.COM 		sts.rsp_info = &pkt24->rsp_sense_data[0];
22107836SJohn.Forte@Sun.COM 		if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
22117836SJohn.Forte@Sun.COM 			sts.rsp_info_length = ddi_get32(ha->hba_buf.acc_handle,
22127836SJohn.Forte@Sun.COM 			    (uint32_t *)&pkt24->fcp_rsp_data_length);
22137836SJohn.Forte@Sun.COM 			if (sts.rsp_info_length >
22147836SJohn.Forte@Sun.COM 			    sizeof (struct fcp_rsp_info)) {
22157836SJohn.Forte@Sun.COM 				sts.rsp_info_length =
22167836SJohn.Forte@Sun.COM 				    sizeof (struct fcp_rsp_info);
22177836SJohn.Forte@Sun.COM 			}
22187836SJohn.Forte@Sun.COM 			for (cnt = 0; cnt < sts.rsp_info_length; cnt += 4) {
22197836SJohn.Forte@Sun.COM 				ql_chg_endian(sts.rsp_info + cnt, 4);
22207836SJohn.Forte@Sun.COM 			}
22217836SJohn.Forte@Sun.COM 		} else {
22227836SJohn.Forte@Sun.COM 			sts.rsp_info_length = 0;
22237836SJohn.Forte@Sun.COM 		}
22247836SJohn.Forte@Sun.COM 
22257836SJohn.Forte@Sun.COM 		/* Setup sense data. */
22267836SJohn.Forte@Sun.COM 		sts.req_sense_data =
22277836SJohn.Forte@Sun.COM 		    &pkt24->rsp_sense_data[sts.rsp_info_length];
22287836SJohn.Forte@Sun.COM 		if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
22297836SJohn.Forte@Sun.COM 			sts.req_sense_length =
22307836SJohn.Forte@Sun.COM 			    ddi_get32(ha->hba_buf.acc_handle,
22317836SJohn.Forte@Sun.COM 			    (uint32_t *)&pkt24->fcp_sense_length);
22327836SJohn.Forte@Sun.COM 			sts.state_flags_h = (uint8_t)
22337836SJohn.Forte@Sun.COM 			    (sts.state_flags_h | SF_ARQ_DONE);
22347836SJohn.Forte@Sun.COM 			sense_sz = (uint32_t)
22357836SJohn.Forte@Sun.COM 			    (((uintptr_t)pkt24 + sizeof (sts_24xx_entry_t)) -
22367836SJohn.Forte@Sun.COM 			    (uintptr_t)sts.req_sense_data);
22377836SJohn.Forte@Sun.COM 			for (cnt = 0; cnt < sense_sz; cnt += 4) {
22387836SJohn.Forte@Sun.COM 				ql_chg_endian(sts.req_sense_data + cnt, 4);
22397836SJohn.Forte@Sun.COM 			}
22407836SJohn.Forte@Sun.COM 		} else {
22417836SJohn.Forte@Sun.COM 			sts.req_sense_length = 0;
22427836SJohn.Forte@Sun.COM 		}
22437836SJohn.Forte@Sun.COM 	} else {
22447836SJohn.Forte@Sun.COM 		/* Setup status. */
22457836SJohn.Forte@Sun.COM 		sts.comp_status = (uint16_t)ddi_get16(
22467836SJohn.Forte@Sun.COM 		    ha->hba_buf.acc_handle, &pkt23->comp_status);
22477836SJohn.Forte@Sun.COM 		sts.scsi_status_l = pkt23->scsi_status_l;
22487836SJohn.Forte@Sun.COM 		sts.scsi_status_h = pkt23->scsi_status_h;
22497836SJohn.Forte@Sun.COM 
22507836SJohn.Forte@Sun.COM 		/* Setup firmware residuals. */
22517836SJohn.Forte@Sun.COM 		sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ?
22527836SJohn.Forte@Sun.COM 		    ddi_get32(ha->hba_buf.acc_handle,
22537836SJohn.Forte@Sun.COM 		    (uint32_t *)&pkt23->residual_length) : 0;
22547836SJohn.Forte@Sun.COM 
22557836SJohn.Forte@Sun.COM 		/* Setup FCP residuals. */
22567836SJohn.Forte@Sun.COM 		sts.fcp_residual_length = sts.scsi_status_h &
22577836SJohn.Forte@Sun.COM 		    (FCP_RESID_UNDER | FCP_RESID_OVER) ?
22587836SJohn.Forte@Sun.COM 		    sts.residual_length : 0;
22597836SJohn.Forte@Sun.COM 
22607836SJohn.Forte@Sun.COM 		/* Setup state flags. */
22617836SJohn.Forte@Sun.COM 		sts.state_flags_l = pkt23->state_flags_l;
22627836SJohn.Forte@Sun.COM 		sts.state_flags_h = pkt23->state_flags_h;
22637836SJohn.Forte@Sun.COM 
22647836SJohn.Forte@Sun.COM 		/* Setup FCP response info. */
22657836SJohn.Forte@Sun.COM 		sts.rsp_info = &pkt23->rsp_info[0];
22667836SJohn.Forte@Sun.COM 		if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) {
22677836SJohn.Forte@Sun.COM 			sts.rsp_info_length = ddi_get16(
22687836SJohn.Forte@Sun.COM 			    ha->hba_buf.acc_handle,
22697836SJohn.Forte@Sun.COM 			    (uint16_t *)&pkt23->rsp_info_length);
22707836SJohn.Forte@Sun.COM 			if (sts.rsp_info_length >
22717836SJohn.Forte@Sun.COM 			    sizeof (struct fcp_rsp_info)) {
22727836SJohn.Forte@Sun.COM 				sts.rsp_info_length =
22737836SJohn.Forte@Sun.COM 				    sizeof (struct fcp_rsp_info);
22747836SJohn.Forte@Sun.COM 			}
22757836SJohn.Forte@Sun.COM 		} else {
22767836SJohn.Forte@Sun.COM 			sts.rsp_info_length = 0;
22777836SJohn.Forte@Sun.COM 		}
22787836SJohn.Forte@Sun.COM 
22797836SJohn.Forte@Sun.COM 		/* Setup sense data. */
22807836SJohn.Forte@Sun.COM 		sts.req_sense_data = &pkt23->req_sense_data[0];
22817836SJohn.Forte@Sun.COM 		sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ?
22827836SJohn.Forte@Sun.COM 		    ddi_get16(ha->hba_buf.acc_handle,
22837836SJohn.Forte@Sun.COM 		    (uint16_t *)&pkt23->req_sense_length) : 0;
22847836SJohn.Forte@Sun.COM 	}
22857836SJohn.Forte@Sun.COM 
22867836SJohn.Forte@Sun.COM 	bzero(sp->pkt->pkt_resp, sp->pkt->pkt_rsplen);
22877836SJohn.Forte@Sun.COM 
22887836SJohn.Forte@Sun.COM 	fcpr = (fcp_rsp_t *)sp->pkt->pkt_resp;
22897836SJohn.Forte@Sun.COM 	rsp = (struct fcp_rsp_info *)(sp->pkt->pkt_resp +
22907836SJohn.Forte@Sun.COM 	    sizeof (fcp_rsp_t));
22917836SJohn.Forte@Sun.COM 
22927836SJohn.Forte@Sun.COM 	tq = sp->lun_queue->target_queue;
22937836SJohn.Forte@Sun.COM 
22947836SJohn.Forte@Sun.COM 	fcpr->fcp_u.fcp_status.scsi_status = sts.scsi_status_l;
22957836SJohn.Forte@Sun.COM 	if (sts.scsi_status_h & FCP_RSP_LEN_VALID) {
22967836SJohn.Forte@Sun.COM 		fcpr->fcp_u.fcp_status.rsp_len_set = 1;
22977836SJohn.Forte@Sun.COM 	}
22987836SJohn.Forte@Sun.COM 	if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
22997836SJohn.Forte@Sun.COM 		fcpr->fcp_u.fcp_status.sense_len_set = 1;
23007836SJohn.Forte@Sun.COM 	}
23017836SJohn.Forte@Sun.COM 	if (sts.scsi_status_h & FCP_RESID_OVER) {
23027836SJohn.Forte@Sun.COM 		fcpr->fcp_u.fcp_status.resid_over = 1;
23037836SJohn.Forte@Sun.COM 	}
23047836SJohn.Forte@Sun.COM 	if (sts.scsi_status_h & FCP_RESID_UNDER) {
23057836SJohn.Forte@Sun.COM 		fcpr->fcp_u.fcp_status.resid_under = 1;
23067836SJohn.Forte@Sun.COM 	}
23077836SJohn.Forte@Sun.COM 	fcpr->fcp_u.fcp_status.reserved_1 = 0;
23087836SJohn.Forte@Sun.COM 
23097836SJohn.Forte@Sun.COM 	/* Set ISP completion status */
23107836SJohn.Forte@Sun.COM 	sp->pkt->pkt_reason = sts.comp_status;
23117836SJohn.Forte@Sun.COM 
23127836SJohn.Forte@Sun.COM 	/* Update statistics. */
23137836SJohn.Forte@Sun.COM 	if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) &&
23147836SJohn.Forte@Sun.COM 	    (sp->pkt->pkt_rsplen > sizeof (fcp_rsp_t))) {
23157836SJohn.Forte@Sun.COM 
23167836SJohn.Forte@Sun.COM 		sense_sz = sp->pkt->pkt_rsplen - (uint32_t)sizeof (fcp_rsp_t);
23177836SJohn.Forte@Sun.COM 		if (sense_sz > sts.rsp_info_length) {
23187836SJohn.Forte@Sun.COM 			sense_sz = sts.rsp_info_length;
23197836SJohn.Forte@Sun.COM 		}
23207836SJohn.Forte@Sun.COM 
23217836SJohn.Forte@Sun.COM 		/* copy response information data. */
23227836SJohn.Forte@Sun.COM 		if (sense_sz) {
23237836SJohn.Forte@Sun.COM 			ddi_rep_get8(ha->hba_buf.acc_handle, (uint8_t *)rsp,
23247836SJohn.Forte@Sun.COM 			    sts.rsp_info, sense_sz, DDI_DEV_AUTOINCR);
23257836SJohn.Forte@Sun.COM 		}
23267836SJohn.Forte@Sun.COM 		fcpr->fcp_response_len = sense_sz;
23277836SJohn.Forte@Sun.COM 
23287836SJohn.Forte@Sun.COM 		rsp = (struct fcp_rsp_info *)((caddr_t)rsp +
23297836SJohn.Forte@Sun.COM 		    fcpr->fcp_response_len);
23307836SJohn.Forte@Sun.COM 
23317836SJohn.Forte@Sun.COM 		switch (*(sts.rsp_info + 3)) {
23327836SJohn.Forte@Sun.COM 		case FCP_NO_FAILURE:
23337836SJohn.Forte@Sun.COM 			break;
23347836SJohn.Forte@Sun.COM 		case FCP_DL_LEN_MISMATCH:
23357836SJohn.Forte@Sun.COM 			ha->adapter_stats->d_stats[lobyte(
23367836SJohn.Forte@Sun.COM 			    tq->loop_id)].dl_len_mismatches++;
23377836SJohn.Forte@Sun.COM 			break;
23387836SJohn.Forte@Sun.COM 		case FCP_CMND_INVALID:
23397836SJohn.Forte@Sun.COM 			break;
23407836SJohn.Forte@Sun.COM 		case FCP_DATA_RO_MISMATCH:
23417836SJohn.Forte@Sun.COM 			ha->adapter_stats->d_stats[lobyte(
23427836SJohn.Forte@Sun.COM 			    tq->loop_id)].data_ro_mismatches++;
23437836SJohn.Forte@Sun.COM 			break;
23447836SJohn.Forte@Sun.COM 		case FCP_TASK_MGMT_NOT_SUPPTD:
23457836SJohn.Forte@Sun.COM 			break;
23467836SJohn.Forte@Sun.COM 		case FCP_TASK_MGMT_FAILED:
23477836SJohn.Forte@Sun.COM 			ha->adapter_stats->d_stats[lobyte(
23487836SJohn.Forte@Sun.COM 			    tq->loop_id)].task_mgmt_failures++;
23497836SJohn.Forte@Sun.COM 			break;
23507836SJohn.Forte@Sun.COM 		default:
23517836SJohn.Forte@Sun.COM 			break;
23527836SJohn.Forte@Sun.COM 		}
23537836SJohn.Forte@Sun.COM 	} else {
23547836SJohn.Forte@Sun.COM 		/*
23557836SJohn.Forte@Sun.COM 		 * EL(sp->ha, "scsi_h=%xh, pkt_rsplen=%xh\n",
23567836SJohn.Forte@Sun.COM 		 *   sts.scsi_status_h, sp->pkt->pkt_rsplen);
23577836SJohn.Forte@Sun.COM 		 */
23587836SJohn.Forte@Sun.COM 		fcpr->fcp_response_len = 0;
23597836SJohn.Forte@Sun.COM 	}
23607836SJohn.Forte@Sun.COM 
23617836SJohn.Forte@Sun.COM 	/* Set reset status received. */
23627836SJohn.Forte@Sun.COM 	if (sts.comp_status == CS_RESET && LOOP_READY(ha)) {
23637836SJohn.Forte@Sun.COM 		rval |= BIT_0;
23647836SJohn.Forte@Sun.COM 	}
23657836SJohn.Forte@Sun.COM 
23667836SJohn.Forte@Sun.COM 	if (!(tq->flags & TQF_TAPE_DEVICE) &&
23677836SJohn.Forte@Sun.COM 	    (!(CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) ||
23687836SJohn.Forte@Sun.COM 	    ha->loop_down_abort_time < LOOP_DOWN_TIMER_START) &&
23697836SJohn.Forte@Sun.COM 	    ha->task_daemon_flags & LOOP_DOWN) {
23707836SJohn.Forte@Sun.COM 		EL(sp->ha, "Loop Not Ready Retry, d_id=%xh, lun=%xh\n",
23717836SJohn.Forte@Sun.COM 		    tq->d_id.b24, sp->lun_queue->lun_no);
23727836SJohn.Forte@Sun.COM 
23737836SJohn.Forte@Sun.COM 		/* Set retry status. */
23747836SJohn.Forte@Sun.COM 		sp->flags |= SRB_RETRY;
23757836SJohn.Forte@Sun.COM 	} else if (!(tq->flags & TQF_TAPE_DEVICE) &&
23767836SJohn.Forte@Sun.COM 	    tq->port_down_retry_count != 0 &&
23777836SJohn.Forte@Sun.COM 	    (sts.comp_status == CS_INCOMPLETE ||
23787836SJohn.Forte@Sun.COM 	    sts.comp_status == CS_PORT_UNAVAILABLE ||
23797836SJohn.Forte@Sun.COM 	    sts.comp_status == CS_PORT_LOGGED_OUT ||
23807836SJohn.Forte@Sun.COM 	    sts.comp_status == CS_PORT_CONFIG_CHG ||
23817836SJohn.Forte@Sun.COM 	    sts.comp_status == CS_PORT_BUSY)) {
23827836SJohn.Forte@Sun.COM 		EL(sp->ha, "Port Down Retry=%xh, d_id=%xh, lun=%xh, count=%d"
23837836SJohn.Forte@Sun.COM 		    "\n", sts.comp_status, tq->d_id.b24, sp->lun_queue->lun_no,
23847836SJohn.Forte@Sun.COM 		    tq->port_down_retry_count);
23857836SJohn.Forte@Sun.COM 
23867836SJohn.Forte@Sun.COM 		/* Set retry status. */
23877836SJohn.Forte@Sun.COM 		sp->flags |= SRB_RETRY;
23887836SJohn.Forte@Sun.COM 
23897836SJohn.Forte@Sun.COM 		if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) {
23907836SJohn.Forte@Sun.COM 			/* Acquire device queue lock. */
23917836SJohn.Forte@Sun.COM 			DEVICE_QUEUE_LOCK(tq);
23927836SJohn.Forte@Sun.COM 
23937836SJohn.Forte@Sun.COM 			tq->flags |= TQF_QUEUE_SUSPENDED;
23947836SJohn.Forte@Sun.COM 
23957836SJohn.Forte@Sun.COM 			/* Decrement port down count. */
23967836SJohn.Forte@Sun.COM 			if (CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) {
23977836SJohn.Forte@Sun.COM 				tq->port_down_retry_count--;
23987836SJohn.Forte@Sun.COM 			}
23997836SJohn.Forte@Sun.COM 
24007836SJohn.Forte@Sun.COM 			DEVICE_QUEUE_UNLOCK(tq);
24017836SJohn.Forte@Sun.COM 
24027836SJohn.Forte@Sun.COM 			if ((ha->task_daemon_flags & ABORT_ISP_ACTIVE)
24037836SJohn.Forte@Sun.COM 			    == 0 &&
24047836SJohn.Forte@Sun.COM 			    (sts.comp_status == CS_PORT_LOGGED_OUT ||
24057836SJohn.Forte@Sun.COM 			    sts.comp_status == CS_PORT_UNAVAILABLE)) {
24067836SJohn.Forte@Sun.COM 				sp->ha->adapter_stats->d_stats[lobyte(
24077836SJohn.Forte@Sun.COM 				    tq->loop_id)].logouts_recvd++;
24087836SJohn.Forte@Sun.COM 				ql_send_logo(sp->ha, tq, done_q);
24097836SJohn.Forte@Sun.COM 			}
24107836SJohn.Forte@Sun.COM 
24117836SJohn.Forte@Sun.COM 			ADAPTER_STATE_LOCK(ha);
24127836SJohn.Forte@Sun.COM 			if (ha->port_retry_timer == 0) {
24137836SJohn.Forte@Sun.COM 				if ((ha->port_retry_timer =
24147836SJohn.Forte@Sun.COM 				    ha->port_down_retry_delay) == 0) {
24157836SJohn.Forte@Sun.COM 					*set_flags |=
24167836SJohn.Forte@Sun.COM 					    PORT_RETRY_NEEDED;
24177836SJohn.Forte@Sun.COM 				}
24187836SJohn.Forte@Sun.COM 			}
24197836SJohn.Forte@Sun.COM 			ADAPTER_STATE_UNLOCK(ha);
24207836SJohn.Forte@Sun.COM 		}
24217836SJohn.Forte@Sun.COM 	} else if (!(tq->flags & TQF_TAPE_DEVICE) &&
24227836SJohn.Forte@Sun.COM 	    (sts.comp_status == CS_RESET ||
24237836SJohn.Forte@Sun.COM 	    (sts.comp_status == CS_QUEUE_FULL && tq->qfull_retry_count != 0) ||
24247836SJohn.Forte@Sun.COM 	    (sts.comp_status == CS_ABORTED && !(sp->flags & SRB_ABORTING)))) {
24257836SJohn.Forte@Sun.COM 		if (sts.comp_status == CS_RESET) {
24267836SJohn.Forte@Sun.COM 			EL(sp->ha, "Reset Retry, d_id=%xh, lun=%xh\n",
24277836SJohn.Forte@Sun.COM 			    tq->d_id.b24, sp->lun_queue->lun_no);
24287836SJohn.Forte@Sun.COM 		} else if (sts.comp_status == CS_QUEUE_FULL) {
24297836SJohn.Forte@Sun.COM 			EL(sp->ha, "Queue Full Retry, d_id=%xh, lun=%xh, "
24307836SJohn.Forte@Sun.COM 			    "cnt=%d\n", tq->d_id.b24, sp->lun_queue->lun_no,
24317836SJohn.Forte@Sun.COM 			    tq->qfull_retry_count);
24327836SJohn.Forte@Sun.COM 			if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) {
24337836SJohn.Forte@Sun.COM 				tq->flags |= TQF_QUEUE_SUSPENDED;
24347836SJohn.Forte@Sun.COM 
24357836SJohn.Forte@Sun.COM 				tq->qfull_retry_count--;
24367836SJohn.Forte@Sun.COM 
24377836SJohn.Forte@Sun.COM 				ADAPTER_STATE_LOCK(ha);
24387836SJohn.Forte@Sun.COM 				if (ha->port_retry_timer == 0) {
24397836SJohn.Forte@Sun.COM 					if ((ha->port_retry_timer =
24407836SJohn.Forte@Sun.COM 					    ha->qfull_retry_delay) ==
24417836SJohn.Forte@Sun.COM 					    0) {
24427836SJohn.Forte@Sun.COM 						*set_flags |=
24437836SJohn.Forte@Sun.COM 						    PORT_RETRY_NEEDED;
24447836SJohn.Forte@Sun.COM 					}
24457836SJohn.Forte@Sun.COM 				}
24467836SJohn.Forte@Sun.COM 				ADAPTER_STATE_UNLOCK(ha);
24477836SJohn.Forte@Sun.COM 			}
24487836SJohn.Forte@Sun.COM 		} else {
24497836SJohn.Forte@Sun.COM 			EL(sp->ha, "Abort Retry, d_id=%xh, lun=%xh\n",
24507836SJohn.Forte@Sun.COM 			    tq->d_id.b24, sp->lun_queue->lun_no);
24517836SJohn.Forte@Sun.COM 		}
24527836SJohn.Forte@Sun.COM 
24537836SJohn.Forte@Sun.COM 		/* Set retry status. */
24547836SJohn.Forte@Sun.COM 		sp->flags |= SRB_RETRY;
24557836SJohn.Forte@Sun.COM 	} else {
24567836SJohn.Forte@Sun.COM 		fcpr->fcp_resid =
24577836SJohn.Forte@Sun.COM 		    sts.fcp_residual_length > sp->fcp->fcp_data_len ?
24587836SJohn.Forte@Sun.COM 		    sp->fcp->fcp_data_len : sts.fcp_residual_length;
24597836SJohn.Forte@Sun.COM 
24607836SJohn.Forte@Sun.COM 		if ((sts.comp_status == CS_DATA_UNDERRUN) &&
24617836SJohn.Forte@Sun.COM 		    (sts.scsi_status_h & FCP_RESID_UNDER) == 0) {
24627836SJohn.Forte@Sun.COM 
24637836SJohn.Forte@Sun.COM 			if (sts.scsi_status_l == STATUS_CHECK) {
24647836SJohn.Forte@Sun.COM 				sp->pkt->pkt_reason = CS_COMPLETE;
24657836SJohn.Forte@Sun.COM 			} else {
24667836SJohn.Forte@Sun.COM 				EL(ha, "transport error - "
24677836SJohn.Forte@Sun.COM 				    "underrun & invalid resid\n");
24687836SJohn.Forte@Sun.COM 				EL(ha, "ssh=%xh, ssl=%xh\n",
24697836SJohn.Forte@Sun.COM 				    sts.scsi_status_h, sts.scsi_status_l);
24707836SJohn.Forte@Sun.COM 				sp->pkt->pkt_reason = CS_FCP_RESPONSE_ERROR;
24717836SJohn.Forte@Sun.COM 			}
24727836SJohn.Forte@Sun.COM 		}
24737836SJohn.Forte@Sun.COM 
24747836SJohn.Forte@Sun.COM 		/* Ignore firmware underrun error. */
24757836SJohn.Forte@Sun.COM 		if (sts.comp_status == CS_DATA_UNDERRUN &&
24767836SJohn.Forte@Sun.COM 		    (sts.scsi_status_h & FCP_RESID_UNDER ||
24777836SJohn.Forte@Sun.COM 		    (sts.scsi_status_l != STATUS_CHECK &&
24787836SJohn.Forte@Sun.COM 		    sts.scsi_status_l != STATUS_GOOD))) {
24797836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = CS_COMPLETE;
24807836SJohn.Forte@Sun.COM 		}
24817836SJohn.Forte@Sun.COM 
24827836SJohn.Forte@Sun.COM 		if (sp->pkt->pkt_reason != CS_COMPLETE) {
24837836SJohn.Forte@Sun.COM 			ha->xioctl->DeviceErrorCount++;
24847836SJohn.Forte@Sun.COM 			EL(sp->ha, "Cmplt status err = %xh, d_id=%xh, lun=%xh"
24857836SJohn.Forte@Sun.COM 			    "\n", sts.comp_status, tq->d_id.b24,
24867836SJohn.Forte@Sun.COM 			    sp->lun_queue->lun_no);
24877836SJohn.Forte@Sun.COM 		}
24887836SJohn.Forte@Sun.COM 
24897836SJohn.Forte@Sun.COM 		/* Set target request sense data. */
24907836SJohn.Forte@Sun.COM 		if (sts.scsi_status_l == STATUS_CHECK) {
24917836SJohn.Forte@Sun.COM 			if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
24927836SJohn.Forte@Sun.COM 
24937836SJohn.Forte@Sun.COM 				if (sp->pkt->pkt_reason == CS_COMPLETE &&
24947836SJohn.Forte@Sun.COM 				    sts.req_sense_data[2] != KEY_NO_SENSE &&
24957836SJohn.Forte@Sun.COM 				    sts.req_sense_data[2] !=
24967836SJohn.Forte@Sun.COM 				    KEY_UNIT_ATTENTION) {
24977836SJohn.Forte@Sun.COM 					ha->xioctl->DeviceErrorCount++;
24987836SJohn.Forte@Sun.COM 				}
24997836SJohn.Forte@Sun.COM 
25007836SJohn.Forte@Sun.COM 				sense_sz = sts.req_sense_length;
25017836SJohn.Forte@Sun.COM 
25027836SJohn.Forte@Sun.COM 				/* Insure data does not exceed buf. */
25037836SJohn.Forte@Sun.COM 				if (sp->pkt->pkt_rsplen <=
25047836SJohn.Forte@Sun.COM 				    (uint32_t)sizeof (fcp_rsp_t) +
25057836SJohn.Forte@Sun.COM 				    fcpr->fcp_response_len) {
25067836SJohn.Forte@Sun.COM 					sp->request_sense_length = 0;
25077836SJohn.Forte@Sun.COM 				} else {
25087836SJohn.Forte@Sun.COM 					sp->request_sense_length = (uint32_t)
25097836SJohn.Forte@Sun.COM 					    (sp->pkt->pkt_rsplen -
25107836SJohn.Forte@Sun.COM 					    sizeof (fcp_rsp_t) -
25117836SJohn.Forte@Sun.COM 					    fcpr->fcp_response_len);
25127836SJohn.Forte@Sun.COM 				}
25137836SJohn.Forte@Sun.COM 
25147836SJohn.Forte@Sun.COM 				if (sense_sz <
25157836SJohn.Forte@Sun.COM 				    sp->request_sense_length) {
25167836SJohn.Forte@Sun.COM 					sp->request_sense_length =
25177836SJohn.Forte@Sun.COM 					    sense_sz;
25187836SJohn.Forte@Sun.COM 				}
25197836SJohn.Forte@Sun.COM 
25207836SJohn.Forte@Sun.COM 				sp->request_sense_ptr = (caddr_t)rsp;
25217836SJohn.Forte@Sun.COM 
25227836SJohn.Forte@Sun.COM 				sense_sz = (uint32_t)
25237836SJohn.Forte@Sun.COM 				    (((uintptr_t)pkt23 +
25247836SJohn.Forte@Sun.COM 				    sizeof (sts_entry_t)) -
25257836SJohn.Forte@Sun.COM 				    (uintptr_t)sts.req_sense_data);
25267836SJohn.Forte@Sun.COM 				if (sp->request_sense_length <
25277836SJohn.Forte@Sun.COM 				    sense_sz) {
25287836SJohn.Forte@Sun.COM 					sense_sz =
25297836SJohn.Forte@Sun.COM 					    sp->request_sense_length;
25307836SJohn.Forte@Sun.COM 				}
25317836SJohn.Forte@Sun.COM 
25327836SJohn.Forte@Sun.COM 				fcpr->fcp_sense_len = sense_sz;
25337836SJohn.Forte@Sun.COM 
25347836SJohn.Forte@Sun.COM 				/* Move sense data. */
25357836SJohn.Forte@Sun.COM 				ddi_rep_get8(ha->hba_buf.acc_handle,
25367836SJohn.Forte@Sun.COM 				    (uint8_t *)sp->request_sense_ptr,
25377836SJohn.Forte@Sun.COM 				    sts.req_sense_data,
25387836SJohn.Forte@Sun.COM 				    (size_t)sense_sz,
25397836SJohn.Forte@Sun.COM 				    DDI_DEV_AUTOINCR);
25407836SJohn.Forte@Sun.COM 
25417836SJohn.Forte@Sun.COM 				sp->request_sense_ptr += sense_sz;
25427836SJohn.Forte@Sun.COM 				sp->request_sense_length -= sense_sz;
254311924SDaniel.Beauregard@Sun.COM 				if (sp->request_sense_length != 0 &&
254411924SDaniel.Beauregard@Sun.COM 				    !(CFG_IST(ha, CFG_CTRL_8021))) {
25457836SJohn.Forte@Sun.COM 					ha->status_srb = sp;
25467836SJohn.Forte@Sun.COM 				}
25477836SJohn.Forte@Sun.COM 			}
25487836SJohn.Forte@Sun.COM 
25497836SJohn.Forte@Sun.COM 			if (sense_sz != 0) {
25507836SJohn.Forte@Sun.COM 				EL(sp->ha, "check condition sense data, "
25517836SJohn.Forte@Sun.COM 				    "d_id=%xh, lun=%xh\n%2xh%3xh%3xh%3xh"
25527836SJohn.Forte@Sun.COM 				    "%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh"
25537836SJohn.Forte@Sun.COM 				    "%3xh%3xh%3xh%3xh%3xh\n", tq->d_id.b24,
25547836SJohn.Forte@Sun.COM 				    sp->lun_queue->lun_no,
25557836SJohn.Forte@Sun.COM 				    sts.req_sense_data[0],
25567836SJohn.Forte@Sun.COM 				    sts.req_sense_data[1],
25577836SJohn.Forte@Sun.COM 				    sts.req_sense_data[2],
25587836SJohn.Forte@Sun.COM 				    sts.req_sense_data[3],
25597836SJohn.Forte@Sun.COM 				    sts.req_sense_data[4],
25607836SJohn.Forte@Sun.COM 				    sts.req_sense_data[5],
25617836SJohn.Forte@Sun.COM 				    sts.req_sense_data[6],
25627836SJohn.Forte@Sun.COM 				    sts.req_sense_data[7],
25637836SJohn.Forte@Sun.COM 				    sts.req_sense_data[8],
25647836SJohn.Forte@Sun.COM 				    sts.req_sense_data[9],
25657836SJohn.Forte@Sun.COM 				    sts.req_sense_data[10],
25667836SJohn.Forte@Sun.COM 				    sts.req_sense_data[11],
25677836SJohn.Forte@Sun.COM 				    sts.req_sense_data[12],
25687836SJohn.Forte@Sun.COM 				    sts.req_sense_data[13],
25697836SJohn.Forte@Sun.COM 				    sts.req_sense_data[14],
25707836SJohn.Forte@Sun.COM 				    sts.req_sense_data[15],
25717836SJohn.Forte@Sun.COM 				    sts.req_sense_data[16],
25727836SJohn.Forte@Sun.COM 				    sts.req_sense_data[17]);
25737836SJohn.Forte@Sun.COM 			} else {
25747836SJohn.Forte@Sun.COM 				EL(sp->ha, "check condition, d_id=%xh, lun=%xh"
25757836SJohn.Forte@Sun.COM 				    "\n", tq->d_id.b24, sp->lun_queue->lun_no);
25767836SJohn.Forte@Sun.COM 			}
25777836SJohn.Forte@Sun.COM 		}
25787836SJohn.Forte@Sun.COM 	}
25797836SJohn.Forte@Sun.COM 
25807836SJohn.Forte@Sun.COM 	/* Set completed status. */
25817836SJohn.Forte@Sun.COM 	sp->flags |= SRB_ISP_COMPLETED;
25827836SJohn.Forte@Sun.COM 
25837836SJohn.Forte@Sun.COM 	/* Place command on done queue. */
25847836SJohn.Forte@Sun.COM 	if (ha->status_srb == NULL) {
25857836SJohn.Forte@Sun.COM 		ql_add_link_b(done_q, &sp->cmd);
25867836SJohn.Forte@Sun.COM 	}
25877836SJohn.Forte@Sun.COM 
25887836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
25897836SJohn.Forte@Sun.COM 
25907836SJohn.Forte@Sun.COM 	return (rval);
25917836SJohn.Forte@Sun.COM }
25927836SJohn.Forte@Sun.COM 
25937836SJohn.Forte@Sun.COM /*
25947836SJohn.Forte@Sun.COM  * ql_status_cont_entry
25957836SJohn.Forte@Sun.COM  *	Processes status continuation entry.
25967836SJohn.Forte@Sun.COM  *
25977836SJohn.Forte@Sun.COM  * Input:
25987836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
25997836SJohn.Forte@Sun.COM  *	pkt:		entry pointer.
26007836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
26017836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
26027836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
26037836SJohn.Forte@Sun.COM  *
26047836SJohn.Forte@Sun.COM  * Context:
26057836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
26067836SJohn.Forte@Sun.COM  */
26077836SJohn.Forte@Sun.COM /* ARGSUSED */
26087836SJohn.Forte@Sun.COM static void
ql_status_cont_entry(ql_adapter_state_t * ha,sts_cont_entry_t * pkt,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)26097836SJohn.Forte@Sun.COM ql_status_cont_entry(ql_adapter_state_t *ha, sts_cont_entry_t *pkt,
26107836SJohn.Forte@Sun.COM     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
26117836SJohn.Forte@Sun.COM {
26127836SJohn.Forte@Sun.COM 	uint32_t	sense_sz, index;
26137836SJohn.Forte@Sun.COM 	ql_srb_t	*sp = ha->status_srb;
26147836SJohn.Forte@Sun.COM 
26157836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
26167836SJohn.Forte@Sun.COM 
26177836SJohn.Forte@Sun.COM 	if (sp != NULL && sp->request_sense_length) {
26187836SJohn.Forte@Sun.COM 		if (sp->request_sense_length > sizeof (pkt->req_sense_data)) {
26197836SJohn.Forte@Sun.COM 			sense_sz = sizeof (pkt->req_sense_data);
26207836SJohn.Forte@Sun.COM 		} else {
26217836SJohn.Forte@Sun.COM 			sense_sz = sp->request_sense_length;
26227836SJohn.Forte@Sun.COM 		}
26237836SJohn.Forte@Sun.COM 
262411924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_24258081)) {
26257836SJohn.Forte@Sun.COM 			for (index = 0; index < sense_sz; index += 4) {
26267836SJohn.Forte@Sun.COM 				ql_chg_endian((uint8_t *)
26277836SJohn.Forte@Sun.COM 				    &pkt->req_sense_data[0] + index, 4);
26287836SJohn.Forte@Sun.COM 			}
26297836SJohn.Forte@Sun.COM 		}
26307836SJohn.Forte@Sun.COM 
26317836SJohn.Forte@Sun.COM 		/* Move sense data. */
26327836SJohn.Forte@Sun.COM 		ddi_rep_get8(ha->hba_buf.acc_handle,
26337836SJohn.Forte@Sun.COM 		    (uint8_t *)sp->request_sense_ptr,
26347836SJohn.Forte@Sun.COM 		    (uint8_t *)&pkt->req_sense_data[0], (size_t)sense_sz,
26357836SJohn.Forte@Sun.COM 		    DDI_DEV_AUTOINCR);
26367836SJohn.Forte@Sun.COM 
26377836SJohn.Forte@Sun.COM 		sp->request_sense_ptr += sense_sz;
26387836SJohn.Forte@Sun.COM 		sp->request_sense_length -= sense_sz;
26397836SJohn.Forte@Sun.COM 
26407836SJohn.Forte@Sun.COM 		/* Place command on done queue. */
26417836SJohn.Forte@Sun.COM 		if (sp->request_sense_length == 0) {
26427836SJohn.Forte@Sun.COM 			ql_add_link_b(done_q, &sp->cmd);
26437836SJohn.Forte@Sun.COM 			ha->status_srb = NULL;
26447836SJohn.Forte@Sun.COM 		}
26457836SJohn.Forte@Sun.COM 	}
26467836SJohn.Forte@Sun.COM 
26477836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
26487836SJohn.Forte@Sun.COM }
26497836SJohn.Forte@Sun.COM 
26507836SJohn.Forte@Sun.COM /*
26517836SJohn.Forte@Sun.COM  * ql_ip_entry
26527836SJohn.Forte@Sun.COM  *	Processes received ISP IP entry.
26537836SJohn.Forte@Sun.COM  *
26547836SJohn.Forte@Sun.COM  * Input:
26557836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
26567836SJohn.Forte@Sun.COM  *	pkt:		entry pointer.
26577836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
26587836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
26597836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
26607836SJohn.Forte@Sun.COM  *
26617836SJohn.Forte@Sun.COM  * Context:
26627836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
26637836SJohn.Forte@Sun.COM  */
26647836SJohn.Forte@Sun.COM /* ARGSUSED */
26657836SJohn.Forte@Sun.COM static void
ql_ip_entry(ql_adapter_state_t * ha,ip_entry_t * pkt23,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)26667836SJohn.Forte@Sun.COM ql_ip_entry(ql_adapter_state_t *ha, ip_entry_t *pkt23, ql_head_t *done_q,
26677836SJohn.Forte@Sun.COM     uint32_t *set_flags, uint32_t *reset_flags)
26687836SJohn.Forte@Sun.COM {
26697836SJohn.Forte@Sun.COM 	ql_srb_t	*sp;
267010240SDaniel.Beauregard@Sun.COM 	uint32_t	index, resp_identifier;
26717836SJohn.Forte@Sun.COM 	ql_tgt_t	*tq;
26727836SJohn.Forte@Sun.COM 
26737836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
26747836SJohn.Forte@Sun.COM 
267510240SDaniel.Beauregard@Sun.COM 	/* Validate the response entry handle. */
267610240SDaniel.Beauregard@Sun.COM 	resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle);
267710240SDaniel.Beauregard@Sun.COM 	index = resp_identifier & OSC_INDEX_MASK;
267810240SDaniel.Beauregard@Sun.COM 	if (index < MAX_OUTSTANDING_COMMANDS) {
267910240SDaniel.Beauregard@Sun.COM 		/* the index seems reasonable */
268010240SDaniel.Beauregard@Sun.COM 		sp = ha->outstanding_cmds[index];
268110240SDaniel.Beauregard@Sun.COM 		if (sp != NULL) {
268210240SDaniel.Beauregard@Sun.COM 			if (sp->handle == resp_identifier) {
268310240SDaniel.Beauregard@Sun.COM 				/* Neo, you're the one... */
268410240SDaniel.Beauregard@Sun.COM 				ha->outstanding_cmds[index] = NULL;
268510240SDaniel.Beauregard@Sun.COM 				sp->handle = 0;
268610240SDaniel.Beauregard@Sun.COM 				sp->flags &= ~SRB_IN_TOKEN_ARRAY;
268710240SDaniel.Beauregard@Sun.COM 			} else {
268810240SDaniel.Beauregard@Sun.COM 				EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
268910240SDaniel.Beauregard@Sun.COM 				    resp_identifier, sp->handle);
269010240SDaniel.Beauregard@Sun.COM 				sp = NULL;
269110240SDaniel.Beauregard@Sun.COM 				ql_signal_abort(ha, set_flags);
269210240SDaniel.Beauregard@Sun.COM 			}
269310240SDaniel.Beauregard@Sun.COM 		} else {
269410240SDaniel.Beauregard@Sun.COM 			sp = ql_verify_preprocessed_cmd(ha,
269510240SDaniel.Beauregard@Sun.COM 			    (uint32_t *)&pkt23->handle, set_flags, reset_flags);
269610240SDaniel.Beauregard@Sun.COM 		}
269710240SDaniel.Beauregard@Sun.COM 	} else {
269810240SDaniel.Beauregard@Sun.COM 		EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
269910240SDaniel.Beauregard@Sun.COM 		    index, resp_identifier);
270010240SDaniel.Beauregard@Sun.COM 		ql_signal_abort(ha, set_flags);
270110240SDaniel.Beauregard@Sun.COM 	}
270210240SDaniel.Beauregard@Sun.COM 
270310240SDaniel.Beauregard@Sun.COM 	if (sp != NULL) {
27047836SJohn.Forte@Sun.COM 		tq = sp->lun_queue->target_queue;
27057836SJohn.Forte@Sun.COM 
27067836SJohn.Forte@Sun.COM 		/* Set ISP completion status */
270711924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_24258081)) {
27087836SJohn.Forte@Sun.COM 			ip_cmd_entry_t	*pkt24 = (ip_cmd_entry_t *)pkt23;
27097836SJohn.Forte@Sun.COM 
27107836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = ddi_get16(
27117836SJohn.Forte@Sun.COM 			    ha->hba_buf.acc_handle, &pkt24->hdl_status);
27127836SJohn.Forte@Sun.COM 		} else {
27137836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = ddi_get16(
27147836SJohn.Forte@Sun.COM 			    ha->hba_buf.acc_handle, &pkt23->comp_status);
27157836SJohn.Forte@Sun.COM 		}
27167836SJohn.Forte@Sun.COM 
27177836SJohn.Forte@Sun.COM 		if (ha->task_daemon_flags & LOOP_DOWN) {
27187836SJohn.Forte@Sun.COM 			EL(ha, "Loop Not Ready Retry, d_id=%xh\n",
27197836SJohn.Forte@Sun.COM 			    tq->d_id.b24);
27207836SJohn.Forte@Sun.COM 
27217836SJohn.Forte@Sun.COM 			/* Set retry status. */
27227836SJohn.Forte@Sun.COM 			sp->flags |= SRB_RETRY;
27237836SJohn.Forte@Sun.COM 
27247836SJohn.Forte@Sun.COM 		} else if (tq->port_down_retry_count &&
27257836SJohn.Forte@Sun.COM 		    (sp->pkt->pkt_reason == CS_INCOMPLETE ||
27267836SJohn.Forte@Sun.COM 		    sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE ||
27277836SJohn.Forte@Sun.COM 		    sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT ||
27287836SJohn.Forte@Sun.COM 		    sp->pkt->pkt_reason == CS_PORT_CONFIG_CHG ||
27297836SJohn.Forte@Sun.COM 		    sp->pkt->pkt_reason == CS_PORT_BUSY)) {
27307836SJohn.Forte@Sun.COM 			EL(ha, "Port Down Retry=%xh, d_id=%xh, count=%d\n",
27317836SJohn.Forte@Sun.COM 			    sp->pkt->pkt_reason, tq->d_id.b24,
27327836SJohn.Forte@Sun.COM 			    tq->port_down_retry_count);
27337836SJohn.Forte@Sun.COM 
27347836SJohn.Forte@Sun.COM 			/* Set retry status. */
27357836SJohn.Forte@Sun.COM 			sp->flags |= SRB_RETRY;
27367836SJohn.Forte@Sun.COM 
27377836SJohn.Forte@Sun.COM 			if (sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT ||
27387836SJohn.Forte@Sun.COM 			    sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE) {
27397836SJohn.Forte@Sun.COM 				ha->adapter_stats->d_stats[lobyte(
27407836SJohn.Forte@Sun.COM 				    tq->loop_id)].logouts_recvd++;
27417836SJohn.Forte@Sun.COM 				ql_send_logo(ha, tq, done_q);
27427836SJohn.Forte@Sun.COM 			}
27437836SJohn.Forte@Sun.COM 
27447836SJohn.Forte@Sun.COM 			/* Acquire device queue lock. */
27457836SJohn.Forte@Sun.COM 			DEVICE_QUEUE_LOCK(tq);
27467836SJohn.Forte@Sun.COM 
27477836SJohn.Forte@Sun.COM 			if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) {
27487836SJohn.Forte@Sun.COM 				tq->flags |= TQF_QUEUE_SUSPENDED;
27497836SJohn.Forte@Sun.COM 
27507836SJohn.Forte@Sun.COM 				tq->port_down_retry_count--;
27517836SJohn.Forte@Sun.COM 
27527836SJohn.Forte@Sun.COM 				ADAPTER_STATE_LOCK(ha);
27537836SJohn.Forte@Sun.COM 				if (ha->port_retry_timer == 0) {
27547836SJohn.Forte@Sun.COM 					if ((ha->port_retry_timer =
27557836SJohn.Forte@Sun.COM 					    ha->port_down_retry_delay) == 0) {
27567836SJohn.Forte@Sun.COM 						*set_flags |=
27577836SJohn.Forte@Sun.COM 						    PORT_RETRY_NEEDED;
27587836SJohn.Forte@Sun.COM 					}
27597836SJohn.Forte@Sun.COM 				}
27607836SJohn.Forte@Sun.COM 				ADAPTER_STATE_UNLOCK(ha);
27617836SJohn.Forte@Sun.COM 			}
27627836SJohn.Forte@Sun.COM 
27637836SJohn.Forte@Sun.COM 			/* Release device queue specific lock. */
27647836SJohn.Forte@Sun.COM 			DEVICE_QUEUE_UNLOCK(tq);
27657836SJohn.Forte@Sun.COM 
27667836SJohn.Forte@Sun.COM 		} else if (sp->pkt->pkt_reason == CS_RESET) {
27677836SJohn.Forte@Sun.COM 			EL(ha, "Reset Retry, d_id=%xh\n", tq->d_id.b24);
27687836SJohn.Forte@Sun.COM 
27697836SJohn.Forte@Sun.COM 			/* Set retry status. */
27707836SJohn.Forte@Sun.COM 			sp->flags |= SRB_RETRY;
27717836SJohn.Forte@Sun.COM 		} else {
27727836SJohn.Forte@Sun.COM 			if (sp->pkt->pkt_reason != CS_COMPLETE) {
27737836SJohn.Forte@Sun.COM 				EL(ha, "Cmplt status err=%xh, d_id=%xh\n",
27747836SJohn.Forte@Sun.COM 				    sp->pkt->pkt_reason, tq->d_id.b24);
27757836SJohn.Forte@Sun.COM 			}
27767836SJohn.Forte@Sun.COM 		}
27777836SJohn.Forte@Sun.COM 
27787836SJohn.Forte@Sun.COM 		/* Set completed status. */
27797836SJohn.Forte@Sun.COM 		sp->flags |= SRB_ISP_COMPLETED;
27807836SJohn.Forte@Sun.COM 
27817836SJohn.Forte@Sun.COM 		ql_add_link_b(done_q, &sp->cmd);
27827836SJohn.Forte@Sun.COM 
27837836SJohn.Forte@Sun.COM 	}
27847836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
27857836SJohn.Forte@Sun.COM }
27867836SJohn.Forte@Sun.COM 
27877836SJohn.Forte@Sun.COM /*
27887836SJohn.Forte@Sun.COM  * ql_ip_rcv_entry
27897836SJohn.Forte@Sun.COM  *	Processes received ISP IP buffers entry.
27907836SJohn.Forte@Sun.COM  *
27917836SJohn.Forte@Sun.COM  * Input:
27927836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
27937836SJohn.Forte@Sun.COM  *	pkt:		entry pointer.
27947836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
27957836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
27967836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
27977836SJohn.Forte@Sun.COM  *
27987836SJohn.Forte@Sun.COM  * Context:
27997836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
28007836SJohn.Forte@Sun.COM  */
28017836SJohn.Forte@Sun.COM /* ARGSUSED */
28027836SJohn.Forte@Sun.COM static void
ql_ip_rcv_entry(ql_adapter_state_t * ha,ip_rcv_entry_t * pkt,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)28037836SJohn.Forte@Sun.COM ql_ip_rcv_entry(ql_adapter_state_t *ha, ip_rcv_entry_t *pkt,
28047836SJohn.Forte@Sun.COM     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
28057836SJohn.Forte@Sun.COM {
28067836SJohn.Forte@Sun.COM 	port_id_t	s_id;
28077836SJohn.Forte@Sun.COM 	uint16_t	index;
28087836SJohn.Forte@Sun.COM 	uint8_t		cnt;
28097836SJohn.Forte@Sun.COM 	ql_tgt_t	*tq;
28107836SJohn.Forte@Sun.COM 
28117836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
28127836SJohn.Forte@Sun.COM 
28137836SJohn.Forte@Sun.COM 	/* Locate device queue. */
28147836SJohn.Forte@Sun.COM 	s_id.b.al_pa = pkt->s_id[0];
28157836SJohn.Forte@Sun.COM 	s_id.b.area = pkt->s_id[1];
28167836SJohn.Forte@Sun.COM 	s_id.b.domain = pkt->s_id[2];
28177836SJohn.Forte@Sun.COM 	if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
28187836SJohn.Forte@Sun.COM 		EL(ha, "Unknown IP device ID=%xh\n", s_id.b24);
28197836SJohn.Forte@Sun.COM 		return;
28207836SJohn.Forte@Sun.COM 	}
28217836SJohn.Forte@Sun.COM 
28227836SJohn.Forte@Sun.COM 	tq->ub_sequence_length = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
28237836SJohn.Forte@Sun.COM 	    &pkt->seq_length);
28247836SJohn.Forte@Sun.COM 	tq->ub_total_seg_cnt = pkt->segment_count;
28257836SJohn.Forte@Sun.COM 	tq->ub_seq_id = ++ha->ub_seq_id;
28267836SJohn.Forte@Sun.COM 	tq->ub_seq_cnt = 0;
28277836SJohn.Forte@Sun.COM 	tq->ub_frame_ro = 0;
28287836SJohn.Forte@Sun.COM 	tq->ub_loop_id = pkt->loop_id;
28297836SJohn.Forte@Sun.COM 	ha->rcv_dev_q = tq;
28307836SJohn.Forte@Sun.COM 
28317836SJohn.Forte@Sun.COM 	for (cnt = 0; cnt < IP_RCVBUF_HANDLES && tq->ub_seq_cnt <
28327836SJohn.Forte@Sun.COM 	    tq->ub_total_seg_cnt; cnt++) {
28337836SJohn.Forte@Sun.COM 
28347836SJohn.Forte@Sun.COM 		index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
28357836SJohn.Forte@Sun.COM 		    &pkt->buffer_handle[cnt]);
28367836SJohn.Forte@Sun.COM 
28377836SJohn.Forte@Sun.COM 		if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
28387836SJohn.Forte@Sun.COM 			EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
28397836SJohn.Forte@Sun.COM 			*set_flags |= ISP_ABORT_NEEDED;
28407836SJohn.Forte@Sun.COM 			break;
28417836SJohn.Forte@Sun.COM 		}
28427836SJohn.Forte@Sun.COM 	}
28437836SJohn.Forte@Sun.COM 
28447836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
28457836SJohn.Forte@Sun.COM }
28467836SJohn.Forte@Sun.COM 
28477836SJohn.Forte@Sun.COM /*
28487836SJohn.Forte@Sun.COM  * ql_ip_rcv_cont_entry
28497836SJohn.Forte@Sun.COM  *	Processes received ISP IP buffers continuation entry.
28507836SJohn.Forte@Sun.COM  *
28517836SJohn.Forte@Sun.COM  * Input:
28527836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
28537836SJohn.Forte@Sun.COM  *	pkt:		entry pointer.
28547836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
28557836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
28567836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
28577836SJohn.Forte@Sun.COM  *
28587836SJohn.Forte@Sun.COM  * Context:
28597836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
28607836SJohn.Forte@Sun.COM  */
28617836SJohn.Forte@Sun.COM /* ARGSUSED */
28627836SJohn.Forte@Sun.COM static void
ql_ip_rcv_cont_entry(ql_adapter_state_t * ha,ip_rcv_cont_entry_t * pkt,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)28637836SJohn.Forte@Sun.COM ql_ip_rcv_cont_entry(ql_adapter_state_t *ha, ip_rcv_cont_entry_t *pkt,
28647836SJohn.Forte@Sun.COM     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
28657836SJohn.Forte@Sun.COM {
28667836SJohn.Forte@Sun.COM 	uint16_t	index;
28677836SJohn.Forte@Sun.COM 	uint8_t		cnt;
28687836SJohn.Forte@Sun.COM 	ql_tgt_t	*tq;
28697836SJohn.Forte@Sun.COM 
28707836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
28717836SJohn.Forte@Sun.COM 
28727836SJohn.Forte@Sun.COM 	if ((tq = ha->rcv_dev_q) == NULL) {
28737836SJohn.Forte@Sun.COM 		EL(ha, "No IP receive device\n");
28747836SJohn.Forte@Sun.COM 		return;
28757836SJohn.Forte@Sun.COM 	}
28767836SJohn.Forte@Sun.COM 
28777836SJohn.Forte@Sun.COM 	for (cnt = 0; cnt < IP_RCVBUF_CONT_HANDLES &&
28787836SJohn.Forte@Sun.COM 	    tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) {
28797836SJohn.Forte@Sun.COM 
28807836SJohn.Forte@Sun.COM 		index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
28817836SJohn.Forte@Sun.COM 		    &pkt->buffer_handle[cnt]);
28827836SJohn.Forte@Sun.COM 
28837836SJohn.Forte@Sun.COM 		if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
28847836SJohn.Forte@Sun.COM 			EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
28857836SJohn.Forte@Sun.COM 			*set_flags |= ISP_ABORT_NEEDED;
28867836SJohn.Forte@Sun.COM 			break;
28877836SJohn.Forte@Sun.COM 		}
28887836SJohn.Forte@Sun.COM 	}
28897836SJohn.Forte@Sun.COM 
28907836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
28917836SJohn.Forte@Sun.COM }
28927836SJohn.Forte@Sun.COM 
28937836SJohn.Forte@Sun.COM /*
28947836SJohn.Forte@Sun.COM  * ip_rcv_24xx_entry_t
28957836SJohn.Forte@Sun.COM  *	Processes received ISP24xx IP buffers entry.
28967836SJohn.Forte@Sun.COM  *
28977836SJohn.Forte@Sun.COM  * Input:
28987836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
28997836SJohn.Forte@Sun.COM  *	pkt:		entry pointer.
29007836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
29017836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
29027836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
29037836SJohn.Forte@Sun.COM  *
29047836SJohn.Forte@Sun.COM  * Context:
29057836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
29067836SJohn.Forte@Sun.COM  */
29077836SJohn.Forte@Sun.COM /* ARGSUSED */
29087836SJohn.Forte@Sun.COM static void
ql_ip_24xx_rcv_entry(ql_adapter_state_t * ha,ip_rcv_24xx_entry_t * pkt,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)29097836SJohn.Forte@Sun.COM ql_ip_24xx_rcv_entry(ql_adapter_state_t *ha, ip_rcv_24xx_entry_t *pkt,
29107836SJohn.Forte@Sun.COM     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
29117836SJohn.Forte@Sun.COM {
29127836SJohn.Forte@Sun.COM 	port_id_t	s_id;
29137836SJohn.Forte@Sun.COM 	uint16_t	index;
29147836SJohn.Forte@Sun.COM 	uint8_t		cnt;
29157836SJohn.Forte@Sun.COM 	ql_tgt_t	*tq;
29167836SJohn.Forte@Sun.COM 
29177836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
29187836SJohn.Forte@Sun.COM 
29197836SJohn.Forte@Sun.COM 	/* Locate device queue. */
29207836SJohn.Forte@Sun.COM 	s_id.b.al_pa = pkt->s_id[0];
29217836SJohn.Forte@Sun.COM 	s_id.b.area = pkt->s_id[1];
29227836SJohn.Forte@Sun.COM 	s_id.b.domain = pkt->s_id[2];
29237836SJohn.Forte@Sun.COM 	if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) {
29247836SJohn.Forte@Sun.COM 		EL(ha, "Unknown IP device ID=%xh\n", s_id.b24);
29257836SJohn.Forte@Sun.COM 		return;
29267836SJohn.Forte@Sun.COM 	}
29277836SJohn.Forte@Sun.COM 
29287836SJohn.Forte@Sun.COM 	if (tq->ub_total_seg_cnt == 0) {
29297836SJohn.Forte@Sun.COM 		tq->ub_sequence_length = (uint16_t)ddi_get16(
29307836SJohn.Forte@Sun.COM 		    ha->hba_buf.acc_handle, &pkt->seq_length);
29317836SJohn.Forte@Sun.COM 		tq->ub_total_seg_cnt = pkt->segment_count;
29327836SJohn.Forte@Sun.COM 		tq->ub_seq_id = ++ha->ub_seq_id;
29337836SJohn.Forte@Sun.COM 		tq->ub_seq_cnt = 0;
29347836SJohn.Forte@Sun.COM 		tq->ub_frame_ro = 0;
29357836SJohn.Forte@Sun.COM 		tq->ub_loop_id = (uint16_t)ddi_get16(
29367836SJohn.Forte@Sun.COM 		    ha->hba_buf.acc_handle, &pkt->n_port_hdl);
29377836SJohn.Forte@Sun.COM 	}
29387836SJohn.Forte@Sun.COM 
29397836SJohn.Forte@Sun.COM 	for (cnt = 0; cnt < IP_24XX_RCVBUF_HANDLES && tq->ub_seq_cnt <
29407836SJohn.Forte@Sun.COM 	    tq->ub_total_seg_cnt; cnt++) {
29417836SJohn.Forte@Sun.COM 
29427836SJohn.Forte@Sun.COM 		index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle,
29437836SJohn.Forte@Sun.COM 		    &pkt->buffer_handle[cnt]);
29447836SJohn.Forte@Sun.COM 
29457836SJohn.Forte@Sun.COM 		if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) {
29467836SJohn.Forte@Sun.COM 			EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n");
29477836SJohn.Forte@Sun.COM 			*set_flags |= ISP_ABORT_NEEDED;
29487836SJohn.Forte@Sun.COM 			break;
29497836SJohn.Forte@Sun.COM 		}
29507836SJohn.Forte@Sun.COM 	}
29517836SJohn.Forte@Sun.COM 
29527836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
29537836SJohn.Forte@Sun.COM }
29547836SJohn.Forte@Sun.COM 
29557836SJohn.Forte@Sun.COM /*
29567836SJohn.Forte@Sun.COM  * ql_ms_entry
29577836SJohn.Forte@Sun.COM  *	Processes received Name/Management/CT Pass-Through entry.
29587836SJohn.Forte@Sun.COM  *
29597836SJohn.Forte@Sun.COM  * Input:
29607836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
29617836SJohn.Forte@Sun.COM  *	pkt23:		entry pointer.
29627836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
29637836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
29647836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
29657836SJohn.Forte@Sun.COM  *
29667836SJohn.Forte@Sun.COM  * Context:
29677836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
29687836SJohn.Forte@Sun.COM  */
29697836SJohn.Forte@Sun.COM /* ARGSUSED */
29707836SJohn.Forte@Sun.COM static void
ql_ms_entry(ql_adapter_state_t * ha,ms_entry_t * pkt23,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)29717836SJohn.Forte@Sun.COM ql_ms_entry(ql_adapter_state_t *ha, ms_entry_t *pkt23, ql_head_t *done_q,
29727836SJohn.Forte@Sun.COM     uint32_t *set_flags, uint32_t *reset_flags)
29737836SJohn.Forte@Sun.COM {
29747836SJohn.Forte@Sun.COM 	ql_srb_t		*sp;
297510240SDaniel.Beauregard@Sun.COM 	uint32_t		index, cnt, resp_identifier;
29767836SJohn.Forte@Sun.COM 	ql_tgt_t		*tq;
29777836SJohn.Forte@Sun.COM 	ct_passthru_entry_t	*pkt24 = (ct_passthru_entry_t *)pkt23;
29787836SJohn.Forte@Sun.COM 
29797836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
29807836SJohn.Forte@Sun.COM 
298110240SDaniel.Beauregard@Sun.COM 	/* Validate the response entry handle. */
298210240SDaniel.Beauregard@Sun.COM 	resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle);
298310240SDaniel.Beauregard@Sun.COM 	index = resp_identifier & OSC_INDEX_MASK;
298410240SDaniel.Beauregard@Sun.COM 	if (index < MAX_OUTSTANDING_COMMANDS) {
298510240SDaniel.Beauregard@Sun.COM 		/* the index seems reasonable */
298610240SDaniel.Beauregard@Sun.COM 		sp = ha->outstanding_cmds[index];
298710240SDaniel.Beauregard@Sun.COM 		if (sp != NULL) {
298810240SDaniel.Beauregard@Sun.COM 			if (sp->handle == resp_identifier) {
298910240SDaniel.Beauregard@Sun.COM 				/* Neo, you're the one... */
299010240SDaniel.Beauregard@Sun.COM 				ha->outstanding_cmds[index] = NULL;
299110240SDaniel.Beauregard@Sun.COM 				sp->handle = 0;
299210240SDaniel.Beauregard@Sun.COM 				sp->flags &= ~SRB_IN_TOKEN_ARRAY;
299310240SDaniel.Beauregard@Sun.COM 			} else {
299410240SDaniel.Beauregard@Sun.COM 				EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
299510240SDaniel.Beauregard@Sun.COM 				    resp_identifier, sp->handle);
299610240SDaniel.Beauregard@Sun.COM 				sp = NULL;
299710240SDaniel.Beauregard@Sun.COM 				ql_signal_abort(ha, set_flags);
299810240SDaniel.Beauregard@Sun.COM 			}
299910240SDaniel.Beauregard@Sun.COM 		} else {
300010240SDaniel.Beauregard@Sun.COM 			sp = ql_verify_preprocessed_cmd(ha,
300110240SDaniel.Beauregard@Sun.COM 			    (uint32_t *)&pkt23->handle, set_flags, reset_flags);
300210240SDaniel.Beauregard@Sun.COM 		}
300310240SDaniel.Beauregard@Sun.COM 	} else {
300410240SDaniel.Beauregard@Sun.COM 		EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
300510240SDaniel.Beauregard@Sun.COM 		    index, resp_identifier);
300610240SDaniel.Beauregard@Sun.COM 		ql_signal_abort(ha, set_flags);
300710240SDaniel.Beauregard@Sun.COM 	}
300810240SDaniel.Beauregard@Sun.COM 
300910240SDaniel.Beauregard@Sun.COM 	if (sp != NULL) {
30107836SJohn.Forte@Sun.COM 		if (!(sp->flags & SRB_MS_PKT)) {
30117836SJohn.Forte@Sun.COM 			EL(ha, "Not SRB_MS_PKT flags=%xh, isp_abort_needed",
30127836SJohn.Forte@Sun.COM 			    sp->flags);
30137836SJohn.Forte@Sun.COM 			*set_flags |= ISP_ABORT_NEEDED;
30147836SJohn.Forte@Sun.COM 			return;
30157836SJohn.Forte@Sun.COM 		}
30167836SJohn.Forte@Sun.COM 
30177836SJohn.Forte@Sun.COM 		tq = sp->lun_queue->target_queue;
30187836SJohn.Forte@Sun.COM 
30197836SJohn.Forte@Sun.COM 		/* Set ISP completion status */
302011924SDaniel.Beauregard@Sun.COM 		if (CFG_IST(ha, CFG_CTRL_24258081)) {
30217836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = ddi_get16(
30227836SJohn.Forte@Sun.COM 			    ha->hba_buf.acc_handle, &pkt24->status);
30237836SJohn.Forte@Sun.COM 		} else {
30247836SJohn.Forte@Sun.COM 			sp->pkt->pkt_reason = ddi_get16(
30257836SJohn.Forte@Sun.COM 			    ha->hba_buf.acc_handle, &pkt23->comp_status);
30267836SJohn.Forte@Sun.COM 		}
30277836SJohn.Forte@Sun.COM 
30287836SJohn.Forte@Sun.COM 		if (sp->pkt->pkt_reason == CS_RESOUCE_UNAVAILABLE &&
30297836SJohn.Forte@Sun.COM 		    sp->retry_count) {
30307836SJohn.Forte@Sun.COM 			EL(ha, "Resouce Unavailable Retry = %d\n",
30317836SJohn.Forte@Sun.COM 			    sp->retry_count);
30327836SJohn.Forte@Sun.COM 
30337836SJohn.Forte@Sun.COM 			/* Set retry status. */
30347836SJohn.Forte@Sun.COM 			sp->retry_count--;
30357836SJohn.Forte@Sun.COM 			sp->flags |= SRB_RETRY;
30367836SJohn.Forte@Sun.COM 
30377836SJohn.Forte@Sun.COM 			/* Acquire device queue lock. */
30387836SJohn.Forte@Sun.COM 			DEVICE_QUEUE_LOCK(tq);
30397836SJohn.Forte@Sun.COM 
30407836SJohn.Forte@Sun.COM 			if (!(tq->flags & TQF_QUEUE_SUSPENDED)) {
30417836SJohn.Forte@Sun.COM 				tq->flags |= TQF_QUEUE_SUSPENDED;
30427836SJohn.Forte@Sun.COM 
30437836SJohn.Forte@Sun.COM 				ADAPTER_STATE_LOCK(ha);
30447836SJohn.Forte@Sun.COM 				if (ha->port_retry_timer == 0) {
30457836SJohn.Forte@Sun.COM 					ha->port_retry_timer = 2;
30467836SJohn.Forte@Sun.COM 				}
30477836SJohn.Forte@Sun.COM 				ADAPTER_STATE_UNLOCK(ha);
30487836SJohn.Forte@Sun.COM 			}
30497836SJohn.Forte@Sun.COM 
30507836SJohn.Forte@Sun.COM 			/* Release device queue specific lock. */
30517836SJohn.Forte@Sun.COM 			DEVICE_QUEUE_UNLOCK(tq);
30527836SJohn.Forte@Sun.COM 
30537836SJohn.Forte@Sun.COM 		} else if (tq->port_down_retry_count &&
30547836SJohn.Forte@Sun.COM 		    (sp->pkt->pkt_reason == CS_PORT_CONFIG_CHG ||
30557836SJohn.Forte@Sun.COM 		    sp->pkt->pkt_reason == CS_PORT_BUSY)) {
30567836SJohn.Forte@Sun.COM 			EL(ha, "Port Down Retry\n");
30577836SJohn.Forte@Sun.COM 
30587836SJohn.Forte@Sun.COM 			/* Set retry status. */
30597836SJohn.Forte@Sun.COM 			sp->flags |= SRB_RETRY;
30607836SJohn.Forte@Sun.COM 
30617836SJohn.Forte@Sun.COM 			/* Acquire device queue lock. */
30627836SJohn.Forte@Sun.COM 			DEVICE_QUEUE_LOCK(tq);
30637836SJohn.Forte@Sun.COM 
30647836SJohn.Forte@Sun.COM 			if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) {
30657836SJohn.Forte@Sun.COM 				tq->flags |= TQF_QUEUE_SUSPENDED;
30667836SJohn.Forte@Sun.COM 
30677836SJohn.Forte@Sun.COM 				tq->port_down_retry_count--;
30687836SJohn.Forte@Sun.COM 
30697836SJohn.Forte@Sun.COM 				ADAPTER_STATE_LOCK(ha);
30707836SJohn.Forte@Sun.COM 				if (ha->port_retry_timer == 0) {
30717836SJohn.Forte@Sun.COM 					if ((ha->port_retry_timer =
30727836SJohn.Forte@Sun.COM 					    ha->port_down_retry_delay) == 0) {
30737836SJohn.Forte@Sun.COM 						*set_flags |=
30747836SJohn.Forte@Sun.COM 						    PORT_RETRY_NEEDED;
30757836SJohn.Forte@Sun.COM 					}
30767836SJohn.Forte@Sun.COM 				}
30777836SJohn.Forte@Sun.COM 				ADAPTER_STATE_UNLOCK(ha);
30787836SJohn.Forte@Sun.COM 			}
30797836SJohn.Forte@Sun.COM 			/* Release device queue specific lock. */
30807836SJohn.Forte@Sun.COM 			DEVICE_QUEUE_UNLOCK(tq);
30817836SJohn.Forte@Sun.COM 
30827836SJohn.Forte@Sun.COM 		} else if (sp->pkt->pkt_reason == CS_RESET) {
30837836SJohn.Forte@Sun.COM 			EL(ha, "Reset Retry\n");
30847836SJohn.Forte@Sun.COM 
30857836SJohn.Forte@Sun.COM 			/* Set retry status. */
30867836SJohn.Forte@Sun.COM 			sp->flags |= SRB_RETRY;
30877836SJohn.Forte@Sun.COM 
308811924SDaniel.Beauregard@Sun.COM 		} else if (CFG_IST(ha, CFG_CTRL_24258081) &&
30897836SJohn.Forte@Sun.COM 		    sp->pkt->pkt_reason == CS_DATA_UNDERRUN) {
30907836SJohn.Forte@Sun.COM 			cnt = ddi_get32(ha->hba_buf.acc_handle,
30917836SJohn.Forte@Sun.COM 			    &pkt24->resp_byte_count);
30927836SJohn.Forte@Sun.COM 			if (cnt < sizeof (fc_ct_header_t)) {
30939156SDaniel.Beauregard@Sun.COM 				EL(ha, "Data underrun\n");
30947836SJohn.Forte@Sun.COM 			} else {
30957836SJohn.Forte@Sun.COM 				sp->pkt->pkt_reason = CS_COMPLETE;
30967836SJohn.Forte@Sun.COM 			}
30977836SJohn.Forte@Sun.COM 
30987836SJohn.Forte@Sun.COM 		} else if (sp->pkt->pkt_reason != CS_COMPLETE) {
30997836SJohn.Forte@Sun.COM 			EL(ha, "status err=%xh\n", sp->pkt->pkt_reason);
31007836SJohn.Forte@Sun.COM 		}
31017836SJohn.Forte@Sun.COM 
31027836SJohn.Forte@Sun.COM 		if (sp->pkt->pkt_reason == CS_COMPLETE) {
31037836SJohn.Forte@Sun.COM 			/*EMPTY*/
31049446SDaniel.Beauregard@Sun.COM 			QL_PRINT_3(CE_CONT, "(%d): ct_cmdrsp=%x%02xh resp\n",
31059446SDaniel.Beauregard@Sun.COM 			    ha->instance, sp->pkt->pkt_cmd[8],
31069446SDaniel.Beauregard@Sun.COM 			    sp->pkt->pkt_cmd[9]);
31077836SJohn.Forte@Sun.COM 			QL_DUMP_3(sp->pkt->pkt_resp, 8, sp->pkt->pkt_rsplen);
31087836SJohn.Forte@Sun.COM 		}
31097836SJohn.Forte@Sun.COM 
31107836SJohn.Forte@Sun.COM 		/* For nameserver restore command, management change header. */
31117836SJohn.Forte@Sun.COM 		if ((sp->flags & SRB_RETRY) == 0) {
31127836SJohn.Forte@Sun.COM 			tq->d_id.b24 == 0xfffffc ?
31137836SJohn.Forte@Sun.COM 			    ql_cthdr_endian(sp->pkt->pkt_cmd_acc,
31147836SJohn.Forte@Sun.COM 			    sp->pkt->pkt_cmd, B_TRUE) :
31157836SJohn.Forte@Sun.COM 			    ql_cthdr_endian(sp->pkt->pkt_resp_acc,
31167836SJohn.Forte@Sun.COM 			    sp->pkt->pkt_resp, B_TRUE);
31177836SJohn.Forte@Sun.COM 		}
31187836SJohn.Forte@Sun.COM 
31197836SJohn.Forte@Sun.COM 		/* Set completed status. */
31207836SJohn.Forte@Sun.COM 		sp->flags |= SRB_ISP_COMPLETED;
31217836SJohn.Forte@Sun.COM 
31227836SJohn.Forte@Sun.COM 		/* Place command on done queue. */
31237836SJohn.Forte@Sun.COM 		ql_add_link_b(done_q, &sp->cmd);
31247836SJohn.Forte@Sun.COM 
31257836SJohn.Forte@Sun.COM 	}
31267836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
31277836SJohn.Forte@Sun.COM }
31287836SJohn.Forte@Sun.COM 
31297836SJohn.Forte@Sun.COM /*
31307836SJohn.Forte@Sun.COM  * ql_report_id_entry
31317836SJohn.Forte@Sun.COM  *	Processes received Name/Management/CT Pass-Through entry.
31327836SJohn.Forte@Sun.COM  *
31337836SJohn.Forte@Sun.COM  * Input:
31347836SJohn.Forte@Sun.COM  *	ha:		adapter state pointer.
313511924SDaniel.Beauregard@Sun.COM  *	pkt:		entry pointer.
31367836SJohn.Forte@Sun.COM  *	done_q:		done queue pointer.
31377836SJohn.Forte@Sun.COM  *	set_flags:	task daemon flags to set.
31387836SJohn.Forte@Sun.COM  *	reset_flags:	task daemon flags to reset.
31397836SJohn.Forte@Sun.COM  *
31407836SJohn.Forte@Sun.COM  * Context:
31417836SJohn.Forte@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
31427836SJohn.Forte@Sun.COM  */
31437836SJohn.Forte@Sun.COM /* ARGSUSED */
31447836SJohn.Forte@Sun.COM static void
ql_report_id_entry(ql_adapter_state_t * ha,report_id_1_t * pkt,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)31457836SJohn.Forte@Sun.COM ql_report_id_entry(ql_adapter_state_t *ha, report_id_1_t *pkt,
31467836SJohn.Forte@Sun.COM     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
31477836SJohn.Forte@Sun.COM {
31487836SJohn.Forte@Sun.COM 	ql_adapter_state_t	*vha;
31497836SJohn.Forte@Sun.COM 
31507836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
31517836SJohn.Forte@Sun.COM 
31527836SJohn.Forte@Sun.COM 	EL(ha, "format=%d, vp=%d, status=%d\n",
31537836SJohn.Forte@Sun.COM 	    pkt->format, pkt->vp_index, pkt->status);
31547836SJohn.Forte@Sun.COM 
31557836SJohn.Forte@Sun.COM 	if (pkt->format == 1) {
31567836SJohn.Forte@Sun.COM 		/* Locate port state structure. */
31577836SJohn.Forte@Sun.COM 		for (vha = ha; vha != NULL; vha = vha->vp_next) {
31587836SJohn.Forte@Sun.COM 			if (vha->vp_index == pkt->vp_index) {
31597836SJohn.Forte@Sun.COM 				break;
31607836SJohn.Forte@Sun.COM 			}
31617836SJohn.Forte@Sun.COM 		}
31629446SDaniel.Beauregard@Sun.COM 		if (vha != NULL && vha->vp_index != 0 &&
31639446SDaniel.Beauregard@Sun.COM 		    (pkt->status == CS_COMPLETE ||
31647836SJohn.Forte@Sun.COM 		    pkt->status == CS_PORT_ID_CHANGE)) {
31657836SJohn.Forte@Sun.COM 			*set_flags |= LOOP_RESYNC_NEEDED;
31667836SJohn.Forte@Sun.COM 			*reset_flags &= ~LOOP_RESYNC_NEEDED;
31677836SJohn.Forte@Sun.COM 			vha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
31687836SJohn.Forte@Sun.COM 			TASK_DAEMON_LOCK(ha);
31697836SJohn.Forte@Sun.COM 			vha->task_daemon_flags |= LOOP_RESYNC_NEEDED;
31707836SJohn.Forte@Sun.COM 			vha->task_daemon_flags &= ~LOOP_DOWN;
31717836SJohn.Forte@Sun.COM 			TASK_DAEMON_UNLOCK(ha);
31727836SJohn.Forte@Sun.COM 		}
31737836SJohn.Forte@Sun.COM 	}
31747836SJohn.Forte@Sun.COM 
31757836SJohn.Forte@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
31767836SJohn.Forte@Sun.COM }
31779446SDaniel.Beauregard@Sun.COM 
31789446SDaniel.Beauregard@Sun.COM /*
31799446SDaniel.Beauregard@Sun.COM  * ql_els_entry
31809446SDaniel.Beauregard@Sun.COM  *	Processes received ELS Pass-Through entry.
31819446SDaniel.Beauregard@Sun.COM  *
31829446SDaniel.Beauregard@Sun.COM  * Input:
31839446SDaniel.Beauregard@Sun.COM  *	ha:		adapter state pointer.
31849446SDaniel.Beauregard@Sun.COM  *	pkt23:		entry pointer.
31859446SDaniel.Beauregard@Sun.COM  *	done_q:		done queue pointer.
31869446SDaniel.Beauregard@Sun.COM  *	set_flags:	task daemon flags to set.
31879446SDaniel.Beauregard@Sun.COM  *	reset_flags:	task daemon flags to reset.
31889446SDaniel.Beauregard@Sun.COM  *
31899446SDaniel.Beauregard@Sun.COM  * Context:
31909446SDaniel.Beauregard@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
31919446SDaniel.Beauregard@Sun.COM  */
31929446SDaniel.Beauregard@Sun.COM /* ARGSUSED */
31939446SDaniel.Beauregard@Sun.COM static void
ql_els_passthru_entry(ql_adapter_state_t * ha,els_passthru_entry_rsp_t * rsp,ql_head_t * done_q,uint32_t * set_flags,uint32_t * reset_flags)31949446SDaniel.Beauregard@Sun.COM ql_els_passthru_entry(ql_adapter_state_t *ha, els_passthru_entry_rsp_t *rsp,
31959446SDaniel.Beauregard@Sun.COM     ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags)
31969446SDaniel.Beauregard@Sun.COM {
31979446SDaniel.Beauregard@Sun.COM 	ql_tgt_t	*tq;
31989446SDaniel.Beauregard@Sun.COM 	port_id_t	d_id, s_id;
31999446SDaniel.Beauregard@Sun.COM 	ql_srb_t	*srb;
320010240SDaniel.Beauregard@Sun.COM 	uint32_t	index, resp_identifier;
32019446SDaniel.Beauregard@Sun.COM 
32029446SDaniel.Beauregard@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
320310240SDaniel.Beauregard@Sun.COM 
320410240SDaniel.Beauregard@Sun.COM 	/* Validate the response entry handle. */
320510240SDaniel.Beauregard@Sun.COM 	resp_identifier = ddi_get32(ha->hba_buf.acc_handle, &rsp->handle);
320610240SDaniel.Beauregard@Sun.COM 	index = resp_identifier & OSC_INDEX_MASK;
320710240SDaniel.Beauregard@Sun.COM 	if (index < MAX_OUTSTANDING_COMMANDS) {
320810240SDaniel.Beauregard@Sun.COM 		/* the index seems reasonable */
320910240SDaniel.Beauregard@Sun.COM 		srb = ha->outstanding_cmds[index];
321010240SDaniel.Beauregard@Sun.COM 		if (srb != NULL) {
321110240SDaniel.Beauregard@Sun.COM 			if (srb->handle == resp_identifier) {
321210240SDaniel.Beauregard@Sun.COM 				/* Neo, you're the one... */
321310240SDaniel.Beauregard@Sun.COM 				ha->outstanding_cmds[index] = NULL;
321410240SDaniel.Beauregard@Sun.COM 				srb->handle = 0;
321510240SDaniel.Beauregard@Sun.COM 				srb->flags &= ~SRB_IN_TOKEN_ARRAY;
321610240SDaniel.Beauregard@Sun.COM 			} else {
321710240SDaniel.Beauregard@Sun.COM 				EL(ha, "IOCB handle mismatch pkt=%xh, sp=%xh\n",
321810240SDaniel.Beauregard@Sun.COM 				    resp_identifier, srb->handle);
321910240SDaniel.Beauregard@Sun.COM 				srb = NULL;
322010240SDaniel.Beauregard@Sun.COM 				ql_signal_abort(ha, set_flags);
322110240SDaniel.Beauregard@Sun.COM 			}
322210240SDaniel.Beauregard@Sun.COM 		} else {
322310240SDaniel.Beauregard@Sun.COM 			srb = ql_verify_preprocessed_cmd(ha,
322410240SDaniel.Beauregard@Sun.COM 			    (uint32_t *)&rsp->handle, set_flags, reset_flags);
322510240SDaniel.Beauregard@Sun.COM 		}
322610240SDaniel.Beauregard@Sun.COM 	} else {
322710240SDaniel.Beauregard@Sun.COM 		EL(ha, "osc index out of range, index=%xh, handle=%xh\n",
322810240SDaniel.Beauregard@Sun.COM 		    index, resp_identifier);
322910240SDaniel.Beauregard@Sun.COM 		ql_signal_abort(ha, set_flags);
323010240SDaniel.Beauregard@Sun.COM 	}
323110240SDaniel.Beauregard@Sun.COM 
323210240SDaniel.Beauregard@Sun.COM 	if (srb != NULL) {
32339446SDaniel.Beauregard@Sun.COM 		if (!(srb->flags & SRB_ELS_PKT)) {
32349446SDaniel.Beauregard@Sun.COM 			EL(ha, "Not SRB_ELS_PKT flags=%xh, isp_abort_needed",
32359446SDaniel.Beauregard@Sun.COM 			    srb->flags);
32369446SDaniel.Beauregard@Sun.COM 			*set_flags |= ISP_ABORT_NEEDED;
32379446SDaniel.Beauregard@Sun.COM 			return;
32389446SDaniel.Beauregard@Sun.COM 		}
323910240SDaniel.Beauregard@Sun.COM 
324010240SDaniel.Beauregard@Sun.COM 		(void) ddi_dma_sync(srb->pkt->pkt_resp_dma, 0, 0,
324110240SDaniel.Beauregard@Sun.COM 		    DDI_DMA_SYNC_FORKERNEL);
32429446SDaniel.Beauregard@Sun.COM 
32439446SDaniel.Beauregard@Sun.COM 		/* Set ISP completion status */
32449446SDaniel.Beauregard@Sun.COM 		srb->pkt->pkt_reason = ddi_get16(
32459446SDaniel.Beauregard@Sun.COM 		    ha->hba_buf.acc_handle, &rsp->comp_status);
32469446SDaniel.Beauregard@Sun.COM 
32479446SDaniel.Beauregard@Sun.COM 		if (srb->pkt->pkt_reason != CS_COMPLETE) {
32489446SDaniel.Beauregard@Sun.COM 			la_els_rjt_t	rjt;
32499446SDaniel.Beauregard@Sun.COM 			EL(ha, "status err=%xh\n", srb->pkt->pkt_reason);
32509446SDaniel.Beauregard@Sun.COM 
32519446SDaniel.Beauregard@Sun.COM 			if (srb->pkt->pkt_reason == CS_LOGIN_LOGOUT_ERROR) {
32529446SDaniel.Beauregard@Sun.COM 				EL(ha, "e1=%xh e2=%xh\n",
32539446SDaniel.Beauregard@Sun.COM 				    rsp->error_subcode1, rsp->error_subcode2);
32549446SDaniel.Beauregard@Sun.COM 			}
32559446SDaniel.Beauregard@Sun.COM 
32569446SDaniel.Beauregard@Sun.COM 			srb->pkt->pkt_state = FC_PKT_TRAN_ERROR;
32579446SDaniel.Beauregard@Sun.COM 
32589446SDaniel.Beauregard@Sun.COM 			/* Build RJT in the response. */
32599446SDaniel.Beauregard@Sun.COM 			rjt.ls_code.ls_code = LA_ELS_RJT;
32609446SDaniel.Beauregard@Sun.COM 			rjt.reason = FC_REASON_NO_CONNECTION;
32619446SDaniel.Beauregard@Sun.COM 
32629446SDaniel.Beauregard@Sun.COM 			ddi_rep_put8(srb->pkt->pkt_resp_acc, (uint8_t *)&rjt,
32639446SDaniel.Beauregard@Sun.COM 			    (uint8_t *)srb->pkt->pkt_resp,
32649446SDaniel.Beauregard@Sun.COM 			    sizeof (rjt), DDI_DEV_AUTOINCR);
32659446SDaniel.Beauregard@Sun.COM 
32669446SDaniel.Beauregard@Sun.COM 			srb->pkt->pkt_state = FC_PKT_TRAN_ERROR;
32679446SDaniel.Beauregard@Sun.COM 			srb->pkt->pkt_reason = FC_REASON_NO_CONNECTION;
32689446SDaniel.Beauregard@Sun.COM 		}
32699446SDaniel.Beauregard@Sun.COM 
32709446SDaniel.Beauregard@Sun.COM 		if (srb->pkt->pkt_reason == CS_COMPLETE) {
32719446SDaniel.Beauregard@Sun.COM 			uint8_t		opcode;
32729446SDaniel.Beauregard@Sun.COM 			uint16_t	loop_id;
32739446SDaniel.Beauregard@Sun.COM 
32749446SDaniel.Beauregard@Sun.COM 			/* Indicate ISP completion */
32759446SDaniel.Beauregard@Sun.COM 			srb->flags |= SRB_ISP_COMPLETED;
32769446SDaniel.Beauregard@Sun.COM 
32779446SDaniel.Beauregard@Sun.COM 			loop_id = ddi_get16(ha->hba_buf.acc_handle,
32789446SDaniel.Beauregard@Sun.COM 			    &rsp->n_port_hdl);
32799446SDaniel.Beauregard@Sun.COM 
32809446SDaniel.Beauregard@Sun.COM 			if (ha->topology & QL_N_PORT) {
32819446SDaniel.Beauregard@Sun.COM 				/* create a target Q if there isn't one */
32829446SDaniel.Beauregard@Sun.COM 				tq = ql_loop_id_to_queue(ha, loop_id);
32839446SDaniel.Beauregard@Sun.COM 				if (tq == NULL) {
32849446SDaniel.Beauregard@Sun.COM 					d_id.b.al_pa = rsp->d_id_7_0;
32859446SDaniel.Beauregard@Sun.COM 					d_id.b.area = rsp->d_id_15_8;
32869446SDaniel.Beauregard@Sun.COM 					d_id.b.domain = rsp->d_id_23_16;
32879446SDaniel.Beauregard@Sun.COM 					/* Acquire adapter state lock. */
32889446SDaniel.Beauregard@Sun.COM 					ADAPTER_STATE_LOCK(ha);
32899446SDaniel.Beauregard@Sun.COM 
32909446SDaniel.Beauregard@Sun.COM 					tq = ql_dev_init(ha, d_id, loop_id);
32919446SDaniel.Beauregard@Sun.COM 					EL(ha, " tq = %x\n", tq);
32929446SDaniel.Beauregard@Sun.COM 
32939446SDaniel.Beauregard@Sun.COM 					ADAPTER_STATE_UNLOCK(ha);
32949446SDaniel.Beauregard@Sun.COM 				}
32959446SDaniel.Beauregard@Sun.COM 
32969446SDaniel.Beauregard@Sun.COM 				/* on plogi success assume the chosen s_id */
32979446SDaniel.Beauregard@Sun.COM 				opcode = ddi_get8(ha->hba_buf.acc_handle,
32989446SDaniel.Beauregard@Sun.COM 				    &rsp->els_cmd_opcode);
32999446SDaniel.Beauregard@Sun.COM 
33009446SDaniel.Beauregard@Sun.COM 				EL(ha, "els_cmd_opcode=%x srb->pkt=%x\n",
33019446SDaniel.Beauregard@Sun.COM 				    opcode, srb->pkt);
33029446SDaniel.Beauregard@Sun.COM 
33039446SDaniel.Beauregard@Sun.COM 				if (opcode == LA_ELS_PLOGI) {
33049446SDaniel.Beauregard@Sun.COM 					s_id.b.al_pa = rsp->s_id_7_0;
33059446SDaniel.Beauregard@Sun.COM 					s_id.b.area = rsp->s_id_15_8;
33069446SDaniel.Beauregard@Sun.COM 					s_id.b.domain = rsp->s_id_23_16;
33079446SDaniel.Beauregard@Sun.COM 
33089446SDaniel.Beauregard@Sun.COM 					ha->d_id.b24 = s_id.b24;
33099446SDaniel.Beauregard@Sun.COM 					EL(ha, "Set port's source ID %xh\n",
33109446SDaniel.Beauregard@Sun.COM 					    ha->d_id.b24);
33119446SDaniel.Beauregard@Sun.COM 				}
33129446SDaniel.Beauregard@Sun.COM 			}
33139446SDaniel.Beauregard@Sun.COM 			ql_isp_els_handle_rsp_endian(ha, srb);
33149446SDaniel.Beauregard@Sun.COM 
33159446SDaniel.Beauregard@Sun.COM 			if (ha != srb->ha) {
33169446SDaniel.Beauregard@Sun.COM 				EL(ha, "ha=%x srb->ha=%x\n", ha, srb->ha);
33179446SDaniel.Beauregard@Sun.COM 			}
33189446SDaniel.Beauregard@Sun.COM 
33199446SDaniel.Beauregard@Sun.COM 			if (tq != NULL) {
33209446SDaniel.Beauregard@Sun.COM 				tq->logout_sent = 0;
33219446SDaniel.Beauregard@Sun.COM 				tq->flags &= ~TQF_NEED_AUTHENTICATION;
33229446SDaniel.Beauregard@Sun.COM 
332311924SDaniel.Beauregard@Sun.COM 				if (CFG_IST(ha, CFG_CTRL_24258081)) {
33249446SDaniel.Beauregard@Sun.COM 					tq->flags |= TQF_IIDMA_NEEDED;
33259446SDaniel.Beauregard@Sun.COM 				}
33269446SDaniel.Beauregard@Sun.COM 			srb->pkt->pkt_state = FC_PKT_SUCCESS;
33279446SDaniel.Beauregard@Sun.COM 			}
33289446SDaniel.Beauregard@Sun.COM 		}
33299446SDaniel.Beauregard@Sun.COM 		/* invoke the callback */
33309446SDaniel.Beauregard@Sun.COM 		ql_awaken_task_daemon(ha, srb, 0, 0);
33319446SDaniel.Beauregard@Sun.COM 	}
33329446SDaniel.Beauregard@Sun.COM 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
33339446SDaniel.Beauregard@Sun.COM }
333410240SDaniel.Beauregard@Sun.COM 
333510240SDaniel.Beauregard@Sun.COM /*
333610240SDaniel.Beauregard@Sun.COM  * ql_signal_abort
333710240SDaniel.Beauregard@Sun.COM  *	Signal to the task daemon that a condition warranting an
333810240SDaniel.Beauregard@Sun.COM  *	isp reset has been detected.
333910240SDaniel.Beauregard@Sun.COM  *
334010240SDaniel.Beauregard@Sun.COM  * Input:
334110240SDaniel.Beauregard@Sun.COM  *	ha:		adapter state pointer.
334210240SDaniel.Beauregard@Sun.COM  *	set_flags:	task daemon flags to set.
334310240SDaniel.Beauregard@Sun.COM  *
334410240SDaniel.Beauregard@Sun.COM  * Context:
334510240SDaniel.Beauregard@Sun.COM  *	Interrupt or Kernel context, no mailbox commands allowed.
334610240SDaniel.Beauregard@Sun.COM  */
334710240SDaniel.Beauregard@Sun.COM static void
ql_signal_abort(ql_adapter_state_t * ha,uint32_t * set_flags)334810240SDaniel.Beauregard@Sun.COM ql_signal_abort(ql_adapter_state_t *ha, uint32_t *set_flags)
334910240SDaniel.Beauregard@Sun.COM {
3350*12279SDaniel.Beauregard@Sun.COM 	if (!CFG_IST(ha, CFG_CTRL_8021) &&
3351*12279SDaniel.Beauregard@Sun.COM 	    !(ha->task_daemon_flags & (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) {
335210240SDaniel.Beauregard@Sun.COM 		*set_flags |= ISP_ABORT_NEEDED;
335310240SDaniel.Beauregard@Sun.COM 	}
335410240SDaniel.Beauregard@Sun.COM }
3355