Module Name: src Committed By: jmcneill Date: Sun Dec 11 22:34:42 UTC 2011
Modified Files: src/sys/arch/usermode/conf: majors.usermode src/sys/arch/usermode/dev: ttycons.c Log Message: make ttycons a proper tty device, now it can be the console To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/arch/usermode/conf/majors.usermode cvs rdiff -u -r1.7 -r1.8 src/sys/arch/usermode/dev/ttycons.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/usermode/conf/majors.usermode diff -u src/sys/arch/usermode/conf/majors.usermode:1.3 src/sys/arch/usermode/conf/majors.usermode:1.4 --- src/sys/arch/usermode/conf/majors.usermode:1.3 Thu Aug 25 11:06:29 2011 +++ src/sys/arch/usermode/conf/majors.usermode Sun Dec 11 22:34:42 2011 @@ -1,4 +1,4 @@ -# $NetBSD: majors.usermode,v 1.3 2011/08/25 11:06:29 jmcneill Exp $ +# $NetBSD: majors.usermode,v 1.4 2011/12/11 22:34:42 jmcneill Exp $ device-major cons char 0 device-major ctty char 1 @@ -12,3 +12,4 @@ device-major com char 8 com device-major md char 24 block 17 md device-major wsdisplay char 47 wsdisplay device-major ld char 69 block 19 ld +device-major ttycons char 159 ttycons Index: src/sys/arch/usermode/dev/ttycons.c diff -u src/sys/arch/usermode/dev/ttycons.c:1.7 src/sys/arch/usermode/dev/ttycons.c:1.8 --- src/sys/arch/usermode/dev/ttycons.c:1.7 Sun Dec 11 20:43:03 2011 +++ src/sys/arch/usermode/dev/ttycons.c Sun Dec 11 22:34:42 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ttycons.c,v 1.7 2011/12/11 20:43:03 jmcneill Exp $ */ +/* $NetBSD: ttycons.c,v 1.8 2011/12/11 22:34:42 jmcneill Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,13 +27,16 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ttycons.c,v 1.7 2011/12/11 20:43:03 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ttycons.c,v 1.8 2011/12/11 22:34:42 jmcneill Exp $"); #include <sys/param.h> +#include <sys/conf.h> #include <sys/proc.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/kauth.h> #include <sys/termios.h> +#include <sys/tty.h> #include <dev/cons.h> @@ -45,9 +48,11 @@ static void ttycons_attach(device_t, dev void ttycons_consinit(void); -typedef struct ttycons_softc { +struct ttycons_softc { device_t sc_dev; -} ttycons_softc_t; + struct tty *sc_tty; + void *sc_rd_sih; +}; dev_type_cngetc(ttycons_cngetc); dev_type_cnputc(ttycons_cnputc); @@ -62,9 +67,39 @@ struct consdev ttycons_consdev = { .cn_pri = CN_NORMAL, }; -CFATTACH_DECL_NEW(ttycons, sizeof(ttycons_softc_t), +CFATTACH_DECL_NEW(ttycons, sizeof(struct ttycons_softc), ttycons_match, ttycons_attach, NULL, NULL); +extern struct cfdriver ttycons_cd; + +dev_type_open(ttycons_open); +dev_type_close(ttycons_close); +dev_type_read(ttycons_read); +dev_type_write(ttycons_write); +dev_type_ioctl(ttycons_ioctl); +dev_type_stop(ttycons_stop); +dev_type_tty(ttycons_tty); +dev_type_poll(ttycons_poll); + +const struct cdevsw ttycons_cdevsw = { + .d_open = ttycons_open, + .d_close = ttycons_close, + .d_read = ttycons_read, + .d_write = ttycons_write, + .d_ioctl = ttycons_ioctl, + .d_stop = ttycons_stop, + .d_tty = ttycons_tty, + .d_poll = ttycons_poll, + .d_kqfilter = ttykqfilter, + .d_flag = D_TTY, +}; + +static void ttycons_start(struct tty *); +static int ttycons_param(struct tty *, struct termios *); + +static void ttycons_intr(int); +static void ttycons_softintr(void *); + static int ttycons_match(device_t parent, cfdata_t match, void *opaque) { @@ -79,12 +114,28 @@ ttycons_match(device_t parent, cfdata_t static void ttycons_attach(device_t parent, device_t self, void *opaque) { - ttycons_softc_t *sc = device_private(self); + struct ttycons_softc *sc = device_private(self); + int maj; aprint_naive("\n"); aprint_normal(": console\n"); sc->sc_dev = self; + sc->sc_tty = tty_alloc(); + tty_attach(sc->sc_tty); + sc->sc_tty->t_oproc = ttycons_start; + sc->sc_tty->t_param = ttycons_param; + + maj = cdevsw_lookup_major(&ttycons_cdevsw); + cn_tab->cn_dev = makedev(maj, device_unit(self)); + sc->sc_tty->t_dev = cn_tab->cn_dev; + + sc->sc_rd_sih = softint_establish(SOFTINT_SERIAL, + ttycons_softintr, sc); + if (sc->sc_rd_sih == NULL) + panic("couldn't establish ttycons softint handler\n"); + + thunk_signal(SIGIO, ttycons_intr); } void @@ -119,3 +170,187 @@ void ttycons_cnpollc(dev_t dev, int on) { } + +int +ttycons_open(dev_t dev, int flag, int mode, lwp_t *l) +{ + struct ttycons_softc *sc; + struct tty *t; + + sc = device_lookup_private(&ttycons_cd, minor(dev)); + if (sc == NULL) + return ENXIO; + t = sc->sc_tty; + + if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, t)) + return EBUSY; + + if ((t->t_state & TS_ISOPEN) == 0 && t->t_wopen == 0) { + t->t_dev = dev; + ttychars(t); + t->t_iflag = TTYDEF_IFLAG; + t->t_oflag = TTYDEF_OFLAG; + t->t_cflag = TTYDEF_CFLAG; + t->t_lflag = TTYDEF_LFLAG; + t->t_ispeed = t->t_ospeed = TTYDEF_SPEED; + ttycons_param(t, &t->t_termios); + ttsetwater(t); + } + t->t_state |= TS_CARR_ON; + + return t->t_linesw->l_open(dev, t); +} + +int +ttycons_close(dev_t dev, int flag, int mode, lwp_t *l) +{ + struct ttycons_softc *sc; + struct tty *t; + + sc = device_lookup_private(&ttycons_cd, minor(dev)); + t = sc->sc_tty; + + if (t == NULL) + return 0; + + t->t_linesw->l_close(t, flag); + ttyclose(t); + + return 0; +} + +int +ttycons_read(dev_t dev, struct uio *uio, int flag) +{ + struct ttycons_softc *sc; + struct tty *t; + + sc = device_lookup_private(&ttycons_cd, minor(dev)); + t = sc->sc_tty; + + return t->t_linesw->l_read(t, uio, flag); +} + +int +ttycons_write(dev_t dev, struct uio *uio, int flag) +{ + struct ttycons_softc *sc; + struct tty *t; + + sc = device_lookup_private(&ttycons_cd, minor(dev)); + t = sc->sc_tty; + + return t->t_linesw->l_write(t, uio, flag); +} + +int +ttycons_poll(dev_t dev, int events, lwp_t *l) +{ + struct ttycons_softc *sc; + struct tty *t; + + sc = device_lookup_private(&ttycons_cd, minor(dev)); + t = sc->sc_tty; + + return t->t_linesw->l_poll(t, events, l); +} + +struct tty * +ttycons_tty(dev_t dev) +{ + struct ttycons_softc *sc; + + sc = device_lookup_private(&ttycons_cd, minor(dev)); + + return sc->sc_tty; +} + +int +ttycons_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l) +{ + struct ttycons_softc *sc; + struct tty *t; + int error; + + sc = device_lookup_private(&ttycons_cd, minor(dev)); + t = sc->sc_tty; + + error = t->t_linesw->l_ioctl(t, cmd, data, flag, l); + if (error != EPASSTHROUGH) + return error; + + error = ttioctl(t, cmd, data, flag, l); + if (error != EPASSTHROUGH) + return error; + + return EPASSTHROUGH; +} + +static void +ttycons_start(struct tty *t) +{ + u_char buf[64+1]; + int s, len, i; + + s = spltty(); + if (t->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) { + splx(s); + return; + } + t->t_state |= TS_BUSY; + splx(s); + + len = q_to_b(&t->t_outq, buf, sizeof(buf) - 1); + for (i = 0; i < len; i++) { + thunk_putchar(buf[i]); + } + + s = spltty(); + t->t_state &= ~TS_BUSY; + if (ttypull(t)) { + t->t_state |= TS_TIMEOUT; + callout_schedule(&t->t_rstrt_ch, 1); + } + splx(s); +} + +void +ttycons_stop(struct tty *t, int flag) +{ +} + +static int +ttycons_param(struct tty *t, struct termios *c) +{ + t->t_ispeed = c->c_ispeed; + t->t_ospeed = c->c_ospeed; + t->t_cflag = c->c_cflag; + return 0; +} + +static void +ttycons_intr(int sig) +{ + struct ttycons_softc *sc; + + sc = device_lookup_private(&ttycons_cd, minor(cn_tab->cn_dev)); + if (sc == NULL) + return; + + softint_schedule(sc->sc_rd_sih); +} + +static void +ttycons_softintr(void *priv) +{ + struct ttycons_softc *sc = priv; + struct tty *t = sc->sc_tty; + unsigned char ch; + int c; + + while ((c = thunk_pollchar()) >= 0) { + ch = (unsigned char)c; + cn_check_magic(t->t_dev, ch, ttycons_cnm_state); + t->t_linesw->l_rint(ch, t); + } +}