コード例 #1
0
ファイル: rmc_comm.c プロジェクト: andreiw/polaris
/*
 * 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);
}
コード例 #2
0
ファイル: ghd.c プロジェクト: MatiasNAmendola/AuroraUX-SunOS
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);
	}
}
コード例 #3
0
static void
ntwdt_cyclic_pat(void)
{
	ddi_trigger_softintr(ntwdt_cyclic_softint_id);
}
コード例 #4
0
/*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);
}
コード例 #5
0
ファイル: sgsbbc.c プロジェクト: andreiw/polaris
/*
 * 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);

}