FreeBSD kernel kern code
kern_cons.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1991 The Regents of the University of California.
4  * Copyright (c) 1999 Michael Smith
5  * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
6  *
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * the Systems Programming Group of the University of Utah Computer
11  * Science Department.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  * 4. Neither the name of the University nor the names of its contributors
22  * may be used to endorse or promote products derived from this software
23  * without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  * from: @(#)cons.c 7.2 (Berkeley) 5/9/91
38  */
39 
40 #include <sys/cdefs.h>
41 __FBSDID("$BSDSUniX$");
42 
43 #include "opt_ddb.h"
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/lock.h>
48 #include <sys/mutex.h>
49 #include <sys/conf.h>
50 #include <sys/cons.h>
51 #include <sys/fcntl.h>
52 #include <sys/kdb.h>
53 #include <sys/kernel.h>
54 #include <sys/malloc.h>
55 #include <sys/msgbuf.h>
56 #include <sys/namei.h>
57 #include <sys/priv.h>
58 #include <sys/proc.h>
59 #include <sys/queue.h>
60 #include <sys/reboot.h>
61 #include <sys/sysctl.h>
62 #include <sys/sbuf.h>
63 #include <sys/tty.h>
64 #include <sys/uio.h>
65 #include <sys/vnode.h>
66 
67 #include <ddb/ddb.h>
68 
69 #include <machine/cpu.h>
70 #include <machine/clock.h>
71 
72 static MALLOC_DEFINE(M_TTYCONS, "tty console", "tty console handling");
73 
74 struct cn_device {
75  STAILQ_ENTRY(cn_device) cnd_next;
76  struct consdev *cnd_cn;
77 };
78 
79 #define CNDEVPATHMAX 32
80 #define CNDEVTAB_SIZE 4
82 static STAILQ_HEAD(, cn_device) cn_devlist =
83  STAILQ_HEAD_INITIALIZER(cn_devlist);
84 
85 int cons_avail_mask = 0; /* Bit mask. Each registered low level console
86  * which is currently unavailable for inpit
87  * (i.e., if it is in graphics mode) will have
88  * this bit cleared.
89  */
90 static int cn_mute;
91 static char *consbuf; /* buffer used by `consmsgbuf' */
92 static struct callout conscallout; /* callout for outputting to constty */
93 struct msgbuf consmsgbuf; /* message buffer for console tty */
94 static u_char console_pausing; /* pause after each line during probe */
95 static char *console_pausestr=
96 "<pause; press any key to proceed to next line or '.' to end pause mode>";
97 struct tty *constty; /* pointer to console "window" tty */
98 static struct mtx cnputs_mtx; /* Mutex for cnputs(). */
99 static int use_cnputs_mtx = 0; /* != 0 if cnputs_mtx locking reqd. */
100 
101 static void constty_timeout(void *arg);
102 
103 static struct consdev cons_consdev;
104 DATA_SET(cons_set, cons_consdev);
105 SET_DECLARE(cons_set, struct consdev);
106 
107 void
108 cninit(void)
109 {
110  struct consdev *best_cn, *cn, **list;
111 
112  /*
113  * Check if we should mute the console (for security reasons perhaps)
114  * It can be changes dynamically using sysctl kern.consmute
115  * once we are up and going.
116  *
117  */
118  cn_mute = ((boothowto & (RB_MUTE
119  |RB_SINGLE
120  |RB_VERBOSE
121  |RB_ASKNAME)) == RB_MUTE);
122 
123  /*
124  * Find the first console with the highest priority.
125  */
126  best_cn = NULL;
127  SET_FOREACH(list, cons_set) {
128  cn = *list;
129  cnremove(cn);
130  /* Skip cons_consdev. */
131  if (cn->cn_ops == NULL)
132  continue;
133  cn->cn_ops->cn_probe(cn);
134  if (cn->cn_pri == CN_DEAD)
135  continue;
136  if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri)
137  best_cn = cn;
138  if (boothowto & RB_MULTIPLE) {
139  /*
140  * Initialize console, and attach to it.
141  */
142  cn->cn_ops->cn_init(cn);
143  cnadd(cn);
144  }
145  }
146  if (best_cn == NULL)
147  return;
148  if ((boothowto & RB_MULTIPLE) == 0) {
149  best_cn->cn_ops->cn_init(best_cn);
150  cnadd(best_cn);
151  }
152  if (boothowto & RB_PAUSE)
153  console_pausing = 1;
154  /*
155  * Make the best console the preferred console.
156  */
157  cnselect(best_cn);
158 }
159 
160 void
162 {
163  console_pausing = 0;
164 }
165 
166 /* add a new physical console to back the virtual console */
167 int
168 cnadd(struct consdev *cn)
169 {
170  struct cn_device *cnd;
171  int i;
172 
173  STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
174  if (cnd->cnd_cn == cn)
175  return (0);
176  for (i = 0; i < CNDEVTAB_SIZE; i++) {
177  cnd = &cn_devtab[i];
178  if (cnd->cnd_cn == NULL)
179  break;
180  }
181  if (cnd->cnd_cn != NULL)
182  return (ENOMEM);
183  cnd->cnd_cn = cn;
184  if (cn->cn_name[0] == '\0') {
185  /* XXX: it is unclear if/where this print might output */
186  printf("WARNING: console at %p has no name\n", cn);
187  }
188  STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next);
189  if (STAILQ_FIRST(&cn_devlist) == cnd)
190  ttyconsdev_select(cnd->cnd_cn->cn_name);
191 
192  /* Add device to the active mask. */
193  cnavailable(cn, (cn->cn_flags & CN_FLAG_NOAVAIL) == 0);
194 
195  return (0);
196 }
197 
198 void
199 cnremove(struct consdev *cn)
200 {
201  struct cn_device *cnd;
202  int i;
203 
204  STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
205  if (cnd->cnd_cn != cn)
206  continue;
207  if (STAILQ_FIRST(&cn_devlist) == cnd)
208  ttyconsdev_select(NULL);
209  STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
210  cnd->cnd_cn = NULL;
211 
212  /* Remove this device from available mask. */
213  for (i = 0; i < CNDEVTAB_SIZE; i++)
214  if (cnd == &cn_devtab[i]) {
215  cons_avail_mask &= ~(1 << i);
216  break;
217  }
218 #if 0
219  /*
220  * XXX
221  * syscons gets really confused if console resources are
222  * freed after the system has initialized.
223  */
224  if (cn->cn_term != NULL)
225  cn->cn_ops->cn_term(cn);
226 #endif
227  return;
228  }
229 }
230 
231 void
232 cnselect(struct consdev *cn)
233 {
234  struct cn_device *cnd;
235 
236  STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
237  if (cnd->cnd_cn != cn)
238  continue;
239  if (cnd == STAILQ_FIRST(&cn_devlist))
240  return;
241  STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
242  STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next);
243  ttyconsdev_select(cnd->cnd_cn->cn_name);
244  return;
245  }
246 }
247 
248 void
249 cnavailable(struct consdev *cn, int available)
250 {
251  int i;
252 
253  for (i = 0; i < CNDEVTAB_SIZE; i++) {
254  if (cn_devtab[i].cnd_cn == cn)
255  break;
256  }
257  if (available) {
258  if (i < CNDEVTAB_SIZE)
259  cons_avail_mask |= (1 << i);
260  cn->cn_flags &= ~CN_FLAG_NOAVAIL;
261  } else {
262  if (i < CNDEVTAB_SIZE)
263  cons_avail_mask &= ~(1 << i);
264  cn->cn_flags |= CN_FLAG_NOAVAIL;
265  }
266 }
267 
268 int
270 {
271 
272  return (cons_avail_mask == 0);
273 }
274 
275 /*
276  * sysctl_kern_console() provides output parseable in conscontrol(1).
277  */
278 static int
279 sysctl_kern_console(SYSCTL_HANDLER_ARGS)
280 {
281  struct cn_device *cnd;
282  struct consdev *cp, **list;
283  char *p;
284  int delete, error;
285  struct sbuf *sb;
286 
287  sb = sbuf_new(NULL, NULL, CNDEVPATHMAX * 2, SBUF_AUTOEXTEND);
288  if (sb == NULL)
289  return (ENOMEM);
290  sbuf_clear(sb);
291  STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
292  sbuf_printf(sb, "%s,", cnd->cnd_cn->cn_name);
293  sbuf_printf(sb, "/");
294  SET_FOREACH(list, cons_set) {
295  cp = *list;
296  if (cp->cn_name[0] != '\0')
297  sbuf_printf(sb, "%s,", cp->cn_name);
298  }
299  sbuf_finish(sb);
300  error = sysctl_handle_string(oidp, sbuf_data(sb), sbuf_len(sb), req);
301  if (error == 0 && req->newptr != NULL) {
302  p = sbuf_data(sb);
303  error = ENXIO;
304  delete = 0;
305  if (*p == '-') {
306  delete = 1;
307  p++;
308  }
309  SET_FOREACH(list, cons_set) {
310  cp = *list;
311  if (strcmp(p, cp->cn_name) != 0)
312  continue;
313  if (delete) {
314  cnremove(cp);
315  error = 0;
316  } else {
317  error = cnadd(cp);
318  if (error == 0)
319  cnselect(cp);
320  }
321  break;
322  }
323  }
324  sbuf_delete(sb);
325  return (error);
326 }
327 
328 SYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW,
329  0, 0, sysctl_kern_console, "A", "Console device control");
330 
331 /*
332  * User has changed the state of the console muting.
333  * This may require us to open or close the device in question.
334  */
335 static int
336 sysctl_kern_consmute(SYSCTL_HANDLER_ARGS)
337 {
338  int error;
339 
340  error = sysctl_handle_int(oidp, &cn_mute, 0, req);
341  if (error != 0 || req->newptr == NULL)
342  return (error);
343  return (error);
344 }
345 
346 SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW,
347  0, sizeof(cn_mute), sysctl_kern_consmute, "I",
348  "State of the console muting");
349 
350 void
352 {
353  struct cn_device *cnd;
354  struct consdev *cn;
355 
356  STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
357  cn = cnd->cnd_cn;
358  if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
359  cn->cn_ops->cn_grab(cn);
360  }
361 }
362 
363 void
365 {
366  struct cn_device *cnd;
367  struct consdev *cn;
368 
369  STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
370  cn = cnd->cnd_cn;
371  if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
372  cn->cn_ops->cn_ungrab(cn);
373  }
374 }
375 
376 /*
377  * Low level console routines.
378  */
379 int
380 cngetc(void)
381 {
382  int c;
383 
384  if (cn_mute)
385  return (-1);
386  while ((c = cncheckc()) == -1)
387  cpu_spinwait();
388  if (c == '\r')
389  c = '\n'; /* console input is always ICRNL */
390  return (c);
391 }
392 
393 int
394 cncheckc(void)
395 {
396  struct cn_device *cnd;
397  struct consdev *cn;
398  int c;
399 
400  if (cn_mute)
401  return (-1);
402  STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
403  cn = cnd->cnd_cn;
404  if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
405  c = cn->cn_ops->cn_getc(cn);
406  if (c != -1)
407  return (c);
408  }
409  }
410  return (-1);
411 }
412 
413 void
414 cngets(char *cp, size_t size, int visible)
415 {
416  char *lp, *end;
417  int c;
418 
419  cngrab();
420 
421  lp = cp;
422  end = cp + size - 1;
423  for (;;) {
424  c = cngetc() & 0177;
425  switch (c) {
426  case '\n':
427  case '\r':
428  cnputc(c);
429  *lp = '\0';
430  cnungrab();
431  return;
432  case '\b':
433  case '\177':
434  if (lp > cp) {
435  if (visible) {
436  cnputc(c);
437  cnputs(" \b");
438  }
439  lp--;
440  }
441  continue;
442  case '\0':
443  continue;
444  default:
445  if (lp < end) {
446  switch (visible) {
447  case GETS_NOECHO:
448  break;
449  case GETS_ECHOPASS:
450  cnputc('*');
451  break;
452  default:
453  cnputc(c);
454  break;
455  }
456  *lp++ = c;
457  }
458  }
459  }
460 }
461 
462 void
463 cnputc(int c)
464 {
465  struct cn_device *cnd;
466  struct consdev *cn;
467  char *cp;
468 
469  if (cn_mute || c == '\0')
470  return;
471  STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
472  cn = cnd->cnd_cn;
473  if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
474  if (c == '\n')
475  cn->cn_ops->cn_putc(cn, '\r');
476  cn->cn_ops->cn_putc(cn, c);
477  }
478  }
479  if (console_pausing && c == '\n' && !kdb_active) {
480  for (cp = console_pausestr; *cp != '\0'; cp++)
481  cnputc(*cp);
482  cngrab();
483  if (cngetc() == '.')
484  console_pausing = 0;
485  cnungrab();
486  cnputc('\r');
487  for (cp = console_pausestr; *cp != '\0'; cp++)
488  cnputc(' ');
489  cnputc('\r');
490  }
491 }
492 
493 void
494 cnputs(char *p)
495 {
496  int c;
497  int unlock_reqd = 0;
498 
499  if (use_cnputs_mtx) {
500  /*
501  * NOTE: Debug prints and/or witness printouts in
502  * console driver clients can cause the "cnputs_mtx"
503  * mutex to recurse. Simply return if that happens.
504  */
505  if (mtx_owned(&cnputs_mtx))
506  return;
507  mtx_lock_spin(&cnputs_mtx);
508  unlock_reqd = 1;
509  }
510 
511  while ((c = *p++) != '\0')
512  cnputc(c);
513 
514  if (unlock_reqd)
515  mtx_unlock_spin(&cnputs_mtx);
516 }
517 
518 static int consmsgbuf_size = 8192;
519 SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0,
520  "Console tty buffer size");
521 
522 /*
523  * Redirect console output to a tty.
524  */
525 void
526 constty_set(struct tty *tp)
527 {
528  int size;
529 
530  KASSERT(tp != NULL, ("constty_set: NULL tp"));
531  if (consbuf == NULL) {
532  size = consmsgbuf_size;
533  consbuf = malloc(size, M_TTYCONS, M_WAITOK);
534  msgbuf_init(&consmsgbuf, consbuf, size);
535  callout_init(&conscallout, 0);
536  }
537  constty = tp;
538  constty_timeout(NULL);
539 }
540 
541 /*
542  * Disable console redirection to a tty.
543  */
544 void
546 {
547  int c;
548 
549  constty = NULL;
550  if (consbuf == NULL)
551  return;
552  callout_stop(&conscallout);
553  while ((c = msgbuf_getchar(&consmsgbuf)) != -1)
554  cnputc(c);
555  free(consbuf, M_TTYCONS);
556  consbuf = NULL;
557 }
558 
559 /* Times per second to check for pending console tty messages. */
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");
564 
565 static void
566 constty_timeout(void *arg)
567 {
568  int c;
569 
570  if (constty != NULL) {
571  tty_lock(constty);
572  while ((c = msgbuf_getchar(&consmsgbuf)) != -1) {
573  if (tty_putchar(constty, c) < 0) {
574  tty_unlock(constty);
575  constty = NULL;
576  break;
577  }
578  }
579 
580  if (constty != NULL)
581  tty_unlock(constty);
582  }
583  if (constty != NULL) {
584  callout_reset(&conscallout, hz / constty_wakeups_per_second,
585  constty_timeout, NULL);
586  } else {
587  /* Deallocate the constty buffer memory. */
588  constty_clear();
589  }
590 }
591 
592 static void
593 cn_drvinit(void *unused)
594 {
595 
596  mtx_init(&cnputs_mtx, "cnputs_mtx", NULL, MTX_SPIN | MTX_NOWITNESS);
597  use_cnputs_mtx = 1;
598 }
599 
600 SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL);
601 
602 /*
603  * Sysbeep(), if we have hardware for it
604  */
605 
606 #ifdef HAS_TIMER_SPKR
607 
608 static int beeping;
609 
610 static void
611 sysbeepstop(void *chan)
612 {
613 
614  timer_spkr_release();
615  beeping = 0;
616 }
617 
618 int
619 sysbeep(int pitch, int period)
620 {
621 
622  if (timer_spkr_acquire()) {
623  if (!beeping) {
624  /* Something else owns it. */
625  return (EBUSY);
626  }
627  }
628  timer_spkr_setfreq(pitch);
629  if (!beeping) {
630  beeping = period;
631  timeout(sysbeepstop, (void *)NULL, period);
632  }
633  return (0);
634 }
635 
636 #else
637 
638 /*
639  * No hardware, no sound
640  */
641 
642 int
643 sysbeep(int pitch __unused, int period __unused)
644 {
645 
646  return (ENODEV);
647 }
648 
649 #endif
650 
static int sysctl_kern_consmute(SYSCTL_HANDLER_ARGS)
Definition: kern_cons.c:336
#define CNDEVPATHMAX
Definition: kern_cons.c:79
void cnungrab()
Definition: kern_cons.c:364
struct callout_handle timeout(timeout_t *ftn, void *arg, int to_ticks)
Definition: kern_timeout.c:713
SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL)
static void constty_timeout(void *arg)
Definition: kern_cons.c:566
void cngrab()
Definition: kern_cons.c:351
ssize_t sbuf_len(struct sbuf *s)
Definition: subr_sbuf.c:736
int mode
void cngets(char *cp, size_t size, int visible)
Definition: kern_cons.c:414
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
Definition: kern_malloc.c:454
int cngetc(void)
Definition: kern_cons.c:380
int boothowto
Definition: init_main.c:104
void cnselect(struct consdev *cn)
Definition: kern_cons.c:232
int sysctl_handle_string(SYSCTL_HANDLER_ARGS)
Definition: kern_sysctl.c:1121
static STAILQ_HEAD(cn_device)
Definition: kern_cons.c:82
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)
Definition: subr_msgbuf.c:65
int cnunavailable(void)
Definition: kern_cons.c:269
void sbuf_clear(struct sbuf *s)
Definition: subr_sbuf.c:269
static int sysctl_kern_console(SYSCTL_HANDLER_ARGS)
Definition: kern_cons.c:279
void ttyconsdev_select(const char *name)
Definition: tty.c:2004
int sbuf_printf(struct sbuf *s, const char *fmt,...)
Definition: subr_sbuf.c:632
int tty_putchar(struct tty *tp, char c)
Definition: tty_ttydisc.c:1256
int sysctl_handle_int(SYSCTL_HANDLER_ARGS)
Definition: kern_sysctl.c:986
int msgbuf_getchar(struct msgbuf *mbp)
Definition: subr_msgbuf.c:293
void cnremove(struct consdev *cn)
Definition: kern_cons.c:199
static struct cn_device cn_devtab[CNDEVTAB_SIZE]
Definition: kern_cons.c:81
struct sbuf * sbuf_new(struct sbuf *s, char *buf, int length, int flags)
Definition: subr_sbuf.c:211
void constty_clear(void)
Definition: kern_cons.c:545
static int consmsgbuf_size
Definition: kern_cons.c:518
int pause(const char *wmesg, int timo)
Definition: kern_synch.c:350
void free(void *addr, struct malloc_type *mtp)
Definition: kern_malloc.c:554
static MALLOC_DEFINE(M_TTYCONS,"tty console","tty console handling")
int printf(const char *fmt,...)
Definition: subr_prf.c:367
void sbuf_delete(struct sbuf *s)
Definition: subr_sbuf.c:753
void callout_init(struct callout *c, int mpsafe)
void mtx_init(struct mtx *m, const char *name, const char *type, int opts)
Definition: kern_mutex.c:837
void constty_set(struct tty *tp)
Definition: kern_cons.c:526
char * sbuf_data(struct sbuf *s)
Definition: subr_sbuf.c:721
SET_DECLARE(sysinit_set, struct sysinit)
int sbuf_finish(struct sbuf *s)
Definition: subr_sbuf.c:694
void cnputc(int c)
Definition: kern_cons.c:463
int kdb_active
Definition: subr_kdb.c:53
int cncheckc(void)
Definition: kern_cons.c:394
int cnadd(struct consdev *cn)
Definition: kern_cons.c:168
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)
Definition: kern_cons.c:249
void cnputs(char *p)
Definition: kern_cons.c:494
#define CNDEVTAB_SIZE
Definition: kern_cons.c:80
__FBSDID("$BSDSUniX$")
static void cn_drvinit(void *unused)
Definition: kern_cons.c:593
int sysbeep(int pitch __unused, int period __unused)
Definition: kern_cons.c:643
void cninit_finish()
Definition: kern_cons.c:161
static int constty_wakeups_per_second
Definition: kern_cons.c:560
int hz
Definition: subr_param.c:84