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); }
/* * 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); } } }
/* * 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); } }