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