/* * High-level interrupt handler: * Checks whether initialisation is complete (to avoid a race * with mutex_init()), and whether chip interrupts are enabled. * If not, the interrupt's not for us, so just return UNCLAIMED. * Otherwise, disable the interrupt, trigger a softint, and return * CLAIMED. The softint handler will then do all the real work. * * NOTE: the chip interrupt capability is only re-enabled once the * receive code has run, but that can be called from a poll loop * or cyclic callback as well as from the softint. So it's *not* * guaranteed that there really is a chip interrupt pending here, * 'cos the work may already have been done and the reason for the * interrupt gone away before we get here. * * OTOH, if we come through here twice without the receive code * having run in between, that's definitely wrong. In such an * event, we would notice that chip interrupts haven't yet been * re-enabled and return UNCLAIMED, allowing the system's jabber * protect code (if any) to do its job. */ static uint_t rmc_comm_hi_intr(caddr_t arg) { struct rmc_comm_state *rcs = (void *)arg; uint_t claim; claim = DDI_INTR_UNCLAIMED; if (rcs->sd_state.cycid != CYCLIC_NONE) { mutex_enter(rcs->sd_state.hw_mutex); if (rcs->sd_state.hw_int_enabled) { rmc_comm_set_irq(rcs, B_FALSE); ddi_trigger_softintr(rcs->sd_state.softid); claim = DDI_INTR_CLAIMED; } mutex_exit(rcs->sd_state.hw_mutex); } return (claim); }
static void ghd_doneq_pollmode_exit(ccc_t *cccp) { kmutex_t *doneq_mutexp = &cccp->ccc_doneq_mutex; mutex_enter(doneq_mutexp); cccp->ccc_hba_pollmode = FALSE; mutex_exit(doneq_mutexp); /* trigger software interrupt for the completion callbacks */ if (!L2_EMPTY(&cccp->ccc_doneq)) { /* * If we are panicking we should just call the completion * function directly as we can not use soft interrupts * or timeouts during panic. */ if (!ddi_in_panic()) ddi_trigger_softintr(cccp->ccc_doneq_softid); else (void) ghd_doneq_process((caddr_t)cccp); } }
static void ntwdt_cyclic_pat(void) { ddi_trigger_softintr(ntwdt_cyclic_softint_id); }
/*ARGSUSED*/ static uint_t ds1287_intr(caddr_t ignore) { hrtime_t tstamp; static hrtime_t o_tstamp = 0; static hrtime_t power_button_tstamp = 0; static int power_button_cnt; uint8_t apcr1; /* * Stop the Fail-safe timer that starts running * after power button is pressed. If it is not * stopped in 21 seconds, system powers off. */ mutex_enter(&ds1287_reg_mutex); select_bank(2); DS1287_ADDR_REG = APC_APCR1; apcr1 = DS1287_DATA_REG; apcr1 |= APC_FSTRC; DS1287_DATA_REG = apcr1; select_bank(1); mutex_exit(&ds1287_reg_mutex); tstamp = gethrtime(); /* need to deal with power button debounce */ if (o_tstamp && (tstamp - o_tstamp) < power_button_debounce) { o_tstamp = tstamp; return (DDI_INTR_CLAIMED); } o_tstamp = tstamp; power_button_cnt++; mutex_enter(&ds1287_reg_mutex); power_button_pressed++; mutex_exit(&ds1287_reg_mutex); /* * If power button abort is enabled and power button was pressed * power_button_abort_presses times within power_button_abort_interval * then call abort_sequence_enter(); */ if (power_button_abort_enable) { if (power_button_abort_presses == 1 || tstamp < (power_button_tstamp + power_button_abort_interval)) { if (power_button_cnt == power_button_abort_presses) { mutex_enter(&ds1287_reg_mutex); power_button_cancel += power_button_timeouts; power_button_pressed = 0; mutex_exit(&ds1287_reg_mutex); power_button_cnt = 0; abort_sequence_enter("Power Button Abort"); return (DDI_INTR_CLAIMED); } } else { power_button_cnt = 1; power_button_tstamp = tstamp; } } if (!power_button_enable) return (DDI_INTR_CLAIMED); /* post softint to issue timeout for power button action */ ddi_trigger_softintr(ds1287_softintr_id); return (DDI_INTR_CLAIMED); }
/* * SBBC Interrupt Handler * * Check the SBBC Port Interrupt Status * register to verify that its our interrupt. * If yes, clear the register. * * Then read the 'interrupt reason' field from SRAM, * this triggers the appropriate soft_intr handler */ uint_t sbbc_intr_handler(caddr_t arg) { sbbc_softstate_t *softsp = (sbbc_softstate_t *)arg; uint32_t *port_int_reg; volatile uint32_t port_int_status; volatile uint32_t intr_reason; uint32_t intr_enabled; sbbc_intrs_t *intr; int i, intr_mask; struct tunnel_key tunnel_key; ddi_acc_handle_t intr_in_handle; uint32_t *intr_in_reason; if (softsp == (sbbc_softstate_t *)NULL) { return (DDI_INTR_UNCLAIMED); } mutex_enter(&softsp->sbbc_lock); if (softsp->port_int_regs == NULL) { mutex_exit(&softsp->sbbc_lock); return (DDI_INTR_UNCLAIMED); } /* * Normally if port_int_status is 0, we assume it is not * our interrupt. However, we don't want to miss the * ones that come in during tunnel switch. Therefore, * we always check the interrupt reason bits in IOSRAM * to be sure. */ port_int_reg = softsp->port_int_regs; port_int_status = ddi_get32(softsp->sbbc_reg_handle1, port_int_reg); /* * Generate a softint for each interrupt * bit set in the intr_in_reason field in SRAM * that has a corresponding bit set in the * intr_in_enabled field in SRAM */ if (iosram_read(SBBC_SC_INTR_ENABLED_KEY, 0, (caddr_t)&intr_enabled, sizeof (intr_enabled))) { goto intr_handler_exit; } tunnel_key = master_iosram->tunnel->tunnel_keys[SBBC_SC_INTR_KEY]; intr_in_reason = (uint32_t *)tunnel_key.base; intr_in_handle = tunnel_key.reg_handle; intr_reason = ddi_get32(intr_in_handle, intr_in_reason); SGSBBC_DBG_INTR(CE_CONT, "intr_reason = %x\n", intr_reason); intr_reason &= intr_enabled; for (i = 0; i < SBBC_MAX_INTRS; i++) { intr_mask = (1 << i); if (intr_reason & intr_mask) { intr = &softsp->intr_hdlrs[i]; if ((intr != NULL) && (intr->sbbc_intr_id != 0)) { /* * XXXX * The model we agree with a handler * is that they run until they have * exhausted all work. To avoid * triggering them again, they pass * a state flag and lock when registering. * We check the flag, if they are idle, * we trigger. * The interrupt handler should so * intr_func() * mutex_enter(sbbc_intr_lock); * sbbc_intr_state = RUNNING; * mutex_exit(sbbc_intr_lock); * .......... * .......... * .......... * mutex_enter(sbbc_intr_lock); * sbbc_intr_state = IDLE; * mutex_exit(sbbc_intr_lock); * * XXXX */ mutex_enter(intr->sbbc_intr_lock); if (*(intr->sbbc_intr_state) == SBBC_INTR_IDLE) { mutex_exit(intr->sbbc_intr_lock); ddi_trigger_softintr( intr->sbbc_intr_id); } else { /* * The handler is running */ mutex_exit(intr->sbbc_intr_lock); } intr_reason &= ~intr_mask; /* * Clear the corresponding reason bit in SRAM * * Since there is no interlocking between * Solaris and the SC when writing to SRAM, * it is possible for the SC to set another * bit in the interrupt reason field while * we are handling the current interrupt. * To minimize the window in which an * additional bit can be set, reading * and writing the interrupt reason * in SRAM must be as close as possible. */ ddi_put32(intr_in_handle, intr_in_reason, ddi_get32(intr_in_handle, intr_in_reason) & ~intr_mask); } } if (intr_reason == 0) /* No more interrupts to be processed */ break; } /* * Clear the Interrupt Status Register (RW1C) */ ddi_put32(softsp->sbbc_reg_handle1, port_int_reg, port_int_status); port_int_status = ddi_get32(softsp->sbbc_reg_handle1, port_int_reg); intr_handler_exit: mutex_exit(&softsp->sbbc_lock); return (DDI_INTR_CLAIMED); }