Make line disciplines modular so they can be added or removed dynamically.

This commit is contained in:
eeh 2000-11-01 23:51:38 +00:00
parent 7607061e3f
commit d85adca51f
4 changed files with 233 additions and 110 deletions

View File

@ -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);
}

View File

@ -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 <sys/ioctl.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/ioctl.h>
#include <sys/ttycom.h>
#include <sys/conf.h>
#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 <sys/malloc.h>
#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; i<nlinesw; i++) {
if (linesw[i] && (strcmp(name, linesw[i]->l_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; i<nlinesw; i++)
if (linesw[i] && (strcmp(name, linesw[i]->l_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
}

View File

@ -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) {

View File

@ -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++)