Exemple #1
0
static void
cvcr_ioctl(queue_t *q, mblk_t *mp)
{
	struct iocblk	*iocp = (struct iocblk *)mp->b_rptr;
	int		error;

	switch (iocp->ioc_cmd) {
	case CVC_BREAK:
		abort_sequence_enter(NULL);
		miocack(q, mp, 0, 0);
		break;

	case CVC_DISCONNECT:
	case TIOCSWINSZ:
		/*
		 * Generate a SIGHUP or SIGWINCH to the console.  Note in this
		 * case cvc_redir does not free up mp, so we can reuse it for
		 * the ACK/NAK.
		 */
		error = cvc_redir(mp);
		if (error != 0)
			miocnak(q, mp, 0, error);
		else
			miocack(q, mp, 0, 0);
		break;

	default:
		miocnak(q, mp, 0, EINVAL);
		break;
	}
}
/*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);
}
Exemple #3
0
/*
 * cvc_iosram_ops()
 *	Process commands sent to cvc from netcon_server via IOSRAM
 */
static void
cvc_iosram_ops(uint8_t op)
{
	int		rval = ESUCCESS;
	static uint8_t	stale_op = 0;

	ASSERT(MUTEX_HELD(&cvc_iosram_input_mutex));

	CVC_DBG1(CVC_DBG_IOSRAM_CNTL, "cntl msg 0x%x", op);

	/*
	 * If this is a repeated notice of a command that was previously
	 * processed but couldn't be cleared due to EAGAIN (tunnel switch in
	 * progress), just clear the data_valid flag and return.
	 */
	if (op == stale_op) {
		if (iosram_set_flag(IOSRAM_KEY_CONC, IOSRAM_DATA_INVALID,
		    IOSRAM_INT_NONE) == 0) {
			stale_op = 0;
		}
		return;
	}
	stale_op = 0;

	switch (op) {
		case CVC_IOSRAM_BREAK:		/* A console break (L1-A) */
			abort_sequence_enter((char *)NULL);
			break;

		case CVC_IOSRAM_DISCONNECT:	/* Break connection, hang up */
			if (cvcinput_q)
				(void) putnextctl(cvcinput_q, M_HANGUP);
			break;

		case CVC_IOSRAM_VIA_NET:	/* console via network */
			via_iosram = 0;
			break;

		case CVC_IOSRAM_VIA_IOSRAM:	/* console via iosram */
			via_iosram = 1;
			/*
			 * Tell cvcd to close any network connection it has.
			 */
			rw_enter(&cvclock, RW_READER);
			if (cvcoutput_q != NULL) {
				(void) putnextctl(cvcoutput_q, M_HANGUP);
			}
			rw_exit(&cvclock);
			break;

		case CVC_IOSRAM_WIN_RESIZE:	/* console window size data */
			/*
			 * In the case of window resizing, we don't want to
			 * record a stale_op value because we should always use
			 * the most recent winsize info, which could change
			 * between the time that we fail to clear the flag and
			 * the next time we try to process the command.  So,
			 * we'll just let cvc_win_resize clear the data_valid
			 * flag itself (hence the TRUE parameter) and not worry
			 * about whether or not it succeeds.
			 */
			cvc_win_resize(TRUE);
			return;
			/* NOTREACHED */

		default:
			cmn_err(CE_WARN, "cvc: unknown IOSRAM opcode %d", op);
			break;
	}

	/*
	 * Clear CONC's data_valid flag to indicate that the chunk is available
	 * for further communications.  If the flag can't be cleared due to an
	 * error, record the op value so we'll know to ignore it when we see it
	 * on the next poll.
	 */
	rval = iosram_set_flag(IOSRAM_KEY_CONC, IOSRAM_DATA_INVALID,
	    IOSRAM_INT_NONE);
	if (rval != 0) {
		stale_op = op;
		if (rval != EAGAIN) {
			cmn_err(CE_WARN,
			    "cvc_iosram_ops: set flag for cntlbuf ret %d",
			    rval);
		}
	}
}
Exemple #4
0
/*
 * Process a byte received from the keyboard
 */
static void
kb8042_received_byte(
	struct kb8042	*kb8042,
	int		scancode)	/* raw scan code */
{
	boolean_t	legit;		/* is this a legit key pos'n? */
	int		key_pos = -1;
	enum keystate	state;
	boolean_t	synthetic_release_needed;

#ifdef	KD_DEBUG
	kb8042_debug_hotkey(scancode);
#endif

	if (!kb8042->w_init)	/* can't do anything anyway */
		return;

	legit = KeyboardConvertScan(kb8042, scancode, &key_pos, &state,
		&synthetic_release_needed);

	if (legit == 0) {
		/* Eaten by translation */
#ifdef	KD_DEBUG
		if (kb8042_debug)
			prom_printf("kb8042_intr: 0x%x -> ignored\n", scancode);
#endif
		return;
	}

#ifdef	KD_DEBUG
	if (kb8042_debug) {
		prom_printf("kb8042_intr:  0x%x -> %s %d",
			scancode,
			state == KEY_RELEASED ? "released" : "pressed",
			key_pos);
	}
#endif

	/*
	 * Don't know if we want this permanently, but it seems interesting
	 * for the moment.
	 */
	if (key_pos == kb8042->debugger.mod1) {
#ifdef	KD_DEBUG
		if (kb8042_debug)
			prom_printf(" -> debug mod1");
#endif
		kb8042->debugger.mod1_down = (state == KEY_PRESSED);
	}
	if (key_pos == kb8042->debugger.mod2) {
#ifdef	KD_DEBUG
		if (kb8042_debug)
			prom_printf(" -> debug mod2");
#endif
		kb8042->debugger.mod2_down = (state == KEY_PRESSED);
	}
	if (kb8042->debugger.enabled &&
	    key_pos == kb8042->debugger.trigger &&
	    kb8042->debugger.mod1_down &&
	    kb8042->debugger.mod2_down) {
#ifdef	KD_DEBUG
		if (kb8042_debug)
			prom_printf(" -> debugger\n");
#endif
		/*
		 * Require new presses of the modifiers.
		 */
		kb8042->debugger.mod1_down = B_FALSE;
		kb8042->debugger.mod2_down = B_FALSE;
		abort_sequence_enter(NULL);
		return;
	}

	/*
	 * If there's no queue above us - as can happen if we've been
	 * attached but not opened - drop the keystroke.
	 * Note that we do this here instead of above so that
	 * Ctrl-Alt-D still works.
	 */
	if (kb8042->w_qp == NULL) {
#ifdef	KD_DEBUG
		if (kb8042_debug)
			prom_printf(" -> nobody home\n");
#endif
		return;
	}

	/*
	 * This is to filter out auto repeat since it can't be
	 * turned off at the hardware.  (Yeah, yeah, PS/2 keyboards
	 * can.  Don't know whether they've taken over the world.
	 * Don't think so.)
	 */
	if (kb8042_autorepeat_detect(kb8042, key_pos, state)) {
#ifdef	KD_DEBUG
		if (kb8042_debug)
			prom_printf(" -> autorepeat ignored\n");
#endif
		return;
	}

#ifdef	KD_DEBUG
	if (kb8042_debug)
		prom_printf(" -> OK\n");
#endif

#if	defined(KD_DEBUG)
	if (kb8042_pressrelease_debug) {
		prom_printf(" %s%d ",
			state == KEY_PRESSED ? "+" : "-",
			key_pos);
	}
#endif

		kb8042_process_key(kb8042, key_pos, state);

	/*
	 * This is a total hack.  For some stupid reason, the two additional
	 * keys on Korean keyboards (Hangul and Hangul/Hanja) report press
	 * only.  We synthesize a release immediately.
	 */
	if (synthetic_release_needed) {
#if	defined(KD_DEBUG)
		if (kb8042_debug)
			prom_printf("synthetic release %d\n", key_pos);
		if (kb8042_pressrelease_debug)
			prom_printf(" -%d(s) ", key_pos);
#endif
		(void) kb8042_autorepeat_detect(kb8042, key_pos, KEY_RELEASED);
		kb8042_process_key(kb8042, key_pos, state);
	}
}