46#include "opt_syscons.h"
57#include <sys/kernel.h>
58#include <sys/malloc.h>
59#include <sys/msgbuf.h>
64#include <sys/reboot.h>
65#include <sys/sysctl.h>
73#include <dev/kbd/kbdreg.h>
75#include <machine/cpu.h>
76#include <machine/clock.h>
82 struct consdev *cnd_cn;
85#define CNDEVPATHMAX 32
86#define CNDEVTAB_SIZE 4
89 STAILQ_HEAD_INITIALIZER(cn_devlist);
91int cons_avail_mask = 0;
98SYSCTL_INT(_kern, OID_AUTO, consmute, CTLFLAG_RW, &cn_mute, 0,
99 "State of the console muting");
102static struct callout conscallout;
103struct msgbuf consmsgbuf;
104static bool console_pausing;
105static const char console_pausestr[] =
106"<pause; press any key to proceed to next line or '.' to end pause mode>";
108static struct mtx constty_mtx;
109MTX_SYSINIT(constty_mtx, &constty_mtx,
"constty_mtx", MTX_DEF);
110static struct mtx cnputs_mtx;
111MTX_SYSINIT(cnputs_mtx, &cnputs_mtx,
"cnputs_mtx", MTX_SPIN | MTX_NOWITNESS);
115static struct consdev cons_consdev;
116DATA_SET(cons_set, cons_consdev);
135 struct consdev *best_cn, *cn, **list;
146 |RB_ASKNAME)) == RB_MUTE);
160 SET_FOREACH(list, cons_set) {
164 if (cn->cn_ops == NULL)
166 cn->cn_ops->cn_probe(cn);
167 if (cn->cn_pri == CN_DEAD)
169 if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri)
175 cn->cn_ops->cn_init(cn);
182 best_cn->cn_ops->cn_init(best_cn);
186 console_pausing =
true;
203 console_pausing =
false;
213 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
214 if (cnd->cnd_cn == cn)
218 if (cnd->cnd_cn == NULL)
221 if (cnd->cnd_cn != NULL)
224 if (cn->cn_name[0] ==
'\0') {
226 printf(
"WARNING: console at %p has no name\n", cn);
228 STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next);
229 if (STAILQ_FIRST(&cn_devlist) == cnd)
233 cnavailable(cn, (cn->cn_flags & CN_FLAG_NOAVAIL) == 0);
244 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
245 if (cnd->cnd_cn != cn)
247 if (STAILQ_FIRST(&cn_devlist) == cnd)
249 STAILQ_REMOVE(&cn_devlist, cnd,
cn_device, cnd_next);
255 cons_avail_mask &= ~(1 << i);
264 if (cn->cn_term != NULL)
265 cn->cn_ops->cn_term(cn);
276 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
277 if (cnd->cnd_cn != cn)
279 if (cnd == STAILQ_FIRST(&cn_devlist))
281 STAILQ_REMOVE(&cn_devlist, cnd,
cn_device, cnd_next);
282 STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next);
299 cons_avail_mask |= (1 << i);
300 cn->cn_flags &= ~CN_FLAG_NOAVAIL;
303 cons_avail_mask &= ~(1 << i);
304 cn->cn_flags |= CN_FLAG_NOAVAIL;
312 return (cons_avail_mask == 0);
322 struct consdev *cp, **list;
333 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
336 SET_FOREACH(list, cons_set) {
338 if (cp->cn_name[0] !=
'\0')
343 if (error == 0 && req->newptr != NULL) {
351 SET_FOREACH(list, cons_set) {
353 if (strcmp(p, cp->cn_name) != 0)
371 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 0, 0,
373 "Console device control");
381 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
383 if (!
kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
384 cn->cn_ops->cn_grab(cn);
394 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
396 if (!
kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
397 cn->cn_ops->cn_ungrab(cn);
407 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
409 if (cn->cn_ops->cn_resume != NULL)
410 cn->cn_ops->cn_resume(cn);
440 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
442 if (!
kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
443 c = cn->cn_ops->cn_getc(cn);
452cngets(
char *cp,
size_t size,
int visible)
506 if (early_putc != NULL) {
514 if (cn_mute || c ==
'\0')
516 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
518 if (!
kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
520 cn->cn_ops->cn_putc(cn,
'\r');
521 cn->cn_ops->cn_putc(cn, c);
524 if (console_pausing && c ==
'\n' && !
kdb_active) {
525 for (cp = console_pausestr; *cp !=
'\0'; cp++)
529 console_pausing =
false;
532 for (cp = console_pausestr; *cp !=
'\0'; cp++)
542 bool unlock_reqd =
false;
544 if (mtx_initialized(&cnputs_mtx)) {
550 if (mtx_owned(&cnputs_mtx))
552 mtx_lock_spin(&cnputs_mtx);
556 for (i = 0; i < n; i++)
560 mtx_unlock_spin(&cnputs_mtx);
571 0,
"Console tty buffer size");
582 tty_assert_locked(tp);
588 if (consbuf == NULL) {
593 mtx_lock(&constty_mtx);
594 if (constty != NULL) {
595 mtx_unlock(&constty_mtx);
599 if (consbuf == NULL) {
605 mtx_unlock(&constty_mtx);
607 callout_init_mtx(&conscallout, tty_getlock(tp), 0);
620 tty_assert_locked(tp);
623 callout_stop(&conscallout);
624 mtx_lock(&constty_mtx);
626 mtx_unlock(&constty_mtx);
637 "Times per second to check for pending console tty messages");
642 struct tty *tp = arg;
645 tty_assert_locked(tp);
663static struct callout beeping_timer;
666sysbeepstop(
void *chan)
669 timer_spkr_release();
674sysbeep(
int pitch, sbintime_t duration)
677 if (timer_spkr_acquire()) {
683 timer_spkr_setfreq(pitch);
686 callout_reset_sbt(&beeping_timer, duration, 0, sysbeepstop,
693sysbeep_init(
void *unused)
698SYSINIT(
sysbeep, SI_SUB_SOFTINTR, SI_ORDER_ANY, sysbeep_init, NULL);
706sysbeep(
int pitch __unused, sbintime_t duration __unused)
720 0,
"Console vty driver");
725 static unsigned vty_selected = 0;
727 if (vty_selected == 0) {
732 vty_selected = VTY_SC;
738 vty_selected = VTY_VT;
747 vty_selected = VTY_VT;
749 vty_selected = VTY_SC;
753 if (vty_selected == VTY_VT)
755 else if (vty_selected == VTY_SC)
758 return ((vty_selected & vty) != 0);
SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init, NULL)
SET_DECLARE(sysinit_set, struct sysinit)
SYSCTL_STRING(_kern, OID_AUTO, vty, CTLFLAG_RDTUN|CTLFLAG_NOFETCH, vty_name, 0, "Console vty driver")
SYSCTL_UINT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RWTUN, &consmsgbuf_size, 0, "Console tty buffer size")
static int constty_wakeups_per_second
static unsigned vty_prefer
void cngets(char *cp, size_t size, int visible)
static struct cn_device cn_devtab[CNDEVTAB_SIZE]
void cnavailable(struct consdev *cn, int available)
void vty_set_preferred(unsigned vty)
static void constty_timeout(void *arg)
int cnadd(struct consdev *cn)
static int sysctl_kern_console(SYSCTL_HANDLER_ARGS)
int sysbeep(int pitch __unused, sbintime_t duration __unused)
static STAILQ_HEAD(cn_device)
static unsigned int consmsgbuf_size
SYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_NEEDGIANT, 0, 0, sysctl_kern_console, "A", "Console device control")
SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW, &constty_wakeups_per_second, 0, "Times per second to check for pending console tty messages")
void cnputsn(const char *p, size_t n)
static MALLOC_DEFINE(M_TTYCONS, "tty console", "tty console handling")
int vty_enabled(unsigned vty)
int constty_clear(struct tty *tp)
void cnputs(const char *p)
void cnselect(struct consdev *cn)
int constty_set(struct tty *tp)
void cnremove(struct consdev *cn)
MTX_SYSINIT(et_eventtimers_init, &et_eventtimers_mtx, "et_mtx", MTX_DEF)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
int sysctl_handle_string(SYSCTL_HANDLER_ARGS)
void callout_init(struct callout *c, int mpsafe)
u_char __read_frequently kdb_active
int msgbuf_getchar(struct msgbuf *mbp)
void msgbuf_init(struct msgbuf *mbp, void *ptr, int size)
int printf(const char *fmt,...)
int sbuf_finish(struct sbuf *s)
void sbuf_delete(struct sbuf *s)
int sbuf_printf(struct sbuf *s, const char *fmt,...)
ssize_t sbuf_len(struct sbuf *s)
char * sbuf_data(struct sbuf *s)
void sbuf_clear(struct sbuf *s)
struct sbuf * sbuf_new(struct sbuf *s, char *buf, int length, int flags)
void ttyconsdev_select(const char *name)
int tty_putchar(struct tty *tp, char c)