Make line disciplines modular so they can be added or removed dynamically.
This commit is contained in:
parent
7607061e3f
commit
d85adca51f
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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++)
|
||||
|
Loading…
Reference in New Issue
Block a user