syscons(4): Use 100x37 when the VESA800X600 flag is specified.
[dragonfly.git] / sys / dev / misc / syscons / syscons.c
index 72ccc2b..afdbef9 100644 (file)
@@ -1,5 +1,5 @@
 /*-
 /*-
- * Copyright (c) 1992-1998 Søren Schmidt
+ * Copyright (c) 1992-1998 Søren Schmidt
  * All rights reserved.
  *
  * This code is derived from software contributed to The DragonFly Project
  * All rights reserved.
  *
  * This code is derived from software contributed to The DragonFly Project
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/dev/syscons/syscons.c,v 1.336.2.17 2004/03/25 08:41:09 ru Exp $
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/dev/syscons/syscons.c,v 1.336.2.17 2004/03/25 08:41:09 ru Exp $
- * $DragonFly: src/sys/dev/misc/syscons/syscons.c,v 1.33 2007/08/19 11:39:11 swildner Exp $
+ * $DragonFly: src/sys/dev/misc/syscons/syscons.c,v 1.35 2008/08/10 19:47:31 swildner Exp $
  */
 
 #include "use_splash.h"
 #include "opt_syscons.h"
 #include "opt_ddb.h"
  */
 
 #include "use_splash.h"
 #include "opt_syscons.h"
 #include "opt_ddb.h"
+#ifdef __i386__
 #include "use_apm.h"
 #include "use_apm.h"
+#endif
 
 #include <sys/param.h>
 #include <sys/systm.h>
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -43,6 +45,7 @@
 #include <sys/reboot.h>
 #include <sys/conf.h>
 #include <sys/proc.h>
 #include <sys/reboot.h>
 #include <sys/conf.h>
 #include <sys/proc.h>
+#include <sys/priv.h>
 #include <sys/signalvar.h>
 #include <sys/sysctl.h>
 #include <sys/tty.h>
 #include <sys/signalvar.h>
 #include <sys/sysctl.h>
 #include <sys/tty.h>
@@ -55,7 +58,9 @@
 #include <machine/console.h>
 #include <machine/psl.h>
 #include <machine/pc/display.h>
 #include <machine/console.h>
 #include <machine/psl.h>
 #include <machine/pc/display.h>
+#ifdef __i386__
 #include <machine/apm_bios.h>
 #include <machine/apm_bios.h>
+#endif
 #include <machine/frame.h>
 
 #include <dev/misc/kbd/kbdreg.h>
 #include <machine/frame.h>
 
 #include <dev/misc/kbd/kbdreg.h>
@@ -120,11 +125,12 @@ SYSCTL_INT(_machdep, OID_AUTO, enable_panic_key, CTLFLAG_RW, &enable_panic_key,
 
 #define SC_CONSOLECTL  255
 
 
 #define SC_CONSOLECTL  255
 
-#define VIRTUAL_TTY(sc, x) (SC_DEV((sc), (x)) != NULL ?        \
-       SC_DEV((sc), (x))->si_tty : NULL)
+#define VIRTUAL_TTY(sc, x) ((SC_DEV((sc),(x)) != NULL) ?       \
+       (SC_DEV((sc),(x))->si_tty) : NULL)
 #define ISTTYOPEN(tp)  ((tp) && ((tp)->t_state & TS_ISOPEN))
 
 #define ISTTYOPEN(tp)  ((tp) && ((tp)->t_state & TS_ISOPEN))
 
-static int             debugger;
+static int     debugger;
+static cdev_t  cctl_dev;
 
 /* prototypes */
 static int scvidprobe(int unit, int flags, int cons);
 
 /* prototypes */
 static int scvidprobe(int unit, int flags, int cons);
@@ -174,6 +180,7 @@ static int save_kbd_state(scr_stat *scp);
 static int update_kbd_state(scr_stat *scp, int state, int mask);
 static int update_kbd_leds(scr_stat *scp, int which);
 static timeout_t blink_screen;
 static int update_kbd_state(scr_stat *scp, int state, int mask);
 static int update_kbd_leds(scr_stat *scp, int which);
 static timeout_t blink_screen;
+static int sc_allocate_keyboard(sc_softc_t *sc, int unit);
 
 #define        CDEV_MAJOR      12
 
 
 #define        CDEV_MAJOR      12
 
@@ -204,7 +211,8 @@ static struct dev_ops sc_ops = {
        .d_ioctl =      scioctl,
        .d_poll =       ttypoll,
        .d_mmap =       scmmap,
        .d_ioctl =      scioctl,
        .d_poll =       ttypoll,
        .d_mmap =       scmmap,
-       .d_kqfilter =   ttykqfilter
+       .d_kqfilter =   ttykqfilter,
+       .d_revoke =     ttyrevoke
 };
 
 int
 };
 
 int
@@ -342,7 +350,7 @@ sc_attach_unit(int unit, int flags)
            splash_term(sc->adp);
 #endif
        sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
            splash_term(sc->adp);
 #endif
        sc_set_graphics_mode(scp, NULL, M_VESA_800x600);
-       sc_set_pixel_mode(scp, NULL, COL, ROW, 16);
+       sc_set_pixel_mode(scp, NULL, 0, 0, 16);
        sc->initial_mode = M_VESA_800x600;
 #if NSPLASH > 0
        /* put up the splash again! */
        sc->initial_mode = M_VESA_800x600;
 #if NSPLASH > 0
        /* put up the splash again! */
@@ -383,28 +391,22 @@ sc_attach_unit(int unit, int flags)
                              (void *)(uintptr_t)unit, SHUTDOWN_PRI_DEFAULT);
 
     /* 
                              (void *)(uintptr_t)unit, SHUTDOWN_PRI_DEFAULT);
 
     /* 
-     * create devices.  dev_ops_add() must be called to make devices under
-     * this major number available to userland.
+     * create devices.
+     *
+     * The first vty already has struct tty and scr_stat initialized
+     * in scinit().  The other vtys will have these structs when
+     * first opened.
      */
      */
-    dev_ops_add(&sc_ops, ~(MAXCONS - 1), unit * MAXCONS);
-
-    for (vc = 0; vc < sc->vtys; vc++) {
+    for (vc = 1; vc < sc->vtys; vc++) {
        dev = make_dev(&sc_ops, vc + unit * MAXCONS,
        dev = make_dev(&sc_ops, vc + unit * MAXCONS,
-           UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc + unit * MAXCONS);
+                       UID_ROOT, GID_WHEEL,
+                       0600, "ttyv%r", vc + unit * MAXCONS);
        sc->dev[vc] = dev;
        sc->dev[vc] = dev;
-       /*
-        * The first vty already has struct tty and scr_stat initialized
-        * in scinit().  The other vtys will have these structs when
-        * first opened.
-        */
     }
     }
-
-    dev_ops_add(&sc_ops, -1, SC_CONSOLECTL);   /* XXX */
-    dev = make_dev(&sc_ops, SC_CONSOLECTL,
-                  UID_ROOT, GID_WHEEL, 0600, "consolectl");
-    dev->si_tty = sc_console_tty = ttymalloc(sc_console_tty);
-    dev->si_drv1 = sc_console;
-
+    cctl_dev = make_dev(&sc_ops, SC_CONSOLECTL,
+                       UID_ROOT, GID_WHEEL, 0600, "consolectl");
+    cctl_dev->si_tty = sc_console_tty = ttymalloc(sc_console_tty);
+    cctl_dev->si_drv1 = sc_console;
     return 0;
 }
 
     return 0;
 }
 
@@ -473,7 +475,9 @@ scopen(struct dev_open_args *ap)
     tp->t_oproc = scstart;
     tp->t_param = scparam;
     tp->t_stop = nottystop;
     tp->t_oproc = scstart;
     tp->t_param = scparam;
     tp->t_stop = nottystop;
+
     tp->t_dev = dev;
     tp->t_dev = dev;
+
     if (!ISTTYOPEN(tp)) {
        ttychars(tp);
         /* Use the current setting of the <-- key as default VERASE. */  
     if (!ISTTYOPEN(tp)) {
        ttychars(tp);
         /* Use the current setting of the <-- key as default VERASE. */  
@@ -492,7 +496,7 @@ scopen(struct dev_open_args *ap)
        (*linesw[tp->t_line].l_modem)(tp, 1);
     }
     else
        (*linesw[tp->t_line].l_modem)(tp, 1);
     }
     else
-       if (tp->t_state & TS_XCLUDE && suser_cred(ap->a_cred, 0))
+       if (tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0))
            return(EBUSY);
 
     error = (*linesw[tp->t_line].l_open)(dev, tp);
            return(EBUSY);
 
     error = (*linesw[tp->t_line].l_open)(dev, tp);
@@ -559,6 +563,7 @@ scclose(struct dev_close_args *ap)
     (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
     ttyclose(tp);
     crit_exit();
     (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
     ttyclose(tp);
     crit_exit();
+
     return(0);
 }
 
     return(0);
 }
 
@@ -578,6 +583,9 @@ sckbdevent(keyboard_t *thiskbd, int event, void *arg)
     size_t len;
     u_char *cp;
 
     size_t len;
     u_char *cp;
 
+    /*
+     * WARNING: In early boot sc->dev may not be setup yet.
+     */
     sc = (sc_softc_t *)arg;
     /* assert(thiskbd == sc->kbd) */
 
     sc = (sc_softc_t *)arg;
     /* assert(thiskbd == sc->kbd) */
 
@@ -599,7 +607,6 @@ sckbdevent(keyboard_t *thiskbd, int event, void *arg)
      * the Xaccel-2.1 keyboard hang, but it can't hurt.                XXX
      */
     while ((c = scgetc(sc, SCGETC_NONBLOCK)) != NOKEY) {
      * the Xaccel-2.1 keyboard hang, but it can't hurt.                XXX
      */
     while ((c = scgetc(sc, SCGETC_NONBLOCK)) != NOKEY) {
-
        cur_tty = VIRTUAL_TTY(sc, sc->cur_scp->index);
        if (!ISTTYOPEN(cur_tty)) {
            cur_tty = sc_console_tty;
        cur_tty = VIRTUAL_TTY(sc, sc->cur_scp->index);
        if (!ISTTYOPEN(cur_tty)) {
            cur_tty = sc_console_tty;
@@ -980,8 +987,8 @@ scioctl(struct dev_ioctl_args *ap)
        scp = SC_STAT(SC_DEV(sc, i));
        if (scp == scp->sc->cur_scp)
            return 0;
        scp = SC_STAT(SC_DEV(sc, i));
        if (scp == scp->sc->cur_scp)
            return 0;
-       while ((error=tsleep((caddr_t)&scp->smode, PCATCH,
-                            "waitvt", 0)) == ERESTART) ;
+       error = tsleep((caddr_t)&scp->smode, PCATCH, "waitvt", 0);
+       /* May return ERESTART */
        return error;
 
     case VT_GETACTIVE:         /* get active vty # */
        return error;
 
     case VT_GETACTIVE:         /* get active vty # */
@@ -1000,16 +1007,24 @@ scioctl(struct dev_ioctl_args *ap)
        return 0;
 
     case KDENABIO:             /* allow io operations */
        return 0;
 
     case KDENABIO:             /* allow io operations */
-       error = suser_cred(ap->a_cred, 0);
+       error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
        if (error != 0)
            return error;
        if (securelevel > 0)
            return EPERM;
        if (error != 0)
            return error;
        if (securelevel > 0)
            return EPERM;
+#if defined(__i386__)
        curthread->td_lwp->lwp_md.md_regs->tf_eflags |= PSL_IOPL;
        curthread->td_lwp->lwp_md.md_regs->tf_eflags |= PSL_IOPL;
+#elif defined(__x86_64__)
+       curthread->td_lwp->lwp_md.md_regs->tf_rflags |= PSL_IOPL;
+#endif
        return 0;
 
     case KDDISABIO:            /* disallow io operations (default) */
        return 0;
 
     case KDDISABIO:            /* disallow io operations (default) */
+#if defined(__i386__)
        curthread->td_lwp->lwp_md.md_regs->tf_eflags &= ~PSL_IOPL;
        curthread->td_lwp->lwp_md.md_regs->tf_eflags &= ~PSL_IOPL;
+#elif defined(__x86_64__)
+       curthread->td_lwp->lwp_md.md_regs->tf_rflags &= ~PSL_IOPL;
+#endif
        return 0;
 
     case KDSKBSTATE:           /* set keyboard state (locks) */
        return 0;
 
     case KDSKBSTATE:           /* set keyboard state (locks) */
@@ -1106,6 +1121,13 @@ scioctl(struct dev_ioctl_args *ap)
        *(int *)data = scp->status & LED_MASK;
        return 0;
 
        *(int *)data = scp->status & LED_MASK;
        return 0;
 
+       case KBADDKBD:              /* add/remove keyboard to/from mux */
+       case KBRELKBD:
+               error = kbd_ioctl(sc->kbd, cmd, data);
+               if (error == ENOIOCTL)
+                       error = ENODEV;
+               return error;
+
     case CONS_SETKBD:          /* set the new keyboard */
        {
            keyboard_t *newkbd;
     case CONS_SETKBD:          /* set the new keyboard */
        {
            keyboard_t *newkbd;
@@ -1362,8 +1384,9 @@ sccninit(struct consdev *cp)
 static void
 sccninit_fini(struct consdev *cp)
 {
 static void
 sccninit_fini(struct consdev *cp)
 {
-    cp->cn_dev = make_dev(&sc_ops, SC_CONSOLECTL,
-                         UID_ROOT, GID_WHEEL, 0600, "consolectl");
+       if (cctl_dev == NULL)
+               kprintf("sccninit_fini: WARNING: cctl_dev is NULL!\n");
+       cp->cn_dev = cctl_dev;
 }
 
 static void
 }
 
 static void
@@ -1594,8 +1617,7 @@ scrn_timer(void *arg)
     if ((sc->kbd == NULL) && (sc->config & SC_AUTODETECT_KBD)) {
        /* try to allocate a keyboard automatically */
        if (++kbd_interval >= 25) {
     if ((sc->kbd == NULL) && (sc->config & SC_AUTODETECT_KBD)) {
        /* try to allocate a keyboard automatically */
        if (++kbd_interval >= 25) {
-           sc->keyboard = kbd_allocate("*", -1, (void *)&sc->keyboard,
-                                       sckbdevent, sc);
+           sc->keyboard = sc_allocate_keyboard(sc, -1);
            if (sc->keyboard >= 0) {
                sc->kbd = kbd_get_keyboard(sc->keyboard);
                kbd_ioctl(sc->kbd, KDSKBMODE,
            if (sc->keyboard >= 0) {
                sc->kbd = kbd_get_keyboard(sc->keyboard);
                kbd_ioctl(sc->kbd, KDSKBMODE,
@@ -1607,9 +1629,6 @@ scrn_timer(void *arg)
        }
     }
 
        }
     }
 
-    /* find the vty to update */
-    scp = sc->cur_scp;
-
     /* should we stop the screen saver? */
     getmicrouptime(&tv);
     if (debugger > 0 || panicstr || shutdown_in_progress)
     /* should we stop the screen saver? */
     getmicrouptime(&tv);
     if (debugger > 0 || panicstr || shutdown_in_progress)
@@ -2009,8 +2028,9 @@ wait_scrn_saver_stop(sc_softc_t *sc)
            break;
        }
        error = tsleep((caddr_t)&scrn_blanked, PCATCH, "scrsav", 0);
            break;
        }
        error = tsleep((caddr_t)&scrn_blanked, PCATCH, "scrsav", 0);
-       if ((error != 0) && (error != ERESTART))
-           break;
+       /* May return ERESTART */
+       if (error)
+               break;
     }
     run_scrn_saver = FALSE;
     return error;
     }
     run_scrn_saver = FALSE;
     return error;
@@ -2500,8 +2520,7 @@ scinit(int unit, int flags)
     sc->adapter = vid_allocate("*", unit, (void *)&sc->adapter);
     sc->adp = vid_get_adapter(sc->adapter);
     /* assert((sc->adapter >= 0) && (sc->adp != NULL)) */
     sc->adapter = vid_allocate("*", unit, (void *)&sc->adapter);
     sc->adp = vid_get_adapter(sc->adapter);
     /* assert((sc->adapter >= 0) && (sc->adp != NULL)) */
-    sc->keyboard = kbd_allocate("*", unit, (void *)&sc->keyboard,
-                               sckbdevent, sc);
+    sc->keyboard = sc_allocate_keyboard(sc, unit);
     DPRINTF(1, ("sc%d: keyboard %d\n", unit, sc->keyboard));
     sc->kbd = kbd_get_keyboard(sc->keyboard);
     if (sc->kbd != NULL) {
     DPRINTF(1, ("sc%d: keyboard %d\n", unit, sc->keyboard));
     sc->kbd = kbd_get_keyboard(sc->keyboard);
     if (sc->kbd != NULL) {
@@ -2547,8 +2566,10 @@ scinit(int unit, int flags)
        } else {
            /* assert(sc_malloc) */
            sc->dev = kmalloc(sizeof(cdev_t)*sc->vtys, M_SYSCONS, M_WAITOK | M_ZERO);
        } else {
            /* assert(sc_malloc) */
            sc->dev = kmalloc(sizeof(cdev_t)*sc->vtys, M_SYSCONS, M_WAITOK | M_ZERO);
+
            sc->dev[0] = make_dev(&sc_ops, unit*MAXCONS, UID_ROOT, 
                                GID_WHEEL, 0600, "ttyv%r", unit*MAXCONS);
            sc->dev[0] = make_dev(&sc_ops, unit*MAXCONS, UID_ROOT, 
                                GID_WHEEL, 0600, "ttyv%r", unit*MAXCONS);
+
            sc->dev[0]->si_tty = ttymalloc(sc->dev[0]->si_tty);
            scp = alloc_scp(sc, sc->first_vty);
            sc->dev[0]->si_drv1 = scp;
            sc->dev[0]->si_tty = ttymalloc(sc->dev[0]->si_tty);
            scp = alloc_scp(sc, sc->first_vty);
            sc->dev[0]->si_drv1 = scp;
@@ -3451,3 +3472,41 @@ blink_screen(void *arg)
        callout_reset(&scp->blink_screen_ch, hz / 10, blink_screen, scp);
     }
 }
        callout_reset(&scp->blink_screen_ch, hz / 10, blink_screen, scp);
     }
 }
+
+
+/*
+ * Allocate active keyboard. Try to allocate "kbdmux" keyboard first, and,
+ * if found, add all non-busy keyboards to "kbdmux". Otherwise look for
+ * any keyboard.
+ */
+
+static int
+sc_allocate_keyboard(sc_softc_t *sc, int unit)
+{
+       int              idx0, idx;
+       keyboard_t      *k0, *k;
+       keyboard_info_t  ki;
+
+       idx0 = kbd_allocate("kbdmux", -1, (void *)&sc->keyboard, sckbdevent, sc);
+       if (idx0 != -1) {
+               k0 = kbd_get_keyboard(idx0);
+
+               for (idx = kbd_find_keyboard2("*", -1, 0, 0);
+                    idx != -1;
+                    idx = kbd_find_keyboard2("*", -1, idx + 1, 0)) {
+                       k = kbd_get_keyboard(idx);
+
+                       if (idx == idx0 || KBD_IS_BUSY(k))
+                               continue;
+
+                       bzero(&ki, sizeof(ki));
+                       strcpy(ki.kb_name, k->kb_name);
+                       ki.kb_unit = k->kb_unit;
+
+                       kbd_ioctl(k0, KBADDKBD, (caddr_t) &ki);
+               }
+       } else
+               idx0 = kbd_allocate("*", unit, (void *)&sc->keyboard, sckbdevent, sc);
+
+       return (idx0);
+}