/* * hci1394_isr_mask_setup() * Setup the initial interrupt mask for OpenHCI. These are the interrupts * that our interrupt handler is expected to handle. */ void hci1394_isr_mask_setup(hci1394_state_t *soft_state) { ASSERT(soft_state != NULL); TNF_PROBE_0_DEBUG(hci1394_isr_mask_setup_enter, HCI1394_TNF_HAL_STACK, ""); /* start off with all interrupts cleared/disabled */ hci1394_ohci_ir_intr_disable(soft_state->ohci, 0xFFFFFFFF); hci1394_ohci_ir_intr_clear(soft_state->ohci, 0xFFFFFFFF); hci1394_ohci_it_intr_disable(soft_state->ohci, 0xFFFFFFFF); hci1394_ohci_it_intr_clear(soft_state->ohci, 0xFFFFFFFF); hci1394_ohci_intr_disable(soft_state->ohci, 0xFFFFFFFF); hci1394_ohci_intr_clear(soft_state->ohci, 0xFFFFFFFF); /* Setup Interrupt Mask Register */ hci1394_ohci_intr_enable(soft_state->ohci, (OHCI_INTR_UNRECOVERABLE_ERR | OHCI_INTR_CYC_TOO_LONG | OHCI_INTR_BUS_RESET | OHCI_INTR_SELFID_CMPLT | OHCI_INTR_REQ_TX_CMPLT | OHCI_INTR_RESP_TX_CMPLT | OHCI_INTR_RQPKT | OHCI_INTR_RSPKT | OHCI_INTR_ISOCH_TX | OHCI_INTR_ISOCH_RX | OHCI_INTR_POST_WR_ERR | OHCI_INTR_PHY | OHCI_INTR_LOCK_RESP_ERR)); TNF_PROBE_0_DEBUG(hci1394_isr_mask_setup_exit, HCI1394_TNF_HAL_STACK, ""); }
/* * hci1394_isr_bus_reset() * Process a 1394 bus reset. This signifies that a bus reset has started. * A bus reset will not be complete until a selfid complete interrupt * comes in. */ static void hci1394_isr_bus_reset(hci1394_state_t *soft_state) { int status; ASSERT(soft_state != NULL); TNF_PROBE_0_DEBUG(hci1394_isr_bus_reset_enter, HCI1394_TNF_HAL_STACK, ""); /* * Set the driver state to reset. If we cannot, we have been shutdown. * The only way we can get in this code is if we have a multi-processor * machine and the HAL is shutdown by one processor running in base * context while this interrupt handler runs in another processor. * We will disable all interrupts and just return. We shouldn't have * to disable the interrupts, but we will just in case. */ status = hci1394_state_set(&soft_state->drvinfo, HCI1394_BUS_RESET); if (status != DDI_SUCCESS) { hci1394_ohci_intr_master_disable(soft_state->ohci); return; } /* * Save away reset generation count so we can detect self-id-compete * interrupt which disappears in event register. This is discussed in * more detail in hci1394_isr() */ soft_state->drvinfo.di_gencnt = hci1394_ohci_current_busgen(soft_state->ohci); soft_state->drvinfo.di_stats.st_bus_reset_count++; /* * Mask off busReset until SelfIdComplete comes in. The bus reset * interrupt will be asserted until the SelfIdComplete interrupt * comes in (i.e. you cannot clear the interrupt until a SelfIdComplete * interrupt). Therefore, we disable the interrupt via its mask so we * don't get stuck in the ISR indefinitely. */ hci1394_ohci_intr_disable(soft_state->ohci, OHCI_INTR_BUS_RESET); /* Reset the ATREQ and ATRESP Q's */ hci1394_async_atreq_reset(soft_state->async); hci1394_async_atresp_reset(soft_state->async); /* Inform Services Layer about Bus Reset */ h1394_bus_reset(soft_state->drvinfo.di_sl_private, (void **)&soft_state->sl_selfid_buf); TNF_PROBE_0_DEBUG(hci1394_isr_bus_reset_exit, HCI1394_TNF_HAL_STACK, ""); }
/* * hci1394_isoch_cycle_inconsistent() * Called during interrupt notification to indicate that the cycle time * has changed unexpectedly. We need to take this opportunity to * update our tracking of each running transmit context's execution. * cycle_inconsistent only affects transmit, so recv contexts are left alone. */ void hci1394_isoch_cycle_inconsistent(hci1394_state_t *soft_statep) { int i, cnt_thresh; boolean_t note; hrtime_t current_time, last_time, delta, delta_thresh; hci1394_iso_ctxt_t *ctxtp; /* current context */ ASSERT(soft_statep); TNF_PROBE_0_DEBUG(hci1394_isoch_cycle_inconsistent_enter, HCI1394_TNF_HAL_STACK_ISOCH, ""); hci1394_ohci_intr_clear(soft_statep->ohci, OHCI_INTR_CYC_INCONSISTENT); /* grab the mutex before checking each context's INUSE and RUNNING */ mutex_enter(&soft_statep->isoch->ctxt_list_mutex); /* check for transmit contexts which are inuse and running */ for (i = 0; i < soft_statep->isoch->ctxt_xmit_count; i++) { ctxtp = &soft_statep->isoch->ctxt_xmit[i]; if ((ctxtp->ctxt_flags & (HCI1394_ISO_CTXT_INUSE | HCI1394_ISO_CTXT_RUNNING)) != 0) { mutex_exit(&soft_statep->isoch->ctxt_list_mutex); hci1394_ixl_interrupt(soft_statep, ctxtp, B_FALSE); mutex_enter(&soft_statep->isoch->ctxt_list_mutex); } } /* * get the current time and calculate the delta between now and * when the last interrupt was processed. (NOTE: if the time * returned by gethrtime() rolls-over while we are counting these * interrupts, we will incorrectly restart the counting process. * However, because the probability of this happening is small and * not catching the roll-over will AT MOST double the time it takes * us to discover and correct from this condition, we can safely * ignore it.) */ current_time = gethrtime(); last_time = soft_statep->isoch->cycle_incon_thresh.last_intr_time; delta = current_time - last_time; /* * compare the calculated delta to the delta T threshold. If it * is less than the threshold, then increment the counter. If it * is not then reset the counter. */ delta_thresh = soft_statep->isoch->cycle_incon_thresh.delta_t_thresh; if (delta < delta_thresh) soft_statep->isoch->cycle_incon_thresh.delta_t_counter++; else soft_statep->isoch->cycle_incon_thresh.delta_t_counter = 0; /* * compare the counter to the counter threshold. If it is greater, * then disable the cycle inconsistent interrupt. */ cnt_thresh = soft_statep->isoch->cycle_incon_thresh.counter_thresh; note = B_FALSE; if (soft_statep->isoch->cycle_incon_thresh.delta_t_counter > cnt_thresh) { hci1394_ohci_intr_disable(soft_statep->ohci, OHCI_INTR_CYC_INCONSISTENT); note = B_TRUE; } /* save away the current time into the last_intr_time field */ soft_statep->isoch->cycle_incon_thresh.last_intr_time = current_time; mutex_exit(&soft_statep->isoch->ctxt_list_mutex); if (note == B_TRUE) { cmn_err(CE_NOTE, "!hci1394(%d): cycle_inconsistent interrupt " "disabled until next bus reset", soft_statep->drvinfo.di_instance); TNF_PROBE_1(hci1394_isoch_cycle_inconsistent_error, HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string, msg, "CYCLE_INCONSISTENT intr disabled until next bus reset"); } TNF_PROBE_0_DEBUG(hci1394_isoch_cycle_inconsistent_exit, HCI1394_TNF_HAL_STACK_ISOCH, ""); }