MPSAFE - TTY & related drivers
authorAlex Hornung <ahornung@gmail.com>
Fri, 27 Aug 2010 23:33:26 +0000 (00:33 +0100)
committerAlex Hornung <ahornung@gmail.com>
Sat, 28 Aug 2010 00:02:11 +0000 (01:02 +0100)
* Put kern/tty_* under the tty_token (and acquire the proc_token where
  needed).

* MPSAFE all related drivers (users of kbdsw, linesw and vidsw) with the
  same tty_token.

* NOTE: syscons.c and scvgarndr.c are not really under this new lock
  yet as some really strange hangs appear. Some are related to the
  cursor drawing (which stalls the  machine if a token is held) and
  others are in some other syscons.c functions.

58 files changed:
sys/bus/isa/vga_isa.c
sys/dev/misc/atkbd/atkbd_isa.c
sys/dev/misc/atkbdc_layer/atkbdc_isa.c
sys/dev/misc/dcons/dcons_os.c
sys/dev/misc/kbd/atkbd.c
sys/dev/misc/kbd/atkbdc.c
sys/dev/misc/kbd/kbd.c
sys/dev/misc/kbdmux/kbdmux.c
sys/dev/misc/nmdm/nmdm.c
sys/dev/misc/snp/snp.c
sys/dev/misc/syscons/blank/blank_saver.c
sys/dev/misc/syscons/dragon/dragon_saver.c
sys/dev/misc/syscons/fade/fade_saver.c
sys/dev/misc/syscons/fire/fire_saver.c
sys/dev/misc/syscons/fred/fred_saver.c
sys/dev/misc/syscons/green/green_saver.c
sys/dev/misc/syscons/logo/logo_saver.c
sys/dev/misc/syscons/rain/rain_saver.c
sys/dev/misc/syscons/scvgarndr.c
sys/dev/misc/syscons/scvidctl.c
sys/dev/misc/syscons/snake/snake_saver.c
sys/dev/misc/syscons/star/star_saver.c
sys/dev/misc/syscons/syscons.c
sys/dev/misc/syscons/sysmouse.c
sys/dev/misc/syscons/warp/warp_saver.c
sys/dev/serial/cy/cy.c
sys/dev/serial/cy/cy_pci.c
sys/dev/serial/dgb/dgm.c
sys/dev/serial/digi/digi.c
sys/dev/serial/digi/digi_pci.c
sys/dev/serial/rc/rc.c
sys/dev/serial/rp/rp.c
sys/dev/serial/si/si.c
sys/dev/serial/si/si_eisa.c
sys/dev/serial/si/si_isa.c
sys/dev/serial/si/si_pci.c
sys/dev/serial/sio/sio.c
sys/dev/usbmisc/ucom/ucom.c
sys/dev/usbmisc/ukbd/ukbd.c
sys/dev/video/fb/bmp/splash_bmp.c
sys/dev/video/fb/fb.c
sys/dev/video/fb/fbreg.h
sys/dev/video/fb/pcx/splash_pcx.c
sys/dev/video/fb/vga.c
sys/dev/video/i386/vesa/vesa.c
sys/kern/tty.c
sys/kern/tty_conf.c
sys/kern/tty_pty.c
sys/kern/tty_subr.c
sys/kern/tty_tty.c
sys/net/ppp_layer/ppp_tty.c
sys/net/sl/if_sl.c
sys/netgraph/tty/ng_tty.c
sys/netgraph7/bluetooth/drivers/h4/ng_h4.c
sys/netgraph7/ng_tty.c
sys/platform/pc32/gnu/isa/dgb.c
sys/platform/vkernel/platform/console.c
sys/platform/vkernel64/platform/console.c

index 3a1c1f0..859a4b4 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
  * All rights reserved.
  *
@@ -40,6 +42,7 @@
 #include <sys/bus.h>
 #include <sys/fbio.h>
 #include <sys/rman.h>
+#include <sys/thread.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -195,6 +198,7 @@ isavga_suspend(device_t dev)
                return (0);
        if (bootverbose)
                device_printf(dev, "saving %d bytes of video state\n", nbytes);
+       lwkt_gettoken(&tty_token);
        if ((*vidsw[sc->adp->va_index]->save_state)(sc->adp, sc->state_buf,
            nbytes) != 0) {
                device_printf(dev, "failed to save state (nbytes=%d)\n",
@@ -202,6 +206,7 @@ isavga_suspend(device_t dev)
                kfree(sc->state_buf, M_TEMP);
                sc->state_buf = NULL;
        }
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
index f3915f8..bb4ebff 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
  * All rights reserved.
  *
@@ -34,6 +36,7 @@
 #include <sys/kernel.h>
 #include <sys/bus.h>
 #include <sys/rman.h>
+#include <sys/thread.h>
 
 #include <sys/kbio.h>
 #include <dev/misc/kbd/kbdreg.h>
 #include <bus/isa/isareg.h>
 #include <bus/isa/isavar.h>
 
+#if 0
+#define lwkt_gettoken(x)
+#define lwkt_reltoken(x)
+#endif
+
 typedef struct {
        struct resource *intr;
        void            *ih;
@@ -111,7 +119,7 @@ atkbdattach(device_t dev)
        rid = 0;
        sc->intr = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, irq, 1,
                                      RF_SHAREABLE | RF_ACTIVE);
-       BUS_SETUP_INTR(device_get_parent(dev), dev, sc->intr, 0,
+       BUS_SETUP_INTR(device_get_parent(dev), dev, sc->intr, INTR_MPSAFE,
                       atkbd_isa_intr, kbd, &sc->ih, NULL);
 
        return 0;
@@ -124,6 +132,7 @@ atkbdresume(device_t dev)
         keyboard_t *kbd;
         int args[2];
 
+       lwkt_gettoken(&tty_token);
         sc = device_get_softc(dev);
         kbd = kbd_get_keyboard(kbd_find_keyboard(ATKBD_DRIVER_NAME,
                                                  device_get_unit(dev)));
@@ -136,6 +145,7 @@ atkbdresume(device_t dev)
                (*kbdsw[kbd->kb_index]->clear_state)(kbd);
 
         }
+       lwkt_reltoken(&tty_token);
         return 0;
 }
 
@@ -144,8 +154,10 @@ atkbd_isa_intr(void *arg)
 {
        keyboard_t *kbd;
 
+       lwkt_gettoken(&tty_token);
        kbd = (keyboard_t *)arg;
        kbd_intr(kbd, NULL);
+       lwkt_reltoken(&tty_token);
 }
 
 DRIVER_MODULE(atkbd, atkbdc, atkbd_driver, atkbd_devclass, 0, 0);
index 4b8cdbc..b7aab0b 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
  * All rights reserved.
  *
 #include <sys/bus.h>
 #include <sys/malloc.h>
 #include <sys/rman.h>
+#include <sys/thread.h>
 
 #include <dev/misc/kbd/atkbdcreg.h>
 
 #include <bus/isa/isareg.h>
 #include <bus/isa/isavar.h>
 
+#if 0
+#define lwkt_gettoken(x)
+#define lwkt_reltoken(x)
+#endif
+
 MALLOC_DEFINE(M_ATKBDDEV, "atkbddev", "AT Keyboard device");
 
 /* children */
@@ -198,6 +206,7 @@ atkbdc_attach(device_t dev)
        int             rid;
        int             i;
 
+       lwkt_gettoken(&tty_token);
        unit = device_get_unit(dev);
        sc = *(atkbdc_softc_t **)device_get_softc(dev);
        if (sc == NULL) {
@@ -209,20 +218,25 @@ atkbdc_attach(device_t dev)
                 * See atkbdc.c. XXX
                 */
                sc = atkbdc_get_softc(unit);
-               if (sc == NULL)
+               if (sc == NULL) {
+                       lwkt_reltoken(&tty_token);
                        return ENOMEM;
+               }
        }
 
        rid = 0;
        sc->port0 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
                                       RF_ACTIVE);
-       if (sc->port0 == NULL)
+       if (sc->port0 == NULL) {
+               lwkt_reltoken(&tty_token);
                return ENXIO;
+       }
        rid = 1;
        sc->port1 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
                                       RF_ACTIVE);
        if (sc->port1 == NULL) {
                bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
+               lwkt_reltoken(&tty_token);
                return ENXIO;
        }
 
@@ -230,6 +244,7 @@ atkbdc_attach(device_t dev)
        if (error) {
                bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
                bus_release_resource(dev, SYS_RES_IOPORT, 1, sc->port1);
+               lwkt_reltoken(&tty_token);
                return error;
        }
        *(atkbdc_softc_t **)device_get_softc(dev) = sc;
@@ -256,6 +271,7 @@ atkbdc_attach(device_t dev)
 
        bus_generic_attach(dev);
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -282,6 +298,7 @@ atkbdc_read_ivar(device_t bus, device_t dev, int index, u_long *val)
 {
        atkbdc_device_t *ivar;
 
+       lwkt_gettoken(&tty_token);
        ivar = (atkbdc_device_t *)device_get_ivars(dev);
        switch (index) {
        case KBDC_IVAR_IRQ:
@@ -303,8 +320,11 @@ atkbdc_read_ivar(device_t bus, device_t dev, int index, u_long *val)
                *val = (u_long)ivar->compatid;
                break;
        default:
+               lwkt_reltoken(&tty_token);
                return ENOENT;
        }
+
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -313,6 +333,7 @@ atkbdc_write_ivar(device_t bus, device_t dev, int index, u_long val)
 {
        atkbdc_device_t *ivar;
 
+       lwkt_gettoken(&tty_token);
        ivar = (atkbdc_device_t *)device_get_ivars(dev);
        switch (index) {
        case KBDC_IVAR_IRQ:
@@ -334,8 +355,11 @@ atkbdc_write_ivar(device_t bus, device_t dev, int index, u_long val)
                ivar->compatid = (u_int32_t)val;
                break;
        default:
+               lwkt_reltoken(&tty_token);
                return ENOENT;
        }
+
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
index 37c9f73..08e10b3 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * (MPSAFE)
+ *
  * Copyright (C) 2003,2004
  *     Hidetoshi Shimokawa. All rights reserved.
  * 
@@ -171,6 +173,7 @@ dcons_check_break(struct dcons_softc *dc, int c)
        if (c < 0)
                return (c);
 
+       lwkt_gettoken(&tty_token);
 #if __FreeBSD_version >= 502122
        if (kdb_alt_break(c, &dc->brk_state)) {
                if ((dc->flags & DC_GDB) != 0) {
@@ -202,6 +205,7 @@ dcons_check_break(struct dcons_softc *dc, int c)
        if (c == KEY_CR)
                dc->brk_state = STATE1;
 #endif
+       lwkt_reltoken(&tty_token);
        return (c);
 }
 #else
@@ -213,6 +217,7 @@ dcons_os_checkc(struct dcons_softc *dc)
 {
        int c;
 
+       lwkt_gettoken(&tty_token);
        if (dg.dma_tag != NULL)
                bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD);
   
@@ -221,6 +226,7 @@ dcons_os_checkc(struct dcons_softc *dc)
        if (dg.dma_tag != NULL)
                bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREREAD);
 
+       lwkt_reltoken(&tty_token);
        return (c);
 }
 
@@ -237,6 +243,7 @@ dcons_os_getc(struct dcons_softc *dc)
 static void
 dcons_os_putc(struct dcons_softc *dc, int c)
 {
+       lwkt_gettoken(&tty_token);
        if (dg.dma_tag != NULL)
                bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTWRITE);
 
@@ -244,6 +251,7 @@ dcons_os_putc(struct dcons_softc *dc, int c)
 
        if (dg.dma_tag != NULL)
                bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE);
+       lwkt_reltoken(&tty_token);
 }
 static int
 dcons_open(struct dev_open_args *ap)
@@ -256,6 +264,7 @@ dcons_open(struct dev_open_args *ap)
        if (unit != 0)
                return (ENXIO);
 
+       lwkt_gettoken(&tty_token);
        tp = dev->si_tty = ttymalloc(dev->si_tty);
        tp->t_oproc = dcons_tty_start;
        tp->t_param = dcons_tty_param;
@@ -276,6 +285,7 @@ dcons_open(struct dev_open_args *ap)
                ttsetwater(tp);
        } else if ((tp->t_state & TS_XCLUDE) && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return (EBUSY);
        }
        crit_exit();
@@ -285,7 +295,7 @@ dcons_open(struct dev_open_args *ap)
 #else
        error = ttyld_open(tp, dev);
 #endif
-
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
@@ -300,11 +310,13 @@ dcons_close(struct dev_close_args *ap)
        if (unit != 0)
                return (ENXIO);
 
+       lwkt_gettoken(&tty_token);
        tp = dev->si_tty;
        if (tp->t_state & TS_ISOPEN) {
                (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
                ttyclose(tp);
        }
+       lwkt_reltoken(&tty_token);
 
        return (0);
 }
@@ -321,24 +333,32 @@ dcons_ioctl(struct dev_ioctl_args *ap)
        if (unit != 0)
                return (ENXIO);
 
+       lwkt_gettoken(&tty_token);
        tp = dev->si_tty;
        error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data, ap->a_fflag, ap->a_cred);
-       if (error != ENOIOCTL)
+       if (error != ENOIOCTL) {
+               lwkt_reltoken(&tty_token);
                return (error);
+       }
 
        error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag);
-       if (error != ENOIOCTL)
+       if (error != ENOIOCTL) {
+               lwkt_reltoken(&tty_token);
                return (error);
+       }
 
+       lwkt_reltoken(&tty_token);
        return (ENOTTY);
 }
 
 static int
 dcons_tty_param(struct tty *tp, struct termios *t)
 {
+       lwkt_gettoken(&tty_token);
        tp->t_ispeed = t->c_ispeed;
        tp->t_ospeed = t->c_ospeed;
        tp->t_cflag = t->c_cflag;
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -347,10 +367,12 @@ dcons_tty_start(struct tty *tp)
 {
        struct dcons_softc *dc;
 
+       lwkt_gettoken(&tty_token);
        dc = (struct dcons_softc *)tp->t_dev->si_drv1;
        crit_enter();
        if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
                ttwwakeup(tp);
+               lwkt_reltoken(&tty_token);
                return;
        }
 
@@ -361,6 +383,7 @@ dcons_tty_start(struct tty *tp)
 
        ttwwakeup(tp);
        crit_exit();
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -370,6 +393,7 @@ dcons_timeout(void *v)
        struct dcons_softc *dc;
        int i, c, polltime;
 
+       lwkt_gettoken(&tty_token);
        for (i = 0; i < DCONS_NPORT; i ++) {
                dc = &sc[i];
                tp = ((DEV)dc->dev)->si_tty;
@@ -385,6 +409,7 @@ dcons_timeout(void *v)
        if (polltime < 1)
                polltime = 1;
        callout_reset(&dcons_callout, polltime, dcons_timeout, tp);
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -407,6 +432,7 @@ dcons_cnprobe(struct consdev *cp)
 static void
 dcons_cninit(struct consdev *cp)
 {
+       lwkt_gettoken(&tty_token);
        dcons_drv_init(0);
 #if CONS_NODEV
        cp->cn_arg
@@ -414,6 +440,7 @@ dcons_cninit(struct consdev *cp)
        cp->cn_private
 #endif
                = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -536,7 +563,9 @@ ok:
        return 0;
 }
 
-
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 dcons_attach_port(int port, char *name, int flags)
 {
@@ -544,6 +573,7 @@ dcons_attach_port(int port, char *name, int flags)
        struct tty *tp;
        DEV dev;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        dc = &sc[port];
        dc->flags = flags;
        dev = make_dev(&dcons_ops, port,
@@ -562,15 +592,19 @@ dcons_attach_port(int port, char *name, int flags)
        return(0);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 dcons_attach(void)
 {
        int polltime;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        dcons_attach_port(DCONS_CON, "dcons", 0);
        dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB);
 #if __FreeBSD_version < 500000
-       callout_init(&dcons_callout);
+       callout_init_mp(&dcons_callout);
 #else
        callout_init(&dcons_callout, 0);
 #endif
@@ -581,12 +615,16 @@ dcons_attach(void)
        return(0);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 dcons_detach(int port)
 {
        struct  tty *tp;
        struct dcons_softc *dc;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        dc = &sc[port];
 
        tp = ((DEV)dc->dev)->si_tty;
@@ -621,6 +659,7 @@ dcons_modevent(module_t mode, int type, void *data)
 {
        int err = 0, ret;
 
+       lwkt_gettoken(&tty_token);
        switch (type) {
        case MOD_LOAD:
                ret = dcons_drv_init(1);
@@ -663,6 +702,7 @@ dcons_modevent(module_t mode, int type, void *data)
                err = EOPNOTSUPP;
                break;
        }
+       lwkt_reltoken(&tty_token);
        return(err);
 }
 
index cb1d0f6..f3564b0 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
  * All rights reserved.
  *
 
 #include <bus/isa/isareg.h>
 
+#if 0
+#define lwkt_gettoken(x)
+#define lwkt_reltoken(x)
+#endif
+
 static timeout_t       atkbd_timeout;
 
 int
@@ -64,13 +71,19 @@ atkbd_probe_unit(int unit, int ctlr, int irq, int flags)
        int args[2];
        int error;
 
+       lwkt_gettoken(&tty_token);
        sw = kbd_get_switch(ATKBD_DRIVER_NAME);
-       if (sw == NULL)
+       if (sw == NULL) {
+               lwkt_reltoken(&tty_token);
                return ENXIO;
+       }
 
        args[0] = ctlr;
        args[1] = irq;
        error = (*sw->probe)(unit, args, flags);
+
+       lwkt_reltoken(&tty_token);
+
        if (error)
                return error;
        return 0;
@@ -83,27 +96,37 @@ atkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags)
        int args[2];
        int error;
 
+       lwkt_gettoken(&tty_token);
+
        sw = kbd_get_switch(ATKBD_DRIVER_NAME);
-       if (sw == NULL)
+       if (sw == NULL) {
+               lwkt_reltoken(&tty_token);
                return ENXIO;
+       }
 
        /* reset, initialize and enable the device */
        args[0] = ctlr;
        args[1] = irq;
        *kbd = NULL;
        error = (*sw->probe)(unit, args, flags);
-       if (error)
+       if (error) {
+               lwkt_reltoken(&tty_token);
                return error;
+       }
        error = (*sw->init)(unit, kbd, args, flags);
-       if (error)
+       if (error) {
+               lwkt_reltoken(&tty_token);
                return error;
+       }
        (*sw->enable)(*kbd);
 
 #ifdef KBD_INSTALL_CDEV
        /* attach a virtual keyboard cdev */
        error = kbd_attach(*kbd);
-       if (error)
+       if (error) {
+               lwkt_reltoken(&tty_token);
                return error;
+       }
 #endif
 
        /*
@@ -114,6 +137,8 @@ atkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags)
 
        if (bootverbose)
                (*sw->diag)(*kbd, bootverbose);
+
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -148,6 +173,7 @@ atkbd_timeout(void *arg)
         * The keyboard apparently unwedges the irq in most cases.
         */
        crit_enter();
+       lwkt_gettoken(&tty_token);
        kbd = (keyboard_t *)arg;
        if (kbd_lock(kbd, TRUE)) {
                /*
@@ -160,6 +186,7 @@ atkbd_timeout(void *arg)
                        kbd_intr(kbd, NULL);
        }
        callout_reset(&kbd->kb_atkbd_timeout_ch, hz / 10, atkbd_timeout, arg);
+       lwkt_reltoken(&tty_token);
        crit_exit();
 }
 
@@ -270,6 +297,8 @@ atkbd_configure(int flags)
        int arg[2];
        int i;
 
+       lwkt_gettoken(&tty_token);
+
        /*
         * Probe the keyboard controller, if not present or if the driver
         * is disabled, unregister the keyboard if any.
@@ -282,6 +311,7 @@ atkbd_configure(int flags)
                        kbd_unregister(kbd);
                        kbd->kb_flags &= ~KB_REGISTERED;
                }
+               lwkt_reltoken(&tty_token);
                return 0;
        }
        
@@ -293,12 +323,17 @@ atkbd_configure(int flags)
        arg[0] = -1;
        arg[1] = -1;
        kbd = NULL;
-       if (atkbd_probe(ATKBD_DEFAULT, arg, flags))
+       if (atkbd_probe(ATKBD_DEFAULT, arg, flags)) {
+               lwkt_reltoken(&tty_token);
                return 0;
-       if (atkbd_init(ATKBD_DEFAULT, &kbd, arg, flags))
+       }
+       if (atkbd_init(ATKBD_DEFAULT, &kbd, arg, flags)) {
+               lwkt_reltoken(&tty_token);
                return 0;
+       }
 
        /* return the number of found keyboards */
+       lwkt_reltoken(&tty_token);
        return 1;
 }
 
@@ -311,18 +346,28 @@ atkbd_probe(int unit, void *arg, int flags)
        KBDC kbdc;
        int *data = (int *)arg; /* data[0]: controller, data[1]: irq */
 
+       lwkt_gettoken(&tty_token);
+
        if (unit == ATKBD_DEFAULT) {
-               if (KBD_IS_PROBED(&default_kbd))
+               if (KBD_IS_PROBED(&default_kbd)) {
+                       lwkt_reltoken(&tty_token);
                        return 0;
+               }
        }
 
        kbdc = atkbdc_open(data[0]);
-       if (kbdc == NULL)
+       if (kbdc == NULL) {
+               lwkt_reltoken(&tty_token);
                return ENXIO;
+       }
        if (probe_keyboard(kbdc, flags)) {
-               if (flags & KB_CONF_FAIL_IF_NO_KBD)
+               if (flags & KB_CONF_FAIL_IF_NO_KBD) {
+                       lwkt_reltoken(&tty_token);
                        return ENXIO;
+               }
        }
+
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -339,11 +384,15 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
        int delay[2];
        int *data = (int *)arg; /* data[0]: controller, data[1]: irq */
 
+       lwkt_gettoken(&tty_token);
+
        /* XXX */
        if (unit == ATKBD_DEFAULT) {
                *kbdp = kbd = &default_kbd;
-               if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd))
+               if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) {
+                       lwkt_reltoken(&tty_token);
                        return 0;
+               }
                state = &default_kbd_state;
                keymap = &default_keymap;
                accmap = &default_accentmap;
@@ -358,6 +407,7 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
                fkeymap = kmalloc(sizeof(fkey_tab), M_DEVBUF, M_WAITOK);
                fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
        } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
+               lwkt_reltoken(&tty_token);
                return 0;
        } else {
                kbd = *kbdp;
@@ -371,8 +421,10 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
 
        if (!KBD_IS_PROBED(kbd)) {
                state->kbdc = atkbdc_open(data[0]);
-               if (state->kbdc == NULL)
+               if (state->kbdc == NULL) {
+                       lwkt_reltoken(&tty_token);
                        return ENXIO;
+               }
                kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags,
                                KB_PRI_ATKBD, 0, 0);
                bcopy(&key_map, keymap, sizeof(key_map));
@@ -383,8 +435,10 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
                kbd->kb_data = (void *)state;
        
                if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */
-                       if (flags & KB_CONF_FAIL_IF_NO_KBD)
+                       if (flags & KB_CONF_FAIL_IF_NO_KBD) {
+                               lwkt_reltoken(&tty_token);
                                return ENXIO;
+                       }
                } else {
                        KBD_FOUND_DEVICE(kbd);
                }
@@ -400,8 +454,10 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
                kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
                if (KBD_HAS_DEVICE(kbd)
                    && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
-                   && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD))
+                   && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) {
+                       lwkt_reltoken(&tty_token);
                        return ENXIO;
+               }
                atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
                get_typematic(kbd);
                delay[0] = kbd->kb_delay1;
@@ -410,11 +466,14 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
                KBD_INIT_DONE(kbd);
        }
        if (!KBD_IS_CONFIGURED(kbd)) {
-               if (kbd_register(kbd) < 0)
+               if (kbd_register(kbd) < 0) {
+                       lwkt_reltoken(&tty_token);
                        return ENXIO;
+               }
                KBD_CONFIG_DONE(kbd);
        }
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -422,7 +481,9 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
 static int
 atkbd_term(keyboard_t *kbd)
 {
+       lwkt_gettoken(&tty_token);
        kbd_unregister(kbd);
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -434,6 +495,7 @@ atkbd_intr(keyboard_t *kbd, void *arg)
        int delay[2];
        int c;
 
+       lwkt_gettoken(&tty_token);
        if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
                /* let the callback function to process the input */
                (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
@@ -460,6 +522,8 @@ atkbd_intr(keyboard_t *kbd, void *arg)
                        KBD_FOUND_DEVICE(kbd);
                }
        }
+
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -489,7 +553,9 @@ static int
 atkbd_enable(keyboard_t *kbd)
 {
        crit_enter();
+       lwkt_gettoken(&tty_token);
        KBD_ACTIVATE(kbd);
+       lwkt_reltoken(&tty_token);
        crit_exit();
        return 0;
 }
@@ -499,7 +565,9 @@ static int
 atkbd_disable(keyboard_t *kbd)
 {
        crit_enter();
+       lwkt_gettoken(&tty_token);
        KBD_DEACTIVATE(kbd);
+       lwkt_reltoken(&tty_token);
        crit_exit();
        return 0;
 }
@@ -508,24 +576,38 @@ atkbd_disable(keyboard_t *kbd)
 static int
 atkbd_read(keyboard_t *kbd, int wait)
 {
-       int c;
+       int c, ret;
 
+       lwkt_gettoken(&tty_token);
        if (wait)
                c = read_kbd_data(((atkbd_state_t *)kbd->kb_data)->kbdc);
        else
                c = read_kbd_data_no_wait(((atkbd_state_t *)kbd->kb_data)->kbdc);
        if (c != -1)
                ++kbd->kb_count;
-       return (KBD_IS_ACTIVE(kbd) ? c : -1);
+
+       ret = (KBD_IS_ACTIVE(kbd) ? c : -1);
+
+       lwkt_reltoken(&tty_token);
+       return ret;
 }
 
 /* check if data is waiting */
 static int
 atkbd_check(keyboard_t *kbd)
 {
-       if (!KBD_IS_ACTIVE(kbd))
+       int ret;
+
+       lwkt_gettoken(&tty_token);
+
+       if (!KBD_IS_ACTIVE(kbd)) {
+               lwkt_reltoken(&tty_token);
                return FALSE;
-       return kbdc_data_ready(((atkbd_state_t *)kbd->kb_data)->kbdc);
+       }
+       ret = kbdc_data_ready(((atkbd_state_t *)kbd->kb_data)->kbdc);
+
+       lwkt_reltoken(&tty_token);
+       return ret;
 }
 
 /* read char from the keyboard */
@@ -537,14 +619,18 @@ atkbd_read_char(keyboard_t *kbd, int wait)
        int scancode;
        int keycode;
 
+       lwkt_gettoken(&tty_token);
        state = (atkbd_state_t *)kbd->kb_data;
 next_code:
        /* do we have a composed char to return? */
        if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
                action = state->ks_composed_char;
                state->ks_composed_char = 0;
-               if (action > UCHAR_MAX)
+               if (action > UCHAR_MAX) {
+                       lwkt_reltoken(&tty_token);
                        return ERRKEY;
+               }
+               lwkt_reltoken(&tty_token);
                return action;
        }
 
@@ -555,8 +641,10 @@ next_code:
                } while (scancode == -1);
        } else {
                scancode = read_kbd_data_no_wait(state->kbdc);
-               if (scancode == -1)
+               if (scancode == -1) {
+                       lwkt_reltoken(&tty_token);
                        return NOKEY;
+               }
        }
        ++kbd->kb_count;
 
@@ -565,8 +653,10 @@ next_code:
 #endif
 
        /* return the byte as is for the K_RAW mode */
-       if (state->ks_mode == K_RAW)
+       if (state->ks_mode == K_RAW) {
+               lwkt_reltoken(&tty_token);
                return scancode;
+       }
 
        /* translate the scan code into a keycode */
        keycode = scancode & 0x7F;
@@ -706,8 +796,10 @@ next_code:
        }
 
        /* return the key code in the K_CODE mode */
-       if (state->ks_mode == K_CODE)
+       if (state->ks_mode == K_CODE) {
+               lwkt_reltoken(&tty_token);
                return (keycode | (scancode & 0x80));
+       }
 
        /* compose a character code */
        if (state->ks_flags & COMPOSE) {
@@ -751,6 +843,7 @@ next_code:
                        if (state->ks_composed_char > 0) {
                                state->ks_flags &= ~COMPOSE;
                                state->ks_composed_char = 0;
+                               lwkt_reltoken(&tty_token);
                                return ERRKEY;
                        }
                        break;
@@ -760,10 +853,13 @@ next_code:
        /* keycode to key action */
        action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
                                  &state->ks_state, &state->ks_accents);
-       if (action == NOKEY)
+       if (action == NOKEY) {
                goto next_code;
-       else
+       } else {
+               lwkt_reltoken(&tty_token);
                return action;
+       }
+       lwkt_reltoken(&tty_token);
 }
 
 /* check if char is waiting */
@@ -771,13 +867,21 @@ static int
 atkbd_check_char(keyboard_t *kbd)
 {
        atkbd_state_t *state;
+       int ret;
 
-       if (!KBD_IS_ACTIVE(kbd))
+       lwkt_gettoken(&tty_token);
+       if (!KBD_IS_ACTIVE(kbd)) {
+               lwkt_reltoken(&tty_token);
                return FALSE;
+       }
        state = (atkbd_state_t *)kbd->kb_data;
-       if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
+       if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
+               lwkt_reltoken(&tty_token);
                return TRUE;
-       return kbdc_data_ready(state->kbdc);
+       }
+       ret = kbdc_data_ready(state->kbdc);
+       lwkt_reltoken(&tty_token);
+       return ret;
 }
 
 /* some useful control functions */
@@ -793,6 +897,7 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
        int i;
 
        crit_enter();
+       lwkt_gettoken(&tty_token);
 
        switch (cmd) {
 
@@ -816,6 +921,7 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                        }
                        break;
                default:
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return EINVAL;
                }
@@ -827,6 +933,7 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
        case KDSETLED:          /* set keyboard LED */
                /* NOTE: lock key state in ks_state won't be changed */
                if (*(int *)arg & ~LOCK_MASK) {
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return EINVAL;
                }
@@ -843,6 +950,7 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                        error = write_kbd(state->kbdc, KBDC_SET_LEDS,
                                          ledmap[i & LED_MASK]);
                        if (error) {
+                               lwkt_reltoken(&tty_token);
                                crit_exit();
                                return error;
                        }
@@ -855,36 +963,44 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                break;
        case KDSKBSTATE:        /* set lock key state */
                if (*(int *)arg & ~LOCK_MASK) {
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return EINVAL;
                }
                state->ks_state &= ~LOCK_MASK;
                state->ks_state |= *(int *)arg;
+               lwkt_reltoken(&tty_token);
                crit_exit();
                /* set LEDs and quit */
                return atkbd_ioctl(kbd, KDSETLED, arg);
 
        case KDSETREPEAT:       /* set keyboard repeat rate (new interface) */
                crit_exit();
-               if (!KBD_HAS_DEVICE(kbd))
+               if (!KBD_HAS_DEVICE(kbd)) {
+                       lwkt_reltoken(&tty_token);
                        return 0;
+               }
                i = typematic(((int *)arg)[0], ((int *)arg)[1]);
                error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, i);
                if (error == 0) {
                        kbd->kb_delay1 = typematic_delay(i);
                        kbd->kb_delay2 = typematic_rate(i);
                }
+               lwkt_reltoken(&tty_token);
                return error;
 
        case KDSETRAD:          /* set keyboard repeat rate (old interface) */
                crit_exit();
-               if (!KBD_HAS_DEVICE(kbd))
+               if (!KBD_HAS_DEVICE(kbd)) {
+                       lwkt_reltoken(&tty_token);
                        return 0;
+               }
                error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, *(int *)arg);
                if (error == 0) {
                        kbd->kb_delay1 = typematic_delay(*(int *)arg);
                        kbd->kb_delay2 = typematic_rate(*(int *)arg);
                }
+               lwkt_reltoken(&tty_token);
                return error;
 
        case PIO_KEYMAP:        /* set keyboard translation table */
@@ -893,10 +1009,12 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                state->ks_accents = 0;
                /* FALL THROUGH */
        default:
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return genkbd_commonioctl(kbd, cmd, arg);
        }
 
+       lwkt_reltoken(&tty_token);
        crit_exit();
        return 0;
 }
@@ -933,7 +1051,10 @@ atkbd_get_state(keyboard_t *kbd, void *buf, size_t len)
                return sizeof(atkbd_state_t);
        if (len < sizeof(atkbd_state_t))
                return -1;
+
+       lwkt_gettoken(&tty_token);
        bcopy(kbd->kb_data, buf, sizeof(atkbd_state_t));
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -946,7 +1067,9 @@ atkbd_set_state(keyboard_t *kbd, void *buf, size_t len)
        if (((atkbd_state_t *)kbd->kb_data)->kbdc
                != ((atkbd_state_t *)buf)->kbdc)
                return ENOMEM;
+       lwkt_gettoken(&tty_token);
        bcopy(buf, kbd->kb_data, sizeof(atkbd_state_t));
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -955,6 +1078,7 @@ atkbd_poll(keyboard_t *kbd, int on)
 {
        atkbd_state_t *state;
 
+       lwkt_gettoken(&tty_token);
        state = (atkbd_state_t *)kbd->kb_data;
        crit_enter();
        if (on)
@@ -962,6 +1086,7 @@ atkbd_poll(keyboard_t *kbd, int on)
        else
                --state->ks_polling;
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
index 111fcf8..fdfec50 100644 (file)
 
 #include <bus/isa/isareg.h>
 
+#if 0
+#define lwkt_gettoken(x)
+#define lwkt_reltoken(x)
+#endif
+
 /* constants */
 
 #define MAXKBDC                MAX(NATKBDC, 1)         /* XXX */
index b7cee66..310b16a 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
  * All rights reserved.
  *
@@ -33,6 +35,8 @@
  * interrupts are not protected by spltty(), we must use a critical section
  * to protect against corruption.
  * XXX: this keyboard driver doesn't use clist functions anymore!
+ *
+ * MPSAFE NOTE: all keyboards could easily be put under a different global token.
  */
 
 #include "opt_kbd.h"
 
 #include "kbdreg.h"
 
+#if 0
+#define lwkt_gettoken(x)
+#define lwkt_reltoken(x)
+#endif
+
 #define KBD_INDEX(dev) minor(dev)
 
 #define KB_QSIZE       512
@@ -98,6 +107,7 @@ kbd_realloc_array(void)
        keyboard_switch_t **new_kbdsw;
        int newsize;
 
+       lwkt_gettoken(&tty_token);
        newsize = ((keyboards + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
        new_kbd = kmalloc(sizeof(*new_kbd) * newsize, M_DEVBUF,
                                M_WAITOK | M_ZERO);
@@ -118,6 +128,7 @@ kbd_realloc_array(void)
        if (bootverbose)
                kprintf("kbd: new array size %d\n", keyboards);
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -137,6 +148,7 @@ kbd_realloc_array(void)
 void
 kbd_reinit_struct(keyboard_t *kbd, int config, int pref)
 {
+       lwkt_gettoken(&tty_token);
        kbd->kb_flags |= KB_NO_DEVICE;  /* device has not been found */
        kbd->kb_config = config & ~KB_CONF_PROBE_ONLY;
        kbd->kb_led = 0;                /* unknown */
@@ -150,6 +162,7 @@ kbd_reinit_struct(keyboard_t *kbd, int config, int pref)
        kbd->kb_count = 0;
        kbd->kb_pref = pref;
        bzero(kbd->kb_lastact, sizeof(kbd->kb_lastact));
+       lwkt_reltoken(&tty_token);
 }
 
 /* initialize the keyboard_t structure */
@@ -157,6 +170,7 @@ void
 kbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config,
                int pref, int port, int port_size)
 {
+       lwkt_gettoken(&tty_token);
        kbd->kb_flags = 0;
        kbd->kb_name = name;
        kbd->kb_type = type;
@@ -164,33 +178,42 @@ kbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config,
        kbd->kb_io_base = port;
        kbd->kb_io_size = port_size;
        kbd_reinit_struct(kbd, config, pref);
+       lwkt_reltoken(&tty_token);
 }
 
 void
 kbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap,
             fkeytab_t *fkeymap, int fkeymap_size)
 {
+       lwkt_gettoken(&tty_token);
        kbd->kb_keymap = keymap;
        kbd->kb_accentmap = accmap;
        kbd->kb_fkeytab = fkeymap;
        kbd->kb_fkeytab_size = fkeymap_size;
+       lwkt_reltoken(&tty_token);
 }
 
 /* declare a new keyboard driver */
 int
 kbd_add_driver(keyboard_driver_t *driver)
 {
-       if (SLIST_NEXT(driver, link))
+       lwkt_gettoken(&tty_token);
+       if (SLIST_NEXT(driver, link)) {
+               lwkt_reltoken(&tty_token);
                return EINVAL;
+       }
        SLIST_INSERT_HEAD(&keyboard_drivers, driver, link);
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
 int
 kbd_delete_driver(keyboard_driver_t *driver)
 {
+       lwkt_gettoken(&tty_token);
        SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link);
        SLIST_NEXT(driver, link) = NULL;
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -204,6 +227,7 @@ kbd_register(keyboard_t *kbd)
        keyboard_info_t ki;
        int index;
 
+       lwkt_gettoken(&tty_token);
        mux = kbd_get_keyboard(kbd_find_keyboard("kbdmux", -1));
 
        for (index = 0; index < keyboards; ++index) {
@@ -211,8 +235,10 @@ kbd_register(keyboard_t *kbd)
                        break;
        }
        if (index >= keyboards) {
-               if (kbd_realloc_array())
+               if (kbd_realloc_array()) {
+                       lwkt_reltoken(&tty_token);
                        return -1;
+               }
        }
 
        kbd->kb_index = index;
@@ -222,7 +248,7 @@ kbd_register(keyboard_t *kbd)
        kbd->kb_token = NULL;
        kbd->kb_callback.kc_func = NULL;
        kbd->kb_callback.kc_arg = NULL;
-       callout_init(&kbd->kb_atkbd_timeout_ch);
+       callout_init_mp(&kbd->kb_atkbd_timeout_ch);
 
        SLIST_FOREACH(p, &keyboard_drivers, link) {
                if (strcmp(p->name, kbd->kb_name) == 0) {
@@ -236,6 +262,7 @@ kbd_register(keyboard_t *kbd)
                                kbd_ioctl(mux, KBADDKBD, (caddr_t) &ki);
                        }
 
+                       lwkt_reltoken(&tty_token);
                        return index;
                }
        }
@@ -252,10 +279,12 @@ kbd_register(keyboard_t *kbd)
                                kbd_ioctl(mux, KBADDKBD, (caddr_t) &ki);
                        }
 
+                       lwkt_reltoken(&tty_token);
                        return index;
                }
        }
 
+       lwkt_reltoken(&tty_token);
        return -1;
 }
 
@@ -264,10 +293,15 @@ kbd_unregister(keyboard_t *kbd)
 {
        int error;
 
-       if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards))
+       lwkt_gettoken(&tty_token);
+       if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards)) {
+               lwkt_reltoken(&tty_token);
                return ENOENT;
-       if (keyboard[kbd->kb_index] != kbd)
+       }
+       if (keyboard[kbd->kb_index] != kbd) {
+               lwkt_reltoken(&tty_token);
                return ENOENT;
+       }
 
        crit_enter();
        callout_stop(&kbd->kb_atkbd_timeout_ch);
@@ -276,10 +310,12 @@ kbd_unregister(keyboard_t *kbd)
                                                    kbd->kb_callback.kc_arg);
                if (error) {
                        crit_exit();
+                       lwkt_reltoken(&tty_token);
                        return error;
                }
                if (KBD_IS_BUSY(kbd)) {
                        crit_exit();
+                       lwkt_reltoken(&tty_token);
                        return EBUSY;
                }
        }
@@ -288,6 +324,7 @@ kbd_unregister(keyboard_t *kbd)
        kbdsw[kbd->kb_index] = NULL;
 
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -298,16 +335,23 @@ kbd_get_switch(char *driver)
        const keyboard_driver_t **list;
        const keyboard_driver_t *p;
 
+       lwkt_gettoken(&tty_token);
+
        SLIST_FOREACH(p, &keyboard_drivers, link) {
-               if (strcmp(p->name, driver) == 0)
+               if (strcmp(p->name, driver) == 0) {
+                       lwkt_reltoken(&tty_token);
                        return p->kbdsw;
+               }
        }
        SET_FOREACH(list, kbddriver_set) {
                p = *list;
-               if (strcmp(p->name, driver) == 0)
+               if (strcmp(p->name, driver) == 0) {
+                       lwkt_reltoken(&tty_token);
                        return p->kbdsw;
+               }
        }
 
+       lwkt_reltoken(&tty_token);
        return NULL;
 }
 
@@ -331,8 +375,11 @@ kbd_find_keyboard2(char *driver, int unit, int index, int legacy)
        pref = 0;
        pref_index = -1;
 
-       if ((index < 0) || (index >= keyboards))
+       lwkt_gettoken(&tty_token);
+       if ((index < 0) || (index >= keyboards)) {
+               lwkt_reltoken(&tty_token);
                return (-1);
+       }
 
        for (i = index; i < keyboards; ++i) {
                if (keyboard[i] == NULL)
@@ -353,6 +400,7 @@ kbd_find_keyboard2(char *driver, int unit, int index, int legacy)
                                pref_index = i;
                        }
                } else {
+                       lwkt_reltoken(&tty_token);
                        return i;
                }
        }
@@ -360,6 +408,7 @@ kbd_find_keyboard2(char *driver, int unit, int index, int legacy)
        if (!legacy)
                KKASSERT(pref_index == -1);
 
+       lwkt_reltoken(&tty_token);
        return (pref_index);
 }
 
@@ -381,6 +430,8 @@ kbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func,
                return -1;
 
        crit_enter();
+       lwkt_gettoken(&tty_token);
+
        index = kbd_find_keyboard(driver, unit);
        if (index >= 0) {
                if (KBD_IS_BUSY(keyboard[index])) {
@@ -393,6 +444,8 @@ kbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func,
                keyboard[index]->kb_callback.kc_arg = arg;
                kbd_clear_state(keyboard[index]);
        }
+
+       lwkt_reltoken(&tty_token);
        crit_exit();
        return index;
 }
@@ -403,6 +456,8 @@ kbd_release(keyboard_t *kbd, void *id)
        int error;
 
        crit_enter();
+       lwkt_gettoken(&tty_token);
+
        if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
                error = EINVAL;
        } else if (kbd->kb_token != id) {
@@ -415,6 +470,8 @@ kbd_release(keyboard_t *kbd, void *id)
                kbd_clear_state(kbd);
                error = 0;
        }
+
+       lwkt_reltoken(&tty_token);
        crit_exit();
        return error;
 }
@@ -426,6 +483,8 @@ kbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func,
        int error;
 
        crit_enter();
+       lwkt_gettoken(&tty_token);
+
        if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
                error = EINVAL;
        } else if (kbd->kb_token != id) {
@@ -437,6 +496,8 @@ kbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func,
                kbd->kb_callback.kc_arg = arg;
                error = 0;
        }
+
+       lwkt_reltoken(&tty_token);
        crit_exit();
        return error;
 }
@@ -445,13 +506,25 @@ kbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func,
 keyboard_t *
 kbd_get_keyboard(int index)
 {
-       if ((index < 0) || (index >= keyboards))
+       keyboard_t *kbd;
+
+       lwkt_gettoken(&tty_token);
+       if ((index < 0) || (index >= keyboards)) {
+               lwkt_reltoken(&tty_token);
                return NULL;
-       if (keyboard[index] == NULL)
+       }
+       if (keyboard[index] == NULL) {
+               lwkt_reltoken(&tty_token);
                return NULL;
-       if (!KBD_IS_VALID(keyboard[index]))
+       }
+       if (!KBD_IS_VALID(keyboard[index])) {
+               lwkt_reltoken(&tty_token);
                return NULL;
-       return keyboard[index];
+       }
+       kbd = keyboard[index];
+       lwkt_reltoken(&tty_token);
+
+       return kbd;
 }
 
 /*
@@ -466,6 +539,8 @@ kbd_configure(int flags)
        const keyboard_driver_t **list;
        const keyboard_driver_t *p;
 
+       lwkt_gettoken(&tty_token);
+
        SLIST_FOREACH(p, &keyboard_drivers, link) {
                if (p->configure != NULL)
                        (*p->configure)(flags);
@@ -476,6 +551,7 @@ kbd_configure(int flags)
                        (*p->configure)(flags);
        }
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -522,10 +598,15 @@ kbd_attach(keyboard_t *kbd)
 {
        cdev_t dev;
 
-       if (kbd->kb_index >= keyboards)
+       lwkt_gettoken(&tty_token);
+       if (kbd->kb_index >= keyboards) {
+               lwkt_reltoken(&tty_token);
                return EINVAL;
-       if (keyboard[kbd->kb_index] != kbd)
+       }
+       if (keyboard[kbd->kb_index] != kbd) {
+               lwkt_reltoken(&tty_token);
                return EINVAL;
+       }
 
        if (kbd->kb_dev == NULL) {
                kbd->kb_dev = make_dev(&kbd_ops, kbd->kb_index,
@@ -540,6 +621,7 @@ kbd_attach(keyboard_t *kbd)
        bzero(dev->si_drv1, sizeof(struct genkbd_softc));
 
        kprintf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit);
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -548,10 +630,16 @@ kbd_detach(keyboard_t *kbd)
 {
        cdev_t dev;
 
-       if (kbd->kb_index >= keyboards)
+       lwkt_gettoken(&tty_token);
+
+       if (kbd->kb_index >= keyboards) {
+               lwkt_reltoken(&tty_token);
                return EINVAL;
-       if (keyboard[kbd->kb_index] != kbd)
+       }
+       if (keyboard[kbd->kb_index] != kbd) {
+               lwkt_reltoken(&tty_token);
                return EINVAL;
+       }
 
        if ((dev = kbd->kb_dev) != NULL) {
                if (dev->si_drv1) {
@@ -561,6 +649,7 @@ kbd_detach(keyboard_t *kbd)
                kbd->kb_dev = NULL;
        }
        dev_ops_remove_minor(&kbd_ops, kbd->kb_index);
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -575,21 +664,31 @@ genkbd_putc(genkbd_softc_t sc, char c)
 {
        unsigned int p;
 
-       if (sc->gkb_q_length == KB_QSIZE)
+       lwkt_gettoken(&tty_token);
+
+       if (sc->gkb_q_length == KB_QSIZE) {
+               lwkt_reltoken(&tty_token);
                return;
+       }
 
        p = (sc->gkb_q_start + sc->gkb_q_length) % KB_QSIZE;
        sc->gkb_q[p] = c;
        sc->gkb_q_length++;
+
+       lwkt_reltoken(&tty_token);
 }
 
 static size_t
 genkbd_getc(genkbd_softc_t sc, char *buf, size_t len)
 {
 
+       lwkt_gettoken(&tty_token);
+
        /* Determine copy size. */
-       if (sc->gkb_q_length == 0)
+       if (sc->gkb_q_length == 0) {
+               lwkt_reltoken(&tty_token);
                return (0);
+       }
        if (len >= sc->gkb_q_length)
                len = sc->gkb_q_length;
        if (len >= KB_QSIZE - sc->gkb_q_start)
@@ -600,6 +699,7 @@ genkbd_getc(genkbd_softc_t sc, char *buf, size_t len)
        sc->gkb_q_start = (sc->gkb_q_start + len) % KB_QSIZE;
        sc->gkb_q_length -= len;
 
+       lwkt_reltoken(&tty_token);
        return (len);
 }
 
@@ -614,15 +714,18 @@ genkbdopen(struct dev_open_args *ap)
        int i;
 
        crit_enter();
+       lwkt_gettoken(&tty_token);
        sc = dev->si_drv1;
        kbd = kbd_get_keyboard(KBD_INDEX(dev));
        if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return ENXIO;
        }
        i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc,
                         genkbd_event, (void *)sc);
        if (i < 0) {
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return EBUSY;
        }
@@ -635,6 +738,7 @@ genkbdopen(struct dev_open_args *ap)
         */
 
        sc->gkb_q_length = 0;
+       lwkt_reltoken(&tty_token);
        crit_exit();
 
        return 0;
@@ -652,6 +756,7 @@ genkbdclose(struct dev_close_args *ap)
         * kbd == NULL || !KBD_IS_VALID(kbd)
         */
        crit_enter();
+       lwkt_gettoken(&tty_token);
        sc = dev->si_drv1;
        kbd = kbd_get_keyboard(KBD_INDEX(dev));
        if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
@@ -659,6 +764,7 @@ genkbdclose(struct dev_close_args *ap)
        } else {
                kbd_release(kbd, (void *)sc);
        }
+       lwkt_reltoken(&tty_token);
        crit_exit();
        return 0;
 }
@@ -676,14 +782,17 @@ genkbdread(struct dev_read_args *ap)
 
        /* wait for input */
        crit_enter();
+       lwkt_gettoken(&tty_token);
        sc = dev->si_drv1;
        kbd = kbd_get_keyboard(KBD_INDEX(dev));
        if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return ENXIO;
        }
        while (sc->gkb_q_length == 0) {
                if (ap->a_ioflag & IO_NDELAY) { /* O_NONBLOCK? */
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return EWOULDBLOCK;
                }
@@ -691,15 +800,18 @@ genkbdread(struct dev_read_args *ap)
                error = tsleep((caddr_t)sc, PCATCH, "kbdrea", 0);
                kbd = kbd_get_keyboard(KBD_INDEX(dev));
                if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return ENXIO;   /* our keyboard has gone... */
                }
                if (error) {
                        sc->gkb_flags &= ~KB_ASLEEP;
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return error;
                }
        }
+       lwkt_reltoken(&tty_token);
        crit_exit();
 
        /* copy as much input as possible */
@@ -723,9 +835,13 @@ genkbdwrite(struct dev_write_args *ap)
        cdev_t dev = ap->a_head.a_dev;
        keyboard_t *kbd;
 
+       lwkt_gettoken(&tty_token);
        kbd = kbd_get_keyboard(KBD_INDEX(dev));
-       if ((kbd == NULL) || !KBD_IS_VALID(kbd))
+       if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
+               lwkt_reltoken(&tty_token);
                return ENXIO;
+       }
+       lwkt_reltoken(&tty_token);
        return ENODEV;
 }
 
@@ -736,12 +852,17 @@ genkbdioctl(struct dev_ioctl_args *ap)
        keyboard_t *kbd;
        int error;
 
+       lwkt_gettoken(&tty_token);
        kbd = kbd_get_keyboard(KBD_INDEX(dev));
-       if ((kbd == NULL) || !KBD_IS_VALID(kbd))
+       if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
+               lwkt_reltoken(&tty_token);
                return ENXIO;
+       }
        error = kbd_ioctl(kbd, ap->a_cmd, ap->a_data);
        if (error == ENOIOCTL)
                error = ENODEV;
+
+       lwkt_reltoken(&tty_token);
        return error;
 }
 
@@ -796,6 +917,7 @@ genkbdfilter(struct knote *kn, long hint)
        int ready = 0;
 
        crit_enter();
+       lwkt_gettoken(&tty_token);
        sc = dev->si_drv1;
         kbd = kbd_get_keyboard(KBD_INDEX(dev));
        if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
@@ -805,6 +927,7 @@ genkbdfilter(struct knote *kn, long hint)
                if (sc->gkb_q_length > 0)
                         ready = 1;
         }
+       lwkt_reltoken(&tty_token);
        crit_exit();
 
        return (ready);
@@ -819,6 +942,7 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
        int mode;
        int c;
 
+       lwkt_gettoken(&tty_token);
        /* assert(KBD_IS_VALID(kbd)) */
        sc = (genkbd_softc_t)arg;
 
@@ -833,8 +957,10 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
                        wakeup((caddr_t)sc);
                }
                KNOTE(&sc->gkb_rkq.ki_note, 0);
+               lwkt_reltoken(&tty_token);
                return 0;
        default:
+               lwkt_reltoken(&tty_token);
                return EINVAL;
        }
 
@@ -905,6 +1031,7 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
                KNOTE(&sc->gkb_rkq.ki_note, 0);
        }
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -924,6 +1051,7 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
        int i;
 
        crit_enter();
+       lwkt_gettoken(&tty_token);
        switch (cmd) {
 
        case KDGKBINFO:         /* get keyboard information */
@@ -955,6 +1083,7 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap));
                break;
 #else
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return ENODEV;
 #endif
@@ -963,6 +1092,7 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                keyp = (keyarg_t *)arg;
                if (keyp->keynum >= sizeof(kbd->kb_keymap->key)
                                        /sizeof(kbd->kb_keymap->key[0])) {
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return EINVAL;
                }
@@ -974,6 +1104,7 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                keyp = (keyarg_t *)arg;
                if (keyp->keynum >= sizeof(kbd->kb_keymap->key)
                                        /sizeof(kbd->kb_keymap->key[0])) {
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return EINVAL;
                }
@@ -981,6 +1112,7 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                      sizeof(keyp->key));
                break;
 #else
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return ENODEV;
 #endif
@@ -993,6 +1125,7 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
                break;
 #else
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return ENODEV;
 #endif
@@ -1000,6 +1133,7 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
        case GETFKEY:           /* get functionkey string */
                fkeyp = (fkeyarg_t *)arg;
                if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return EINVAL;
                }
@@ -1011,6 +1145,7 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
 #ifndef KBD_DISABLE_KEYMAP_LOAD
                fkeyp = (fkeyarg_t *)arg;
                if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        return EINVAL;
                }
@@ -1019,15 +1154,18 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                      kbd->kb_fkeytab[fkeyp->keynum].len);
                break;
 #else
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return ENODEV;
 #endif
 
        default:
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return ENOIOCTL;
        }
 
+       lwkt_reltoken(&tty_token);
        crit_exit();
        return 0;
 }
@@ -1036,13 +1174,22 @@ genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
 u_char *
 genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len)
 {
+       u_char *ch;
+
        if (kbd == NULL)
                return NULL;
+
+       lwkt_gettoken(&tty_token);
        fkey -= F_FN;
-       if (fkey > kbd->kb_fkeytab_size)
+       if (fkey > kbd->kb_fkeytab_size) {
+               lwkt_reltoken(&tty_token);
                return NULL;
+       }
        *len = kbd->kb_fkeytab[fkey].len;
-       return kbd->kb_fkeytab[fkey].str;
+       ch = kbd->kb_fkeytab[fkey].str;
+
+       lwkt_reltoken(&tty_token);
+       return ch;
 }
 
 /* diagnostic dump */
@@ -1095,12 +1242,14 @@ save_accent_key(keyboard_t *kbd, u_int key, int *accents)
 {
        int i;
 
+       lwkt_gettoken(&tty_token);
        /* make an index into the accent map */
        i = key - F_ACC + 1;
        if ((i > kbd->kb_accentmap->n_accs)
            || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) {
                /* the index is out of range or pointing to an empty entry */
                *accents = 0;
+               lwkt_reltoken(&tty_token);
                return ERRKEY;
        }
 
@@ -1111,11 +1260,13 @@ save_accent_key(keyboard_t *kbd, u_int key, int *accents)
        if (i == *accents) {
                key = kbd->kb_accentmap->acc[i - 1].accchar;
                *accents = 0;
+               lwkt_reltoken(&tty_token);
                return key;
        }
 
        /* remember the index and wait for the next key  */
        *accents = i; 
+       lwkt_reltoken(&tty_token);
        return NOKEY;
 }
 
@@ -1125,6 +1276,7 @@ make_accent_char(keyboard_t *kbd, u_int ch, int *accents)
        struct acc_t *acc;
        int i;
 
+       lwkt_gettoken(&tty_token);
        acc = &kbd->kb_accentmap->acc[*accents - 1];
        *accents = 0;
 
@@ -1132,8 +1284,10 @@ make_accent_char(keyboard_t *kbd, u_int ch, int *accents)
         * If the accent key is followed by the space key,
         * produce the accent char itself.
         */
-       if (ch == ' ')
+       if (ch == ' ') {
+               lwkt_reltoken(&tty_token);
                return acc->accchar;
+       }
 
        /* scan the accent map */
        for (i = 0; i < NUM_ACCENTCHARS; ++i) {
@@ -1142,6 +1296,7 @@ make_accent_char(keyboard_t *kbd, u_int ch, int *accents)
                if (acc->map[i][0] == ch)
                        return acc->map[i][1];
        }
+       lwkt_reltoken(&tty_token);
        /* this char cannot be accented... */
        return ERRKEY;
 }
@@ -1156,6 +1311,7 @@ genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
        int f;
        int i;
 
+       lwkt_gettoken(&tty_token);
        i = keycode;
        f = state & (AGRS | ALKED);
        if ((f == AGRS1) || (f == AGRS2) || (f == ALKED))
@@ -1253,9 +1409,11 @@ genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
                case NOP:
                        /* release events of regular keys are not reported */
                        *shiftstate &= ~SHIFTAON;
+                       lwkt_reltoken(&tty_token);
                        return NOKEY;
                }
                *shiftstate = state & ~SHIFTAON;
+               lwkt_reltoken(&tty_token);
                return (SPCLKEY | RELKEY | action);
        } else {        /* make: key pressed */
                action = key->map[i];
@@ -1340,6 +1498,7 @@ genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
                                break;
                        case NOP:
                                *shiftstate = state;
+                               lwkt_reltoken(&tty_token);
                                return NOKEY;
                        default:
                                /* is this an accent (dead) key? */
@@ -1350,26 +1509,33 @@ genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
                                        switch (action) {
                                        case NOKEY:
                                        case ERRKEY:
+                                               lwkt_reltoken(&tty_token);
                                                return action;
                                        default:
-                                               if (state & METAS)
+                                               if (state & METAS) {
+                                                       lwkt_reltoken(&tty_token);
                                                        return (action | MKEY);
-                                               else
+                                               } else { 
+                                                       lwkt_reltoken(&tty_token);
                                                        return action;
+                                               }
                                        }
                                        /* NOT REACHED */
                                }
                                /* other special keys */
                                if (*accents > 0) {
                                        *accents = 0;
+                                       lwkt_reltoken(&tty_token);
                                        return ERRKEY;
                                }
                                if (action >= F_FN && action <= L_FN)
                                        action |= FKEY;
                                /* XXX: return fkey string for the FKEY? */
+                               lwkt_reltoken(&tty_token);
                                return (SPCLKEY | action);
                        }
                        *shiftstate = state;
+                       lwkt_reltoken(&tty_token);
                        return (SPCLKEY | action);
                } else {
                        /* regular keys */
@@ -1378,13 +1544,17 @@ genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
                        if (*accents > 0) {
                                /* make an accented char */
                                action = make_accent_char(kbd, action, accents);
-                               if (action == ERRKEY)
+                               if (action == ERRKEY) {
+                                       lwkt_reltoken(&tty_token);
                                        return action;
+                               }
                        }
                        if (state & METAS)
                                action |= MKEY;
+                       lwkt_reltoken(&tty_token);
                        return action;
                }
        }
        /* NOT REACHED */
+       lwkt_reltoken(&tty_token);
 }
index 4de39e3..7211802 100644 (file)
@@ -3,6 +3,8 @@
  */
 
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
  * All rights reserved.
  *
@@ -68,34 +70,28 @@ MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
 
 #define        KBDMUX_Q_SIZE   512     /* input queue size */
 
-/*
- * XXX
- * For now rely on Giant mutex to protect our data structures.
- * Just like the rest of keyboard drivers and syscons(4) do.
- * Note that callout is initialized as not MP-safe to make sure
- * Giant is held.
- * XXX: I don't think we are MP-Safing the callout, maybe we
- *      should, using get_mplock() around it? NFI
- */
+#if 0
+#define lwkt_gettoken(x)
+#define lwkt_reltoken(x)
+#endif
 
-#if 0 /* not yet */
-#error "This stuff still needs porting!"
+#if 1
 #define KBDMUX_LOCK_DECL_GLOBAL \
-       struct mtx ks_lock
+       struct lock ks_lock
 #define KBDMUX_LOCK_INIT(s) \
-       mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
+       lockinit(&(s)->ks_lock, "kbdmux", 0, LK_CANRECURSE)
 #define KBDMUX_LOCK_DESTROY(s) \
-       mtx_destroy(&(s)->ks_lock)
+       lockuninit(&(s)->ks_lock)
 #define KBDMUX_LOCK(s) \
-       mtx_lock(&(s)->ks_lock)
+       lockmgr(&(s)->ks_lock, LK_EXCLUSIVE)
 #define KBDMUX_UNLOCK(s) \
-       mtx_unlock(&(s)->ks_lock)
+       lockmgr(&(s)->ks_lock, LK_RELEASE)
 #define KBDMUX_LOCK_ASSERT(s, w) \
-       mtx_assert(&(s)->ks_lock, (w))
+       KKASSERT((lockstatus(&(s)->ks_lock, curthread) == LK_EXCLUSIVE))
 #define KBDMUX_SLEEP(s, f, d, t) \
-       msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
+       lksleep(&(s)->f, &(s)->ks_lock, PCATCH, (d), (t))
 #define KBDMUX_CALLOUT_INIT(s) \
-       callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
+       callout_init_mp(&(s)->ks_timo)
 #define KBDMUX_QUEUE_INTR(s) \
        taskqueue_enqueue(taskqueue_swi, &(s)->ks_task)
 #else
@@ -205,6 +201,7 @@ void
 kbdmux_kbd_intr(void *xkbd, int pending)
 {
        keyboard_t      *kbd = (keyboard_t *) xkbd;
+       lwkt_gettoken(&tty_token);
        kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
 
        kbd_intr(kbd, NULL);
@@ -215,6 +212,7 @@ kbdmux_kbd_intr(void *xkbd, int pending)
        wakeup(&state->ks_task);
 
        KBDMUX_UNLOCK(state);
+       lwkt_reltoken(&tty_token);
 }
 
 /*
@@ -225,13 +223,18 @@ kbdmux_kbd_intr_timo(void *xstate)
 {
        kbdmux_state_t  *state = (kbdmux_state_t *) xstate;
 
+       KBDMUX_LOCK(state);
        KBDMUX_LOCK_ASSERT(state, MA_OWNED);
 
-       if (callout_pending(&state->ks_timo))
+       if (callout_pending(&state->ks_timo)) {
+               KBDMUX_UNLOCK(state);
                return; /* callout was reset */
+       }
 
-       if (!callout_active(&state->ks_timo))
+       if (!callout_active(&state->ks_timo)) {
+               KBDMUX_UNLOCK(state);
                return; /* callout was stopped */
+       }
 
        callout_deactivate(&state->ks_timo);
 
@@ -242,6 +245,7 @@ kbdmux_kbd_intr_timo(void *xstate)
 
        /* re-schedule timeout */
        callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
+       KBDMUX_UNLOCK(state);
 }
 
 /*
@@ -252,6 +256,8 @@ kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
 {
        kbdmux_state_t  *state = (kbdmux_state_t *) arg;
 
+       lwkt_gettoken(&tty_token);
+
        switch (event) {
        case KBDIO_KEYINPUT: {
                int     c;
@@ -310,10 +316,12 @@ kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
                } break;
 
        default:
+               lwkt_reltoken(&tty_token);
                return (EINVAL);
                /* NOT REACHED */
        }
 
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -399,6 +407,8 @@ kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
         fkeytab_t      *fkeymap = NULL;
        int              error, needfree, fkeymap_size, delay[2];
 
+       lwkt_gettoken(&tty_token);
+
        if (*kbdp == NULL) {
                *kbdp = kbd = kmalloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
                state = kmalloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
@@ -419,6 +429,7 @@ kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
                KBDMUX_CALLOUT_INIT(state);
                SLIST_INIT(&state->ks_kbds);
        } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
+               lwkt_reltoken(&tty_token);
                return (0);
        } else {
                kbd = *kbdp;
@@ -475,6 +486,7 @@ kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
                KBDMUX_UNLOCK(state);
        }
 
+       lwkt_reltoken(&tty_token);
        return (0);
 bad:
        if (needfree) {
@@ -492,6 +504,7 @@ bad:
                }
        }
 
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
@@ -504,6 +517,7 @@ kbdmux_term(keyboard_t *kbd)
        kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
        kbdmux_kbd_t    *k;
 
+       lwkt_gettoken(&tty_token);
        KBDMUX_LOCK(state);
 
        /* kill callout */
@@ -526,6 +540,7 @@ kbdmux_term(keyboard_t *kbd)
        KBDMUX_UNLOCK(state);
 
        kbd_unregister(kbd);
+       lwkt_reltoken(&tty_token);
 
        KBDMUX_LOCK_DESTROY(state);
        bzero(state, sizeof(*state));
@@ -547,6 +562,7 @@ kbdmux_intr(keyboard_t *kbd, void *arg)
 {
        int     c;
 
+       lwkt_gettoken(&tty_token);
        if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
                /* let the callback function to process the input */
                (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
@@ -558,6 +574,7 @@ kbdmux_intr(keyboard_t *kbd, void *arg)
                } while (c != NOKEY);
        }
 
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -577,7 +594,9 @@ kbdmux_test_if(keyboard_t *kbd)
 static int
 kbdmux_enable(keyboard_t *kbd)
 {
+       lwkt_gettoken(&tty_token);
        KBD_ACTIVATE(kbd);
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -587,7 +606,9 @@ kbdmux_enable(keyboard_t *kbd)
 static int
 kbdmux_disable(keyboard_t *kbd)
 {
+       lwkt_gettoken(&tty_token);
        KBD_DEACTIVATE(kbd);
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -598,8 +619,9 @@ static int
 kbdmux_read(keyboard_t *kbd, int wait)
 {
        kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
-       int              c;
+       int              c, ret;
 
+       lwkt_gettoken(&tty_token);
        KBDMUX_LOCK(state);
        do {
                c = kbdmux_kbd_getc(state);
@@ -609,7 +631,11 @@ kbdmux_read(keyboard_t *kbd, int wait)
        if (c != -1)
                kbd->kb_count++;
 
-       return (KBD_IS_ACTIVE(kbd)? c : -1);
+       ret = (KBD_IS_ACTIVE(kbd)? c : -1);
+
+       lwkt_reltoken(&tty_token);
+
+       return ret;
 }
 
 /*
@@ -621,13 +647,18 @@ kbdmux_check(keyboard_t *kbd)
        kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
        int              ready;
 
-       if (!KBD_IS_ACTIVE(kbd))
+       lwkt_gettoken(&tty_token);
+
+       if (!KBD_IS_ACTIVE(kbd)) {
+               lwkt_reltoken(&tty_token);
                return (FALSE);
+       }
 
        KBDMUX_LOCK(state);
        ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
        KBDMUX_UNLOCK(state);
 
+       lwkt_reltoken(&tty_token);
        return (ready);
 }
 
@@ -647,6 +678,7 @@ kbdmux_read_char(keyboard_t *kbd, int wait)
        u_int            action;
        int              scancode, keycode;
 
+       lwkt_gettoken(&tty_token);
        KBDMUX_LOCK(state);
 
 next_code:
@@ -658,11 +690,13 @@ next_code:
                if (action > UCHAR_MAX) {
                        KBDMUX_UNLOCK(state);
 
+                       lwkt_reltoken(&tty_token);
                        return (ERRKEY);
                }
 
                KBDMUX_UNLOCK(state);
 
+               lwkt_reltoken(&tty_token);
                return (action);
        }
 
@@ -700,6 +734,7 @@ next_code:
                }
 
                KBDMUX_UNLOCK(state);
+               lwkt_reltoken(&tty_token);
                return (NOKEY);
        }
 
@@ -708,6 +743,7 @@ next_code:
        /* return the byte as is for the K_RAW mode */
        if (state->ks_mode == K_RAW) {
                KBDMUX_UNLOCK(state);
+               lwkt_reltoken(&tty_token);
                return (scancode);
        }
 
@@ -847,6 +883,7 @@ next_code:
        /* return the key code in the K_CODE mode */
        if (state->ks_mode == K_CODE) {
                KBDMUX_UNLOCK(state);
+               lwkt_reltoken(&tty_token);
                return (keycode | (scancode & 0x80));
        }
 
@@ -859,6 +896,7 @@ next_code:
                        state->ks_composed_char += keycode - 0x40;
                        if (state->ks_composed_char > UCHAR_MAX) {
                                KBDMUX_UNLOCK(state);
+                               lwkt_reltoken(&tty_token);
                                return (ERRKEY);
                        }
                        goto next_code;
@@ -867,6 +905,7 @@ next_code:
                        state->ks_composed_char += keycode - 0x47;
                        if (state->ks_composed_char > UCHAR_MAX) {
                                KBDMUX_UNLOCK(state);
+                               lwkt_reltoken(&tty_token);
                                return (ERRKEY);
                        }
                        goto next_code;
@@ -875,6 +914,7 @@ next_code:
                        state->ks_composed_char += keycode - 0x4E;
                        if (state->ks_composed_char > UCHAR_MAX) {
                                KBDMUX_UNLOCK(state);
+                               lwkt_reltoken(&tty_token);
                                return (ERRKEY);
                        }
                        goto next_code;
@@ -882,6 +922,7 @@ next_code:
                        state->ks_composed_char *= 10;
                        if (state->ks_composed_char > UCHAR_MAX) {
                                KBDMUX_UNLOCK(state);
+                               lwkt_reltoken(&tty_token);
                                return (ERRKEY);
                        }
                        goto next_code;
@@ -901,6 +942,7 @@ next_code:
                                state->ks_flags &= ~COMPOSE;
                                state->ks_composed_char = 0;
                                KBDMUX_UNLOCK(state);
+                               lwkt_reltoken(&tty_token);
                                return (ERRKEY);
                        }
                        break;
@@ -915,6 +957,7 @@ next_code:
 
        KBDMUX_UNLOCK(state);
 
+       lwkt_reltoken(&tty_token);
        return (action);
 }
 
@@ -927,8 +970,11 @@ kbdmux_check_char(keyboard_t *kbd)
        kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
        int              ready;
 
-       if (!KBD_IS_ACTIVE(kbd))
+       lwkt_gettoken(&tty_token);
+       if (!KBD_IS_ACTIVE(kbd)) {
+               lwkt_reltoken(&tty_token);
                return (FALSE);
+       }
 
        KBDMUX_LOCK(state);
 
@@ -939,6 +985,7 @@ kbdmux_check_char(keyboard_t *kbd)
 
        KBDMUX_UNLOCK(state);
 
+       lwkt_reltoken(&tty_token);
        return (ready);
 }
 
@@ -959,21 +1006,27 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                272, 304, 336, 368, 400, 440, 472, 504
        };
 
+       lwkt_gettoken(&tty_token);
+
        kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
        kbdmux_kbd_t    *k;
        keyboard_info_t *ki;
        int              error = 0, mode;
 
-       if (state == NULL)
+       if (state == NULL) {
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
+       }
 
        switch (cmd) {
        case KBADDKBD: /* add keyboard to the mux */
                ki = (keyboard_info_t *) arg;
 
                if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
-                   strcmp(ki->kb_name, "*") == 0)
+                   strcmp(ki->kb_name, "*") == 0) {
+                       lwkt_reltoken(&tty_token);
                        return (EINVAL); /* bad input */
+               }
 
                KBDMUX_LOCK(state);
 
@@ -985,6 +1038,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                if (k != NULL) {
                        KBDMUX_UNLOCK(state);
 
+                       lwkt_reltoken(&tty_token);
                        return (0); /* keyboard already in the mux */
                }
 
@@ -992,6 +1046,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                if (k == NULL) {
                        KBDMUX_UNLOCK(state);
 
+                       lwkt_reltoken(&tty_token);
                        return (ENOMEM); /* out of memory */
                }
 
@@ -1005,6 +1060,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                        KBDMUX_UNLOCK(state);
                        kfree(k, M_KBDMUX);
 
+                       lwkt_reltoken(&tty_token);
                        return (EINVAL); /* bad keyboard */
                }
 
@@ -1028,6 +1084,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
 
                        kfree(k, M_KBDMUX);
 
+                       lwkt_reltoken(&tty_token);
                        return (error); /* could not set mode */
                }
 
@@ -1040,8 +1097,10 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                ki = (keyboard_info_t *) arg;
 
                if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
-                   strcmp(ki->kb_name, "*") == 0)
+                   strcmp(ki->kb_name, "*") == 0) {
+                       lwkt_reltoken(&tty_token);
                        return (EINVAL); /* bad input */
+               }
 
                KBDMUX_LOCK(state);
 
@@ -1112,6 +1171,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                if (*(int *)arg & ~LOCK_MASK) {
                        KBDMUX_UNLOCK(state);
 
+                       lwkt_reltoken(&tty_token);
                        return (EINVAL);
                }
 
@@ -1136,6 +1196,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                if (*(int *)arg & ~LOCK_MASK) {
                        KBDMUX_UNLOCK(state);
 
+                       lwkt_reltoken(&tty_token);
                        return (EINVAL);
                }
 
@@ -1148,6 +1209,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
 
                KBDMUX_UNLOCK(state);
 
+               lwkt_reltoken(&tty_token);
                return (kbdmux_ioctl(kbd, KDSETLED, arg));
                /* NOT REACHED */
 
@@ -1175,6 +1237,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                if (mode & ~0x7f) {
                        KBDMUX_UNLOCK(state);
 
+                       lwkt_reltoken(&tty_token);
                        return (EINVAL);
                }
 
@@ -1206,6 +1269,7 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
                break;
        }
 
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
@@ -1283,6 +1347,7 @@ kbdmux_poll(keyboard_t *kbd, int on)
        kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
        kbdmux_kbd_t    *k;
 
+       lwkt_gettoken(&tty_token);
        KBDMUX_LOCK(state);
 
        if (on)
@@ -1296,6 +1361,7 @@ kbdmux_poll(keyboard_t *kbd, int on)
 
        KBDMUX_UNLOCK(state);
 
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -1314,6 +1380,8 @@ kbdmux_modevent(module_t mod, int type, void *data)
        keyboard_t              *kbd;
        int                      error;
 
+       lwkt_gettoken(&tty_token);
+
        switch (type) {
        case MOD_LOAD:
                if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
@@ -1373,6 +1441,7 @@ kbdmux_modevent(module_t mod, int type, void *data)
                break;
        }
 
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
index 075c96b..42ba14d 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * (MPSAFE)
+ *
  * Copyright (c) 1982, 1986, 1989, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
  * $DragonFly: src/sys/dev/misc/nmdm/nmdm.c,v 1.16 2008/01/05 14:02:37 swildner Exp $
  */
 
+/*
+ * MPSAFE NOTE: This file acquires the tty_token mainly for linesw access and
+ *             tp (struct tty) access.
+ */
+
 /*
  * Pseudo-nulmodem Driver
  */
@@ -115,6 +122,8 @@ do {        \
 
 /*
  * This function creates and initializes a pair of ttys.
+ *
+ * NOTE: Must be called with tty_token held
  */
 static void
 nmdminit(int n)
@@ -129,6 +138,8 @@ nmdminit(int n)
        if (n & ~0x7f)
                return;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
+
        pt = kmalloc(sizeof(*pt), M_NLMDM, M_WAITOK | M_ZERO);
        pt->part1.dev = dev1 = make_dev(&nmdm_ops, n << 1,
                                        0, 0, 0666, "nmdm%dA", n);
@@ -187,6 +198,7 @@ nmdmopen(struct dev_open_args *ap)
        if (!dev->si_drv1)
                return(ENXIO);  
 
+       lwkt_gettoken(&tty_token);
        pti = dev->si_drv1;
        if (is_b) 
                tp = &pti->part2.nm_tty;
@@ -204,8 +216,10 @@ nmdmopen(struct dev_open_args *ap)
                tp->t_cflag = TTYDEF_CFLAG;
                tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
        } else if (tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
+               lwkt_reltoken(&tty_token);
                return (EBUSY);
        } else if (pti->pt_prison != ap->a_cred->cr_prison) {
+               lwkt_reltoken(&tty_token);
                return (EBUSY);
        }
 
@@ -232,8 +246,10 @@ nmdmopen(struct dev_open_args *ap)
                if (flag & FNONBLOCK)
                        break;
                error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "nmdopn", 0);
-               if (error)
+               if (error) {
+                       lwkt_reltoken(&tty_token);
                        return (error);
+               }
        }
 #endif
 
@@ -250,6 +266,7 @@ nmdmopen(struct dev_open_args *ap)
        nmdm_crossover(pti, ourpart, otherpart);
        if (error == 0)
                wakeup_other(tp, FREAD|FWRITE); /* XXX */
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
@@ -261,6 +278,7 @@ nmdmclose(struct dev_close_args *ap)
        int err;
        struct softpart *ourpart, *otherpart;
 
+       lwkt_gettoken(&tty_token);
        /*
         * let the other end know that the game is up
         */
@@ -288,6 +306,7 @@ nmdmclose(struct dev_close_args *ap)
        nmdm_crossover(dev->si_drv1, ourpart, otherpart);
        nmdmstop(tp, FREAD|FWRITE);
        (void) ttyclose(tp);
+       lwkt_reltoken(&tty_token);
        return (err);
 }
 
@@ -299,6 +318,7 @@ nmdmread(struct dev_read_args *ap)
        struct tty *tp, *tp2;
        struct softpart *ourpart, *otherpart;
 
+       lwkt_gettoken(&tty_token);
        tp = dev->si_tty;
        GETPARTS(tp, ourpart, otherpart);
        tp2 = &otherpart->nm_tty;
@@ -309,6 +329,7 @@ nmdmread(struct dev_read_args *ap)
                wakeup_other(tp, FWRITE);
        } else {
                if (flag & IO_NDELAY) {
+                       lwkt_reltoken(&tty_token);
                        return (EWOULDBLOCK);
                }
                error = tsleep(TSA_PTC_READ(tp), PCATCH, "nmdout", 0);
@@ -318,6 +339,7 @@ nmdmread(struct dev_read_args *ap)
        if ((error = (*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag)) == 0)
                wakeup_other(tp, FWRITE);
 #endif
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
@@ -339,6 +361,7 @@ nmdmwrite(struct dev_write_args *ap)
        struct tty *tp1, *tp;
        struct softpart *ourpart, *otherpart;
 
+       lwkt_gettoken(&tty_token);
        tp1 = dev->si_tty;
        /*
         * Get the other tty struct.
@@ -348,8 +371,10 @@ nmdmwrite(struct dev_write_args *ap)
        tp = &otherpart->nm_tty;
 
 again:
-       if ((tp->t_state & TS_ISOPEN) == 0) 
+       if ((tp->t_state & TS_ISOPEN) == 0) {
+               lwkt_reltoken(&tty_token);
                return (EIO);
+       }
        while (uio->uio_resid > 0 || cc > 0) {
                /*
                 * Fill up the buffer if it's empty
@@ -358,12 +383,15 @@ again:
                        cc = szmin(uio->uio_resid, BUFSIZ);
                        cp = locbuf;
                        error = uiomove((caddr_t)cp, cc, uio);
-                       if (error)
+                       if (error) {
+                               lwkt_reltoken(&tty_token);
                                return (error);
+                       }
                        /* check again for safety */
                        if ((tp->t_state & TS_ISOPEN) == 0) {
                                /* adjust for data copied in but not written */
                                uio->uio_resid += cc;
+                               lwkt_reltoken(&tty_token);
                                return (EIO);
                        }
                }
@@ -382,6 +410,7 @@ again:
                                         * not written.
                                         */
                                        uio->uio_resid += cc;
+                                       lwkt_reltoken(&tty_token);
                                        return (EIO);
                                }
                                if (ap->a_ioflag & IO_NDELAY) {
@@ -391,8 +420,11 @@ again:
                                         * not written.
                                         */
                                        uio->uio_resid += cc;
-                                       if (cnt == 0)
+                                       if (cnt == 0) {
+                                               lwkt_reltoken(&tty_token);
                                                return (EWOULDBLOCK);
+                                       }
+                                       lwkt_reltoken(&tty_token);
                                        return (0);
                                }
                                error = tsleep(TSA_PTC_WRITE(tp),
@@ -405,6 +437,7 @@ again:
                                         * not written
                                         */
                                        uio->uio_resid += cc;
+                                       lwkt_reltoken(&tty_token);
                                        return (error);
                                }
                                goto again;
@@ -415,6 +448,7 @@ again:
                }
                cc = 0;
        }
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -427,10 +461,14 @@ nmdmstart(struct tty *tp)
 {
        struct nm_softc *pti = tp->t_dev->si_drv1;
 
-       if (tp->t_state & TS_TTSTOP)
+       lwkt_gettoken(&tty_token);
+       if (tp->t_state & TS_TTSTOP) {
+               lwkt_reltoken(&tty_token);
                return;
+       }
        pti->pt_flags &= ~PF_STOPPED;
        wakeup_other(tp, FREAD);
+       lwkt_reltoken(&tty_token);
 }
 
 /* Wakes up the OTHER tty;*/
@@ -439,6 +477,7 @@ wakeup_other(struct tty *tp, int flag)
 {
        struct softpart *ourpart, *otherpart;
 
+       lwkt_gettoken(&tty_token);
        GETPARTS(tp, ourpart, otherpart);
        if (flag & FREAD) {
                wakeup(TSA_PTC_READ((&otherpart->nm_tty)));
@@ -448,6 +487,7 @@ wakeup_other(struct tty *tp, int flag)
                wakeup(TSA_PTC_WRITE((&otherpart->nm_tty)));
                KNOTE(&otherpart->nm_tty.t_wkq.ki_note, 0);
        }
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -456,6 +496,7 @@ nmdmstop(struct tty *tp, int flush)
        struct nm_softc *pti = tp->t_dev->si_drv1;
        int flag;
 
+       lwkt_gettoken(&tty_token);
        /* note: FLUSHREAD and FLUSHWRITE already ok */
        if (flush == 0) {
                flush = TIOCPKT_STOP;
@@ -469,6 +510,7 @@ nmdmstop(struct tty *tp, int flush)
        if (flush & FWRITE)
                flag |= FREAD;
        wakeup_other(tp, flag);
+       lwkt_reltoken(&tty_token);
 }
 
 /*ARGSUSED*/
@@ -483,6 +525,7 @@ nmdmioctl(struct dev_ioctl_args *ap)
        struct softpart *ourpart, *otherpart;
 
        crit_enter();
+       lwkt_gettoken(&tty_token);
        GETPARTS(tp, ourpart, otherpart);
        tp2 = &otherpart->nm_tty;
 
@@ -525,6 +568,7 @@ nmdmioctl(struct dev_ioctl_args *ap)
                case TIOCTIMESTAMP:
                case TIOCDCDTIMESTAMP:
                default:
+                       lwkt_reltoken(&tty_token);
                        crit_exit();
                        error = ENOTTY;
                        return (error);
@@ -532,6 +576,7 @@ nmdmioctl(struct dev_ioctl_args *ap)
                error = 0;
                nmdm_crossover(pti, ourpart, otherpart);
        }
+       lwkt_reltoken(&tty_token);
        crit_exit();
        return (error);
 }
@@ -541,11 +586,13 @@ nmdm_crossover(struct nm_softc *pti,
                struct softpart *ourpart,
                struct softpart *otherpart)
 {
+       lwkt_gettoken(&tty_token);
        otherpart->modemsignals &= ~(TIOCM_CTS|TIOCM_CAR);
        if (ourpart->modemsignals & TIOCM_RTS)
                otherpart->modemsignals |= TIOCM_CTS;
        if (ourpart->modemsignals & TIOCM_DTR)
                otherpart->modemsignals |= TIOCM_CAR;
+       lwkt_reltoken(&tty_token);
 }
 
 
@@ -556,7 +603,9 @@ static void
 nmdm_drvinit(void *unused)
 {
        /* XXX: Gross hack for DEVFS */
+       lwkt_gettoken(&tty_token);
        nmdminit(0);
+       lwkt_reltoken(&tty_token);
 }
 
 SYSINIT(nmdmdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,nmdm_drvinit,NULL)
index 2dd93fa..28e53c9 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * (MPSAFE)
+ *
  * Copyright (c) 1995 Ugen J.S.Antsilevich
  *
  * Redistribution and use in source forms, with and without modification,
@@ -130,11 +132,15 @@ snplclose(struct tty *tp, int flag)
        struct snoop *snp;
        int error;
 
+       lwkt_gettoken(&tty_token);
        snp = tp->t_sc;
        error = snp_down(snp);
-       if (error != 0)
+       if (error != 0) {
+               lwkt_reltoken(&tty_token);
                return (error);
+       }
        error = ttylclose(tp, flag);
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
@@ -147,6 +153,7 @@ snplwrite(struct tty *tp, struct uio *uio, int flag)
        int error, ilen;
        char *ibuf;
 
+       lwkt_gettoken(&tty_token);
        error = 0;
        ibuf = NULL;
        snp = tp->t_sc;
@@ -175,6 +182,7 @@ snplwrite(struct tty *tp, struct uio *uio, int flag)
        }
        if (ibuf != NULL)
                kfree(ibuf, M_SNP);
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
@@ -201,30 +209,41 @@ snpwrite(struct dev_write_args *ap)
        int error, i, len;
        unsigned char c[SNP_INPUT_BUF];
 
+       lwkt_gettoken(&tty_token);
        snp = dev->si_drv1;
        tp = snp->snp_tty;
-       if (tp == NULL)
+       if (tp == NULL) {
+               lwkt_reltoken(&tty_token);
                return (EIO);
+       }
        if ((tp->t_sc == snp) && (tp->t_state & TS_SNOOP) &&
            tp->t_line == snooplinedisc)
                goto tty_input;
 
        kprintf("Snoop: attempt to write to bad tty.\n");
+       lwkt_reltoken(&tty_token);
        return (EIO);
 
 tty_input:
-       if (!(tp->t_state & TS_ISOPEN))
+       if (!(tp->t_state & TS_ISOPEN)) {
+               lwkt_reltoken(&tty_token);
                return (EIO);
+       }
 
        while (uio->uio_resid > 0) {
                len = (int)szmin(uio->uio_resid, SNP_INPUT_BUF);
-               if ((error = uiomove(c, (size_t)len, uio)) != 0)
+               if ((error = uiomove(c, (size_t)len, uio)) != 0) {
+                       lwkt_reltoken(&tty_token);
                        return (error);
+               }
                for (i=0; i < len; i++) {
-                       if (ttyinput(c[i], tp))
+                       if (ttyinput(c[i], tp)) {
+                               lwkt_reltoken(&tty_token);
                                return (EIO);
+                       }
                }
        }
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -239,23 +258,30 @@ snpread(struct dev_read_args *ap)
        caddr_t from;
        char *nbuf;
 
+       lwkt_gettoken(&tty_token);
        snp = dev->si_drv1;
        KASSERT(snp->snp_len + snp->snp_base <= snp->snp_blen,
            ("snoop buffer error"));
 
-       if (snp->snp_tty == NULL)
+       if (snp->snp_tty == NULL) {
+               lwkt_reltoken(&tty_token);
                return (EIO);
+       }
 
        snp->snp_flags &= ~SNOOP_RWAIT;
 
        do {
                if (snp->snp_len == 0) {
-                       if (ap->a_ioflag & IO_NDELAY)
+                       if (ap->a_ioflag & IO_NDELAY) {
+                               lwkt_reltoken(&tty_token);
                                return (EWOULDBLOCK);
+                       }
                        snp->snp_flags |= SNOOP_RWAIT;
                        error = tsleep((caddr_t)snp, PCATCH, "snprd", 0);
-                       if (error != 0)
+                       if (error != 0) {
+                               lwkt_reltoken(&tty_token);
                                return (error);
+                       }
                }
        } while (snp->snp_len == 0);
 
@@ -290,9 +316,13 @@ snpread(struct dev_read_args *ap)
        }
        crit_exit();
 
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 snp_in(struct snoop *snp, char *buf, int n)
 {
@@ -301,6 +331,7 @@ snp_in(struct snoop *snp, char *buf, int n)
        caddr_t from, to;
        char *nbuf;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        KASSERT(n >= 0, ("negative snoop char count"));
 
        if (n == 0)
@@ -376,6 +407,7 @@ snpopen(struct dev_open_args *ap)
        cdev_t dev = ap->a_head.a_dev;
        struct snoop *snp;
 
+       lwkt_gettoken(&tty_token);
        if (dev->si_drv1 == NULL) {
 #if 0
                make_dev(&snp_ops, minor(dev), UID_ROOT, GID_WHEEL,
@@ -384,6 +416,7 @@ snpopen(struct dev_open_args *ap)
                dev->si_drv1 = snp = kmalloc(sizeof(*snp), M_SNP,
                    M_WAITOK | M_ZERO);
        } else {
+               lwkt_reltoken(&tty_token);
                return (EBUSY);
        }
 
@@ -405,15 +438,19 @@ snpopen(struct dev_open_args *ap)
        snp->snp_target = NULL;
 
        LIST_INSERT_HEAD(&snp_sclist, snp, snp_list);
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
-
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 snp_detach(struct snoop *snp)
 {
        struct tty *tp;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        snp->snp_base = 0;
        snp->snp_len = 0;
 
@@ -449,7 +486,9 @@ snpclose(struct dev_close_args *ap)
 {
        cdev_t dev = ap->a_head.a_dev;
        struct snoop *snp;
+       int ret;
 
+       lwkt_gettoken(&tty_token);
        snp = dev->si_drv1;
        snp->snp_blen = 0;
        LIST_REMOVE(snp, snp_list);
@@ -460,13 +499,19 @@ snpclose(struct dev_close_args *ap)
                devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(snp), dev->si_uminor);
                destroy_dev(dev);
        }
-       return (snp_detach(snp));
+       ret = snp_detach(snp);
+       lwkt_reltoken(&tty_token);
+       return ret;
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 snp_down(struct snoop *snp)
 {
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        if (snp->snp_blen != SNOOP_MINLEN) {
                kfree(snp->snp_buf, M_SNP);
                snp->snp_buf = kmalloc(SNOOP_MINLEN, M_SNP, M_WAITOK);
@@ -484,19 +529,28 @@ snpioctl(struct dev_ioctl_args *ap)
        struct snoop *snp;
        struct tty *tp, *tpo;
        cdev_t tdev;
+       int ret;
 
+       lwkt_gettoken(&tty_token);
        snp = dev->si_drv1;
        switch (ap->a_cmd) {
        case SNPSTTY:
                tdev = udev2dev(*((udev_t *)ap->a_data), 0);
-               if (tdev == NULL)
-                       return (snp_down(snp));
+               if (tdev == NULL) {
+                       lwkt_reltoken(&tty_token);
+                       ret = snp_down(snp);
+                       return ret;
+               }
 
                tp = snpdevtotty(tdev);
-               if (!tp)
+               if (!tp) {
+                       lwkt_reltoken(&tty_token);
                        return (EINVAL);
-               if (tp->t_state & TS_SNOOP)
+               }
+               if (tp->t_state & TS_SNOOP) {
+                       lwkt_reltoken(&tty_token);
                        return (EBUSY);
+               }
 
                crit_enter();
 
@@ -555,8 +609,10 @@ snpioctl(struct dev_ioctl_args *ap)
                break;
 
        default:
+               lwkt_reltoken(&tty_token);
                return (ENOTTY);
        }
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -573,6 +629,7 @@ snpkqfilter(struct dev_kqfilter_args *ap)
        struct knote *kn = ap->a_kn;
        struct klist *klist;
 
+       lwkt_gettoken(&tty_token);
        ap->a_result = 0;
 
        switch (kn->kn_filter) {
@@ -586,12 +643,14 @@ snpkqfilter(struct dev_kqfilter_args *ap)
                break;
        default:
                ap->a_result = EOPNOTSUPP;
+               lwkt_reltoken(&tty_token);
                return (0);
        }
 
        klist = &snp->snp_kq.ki_note;
        knote_insert(klist, kn);
 
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -611,6 +670,7 @@ snpfilter_rd(struct knote *kn, long hint)
        struct snoop *snp = (struct snoop *)kn->kn_hook;
        int ready = 0;
 
+       lwkt_gettoken(&tty_token);
        /*
         * If snoop is down, we don't want to poll forever so we return 1.
         * Caller should see if we down via FIONREAD ioctl().  The last should
@@ -619,6 +679,7 @@ snpfilter_rd(struct knote *kn, long hint)
        if (snp->snp_flags & SNOOP_DOWN || snp->snp_len > 0)
                ready = 1;
 
+       lwkt_reltoken(&tty_token);
        return (ready);
 }
 
@@ -633,10 +694,11 @@ static int
 snpclone(struct dev_clone_args *ap)
 {
        int unit;
+       lwkt_gettoken(&tty_token);
        unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(snp), 0);
        ap->a_dev = make_only_dev(&snp_ops, unit, UID_ROOT, GID_WHEEL, 0600,
                                                        "snp%d", unit);
-
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -645,6 +707,7 @@ snp_modevent(module_t mod, int type, void *data)
 {
        int i;
 
+       lwkt_gettoken(&tty_token);
        switch (type) {
        case MOD_LOAD:
                snooplinedisc = ldisc_register(LDISC_LOAD, &snpdisc);
@@ -667,6 +730,7 @@ snp_modevent(module_t mod, int type, void *data)
        default:
                break;
        }
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
index 8d0141f..3718782 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1995-1998 Søren Schmidt
  * All rights reserved.
  *
@@ -35,6 +37,7 @@
 #include <sys/module.h>
 #include <sys/consio.h>
 #include <sys/fbio.h>
+#include <sys/thread.h>
 
 #include <dev/video/fb/fbreg.h>
 #include <dev/video/fb/splashreg.h>
@@ -45,22 +48,33 @@ static int blanked;
 static int
 blank_saver(video_adapter_t *adp, int blank)
 {
-       if (blank == blanked)
+       lwkt_gettoken(&tty_token);
+
+       if (blank == blanked) {
+               lwkt_reltoken(&tty_token);
                return 0;
+       }
 
        (*vidsw[adp->va_index]->blank_display)
                (adp, blank ? V_DISPLAY_OFF : V_DISPLAY_ON);
 
        blanked = blank;
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
 static int
 blank_init(video_adapter_t *adp)
 {
-       if ((*vidsw[adp->va_index]->blank_display)(adp, V_DISPLAY_ON) == 0)
+       lwkt_gettoken(&tty_token);
+
+       if ((*vidsw[adp->va_index]->blank_display)(adp, V_DISPLAY_ON) == 0) {
+               lwkt_reltoken(&tty_token);
                return 0;
+       }
+
+       lwkt_reltoken(&tty_token);
        return ENODEV;
 }
 
index 9b907d0..28ab9b9 100644 (file)
@@ -36,6 +36,7 @@
 #include       <sys/syslog.h>
 #include       <sys/consio.h>
 #include       <sys/fbio.h>
+#include       <sys/thread.h>
 #include       <sys/thread2.h>
 
 #include       <sys/random.h>
index 303c3d9..dbac16a 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1995-1998 Søren Schmidt
  * All rights reserved.
  *
@@ -35,6 +37,7 @@
 #include <sys/module.h>
 #include <sys/consio.h>
 #include <sys/fbio.h>
+#include <sys/thread.h>
 
 #include <dev/video/fb/fbreg.h>
 #include <dev/video/fb/splashreg.h>
@@ -50,6 +53,8 @@ fade_saver(video_adapter_t *adp, int blank)
        u_char pal[256*3];
        int i;
 
+       lwkt_gettoken(&tty_token);
+
        if (blank) {
                blanked = TRUE;
                if (ISPALAVAIL(adp->va_flags)) {
@@ -80,16 +85,21 @@ fade_saver(video_adapter_t *adp, int blank)
                }
                blanked = FALSE;
        }
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
 static int
 fade_init(video_adapter_t *adp)
 {
+       lwkt_gettoken(&tty_token);
        if (!ISPALAVAIL(adp->va_flags)
-           && (*vidsw[adp->va_index]->blank_display)(adp, V_DISPLAY_ON) != 0)
+           && (*vidsw[adp->va_index]->blank_display)(adp, V_DISPLAY_ON) != 0) {
+               lwkt_reltoken(&tty_token);
                return ENODEV;
+       }
        blanked = FALSE;
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
index 7ac3df2..2acf29d 100644 (file)
@@ -42,6 +42,7 @@
 #include <sys/consio.h>
 #include <sys/fbio.h>
 #include <sys/random.h>
+#include <sys/thread.h>
 
 #include <dev/video/fb/fbreg.h>
 #include <dev/video/fb/splashreg.h>
index 6365652..95095ad 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1997 Sandro Sigala, Brescia, Italy.
  * Copyright (c) 1997 Chris Shenton
  * Copyright (c) 1995 S ren Schmidt
@@ -37,6 +39,7 @@
 #include <sys/sysctl.h>
 #include <sys/consio.h>
 #include <sys/fbio.h>
+#include <sys/thread.h>
 
 #include <machine/pc/display.h>
 
@@ -116,12 +119,15 @@ clear_fred(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
 
        if (xlen <= 0)
                return;
+
+       lwkt_gettoken(&tty_token);
        for (y = yoff; y < ylen; y++) {
                sc_vtb_erase(&sc->cur_scp->scr,
                             (ypos + y)*sc->cur_scp->xsize + xpos + xoff,
                             xlen - xoff,
                             sc->scr_map[0x20], (FG_LIGHTGREY | BG_BLACK) << 8);
        }
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -132,6 +138,7 @@ draw_fred(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
        int px;
        int attr;
 
+       lwkt_gettoken(&tty_token);
        for (y = yoff; y < ylen; y++) {
                if (dxdir < 0)
                        px = xoff;
@@ -162,6 +169,7 @@ draw_fred(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
                        }
                }
        }
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -169,9 +177,11 @@ clear_string(sc_softc_t *sc, int xpos, int ypos, int xoff, char *s, int len)
 {
        if (len <= 0)
                return;
+       lwkt_gettoken(&tty_token);
        sc_vtb_erase(&sc->cur_scp->scr,
                     ypos*sc->cur_scp->xsize + xpos + xoff, len - xoff,
                     sc->scr_map[0x20], (FG_LIGHTGREY | BG_BLACK) << 8);
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -179,11 +189,13 @@ draw_string(sc_softc_t *sc, int xpos, int ypos, int xoff, char *s, int len)
 {
        int x;
 
+       lwkt_gettoken(&tty_token);
        for (x = xoff; x < len; x++) {
                sc_vtb_putc(&sc->cur_scp->scr,
                            ypos*sc->cur_scp->xsize + xpos + x,
                            sc->scr_map[(int)s[x]], (FG_LIGHTBLUE | BG_BLACK) << 8);
        }
+       lwkt_reltoken(&tty_token);
 }
 
 static int
@@ -200,14 +212,19 @@ fred_saver(video_adapter_t *adp, int blank)
        scr_stat *scp;
        int min, max;
 
+       lwkt_gettoken(&tty_token);
        sc = sc_find_softc(adp, NULL);
-       if (sc == NULL)
+       if (sc == NULL) {
+               lwkt_reltoken(&tty_token);
                return EAGAIN;
+       }
        scp = sc->cur_scp;
 
        if (blank) {
-               if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
+               if (adp->va_info.vi_flags & V_INFO_GRAPHICS) {
+                       lwkt_reltoken(&tty_token);
                        return EAGAIN;
+               }
                if (blanked == 0) {
                        /* clear the screen and set the border color */
                        sc_vtb_clear(&scp->scr, sc->scr_map[0x20],
@@ -216,8 +233,10 @@ fred_saver(video_adapter_t *adp, int blank)
                        sc_set_border(scp, 0);
                        xlen = ylen = tlen = 0;
                }
-               if (blanked++ < 2)
+               if (blanked++ < 2) {
+                       lwkt_reltoken(&tty_token);
                        return 0;
+               }
                blanked = 1;
 
                clear_fred(sc, dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
@@ -331,6 +350,7 @@ fred_saver(video_adapter_t *adp, int blank)
        } else {
                blanked = 0;
        }
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
index 96b17e2..09e2a29 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1995-1998 Søren Schmidt
  * All rights reserved.
  *
@@ -35,6 +37,7 @@
 #include <sys/module.h>
 #include <sys/consio.h>
 #include <sys/fbio.h>
+#include <sys/thread.h>
 
 #include <dev/video/fb/fbreg.h>
 #include <dev/video/fb/splashreg.h>
@@ -45,22 +48,33 @@ static int blanked;
 static int
 green_saver(video_adapter_t *adp, int blank)
 {
-       if (blank == blanked)
+       lwkt_gettoken(&tty_token);
+
+       if (blank == blanked) {
+               lwkt_reltoken(&tty_token);
                return 0;
+       }
 
        (*vidsw[adp->va_index]->blank_display)
                (adp, blank ? V_DISPLAY_STAND_BY : V_DISPLAY_ON);
 
        blanked = blank;
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
 static int
 green_init(video_adapter_t *adp)
 {
-       if ((*vidsw[adp->va_index]->blank_display)(adp, V_DISPLAY_ON) == 0)
+       lwkt_gettoken(&tty_token);
+
+       if ((*vidsw[adp->va_index]->blank_display)(adp, V_DISPLAY_ON) == 0) {
+               lwkt_reltoken(&tty_token);
                return 0;
+       }
+
+       lwkt_reltoken(&tty_token);
        return ENODEV;
 }
 
index d57808d..bfa452d 100644 (file)
@@ -36,6 +36,7 @@
 #include <sys/syslog.h>
 #include <sys/consio.h>
 #include <sys/fbio.h>
+#include <sys/thread.h>
 #include <sys/thread2.h>
 
 #include <dev/video/fb/fbreg.h>
index c087d07..2ae27e1 100644 (file)
@@ -37,6 +37,7 @@
 #include <sys/consio.h>
 #include <sys/fbio.h>
 #include <sys/random.h>
+#include <sys/thread.h>
 #include <sys/thread2.h>
 
 #include <dev/video/fb/fbreg.h>
index d74293d..26bf40a 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
  * All rights reserved.
  *
@@ -36,6 +38,8 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/thread.h>
+#include <sys/thread2.h>
 
 #include <machine/console.h>
 
 
 #include <bus/isa/isareg.h>
 
+/*
+ * XXX: this still doesn't quite work with tokens (mainly vga_txtcursor*),
+ *     so temporarily disable tokens here.
+ */
+#if 1
+#define lwkt_gettoken(x)
+#define lwkt_reltoken(x)
+#endif
+
 static vr_draw_border_t                vga_txtborder;
 static vr_draw_t               vga_txtdraw;
 static vr_set_cursor_t         vga_txtcursor_shape;
@@ -164,7 +177,9 @@ vga_nop(scr_stat *scp, ...)
 static void
 vga_txtborder(scr_stat *scp, int color)
 {
+       lwkt_gettoken(&tty_token);
        (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -195,6 +210,7 @@ vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
 {
        if (base < 0 || base >= scp->font_size)
                return;
+       lwkt_gettoken(&tty_token);
        /* the caller may set height <= 0 in order to disable the cursor */
 #if 0
        scp->cursor_base = base;
@@ -203,6 +219,7 @@ vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
        (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
                                                        base, height,
                                                        scp->font_size, blink);
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -214,6 +231,7 @@ draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
        scp->cursor_saveunder_char = c;
        scp->cursor_saveunder_attr = a;
 
+       //lwkt_gettoken(&tty_token);
 #ifndef SC_NO_FONT_LOADING
        if (sc->flags & SC_CHAR_CURSOR) {
                unsigned char *font;
@@ -230,8 +248,10 @@ draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
                        font = sc->font_14;
                        h = 14;
                }
-               if (scp->cursor_base >= h)
+               if (scp->cursor_base >= h) {
+                       lwkt_reltoken(&tty_token);
                        return;
+               }
                if (flip)
                        a = (a & 0x8800)
                                | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
@@ -264,6 +284,7 @@ draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
                                | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
                sc_vtb_putc(&scp->scr, at, c, a);
        }
+       //lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -275,6 +296,7 @@ vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
        if (scp->cursor_height <= 0)    /* the text cursor is disabled */
                return;
 
+       //lwkt_gettoken(&tty_token);
        adp = scp->sc->adp;
        if (blink) {
                scp->status |= VR_CURSOR_BLINK;
@@ -310,6 +332,7 @@ vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
                        scp->status &= ~VR_CURSOR_ON;
                }
        }
+       //lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -331,6 +354,8 @@ draw_txtmouse(scr_stat *scp, int x, int y)
        int xoffset, yoffset;
        int i;
 
+       lwkt_gettoken(&tty_token);
+
        /* prepare mousepointer char's bitmaps */
        pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
        bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size,
@@ -401,6 +426,8 @@ draw_txtmouse(scr_stat *scp, int x, int y)
                color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
        sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
     }
+
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -544,6 +571,8 @@ vga_pxlborder_planar(scr_stat *scp, int color)
        int y;
        int i;
 
+       lwkt_gettoken(&tty_token);
+
        (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
 
        outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
@@ -569,6 +598,7 @@ vga_pxlborder_planar(scr_stat *scp, int color)
        }
        outw(GDCIDX, 0x0000);           /* set/reset */
        outw(GDCIDX, 0x0001);           /* set/reset enable */
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -1212,7 +1242,9 @@ vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
 static void
 vga_grborder(scr_stat *scp, int color)
 {
+       lwkt_gettoken(&tty_token);
        (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
+       lwkt_reltoken(&tty_token);
 }
 
 #endif
index edc2782..5027d66 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
  * All rights reserved.
  *
@@ -57,8 +59,12 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
     int new_ysize;
     int error;
 
-    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info))
+    lwkt_gettoken(&tty_token);
+    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) {
+       lwkt_reltoken(&tty_token);
        return ENODEV;
+    }
+    lwkt_reltoken(&tty_token);
 
     /* adjust argument values */
     if (fontsize <= 0)
@@ -172,8 +178,12 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
     video_info_t info;
     int error;
 
-    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info))
+    lwkt_gettoken(&tty_token);
+    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) {
+        lwkt_reltoken(&tty_token);
        return ENODEV;
+    }
+    lwkt_reltoken(&tty_token);
 
     /* stop screen saver, etc */
     crit_enter();
@@ -241,8 +251,11 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
     int new_ysize;
     int error;
 
-    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info))
+    lwkt_gettoken(&tty_token);
+    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) {
+        lwkt_reltoken(&tty_token);
        return ENODEV;          /* this shouldn't happen */
+    }
 
     /* adjust argument values */
     if (fontsize <= 0)
@@ -392,7 +405,7 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
     scr_stat *scp;
     video_adapter_t *adp;
     video_info_t info;
-    int error;
+    int error, ret;
 
        KKASSERT(tp->t_dev);
 
@@ -403,71 +416,104 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
     if (adp == NULL)           /* shouldn't happen??? */
                return ENODEV;
 
+    lwkt_gettoken(&tty_token);
     switch (cmd) {
 
     case CONS_CURRENTADP:      /* get current adapter index */
     case FBIO_ADAPTER:
-       return fb_ioctl(adp, FBIO_ADAPTER, data);
+       ret = fb_ioctl(adp, FBIO_ADAPTER, data);
+       lwkt_reltoken(&tty_token);
+       return ret;
 
     case CONS_CURRENT:         /* get current adapter type */
     case FBIO_ADPTYPE:
-       return fb_ioctl(adp, FBIO_ADPTYPE, data);
+       ret = fb_ioctl(adp, FBIO_ADPTYPE, data);
+       lwkt_reltoken(&tty_token);
+       return ret;
 
     case CONS_ADPINFO:         /* adapter information */
     case FBIO_ADPINFO:
        if (((video_adapter_info_t *)data)->va_index >= 0) {
            adp = vid_get_adapter(((video_adapter_info_t *)data)->va_index);
-           if (adp == NULL)
+           if (adp == NULL) {
+               lwkt_reltoken(&tty_token);
                return ENODEV;
+           }
        }
-       return fb_ioctl(adp, FBIO_ADPINFO, data);
+       ret = fb_ioctl(adp, FBIO_ADPINFO, data);
+       lwkt_reltoken(&tty_token);
+       return ret;
 
     case CONS_GET:             /* get current video mode */
     case FBIO_GETMODE:
        *(int *)data = scp->mode;
+       lwkt_reltoken(&tty_token);
        return 0;
 
 #ifndef SC_NO_MODE_CHANGE
     case CONS_SET:
     case FBIO_SETMODE:         /* set video mode */
-       if (!(adp->va_flags & V_ADP_MODECHANGE))
+       if (!(adp->va_flags & V_ADP_MODECHANGE)) {
+           lwkt_reltoken(&tty_token);
            return ENODEV;
+       }
        info.vi_mode = *(int *)data;
        error = fb_ioctl(adp, FBIO_MODEINFO, &info);
-       if (error)
+       if (error) {
+           lwkt_reltoken(&tty_token);
            return error;
-       if (info.vi_flags & V_INFO_GRAPHICS)
+       }
+       if (info.vi_flags & V_INFO_GRAPHICS) {
+           lwkt_reltoken(&tty_token);
            return sc_set_graphics_mode(scp, tp, *(int *)data);
-       else
+       } else {
+           lwkt_reltoken(&tty_token);
            return sc_set_text_mode(scp, tp, *(int *)data, 0, 0, 0);
+       }
 #endif /* SC_NO_MODE_CHANGE */
 
     case CONS_MODEINFO:                /* get mode information */
     case FBIO_MODEINFO:
-       return fb_ioctl(adp, FBIO_MODEINFO, data);
+       ret = fb_ioctl(adp, FBIO_MODEINFO, data);
+       lwkt_reltoken(&tty_token);
+       return ret;
 
     case CONS_FINDMODE:                /* find a matching video mode */
     case FBIO_FINDMODE:
-       return fb_ioctl(adp, FBIO_FINDMODE, data);
+       ret = fb_ioctl(adp, FBIO_FINDMODE, data);
+       lwkt_reltoken(&tty_token);
+       return ret;
 
     case CONS_SETWINORG:       /* set frame buffer window origin */
     case FBIO_SETWINORG:
-       if (scp != scp->sc->cur_scp)
+       if (scp != scp->sc->cur_scp) {
+           lwkt_reltoken(&tty_token);
            return ENODEV;      /* XXX */
-       return fb_ioctl(adp, FBIO_SETWINORG, data);
+       }
+       ret = fb_ioctl(adp, FBIO_SETWINORG, data);
+       lwkt_reltoken(&tty_token);
+       return ret;
 
     case FBIO_GETWINORG:       /* get frame buffer window origin */
-       if (scp != scp->sc->cur_scp)
+       if (scp != scp->sc->cur_scp) {
+           lwkt_reltoken(&tty_token);
            return ENODEV;      /* XXX */
-       return fb_ioctl(adp, FBIO_GETWINORG, data);
+       }
+       ret = fb_ioctl(adp, FBIO_GETWINORG, data);
+       lwkt_reltoken(&tty_token);
+       return ret;
 
     case FBIO_GETDISPSTART:
     case FBIO_SETDISPSTART:
     case FBIO_GETLINEWIDTH:
     case FBIO_SETLINEWIDTH:
-       if (scp != scp->sc->cur_scp)
+       if (scp != scp->sc->cur_scp) {
+           lwkt_reltoken(&tty_token);
            return ENODEV;      /* XXX */
-       return fb_ioctl(adp, cmd, data);
+       }
+       ret = fb_ioctl(adp, cmd, data);
+       lwkt_reltoken(&tty_token);
+       return ret;
 
     case FBIO_GETPALETTE:
     case FBIO_SETPALETTE:
@@ -482,9 +528,13 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
     case FBIOSCURPOS:
     case FBIOGCURPOS:
     case FBIOGCURMAX:
-       if (scp != scp->sc->cur_scp)
+       if (scp != scp->sc->cur_scp) {
+           lwkt_reltoken(&tty_token);
            return ENODEV;      /* XXX */
-       return fb_ioctl(adp, cmd, data);
+       }
+       ret = fb_ioctl(adp, cmd, data);
+       lwkt_reltoken(&tty_token);
+       return ret;
 
     case KDSETMODE:            /* set current mode of this (virtual) console */
        switch (*(int *)data) {
@@ -493,8 +543,10 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
             * If scp->mode is of graphics modes, we don't know which
             * text mode to switch back to...
             */
-           if (scp->status & GRAPHICS_MODE)
+           if (scp->status & GRAPHICS_MODE) {
+               lwkt_reltoken(&tty_token);
                return EINVAL;
+           }
            /* restore fonts & palette ! */
 #if 0
 #ifndef SC_NO_FONT_LOADING
@@ -527,11 +579,14 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
             * If scp->mode is of graphics modes, we don't know which
             * text/pixel mode to switch back to...
             */
-           if (scp->status & GRAPHICS_MODE)
+           if (scp->status & GRAPHICS_MODE) {
+               lwkt_reltoken(&tty_token);
                return EINVAL;
+           }
            crit_enter();
            if ((error = sc_clean_up(scp))) {
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return error;
            }
            scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN;
@@ -541,18 +596,24 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
                set_mode(scp);
            sc_clear_screen(scp);
            scp->status &= ~UNKNOWN_MODE;
+           lwkt_reltoken(&tty_token);
            return 0;
 
 #ifdef SC_PIXEL_MODE
        case KD_PIXEL:          /* pixel (raster) display */
-           if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
+           if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) {
+               lwkt_reltoken(&tty_token);
                return EINVAL;
-           if (scp->status & GRAPHICS_MODE)
+            }
+           if (scp->status & GRAPHICS_MODE) {
+               lwkt_reltoken(&tty_token);
                return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, 
                                         scp->font_size);
+           }
            crit_enter();
            if ((error = sc_clean_up(scp))) {
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return error;
            }
            scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN);
@@ -565,6 +626,7 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
            }
            sc_clear_screen(scp);
            scp->status &= ~UNKNOWN_MODE;
+           lwkt_reltoken(&tty_token);
            return 0;
 #endif /* SC_PIXEL_MODE */
 
@@ -572,21 +634,27 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
            crit_enter();
            if ((error = sc_clean_up(scp))) {
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return error;
            }
            scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN;
            crit_exit();
+           lwkt_reltoken(&tty_token);
            return 0;
 
        default:
+           lwkt_reltoken(&tty_token);
            return EINVAL;
        }
        /* NOT REACHED */
 
 #ifdef SC_PIXEL_MODE
     case KDRASTER:             /* set pixel (raster) display mode */
-       if (ISUNKNOWNSC(scp) || ISTEXTSC(scp))
+       if (ISUNKNOWNSC(scp) || ISTEXTSC(scp)) {
+           lwkt_reltoken(&tty_token);
            return ENODEV;
+       }
+       lwkt_reltoken(&tty_token);
        return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], 
                                 ((int *)data)[2]);
 #endif /* SC_PIXEL_MODE */
@@ -597,15 +665,18 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
         * as KD_TEXT... 
         */
        *data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT;
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KDSBORDER:            /* set border color of this (virtual) console */
        scp->border = *data;
        if (scp == scp->sc->cur_scp)
            sc_set_border(scp, scp->border);
+       lwkt_reltoken(&tty_token);
        return 0;
     }
 
+    lwkt_reltoken(&tty_token);
     return ENOIOCTL;
 }
 
index 4438ccb..b0682df 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1995-1998 Søren Schmidt
  * All rights reserved.
  *
@@ -37,6 +39,7 @@
 #include <sys/sysctl.h>
 #include <sys/consio.h>
 #include <sys/fbio.h>
+#include <sys/thread.h>
 
 #include <machine/pc/display.h>
 
@@ -61,14 +64,20 @@ snake_saver(video_adapter_t *adp, int blank)
 #define        save    message
 #define        savs    messagep
 
+       lwkt_gettoken(&tty_token);
+
        sc = sc_find_softc(adp, NULL);
-       if (sc == NULL)
+       if (sc == NULL) {
+               lwkt_reltoken(&tty_token);
                return EAGAIN;
+       }
        scp = sc->cur_scp;
 
        if (blank) {
-               if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
+               if (adp->va_info.vi_flags & V_INFO_GRAPHICS) {
+                       lwkt_reltoken(&tty_token);
                        return EAGAIN;
+               }
                if (blanked <= 0) {
                        sc_vtb_clear(&scp->scr, sc->scr_map[0x20],
                                     (FG_LIGHTGREY | BG_BLACK) << 8);
@@ -83,8 +92,10 @@ snake_saver(video_adapter_t *adp, int blank)
                                    (FG_LIGHTGREY | BG_BLACK) << 8);
                        blanked = 1;
                }
-               if (blanked++ < 4)
+               if (blanked++ < 4) {
+                       lwkt_reltoken(&tty_token);
                        return 0;
+               }
                blanked = 1;
                sc_vtb_putc(&scp->scr, savs[messagelen - 1], sc->scr_map[0x20],
                            (FG_LIGHTGREY | BG_BLACK) << 8);
@@ -103,9 +114,11 @@ snake_saver(video_adapter_t *adp, int blank)
                for (f=messagelen-1; f>=0; f--)
                        sc_vtb_putc(&scp->scr, savs[f], sc->scr_map[save[f]],
                                    (FG_LIGHTGREY | BG_BLACK) << 8);
-       } else
+       } else {
                blanked = 0;
+       }
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
index 6037bff..fba5847 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1995-1998 Søren Schmidt
  * All rights reserved.
  *
@@ -35,6 +37,7 @@
 #include <sys/module.h>
 #include <sys/consio.h>
 #include <sys/fbio.h>
+#include <sys/thread.h>
 
 #include <machine/pc/display.h>
 
@@ -61,14 +64,19 @@ star_saver(video_adapter_t *adp, int blank)
                                    FG_WHITE, FG_LIGHTCYAN};
        static u_short  stars[NUM_STARS][2];
 
+       lwkt_gettoken(&tty_token);
        sc = sc_find_softc(adp, NULL);
-       if (sc == NULL)
+       if (sc == NULL) {
+               lwkt_reltoken(&tty_token);
                return EAGAIN;
+       }
        scp = sc->cur_scp;
 
        if (blank) {
-               if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
+               if (adp->va_info.vi_flags & V_INFO_GRAPHICS) {
+                       lwkt_reltoken(&tty_token);
                        return EAGAIN;
+               }
                if (!blanked) {
                        /* clear the screen and set the border color */
                        sc_vtb_clear(&scp->scr, sc->scr_map[0x20],
@@ -94,6 +102,7 @@ star_saver(video_adapter_t *adp, int blank)
        else
                blanked = FALSE;
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
index 1a10cea..dff5331 100644 (file)
 
 #define KEYCODE_BS             0x0e            /* "<-- Backspace" key, XXX */
 
+#if 1
+#undef ASSERT_LWKT_TOKEN_HELD
+#define        ASSERT_LWKT_TOKEN_HELD(x)
+#define        lwkt_gettoken(x)
+#define        lwkt_reltoken(x)
+#endif
+
 MALLOC_DEFINE(M_SYSCONS, "syscons", "Syscons");
 
 typedef struct default_attr {
@@ -319,7 +326,7 @@ sc_attach_unit(int unit, int flags)
 #endif
     int vc;
     cdev_t dev;
-
+    lwkt_gettoken(&tty_token);
     flags &= ~SC_KERNEL_CONSOLE;
 
     if (sc_console_unit == unit) {
@@ -437,6 +444,7 @@ sc_attach_unit(int unit, int flags)
                        UID_ROOT, GID_WHEEL, 0600, "consolectl");
     cctl_dev->si_tty = sc_console_tty = ttymalloc(sc_console_tty);
     cctl_dev->si_drv1 = sc_console;
+    lwkt_reltoken(&tty_token);
     return 0;
 }
 
@@ -487,19 +495,23 @@ int
 scopen(struct dev_open_args *ap)
 {
     cdev_t dev = ap->a_head.a_dev;
-    int unit = scdevtounit(dev);
+    int unit;
     sc_softc_t *sc;
     struct tty *tp;
     scr_stat *scp;
     keyarg_t key;
     int error;
 
+    lwkt_gettoken(&tty_token);
+    unit = scdevtounit(dev);
     DPRINTF(5, ("scopen: dev:%d,%d, unit:%d, vty:%d\n",
                major(dev), minor(dev), unit, SC_VTY(dev)));
 
     sc = sc_get_softc(unit, (sc_console_unit == unit) ? SC_KERNEL_CONSOLE : 0);
-    if (sc == NULL)
+    if (sc == NULL) {
+       lwkt_reltoken(&tty_token);
        return ENXIO;
+    }
 
     tp = dev->si_tty = ttymalloc(dev->si_tty);
     tp->t_oproc = scstart;
@@ -526,8 +538,10 @@ scopen(struct dev_open_args *ap)
        (*linesw[tp->t_line].l_modem)(tp, 1);
     }
     else
-       if (tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0))
+       if (tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
+           lwkt_reltoken(&tty_token);
            return(EBUSY);
+       }
 
     error = (*linesw[tp->t_line].l_open)(dev, tp);
 
@@ -542,6 +556,7 @@ scopen(struct dev_open_args *ap)
        tp->t_winsize.ws_row = scp->ysize;
     }
 
+    lwkt_reltoken(&tty_token);
     return error;
 }
 
@@ -553,6 +568,7 @@ scclose(struct dev_close_args *ap)
     scr_stat *scp;
 
     crit_enter();
+    lwkt_gettoken(&tty_token);
     if (SC_VTY(dev) != SC_CONSOLECTL) {
        scp = SC_STAT(tp->t_dev);
        /* were we in the middle of the VT switching process? */
@@ -592,6 +608,7 @@ scclose(struct dev_close_args *ap)
     }
     (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
     ttyclose(tp);
+    lwkt_reltoken(&tty_token);
     crit_exit();
 
     return(0);
@@ -600,8 +617,13 @@ scclose(struct dev_close_args *ap)
 int
 scread(struct dev_read_args *ap)
 {
+    int ret;
+
+    lwkt_gettoken(&tty_token);
     sc_touch_scrn_saver();
-    return (ttyread(ap));
+    ret = (ttyread(ap));
+    lwkt_reltoken(&tty_token);
+    return ret;
 }
 
 static int
@@ -613,6 +635,7 @@ sckbdevent(keyboard_t *thiskbd, int event, void *arg)
     size_t len;
     u_char *cp;
 
+    lwkt_gettoken(&tty_token);
     /*
      * WARNING: In early boot sc->dev may not be setup yet.
      */
@@ -626,8 +649,10 @@ sckbdevent(keyboard_t *thiskbd, int event, void *arg)
        sc->kbd = NULL;
        sc->keyboard = -1;
        kbd_release(thiskbd, (void *)&sc->keyboard);
+       lwkt_reltoken(&tty_token);
        return 0;
     default:
+        lwkt_reltoken(&tty_token);
        return EINVAL;
     }
 
@@ -672,15 +697,18 @@ sckbdevent(keyboard_t *thiskbd, int event, void *arg)
 
     sc->cur_scp->status |= MOUSE_HIDDEN;
 
+    lwkt_reltoken(&tty_token);
     return 0;
 }
 
 static int
 scparam(struct tty *tp, struct termios *t)
 {
+    lwkt_gettoken(&tty_token);
     tp->t_ispeed = t->c_ispeed;
     tp->t_ospeed = t->c_ospeed;
     tp->t_cflag = t->c_cflag;
+    lwkt_reltoken(&tty_token);
     return 0;
 }
 
@@ -697,22 +725,29 @@ scioctl(struct dev_ioctl_args *ap)
     sc_softc_t *sc;
     scr_stat *scp;
 
+    lwkt_gettoken(&tty_token);
     tp = dev->si_tty;
 
     error = sc_vid_ioctl(tp, cmd, data, flag);
-    if (error != ENOIOCTL)
+    if (error != ENOIOCTL) {
+        lwkt_reltoken(&tty_token);
        return error;
+    }
 
 #ifndef SC_NO_HISTORY
     error = sc_hist_ioctl(tp, cmd, data, flag);
-    if (error != ENOIOCTL)
+    if (error != ENOIOCTL) {
+        lwkt_reltoken(&tty_token);
        return error;
+    }
 #endif
 
 #ifndef SC_NO_SYSMOUSE
     error = sc_mouse_ioctl(tp, cmd, data, flag);
-    if (error != ENOIOCTL)
+    if (error != ENOIOCTL) {
+        lwkt_reltoken(&tty_token);
        return error;
+    }
 #endif
 
     scp = SC_STAT(tp->t_dev);
@@ -722,27 +757,34 @@ scioctl(struct dev_ioctl_args *ap)
 
     if (scp->tsw) {
        error = (*scp->tsw->te_ioctl)(scp, tp, cmd, data, flag);
-       if (error != ENOIOCTL)
+       if (error != ENOIOCTL) {
+           lwkt_reltoken(&tty_token);
            return error;
+       }
     }
 
     switch (cmd) {             /* process console hardware related ioctl's */
 
     case GIO_ATTR:             /* get current attributes */
        /* this ioctl is not processed here, but in the terminal emulator */
+       lwkt_reltoken(&tty_token);
        return ENOTTY;
 
     case GIO_COLOR:            /* is this a color console ? */
        *(int *)data = (sc->adp->va_flags & V_ADP_COLOR) ? 1 : 0;
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case CONS_BLANKTIME:       /* set screen saver timeout (0 = no saver) */
-       if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME)
+       if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME) {
+           lwkt_reltoken(&tty_token);
             return EINVAL;
+       }
        crit_enter();
        scrn_blank_time = *(int *)data;
        run_scrn_saver = (scrn_blank_time != 0);
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case CONS_CURSORTYPE:      /* set cursor type blink/noblink */
@@ -766,6 +808,7 @@ scioctl(struct dev_ioctl_args *ap)
            sc_draw_cursor_image(sc->cur_scp);
        }
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case CONS_BELLTYPE:        /* set bell type sound/visual */
@@ -777,6 +820,7 @@ scioctl(struct dev_ioctl_args *ap)
            sc->flags |= SC_QUIET_BELL;
        else
            sc->flags &= ~SC_QUIET_BELL;
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case CONS_GETINFO:         /* get current (virtual) console info */
@@ -803,13 +847,16 @@ scioctl(struct dev_ioctl_args *ap)
            if (scp == sc->cur_scp)
                save_kbd_state(scp);
            ptr->mk_keylock = scp->status & LOCK_MASK;
+           lwkt_reltoken(&tty_token);
            return 0;
        }
+       lwkt_reltoken(&tty_token);
        return EINVAL;
     }
 
     case CONS_GETVERS:         /* get version number */
        *(int*)data = 0x200;    /* version 2.0 */
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case CONS_IDLE:            /* see if the screen has been idle */
@@ -825,6 +872,7 @@ scioctl(struct dev_ioctl_args *ap)
        *(int *)data = (sc->flags & SC_SCRN_IDLE)
                       && (!ISGRAPHSC(sc->cur_scp)
                           || (sc->cur_scp->status & SAVER_RUNNING));
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case CONS_SAVERMODE:       /* set saver mode */
@@ -838,6 +886,7 @@ scioctl(struct dev_ioctl_args *ap)
 #if NSPLASH > 0
            if ((error = wait_scrn_saver_stop(NULL))) {
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return error;
            }
 #endif /* NSPLASH */
@@ -857,8 +906,10 @@ scioctl(struct dev_ioctl_args *ap)
            crit_exit();
            break;
        default:
+           lwkt_reltoken(&tty_token);
            return EINVAL;
        }
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case CONS_SAVERSTART:      /* immediately start/stop the screen saver */
@@ -871,6 +922,7 @@ scioctl(struct dev_ioctl_args *ap)
        if (run_scrn_saver)
            sc->scrn_time_stamp -= scrn_blank_time;
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case CONS_SCRSHOT:         /* get a screen shot */
@@ -879,15 +931,18 @@ scioctl(struct dev_ioctl_args *ap)
        crit_enter();
        if (ISGRAPHSC(scp)) {
            crit_exit();
+           lwkt_reltoken(&tty_token);
            return EOPNOTSUPP;
        }
        if (scp->xsize != ptr->xsize || scp->ysize != ptr->ysize) {
            crit_exit();
+           lwkt_reltoken(&tty_token);
            return EINVAL;
        }
        copyout ((void*)scp->vtb.vtb_buffer, ptr->buf,
                 ptr->xsize * ptr->ysize * sizeof(uint16_t));
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
     }
 
@@ -898,10 +953,14 @@ scioctl(struct dev_ioctl_args *ap)
        mode = (struct vt_mode *)data;
        DPRINTF(5, ("sc%d: VT_SETMODE ", sc->unit));
        if (scp->smode.mode == VT_PROCESS) {
+           lwkt_gettoken(&proc_token);
            if (scp->proc == pfind(scp->pid) && scp->proc != curproc) {
                DPRINTF(5, ("error EPERM\n"));
+               lwkt_reltoken(&proc_token);
+               lwkt_reltoken(&tty_token);
                return EPERM;
            }
+           lwkt_reltoken(&proc_token);
        }
        crit_enter();
        if (mode->mode == VT_AUTO) {
@@ -925,22 +984,27 @@ scioctl(struct dev_ioctl_args *ap)
                || !ISSIGVALID(mode->frsig)) {
                crit_exit();
                DPRINTF(5, ("error EINVAL\n"));
+               lwkt_reltoken(&tty_token);
                return EINVAL;
            }
            DPRINTF(5, ("VT_PROCESS %d, ", curproc->p_pid));
+           lwkt_gettoken(&proc_token);
            bcopy(data, &scp->smode, sizeof(struct vt_mode));
            scp->proc = curproc;
            scp->pid = scp->proc->p_pid;
+           lwkt_reltoken(&proc_token);
            if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit))
                cons_unavail = TRUE;
        }
        crit_exit();
        DPRINTF(5, ("\n"));
+       lwkt_reltoken(&tty_token);
        return 0;
     }
 
     case VT_GETMODE:           /* get screen switcher mode */
        bcopy(&scp->smode, data, sizeof(struct vt_mode));
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case VT_RELDISP:           /* screen switcher ioctl */
@@ -951,11 +1015,13 @@ scioctl(struct dev_ioctl_args *ap)
         */
        if ((scp != sc->cur_scp) || (scp->smode.mode != VT_PROCESS)) {
            crit_exit();
+           lwkt_reltoken(&tty_token);
            return EINVAL;
        }
        /* ...and this process is controlling it. */
        if (scp->proc != curproc) {
            crit_exit();
+           lwkt_reltoken(&tty_token);
            return EPERM;
        }
        error = EINVAL;
@@ -993,9 +1059,11 @@ scioctl(struct dev_ioctl_args *ap)
            tp = VIRTUAL_TTY(sc, i);
            if (!ISTTYOPEN(tp)) {
                *(int *)data = i + 1;
+               lwkt_reltoken(&tty_token);
                return 0;
            }
        }
+       lwkt_reltoken(&tty_token);
        return EINVAL;
 
     case VT_ACTIVATE:          /* switch to screen *data */
@@ -1003,30 +1071,40 @@ scioctl(struct dev_ioctl_args *ap)
        crit_enter();
        sc_clean_up(sc->cur_scp);
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return sc_switch_scr(sc, i);
 
     case VT_WAITACTIVE:        /* wait for switch to occur */
        i = (*(int *)data == 0) ? scp->index : (*(int *)data - 1);
-       if ((i < sc->first_vty) || (i >= sc->first_vty + sc->vtys))
+       if ((i < sc->first_vty) || (i >= sc->first_vty + sc->vtys)) {
+           lwkt_reltoken(&tty_token);
            return EINVAL;
+       }
        crit_enter();
        error = sc_clean_up(sc->cur_scp);
        crit_exit();
-       if (error)
+       if (error) {
+           lwkt_reltoken(&tty_token);
            return error;
+       }
        scp = SC_STAT(SC_DEV(sc, i));
-       if (scp == scp->sc->cur_scp)
+       if (scp == scp->sc->cur_scp) {
+           lwkt_reltoken(&tty_token);
            return 0;
+       }
        error = tsleep((caddr_t)&scp->smode, PCATCH, "waitvt", 0);
        /* May return ERESTART */
+       lwkt_reltoken(&tty_token);
        return error;
 
     case VT_GETACTIVE:         /* get active vty # */
        *(int *)data = sc->cur_scp->index + 1;
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case VT_GETINDEX:          /* get this vty # */
        *(int *)data = scp->index + 1;
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case VT_LOCKSWITCH:                /* prevent vty switching */
@@ -1034,42 +1112,57 @@ scioctl(struct dev_ioctl_args *ap)
            sc->flags |= SC_SCRN_VTYLOCK;
        else
            sc->flags &= ~SC_SCRN_VTYLOCK;
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KDENABIO:             /* allow io operations */
        error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
-       if (error != 0)
+       if (error != 0) {
+           lwkt_reltoken(&tty_token);
            return error;
-       if (securelevel > 0)
+       }
+       if (securelevel > 0) {
+           lwkt_reltoken(&tty_token);
            return EPERM;
+       }
+       lwkt_gettoken(&proc_token);
 #if defined(__i386__)
        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
+        lwkt_reltoken(&proc_token);
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KDDISABIO:            /* disallow io operations (default) */
+        lwkt_gettoken(&proc_token);
 #if defined(__i386__)
        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
+        lwkt_reltoken(&proc_token);
+        lwkt_reltoken(&tty_token);
        return 0;
 
     case KDSKBSTATE:           /* set keyboard state (locks) */
-       if (*(int *)data & ~LOCK_MASK)
+       if (*(int *)data & ~LOCK_MASK) {
+           lwkt_reltoken(&tty_token);
            return EINVAL;
+       }
        scp->status &= ~LOCK_MASK;
        scp->status |= *(int *)data;
        if (scp == sc->cur_scp)
            update_kbd_state(scp, scp->status, LOCK_MASK);
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KDGKBSTATE:           /* get keyboard state (locks) */
        if (scp == sc->cur_scp)
            save_kbd_state(scp);
        *(int *)data = scp->status & LOCK_MASK;
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KDGETREPEAT:          /* get keyboard repeat & delay rates */
@@ -1077,6 +1170,7 @@ scioctl(struct dev_ioctl_args *ap)
        error = kbd_ioctl(sc->kbd, cmd, data);
        if (error == ENOIOCTL)
            error = ENODEV;
+       lwkt_reltoken(&tty_token);
        return error;
 
     case KDSETRAD:             /* set keyboard repeat & delay rates (old) */
@@ -1085,6 +1179,7 @@ scioctl(struct dev_ioctl_args *ap)
        error = kbd_ioctl(sc->kbd, cmd, data);
        if (error == ENOIOCTL)
            error = ENODEV;
+       lwkt_reltoken(&tty_token);
        return error;
 
     case KDSKBMODE:            /* set keyboard mode */
@@ -1095,20 +1190,24 @@ scioctl(struct dev_ioctl_args *ap)
            scp->kbd_mode = *(int *)data;
            if (scp == sc->cur_scp)
                kbd_ioctl(sc->kbd, cmd, data);
+            lwkt_reltoken(&tty_token);
            return 0;
        default:
+           lwkt_reltoken(&tty_token);
            return EINVAL;
        }
        /* NOT REACHED */
 
     case KDGKBMODE:            /* get keyboard mode */
        *(int *)data = scp->kbd_mode;
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KDGKBINFO:
        error = kbd_ioctl(sc->kbd, cmd, data);
        if (error == ENOIOCTL)
            error = ENODEV;
+       lwkt_reltoken(&tty_token);
        return error;
 
     case KDMKTONE:             /* sound the bell */
@@ -1117,15 +1216,20 @@ scioctl(struct dev_ioctl_args *ap)
                    (((*(int*)data)>>16)&0xffff)*hz/1000);
        else
            sc_bell(scp, scp->bell_pitch, scp->bell_duration);
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KIOCSOUND:            /* make tone (*data) hz */
        if (scp == sc->cur_scp) {
-           if (*(int *)data)
+           if (*(int *)data) {
+               lwkt_reltoken(&tty_token);
                return sc_tone(*(int *)data);
-           else
+           } else {
+               lwkt_reltoken(&tty_token);
                return sc_tone(0);
+           }
        }
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KDGKBTYPE:            /* get keyboard type */
@@ -1134,21 +1238,26 @@ scioctl(struct dev_ioctl_args *ap)
            /* always return something? XXX */
            *(int *)data = 0;
        }
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KDSETLED:             /* set keyboard LED status */
-       if (*(int *)data & ~LED_MASK)   /* FIXME: LOCK_MASK? */
+       if (*(int *)data & ~LED_MASK) { /* FIXME: LOCK_MASK? */
+           lwkt_reltoken(&tty_token);
            return EINVAL;
+       }
        scp->status &= ~LED_MASK;
        scp->status |= *(int *)data;
        if (scp == sc->cur_scp)
            update_kbd_leds(scp, scp->status);
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case KDGETLED:             /* get keyboard LED status */
        if (scp == sc->cur_scp)
            save_kbd_state(scp);
        *(int *)data = scp->status & LED_MASK;
+       lwkt_reltoken(&tty_token);
        return 0;
 
        case KBADDKBD:              /* add/remove keyboard to/from mux */
@@ -1156,6 +1265,7 @@ scioctl(struct dev_ioctl_args *ap)
                error = kbd_ioctl(sc->kbd, cmd, data);
                if (error == ENOIOCTL)
                        error = ENODEV;
+               lwkt_reltoken(&tty_token);
                return error;
 
     case CONS_SETKBD:          /* set the new keyboard */
@@ -1166,6 +1276,7 @@ scioctl(struct dev_ioctl_args *ap)
            newkbd = kbd_get_keyboard(*(int *)data);
            if (newkbd == NULL) {
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return EINVAL;
            }
            error = 0;
@@ -1189,6 +1300,7 @@ scioctl(struct dev_ioctl_args *ap)
                }
            }
            crit_exit();
+           lwkt_reltoken(&tty_token);
            return error;
        }
 
@@ -1204,6 +1316,7 @@ scioctl(struct dev_ioctl_args *ap)
            }
        }
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return error;
 
     case CONS_GETTERM:         /* get the current terminal emulator info */
@@ -1221,11 +1334,13 @@ scioctl(struct dev_ioctl_args *ap)
                strncpy(((term_info_t *)data)->ti_desc, sw->te_desc, 
                        sizeof(((term_info_t *)data)->ti_desc));
                ((term_info_t *)data)->ti_flags = 0;
+               lwkt_reltoken(&tty_token);
                return 0;
            } else {
                ((term_info_t *)data)->ti_name[0] = '\0';
                ((term_info_t *)data)->ti_desc[0] = '\0';
                ((term_info_t *)data)->ti_flags = 0;
+               lwkt_reltoken(&tty_token);
                return EINVAL;
            }
        }
@@ -1235,10 +1350,12 @@ scioctl(struct dev_ioctl_args *ap)
        error = sc_init_emulator(scp, ((term_info_t *)data)->ti_name);
        /* FIXME: what if scp == sc_console! XXX */
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return error;
 
     case GIO_SCRNMAP:          /* get output translation table */
        bcopy(&sc->scr_map, data, sizeof(sc->scr_map));
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case PIO_SCRNMAP:          /* set output translation table */
@@ -1246,6 +1363,7 @@ scioctl(struct dev_ioctl_args *ap)
        for (i=0; i<sizeof(sc->scr_map); i++) {
            sc->scr_rmap[sc->scr_map[i]] = i;
        }
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case GIO_KEYMAP:           /* get keyboard translation table */
@@ -1257,13 +1375,16 @@ scioctl(struct dev_ioctl_args *ap)
        error = kbd_ioctl(sc->kbd, cmd, data);
        if (error == ENOIOCTL)
            error = ENODEV;
+       lwkt_reltoken(&tty_token);
        return error;
 
 #ifndef SC_NO_FONT_LOADING
 
     case PIO_FONT8x8:          /* set 8x8 dot font */
-       if (!ISFONTAVAIL(sc->adp->va_flags))
+       if (!ISFONTAVAIL(sc->adp->va_flags)) {
+           lwkt_reltoken(&tty_token);
            return ENXIO;
+       }
        bcopy(data, sc->font_8, 8*256);
        sc->fonts_loaded |= FONT_8;
        /*
@@ -1273,21 +1394,29 @@ scioctl(struct dev_ioctl_args *ap)
         */
        if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size < 14))
            sc_load_font(sc->cur_scp, 0, 8, sc->font_8, 0, 256);
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case GIO_FONT8x8:          /* get 8x8 dot font */
-       if (!ISFONTAVAIL(sc->adp->va_flags))
+       if (!ISFONTAVAIL(sc->adp->va_flags)) {
+           lwkt_reltoken(&tty_token);
            return ENXIO;
+       }
        if (sc->fonts_loaded & FONT_8) {
            bcopy(sc->font_8, data, 8*256);
+           lwkt_reltoken(&tty_token);
            return 0;
        }
-       else
+       else {
+           lwkt_reltoken(&tty_token);
            return ENXIO;
+       }
 
     case PIO_FONT8x14:         /* set 8x14 dot font */
-       if (!ISFONTAVAIL(sc->adp->va_flags))
+       if (!ISFONTAVAIL(sc->adp->va_flags)) {
+           lwkt_reltoken(&tty_token);
            return ENXIO;
+       }
        bcopy(data, sc->font_14, 14*256);
        sc->fonts_loaded |= FONT_14;
        /*
@@ -1299,21 +1428,29 @@ scioctl(struct dev_ioctl_args *ap)
            && (sc->cur_scp->font_size >= 14)
            && (sc->cur_scp->font_size < 16))
            sc_load_font(sc->cur_scp, 0, 14, sc->font_14, 0, 256);
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case GIO_FONT8x14:         /* get 8x14 dot font */
-       if (!ISFONTAVAIL(sc->adp->va_flags))
+       if (!ISFONTAVAIL(sc->adp->va_flags)) {
+           lwkt_reltoken(&tty_token);
            return ENXIO;
+       }
        if (sc->fonts_loaded & FONT_14) {
            bcopy(sc->font_14, data, 14*256);
+           lwkt_reltoken(&tty_token);
            return 0;
        }
-       else
+       else {
+           lwkt_reltoken(&tty_token);
            return ENXIO;
+        }
 
     case PIO_FONT8x16:         /* set 8x16 dot font */
-       if (!ISFONTAVAIL(sc->adp->va_flags))
+       if (!ISFONTAVAIL(sc->adp->va_flags)) {
+           lwkt_reltoken(&tty_token);
            return ENXIO;
+       }
        bcopy(data, sc->font_16, 16*256);
        sc->fonts_loaded |= FONT_16;
        /*
@@ -1323,17 +1460,23 @@ scioctl(struct dev_ioctl_args *ap)
         */
        if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size >= 16))
            sc_load_font(sc->cur_scp, 0, 16, sc->font_16, 0, 256);
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case GIO_FONT8x16:         /* get 8x16 dot font */
-       if (!ISFONTAVAIL(sc->adp->va_flags))
+       if (!ISFONTAVAIL(sc->adp->va_flags)) {
+           lwkt_reltoken(&tty_token);
            return ENXIO;
+       }
        if (sc->fonts_loaded & FONT_16) {
            bcopy(sc->font_16, data, 16*256);
+           lwkt_reltoken(&tty_token);
            return 0;
        }
-       else
+       else {
+           lwkt_reltoken(&tty_token);
            return ENXIO;
+        }
 
 #endif /* SC_NO_FONT_LOADING */
 
@@ -1342,11 +1485,16 @@ scioctl(struct dev_ioctl_args *ap)
     }
 
     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, ap->a_cred);
-    if (error != ENOIOCTL)
+    if (error != ENOIOCTL) {
+        lwkt_reltoken(&tty_token);
        return(error);
+    }
     error = ttioctl(tp, cmd, data, flag);
-    if (error != ENOIOCTL)
+    if (error != ENOIOCTL) {
+        lwkt_reltoken(&tty_token);
        return(error);
+    }
+    lwkt_reltoken(&tty_token);
     return(ENOTTY);
 }
 
@@ -1358,11 +1506,13 @@ scstart(struct tty *tp)
     u_char buf[PCBURST];
     scr_stat *scp = SC_STAT(tp->t_dev);
 
+    lwkt_gettoken(&tty_token);
     syscons_lock();
     if (scp->status & SLKED ||
        (scp == scp->sc->cur_scp && scp->sc->blink_in_progress))
     {
        syscons_unlock();
+       lwkt_reltoken(&tty_token);
        return;
     }
     if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
@@ -1376,6 +1526,7 @@ scstart(struct tty *tp)
        ttwwakeup(tp);
     }
     syscons_unlock();
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -1384,6 +1535,7 @@ sccnprobe(struct consdev *cp)
     int unit;
     int flags;
 
+    lwkt_gettoken(&tty_token);
     cp->cn_pri = sc_get_cons_priority(&unit, &flags);
 
     /* a video card is always required */
@@ -1393,8 +1545,10 @@ sccnprobe(struct consdev *cp)
     /* syscons will become console even when there is no keyboard */
     sckbdprobe(unit, flags, TRUE);
 
-    if (cp->cn_pri == CN_DEAD)
+    if (cp->cn_pri == CN_DEAD) {
+        lwkt_reltoken(&tty_token);
        return;
+    }
 
     /* initialize required fields */
     cp->cn_probegood = 1;
@@ -1406,10 +1560,12 @@ sccninit(struct consdev *cp)
     int unit;
     int flags;
 
+    lwkt_gettoken(&tty_token);
     sc_get_cons_priority(&unit, &flags);
     scinit(unit, flags | SC_KERNEL_CONSOLE);
     sc_console_unit = unit;
     sc_console = sc_get_softc(unit, SC_KERNEL_CONSOLE)->console_scp;
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -1428,6 +1584,7 @@ sccnterm(struct consdev *cp)
     if (sc_console_unit < 0)
        return;                 /* shouldn't happen */
 
+    lwkt_gettoken(&tty_token);
 #if 0 /* XXX */
     sc_clear_screen(sc_console);
     sccnupdate(sc_console);
@@ -1435,6 +1592,7 @@ sccnterm(struct consdev *cp)
     scterm(sc_console_unit, SC_KERNEL_CONSOLE);
     sc_console_unit = -1;
     sc_console = NULL;
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -1449,6 +1607,7 @@ sccnputc(void *private, int c)
 
     /* assert(sc_console != NULL) */
 
+    lwkt_gettoken(&tty_token);
     syscons_lock();
 #ifndef SC_NO_HISTORY
     if (scp == scp->sc->cur_scp && scp->status & SLKED) {
@@ -1479,6 +1638,7 @@ sccnputc(void *private, int c)
 
     sccnupdate(scp);
     syscons_unlock();
+    lwkt_reltoken(&tty_token);
 }
 
 static int
@@ -1504,6 +1664,7 @@ sccndbctl(void *private, int on)
         * and the screen is updated before switching to 
         * the vty0.
         */
+        lwkt_gettoken(&tty_token);
        scrn_timer(NULL);
        if (!cold
            && sc_console->sc->cur_scp->smode.mode == VT_AUTO
@@ -1511,6 +1672,7 @@ sccndbctl(void *private, int on)
            sc_console->sc->cur_scp->status |= MOUSE_HIDDEN;
            sc_switch_scr(sc_console->sc, sc_console->index);
        }
+       lwkt_reltoken(&tty_token);
     }
     if (on)
        ++debugger;
@@ -1528,6 +1690,7 @@ sccngetch(int flags)
     int cur_mode;
     int c;
 
+    lwkt_gettoken(&tty_token);
     syscons_lock();
     /* assert(sc_console != NULL) */
 
@@ -1540,11 +1703,15 @@ sccngetch(int flags)
     sccnupdate(scp);
     syscons_unlock();
 
-    if (fkeycp < fkey.len)
+    if (fkeycp < fkey.len) {
+        lwkt_reltoken(&tty_token);
        return fkey.str[fkeycp++];
+    }
 
-    if (scp->sc->kbd == NULL)
+    if (scp->sc->kbd == NULL) {
+        lwkt_reltoken(&tty_token);
        return -1;
+    }
 
     /* 
      * Make sure the keyboard is accessible even when the kbd device
@@ -1569,6 +1736,7 @@ sccngetch(int flags)
 
     switch (KEYFLAGS(c)) {
     case 0:    /* normal char */
+        lwkt_reltoken(&tty_token);
        return KEYCHAR(c);
     case FKEY: /* function key */
        p = kbd_get_fkeystr(scp->sc->kbd, KEYCHAR(c), (size_t *)&fkeycp);
@@ -1576,12 +1744,15 @@ sccngetch(int flags)
        if ((p != NULL) && (fkey.len > 0)) {
            bcopy(p, fkey.str, fkey.len);
            fkeycp = 1;
+           lwkt_reltoken(&tty_token);
            return fkey.str[0];
        }
+       lwkt_reltoken(&tty_token);
        return c;       /* XXX */
     case NOKEY:
     case ERRKEY:
     default:
+        lwkt_reltoken(&tty_token);
        return -1;
     }
     /* NOT REACHED */
@@ -1592,12 +1763,16 @@ sccnupdate(scr_stat *scp)
 {
     /* this is a cut-down version of scrn_timer()... */
 
-    if (scp->sc->font_loading_in_progress || scp->sc->videoio_in_progress)
+    lwkt_gettoken(&tty_token);
+    if (scp->sc->font_loading_in_progress || scp->sc->videoio_in_progress) {
+        lwkt_reltoken(&tty_token);
        return;
+    }
 
     if (debugger > 0 || panicstr || shutdown_in_progress) {
        sc_touch_scrn_saver();
     } else if (scp != scp->sc->cur_scp) {
+        lwkt_reltoken(&tty_token);
        return;
     }
 
@@ -1610,8 +1785,10 @@ sccnupdate(scr_stat *scp)
 #endif /* NSPLASH */
 
     if (scp != scp->sc->cur_scp || scp->sc->blink_in_progress
-       || scp->sc->switch_in_progress)
+       || scp->sc->switch_in_progress) {
+       lwkt_reltoken(&tty_token);
        return;
+    }
     /*
      * FIXME: unlike scrn_timer(), we call scrn_update() from here even
      * when write_in_progress is non-zero.  XXX
@@ -1619,6 +1796,7 @@ sccnupdate(scr_stat *scp)
 
     if (!ISGRAPHSC(scp) && !(scp->sc->flags & SC_SCRN_BLANKED))
        scrn_update(scp, TRUE);
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -1630,17 +1808,21 @@ scrn_timer(void *arg)
     scr_stat *scp;
     int again;
 
+    lwkt_gettoken(&tty_token);
     again = (arg != NULL);
-    if (arg != NULL)
+    if (arg != NULL) {
        sc = (sc_softc_t *)arg;
-    else if (sc_console != NULL)
+    } else if (sc_console != NULL) {
        sc = sc_console->sc;
-    else
+    } else {
+        lwkt_reltoken(&tty_token);
        return;
+    }
 
     if (syscons_lock_nonblock() == 0) {
        if (again)
            callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
+       lwkt_reltoken(&tty_token);
        return;
     }
 
@@ -1650,6 +1832,7 @@ scrn_timer(void *arg)
        if (again)
            callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
        syscons_unlock();
+       lwkt_reltoken(&tty_token);
        return;
     }
 
@@ -1695,6 +1878,7 @@ scrn_timer(void *arg)
        if (again)
            callout_reset(&sc->scrn_timer_ch, hz / 10, scrn_timer, sc);
        syscons_unlock();
+       lwkt_reltoken(&tty_token);
        return;
     }
 
@@ -1713,6 +1897,7 @@ scrn_timer(void *arg)
     if (again)
        callout_reset(&sc->scrn_timer_ch, hz / 25, scrn_timer, sc);
     syscons_unlock();
+    lwkt_reltoken(&tty_token);
 }
 
 static int
@@ -1735,6 +1920,7 @@ scrn_update(scr_stat *scp, int show_cursor)
 
     /* assert(scp == scp->sc->cur_scp) */
 
+    lwkt_gettoken(&tty_token);
     ++scp->sc->videoio_in_progress;
 
 #ifndef SC_NO_CUTPASTE
@@ -1806,6 +1992,7 @@ scrn_update(scr_stat *scp, int show_cursor)
         scp->end = 0;
         scp->start = scp->xsize*scp->ysize - 1;
        --scp->sc->videoio_in_progress;
+       lwkt_reltoken(&tty_token);
        return;
     }
 
@@ -1845,6 +2032,7 @@ scrn_update(scr_stat *scp, int show_cursor)
     scp->start = scp->xsize*scp->ysize - 1;
 
     --scp->sc->videoio_in_progress;
+    lwkt_reltoken(&tty_token);
 }
 
 #if NSPLASH > 0
@@ -1854,6 +2042,7 @@ scsplash_callback(int event, void *arg)
     sc_softc_t *sc;
     int error;
 
+    lwkt_gettoken(&tty_token);
     sc = (sc_softc_t *)arg;
 
     switch (event) {
@@ -1866,18 +2055,23 @@ scsplash_callback(int event, void *arg)
                (*current_saver)(sc, TRUE);
            }
        }
+       lwkt_reltoken(&tty_token);
        return 0;
 
     case SPLASH_TERM:
        if (current_saver == scsplash_saver) {
            scsplash_stick(FALSE);
            error = remove_scrn_saver(scsplash_saver);
-           if (error)
+           if (error) {
+               lwkt_reltoken(&tty_token);
                return error;
+            }
        }
+       lwkt_reltoken(&tty_token);
        return 0;
 
     default:
+        lwkt_reltoken(&tty_token);
        return EINVAL;
     }
 }
@@ -1891,6 +2085,7 @@ scsplash_saver(sc_softc_t *sc, int show)
     if (busy)
        return;
     busy = TRUE;
+    lwkt_gettoken(&tty_token);
 
     scp = sc->cur_scp;
     if (show) {
@@ -1917,6 +2112,7 @@ scsplash_saver(sc_softc_t *sc, int show)
            restore_scrn_saver_mode(scp, TRUE);
     }
     busy = FALSE;
+    lwkt_reltoken(&tty_token);
 }
 
 static int
@@ -1931,12 +2127,16 @@ add_scrn_saver(void (*this_saver)(sc_softc_t *, int))
            return error;
     }
 #endif
-    if (current_saver != none_saver)
+    lwkt_gettoken(&tty_token);
+    if (current_saver != none_saver) {
+       lwkt_reltoken(&tty_token);
        return EBUSY;
+    }
 
     run_scrn_saver = FALSE;
     saver_mode = CONS_LKM_SAVER;
     current_saver = this_saver;
+    lwkt_reltoken(&tty_token);
     return 0;
 }
 
@@ -1957,13 +2157,16 @@ remove_scrn_saver(void (*this_saver)(sc_softc_t *, int))
     if (scrn_blanked)
         stop_scrn_saver(this_saver);
 #endif
-
+    lwkt_gettoken(&tty_token);
     /* unblank all blanked screens */
     wait_scrn_saver_stop(NULL);
-    if (scrn_blanked)
+    if (scrn_blanked) {
+        lwkt_reltoken(&tty_token);
        return EBUSY;
+    }
 
     current_saver = none_saver;
+    lwkt_reltoken(&tty_token);
     return 0;
 }
 
@@ -1972,6 +2175,7 @@ set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border)
 {
 
     /* assert(scp == scp->sc->cur_scp) */
+    lwkt_gettoken(&tty_token);
     crit_enter();
     if (!ISGRAPHSC(scp))
        sc_remove_cursor_image(scp);
@@ -1982,8 +2186,10 @@ set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border)
     scp->sc->flags |= SC_SCRN_BLANKED;
     ++scrn_blanked;
     crit_exit();
-    if (mode < 0)
+    if (mode < 0) {
+        lwkt_reltoken(&tty_token);
        return 0;
+    }
     scp->mode = mode;
     if (set_mode(scp) == 0) {
        if (scp->sc->adp->va_info.vi_flags & V_INFO_GRAPHICS)
@@ -1993,6 +2199,7 @@ set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border)
            load_palette(scp->sc->adp, pal);
 #endif
        sc_set_border(scp, border);
+       lwkt_reltoken(&tty_token);
        return 0;
     } else {
        crit_enter();
@@ -2000,8 +2207,10 @@ set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border)
        scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING);
        scp->status |= scp->splash_save_status;
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 1;
     }
+    /* NOTREACHED */
 }
 
 static int
@@ -2011,6 +2220,7 @@ restore_scrn_saver_mode(scr_stat *scp, int changemode)
     int status;
 
     /* assert(scp == scp->sc->cur_scp) */
+    lwkt_gettoken(&tty_token);
     crit_enter();
     mode = scp->mode;
     status = scp->status;
@@ -2023,6 +2233,7 @@ restore_scrn_saver_mode(scr_stat *scp, int changemode)
            sc_draw_cursor_image(scp);
        --scrn_blanked;
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
     }
     if (set_mode(scp) == 0) {
@@ -2031,28 +2242,35 @@ restore_scrn_saver_mode(scr_stat *scp, int changemode)
 #endif
        --scrn_blanked;
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
     } else {
        scp->mode = mode;
        scp->status = status;
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 1;
     }
+    /* NOTREACHED */
 }
 
 static void
 stop_scrn_saver(sc_softc_t *sc, void (*saver)(sc_softc_t *, int))
 {
+    lwkt_gettoken(&tty_token);
     (*saver)(sc, FALSE);
     run_scrn_saver = FALSE;
     /* the screen saver may have chosen not to stop after all... */
-    if (sc->flags & SC_SCRN_BLANKED)
+    if (sc->flags & SC_SCRN_BLANKED) {
+        lwkt_reltoken(&tty_token);
        return;
+    }
 
     mark_all(sc->cur_scp);
     if (sc->delayed_next_scr)
        sc_switch_scr(sc, sc->delayed_next_scr - 1);
     wakeup((caddr_t)&scrn_blanked);
+    lwkt_reltoken(&tty_token);
 }
 
 static int
@@ -2060,6 +2278,7 @@ wait_scrn_saver_stop(sc_softc_t *sc)
 {
     int error = 0;
 
+    lwkt_gettoken(&tty_token);
     while (scrn_blanked > 0) {
        run_scrn_saver = FALSE;
        if (sc && !(sc->flags & SC_SCRN_BLANKED)) {
@@ -2072,6 +2291,7 @@ wait_scrn_saver_stop(sc_softc_t *sc)
                break;
     }
     run_scrn_saver = FALSE;
+    lwkt_reltoken(&tty_token);
     return error;
 }
 #endif /* NSPLASH */
@@ -2091,10 +2311,12 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
 
     DPRINTF(5, ("sc0: sc_switch_scr() %d ", next_scr + 1));
 
+    lwkt_gettoken(&tty_token);
     /* prevent switch if previously requested */
     if (sc->flags & SC_SCRN_VTYLOCK) {
            sc_bell(sc->cur_scp, sc->cur_scp->bell_pitch,
                sc->cur_scp->bell_duration);
+           lwkt_reltoken(&tty_token);
            return EPERM;
     }
 
@@ -2104,6 +2326,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
        sc->delayed_next_scr = next_scr + 1;
        sc_touch_scrn_saver();
        DPRINTF(5, ("switch delayed\n"));
+       lwkt_reltoken(&tty_token);
        return 0;
     }
 
@@ -2111,6 +2334,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
     cur_scp = sc->cur_scp;
 
     /* we are in the middle of the vty switching process... */
+    lwkt_gettoken(&proc_token);
     if (sc->switch_in_progress
        && (cur_scp->smode.mode == VT_PROCESS)
        && cur_scp->proc) {
@@ -2135,6 +2359,8 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
                finish_vt_rel(cur_scp, TRUE);
                crit_exit();
                DPRINTF(5, ("finishing previous switch\n"));
+               lwkt_reltoken(&proc_token);
+               lwkt_reltoken(&tty_token);
                return EINVAL;
            } else if (cur_scp->status & SWITCH_WAIT_ACQ) {
                /* let's assume screen switch has been completed. */
@@ -2179,6 +2405,8 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
                    finish_vt_rel(cur_scp, FALSE);
                    crit_exit();
                    DPRINTF(5, ("act as if VT_FALSE was seen\n"));
+                   lwkt_reltoken(&proc_token);
+                   lwkt_reltoken(&tty_token);
                    return EINVAL;
                }
            } else if (cur_scp->status & SWITCH_WAIT_ACQ) {
@@ -2201,6 +2429,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
            }
        }
     }
+    lwkt_reltoken(&proc_token);
 
     /*
      * Return error if an invalid argument is given, or vty switch
@@ -2211,6 +2440,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
        crit_exit();
        sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
        DPRINTF(5, ("error 1\n"));
+       lwkt_reltoken(&tty_token);
        return EINVAL;
     }
 
@@ -2227,6 +2457,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
        crit_exit();
        sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
        DPRINTF(5, ("error, graphics mode\n"));
+       lwkt_reltoken(&tty_token);
        return EINVAL;
     }
 
@@ -2242,11 +2473,13 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
            crit_exit();
            sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
            DPRINTF(5, ("error 2, requested vty isn't open!\n"));
+           lwkt_reltoken(&tty_token);
            return EINVAL;
        }
        if ((debugger > 0) && (SC_STAT(tp->t_dev)->smode.mode == VT_PROCESS)) {
            crit_exit();
            DPRINTF(5, ("error 3, requested vty is in the VT_PROCESS mode\n"));
+           lwkt_reltoken(&tty_token);
            return EINVAL;
        }
     }
@@ -2261,6 +2494,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
        wakeup((caddr_t)&sc->new_scp->smode);
        crit_exit();
        DPRINTF(5, ("switch done (new == old)\n"));
+       lwkt_reltoken(&tty_token);
        return 0;
     }
 
@@ -2271,6 +2505,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
     /* wait for the controlling process to release the screen, if necessary */
     if (signal_vt_rel(sc->old_scp)) {
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
     }
 
@@ -2285,6 +2520,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
     /* wait for the controlling process to acknowledge, if necessary */
     if (signal_vt_acq(sc->cur_scp)) {
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return 0;
     }
 
@@ -2294,6 +2530,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
     crit_exit();
     DPRINTF(5, ("switch done\n"));
 
+    lwkt_reltoken(&tty_token);
     return 0;
 }
 
@@ -2304,6 +2541,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
 static void
 do_switch_scr(sc_softc_t *sc)
 {
+    lwkt_gettoken(&tty_token);
     vt_proc_alive(sc->new_scp);
 
     crit_exit();
@@ -2318,42 +2556,62 @@ do_switch_scr(sc_softc_t *sc)
        if (sc->unit == sc_console_unit)
            cons_unavail = FALSE;
     }
+    lwkt_reltoken(&tty_token);
 }
 
 static int
 vt_proc_alive(scr_stat *scp)
 {
+    lwkt_gettoken(&tty_token);
+    lwkt_gettoken(&proc_token);
     if (scp->proc) {
-       if (scp->proc == pfind(scp->pid))
+       if (scp->proc == pfind(scp->pid)) {
+           lwkt_reltoken(&proc_token);
+           lwkt_reltoken(&tty_token);
            return TRUE;
+       }
        scp->proc = NULL;
        scp->smode.mode = VT_AUTO;
        DPRINTF(5, ("vt controlling process %d died\n", scp->pid));
     }
+    lwkt_reltoken(&proc_token);
+    lwkt_reltoken(&tty_token);
     return FALSE;
 }
 
 static int
 signal_vt_rel(scr_stat *scp)
 {
-    if (scp->smode.mode != VT_PROCESS)
+    lwkt_gettoken(&tty_token);
+    if (scp->smode.mode != VT_PROCESS) {
+        lwkt_reltoken(&tty_token);
        return FALSE;
+    }
     scp->status |= SWITCH_WAIT_REL;
+    lwkt_gettoken(&proc_token);
     ksignal(scp->proc, scp->smode.relsig);
+    lwkt_reltoken(&proc_token);
     DPRINTF(5, ("sending relsig to %d\n", scp->pid));
+    lwkt_reltoken(&tty_token);
     return TRUE;
 }
 
 static int
 signal_vt_acq(scr_stat *scp)
 {
-    if (scp->smode.mode != VT_PROCESS)
+    lwkt_gettoken(&tty_token);
+    if (scp->smode.mode != VT_PROCESS) {
+        lwkt_reltoken(&tty_token);
        return FALSE;
+    }
     if (scp->sc->unit == sc_console_unit)
        cons_unavail = TRUE;
     scp->status |= SWITCH_WAIT_ACQ;
+    lwkt_gettoken(&proc_token);
     ksignal(scp->proc, scp->smode.acqsig);
+    lwkt_reltoken(&proc_token);
     DPRINTF(5, ("sending acqsig to %d\n", scp->pid));
+    lwkt_reltoken(&tty_token);
     return TRUE;
 }
 
@@ -2364,25 +2622,31 @@ signal_vt_acq(scr_stat *scp)
 static int
 finish_vt_rel(scr_stat *scp, int release)
 {
+    lwkt_gettoken(&tty_token);
     if (scp == scp->sc->old_scp && scp->status & SWITCH_WAIT_REL) {
        scp->status &= ~SWITCH_WAIT_REL;
        if (release)
            do_switch_scr(scp->sc);
        else
            scp->sc->switch_in_progress = 0;
+       lwkt_reltoken(&tty_token);
        return 0;
     }
+    lwkt_reltoken(&tty_token);
     return EINVAL;
 }
 
 static int
 finish_vt_acq(scr_stat *scp)
 {
+    lwkt_gettoken(&tty_token);
     if (scp == scp->sc->new_scp && scp->status & SWITCH_WAIT_ACQ) {
        scp->status &= ~SWITCH_WAIT_ACQ;
        scp->sc->switch_in_progress = 0;
+       lwkt_reltoken(&tty_token);
        return 0;
     }
+    lwkt_reltoken(&tty_token);
     return EINVAL;
 }
 
@@ -2391,6 +2655,7 @@ exchange_scr(sc_softc_t *sc)
 {
     scr_stat *scp;
 
+    lwkt_gettoken(&tty_token);
     /* save the current state of video and keyboard */
     sc_move_cursor(sc->old_scp, sc->old_scp->xpos, sc->old_scp->ypos);
     if (!ISGRAPHSC(sc->old_scp))
@@ -2421,11 +2686,13 @@ exchange_scr(sc_softc_t *sc)
     update_kbd_state(scp, scp->status, LOCK_MASK);
 
     mark_all(scp);
+    lwkt_reltoken(&tty_token);
 }
 
 static void
 sc_puts(scr_stat *scp, u_char *buf, int len)
 {
+    lwkt_gettoken(&tty_token);
 #if NSPLASH > 0
     /* make screensaver happy */
     if (!sticky_splash && scp == scp->sc->cur_scp)
@@ -2437,11 +2704,14 @@ sc_puts(scr_stat *scp, u_char *buf, int len)
 
     if (scp->sc->delayed_next_scr)
        sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
+
+    lwkt_reltoken(&tty_token);
 }
 
 void
 sc_draw_cursor_image(scr_stat *scp)
 {
+    lwkt_gettoken(&tty_token);
     /* assert(scp == scp->sc->cur_scp); */
     ++scp->sc->videoio_in_progress;
     (*scp->rndr->draw_cursor)(scp, scp->cursor_pos,
@@ -2449,17 +2719,20 @@ sc_draw_cursor_image(scr_stat *scp)
                              sc_inside_cutmark(scp, scp->cursor_pos));
     scp->cursor_oldpos = scp->cursor_pos;
     --scp->sc->videoio_in_progress;
+    lwkt_reltoken(&tty_token);
 }
 
 void
 sc_remove_cursor_image(scr_stat *scp)
 {
+    lwkt_gettoken(&tty_token);
     /* assert(scp == scp->sc->cur_scp); */
     ++scp->sc->videoio_in_progress;
     (*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos,
                              scp->sc->flags & SC_BLINK_CURSOR, FALSE,
                              sc_inside_cutmark(scp, scp->cursor_oldpos));
     --scp->sc->videoio_in_progress;
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -2467,6 +2740,7 @@ update_cursor_image(scr_stat *scp)
 {
     int blink;
 
+    lwkt_gettoken(&tty_token);
     if (scp->sc->flags & SC_CHAR_CURSOR) {
        scp->cursor_base = imax(0, scp->sc->cursor_base);
        scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
@@ -2484,11 +2758,13 @@ update_cursor_image(scr_stat *scp)
     (*scp->rndr->draw_cursor)(scp, scp->cursor_pos, blink, TRUE, 
                              sc_inside_cutmark(scp, scp->cursor_pos));
     --scp->sc->videoio_in_progress;
+    lwkt_reltoken(&tty_token);
 }
 
 void
 sc_set_cursor_image(scr_stat *scp)
 {
+    lwkt_gettoken(&tty_token);
     if (scp->sc->flags & SC_CHAR_CURSOR) {
        scp->cursor_base = imax(0, scp->sc->cursor_base);
        scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
@@ -2502,6 +2778,7 @@ sc_set_cursor_image(scr_stat *scp)
     (*scp->rndr->set_cursor)(scp, scp->cursor_base, scp->cursor_height,
                             scp->sc->flags & SC_BLINK_CURSOR);
     --scp->sc->videoio_in_progress;
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -2529,6 +2806,7 @@ scinit(int unit, int flags)
     int row;
     int i;
 
+    lwkt_gettoken(&tty_token);
     /* one time initialization */
     if (init_done == COLD)
        sc_get_bios_values(&bios_value);
@@ -2690,14 +2968,17 @@ scinit(int unit, int flags)
     }
 
     /* the rest is not necessary, if we have done it once */
-    if (sc->flags & SC_INIT_DONE)
+    if (sc->flags & SC_INIT_DONE) {
+        lwkt_reltoken(&tty_token);
        return;
+    }
 
     /* initialize mapscrn arrays to a one to one map */
     for (i = 0; i < sizeof(sc->scr_map); i++)
        sc->scr_map[i] = sc->scr_rmap[i] = i;
 
     sc->flags |= SC_INIT_DONE;
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -2710,6 +2991,7 @@ scterm(int unit, int flags)
     if (sc == NULL)
        return;                 /* shouldn't happen */
 
+    lwkt_gettoken(&tty_token);
 #if NSPLASH > 0
     /* this console is no longer available for the splash screen */
     if (sc->flags & SC_SPLASH_SCRN) {
@@ -2760,6 +3042,7 @@ scterm(int unit, int flags)
     bzero(sc, sizeof(*sc));
     sc->keyboard = -1;
     sc->adapter = -1;
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -2767,12 +3050,14 @@ scshutdown(void *arg, int howto)
 {
     /* assert(sc_console != NULL) */
 
+    lwkt_gettoken(&tty_token);
     sc_touch_scrn_saver();
     if (!cold && sc_console
        && sc_console->sc->cur_scp->smode.mode == VT_AUTO 
        && sc_console->smode.mode == VT_AUTO)
        sc_switch_scr(sc_console->sc, sc_console->index);
     shutdown_in_progress = TRUE;
+    lwkt_reltoken(&tty_token);
 }
 
 int
@@ -2782,16 +3067,20 @@ sc_clean_up(scr_stat *scp)
     int error;
 #endif /* NSPLASH */
 
+    lwkt_gettoken(&tty_token);
     if (scp->sc->flags & SC_SCRN_BLANKED) {
        sc_touch_scrn_saver();
 #if NSPLASH > 0
-       if ((error = wait_scrn_saver_stop(scp->sc)))
+       if ((error = wait_scrn_saver_stop(scp->sc))) {
+           lwkt_reltoken(&tty_token);
            return error;
+       }
 #endif /* NSPLASH */
     }
     scp->status |= MOUSE_HIDDEN;
     sc_remove_mouse_image(scp);
     sc_remove_cutmarking(scp);
+    lwkt_reltoken(&tty_token);
     return 0;
 }
 
@@ -2801,6 +3090,7 @@ sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard)
     sc_vtb_t new;
     sc_vtb_t old;
 
+    lwkt_gettoken(&tty_token);
     old = scp->vtb;
     sc_vtb_init(&new, VTB_MEMORY, scp->xsize, scp->ysize, NULL, wait);
     if (!discard && (old.vtb_flags & VTB_VALID)) {
@@ -2821,6 +3111,7 @@ sc_alloc_scr_buffer(scr_stat *scp, int wait, int discard)
     /* move the mouse cursor at the center of the screen */
     sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
 #endif
+    lwkt_reltoken(&tty_token);
 }
 
 static scr_stat *
@@ -2831,6 +3122,7 @@ alloc_scp(sc_softc_t *sc, int vty)
     /* assert(sc_malloc) */
 
     scp = kmalloc(sizeof(scr_stat), M_SYSCONS, M_WAITOK);
+    lwkt_gettoken(&tty_token);
     init_scp(sc, vty, scp);
 
     sc_alloc_scr_buffer(scp, TRUE, TRUE);
@@ -2844,15 +3136,19 @@ alloc_scp(sc_softc_t *sc, int vty)
 #ifndef SC_NO_HISTORY
     sc_alloc_history_buffer(scp, 0, 0, TRUE);
 #endif
-
+    lwkt_reltoken(&tty_token);
     return scp;
 }
 
+/*
+ * NOTE: Must be called with tty_token held.
+ */
 static void
 init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
 {
     video_info_t info;
 
+    ASSERT_LWKT_TOKEN_HELD(&tty_token);
     bzero(scp, sizeof(*scp));
 
     scp->index = vty;
@@ -2935,12 +3231,15 @@ sc_init_emulator(scr_stat *scp, char *name)
     void *p;
     int error;
 
+    lwkt_gettoken(&tty_token);
     if (name == NULL)  /* if no name is given, use the current emulator */
        sw = scp->tsw;
     else               /* ...otherwise find the named emulator */
        sw = sc_term_match(name);
-    if (sw == NULL)
+    if (sw == NULL) {
+        lwkt_reltoken(&tty_token);
        return EINVAL;
+    }
 
     rndr = NULL;
     if (strcmp(sw->te_renderer, "*") != 0) {
@@ -2948,8 +3247,10 @@ sc_init_emulator(scr_stat *scp, char *name)
     }
     if (rndr == NULL) {
        rndr = sc_render_match(scp, scp->sc->adp->va_name, scp->model);
-       if (rndr == NULL)
+       if (rndr == NULL) {
+           lwkt_reltoken(&tty_token);
            return ENODEV;
+       }
     }
 
     if (sw == scp->tsw) {
@@ -2957,6 +3258,7 @@ sc_init_emulator(scr_stat *scp, char *name)
        scp->rndr = rndr;
        sc_clear_screen(scp);
        /* assert(error == 0); */
+       lwkt_reltoken(&tty_token);
        return error;
     }
 
@@ -2965,8 +3267,10 @@ sc_init_emulator(scr_stat *scp, char *name)
     else
        p = NULL;
     error = (*sw->te_init)(scp, &p, SC_TE_COLD_INIT);
-    if (error)
+    if (error) {
+        lwkt_reltoken(&tty_token);
        return error;
+    }
 
     if (scp->tsw)
        (*scp->tsw->te_term)(scp, &scp->ts);
@@ -2980,6 +3284,7 @@ sc_init_emulator(scr_stat *scp, char *name)
     (*sw->te_default_attr)(scp, user_default.std_color, user_default.rev_color);
     sc_clear_screen(scp);
 
+    lwkt_reltoken(&tty_token);
     return 0;
 }
 
@@ -3001,8 +3306,11 @@ scgetc(sc_softc_t *sc, u_int flags)
     int f;
     int i;
 
-    if (sc->kbd == NULL)
+    lwkt_gettoken(&tty_token);
+    if (sc->kbd == NULL) {
+        lwkt_reltoken(&tty_token);
        return NOKEY;
+    }
 
 next_code:
 #if 1
@@ -3020,10 +3328,12 @@ next_code:
        if (c == ERRKEY) {
            if (!(flags & SCGETC_CN))
                sc_bell(scp, bios_value.bell_pitch, BELL_DURATION);
-       } else if (c == NOKEY)
+       } else if (c == NOKEY) {
+           lwkt_reltoken(&tty_token);
            return c;
-       else
+       } else {
            break;
+       }
     }
 
     /* make screensaver happy */
@@ -3034,8 +3344,10 @@ next_code:
        /* do the /dev/random device a favour */
        add_keyboard_randomness(c);
 
-    if (scp->kbd_mode != K_XLATE)
+    if (scp->kbd_mode != K_XLATE) {
+        lwkt_reltoken(&tty_token);
        return KEYCHAR(c);
+    }
 
     /* if scroll-lock pressed allow history browsing */
     if (!ISGRAPHSC(scp) && scp->history && scp->status & SLKED) {
@@ -3142,8 +3454,10 @@ next_code:
                break;
 
            case BTAB:
-               if (!(sc->flags & SC_SCRN_BLANKED))
+               if (!(sc->flags & SC_SCRN_BLANKED)) {
+                    lwkt_reltoken(&tty_token);
                    return c;
+               }
                break;
 
            case SPSC:
@@ -3251,8 +3565,10 @@ next_code:
                    break;
                }
                /* assert(c & FKEY) */
-               if (!(sc->flags & SC_SCRN_BLANKED))
+               if (!(sc->flags & SC_SCRN_BLANKED)) {
+                   lwkt_reltoken(&tty_token);
                    return c;
+               }
                break;
            }
            /* goto next_code */
@@ -3271,11 +3587,15 @@ scmmap(struct dev_mmap_args *ap)
 {
     scr_stat *scp;
 
+    lwkt_gettoken(&tty_token);
     scp = SC_STAT(ap->a_head.a_dev);
-    if (scp != scp->sc->cur_scp)
+    if (scp != scp->sc->cur_scp) {
+        lwkt_reltoken(&tty_token);
        return EINVAL;
+    }
     ap->a_result = (*vidsw[scp->sc->adapter]->mmap)(scp->sc->adp, ap->a_offset,
                                                    ap->a_nprot);
+    lwkt_reltoken(&tty_token);
     return(0);
 }
 
@@ -3285,6 +3605,7 @@ save_kbd_state(scr_stat *scp)
     int state;
     int error;
 
+    lwkt_gettoken(&tty_token);
     error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
     if (error == ENOIOCTL)
        error = ENODEV;
@@ -3292,6 +3613,7 @@ save_kbd_state(scr_stat *scp)
        scp->status &= ~LOCK_MASK;
        scp->status |= state;
     }
+    lwkt_reltoken(&tty_token);
     return error;
 }
 
@@ -3301,12 +3623,15 @@ update_kbd_state(scr_stat *scp, int new_bits, int mask)
     int state;
     int error;
 
+    lwkt_gettoken(&tty_token);
     if (mask != LOCK_MASK) {
        error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state);
        if (error == ENOIOCTL)
            error = ENODEV;
-       if (error)
+       if (error) {
+           lwkt_reltoken(&tty_token);
            return error;
+       }
        state &= ~mask;
        state |= new_bits & mask;
     } else {
@@ -3315,6 +3640,7 @@ update_kbd_state(scr_stat *scp, int new_bits, int mask)
     error = kbd_ioctl(scp->sc->kbd, KDSKBSTATE, (caddr_t)&state);
     if (error == ENOIOCTL)
        error = ENODEV;
+    lwkt_reltoken(&tty_token);
     return error;
 }
 
@@ -3323,10 +3649,12 @@ update_kbd_leds(scr_stat *scp, int which)
 {
     int error;
 
+    lwkt_gettoken(&tty_token);
     which &= LOCK_MASK;
     error = kbd_ioctl(scp->sc->kbd, KDSETLED, (caddr_t)&which);
     if (error == ENOIOCTL)
        error = ENODEV;
+    lwkt_reltoken(&tty_token);
     return error;
 }
 
@@ -3335,13 +3663,18 @@ set_mode(scr_stat *scp)
 {
     video_info_t info;
 
+    lwkt_gettoken(&tty_token);
     /* reject unsupported mode */
-    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info))
+    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) {
+        lwkt_reltoken(&tty_token);
        return 1;
+    }
 
     /* if this vty is not currently showing, do nothing */
-    if (scp != scp->sc->cur_scp)
+    if (scp != scp->sc->cur_scp) {
+        lwkt_reltoken(&tty_token);
        return 0;
+    }
 
     /* setup video hardware for the given mode */
     (*vidsw[scp->sc->adapter]->set_mode)(scp->sc->adp, scp->mode);
@@ -3378,6 +3711,7 @@ set_mode(scr_stat *scp)
     sc_set_border(scp, scp->border);
     sc_set_cursor_image(scp);
 
+    lwkt_reltoken(&tty_token);
     return 0;
 }
 
@@ -3390,6 +3724,7 @@ refresh_ega_palette(scr_stat *scp)
     int rfld, gfld, bfld;
     int i;
 
+    lwkt_gettoken(&tty_token);
     rsize = scp->sc->adp->va_info.vi_pixel_fsizes[0];
     gsize = scp->sc->adp->va_info.vi_pixel_fsizes[1];
     bsize = scp->sc->adp->va_info.vi_pixel_fsizes[2];
@@ -3406,14 +3741,17 @@ refresh_ega_palette(scr_stat *scp)
 
        scp->ega_palette[i] = (r << rfld) + (g << gfld) + (b << bfld);
     }
+    lwkt_reltoken(&tty_token);
 }
 
 void
 sc_set_border(scr_stat *scp, int color)
 {
+    lwkt_gettoken(&tty_token);
     ++scp->sc->videoio_in_progress;
     (*scp->rndr->draw_border)(scp, color);
     --scp->sc->videoio_in_progress;
+    lwkt_reltoken(&tty_token);
 }
 
 #ifndef SC_NO_FONT_LOADING
@@ -3423,10 +3761,12 @@ sc_load_font(scr_stat *scp, int page, int size, u_char *buf,
 {
     sc_softc_t *sc;
 
+    lwkt_gettoken(&tty_token);
     sc = scp->sc;
     sc->font_loading_in_progress = TRUE;
     (*vidsw[sc->adapter]->load_font)(sc->adp, page, size, buf, base, count);
     sc->font_loading_in_progress = FALSE;
+    lwkt_reltoken(&tty_token);
 }
 
 void
@@ -3435,16 +3775,20 @@ sc_save_font(scr_stat *scp, int page, int size, u_char *buf,
 {
     sc_softc_t *sc;
 
+    lwkt_gettoken(&tty_token);
     sc = scp->sc;
     sc->font_loading_in_progress = TRUE;
     (*vidsw[sc->adapter]->save_font)(sc->adp, page, size, buf, base, count);
     sc->font_loading_in_progress = FALSE;
+    lwkt_reltoken(&tty_token);
 }
 
 void
 sc_show_font(scr_stat *scp, int page)
 {
+    lwkt_gettoken(&tty_token);
     (*vidsw[scp->sc->adapter]->show_font)(scp->sc->adp, page);
+    lwkt_reltoken(&tty_token);
 }
 #endif /* !SC_NO_FONT_LOADING */
 
@@ -3454,14 +3798,18 @@ sc_paste(scr_stat *scp, u_char *p, int count)
     struct tty *tp;
     u_char *rmap;
 
+    lwkt_gettoken(&tty_token);
     if (scp->status & MOUSE_VISIBLE) {
        tp = VIRTUAL_TTY(scp->sc, scp->sc->cur_scp->index);
-       if (!ISTTYOPEN(tp))
+       if (!ISTTYOPEN(tp)) {
+           lwkt_reltoken(&tty_token);
            return;
+       }
        rmap = scp->sc->scr_rmap;
        for (; count > 0; --count)
            (*linesw[tp->t_line].l_rint)(rmap[*p++], tp);
     }
+    lwkt_reltoken(&tty_token);
 }
 
 void
@@ -3470,12 +3818,17 @@ sc_bell(scr_stat *scp, int pitch, int duration)
     if (cold || shutdown_in_progress)
        return;
 
-    if (scp != scp->sc->cur_scp && (scp->sc->flags & SC_QUIET_BELL))
+    lwkt_gettoken(&tty_token);
+    if (scp != scp->sc->cur_scp && (scp->sc->flags & SC_QUIET_BELL)) {
+        lwkt_reltoken(&tty_token);
        return;
+    }
 
     if (scp->sc->flags & SC_VISUAL_BELL) {
-       if (scp->sc->blink_in_progress)
+       if (scp->sc->blink_in_progress) {
+           lwkt_reltoken(&tty_token);
            return;
+       }
        scp->sc->blink_in_progress = 3;
        if (scp != scp->sc->cur_scp)
            scp->sc->blink_in_progress += 2;
@@ -3485,6 +3838,7 @@ sc_bell(scr_stat *scp, int pitch, int duration)
            pitch *= 2;
        sysbeep(pitch, duration);
     }
+    lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -3493,6 +3847,7 @@ blink_screen(void *arg)
     scr_stat *scp = arg;
     struct tty *tp;
 
+    lwkt_gettoken(&tty_token);
     if (ISGRAPHSC(scp) || (scp->sc->blink_in_progress <= 1)) {
        scp->sc->blink_in_progress = 0;
        mark_all(scp);
@@ -3508,6 +3863,7 @@ blink_screen(void *arg)
        scp->sc->blink_in_progress--;
        callout_reset(&scp->blink_screen_ch, hz / 10, blink_screen, scp);
     }
+    lwkt_reltoken(&tty_token);
 }
 
 
@@ -3524,6 +3880,7 @@ sc_allocate_keyboard(sc_softc_t *sc, int unit)
        keyboard_t      *k0, *k;
        keyboard_info_t  ki;
 
+       lwkt_gettoken(&tty_token);
        idx0 = kbd_allocate("kbdmux", -1, (void *)&sc->keyboard, sckbdevent, sc);
        if (idx0 != -1) {
                k0 = kbd_get_keyboard(idx0);
@@ -3545,5 +3902,6 @@ sc_allocate_keyboard(sc_softc_t *sc, int unit)
        } else
                idx0 = kbd_allocate("*", unit, (void *)&sc->keyboard, sckbdevent, sc);
 
+       lwkt_reltoken(&tty_token);
        return (idx0);
 }
index 1b1cda7..52cbfcf 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
  * All rights reserved.
  *
  * $DragonFly: src/sys/dev/misc/syscons/sysmouse.c,v 1.12 2006/09/10 01:26:35 dillon Exp $
  */
 
+/* MPSAFE NOTE: This file uses the tty_token mostly for the linesw access and
+ *             for the internal mouse structures. The latter ones could be protected
+ *             by a local lock.
+ */
 #include "opt_syscons.h"
 
 #include <sys/param.h>
@@ -75,6 +81,7 @@ smopen(struct dev_open_args *ap)
 {
        cdev_t dev = ap->a_head.a_dev;
        struct tty *tp;
+       int ret;
 
        DPRINTF(5, ("smopen: dev:%d,%d, vty:%d\n",
                major(dev), minor(dev), SC_VTY(dev)));
@@ -84,6 +91,7 @@ smopen(struct dev_open_args *ap)
                return ENXIO;
 #endif
 
+       lwkt_gettoken(&tty_token);
        tp = dev->si_tty = ttymalloc(dev->si_tty);
        if (!(tp->t_state & TS_ISOPEN)) {
                sysmouse_tty = tp;
@@ -100,10 +108,13 @@ smopen(struct dev_open_args *ap)
                smparam(tp, &tp->t_termios);
                (*linesw[tp->t_line].l_modem)(tp, 1);
        } else if (tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) {
+               lwkt_reltoken(&tty_token);
                return EBUSY;
        }
 
-       return (*linesw[tp->t_line].l_open)(dev, tp);
+       ret = (*linesw[tp->t_line].l_open)(dev, tp);
+       lwkt_reltoken(&tty_token);
+       return ret;
 }
 
 static int
@@ -114,9 +125,11 @@ smclose(struct dev_close_args *ap)
 
        tp = dev->si_tty;
        crit_enter();
+       lwkt_gettoken(&tty_token);
        mouse_level = 0;
        (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
        ttyclose(tp);
+       lwkt_reltoken(&tty_token);
        crit_exit();
 
        return 0;
@@ -129,6 +142,7 @@ smstart(struct tty *tp)
        u_char buf[PCBURST];
 
        crit_enter();
+       lwkt_gettoken(&tty_token);
        if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) {
                tp->t_state |= TS_BUSY;
                rbp = &tp->t_outq;
@@ -137,15 +151,18 @@ smstart(struct tty *tp)
                tp->t_state &= ~TS_BUSY;
                ttwwakeup(tp);
        }
+       lwkt_reltoken(&tty_token);
        crit_exit();
 }
 
 static int
 smparam(struct tty *tp, struct termios *t)
 {
+       lwkt_gettoken(&tty_token);
        tp->t_ispeed = t->c_ispeed;
        tp->t_ospeed = t->c_ospeed;
        tp->t_cflag = t->c_cflag;
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -158,6 +175,7 @@ smioctl(struct dev_ioctl_args *ap)
        mousemode_t *mode;
        int error;
 
+       lwkt_gettoken(&tty_token);
        tp = dev->si_tty;
 
        switch (ap->a_cmd) {
@@ -168,6 +186,7 @@ smioctl(struct dev_ioctl_args *ap)
                hw->type = MOUSE_MOUSE;
                hw->model = MOUSE_MODEL_GENERIC;
                hw->hwid = 0;
+               lwkt_reltoken(&tty_token);
                return 0;
 
        case MOUSE_GETMODE:     /* get protocol/mode */
@@ -194,26 +213,34 @@ smioctl(struct dev_ioctl_args *ap)
                        mode->syncmask[1] = MOUSE_SYS_SYNC;
                        break;
                }
+               lwkt_reltoken(&tty_token);
                return 0;
 
        case MOUSE_SETMODE:     /* set protocol/mode */
                mode = (mousemode_t *)ap->a_data;
                if (mode->level == -1)
                        ;       /* don't change the current setting */
-               else if ((mode->level < 0) || (mode->level > 1))
+               else if ((mode->level < 0) || (mode->level > 1)) {
+                       lwkt_reltoken(&tty_token);
                        return EINVAL;
-               else
+               } else {
                        mouse_level = mode->level;
+               }
+               lwkt_reltoken(&tty_token);
                return 0;
 
        case MOUSE_GETLEVEL:    /* get operation level */
                *(int *)ap->a_data = mouse_level;
+               lwkt_reltoken(&tty_token);
                return 0;
 
        case MOUSE_SETLEVEL:    /* set operation level */
-               if ((*(int *)ap->a_data  < 0) || (*(int *)ap->a_data > 1))
+               if ((*(int *)ap->a_data  < 0) || (*(int *)ap->a_data > 1)) {
+                       lwkt_reltoken(&tty_token);
                        return EINVAL;
+               }
                mouse_level = *(int *)ap->a_data;
+               lwkt_reltoken(&tty_token);
                return 0;
 
        case MOUSE_GETSTATUS:   /* get accumulated mouse events */
@@ -225,25 +252,33 @@ smioctl(struct dev_ioctl_args *ap)
                mouse_status.dy = 0;
                mouse_status.dz = 0;
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return 0;
 
 #if notyet
        case MOUSE_GETVARS:     /* get internal mouse variables */
        case MOUSE_SETVARS:     /* set internal mouse variables */
+               lwkt_reltoken(&tty_token);
                return ENODEV;
 #endif
 
        case MOUSE_READSTATE:   /* read status from the device */
        case MOUSE_READDATA:    /* read data from the device */
+               lwkt_reltoken(&tty_token);
                return ENODEV;
        }
 
        error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data, ap->a_fflag, ap->a_cred);
-       if (error != ENOIOCTL)
+       if (error != ENOIOCTL) {
+               lwkt_reltoken(&tty_token);
                return error;
+       }
        error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag);
-       if (error != ENOIOCTL)
+       if (error != ENOIOCTL) {
+               lwkt_reltoken(&tty_token);
                return error;
+       }
+       lwkt_reltoken(&tty_token);
        return ENOTTY;
 }
 
@@ -278,6 +313,7 @@ sysmouse_event(mouse_info_t *info)
        int x, y, z;
        int i;
 
+       lwkt_gettoken(&tty_token);
        switch (info->operation) {
        case MOUSE_ACTION:
                mouse_status.button = info->u.data.buttons;
@@ -295,6 +331,7 @@ sysmouse_event(mouse_info_t *info)
                        mouse_status.button &= ~info->u.event.id;
                break;
        default:
+               lwkt_reltoken(&tty_token);
                return 0;
        }
 
@@ -303,11 +340,15 @@ sysmouse_event(mouse_info_t *info)
        mouse_status.dz += z;
        mouse_status.flags |= ((x || y || z) ? MOUSE_POSCHANGED : 0)
                              | (mouse_status.obutton ^ mouse_status.button);
-       if (mouse_status.flags == 0)
+       if (mouse_status.flags == 0) {
+               lwkt_reltoken(&tty_token);
                return 0;
+       }
 
-       if ((sysmouse_tty == NULL) || !(sysmouse_tty->t_state & TS_ISOPEN))
+       if ((sysmouse_tty == NULL) || !(sysmouse_tty->t_state & TS_ISOPEN)) {
+               lwkt_reltoken(&tty_token);
                return mouse_status.flags;
+       }
 
        /* the first five bytes are compatible with MouseSystems' */
        buf[0] = MOUSE_MSC_SYNC
@@ -332,6 +373,7 @@ sysmouse_event(mouse_info_t *info)
                                                               sysmouse_tty);
        }
 
+       lwkt_reltoken(&tty_token);
        return mouse_status.flags;
 }
 
index 9a7a963..80687c2 100644 (file)
@@ -38,6 +38,7 @@
 #include <sys/fbio.h>
 #include <sys/random.h>
 #include <sys/thread2.h>
+#include <sys/thread.h>
 
 #include <dev/video/fb/fbreg.h>
 #include <dev/video/fb/splashreg.h>
index 550da5e..a78773c 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * cyclades cyclom-y serial driver
  *     Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993
  *
@@ -495,9 +497,12 @@ sioattach(struct isa_device *isdp)
 {
        int     adapter;
 
+       lwkt_gettoken(&tty_token);
        adapter = cyattach_common((cy_addr) isdp->id_maddr, 0);
-       if (adapter < 0)
+       if (adapter < 0) {
+               lwkt_reltoken(&tty_token);
                return (0);
+       }
 
        /*
         * XXX
@@ -510,9 +515,13 @@ sioattach(struct isa_device *isdp)
        }
        isdp->id_intr = (inthand2_t *)siointr;
        /* isdp->id_ri_flags |= RI_FAST; XXX unimplemented - use newbus! */
+       lwkt_reltoken(&tty_token);
        return (1);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 int
 cyattach_common(cy_addr cy_iobase, int cy_align)
 {
@@ -524,6 +533,8 @@ cyattach_common(cy_addr cy_iobase, int cy_align)
        int     ncyu;
        int     unit;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
+
        adapter = cy_total_devices;
        if ((u_int)adapter >= NCY) {
                kprintf(
@@ -555,7 +566,7 @@ cyattach_common(cy_addr cy_iobase, int cy_align)
 
        com = kmalloc(sizeof *com, M_DEVBUF, M_WAITOK | M_ZERO);
        com->unit = unit;
-                       callout_init(&com->dtr_ch);
+                       callout_init_mp(&com->dtr_ch);
                        com->gfrcr_image = firmware_version;
                        if (CY_RTS_DTR_SWAPPED(firmware_version)) {
                                com->mcr_dtr = MCR_RTS;
@@ -607,8 +618,8 @@ cyattach_common(cy_addr cy_iobase, int cy_align)
        crit_exit();
 
        if (!sio_registered) {
-               callout_init(&sio_timeout_handle);
-               register_swi(SWI_TTY, siopoll, NULL, "cy", NULL);
+               callout_init_mp(&sio_timeout_handle);
+               register_swi_mp(SWI_TTY, siopoll, NULL, "cy", NULL);
                sio_registered = TRUE;
        }
        minorbase = UNIT_TO_MINOR(unit);
@@ -657,6 +668,8 @@ sioopen(struct dev_open_args *ap)
                return (ENXIO);
        if (mynor & CONTROL_MASK)
                return (0);
+
+       lwkt_gettoken(&tty_token);
 #if 0 /* XXX */
        tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]);
 #else
@@ -819,9 +832,13 @@ out:
        crit_exit();
        if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
                comhardclose(com);
+       lwkt_reltoken(&tty_token);
        return (error);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 sioclose(struct dev_close_args *ap)
 {
@@ -830,9 +847,11 @@ sioclose(struct dev_close_args *ap)
        int             mynor;
        struct tty      *tp;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        mynor = minor(dev);
        if (mynor & CONTROL_MASK)
                return (0);
+       lwkt_gettoken(&tty_token);
        com = com_addr(MINOR_TO_UNIT(mynor));
        tp = com->tp;
        crit_enter();
@@ -848,9 +867,13 @@ sioclose(struct dev_close_args *ap)
        ttyfree(tp);
        com->tp = sio_tty[unit] = NULL;
 #endif
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 comhardclose(struct com_s *com)
 {
@@ -858,6 +881,8 @@ comhardclose(struct com_s *com)
        struct tty      *tp;
        int             unit;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
+
        unit = com->unit;
        iobase = com->iobase;
        crit_enter();
@@ -942,6 +967,7 @@ siowrite(struct dev_write_args *ap)
        if (mynor & CONTROL_MASK)
                return (ENODEV);
 
+       lwkt_gettoken(&tty_token);
        unit = MINOR_TO_UNIT(mynor);
        tp = com_addr(unit)->tp;
        /*
@@ -960,6 +986,7 @@ siowrite(struct dev_write_args *ap)
 #else
        return ((*linesw[tp->t_line].l_write)(tp, uio, ap->a_ioflag));
 #endif
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -967,11 +994,16 @@ siodtrwakeup(void *chan)
 {
        struct com_s    *com;
 
+       lwkt_gettoken(&tty_token);
        com = (struct com_s *)chan;
        com->state &= ~CS_DTR_OFF;
        wakeup(&com->dtr_wait);
+       lwkt_reltoken(&tty_token);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 sioinput(struct com_s *com)
 {
@@ -981,6 +1013,8 @@ sioinput(struct com_s *com)
        int             recv_data;
        struct tty      *tp;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
+
        buf = com->ibuf;
        tp = com->tp;
        if (!(tp->t_state & TS_ISOPEN)) {
@@ -1069,6 +1103,7 @@ siointr(void *arg)
        cy_addr iobase;
        u_char  status;
 
+       lwkt_gettoken(&tty_token);
        com_lock();     /* XXX could this be placed down lower in the loop? */
 
        baseu = unit * CY_MAX_PORTS;
@@ -1535,6 +1570,7 @@ terminate_tx_service:
        schedsofttty();
 
        com_unlock();
+       lwkt_reltoken(&tty_token);
 }
 
 #if 0
@@ -1559,6 +1595,7 @@ sioioctl(struct dev_ioctl_args *ap)
        struct termios  term;
 #endif
 
+       lwkt_gettoken(&tty_token);
        mynor = minor(dev);
        com = com_addr(MINOR_TO_UNIT(mynor));
        if (mynor & CONTROL_MASK) {
@@ -1572,25 +1609,33 @@ sioioctl(struct dev_ioctl_args *ap)
                        ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
                        break;
                default:
+                       lwkt_reltoken(&tty_token);
                        return (ENODEV);        /* /dev/nodev */
                }
                switch (cmd) {
                case TIOCSETA:
                        error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
-                       if (error != 0)
+                       if (error != 0) {
+                               lwkt_reltoken(&tty_token);
                                return (error);
+                       }
                        *ct = *(struct termios *)data;
+                       lwkt_reltoken(&tty_token);
                        return (0);
                case TIOCGETA:
                        *(struct termios *)data = *ct;
+                       lwkt_reltoken(&tty_token);
                        return (0);
                case TIOCGETD:
                        *(int *)data = TTYDISC;
+                       lwkt_reltoken(&tty_token);
                        return (0);
                case TIOCGWINSZ:
                        bzero(data, sizeof(struct winsize));
+                       lwkt_reltoken(&tty_token);
                        return (0);
                default:
+                       lwkt_reltoken(&tty_token);
                        return (ENOTTY);
                }
        }
@@ -1599,8 +1644,10 @@ sioioctl(struct dev_ioctl_args *ap)
        term = tp->t_termios;
        oldcmd = cmd;
        error = ttsetcompat(tp, &cmd, data, &term);
-       if (error != 0)
+       if (error != 0) {
+               lwkt_reltoken(&tty_token);
                return (error);
+       }
        if (cmd != oldcmd)
                data = (caddr_t)&term;
 #endif
@@ -1628,13 +1675,16 @@ sioioctl(struct dev_ioctl_args *ap)
        }
        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data,
                                              ap->a_fflag, ap->a_cred);
-       if (error != ENOIOCTL)
+       if (error != ENOIOCTL) {
+               lwkt_reltoken(&tty_token);
                return (error);
+       }
        crit_enter();
        error = ttioctl(tp, cmd, data, ap->a_fflag);
        disc_optim(tp, &tp->t_termios, com);
        if (error != ENOIOCTL) {
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return (error);
        }
        switch (cmd) {
@@ -1679,6 +1729,7 @@ sioioctl(struct dev_ioctl_args *ap)
                error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
                if (error != 0) {
                        crit_exit();
+                       lwkt_reltoken(&tty_token);
                        return (error);
                }
                com->dtr_wait = *(int *)data * hz / 100;
@@ -1696,9 +1747,11 @@ sioioctl(struct dev_ioctl_args *ap)
                break;
        default:
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return (ENOTTY);
        }
        crit_exit();
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -1707,11 +1760,14 @@ siopoll(void *data, void *frame)
 {
        int             unit;
 
+       lwkt_gettoken(&tty_token);
 #ifdef CyDebug
        ++cy_timeouts;
 #endif
-       if (com_events == 0)
+       if (com_events == 0) {
+               lwkt_reltoken(&tty_token);
                return;
+       }
 repeat:
        for (unit = 0; unit < NSIO; ++unit) {
                struct com_s    *com;
@@ -1789,6 +1845,7 @@ repeat:
        }
        if (com_events >= LOTS_OF_EVENTS)
                goto repeat;
+       lwkt_reltoken(&tty_token);
 }
 
 static int
@@ -1808,6 +1865,7 @@ comparam(struct tty *tp, struct termios *t)
        u_char          opt;
        int             unit;
 
+       lwkt_gettoken(&tty_token);
        /* do historical conversions */
        if (t->c_ispeed == 0)
                t->c_ispeed = t->c_ospeed;
@@ -1818,11 +1876,15 @@ comparam(struct tty *tp, struct termios *t)
        /* check requested parameters */
        cy_clock = CY_CLOCK(com->gfrcr_image);
        idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler);
-       if (idivisor < 0)
+       if (idivisor < 0) {
+               lwkt_reltoken(&tty_token);
                return (EINVAL);
+       }
        odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler);
-       if (odivisor < 0)
+       if (odivisor < 0) {
+               lwkt_reltoken(&tty_token);
                return (EINVAL);
+       }
 
        /* parameters are OK, convert them to the com struct and the device */
        crit_enter();
@@ -2158,9 +2220,13 @@ comparam(struct tty *tp, struct termios *t)
                kfree(com->ibufold, M_DEVBUF);
                com->ibufold = NULL;
        }
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 siosetwater(struct com_s *com, speed_t speed)
 {
@@ -2169,6 +2235,8 @@ siosetwater(struct com_s *com, speed_t speed)
        int             ibufsize;
        struct tty      *tp;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
+
        /*
         * Make the buffer size large enough to handle a softtty interrupt
         * latency of about 2 ticks without loss of throughput or data
@@ -2237,6 +2305,7 @@ comstart(struct tty *tp)
        unit = DEV_TO_UNIT(tp->t_dev);
        com = com_addr(unit);
        crit_enter();
+       lwkt_gettoken(&tty_token);
 
 #ifdef CyDebug
        ++com->start_count;
@@ -2282,6 +2351,7 @@ comstart(struct tty *tp)
        enable_intr();
        if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
                ttwwakeup(tp);
+               lwkt_reltoken(&tty_token);
                crit_exit();
                return;
        }
@@ -2362,6 +2432,7 @@ comstart(struct tty *tp)
        enable_intr();
 #endif
        ttwwakeup(tp);
+       lwkt_reltoken(&tty_token);
        crit_exit();
 }
 
@@ -2371,6 +2442,7 @@ comstop(struct tty *tp, int rw)
        struct com_s    *com;
        bool_t          wakeup_etc;
 
+       lwkt_gettoken(&tty_token);
        com = com_addr(DEV_TO_UNIT(tp->t_dev));
        wakeup_etc = FALSE;
        disable_intr();
@@ -2402,14 +2474,20 @@ comstop(struct tty *tp, int rw)
        if (rw & FWRITE && com->etc == ETC_NONE)
                cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
        comstart(tp);
+       lwkt_reltoken(&tty_token);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 commctl(struct com_s *com, int bits, int how)
 {
        int     mcr;
        int     msr;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
+
        if (how == DMGET) {
                if (com->channel_control & CD1400_CCR_RCVEN)
                        bits |= TIOCM_LE;
@@ -2468,6 +2546,9 @@ commctl(struct com_s *com, int bits, int how)
        return (0);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 siosettimeout(void)
 {
@@ -2475,6 +2556,7 @@ siosettimeout(void)
        bool_t          someopen;
        int             unit;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        /*
         * Set our timeout period to 1 second if no polled devices are open.
         * Otherwise set it to max(1/200, 1/hz).
@@ -2514,6 +2596,7 @@ comwakeup(void *chan)
        struct com_s    *com;
        int             unit;
 
+       lwkt_gettoken(&tty_token);
        callout_reset(&sio_timeout_handle, sio_timeout, comwakeup, NULL);
 
 #if 0
@@ -2535,8 +2618,10 @@ comwakeup(void *chan)
        /*
         * Check for and log errors, but not too often.
         */
-       if (--sio_timeouts_until_log > 0)
+       if (--sio_timeouts_until_log > 0) {
+               lwkt_reltoken(&tty_token);
                return;
+       }
        sio_timeouts_until_log = hz / sio_timeout;
        for (unit = 0; unit < NSIO; ++unit) {
                int     errnum;
@@ -2560,6 +2645,7 @@ comwakeup(void *chan)
                            delta == 1 ? "" : "s", total);
                }
        }
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -2569,6 +2655,7 @@ disc_optim(struct tty *tp, struct termios *t, struct com_s *com)
        u_char  opt;
 #endif
 
+       lwkt_gettoken(&tty_token);
        /*
         * XXX can skip a lot more cases if Smarts.  Maybe
         * (IGNCR | ISTRIP | IXON) in c_iflag.  But perhaps we
@@ -2596,6 +2683,7 @@ disc_optim(struct tty *tp, struct termios *t, struct com_s *com)
                cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3);
        }
 #endif
+       lwkt_reltoken(&tty_token);
 }
 
 #ifdef Smarts
@@ -2654,14 +2742,21 @@ comspeed(speed_t speed, u_long cy_clock, int *prescaler_io)
        return (divider);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 cd1400_channel_cmd(struct com_s *com, int cmd)
 {
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        cd1400_channel_cmd_wait(com);
        cd_setreg(com, CD1400_CCR, cmd);
        cd1400_channel_cmd_wait(com);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 cd1400_channel_cmd_wait(struct com_s *com)
 {
@@ -2669,6 +2764,8 @@ cd1400_channel_cmd_wait(struct com_s *com)
        struct timeval  tv;
        long            usec;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
+
        if (cd_getreg(com, CD1400_CCR) == 0)
                return;
        microtime(&start);
@@ -2687,9 +2784,13 @@ cd1400_channel_cmd_wait(struct com_s *com)
        }
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 cd_etc(struct com_s *com, int etc)
 {
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        /*
         * We can't change the hardware's ETC state while there are any
         * characters in the tx fifo, since those characters would be
@@ -2726,6 +2827,9 @@ wait:
                continue;
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 cd_getreg(struct com_s *com, int reg)
 {
@@ -2736,6 +2840,8 @@ cd_getreg(struct com_s *com, int reg)
        cy_addr iobase;
        int     val;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
+
        basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
        car = com->unit & CD1400_CAR_CHAN;
        cy_align = com->cy_align;
@@ -2751,6 +2857,9 @@ cd_getreg(struct com_s *com, int reg)
        return (val);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 cd_setreg(struct com_s *com, int reg, int val)
 {
@@ -2760,6 +2869,8 @@ cd_setreg(struct com_s *com, int reg, int val)
        u_long  ef;
        cy_addr iobase;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
+
        basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
        car = com->unit & CD1400_CAR_CHAN;
        cy_align = com->cy_align;
@@ -2791,6 +2902,7 @@ cystatus(int unit)
        kprintf("calls to upper layer:\t\t%d\n", cy_timeouts);
        if (com == NULL)
                return;
+       lwkt_gettoken(&tty_token);
        iobase = com->iobase;
        kprintf("\n");
        kprintf("cd1400 base address:\\tt%p\n", iobase);
@@ -2829,7 +2941,9 @@ cystatus(int unit)
                kprintf(
                "upper layer queue lengths:\t%d raw, %d canon, %d output\n",
                       tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc);
-       } else
+       } else {
                kprintf("tty state:\t\t\tclosed\n");
+       }
+       lwkt_reltoken(&tty_token);
 }
 #endif /* CyDebug */
index 5313364..69cacce 100644 (file)
@@ -107,7 +107,7 @@ cy_attach(pcici_t config_id, int unit)
         *      the unit number as the token even for PCI.
         */
        if (!pci_map_int_right(config_id, (pci_inthand_t *)cyintr,
-                              (void *)adapter, 0)) {
+                              (void *)adapter, INTR_MPSAFE)) {
                kprintf("cy%d: couldn't map interrupt\n", unit);
                goto fail;
        }
index 88912c2..90e8dfc 100644 (file)
@@ -464,6 +464,7 @@ dgmprobe(device_t dev)
        if (sc->io_res == NULL)
                return (ENXIO);
 
+       lwkt_gettoken(&tty_token);
        outb(sc->port, FEPRST);
        sc->enabled = 0;
 
@@ -480,6 +481,7 @@ dgmprobe(device_t dev)
        if (!sc->enabled) {
                DPRINT2(DB_EXCEPT, "dgm%d: failed to respond\n", sc->unit);
                bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
        }
 
@@ -506,6 +508,7 @@ dgmprobe(device_t dev)
        if (sc->mem_res == NULL) {
                device_printf(dev, "0x%lx: Memory range is in use\n", sc->pmem);
                bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
        }
 
@@ -520,6 +523,7 @@ dgmprobe(device_t dev)
 
        DPRINT2(DB_INFO, "dgm%d: Probe returns 0\n", sc->unit);
 
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -539,7 +543,8 @@ dgmattach(device_t dev)
 
        DPRINT2(DB_INFO, "dbg%d: attaching\n", device_get_unit(dev));
 
-       callout_init(&sc->toh);
+       lwkt_gettoken(&tty_token);
+       callout_init_mp(&sc->toh);
        sc->unit = device_get_unit(dev);
        bus_get_resource(dev, SYS_RES_IOPORT, 0, &sc->port, &iosize);
        bus_get_resource(dev, SYS_RES_MEMORY, 0, &sc->pmem, &msize);
@@ -554,14 +559,17 @@ dgmattach(device_t dev)
        sc->iorid = 0;
        sc->io_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->iorid,
            0ul, ~0ul, iosize, RF_ACTIVE);
-       if (sc->io_res == NULL)
+       if (sc->io_res == NULL) {
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
+       }
        sc->mrid = 0;
        sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mrid,
            0ul, ~0ul, msize, RF_ACTIVE);
        if (sc->mem_res == NULL) {
                device_printf(dev, "0x%lx: Memory range is in use\n", sc->pmem);
                bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
        }
 
@@ -582,6 +590,7 @@ dgmattach(device_t dev)
                        hidewin(sc);
                        bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                        bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+                       lwkt_reltoken(&tty_token);
                        return (ENXIO);
                }
                DELAY(1);
@@ -606,6 +615,7 @@ dgmattach(device_t dev)
                hidewin(sc);
                bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
        }
 
@@ -619,6 +629,7 @@ dgmattach(device_t dev)
                hidewin(sc);
                bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
        }
 
@@ -648,6 +659,7 @@ dgmattach(device_t dev)
                        hidewin(sc);
                        bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                        bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+                       lwkt_reltoken(&tty_token);
                        return (ENXIO);
                }
        }
@@ -666,6 +678,7 @@ dgmattach(device_t dev)
                        hidewin(sc);
                        bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                        bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+                       lwkt_reltoken(&tty_token);
                        return (ENXIO);
                }
        }
@@ -687,6 +700,7 @@ dgmattach(device_t dev)
                        hidewin(sc);
                        bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                        bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+                       lwkt_reltoken(&tty_token);
                        return (ENXIO);
                }
        }
@@ -697,6 +711,7 @@ dgmattach(device_t dev)
                hidewin(sc);
                bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
        }
        kprintf(", DigiBIOS running\n");
@@ -716,6 +731,7 @@ dgmattach(device_t dev)
                        hidewin(sc);
                        bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                        bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+                       lwkt_reltoken(&tty_token);
                        return (ENXIO);
                }
        }
@@ -735,6 +751,7 @@ dgmattach(device_t dev)
                        hidewin(sc);
                        bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                        bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+                       lwkt_reltoken(&tty_token);
                        return (ENXIO);
                }
        }
@@ -745,6 +762,7 @@ dgmattach(device_t dev)
                hidewin(sc);
                bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
        }
        kprintf(", FEP/OS running\n");
@@ -758,6 +776,7 @@ dgmattach(device_t dev)
                hidewin(sc);
                bus_release_resource(dev, SYS_RES_MEMORY, sc->mrid, sc->mem_res);
                bus_release_resource(dev, SYS_RES_IOPORT, sc->iorid, sc->io_res);
+               lwkt_reltoken(&tty_token);
                return (ENXIO);
        }
 
@@ -769,8 +788,8 @@ dgmattach(device_t dev)
        DPRINT3(DB_INFO, "dgm%d: enable %d ports\n", sc->unit, sc->numports);
        for (i = 0; i < sc->numports; i++) {
                sc->ports[i].enabled = 1;
-               callout_init(&sc->ports[i].hc_timeout);
-               callout_init(&sc->ports[i].wf_timeout);
+               callout_init_mp(&sc->ports[i].hc_timeout);
+               callout_init_mp(&sc->ports[i].wf_timeout);
        }
 
        /* We should now init per-port structures */
@@ -881,6 +900,7 @@ dgmattach(device_t dev)
 
        DPRINT2(DB_INFO, "dgm%d: poll thread started\n", sc->unit);
 
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -890,9 +910,13 @@ dgmdetach(device_t dev)
        struct dgm_softc *sc = device_get_softc(dev);
        int i;
 
-       for (i = 0; i < sc->numports; i++)
-               if (sc->ttys[i].t_state & TS_ISOPEN)
+       lwkt_gettoken(&tty_token);
+       for (i = 0; i < sc->numports; i++) {
+               if (sc->ttys[i].t_state & TS_ISOPEN) {
+                       lwkt_reltoken(&tty_token);
                        return (EBUSY);
+               }
+       }
 
        DPRINT2(DB_INFO, "dgm%d: detach\n", sc->unit);
 
@@ -916,6 +940,7 @@ dgmdetach(device_t dev)
                sc->vmem = NULL;
        }
 
+       lwkt_reltoken(&tty_token);
        return (0);
 }
 
@@ -945,6 +970,7 @@ dgmopen(struct dev_open_args *ap)
        int error;
        volatile struct board_chan *bc;
 
+       lwkt_gettoken(&tty_token);
        error = 0;
        mynor = minor(dev);
        unit = MINOR_TO_UNIT(mynor);
@@ -954,6 +980,7 @@ dgmopen(struct dev_open_args *ap)
        if (sc == NULL) {
                DPRINT2(DB_EXCEPT, "dgm%d: try to open a nonexisting card\n",
                    unit);
+               lwkt_reltoken(&tty_token);
                return ENXIO;
        }
 
@@ -962,17 +989,21 @@ dgmopen(struct dev_open_args *ap)
        if (!sc->enabled) {
                DPRINT2(DB_EXCEPT, "dgm%d: try to open a disabled card\n",
                    unit);
+               lwkt_reltoken(&tty_token);
                return ENXIO;
        }
 
        if (pnum >= sc->numports) {
                DPRINT3(DB_EXCEPT, "dgm%d: try to open non-existing port %d\n",
                    unit, pnum);
+               lwkt_reltoken(&tty_token);
                return ENXIO;
        }
 
-       if (mynor & CONTROL_MASK)
+       if (mynor & CONTROL_MASK) {
+               lwkt_reltoken(&tty_token);
                return 0;
+       }
 
        tp = &sc->ttys[pnum];
        dev->si_tty = tp;
@@ -1109,6 +1140,7 @@ out:
        DPRINT4(DB_OPEN, "dgm%d: port%d: open() returns %d\n",
            unit, pnum, error);
 
+       lwkt_reltoken(&tty_token);
        return error;
 }
 
@@ -1127,6 +1159,8 @@ dgmclose(struct dev_close_args *ap)
        mynor = minor(dev);
        if (mynor & CONTROL_MASK)
                return 0;
+
+       lwkt_gettoken(&tty_token);
        unit = MINOR_TO_UNIT(mynor);
        pnum = MINOR_TO_PORT(mynor);
 
@@ -1170,15 +1204,20 @@ dgmclose(struct dev_close_args *ap)
 
        DPRINT3(DB_CLOSE, "dgm%d: port%d: close exit\n", unit, pnum);
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 dgmhardclose(struct dgm_p *port)
 {
        volatile struct board_chan *bc = port->brdchan;
        struct dgm_softc *sc;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        sc = devclass_get_softc(dgmdevclass, port->sc->unit);
        DPRINT2(DB_INFO, "dgm%d: dgmhardclose\n", sc->unit);
        crit_enter();
@@ -1203,7 +1242,9 @@ dgmhardclose(struct dgm_p *port)
 static void
 dgm_pause(void *chan)
 {
+       lwkt_gettoken(&tty_token);
        wakeup((caddr_t)chan);
+       lwkt_reltoken(&tty_token);
 }
 
 static void
@@ -1226,11 +1267,13 @@ dgmpoll(void *unit_c)
        int ibuf_full, obuf_full;
        BoardMemWinState ws = bmws_get();
 
+       lwkt_gettoken(&tty_token);
        sc = devclass_get_softc(dgmdevclass, unit);
        DPRINT2(DB_INFO, "dgm%d: poll\n", sc->unit);
 
        if (!sc->enabled) {
                kprintf("dgm%d: polling of disabled board stopped\n", unit);
+               lwkt_reltoken(&tty_token);
                return;
        }
 
@@ -1481,6 +1524,7 @@ dgmpoll(void *unit_c)
        callout_reset(&sc->toh, hz / POLLSPERSEC, dgmpoll, unit_c);
 
        DPRINT2(DB_INFO, "dgm%d: poll done\n", sc->unit);
+       lwkt_reltoken(&tty_token);
 }
 
 static int
@@ -1498,6 +1542,7 @@ dgmioctl(struct dev_ioctl_args *ap)
        int error;
        int tiocm_xxx;
 
+       lwkt_gettoken(&tty_token);
 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
        u_long          oldcmd;
        struct termios  term;
@@ -1530,20 +1575,27 @@ dgmioctl(struct dev_ioctl_args *ap)
                switch (cmd) {
                case TIOCSETA:
                        error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
-                       if (error != 0)
+                       if (error != 0) {
+                               lwkt_reltoken(&tty_token);
                                return (error);
+                       }
                        *ct = *(struct termios *)data;
+                       lwkt_reltoken(&tty_token);
                        return (0);
                case TIOCGETA:
                        *(struct termios *)data = *ct;
+                       lwkt_reltoken(&tty_token);
                        return (0);
                case TIOCGETD:
                        *(int *)data = TTYDISC;
+                       lwkt_reltoken(&tty_token);
                        return (0);
                case TIOCGWINSZ:
                        bzero(data, sizeof(struct winsize));
+                       lwkt_reltoken(&tty_token);
                        return (0);
                default:
+                       lwkt_reltoken(&tty_token);
                        return (ENOTTY);
                }
        }
@@ -1555,8 +1607,10 @@ dgmioctl(struct dev_ioctl_args *ap)
        }
        oldcmd = cmd;
        error = ttsetcompat(tp, &cmd, data, &term);
-       if (error != 0)
+       if (error != 0) {
+               lwkt_reltoken(&tty_token);
                return (error);
+       }
        if (cmd != oldcmd)
                data = (caddr_t)&term;
 #endif
@@ -1591,6 +1645,7 @@ dgmioctl(struct dev_ioctl_args *ap)
                fepcmd(port, PAUSETX, 0, 0, 0, 0);
                bmws_set(ws);
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return 0;
        } else if (cmd == TIOCSTART) {
                crit_enter();
@@ -1598,6 +1653,7 @@ dgmioctl(struct dev_ioctl_args *ap)
                fepcmd(port, RESUMETX, 0, 0, 0, 0);
                bmws_set(ws);
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return 0;
        }
 
@@ -1606,8 +1662,10 @@ dgmioctl(struct dev_ioctl_args *ap)
 
        error = linesw[tp->t_line].l_ioctl(tp, cmd, data,
                                           ap->a_fflag, ap->a_cred);
-       if (error != ENOIOCTL)
+       if (error != ENOIOCTL) {
+               lwkt_reltoken(&tty_token);
                return error;
+       }
        crit_enter();
        error = ttioctl(tp, cmd, data, ap->a_fflag);
        disc_optim(tp, &tp->t_termios);
@@ -1617,6 +1675,7 @@ dgmioctl(struct dev_ioctl_args *ap)
                if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
                        DPRINT6(DB_PARAM, "dgm%d: port%d: dgmioctl-RES c = 0x%x i = 0x%x l = 0x%x\n", unit, pnum, tp->t_cflag, tp->t_iflag, tp->t_lflag);
                }
+               lwkt_reltoken(&tty_token);
                return error;
        }
 
@@ -1627,6 +1686,7 @@ dgmioctl(struct dev_ioctl_args *ap)
 
                if (error != 0) {
                        crit_exit();
+                       lwkt_reltoken(&tty_token);
                        return error;
                }
 #endif
@@ -1755,6 +1815,7 @@ dgmioctl(struct dev_ioctl_args *ap)
                error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
                if (error != 0) {
                        crit_exit();
+                       lwkt_reltoken(&tty_token);
                        return (error);
                }
                port->close_delay = *(int *)data * hz / 100;
@@ -1773,11 +1834,13 @@ dgmioctl(struct dev_ioctl_args *ap)
        default:
                bmws_set(ws);
                crit_exit();
+               lwkt_reltoken(&tty_token);
                return ENOTTY;
        }
        bmws_set(ws);
        crit_exit();
 
+       lwkt_reltoken(&tty_token);
        return 0;
 }
 
@@ -1786,11 +1849,15 @@ wakeflush(void *p)
 {
        struct dgm_p *port = p;
 
+       lwkt_gettoken(&tty_token);
        wakeup(&port->draining);
+       lwkt_reltoken(&tty_token);
 }
 
 /* wait for the output to drain */
-
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 dgmdrain(struct dgm_p *port)
 {
@@ -1800,6 +1867,7 @@ dgmdrain(struct dgm_p *port)
        int head, tail;
        BoardMemWinState ws = bmws_get();
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        sc = devclass_get_softc(dgmdevclass, port->sc->unit);
 
        setwin(sc, 0);
@@ -1839,7 +1907,9 @@ dgmdrain(struct dgm_p *port)
 
 /* wait for the output to drain */
 /* or simply clear the buffer it it's stopped */
-
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 dgm_drain_or_flush(struct dgm_p *port)
 {
@@ -1850,6 +1920,7 @@ dgm_drain_or_flush(struct dgm_p *port)
        int lasttail;
        int head, tail;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        sc = devclass_get_softc(dgmdevclass, port->sc->unit);
        setwin(sc, 0);
 
@@ -1913,6 +1984,7 @@ dgmparam(struct tty *tp, struct termios *t)
        int hflow;
        BoardMemWinState ws = bmws_get();
 
+       lwkt_gettoken(&tty_token);
        sc = devclass_get_softc(dgmdevclass, unit);
        port = &sc->ports[pnum];
        bc = port->brdchan;
@@ -1931,6 +2003,7 @@ dgmparam(struct tty *tp, struct termios *t)
 
        if (cflag < 0 /* || cflag > 0 && t->c_ispeed != t->c_ospeed */) {
                DPRINT4(DB_PARAM, "dgm%d: port%d: invalid cflag = 0%o\n", unit, pnum, cflag);
+               lwkt_reltoken(&tty_token);
                return (EINVAL);
        }
 
@@ -1990,6 +2063,7 @@ dgmparam(struct tty *tp, struct termios *t)
        bmws_set(ws);
        crit_exit();
 
+       lwkt_reltoken(&tty_token);
        return 0;
 
 }
@@ -2006,6 +2080,7 @@ dgmstart(struct tty *tp)
        int size, ocount;
        int wmask;
 
+       lwkt_gettoken(&tty_token);
        BoardMemWinState ws = bmws_get();
 
        unit = MINOR_TO_UNIT(minor(tp->t_dev));
@@ -2067,6 +2142,7 @@ dgmstart(struct tty *tp)
                        bmws_set(ws);
                        tp->t_state |= TS_BUSY;
                        crit_exit();
+                       lwkt_reltoken(&tty_token);
                        return;
                }
 
@@ -2102,6 +2178,7 @@ dgmstart(struct tty *tp)
        }
        tp->t_state& = ~TS_BUSY;
 #endif
+       lwkt_reltoken(&tty_token);
 }
 
 void
@@ -2113,6 +2190,7 @@ dgmstop(struct tty *tp, int rw)
        struct dgm_softc *sc;
        volatile struct board_chan *bc;
 
+       lwkt_gettoken(&tty_token);
        BoardMemWinState ws = bmws_get();
 
        unit = MINOR_TO_UNIT(minor(tp->t_dev));
@@ -2142,8 +2220,12 @@ dgmstop(struct tty *tp, int rw)
        bmws_set(ws);
        crit_exit();
        dgmstart(tp);
+       lwkt_reltoken(&tty_token);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static void
 fepcmd(struct dgm_p *port,
        unsigned cmd,
@@ -2156,6 +2238,7 @@ fepcmd(struct dgm_p *port,
        unsigned tail, head;
        int count, n;
 
+       ASSERT_LWKT_TOKEN_HELD(&tty_token);
        KASSERT(port->sc, ("Couldn't (re)obtain driver softc"));
        mem = port->sc->vmem;
 
@@ -2206,6 +2289,7 @@ fepcmd(struct dgm_p *port,
 static void
 disc_optim(struct tty *tp, struct termios *t)
 {
+       lwkt_gettoken(&tty_token);
        if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
            && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
            && (!(t->c_iflag & PARMRK)
@@ -2215,4 +2299,5 @@ disc_optim(struct tty *tp, struct termios *t)
                tp->t_state |= TS_CAN_BYPASS_L_RINT;
        else
                tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
+       lwkt_reltoken(&tty_token);
 }
index 3dddc47..eac99ce 100644 (file)
@@ -1,4 +1,6 @@
 /*-
+ * (MPSAFE)
+ *
  * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
  *   based on work by Slawa Olhovchenkov
  *                    John Prince <johnp@knight-trosoft.com>
@@ -163,7 +165,7 @@ digi_poll(void *ptr)
        struct digi_softc *sc;
 
        sc = (struct digi_softc *)ptr;
-       callout_init(&sc->callout);
+       callout_init_mp(&sc->callout);
        digi_intr(sc);
        callout_reset(&sc->callout, (hz >= 200) ? hz / 100 : 1, digi_poll, sc);
 }
@@ -173,7 +175,7 @@ digi_int_test(void *v)
 {
        struct digi_softc *sc = v;
 
-       callout_init(&sc->inttest);
+       callout_init_mp(&sc->inttest);
 #ifdef DIGI_INTERRUPT
        if (sc->intr_timestamp.tv_sec || sc->intr_timestamp.tv_usec) {
                /* interrupt OK! */
@@ -228,6 +230,9 @@ digi_delay(struct digi_softc *sc, const char *txt, u_long timo)
                tsleep(sc, PCATCH, txt, timo);
 }
 
+/*
+ * NOTE: Must be called with tty_token held
+ */
 static int
 digi_init(struct digi_softc *sc)
 {
@@ -237,6 +242,7 @@ digi_init(struct digi_softc *sc)
        s