This patch adds support for multiple simultaneous low level consoles to the kernel. In essence, it is equivalent to the -D flag in the /boot.config file.
Support can be turned on by executing 'boot -D' from the loader, or by using the comcontrol program (which is appended to the end of the patch). The motivation for performing this work (other than wanting to be able to use ddb on vidconsol and comconsole interchangeably) is the upcoming network console support, which requires the ability to add a console after the system is up. Objections and bugs aside, I plan to commit this shortly. -- Jonathan Index: kern/tty_cons.c =================================================================== RCS file: /ncvs/src/sys/kern/tty_cons.c,v retrieving revision 1.92 diff -u -r1.92 tty_cons.c --- kern/tty_cons.c 2001/09/12 08:37:46 1.92 +++ kern/tty_cons.c 2001/10/20 03:23:04 @@ -44,11 +44,15 @@ #include <sys/conf.h> #include <sys/cons.h> #include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/namei.h> #include <sys/proc.h> +#include <sys/queue.h> #include <sys/reboot.h> #include <sys/sysctl.h> #include <sys/tty.h> #include <sys/uio.h> +#include <sys/vnode.h> #include <machine/cpu.h> @@ -78,47 +82,43 @@ /* kqfilter */ cnkqfilter, }; -static dev_t cn_dev_t; /* seems to be never really used */ +struct cn_device { + STAILQ_ENTRY(cn_device) cnd_next; + char cnd_name[16]; + struct vnode *cnd_vp; + struct consdev *cnd_cn; +}; + +#define CNDEVPATHMAX 32 +#define CNDEVTAB_SIZE 4 +static struct cn_device cn_devtab[CNDEVTAB_SIZE]; +static STAILQ_HEAD(, cn_device) cn_devlist = + STAILQ_HEAD_INITIALIZER(cn_devlist); + +#define CND_INVALID(cnd, td) \ + (cnd == NULL || cnd->cnd_vp == NULL || \ + (cnd->cnd_vp->v_type == VBAD && !cn_devopen(cnd, td, 1))) + static udev_t cn_udev_t; SYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLFLAG_RD, &cn_udev_t, sizeof cn_udev_t, "T,dev_t", ""); -static int cn_mute; - int cons_unavail = 0; /* XXX: * physical console not available for * input (i.e., it is in graphics mode) */ - -static u_char cn_is_open; /* nonzero if logical console is open */ -static int openmode, openflag; /* how /dev/console was openned */ +static int cn_mute; +static int openflag; /* how /dev/console was opened */ +static int cn_is_open; static dev_t cn_devfsdev; /* represents the device private info */ -static u_char cn_phys_is_open; /* nonzero if physical device is open */ -static d_close_t *cn_phys_close; /* physical device close function */ -static d_open_t *cn_phys_open; /* physical device open function */ - struct consdev *cn_tab; /* physical console device info */ CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL, NULL); SET_DECLARE(cons_set, struct consdev); void -cninit() +cninit(void) { - struct consdev *best_cp, *cp, **list; - - /* - * Find the first console with the highest priority. - */ - best_cp = NULL; - SET_FOREACH(list, cons_set) { - cp = *list; - if (cp->cn_probe == NULL) - continue; - (*cp->cn_probe)(cp); - if (cp->cn_pri > CN_DEAD && - (best_cp == NULL || cp->cn_pri > best_cp->cn_pri)) - best_cp = cp; - } + struct consdev *best_cn, *cn, **list; /* * Check if we should mute the console (for security reasons perhaps) @@ -131,74 +131,176 @@ |RB_VERBOSE |RB_ASKNAME |RB_CONFIG)) == RB_MUTE); - + /* - * If no console, give up. + * Find the first console with the highest priority. */ - if (best_cp == NULL) { - if (cn_tab != NULL && cn_tab->cn_term != NULL) - (*cn_tab->cn_term)(cn_tab); - cn_tab = best_cp; + best_cn = NULL; + SET_FOREACH(list, cons_set) { + cn = *list; + if (cn->cn_probe == NULL) + continue; + cn->cn_probe(cn); + if (cn->cn_pri == CN_DEAD) + continue; + if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri) + best_cn = cn; + if (boothowto & RB_MULTIPLE) { + /* + * Initialize console, and attach to it. + */ + cnadd(cn); + cn->cn_init(cn); + } + } + if (best_cn == NULL) return; + if ((boothowto & RB_MULTIPLE) == 0) { + cnadd(best_cn); + best_cn->cn_init(best_cn); } - /* - * Initialize console, then attach to it. This ordering allows - * debugging using the previous console, if any. + * Make the best console the preferred console. */ - (*best_cp->cn_init)(best_cp); - if (cn_tab != NULL && cn_tab != best_cp) { - /* Turn off the previous console. */ - if (cn_tab->cn_term != NULL) - (*cn_tab->cn_term)(cn_tab); - } - cn_tab = best_cp; + cnselect(best_cn); +} + +/* add a new physical console to back the virtual console */ +int +cnadd(struct consdev *cn) +{ + struct cn_device *cnd; + int i; + + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) + if (cnd->cnd_cn == cn) + return (0); + for (i = 0; i < CNDEVTAB_SIZE; i++) { + cnd = &cn_devtab[i]; + if (cnd->cnd_cn == NULL) + break; + } + if (cnd->cnd_cn != NULL) + return (ENOMEM); + cnd->cnd_cn = cn; + STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next); + return (0); } void -cninit_finish() +cnremove(struct consdev *cn) { - struct cdevsw *cdp; + struct cn_device *cnd; - if ((cn_tab == NULL) || cn_mute) + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { + if (cnd->cnd_cn != cn) + continue; + STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next); + if (cnd->cnd_vp != NULL) + vn_close(cnd->cnd_vp, openflag, NOCRED, NULL); + cnd->cnd_vp = NULL; + cnd->cnd_cn = NULL; + cnd->cnd_name[0] = '\0'; +#if 0 + /* + * XXX + * syscons gets really confused if console resources are + * freed after the system has initialized. + */ + if (cn->cn_term != NULL) + cn->cn_term(cn); +#endif return; - - /* - * Hook the open and close functions. - */ - cdp = devsw(cn_tab->cn_dev); - if (cdp != NULL) { - cn_phys_close = cdp->d_close; - cdp->d_close = cnclose; - cn_phys_open = cdp->d_open; - cdp->d_open = cnopen; } - cn_dev_t = cn_tab->cn_dev; - cn_udev_t = dev2udev(cn_dev_t); } -static void -cnuninit(void) +void +cnselect(struct consdev *cn) { - struct cdevsw *cdp; + struct cn_device *cnd; - if (cn_tab == NULL) + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { + if (cnd->cnd_cn != cn) + continue; + if (cnd == STAILQ_FIRST(&cn_devlist)) + return; + STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next); + STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next); return; + } +} - /* - * Unhook the open and close functions. - */ - cdp = devsw(cn_tab->cn_dev); - if (cdp != NULL) { - cdp->d_close = cn_phys_close; - cdp->d_open = cn_phys_open; - } - cn_phys_close = NULL; - cn_phys_open = NULL; - cn_dev_t = NODEV; - cn_udev_t = NOUDEV; +void +cndebug(char *str) +{ + int i, len; + + len = strlen(str); + cnputc('>'); cnputc('>'); cnputc('>'); cnputc(' '); + for (i = 0; i < len; i++) + cnputc(str[i]); + cnputc('\n'); +} + +static int +sysctl_kern_console(SYSCTL_HANDLER_ARGS) +{ + struct cn_device *cnd; + struct consdev *cp, **list; + char *name, *p; + int delete, len, error; + + len = 2; + SET_FOREACH(list, cons_set) { + cp = *list; + if (cp->cn_dev != NULL) + len += strlen(devtoname(cp->cn_dev)) + 1; + } + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) + len += strlen(devtoname(cnd->cnd_cn->cn_dev)) + 1; + len = len > CNDEVPATHMAX ? len : CNDEVPATHMAX; + MALLOC(name, char *, len, M_TEMP, M_WAITOK | M_ZERO); + p = name; + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) + p += sprintf(p, "%s,", devtoname(cnd->cnd_cn->cn_dev)); + *p++ = '/'; + SET_FOREACH(list, cons_set) { + cp = *list; + if (cp->cn_dev != NULL) + p += sprintf(p, "%s,", devtoname(cp->cn_dev)); + } + error = sysctl_handle_string(oidp, name, len, req); + if (error == 0 && req->newptr != NULL) { + p = name; + error = ENXIO; + delete = 0; + if (*p == '-') { + delete = 1; + p++; + } + SET_FOREACH(list, cons_set) { + cp = *list; + if (cp->cn_dev == NULL || + strcmp(p, devtoname(cp->cn_dev)) != 0) + continue; + if (delete) { + cnremove(cp); + error = 0; + } else { + error = cnadd(cp); + if (error == 0) + cnselect(cp); + } + break; + } + } + FREE(name, M_TEMP); + return (error); } +SYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW, + 0, 0, sysctl_kern_console, "A", "Console device control"); + /* * User has changed the state of the console muting. * This may require us to open or close the device in question. @@ -211,165 +313,123 @@ ocn_mute = cn_mute; error = sysctl_handle_int(oidp, &cn_mute, 0, req); - if((error == 0) && (cn_tab != NULL) && (req->newptr != NULL)) { - if(ocn_mute && !cn_mute) { - /* - * going from muted to unmuted.. open the physical dev - * if the console has been openned - */ - cninit_finish(); - if(cn_is_open) - /* XXX curthread is not what we want really */ - error = cnopen(cn_dev_t, openflag, - openmode, curthread); - /* if it failed, back it out */ - if ( error != 0) cnuninit(); - } else if (!ocn_mute && cn_mute) { - /* - * going from unmuted to muted.. close the physical dev - * if it's only open via /dev/console - */ - if(cn_is_open) - error = cnclose(cn_dev_t, openflag, - openmode, curthread); - if ( error == 0) cnuninit(); - } - if (error != 0) { - /* - * back out the change if there was an error - */ - cn_mute = ocn_mute; - } + if (error != 0 || req->newptr == NULL) + return (error); + if (ocn_mute && !cn_mute && cn_is_open) + error = cnopen(NODEV, openflag, 0, curthread); + else if (!ocn_mute && cn_mute && cn_is_open) { + error = cnclose(NODEV, openflag, 0, curthread); + cn_is_open = 1; /* XXX hack */ } return (error); } SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW, - 0, sizeof cn_mute, sysctl_kern_consmute, "I", ""); + 0, sizeof(cn_mute), sysctl_kern_consmute, "I", ""); static int -cnopen(dev, flag, mode, td) - dev_t dev; - int flag, mode; - struct thread *td; +cn_devopen(struct cn_device *cnd, struct thread *td, int forceopen) { - dev_t cndev, physdev; - int retval = 0; + char path[CNDEVPATHMAX]; + struct nameidata nd; + dev_t dev; + int error; - if (cn_tab == NULL || cn_phys_open == NULL) - return (0); - cndev = cn_tab->cn_dev; - physdev = (major(dev) == major(cndev) ? dev : cndev); - /* - * If mute is active, then non console opens don't get here - * so we don't need to check for that. They - * bypass this and go straight to the device. - */ - if(!cn_mute) - retval = (*cn_phys_open)(physdev, flag, mode, td); - if (retval == 0) { - /* - * check if we openned it via /dev/console or - * via the physical entry (e.g. /dev/sio0). - */ - if (dev == cndev) - cn_phys_is_open = 1; - else if (physdev == cndev) { - openmode = mode; - openflag = flag; - cn_is_open = 1; + if (cnd->cnd_vp != NULL) { + if (!forceopen) { + dev = cnd->cnd_vp->v_rdev; + return ((*devsw(dev)->d_open)(dev, openflag, 0, td)); } - dev->si_tty = physdev->si_tty; + vn_close(cnd->cnd_vp, openflag, td->td_proc->p_ucred, td); + cnd->cnd_vp = NULL; + } + if (cnd->cnd_name[0] == '\0') + strncpy(cnd->cnd_name, devtoname(cnd->cnd_cn->cn_dev), + sizeof(cnd->cnd_name)); + snprintf(path, sizeof(path), "/dev/%s", cnd->cnd_name); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); + error = vn_open(&nd, &openflag, 0); + if (error == 0) { + NDFREE(&nd, NDF_ONLY_PNBUF); + VOP_UNLOCK(nd.ni_vp, 0, td); + if (nd.ni_vp->v_type == VCHR) + cnd->cnd_vp = nd.ni_vp; + else + vn_close(nd.ni_vp, openflag, td->td_proc->p_ucred, td); } - return (retval); + return (cnd->cnd_vp != NULL); } static int -cnclose(dev, flag, mode, td) - dev_t dev; - int flag, mode; - struct thread *td; +cnopen(dev_t dev, int flag, int mode, struct thread *td) { - dev_t cndev; - struct tty *cn_tp; + struct cn_device *cnd; - if (cn_tab == NULL || cn_phys_open == NULL) + openflag = flag; + cn_is_open = 1; /* console is logically open */ + if (cn_mute) return (0); - cndev = cn_tab->cn_dev; - cn_tp = cndev->si_tty; - /* - * act appropriatly depending on whether it's /dev/console - * or the pysical device (e.g. /dev/sio) that's being closed. - * in either case, don't actually close the device unless - * both are closed. - */ - if (dev == cndev) { - /* the physical device is about to be closed */ - cn_phys_is_open = 0; - if (cn_is_open) { - if (cn_tp) { - /* perform a ttyhalfclose() */ - /* reset session and proc group */ - cn_tp->t_pgrp = NULL; - cn_tp->t_session = NULL; - } - return (0); - } - } else if (major(dev) != major(cndev)) { - /* the logical console is about to be closed */ - cn_is_open = 0; - if (cn_phys_is_open) - return (0); - dev = cndev; + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) + cn_devopen(cnd, td, 0); + return (0); +} + +static int +cnclose(dev_t dev, int flag, int mode, struct thread *td) +{ + struct cn_device *cnd; + + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { + if (cnd->cnd_vp == NULL) + continue; + vn_close(cnd->cnd_vp, mode, td->td_proc->p_ucred, td); + cnd->cnd_vp = NULL; } - if(cn_phys_close) - return ((*cn_phys_close)(dev, flag, mode, td)); + cn_is_open = 0; return (0); } static int -cnread(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; +cnread(dev_t dev, struct uio *uio, int flag) { + struct cn_device *cnd; - if (cn_tab == NULL || cn_phys_open == NULL) + cnd = STAILQ_FIRST(&cn_devlist); + if (cn_mute || CND_INVALID(cnd, curthread)) return (0); - dev = cn_tab->cn_dev; + dev = cnd->cnd_vp->v_rdev; return ((*devsw(dev)->d_read)(dev, uio, flag)); } static int -cnwrite(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; +cnwrite(dev_t dev, struct uio *uio, int flag) { + struct cn_device *cnd; - if (cn_tab == NULL || cn_phys_open == NULL) { - uio->uio_resid = 0; /* dump the data */ - return (0); - } + cnd = STAILQ_FIRST(&cn_devlist); + if (cn_mute || CND_INVALID(cnd, curthread)) + goto done; if (constty) dev = constty->t_dev; else - dev = cn_tab->cn_dev; - log_console(uio); - return ((*devsw(dev)->d_write)(dev, uio, flag)); + dev = cnd->cnd_vp->v_rdev; + if (dev != NULL) { + log_console(uio); + return ((*devsw(dev)->d_write)(dev, uio, flag)); + } +done: + uio->uio_resid = 0; /* dump the data */ + return (0); } static int -cnioctl(dev, cmd, data, flag, td) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct thread *td; +cnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) { + struct cn_device *cnd; int error; - if (cn_tab == NULL || cn_phys_open == NULL) + cnd = STAILQ_FIRST(&cn_devlist); + if (cn_mute || CND_INVALID(cnd, td)) return (0); /* * Superuser can always use this to wrest control of console @@ -382,82 +442,111 @@ constty = NULL; return (0); } - dev = cn_tab->cn_dev; - return ((*devsw(dev)->d_ioctl)(dev, cmd, data, flag, td)); + dev = cnd->cnd_vp->v_rdev; + if (dev != NULL) + return ((*devsw(dev)->d_ioctl)(dev, cmd, data, flag, td)); + return (0); } +/* + * XXX + * poll/kqfilter do not appear to be correct + */ static int -cnpoll(dev, events, td) - dev_t dev; - int events; - struct thread *td; +cnpoll(dev_t dev, int events, struct thread *td) { - if ((cn_tab == NULL) || cn_mute) - return (1); - - dev = cn_tab->cn_dev; + struct cn_device *cnd; - return ((*devsw(dev)->d_poll)(dev, events, td)); + cnd = STAILQ_FIRST(&cn_devlist); + if (cn_mute || CND_INVALID(cnd, td)) + return (0); + dev = cnd->cnd_vp->v_rdev; + if (dev != NULL) + return ((*devsw(dev)->d_poll)(dev, events, td)); + return (0); } static int -cnkqfilter(dev, kn) - dev_t dev; - struct knote *kn; +cnkqfilter(dev_t dev, struct knote *kn) { - if ((cn_tab == NULL) || cn_mute) - return (1); + struct cn_device *cnd; - dev = cn_tab->cn_dev; - if (devsw(dev)->d_flags & D_KQFILTER) + cnd = STAILQ_FIRST(&cn_devlist); + if (cn_mute || CND_INVALID(cnd, curthread)) + return (1); + dev = cnd->cnd_vp->v_rdev; + if (dev != NULL) return ((*devsw(dev)->d_kqfilter)(dev, kn)); return (1); } +/* + * Low level console routines. + */ int -cngetc() +cngetc(void) { int c; - if ((cn_tab == NULL) || cn_mute) + + if (cn_mute) return (-1); - c = (*cn_tab->cn_getc)(cn_tab->cn_dev); - if (c == '\r') c = '\n'; /* console input is always ICRNL */ + while ((c = cncheckc()) == -1) + ; + if (c == '\r') + c = '\n'; /* console input is always ICRNL */ return (c); } int -cncheckc() +cncheckc(void) { - if ((cn_tab == NULL) || cn_mute) + struct cn_device *cnd; + struct consdev *cn; + int c; + + if (cn_mute) return (-1); - return ((*cn_tab->cn_checkc)(cn_tab->cn_dev)); + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { + cn = cnd->cnd_cn; + c = cn->cn_checkc(cn->cn_dev); + if (c != -1) { + return (c); + } + } + return (-1); } void -cnputc(c) - register int c; +cnputc(int c) { - if ((cn_tab == NULL) || cn_mute) + struct cn_device *cnd; + struct consdev *cn; + + if (cn_mute || c == '\0') return; - if (c) { + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { + cn = cnd->cnd_cn; if (c == '\n') - (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r'); - (*cn_tab->cn_putc)(cn_tab->cn_dev, c); + cn->cn_putc(cn->cn_dev, '\r'); + cn->cn_putc(cn->cn_dev, c); } } void -cndbctl(on) - int on; +cndbctl(int on) { + struct cn_device *cnd; + struct consdev *cn; static int refcount; - if (cn_tab == NULL) - return; if (!on) refcount--; - if (refcount == 0 && cn_tab->cn_dbctl != NULL) - (*cn_tab->cn_dbctl)(cn_tab->cn_dev, on); + if (refcount == 0) + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { + cn = cnd->cnd_cn; + if (cn->cn_dbctl != NULL) + cn->cn_dbctl(cn->cn_dev, on); + } if (on) refcount++; } Index: sys/conf.h =================================================================== RCS file: /ncvs/src/sys/sys/conf.h,v retrieving revision 1.135 diff -u -r1.135 conf.h --- sys/conf.h 2001/10/17 18:47:12 1.135 +++ sys/conf.h 2001/10/19 16:04:51 @@ -60,6 +60,8 @@ #define SI_NAMED 0x0004 /* make_dev{_alias} has been called */ #define SI_CHEAPCLONE 0x0008 /* can be removed_dev'ed when vnode reclaims */ #define SI_CHILD 0x0010 /* child of another dev_t */ +#define SI_DEVOPEN 0x0020 /* opened by device */ +#define SI_CONSOPEN 0x0040 /* opened by console */ struct timespec si_atime; struct timespec si_ctime; struct timespec si_mtime; Index: sys/cons.h =================================================================== RCS file: /ncvs/src/sys/sys/cons.h,v retrieving revision 1.25 diff -u -r1.25 cons.h --- sys/cons.h 2001/06/13 10:58:39 1.25 +++ sys/cons.h 2001/09/27 02:25:27 @@ -78,8 +78,7 @@ #define CN_REMOTE 3 /* serial interface with remote bit set */ #ifdef _KERNEL -extern int cons_unavail; -extern struct consdev *cn_tab; +extern int cons_unavail; #define CONS_DRIVER(name, probe, init, term, getc, checkc, putc, dbctl) \ static struct consdev name##_consdev = { \ @@ -88,12 +87,14 @@ DATA_SET(cons_set, name##_consdev) /* Other kernel entry points. */ -int cncheckc __P((void)); -int cngetc __P((void)); -void cninit __P((void)); -void cninit_finish __P((void)); -void cndbctl __P((int)); -void cnputc __P((int)); +void cninit(void); +int cnadd(struct consdev *); +void cnremove(struct consdev *); +void cnselect(struct consdev *); +int cncheckc(void); +int cngetc(void); +void cndbctl(int); +void cnputc(int); #endif /* _KERNEL */ Index: sys/reboot.h =================================================================== RCS file: /ncvs/src/sys/sys/reboot.h,v retrieving revision 1.18 diff -u -r1.18 reboot.h --- sys/reboot.h 1999/08/28 00:51:58 1.18 +++ sys/reboot.h 2001/10/19 06:36:45 @@ -61,6 +61,7 @@ #define RB_GDB 0x8000 /* use GDB remote debugger instead of DDB */ #define RB_MUTE 0x10000 /* Come up with the console muted */ #define RB_SELFTEST 0x20000 /* don't boot to normal operation, do selftest */ +#define RB_MULTIPLE 0x20000000 /* Use multiple consoles */ #define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */ Index: isa/sio.c =================================================================== RCS file: /ncvs/src/sys/isa/sio.c,v retrieving revision 1.347 diff -u -r1.347 sio.c --- isa/sio.c 2001/09/29 04:49:11 1.347 +++ isa/sio.c 2001/10/20 02:24:30 @@ -2922,13 +2922,14 @@ #else static cn_probe_t siocnprobe; static cn_init_t siocninit; +static cn_term_t siocnterm; #endif static cn_checkc_t siocncheckc; static cn_getc_t siocngetc; static cn_putc_t siocnputc; #ifndef __alpha__ -CONS_DRIVER(sio, siocnprobe, siocninit, NULL, siocngetc, siocncheckc, +CONS_DRIVER(sio, siocnprobe, siocninit, siocnterm, siocngetc, siocncheckc, siocnputc, NULL); #endif @@ -3178,6 +3179,13 @@ struct consdev *cp; { comconsole = DEV_TO_UNIT(cp->cn_dev); +} + +static void +siocnterm(cp) + struct consdev *cp; +{ + comconsole = -1; } #endif Index: i386//i386/autoconf.c =================================================================== RCS file: /ncvs/src/sys/i386/i386/autoconf.c,v retrieving revision 1.158 diff -u -r1.158 autoconf.c --- i386//i386/autoconf.c 2001/09/18 23:31:29 1.158 +++ i386//i386/autoconf.c 2001/09/22 00:38:09 @@ -176,7 +176,7 @@ { int i; - cninit_finish(); +/* cninit_finish(); */ if (bootverbose) { Index: boot/i386/boot2/boot2.c =================================================================== RCS file: /ncvs/src/sys/boot/i386/boot2/boot2.c,v retrieving revision 1.32 diff -u -r1.32 boot2.c --- boot/i386/boot2/boot2.c 2001/07/31 19:50:09 1.32 +++ boot/i386/boot2/boot2.c 2001/10/19 06:37:45 @@ -49,7 +49,7 @@ #define RBX_DUAL 0x1d /* -D */ #define RBX_PROBEKBD 0x1e /* -P */ -#define RBX_MASK 0xffff +#define RBX_MASK 0x2000ffff #define PATH_CONFIG "/boot.config" #define PATH_BOOT3 "/boot/loader" Index: boot/i386/libi386/bootinfo.c =================================================================== RCS file: /ncvs/src/sys/boot/i386/libi386/bootinfo.c,v retrieving revision 1.28 diff -u -r1.28 bootinfo.c --- boot/i386/libi386/bootinfo.c 2001/02/18 10:25:41 1.28 +++ boot/i386/libi386/bootinfo.c 2001/10/19 06:30:27 @@ -88,6 +88,9 @@ case 'd': howto |= RB_KDB; break; + case 'D': + howto |= RB_MULTIPLE; + break; case 'm': howto |= RB_MUTE; break; ---------------------------------- cut here ---------------------------------- # $FreeBSD$ PROG= conscontrol MAN= conscontrol.8 .include <bsd.prog.mk> ---------------------------------- cut here ---------------------------------- #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/sysctl.h> static void __dead2 usage(void) { const char *pname = getprogname(); fprintf(stderr, "usage: %s [list]\n", pname); fprintf(stderr, " %s mute on|off\n", pname); fprintf(stderr, " %s add|delete console\n", pname); exit(1); } #define CONSBUFSIZE 32 static void constatus(void) { int mute; size_t len; char *buf, *p, *avail; len = sizeof(mute); if (sysctlbyname("kern.consmute", &mute, &len, NULL, 0) == -1) goto fail; len = 0; alloc: len += CONSBUFSIZE; buf = malloc(len); if (buf == NULL) err(1, "Could not malloc sysctl buffer"); if (sysctlbyname("kern.console", buf, &len, NULL, 0) == -1) { if (errno == ENOMEM) { free(buf); goto alloc; } goto fail; } avail = strchr(buf, '/'); p = avail; *avail++ = '\0'; if (p != buf) *--p = '\0'; /* remove trailing ',' */ p = avail + strlen(avail); if (p != avail) *--p = '\0'; /* remove trailing ',' */ printf("Configured: %s\n", buf); printf(" Available: %s\n", avail); printf(" Muting: %s\n", mute ? "on" : "off"); free(buf); return; fail: err(1, "Could not get console information"); } static void consmute(const char *onoff) { int mute; size_t len; if (strcmp(onoff, "on") == 0) mute = 1; else if (strcmp(onoff, "off") == 0) mute = 0; else usage(); len = sizeof(mute); if (sysctlbyname("kern.consmute", NULL, NULL, &mute, len) == -1) err(1, "Could not change console muting"); } static void consadd(char *devname) { size_t len; len = strlen(devname); if (sysctlbyname("kern.console", NULL, NULL, devname, len) == -1) err(1, "Could not add %s as a console", devname); } #define MAXDEVNAME 32 static void consdel(const char *devname) { char buf[MAXDEVNAME]; size_t len; snprintf(buf, MAXDEVNAME, "-%s", devname); len = strlen(buf); if (sysctlbyname("kern.console", NULL, NULL, &buf, len) == -1) err(1, "Could not remove %s as a console", devname); } int main(int argc, char **argv) { if (argc < 2 || strcmp(argv[1], "list") == 0) goto done; if (argc < 3) usage(); if (strcmp(argv[1], "mute") == 0) consmute(argv[2]); else if (strcmp(argv[1], "add") == 0) consadd(argv[2]); else if (strcmp(argv[1], "delete") == 0) consdel(argv[2]); else usage(); done: constatus(); } To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-hackers" in the body of the message