17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5ae85eacfSBarry Harding  * Common Development and Distribution License (the "License").
6ae85eacfSBarry Harding  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22ae85eacfSBarry Harding  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * hci1394_isr.c
287c478bd9Sstevel@tonic-gate  *    Contains the core interrupt handling logic for the hci1394 driver.
297c478bd9Sstevel@tonic-gate  *    It also contains the routine which sets up the initial interrupt
307c478bd9Sstevel@tonic-gate  *    mask during HW init.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <sys/conf.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
357c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
367c478bd9Sstevel@tonic-gate #include <sys/stat.h>
377c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
387c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h>
417c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate static uint_t hci1394_isr(caddr_t parm);
457c478bd9Sstevel@tonic-gate static void hci1394_isr_bus_reset(hci1394_state_t *soft_state);
467c478bd9Sstevel@tonic-gate static void hci1394_isr_self_id(hci1394_state_t *soft_state);
477c478bd9Sstevel@tonic-gate static void hci1394_isr_isoch_ir(hci1394_state_t *soft_state);
487c478bd9Sstevel@tonic-gate static void hci1394_isr_isoch_it(hci1394_state_t *soft_state);
497c478bd9Sstevel@tonic-gate static void hci1394_isr_atreq_complete(hci1394_state_t *soft_state);
507c478bd9Sstevel@tonic-gate static void hci1394_isr_arresp(hci1394_state_t *soft_state);
517c478bd9Sstevel@tonic-gate static void hci1394_isr_arreq(hci1394_state_t *soft_state);
527c478bd9Sstevel@tonic-gate static void hci1394_isr_atresp_complete(hci1394_state_t *soft_state);
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate  * hci1394_isr_init()
577c478bd9Sstevel@tonic-gate  *    Get the iblock_cookie, make sure we are not using a high level interrupt,
587c478bd9Sstevel@tonic-gate  *    register our interrupt service routine.
597c478bd9Sstevel@tonic-gate  */
607c478bd9Sstevel@tonic-gate int
hci1394_isr_init(hci1394_state_t * soft_state)617c478bd9Sstevel@tonic-gate hci1394_isr_init(hci1394_state_t *soft_state)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate 	int status;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 	/* This driver does not support running at a high level interrupt */
687c478bd9Sstevel@tonic-gate 	status = ddi_intr_hilevel(soft_state->drvinfo.di_dip, 0);
697c478bd9Sstevel@tonic-gate 	if (status != 0) {
707c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
717c478bd9Sstevel@tonic-gate 	}
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	/* There should only be 1 1394 interrupt for an OpenHCI adapter */
747c478bd9Sstevel@tonic-gate 	status = ddi_get_iblock_cookie(soft_state->drvinfo.di_dip, 0,
757c478bd9Sstevel@tonic-gate 	    &soft_state->drvinfo.di_iblock_cookie);
767c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
777c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
787c478bd9Sstevel@tonic-gate 	}
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * hci1394_isr_fini()
867c478bd9Sstevel@tonic-gate  *    un-register our interrupt service routine.
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate /* ARGSUSED */
897c478bd9Sstevel@tonic-gate void
hci1394_isr_fini(hci1394_state_t * soft_state)907c478bd9Sstevel@tonic-gate hci1394_isr_fini(hci1394_state_t *soft_state)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	/* nothing to do right now */
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * hci1394_isr_handler_init()
1007c478bd9Sstevel@tonic-gate  *    register our interrupt service routine.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate int
hci1394_isr_handler_init(hci1394_state_t * soft_state)1037c478bd9Sstevel@tonic-gate hci1394_isr_handler_init(hci1394_state_t *soft_state)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 	int status;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	/* Initialize interrupt handler */
1107c478bd9Sstevel@tonic-gate 	status = ddi_add_intr(soft_state->drvinfo.di_dip, 0, NULL, NULL,
1117c478bd9Sstevel@tonic-gate 	    hci1394_isr, (caddr_t)soft_state);
112*2570281cSToomas Soome 	return (status);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate  * hci1394_isr_handler_fini()
1187c478bd9Sstevel@tonic-gate  *    un-register our interrupt service routine.
1197c478bd9Sstevel@tonic-gate  */
1207c478bd9Sstevel@tonic-gate void
hci1394_isr_handler_fini(hci1394_state_t * soft_state)1217c478bd9Sstevel@tonic-gate hci1394_isr_handler_fini(hci1394_state_t *soft_state)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	/* Remove interrupt handler */
1267c478bd9Sstevel@tonic-gate 	ddi_remove_intr(soft_state->drvinfo.di_dip, 0,
1277c478bd9Sstevel@tonic-gate 	    soft_state->drvinfo.di_iblock_cookie);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate  * hci1394_isr_mask_setup()
1337c478bd9Sstevel@tonic-gate  *    Setup the initial interrupt mask for OpenHCI.  These are the interrupts
1347c478bd9Sstevel@tonic-gate  *    that our interrupt handler is expected to handle.
1357c478bd9Sstevel@tonic-gate  */
1367c478bd9Sstevel@tonic-gate void
hci1394_isr_mask_setup(hci1394_state_t * soft_state)1377c478bd9Sstevel@tonic-gate hci1394_isr_mask_setup(hci1394_state_t *soft_state)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	/* start off with all interrupts cleared/disabled */
1427c478bd9Sstevel@tonic-gate 	hci1394_ohci_ir_intr_disable(soft_state->ohci, 0xFFFFFFFF);
1437c478bd9Sstevel@tonic-gate 	hci1394_ohci_ir_intr_clear(soft_state->ohci, 0xFFFFFFFF);
1447c478bd9Sstevel@tonic-gate 	hci1394_ohci_it_intr_disable(soft_state->ohci, 0xFFFFFFFF);
1457c478bd9Sstevel@tonic-gate 	hci1394_ohci_it_intr_clear(soft_state->ohci, 0xFFFFFFFF);
1467c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_disable(soft_state->ohci, 0xFFFFFFFF);
1477c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(soft_state->ohci, 0xFFFFFFFF);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/* Setup Interrupt Mask Register */
1507c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_enable(soft_state->ohci,
1517c478bd9Sstevel@tonic-gate 	    (OHCI_INTR_UNRECOVERABLE_ERR | OHCI_INTR_CYC_TOO_LONG |
1527c478bd9Sstevel@tonic-gate 	    OHCI_INTR_BUS_RESET | OHCI_INTR_SELFID_CMPLT |
1537c478bd9Sstevel@tonic-gate 	    OHCI_INTR_REQ_TX_CMPLT | OHCI_INTR_RESP_TX_CMPLT |
1547c478bd9Sstevel@tonic-gate 	    OHCI_INTR_RQPKT | OHCI_INTR_RSPKT | OHCI_INTR_ISOCH_TX |
1557c478bd9Sstevel@tonic-gate 	    OHCI_INTR_ISOCH_RX | OHCI_INTR_POST_WR_ERR | OHCI_INTR_PHY |
1567c478bd9Sstevel@tonic-gate 	    OHCI_INTR_LOCK_RESP_ERR));
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate  * hci1394_isr()
1627c478bd9Sstevel@tonic-gate  *    Core interrupt handler.  Every interrupt enabled in
1637c478bd9Sstevel@tonic-gate  *    hci1394_isr_mask_setup() should be covered here.  There may be other
1647c478bd9Sstevel@tonic-gate  *    interrupts supported in here even if they are not initially enabled
1657c478bd9Sstevel@tonic-gate  *    (like OHCI_INTR_CYC_64_SECS) since they may be enabled later (i.e. due to
1667c478bd9Sstevel@tonic-gate  *    CSR register write)
1677c478bd9Sstevel@tonic-gate  */
1687c478bd9Sstevel@tonic-gate static uint_t
hci1394_isr(caddr_t parm)1697c478bd9Sstevel@tonic-gate hci1394_isr(caddr_t parm)
1707c478bd9Sstevel@tonic-gate {
1717c478bd9Sstevel@tonic-gate 	hci1394_state_t *soft_state;
1727c478bd9Sstevel@tonic-gate 	h1394_posted_wr_err_t posted_wr_err;
1737c478bd9Sstevel@tonic-gate 	uint32_t interrupt_event;
1747c478bd9Sstevel@tonic-gate 	uint_t status;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	status = DDI_INTR_UNCLAIMED;
1787c478bd9Sstevel@tonic-gate 	soft_state = (hci1394_state_t *)parm;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
1817c478bd9Sstevel@tonic-gate 
182ae85eacfSBarry Harding 	if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN)
183ae85eacfSBarry Harding 		return (DDI_INTR_UNCLAIMED);
184ae85eacfSBarry Harding 
1857c478bd9Sstevel@tonic-gate 	/*
1867c478bd9Sstevel@tonic-gate 	 * Get all of the enabled 1394 interrupts which are currently
1877c478bd9Sstevel@tonic-gate 	 * asserted.
1887c478bd9Sstevel@tonic-gate 	 */
1897c478bd9Sstevel@tonic-gate 	interrupt_event = hci1394_ohci_intr_asserted(soft_state->ohci);
1907c478bd9Sstevel@tonic-gate 	do {
1917c478bd9Sstevel@tonic-gate 		/* handle the asserted interrupts */
1927c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_BUS_RESET) {
1937c478bd9Sstevel@tonic-gate 			hci1394_isr_bus_reset(soft_state);
1947c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
1957c478bd9Sstevel@tonic-gate 		}
1967c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_SELFID_CMPLT) {
1977c478bd9Sstevel@tonic-gate 			hci1394_isr_self_id(soft_state);
1987c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
1997c478bd9Sstevel@tonic-gate 		}
2007c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_ISOCH_TX) {
2017c478bd9Sstevel@tonic-gate 			hci1394_isr_isoch_it(soft_state);
2027c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2037c478bd9Sstevel@tonic-gate 		}
2047c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_ISOCH_RX) {
2057c478bd9Sstevel@tonic-gate 			hci1394_isr_isoch_ir(soft_state);
2067c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2077c478bd9Sstevel@tonic-gate 		}
2087c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_REQ_TX_CMPLT) {
2097c478bd9Sstevel@tonic-gate 			hci1394_isr_atreq_complete(soft_state);
2107c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2117c478bd9Sstevel@tonic-gate 		}
2127c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_RSPKT) {
2137c478bd9Sstevel@tonic-gate 			hci1394_isr_arresp(soft_state);
2147c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2157c478bd9Sstevel@tonic-gate 		}
2167c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_RQPKT) {
2177c478bd9Sstevel@tonic-gate 			hci1394_isr_arreq(soft_state);
2187c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2197c478bd9Sstevel@tonic-gate 		}
2207c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_RESP_TX_CMPLT) {
2217c478bd9Sstevel@tonic-gate 			hci1394_isr_atresp_complete(soft_state);
2227c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2237c478bd9Sstevel@tonic-gate 		}
2247c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_CYC_64_SECS) {
2257c478bd9Sstevel@tonic-gate 			hci1394_ohci_isr_cycle64seconds(soft_state->ohci);
2267c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2277c478bd9Sstevel@tonic-gate 		}
2287c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_UNRECOVERABLE_ERR) {
2297c478bd9Sstevel@tonic-gate 			h1394_error_detected(soft_state->drvinfo.di_sl_private,
2307c478bd9Sstevel@tonic-gate 			    H1394_SELF_INITIATED_SHUTDOWN, NULL);
2317c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "hci1394(%d): driver shutdown: "
2327c478bd9Sstevel@tonic-gate 			    "unrecoverable error interrupt detected",
2337c478bd9Sstevel@tonic-gate 			    soft_state->drvinfo.di_instance);
2347c478bd9Sstevel@tonic-gate 			hci1394_shutdown(soft_state->drvinfo.di_dip);
2357c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2367c478bd9Sstevel@tonic-gate 		}
2377c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_CYC_LOST) {
2387c478bd9Sstevel@tonic-gate 			hci1394_isoch_cycle_lost(soft_state);
2397c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2407c478bd9Sstevel@tonic-gate 		}
2417c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_CYC_INCONSISTENT) {
2427c478bd9Sstevel@tonic-gate 			hci1394_isoch_cycle_inconsistent(soft_state);
2437c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2447c478bd9Sstevel@tonic-gate 		}
2457c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_CYC_TOO_LONG) {
2467c478bd9Sstevel@tonic-gate 			hci1394_ohci_intr_clear(soft_state->ohci,
2477c478bd9Sstevel@tonic-gate 			    OHCI_INTR_CYC_TOO_LONG);
2487c478bd9Sstevel@tonic-gate 			/* clear cycle master bit in csr state register */
2497c478bd9Sstevel@tonic-gate 			hci1394_csr_state_bclr(soft_state->csr,
2507c478bd9Sstevel@tonic-gate 			    IEEE1394_CSR_STATE_CMSTR);
2517c478bd9Sstevel@tonic-gate 			h1394_error_detected(soft_state->drvinfo.di_sl_private,
2527c478bd9Sstevel@tonic-gate 			    H1394_CYCLE_TOO_LONG, NULL);
2537c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2547c478bd9Sstevel@tonic-gate 		}
2557c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_POST_WR_ERR) {
2567c478bd9Sstevel@tonic-gate 			hci1394_ohci_postwr_addr(soft_state->ohci,
2577c478bd9Sstevel@tonic-gate 			    &posted_wr_err.addr);
2587c478bd9Sstevel@tonic-gate 			h1394_error_detected(soft_state->drvinfo.di_sl_private,
2597c478bd9Sstevel@tonic-gate 			    H1394_POSTED_WR_ERR, &posted_wr_err);
2607c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2617c478bd9Sstevel@tonic-gate 		}
2627c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_PHY) {
2637c478bd9Sstevel@tonic-gate 			hci1394_ohci_isr_phy(soft_state->ohci);
2647c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2657c478bd9Sstevel@tonic-gate 		}
2667c478bd9Sstevel@tonic-gate 		if (interrupt_event & OHCI_INTR_LOCK_RESP_ERR) {
2677c478bd9Sstevel@tonic-gate 			hci1394_ohci_intr_clear(soft_state->ohci,
2687c478bd9Sstevel@tonic-gate 			    OHCI_INTR_LOCK_RESP_ERR);
2697c478bd9Sstevel@tonic-gate 			h1394_error_detected(soft_state->drvinfo.di_sl_private,
2707c478bd9Sstevel@tonic-gate 			    H1394_LOCK_RESP_ERR, NULL);
2717c478bd9Sstevel@tonic-gate 			status = DDI_INTR_CLAIMED;
2727c478bd9Sstevel@tonic-gate 		}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 		/*
2757c478bd9Sstevel@tonic-gate 		 * Check for self-id-complete interrupt disappearing.  There is
2767c478bd9Sstevel@tonic-gate 		 * a chance in OpenHCI where it will assert the selfid
2777c478bd9Sstevel@tonic-gate 		 * interrupt and then take it away.  We will look for this case
2787c478bd9Sstevel@tonic-gate 		 * and claim it just in case.  We could possibly claim an
2797c478bd9Sstevel@tonic-gate 		 * interrupt that's not ours.  We would have to be in the
2807c478bd9Sstevel@tonic-gate 		 * middle of a bus reset and a bunch of other weird stuff
2817c478bd9Sstevel@tonic-gate 		 * would have to align.  It should not hurt anything if we do.
2827c478bd9Sstevel@tonic-gate 		 *
2837c478bd9Sstevel@tonic-gate 		 * This will very very rarely happen, if ever.  We still have
2847c478bd9Sstevel@tonic-gate 		 * to handle the case, just in case. OpenHCI 1.1 should fix
2857c478bd9Sstevel@tonic-gate 		 * this problem.
2867c478bd9Sstevel@tonic-gate 		 */
2877c478bd9Sstevel@tonic-gate 		if ((status == DDI_INTR_UNCLAIMED) &&
2887c478bd9Sstevel@tonic-gate 		    (hci1394_state(&soft_state->drvinfo) ==
2897c478bd9Sstevel@tonic-gate 		    HCI1394_BUS_RESET)) {
2907c478bd9Sstevel@tonic-gate 			if (soft_state->drvinfo.di_gencnt !=
2917c478bd9Sstevel@tonic-gate 			    hci1394_ohci_current_busgen(soft_state->ohci)) {
2927c478bd9Sstevel@tonic-gate 				status = DDI_INTR_CLAIMED;
2937c478bd9Sstevel@tonic-gate 			}
2947c478bd9Sstevel@tonic-gate 		}
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 		/*
2977c478bd9Sstevel@tonic-gate 		 * See if any of the enabled 1394 interrupts have been asserted
2987c478bd9Sstevel@tonic-gate 		 * since we first checked.
2997c478bd9Sstevel@tonic-gate 		 */
3007c478bd9Sstevel@tonic-gate 		interrupt_event = hci1394_ohci_intr_asserted(
3017c478bd9Sstevel@tonic-gate 		    soft_state->ohci);
3027c478bd9Sstevel@tonic-gate 	} while (interrupt_event != 0);
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	return (status);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate /*
3097c478bd9Sstevel@tonic-gate  * hci1394_isr_bus_reset()
3107c478bd9Sstevel@tonic-gate  *    Process a 1394 bus reset.  This signifies that a bus reset has started.
3117c478bd9Sstevel@tonic-gate  *    A bus reset will not be complete until a selfid complete interrupt
3127c478bd9Sstevel@tonic-gate  *    comes in.
3137c478bd9Sstevel@tonic-gate  */
3147c478bd9Sstevel@tonic-gate static void
hci1394_isr_bus_reset(hci1394_state_t * soft_state)3157c478bd9Sstevel@tonic-gate hci1394_isr_bus_reset(hci1394_state_t *soft_state)
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate 	int status;
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/*
3237c478bd9Sstevel@tonic-gate 	 * Set the driver state to reset.  If we cannot, we have been shutdown.
3247c478bd9Sstevel@tonic-gate 	 * The only way we can get in this code is if we have a multi-processor
3257c478bd9Sstevel@tonic-gate 	 * machine and the HAL is shutdown by one processor running in base
3267c478bd9Sstevel@tonic-gate 	 * context while this interrupt handler runs in another processor.
3277c478bd9Sstevel@tonic-gate 	 * We will disable all interrupts and just return.  We shouldn't have
3287c478bd9Sstevel@tonic-gate 	 * to disable the interrupts, but we will just in case.
3297c478bd9Sstevel@tonic-gate 	 */
3307c478bd9Sstevel@tonic-gate 	status = hci1394_state_set(&soft_state->drvinfo, HCI1394_BUS_RESET);
3317c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
3327c478bd9Sstevel@tonic-gate 		hci1394_ohci_intr_master_disable(soft_state->ohci);
3337c478bd9Sstevel@tonic-gate 		return;
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	/*
3377c478bd9Sstevel@tonic-gate 	 * Save away reset generation count so we can detect self-id-compete
3387c478bd9Sstevel@tonic-gate 	 * interrupt which disappears in event register.  This is discussed in
3397c478bd9Sstevel@tonic-gate 	 * more detail in hci1394_isr()
3407c478bd9Sstevel@tonic-gate 	 */
3417c478bd9Sstevel@tonic-gate 	soft_state->drvinfo.di_gencnt =
3427c478bd9Sstevel@tonic-gate 	    hci1394_ohci_current_busgen(soft_state->ohci);
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	soft_state->drvinfo.di_stats.st_bus_reset_count++;
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	/*
3477c478bd9Sstevel@tonic-gate 	 * Mask off busReset until SelfIdComplete comes in.  The bus reset
3487c478bd9Sstevel@tonic-gate 	 * interrupt will be asserted until the SelfIdComplete interrupt
3497c478bd9Sstevel@tonic-gate 	 * comes in (i.e. you cannot clear the interrupt until a SelfIdComplete
3507c478bd9Sstevel@tonic-gate 	 * interrupt).  Therefore, we disable the interrupt via its mask so we
3517c478bd9Sstevel@tonic-gate 	 * don't get stuck in the ISR indefinitely.
3527c478bd9Sstevel@tonic-gate 	 */
3537c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_disable(soft_state->ohci, OHCI_INTR_BUS_RESET);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	/* Reset the ATREQ and ATRESP Q's */
3567c478bd9Sstevel@tonic-gate 	hci1394_async_atreq_reset(soft_state->async);
3577c478bd9Sstevel@tonic-gate 	hci1394_async_atresp_reset(soft_state->async);
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	/* Inform Services Layer about Bus Reset */
3607c478bd9Sstevel@tonic-gate 	h1394_bus_reset(soft_state->drvinfo.di_sl_private,
3617c478bd9Sstevel@tonic-gate 	    (void **)&soft_state->sl_selfid_buf);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate /*
3667c478bd9Sstevel@tonic-gate  * hci1394_isr_self_id()
3677c478bd9Sstevel@tonic-gate  *    Process the selfid complete interrupt.  The bus reset has completed
3687c478bd9Sstevel@tonic-gate  *    and the 1394 HW has finished it's bus enumeration.  The SW needs to
3697c478bd9Sstevel@tonic-gate  *    see what's changed and handle any hotplug conditions.
3707c478bd9Sstevel@tonic-gate  */
3717c478bd9Sstevel@tonic-gate static void
hci1394_isr_self_id(hci1394_state_t * soft_state)3727c478bd9Sstevel@tonic-gate hci1394_isr_self_id(hci1394_state_t *soft_state)
3737c478bd9Sstevel@tonic-gate {
3747c478bd9Sstevel@tonic-gate 	int status;
3757c478bd9Sstevel@tonic-gate 	uint_t node_id;
3767c478bd9Sstevel@tonic-gate 	uint_t selfid_size;
3777c478bd9Sstevel@tonic-gate 	uint_t quadlet_count;
3787c478bd9Sstevel@tonic-gate 	uint_t index;
3797c478bd9Sstevel@tonic-gate 	uint32_t *selfid_buf_p;
3807c478bd9Sstevel@tonic-gate 	boolean_t selfid_error;
3817c478bd9Sstevel@tonic-gate 	boolean_t nodeid_error;
3827c478bd9Sstevel@tonic-gate 	boolean_t saw_error = B_FALSE;
3837c478bd9Sstevel@tonic-gate 	uint_t phy_status;
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	soft_state->drvinfo.di_stats.st_selfid_count++;
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	/*
3917c478bd9Sstevel@tonic-gate 	 * check for the bizarre case that we got both a bus reset and self id
3927c478bd9Sstevel@tonic-gate 	 * complete after checking for a bus reset
3937c478bd9Sstevel@tonic-gate 	 */
3947c478bd9Sstevel@tonic-gate 	if (hci1394_state(&soft_state->drvinfo) != HCI1394_BUS_RESET) {
3957c478bd9Sstevel@tonic-gate 		hci1394_isr_bus_reset(soft_state);
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	/*
3997c478bd9Sstevel@tonic-gate 	 * Clear any set PHY error status bits set.  The PHY status bits
4007c478bd9Sstevel@tonic-gate 	 * may always be set (i.e. we removed cable power) so we do not want
4017c478bd9Sstevel@tonic-gate 	 * to clear them when we handle the interrupt. We will clear them
4027c478bd9Sstevel@tonic-gate 	 * every selfid complete interrupt so worst case we will get 1 PHY event
4037c478bd9Sstevel@tonic-gate 	 * interrupt every bus reset.
4047c478bd9Sstevel@tonic-gate 	 */
4057c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_read(soft_state->ohci, 5, &phy_status);
406*2570281cSToomas Soome 	if (status == DDI_SUCCESS) {
4077c478bd9Sstevel@tonic-gate 		phy_status |= OHCI_PHY_LOOP_ERR | OHCI_PHY_PWRFAIL_ERR |
4087c478bd9Sstevel@tonic-gate 		    OHCI_PHY_TIMEOUT_ERR | OHCI_PHY_PORTEVT_ERR;
4097c478bd9Sstevel@tonic-gate 		status = hci1394_ohci_phy_write(soft_state->ohci, 5,
4107c478bd9Sstevel@tonic-gate 		    phy_status);
411*2570281cSToomas Soome 		if (status == DDI_SUCCESS) {
4127c478bd9Sstevel@tonic-gate 			/*
4137c478bd9Sstevel@tonic-gate 			 * Re-enable PHY interrupt. We disable the PHY interrupt
4147c478bd9Sstevel@tonic-gate 			 *  when we get one so that we do not get stuck in the
4157c478bd9Sstevel@tonic-gate 			 * ISR.
4167c478bd9Sstevel@tonic-gate 			 */
4177c478bd9Sstevel@tonic-gate 			hci1394_ohci_intr_enable(soft_state->ohci,
4187c478bd9Sstevel@tonic-gate 			    OHCI_INTR_PHY);
4197c478bd9Sstevel@tonic-gate 		}
4207c478bd9Sstevel@tonic-gate 	}
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	/* See if either AT active bit is set */
4237c478bd9Sstevel@tonic-gate 	if (hci1394_ohci_at_active(soft_state->ohci) == B_TRUE) {
4247c478bd9Sstevel@tonic-gate 		saw_error = B_TRUE;
4257c478bd9Sstevel@tonic-gate 	}
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	/* Clear busReset and selfIdComplete interrupts */
4287c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(soft_state->ohci, (OHCI_INTR_BUS_RESET |
4297c478bd9Sstevel@tonic-gate 	    OHCI_INTR_SELFID_CMPLT));
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	/* Read node info and test for Invalid Node ID */
4327c478bd9Sstevel@tonic-gate 	hci1394_ohci_nodeid_info(soft_state->ohci, &node_id, &nodeid_error);
4337c478bd9Sstevel@tonic-gate 	if (nodeid_error == B_TRUE) {
4347c478bd9Sstevel@tonic-gate 		saw_error = B_TRUE;
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	/* Sync Selfid Buffer */
4387c478bd9Sstevel@tonic-gate 	hci1394_ohci_selfid_sync(soft_state->ohci);
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	/* store away selfid info */
4417c478bd9Sstevel@tonic-gate 	hci1394_ohci_selfid_info(soft_state->ohci,
4427c478bd9Sstevel@tonic-gate 	    &soft_state->drvinfo.di_gencnt, &selfid_size, &selfid_error);
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	/* Test for selfid error */
4457c478bd9Sstevel@tonic-gate 	if (selfid_error == B_TRUE) {
4467c478bd9Sstevel@tonic-gate 		saw_error = B_TRUE;
4477c478bd9Sstevel@tonic-gate 	}
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	/*
4507c478bd9Sstevel@tonic-gate 	 * selfid size could be 0 if a bus reset has occurred. If this occurs,
4517c478bd9Sstevel@tonic-gate 	 * we should have another selfid int coming later.
4527c478bd9Sstevel@tonic-gate 	 */
4537c478bd9Sstevel@tonic-gate 	if ((saw_error == B_FALSE) && (selfid_size == 0)) {
4547c478bd9Sstevel@tonic-gate 		return;
4557c478bd9Sstevel@tonic-gate 	}
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	/*
4587c478bd9Sstevel@tonic-gate 	 * make sure generation count in buffer matches generation
4597c478bd9Sstevel@tonic-gate 	 * count in register.
4607c478bd9Sstevel@tonic-gate 	 */
4617c478bd9Sstevel@tonic-gate 	if (hci1394_ohci_selfid_buf_current(soft_state->ohci) == B_FALSE) {
4627c478bd9Sstevel@tonic-gate 		return;
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	/*
4667c478bd9Sstevel@tonic-gate 	 * Skip over first quadlet in selfid buffer, this is OpenHCI specific
4677c478bd9Sstevel@tonic-gate 	 * data.
4687c478bd9Sstevel@tonic-gate 	 */
4697c478bd9Sstevel@tonic-gate 	selfid_size = selfid_size - IEEE1394_QUADLET;
4707c478bd9Sstevel@tonic-gate 	quadlet_count = selfid_size >> 2;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	/* Copy selfid buffer to Services Layer buffer */
4737c478bd9Sstevel@tonic-gate 	for (index = 0; index < quadlet_count; index++) {
4747c478bd9Sstevel@tonic-gate 		hci1394_ohci_selfid_read(soft_state->ohci, index + 1,
4757c478bd9Sstevel@tonic-gate 		    &soft_state->sl_selfid_buf[index]);
4767c478bd9Sstevel@tonic-gate 	}
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	/*
4797c478bd9Sstevel@tonic-gate 	 * Put our selfID info into the Services Layer's selfid buffer if we
4807c478bd9Sstevel@tonic-gate 	 * have a 1394-1995 PHY.
4817c478bd9Sstevel@tonic-gate 	 */
4827c478bd9Sstevel@tonic-gate 	if (soft_state->halinfo.phy == H1394_PHY_1995) {
4837c478bd9Sstevel@tonic-gate 		selfid_buf_p = (uint32_t *)(
4847c478bd9Sstevel@tonic-gate 		    (uintptr_t)soft_state->sl_selfid_buf +
4857c478bd9Sstevel@tonic-gate 		    (uintptr_t)selfid_size);
4867c478bd9Sstevel@tonic-gate 		status = hci1394_ohci_phy_info(soft_state->ohci,
4877c478bd9Sstevel@tonic-gate 		    &selfid_buf_p[0]);
4887c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
4897c478bd9Sstevel@tonic-gate 			/*
4907c478bd9Sstevel@tonic-gate 			 * If we fail reading from PHY, put invalid data into
4917c478bd9Sstevel@tonic-gate 			 * the selfid buffer so the SL will reset the bus again.
4927c478bd9Sstevel@tonic-gate 			 */
4937c478bd9Sstevel@tonic-gate 			selfid_buf_p[0] = 0xFFFFFFFF;
4947c478bd9Sstevel@tonic-gate 			selfid_buf_p[1] = 0xFFFFFFFF;
4957c478bd9Sstevel@tonic-gate 		} else {
4967c478bd9Sstevel@tonic-gate 			selfid_buf_p[1] = ~selfid_buf_p[0];
4977c478bd9Sstevel@tonic-gate 		}
4987c478bd9Sstevel@tonic-gate 		selfid_size = selfid_size + 8;
4997c478bd9Sstevel@tonic-gate 	}
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	/* Flush out async DMA Q's */
5027c478bd9Sstevel@tonic-gate 	hci1394_async_flush(soft_state->async);
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	/*
5057c478bd9Sstevel@tonic-gate 	 * Make sure generation count is still valid.  i.e. we have not gotten
5067c478bd9Sstevel@tonic-gate 	 * another bus reset since the last time we checked.  If we have gotten
5077c478bd9Sstevel@tonic-gate 	 * another bus reset, we should have another selfid interrupt coming.
5087c478bd9Sstevel@tonic-gate 	 */
5097c478bd9Sstevel@tonic-gate 	if (soft_state->drvinfo.di_gencnt !=
5107c478bd9Sstevel@tonic-gate 	    hci1394_ohci_current_busgen(soft_state->ohci)) {
5117c478bd9Sstevel@tonic-gate 		return;
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	/*
5157c478bd9Sstevel@tonic-gate 	 * do whatever CSR register processing that needs to be done.
5167c478bd9Sstevel@tonic-gate 	 */
5177c478bd9Sstevel@tonic-gate 	hci1394_csr_bus_reset(soft_state->csr);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	/*
5207c478bd9Sstevel@tonic-gate 	 * do whatever management may be necessary for the CYCLE_LOST and
5217c478bd9Sstevel@tonic-gate 	 * CYCLE_INCONSISTENT interrupts.
5227c478bd9Sstevel@tonic-gate 	 */
5237c478bd9Sstevel@tonic-gate 	hci1394_isoch_error_ints_enable(soft_state);
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	/*
5267c478bd9Sstevel@tonic-gate 	 * See if we saw an error.  If we did, tell the services layer that we
5277c478bd9Sstevel@tonic-gate 	 * finished selfid processing and give them an illegal selfid buffer
5287c478bd9Sstevel@tonic-gate 	 * size of 0.  The Services Layer will try to reset the bus again to
5297c478bd9Sstevel@tonic-gate 	 * see if we can recover from this problem.  It will threshold after
5307c478bd9Sstevel@tonic-gate 	 * a finite number of errors.
5317c478bd9Sstevel@tonic-gate 	 */
5327c478bd9Sstevel@tonic-gate 	if (saw_error == B_TRUE) {
5337c478bd9Sstevel@tonic-gate 		h1394_self_ids(soft_state->drvinfo.di_sl_private,
5347c478bd9Sstevel@tonic-gate 		    soft_state->sl_selfid_buf, 0, node_id,
5357c478bd9Sstevel@tonic-gate 		    soft_state->drvinfo.di_gencnt);
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 		/*
5387c478bd9Sstevel@tonic-gate 		 * Take ourself out of Bus Reset processing mode
5397c478bd9Sstevel@tonic-gate 		 *
5407c478bd9Sstevel@tonic-gate 		 * Set the driver state to normal. If we cannot, we have been
5417c478bd9Sstevel@tonic-gate 		 * shutdown. The only way we can get in this code is if we have
5427c478bd9Sstevel@tonic-gate 		 * a multi-processor machine and the HAL is shutdown by one
5437c478bd9Sstevel@tonic-gate 		 * processor running in base context while this interrupt
5447c478bd9Sstevel@tonic-gate 		 * handler runs in another processor. We will disable all
5457c478bd9Sstevel@tonic-gate 		 * interrupts and just return.  We shouldn't have to disable
5467c478bd9Sstevel@tonic-gate 		 * the interrupts, but we will just in case.
5477c478bd9Sstevel@tonic-gate 		 */
5487c478bd9Sstevel@tonic-gate 		status = hci1394_state_set(&soft_state->drvinfo,
5497c478bd9Sstevel@tonic-gate 		    HCI1394_NORMAL);
5507c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
5517c478bd9Sstevel@tonic-gate 			hci1394_ohci_intr_master_disable(soft_state->ohci);
5527c478bd9Sstevel@tonic-gate 			return;
5537c478bd9Sstevel@tonic-gate 		}
5547c478bd9Sstevel@tonic-gate 	} else if (IEEE1394_NODE_NUM(node_id) != 63) {
5557c478bd9Sstevel@tonic-gate 		/*
5567c478bd9Sstevel@tonic-gate 		 * Notify services layer about self-id-complete. Don't notify
5577c478bd9Sstevel@tonic-gate 		 * the services layer if there are too many devices on the bus.
5587c478bd9Sstevel@tonic-gate 		 */
5597c478bd9Sstevel@tonic-gate 		h1394_self_ids(soft_state->drvinfo.di_sl_private,
5607c478bd9Sstevel@tonic-gate 		    soft_state->sl_selfid_buf, selfid_size,
5617c478bd9Sstevel@tonic-gate 		    node_id, soft_state->drvinfo.di_gencnt);
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 		/*
5647c478bd9Sstevel@tonic-gate 		 * Take ourself out of Bus Reset processing mode
5657c478bd9Sstevel@tonic-gate 		 *
5667c478bd9Sstevel@tonic-gate 		 * Set the driver state to normal. If we cannot, we have been
5677c478bd9Sstevel@tonic-gate 		 * shutdown. The only way we can get in this code is if we have
5687c478bd9Sstevel@tonic-gate 		 * a multi-processor machine and the HAL is shutdown by one
5697c478bd9Sstevel@tonic-gate 		 * processor running in base context while this interrupt
5707c478bd9Sstevel@tonic-gate 		 * handler runs in another processor. We will disable all
5717c478bd9Sstevel@tonic-gate 		 * interrupts and just return.  We shouldn't have to disable
5727c478bd9Sstevel@tonic-gate 		 * the interrupts, but we will just in case.
5737c478bd9Sstevel@tonic-gate 		 */
5747c478bd9Sstevel@tonic-gate 		status = hci1394_state_set(&soft_state->drvinfo,
5757c478bd9Sstevel@tonic-gate 		    HCI1394_NORMAL);
5767c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
5777c478bd9Sstevel@tonic-gate 			hci1394_ohci_intr_master_disable(soft_state->ohci);
5787c478bd9Sstevel@tonic-gate 			return;
5797c478bd9Sstevel@tonic-gate 		}
5807c478bd9Sstevel@tonic-gate 	} else {
5817c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "hci1394(%d): Too many devices on the 1394 "
5827c478bd9Sstevel@tonic-gate 		    "bus", soft_state->drvinfo.di_instance);
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	/* enable bus reset interrupt */
5867c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_enable(soft_state->ohci, OHCI_INTR_BUS_RESET);
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate /*
5917c478bd9Sstevel@tonic-gate  * hci1394_isr_isoch_ir()
5927c478bd9Sstevel@tonic-gate  *    Process each isoch recv context which has its interrupt asserted.  The
5937c478bd9Sstevel@tonic-gate  *    interrupt will be asserted when an isoch recv descriptor with the
5947c478bd9Sstevel@tonic-gate  *    interrupt bits enabled have finished being processed.
5957c478bd9Sstevel@tonic-gate  */
5967c478bd9Sstevel@tonic-gate static void
hci1394_isr_isoch_ir(hci1394_state_t * soft_state)5977c478bd9Sstevel@tonic-gate hci1394_isr_isoch_ir(hci1394_state_t *soft_state)
5987c478bd9Sstevel@tonic-gate {
5997c478bd9Sstevel@tonic-gate 	uint32_t i;
6007c478bd9Sstevel@tonic-gate 	uint32_t mask = 0x00000001;
6017c478bd9Sstevel@tonic-gate 	uint32_t ev;
6027c478bd9Sstevel@tonic-gate 	int num_ir_contexts;
6037c478bd9Sstevel@tonic-gate 	hci1394_iso_ctxt_t *ctxtp;
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	num_ir_contexts = hci1394_isoch_recv_count_get(soft_state->isoch);
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	/*
6117c478bd9Sstevel@tonic-gate 	 * Main isochRx int is not clearable. it is automatically
6127c478bd9Sstevel@tonic-gate 	 * cleared by the hw when the ir_intr_event is cleared
6137c478bd9Sstevel@tonic-gate 	 */
6147c478bd9Sstevel@tonic-gate 	/* loop until no more IR events */
6157c478bd9Sstevel@tonic-gate 	while ((ev = hci1394_ohci_ir_intr_asserted(soft_state->ohci)) != 0) {
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 		/* clear the events we just learned about */
6187c478bd9Sstevel@tonic-gate 		hci1394_ohci_ir_intr_clear(soft_state->ohci, ev);
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 		/* for each interrupting IR context, process the interrupt */
6217c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_ir_contexts; i++) {
6227c478bd9Sstevel@tonic-gate 			/*
6237c478bd9Sstevel@tonic-gate 			 * if the intr bit is on for a context,
6247c478bd9Sstevel@tonic-gate 			 * call xmit/recv common processing code
6257c478bd9Sstevel@tonic-gate 			 */
6267c478bd9Sstevel@tonic-gate 			if (ev & mask) {
6277c478bd9Sstevel@tonic-gate 				ctxtp = hci1394_isoch_recv_ctxt_get(
628ae85eacfSBarry Harding 				    soft_state->isoch, i);
6297c478bd9Sstevel@tonic-gate 				hci1394_ixl_interrupt(soft_state, ctxtp,
6307c478bd9Sstevel@tonic-gate 				    B_FALSE);
6317c478bd9Sstevel@tonic-gate 			}
6327c478bd9Sstevel@tonic-gate 			mask <<= 1;
6337c478bd9Sstevel@tonic-gate 		}
6347c478bd9Sstevel@tonic-gate 	}
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate /*
6397c478bd9Sstevel@tonic-gate  * hci1394_isr_isoch_it()
6407c478bd9Sstevel@tonic-gate  *    Process each isoch transmit context which has its interrupt asserted.  The
6417c478bd9Sstevel@tonic-gate  *    interrupt will be asserted when an isoch transmit descriptor with the
6427c478bd9Sstevel@tonic-gate  *    interrupt bit is finished being processed.
6437c478bd9Sstevel@tonic-gate  */
6447c478bd9Sstevel@tonic-gate static void
hci1394_isr_isoch_it(hci1394_state_t * soft_state)6457c478bd9Sstevel@tonic-gate hci1394_isr_isoch_it(hci1394_state_t *soft_state)
6467c478bd9Sstevel@tonic-gate {
6477c478bd9Sstevel@tonic-gate 	uint32_t i;
6487c478bd9Sstevel@tonic-gate 	uint32_t mask = 0x00000001;
6497c478bd9Sstevel@tonic-gate 	uint32_t ev;
6507c478bd9Sstevel@tonic-gate 	int num_it_contexts;
6517c478bd9Sstevel@tonic-gate 	hci1394_iso_ctxt_t *ctxtp;
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	num_it_contexts = hci1394_isoch_xmit_count_get(soft_state->isoch);
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	/*
6597c478bd9Sstevel@tonic-gate 	 * Main isochTx int is not clearable. it is automatically
6607c478bd9Sstevel@tonic-gate 	 * cleared by the hw when the it_intr_event is cleared.
6617c478bd9Sstevel@tonic-gate 	 */
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	/* loop until no more IT events */
6647c478bd9Sstevel@tonic-gate 	while ((ev = hci1394_ohci_it_intr_asserted(soft_state->ohci)) != 0) {
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 		/* clear the events we just learned about */
6677c478bd9Sstevel@tonic-gate 		hci1394_ohci_it_intr_clear(soft_state->ohci, ev);
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 		/* for each interrupting IR context, process the interrupt */
6707c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_it_contexts; i++) {
6717c478bd9Sstevel@tonic-gate 			/*
6727c478bd9Sstevel@tonic-gate 			 * if the intr bit is on for a context,
6737c478bd9Sstevel@tonic-gate 			 * call xmit/recv common processing code
6747c478bd9Sstevel@tonic-gate 			 */
6757c478bd9Sstevel@tonic-gate 			if (ev & mask) {
6767c478bd9Sstevel@tonic-gate 				ctxtp = hci1394_isoch_xmit_ctxt_get(
677ae85eacfSBarry Harding 				    soft_state->isoch, i);
6787c478bd9Sstevel@tonic-gate 				hci1394_ixl_interrupt(soft_state, ctxtp,
6797c478bd9Sstevel@tonic-gate 				    B_FALSE);
6807c478bd9Sstevel@tonic-gate 			}
6817c478bd9Sstevel@tonic-gate 			mask <<= 1;
6827c478bd9Sstevel@tonic-gate 		}
6837c478bd9Sstevel@tonic-gate 	}
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate /*
6887c478bd9Sstevel@tonic-gate  * hci1394_isr_atreq_complete()
6897c478bd9Sstevel@tonic-gate  *    Process all completed requests that we have sent out (i.e. HW gave us
6907c478bd9Sstevel@tonic-gate  *    an ack).
6917c478bd9Sstevel@tonic-gate  */
6927c478bd9Sstevel@tonic-gate static void
hci1394_isr_atreq_complete(hci1394_state_t * soft_state)6937c478bd9Sstevel@tonic-gate hci1394_isr_atreq_complete(hci1394_state_t *soft_state)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate 	boolean_t request_available;
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(soft_state->ohci, OHCI_INTR_REQ_TX_CMPLT);
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	/*
7027c478bd9Sstevel@tonic-gate 	 * Processes all ack'd AT requests.  If the request is pended, it is
7037c478bd9Sstevel@tonic-gate 	 * considered complete relative the the atreq engine. AR response
7047c478bd9Sstevel@tonic-gate 	 * processing will make sure we track the response.
7057c478bd9Sstevel@tonic-gate 	 */
7067c478bd9Sstevel@tonic-gate 	do {
7077c478bd9Sstevel@tonic-gate 		/*
7087c478bd9Sstevel@tonic-gate 		 * Process a single request. Do not flush Q. That is only
7097c478bd9Sstevel@tonic-gate 		 * done during bus reset processing.
7107c478bd9Sstevel@tonic-gate 		 */
711*2570281cSToomas Soome 		(void) hci1394_async_atreq_process(soft_state->async, B_FALSE,
7127c478bd9Sstevel@tonic-gate 		    &request_available);
7137c478bd9Sstevel@tonic-gate 	} while (request_available == B_TRUE);
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate /*
7187c478bd9Sstevel@tonic-gate  * hci1394_isr_arresp()
7197c478bd9Sstevel@tonic-gate  *    Process all responses that have come in off the bus and send then up to
7207c478bd9Sstevel@tonic-gate  *    the services layer. We send out a request on the bus (atreq) and some time
7217c478bd9Sstevel@tonic-gate  *    later a response comes in.  We send this response up to the services
7227c478bd9Sstevel@tonic-gate  *    layer.
7237c478bd9Sstevel@tonic-gate  */
7247c478bd9Sstevel@tonic-gate static void
hci1394_isr_arresp(hci1394_state_t * soft_state)7257c478bd9Sstevel@tonic-gate hci1394_isr_arresp(hci1394_state_t *soft_state)
7267c478bd9Sstevel@tonic-gate {
7277c478bd9Sstevel@tonic-gate 	boolean_t response_available;
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(soft_state->ohci, OHCI_INTR_RSPKT);
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	/*
7347c478bd9Sstevel@tonic-gate 	 * Process all responses that have been received.  If more responses
7357c478bd9Sstevel@tonic-gate 	 * come in we will stay in interrupt handler and re-run this routine.
7367c478bd9Sstevel@tonic-gate 	 * It is possible that we will call hci1394_async_arresp_process()
7377c478bd9Sstevel@tonic-gate 	 * even though there are no more AR responses to process.  This would
7387c478bd9Sstevel@tonic-gate 	 * be because we have processed them earlier on. (i.e. we cleared
7397c478bd9Sstevel@tonic-gate 	 * interrupt, then got another response and processed it. The interrupt
7407c478bd9Sstevel@tonic-gate 	 * would still be pending.
7417c478bd9Sstevel@tonic-gate 	 */
7427c478bd9Sstevel@tonic-gate 	do {
743*2570281cSToomas Soome 		(void) hci1394_async_arresp_process(soft_state->async,
7447c478bd9Sstevel@tonic-gate 		    &response_available);
7457c478bd9Sstevel@tonic-gate 	} while (response_available == B_TRUE);
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate /*
7507c478bd9Sstevel@tonic-gate  * hci1394_isr_arreq()
7517c478bd9Sstevel@tonic-gate  *    Process all requests that have come in off the bus and send then up to
7527c478bd9Sstevel@tonic-gate  *    the services layer.
7537c478bd9Sstevel@tonic-gate  */
7547c478bd9Sstevel@tonic-gate static void
hci1394_isr_arreq(hci1394_state_t * soft_state)7557c478bd9Sstevel@tonic-gate hci1394_isr_arreq(hci1394_state_t *soft_state)
7567c478bd9Sstevel@tonic-gate {
7577c478bd9Sstevel@tonic-gate 	boolean_t request_available;
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(soft_state->ohci, OHCI_INTR_RQPKT);
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	/*
7647c478bd9Sstevel@tonic-gate 	 * Process all requests that have been received. It is possible that we
7657c478bd9Sstevel@tonic-gate 	 * will call hci1394_async_arreq_process() even though there are no
7667c478bd9Sstevel@tonic-gate 	 * more requests to process.  This would be because we have processed
7677c478bd9Sstevel@tonic-gate 	 * them earlier on. (i.e. we cleared interrupt, got another request
7687c478bd9Sstevel@tonic-gate 	 * and processed it. The interrupt would still be pending.
7697c478bd9Sstevel@tonic-gate 	 */
7707c478bd9Sstevel@tonic-gate 	do {
771*2570281cSToomas Soome 		(void) hci1394_async_arreq_process(soft_state->async,
7727c478bd9Sstevel@tonic-gate 		    &request_available);
7737c478bd9Sstevel@tonic-gate 	} while (request_available == B_TRUE);
7747c478bd9Sstevel@tonic-gate }
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate /*
7787c478bd9Sstevel@tonic-gate  * hci1394_isr_atresp_complete()
7797c478bd9Sstevel@tonic-gate  *    Process all completed responses that we have sent out (i.e. HW gave us
7807c478bd9Sstevel@tonic-gate  *    an ack). We get in a request off the bus (arreq) and send it up to the
7817c478bd9Sstevel@tonic-gate  *    services layer, they send down a response to that request some time
7827c478bd9Sstevel@tonic-gate  *    later. This interrupt signifies that the HW is done with the response.
7837c478bd9Sstevel@tonic-gate  *    (i.e. it sent it out or failed it)
7847c478bd9Sstevel@tonic-gate  */
7857c478bd9Sstevel@tonic-gate static void
hci1394_isr_atresp_complete(hci1394_state_t * soft_state)7867c478bd9Sstevel@tonic-gate hci1394_isr_atresp_complete(hci1394_state_t *soft_state)
7877c478bd9Sstevel@tonic-gate {
7887c478bd9Sstevel@tonic-gate 	boolean_t response_available;
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(soft_state->ohci, OHCI_INTR_RESP_TX_CMPLT);
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	/*
7957c478bd9Sstevel@tonic-gate 	 * Processes all ack'd AT responses It is possible that we will call
7967c478bd9Sstevel@tonic-gate 	 * hci1394_async_atresp_process() even thought there are no more
7977c478bd9Sstevel@tonic-gate 	 * responses to process.  This would be because we have processed
7987c478bd9Sstevel@tonic-gate 	 * them earlier on. (i.e. we cleared interrupt, then got another
7997c478bd9Sstevel@tonic-gate 	 * response and processed it. The interrupt would still be pending.
8007c478bd9Sstevel@tonic-gate 	 */
8017c478bd9Sstevel@tonic-gate 	do {
8027c478bd9Sstevel@tonic-gate 		/*
8037c478bd9Sstevel@tonic-gate 		 * Process a single response. Do not flush Q. That is only
8047c478bd9Sstevel@tonic-gate 		 * done during bus reset processing.
8057c478bd9Sstevel@tonic-gate 		 */
806*2570281cSToomas Soome 		(void) hci1394_async_atresp_process(soft_state->async,
8077c478bd9Sstevel@tonic-gate 		    B_FALSE, &response_available);
8087c478bd9Sstevel@tonic-gate 	} while (response_available == B_TRUE);
8097c478bd9Sstevel@tonic-gate }
810