40 #include <sys/cdefs.h>
45 #include <sys/param.h>
46 #include <sys/systm.h>
48 #include <sys/mutex.h>
51 #include <sys/fcntl.h>
53 #include <sys/kernel.h>
54 #include <sys/malloc.h>
55 #include <sys/msgbuf.h>
56 #include <sys/namei.h>
59 #include <sys/queue.h>
60 #include <sys/reboot.h>
61 #include <sys/sysctl.h>
65 #include <sys/vnode.h>
69 #include <machine/cpu.h>
70 #include <machine/clock.h>
72 static MALLOC_DEFINE(M_TTYCONS,
"tty console",
"tty console handling");
76 struct consdev *cnd_cn;
79 #define CNDEVPATHMAX 32
80 #define CNDEVTAB_SIZE 4
83 STAILQ_HEAD_INITIALIZER(cn_devlist);
85 int cons_avail_mask = 0;
92 static struct callout conscallout;
93 struct msgbuf consmsgbuf;
94 static u_char console_pausing;
95 static
char *console_pausestr=
96 "<
pause; press any key to proceed to next line or '.' to end pause
mode>";
98 static struct mtx cnputs_mtx;
99 static
int use_cnputs_mtx = 0;
103 static struct consdev cons_consdev;
104 DATA_SET(cons_set, cons_consdev);
110 struct consdev *best_cn, *cn, **list;
121 |RB_ASKNAME)) == RB_MUTE);
127 SET_FOREACH(list, cons_set) {
131 if (cn->cn_ops == NULL)
133 cn->cn_ops->cn_probe(cn);
134 if (cn->cn_pri == CN_DEAD)
136 if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri)
142 cn->cn_ops->cn_init(cn);
149 best_cn->cn_ops->cn_init(best_cn);
173 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
174 if (cnd->cnd_cn == cn)
178 if (cnd->cnd_cn == NULL)
181 if (cnd->cnd_cn != NULL)
184 if (cn->cn_name[0] ==
'\0') {
186 printf(
"WARNING: console at %p has no name\n", cn);
188 STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next);
189 if (STAILQ_FIRST(&cn_devlist) == cnd)
193 cnavailable(cn, (cn->cn_flags & CN_FLAG_NOAVAIL) == 0);
204 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
205 if (cnd->cnd_cn != cn)
207 if (STAILQ_FIRST(&cn_devlist) == cnd)
209 STAILQ_REMOVE(&cn_devlist, cnd,
cn_device, cnd_next);
215 cons_avail_mask &= ~(1 << i);
224 if (cn->cn_term != NULL)
225 cn->cn_ops->cn_term(cn);
236 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
237 if (cnd->cnd_cn != cn)
239 if (cnd == STAILQ_FIRST(&cn_devlist))
241 STAILQ_REMOVE(&cn_devlist, cnd,
cn_device, cnd_next);
242 STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next);
258 if (i < CNDEVTAB_SIZE)
259 cons_avail_mask |= (1 << i);
260 cn->cn_flags &= ~CN_FLAG_NOAVAIL;
262 if (i < CNDEVTAB_SIZE)
263 cons_avail_mask &= ~(1 << i);
264 cn->cn_flags |= CN_FLAG_NOAVAIL;
272 return (cons_avail_mask == 0);
282 struct consdev *cp, **list;
291 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
294 SET_FOREACH(list, cons_set) {
296 if (cp->cn_name[0] !=
'\0')
301 if (error == 0 && req->newptr != NULL) {
309 SET_FOREACH(list, cons_set) {
311 if (strcmp(p, cp->cn_name) != 0)
328 SYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW,
341 if (error != 0 || req->newptr == NULL)
346 SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW,
348 "State of the console muting");
356 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
358 if (!
kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
359 cn->cn_ops->cn_grab(cn);
369 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
371 if (!
kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
372 cn->cn_ops->cn_ungrab(cn);
402 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
404 if (!
kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
405 c = cn->cn_ops->cn_getc(cn);
414 cngets(
char *cp,
size_t size,
int visible)
469 if (cn_mute || c ==
'\0')
471 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
473 if (!
kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
475 cn->cn_ops->cn_putc(cn,
'\r');
476 cn->cn_ops->cn_putc(cn, c);
479 if (console_pausing && c ==
'\n' && !
kdb_active) {
480 for (cp = console_pausestr; *cp !=
'\0'; cp++)
487 for (cp = console_pausestr; *cp !=
'\0'; cp++)
499 if (use_cnputs_mtx) {
505 if (mtx_owned(&cnputs_mtx))
507 mtx_lock_spin(&cnputs_mtx);
511 while ((c = *p++) !=
'\0')
515 mtx_unlock_spin(&cnputs_mtx);
519 SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0,
520 "Console tty buffer size");
530 KASSERT(tp != NULL, (
"constty_set: NULL tp"));
531 if (consbuf == NULL) {
533 consbuf =
malloc(size, M_TTYCONS, M_WAITOK);
552 callout_stop(&conscallout);
555 free(consbuf, M_TTYCONS);
561 SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW,
562 &constty_wakeups_per_second, 0,
563 "Times per second to check for pending console tty messages");
570 if (constty != NULL) {
583 if (constty != NULL) {
584 callout_reset(&conscallout,
hz / constty_wakeups_per_second,
596 mtx_init(&cnputs_mtx,
"cnputs_mtx", NULL, MTX_SPIN | MTX_NOWITNESS);
606 #ifdef HAS_TIMER_SPKR
611 sysbeepstop(
void *chan)
614 timer_spkr_release();
622 if (timer_spkr_acquire()) {
628 timer_spkr_setfreq(pitch);
631 timeout(sysbeepstop, (
void *)NULL, period);
643 sysbeep(
int pitch __unused,
int period __unused)
static int sysctl_kern_consmute(SYSCTL_HANDLER_ARGS)
struct callout_handle timeout(timeout_t *ftn, void *arg, int to_ticks)
SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL)
static void constty_timeout(void *arg)
ssize_t sbuf_len(struct sbuf *s)
void cngets(char *cp, size_t size, int visible)
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
void cnselect(struct consdev *cn)
int sysctl_handle_string(SYSCTL_HANDLER_ARGS)
static STAILQ_HEAD(cn_device)
SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW,&consmsgbuf_size, 0,"Console tty buffer size")
void msgbuf_init(struct msgbuf *mbp, void *ptr, int size)
void sbuf_clear(struct sbuf *s)
static int sysctl_kern_console(SYSCTL_HANDLER_ARGS)
void ttyconsdev_select(const char *name)
int sbuf_printf(struct sbuf *s, const char *fmt,...)
int tty_putchar(struct tty *tp, char c)
int sysctl_handle_int(SYSCTL_HANDLER_ARGS)
int msgbuf_getchar(struct msgbuf *mbp)
void cnremove(struct consdev *cn)
static struct cn_device cn_devtab[CNDEVTAB_SIZE]
struct sbuf * sbuf_new(struct sbuf *s, char *buf, int length, int flags)
static int consmsgbuf_size
int pause(const char *wmesg, int timo)
void free(void *addr, struct malloc_type *mtp)
static MALLOC_DEFINE(M_TTYCONS,"tty console","tty console handling")
int printf(const char *fmt,...)
void sbuf_delete(struct sbuf *s)
void callout_init(struct callout *c, int mpsafe)
void mtx_init(struct mtx *m, const char *name, const char *type, int opts)
void constty_set(struct tty *tp)
char * sbuf_data(struct sbuf *s)
SET_DECLARE(sysinit_set, struct sysinit)
int sbuf_finish(struct sbuf *s)
int cnadd(struct consdev *cn)
SYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW, 0, 0, sysctl_kern_console,"A","Console device control")
void cnavailable(struct consdev *cn, int available)
static void cn_drvinit(void *unused)
int sysbeep(int pitch __unused, int period __unused)
static int constty_wakeups_per_second