From d85adca51f2910b6d47f7901406b6f7799406d47 Mon Sep 17 00:00:00 2001 From: eeh Date: Wed, 1 Nov 2000 23:51:38 +0000 Subject: [PATCH] Make line disciplines modular so they can be added or removed dynamically. --- sys/kern/tty.c | 56 ++++++++-- sys/kern/tty_conf.c | 265 +++++++++++++++++++++++++++++--------------- sys/kern/tty_pty.c | 18 +-- sys/kern/tty_tb.c | 4 +- 4 files changed, 233 insertions(+), 110 deletions(-) diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 46dcae987a26..1bfc17dacaaa 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty.c,v 1.120 2000/06/27 17:41:41 mrg Exp $ */ +/* $NetBSD: tty.c,v 1.121 2000/11/01 23:51:38 eeh Exp $ */ /*- * Copyright (c) 1982, 1986, 1990, 1991, 1993 @@ -749,6 +749,7 @@ ttioctl(tp, cmd, data, flag, p) case TIOCSTART: case TIOCSETA: case TIOCSETD: + case TIOCSLINED: case TIOCSETAF: case TIOCSETAW: #ifdef notdef @@ -833,7 +834,13 @@ ttioctl(tp, cmd, data, flag, p) break; } case TIOCGETD: /* get line discipline */ - *(int *)data = tp->t_line; + *(int *)data = (tp->t_linesw) ? tp->t_linesw->l_no : 0; + break; + case TIOCGLINED: + if (!tp->t_linesw) + return (EIO); + strncpy((char *)data, tp->t_linesw->l_name, + TTLINEDNAMELEN); break; case TIOCGWINSZ: /* get window size */ *(struct winsize *)data = tp->t_winsize; @@ -928,20 +935,50 @@ ttioctl(tp, cmd, data, flag, p) } case TIOCSETD: { /* set line discipline */ int t = *(int *)data; + struct linesw *lp; dev_t device = tp->t_dev; if ((u_int)t >= nlinesw) return (ENXIO); - if (t != tp->t_line) { + lp = linesw[t]; + if (lp != tp->t_linesw) { s = spltty(); - (*linesw[tp->t_line].l_close)(tp, flag); - error = (*linesw[t].l_open)(device, tp); + if (tp->t_linesw) + (*tp->t_linesw->l_close)(tp, flag); + error = (*lp->l_open)(device, tp); if (error) { - (void)(*linesw[tp->t_line].l_open)(device, tp); + (void)(*tp->t_linesw->l_open)(device, tp); splx(s); return (error); } - tp->t_line = t; + tp->t_linesw = lp; + splx(s); + } + break; + } + case TIOCSLINED: { /* set line discipline */ + char *name = (char *)data; + struct linesw *lp; + dev_t device = tp->t_dev; + + /* Null terminate to prevent buffer overflow */ + data[TTLINEDNAMELEN] = 0; + lp = ttyldisc_lookup(name); + + if (!lp) + return (ENXIO); + + if (lp != tp->t_linesw) { + s = spltty(); + if (tp->t_linesw) + (*tp->t_linesw->l_close)(tp, flag); + error = (*lp->l_open)(device, tp); + if (error) { + (void)(*tp->t_linesw->l_open)(device, tp); + splx(s); + return (error); + } + tp->t_linesw = lp; splx(s); } break; @@ -961,7 +998,7 @@ ttioctl(tp, cmd, data, flag, p) return (EPERM); if (p->p_ucred->cr_uid && !isctty(p, tp)) return (EACCES); - (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp); + (*tp->t_linesw->l_rint)(*(u_char *)data, tp); break; case TIOCSTOP: /* stop output, like ^S */ s = spltty(); @@ -2127,6 +2164,7 @@ ttysleep(tp, chan, pri, wmesg, timo) void tty_init() { + ttyldisc_init(); TAILQ_INIT(&ttylist); tty_count = 0; @@ -2189,6 +2227,8 @@ ttymalloc() clalloc(&tp->t_canq, 1024, 1); /* output queue doesn't need quoting */ clalloc(&tp->t_outq, 1024, 0); + /* Set default line discipline. */ + tp->t_linesw = linesw[0]; return(tp); } diff --git a/sys/kern/tty_conf.c b/sys/kern/tty_conf.c index 8bf978882d98..7b4680e844b1 100644 --- a/sys/kern/tty_conf.c +++ b/sys/kern/tty_conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty_conf.c,v 1.27 2000/09/22 01:37:27 eeh Exp $ */ +/* $NetBSD: tty_conf.c,v 1.28 2000/11/01 23:51:39 eeh Exp $ */ /*- * Copyright (c) 1982, 1986, 1991, 1993 @@ -49,15 +49,10 @@ #include #include #include +#include +#include #include - -#define ttynodisc ((int (*) __P((dev_t, struct tty *)))enodev) -#define ttyerrclose ((int (*) __P((struct tty *, int flags)))enodev) -#define ttyerrio ((int (*) __P((struct tty *, struct uio *, int)))enodev) -#define ttyerrinput ((int (*) __P((int c, struct tty *)))enodev) -#define ttyerrstart ((int (*) __P((struct tty *)))enodev) - -int nullioctl __P((struct tty *, u_long, caddr_t, int, struct proc *)); +#include #include "tb.h" #if NTB > 0 @@ -101,102 +96,47 @@ int stripinput __P((int c, struct tty *tp)); int stripstart __P((struct tty *tp)); #endif -/* - * XXXXXX - * - * The implementation for the following is currently in - * sys/dev/sun. I expect it will be moved out of there - * eventually, but until then add yourself to the list if - * you want to use the Sun Keyboard or Mouse line disciplines. - */ -#if defined(__sparc__) || defined(__sparc_v9__) || defined(sun3) || defined(sun3x) -#include "kbd.h" -#if NKBD > 0 -int sunkbdinput __P((int c, struct tty *tp)); -int sunkbdstart __P((struct tty *tp)); -int sunkbdstart __P((struct tty *tp)); -#endif - -#include "ms.h" -#if NMS > 0 -int sunmsinput __P((int c, struct tty *tp)); -#endif -#endif - -struct linesw linesw[] = -{ - { ttylopen, ttylclose, ttread, ttwrite, nullioctl, - ttyinput, ttstart, ttymodem }, /* 0- termios */ - - { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, - ttyerrinput, ttyerrstart, nullmodem }, /* 1- defunct */ +struct linesw termios_disc = + { "termios", 0, ttylopen, ttylclose, ttread, ttwrite, nullioctl, + ttyinput, ttstart, ttymodem }; /* 0- termios */ +struct linesw defunct_disc = + { "defunct", 1, ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, + ttyerrinput, ttyerrstart, nullmodem }; /* 1- defunct */ #if defined(COMPAT_43) || defined(COMPAT_FREEBSD) - { ttylopen, ttylclose, ttread, ttwrite, nullioctl, - ttyinput, ttstart, ttymodem }, /* 2- old NTTYDISC */ -#else - { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, - ttyerrinput, ttyerrstart, nullmodem }, /* 2- defunct */ +struct linesw ntty_disc = + { "ntty", 2, ttylopen, ttylclose, ttread, ttwrite, nullioctl, + ttyinput, ttstart, ttymodem }; /* 2- old NTTYDISC */ #endif - #if NTB > 0 - { tbopen, tbclose, tbread, ttyerrio, tbtioctl, - tbinput, ttstart, nullmodem }, /* 3- TABLDISC */ -#else - { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, - ttyerrinput, ttyerrstart, nullmodem }, +struct linesw table_disc = + { "table", 3, tbopen, tbclose, tbread, ttyerrio, tbtioctl, + tbinput, ttstart, nullmodem }; /* 3- TABLDISC */ #endif - #if NSL > 0 - { slopen, slclose, ttyerrio, ttyerrio, sltioctl, - slinput, slstart, nullmodem }, /* 4- SLIPDISC */ -#else - { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, - ttyerrinput, ttyerrstart, nullmodem }, +struct linesw slip_disc = + { "slip", 4, slopen, slclose, ttyerrio, ttyerrio, sltioctl, + slinput, slstart, nullmodem }; /* 4- SLIPDISC */ #endif - #if NPPP > 0 - { pppopen, pppclose, pppread, pppwrite, ppptioctl, - pppinput, pppstart, ttymodem }, /* 5- PPPDISC */ -#else - { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, - ttyerrinput, ttyerrstart, nullmodem }, +struct linesw ppp_disc = + { "ppp", 5, pppopen, pppclose, pppread, pppwrite, ppptioctl, + pppinput, pppstart, ttymodem }; /* 5- PPPDISC */ #endif - #if NSTRIP > 0 - { stripopen, stripclose, ttyerrio, ttyerrio, striptioctl, - stripinput, stripstart, nullmodem }, /* 6- STRIPDISC */ -#else - { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, - ttyerrinput, ttyerrstart, nullmodem }, +struct linesw strip_disc = + { "strip", 6, stripopen, stripclose, ttyerrio, ttyerrio, striptioctl, + stripinput, stripstart, nullmodem }; /* 6- STRIPDISC */ #endif /* - * The following are special line disciplines for Sun style Keybaords and Mice. - * Since they are used to handle special hardware they are enabled if/when the - * hardware is detected and you cannot switch in or out of them by normal means. - * - * All I/O currently goes through the keyboard and mouse device nodes so the - * TTY does no I/O itself. + * Registered line disciplines. Don't use this + * it will go away. */ -#if NKBD > 0 - { ttylopen, ttylclose, ttyerrio, ttyerrio, nullioctl, - sunkbdinput, sunkbdstart, nullmodem }, /* 7- SUNKBDDISC */ -#else - { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, - ttyerrinput, ttyerrstart, nullmodem }, -#endif - -#if NMS > 0 - { ttylopen, ttylclose, ttyerrio, ttyerrio, nullioctl, - sunmsinput, ttstart, nullmodem }, /* 8- SUNMOUSEDISC */ -#else - { ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, - ttyerrinput, ttyerrstart, nullmodem }, -#endif -}; - -int nlinesw = sizeof(linesw) / sizeof(linesw[0]); +#define LSWITCHBRK 20 +struct linesw **linesw = NULL; +int nlinesw = 0; +int slinesw = 0; /* * Do nothing specific version of line @@ -217,3 +157,146 @@ nullioctl(tp, cmd, data, flags, p) #endif return (-1); } + +/* + * Register a line discipline, optionally providing a + * specific discipline number for compatibility, -1 allocates + * a new one. Returns a discipline number, or -1 on + * failure. + */ +int +ttyldisc_add(disc, no) + struct linesw *disc; + int no; +{ + + /* You are not allowed to exceed TTLINEDNAMELEN */ + if (strlen(disc->l_name) > TTLINEDNAMELEN) + return (-1); + + /* + * You are not allowed to specify a line switch + * compatibility number greater than 10. + */ + if (no > 10) + return (-1); + + if (linesw == NULL) + panic("adding uninitialized linesw"); + + if (no == -1) { + /* Hunt for any slot */ + + for (no = slinesw; no-->0; ) + if (linesw[no] == NULL) break; + /* if no == -1 we should realloc linesw. */ + } + + /* Need a specific slot */ + if (linesw[no] != NULL) + return (-1); + + linesw[no] = disc; + disc->l_no = no; + + /* Define size of table */ + if (no >= nlinesw) + nlinesw = no + 1; + + return (no); +} + +/* + * Remove a line discipline by its name. Returns the + * discipline on success or NULL on failure. + */ + +struct linesw * +ttyldisc_remove(name) + char *name; +{ + struct linesw *disc; + int i; + + if (linesw == NULL) + panic("removing uninitialized linesw"); + + for (i=0; il_name) == 0)) { + disc = linesw[i]; + linesw[i] = NULL; + + if (nlinesw == i + 1) { + /* Need to fix up array sizing */ + while (i && (linesw[i] != NULL)) + i--; + nlinesw = i + i; + } + return (disc); + } + } + return (NULL); +} + +/* + * Look up a line discipline by its name. + */ + +struct linesw * +ttyldisc_lookup(name) + char *name; +{ + int i; + + for (i=0; il_name) == 0)) + return (linesw[i]); + return (NULL); +} + +#define TTYLDISCINIT(s, v) \ + do { \ + if (ttyldisc_add(&(s), (v)) != (v)) \ + panic(__CONCAT("ttyldisc_init: ", __STRING(s))); \ + } while (0); + +/* + * Register the basic line disciplines. + */ +void +ttyldisc_init() { + /* Only initialize once */ + if (linesw) + return; + + slinesw = LSWITCHBRK; + linesw = malloc(slinesw * sizeof(struct linesw *), + M_TTYS, M_WAITOK); + bzero(linesw, slinesw * sizeof(struct linesw *)); + + TTYLDISCINIT(termios_disc, 0); + /* Do we really need this one? */ + TTYLDISCINIT(defunct_disc, 1); + + /* + * The following should really be moved to + * initialization code for each module. + */ + +#if defined(COMPAT_43) || defined(COMPAT_FREEBSD) + TTYLDISCINIT(ntty_disc, 2); +#endif +#if NTB > 0 + TTYLDISCINIT(table_disc, 3); +#endif +#if NSL > 0 + TTYLDISCINIT(slip_disc, 4); +#endif +#if NPPP > 0 + TTYLDISCINIT(ppp_disc, 5); +#endif +#if NSTRIP > 0 + TTYLDISCINIT(strip_disc, 6); +#endif + +} diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index ead31070e5d0..49f4ef4be3d6 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty_pty.c,v 1.49 2000/09/11 13:51:29 pk Exp $ */ +/* $NetBSD: tty_pty.c,v 1.50 2000/11/01 23:51:39 eeh Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -301,7 +301,7 @@ ptsopen(dev, flag, devtype, p) if (error) return (error); } - error = (*linesw[tp->t_line].l_open)(dev, tp); + error = (*tp->t_linesw->l_open)(dev, tp); ptcwakeup(tp, FREAD|FWRITE); return (error); } @@ -316,7 +316,7 @@ ptsclose(dev, flag, mode, p) struct tty *tp = pti->pt_tty; int error; - error = (*linesw[tp->t_line].l_close)(tp, flag); + error = (*tp->t_linesw->l_close)(tp, flag); error |= ttyclose(tp); ptcwakeup(tp, FREAD|FWRITE); return (error); @@ -367,7 +367,7 @@ again: return (error); } else if (tp->t_oproc) - error = (*linesw[tp->t_line].l_read)(tp, uio, flag); + error = (*tp->t_linesw->l_read)(tp, uio, flag); ptcwakeup(tp, FWRITE); return (error); } @@ -388,7 +388,7 @@ ptswrite(dev, uio, flag) if (tp->t_oproc == 0) return (EIO); - return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); + return ((*tp->t_linesw->l_write)(tp, uio, flag)); } /* @@ -471,7 +471,7 @@ ptcopen(dev, flag, devtype, p) if (tp->t_oproc) return (EIO); tp->t_oproc = ptsstart; - (void)(*linesw[tp->t_line].l_modem)(tp, 1); + (void)(*tp->t_linesw->l_modem)(tp, 1); CLR(tp->t_lflag, EXTPROC); pti->pt_flags = 0; pti->pt_send = 0; @@ -489,7 +489,7 @@ ptcclose(dev, flag, devtype, p) struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; - (void)(*linesw[tp->t_line].l_modem)(tp, 0); + (void)(*tp->t_linesw->l_modem)(tp, 0); CLR(tp->t_state, TS_CARR_ON); tp->t_oproc = 0; /* mark closed */ return (0); @@ -623,7 +623,7 @@ again: wakeup((caddr_t)&tp->t_rawq); goto block; } - (*linesw[tp->t_line].l_rint)(*cp++, tp); + (*tp->t_linesw->l_rint)(*cp++, tp); cnt++; cc--; } @@ -820,7 +820,7 @@ ptyioctl(dev, cmd, data, flag, p) ttyinfo(tp); return(0); } - error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); if (error < 0) error = ttioctl(tp, cmd, data, flag, p); if (error < 0) { diff --git a/sys/kern/tty_tb.c b/sys/kern/tty_tb.c index 1f33b94b4624..5a41d52fa1b3 100644 --- a/sys/kern/tty_tb.c +++ b/sys/kern/tty_tb.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty_tb.c,v 1.22 2000/03/30 09:27:14 augustss Exp $ */ +/* $NetBSD: tty_tb.c,v 1.23 2000/11/01 23:51:39 eeh Exp $ */ /*- * Copyright (c) 1982, 1986, 1991, 1993 @@ -126,7 +126,7 @@ tbopen(dev, tp) { struct tb *tbp; - if (tp->t_line == TABLDISC) + if (tp->t_linesw && (tp->t_linesw->t_no == TABLDISC)) return (ENODEV); ttywflush(tp); for (tbp = tb; tbp < &tb[NTB]; tbp++)