summaryrefslogtreecommitdiffstats
path: root/sys/kern/tty.c
diff options
context:
space:
mode:
authorarchie <archie@FreeBSD.org>2000-01-28 02:22:22 +0000
committerarchie <archie@FreeBSD.org>2000-01-28 02:22:22 +0000
commit219d3e45839f2e2dede47705b29ab11268d849c3 (patch)
tree1bd8f21d8595af9dadf8adb716f6afbb395a16b2 /sys/kern/tty.c
parent10d6a2ddbb724c01ef1314f818671049f0708816 (diff)
downloadFreeBSD-src-219d3e45839f2e2dede47705b29ab11268d849c3.zip
FreeBSD-src-219d3e45839f2e2dede47705b29ab11268d849c3.tar.gz
When an attempt to install a line discipline fails, check for
known KLD's that might support it, and load the KLD if found. Currently the list includes SLIPDISC, PPPDISC, and NETGRAPHDISC.
Diffstat (limited to 'sys/kern/tty.c')
-rw-r--r--sys/kern/tty.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index b8eff2c..0d124a2 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -91,6 +91,7 @@
#include <sys/resourcevar.h>
#include <sys/malloc.h>
#include <sys/filedesc.h>
+#include <sys/linker.h>
#if NSNP > 0
#include <sys/snoop.h>
#endif
@@ -113,6 +114,7 @@ static void ttyrub __P((int c, struct tty *tp));
static void ttyrubo __P((struct tty *tp, int cnt));
static void ttyunblock __P((struct tty *tp));
static int ttywflush __P((struct tty *tp));
+static int tty_load_disc __P((int t));
/*
* Table with character classes and parity. The 8th bit indicates parity,
@@ -201,6 +203,23 @@ static u_char const char_type[] = {
static SLIST_HEAD(, tty) tty_list;
/*
+ * Some line disciplines may exist as external KLD modules.
+ * Put them here and they will be automatically loaded
+ * whenever someone attempts to install the corresponding
+ * line discipline.
+ */
+static struct tty_kldinfo {
+ int discnum; /* line discipline number, -1 ends */
+ const char *filename; /* name of the KLD file */
+ int loaded; /* set to 1 if already loaded */
+} tty_ldisc_klds[] = {
+ { SLIPDISC, "if_sl.ko" },
+ { PPPDISC, "if_ppp.ko" },
+ { NETGRAPHDISC, "ng_tty.ko" },
+ { -1 }
+};
+
+/*
* Initial open of tty, or (re)entry to standard tty line discipline.
*/
int
@@ -960,6 +979,8 @@ ttioctl(tp, cmd, data, flag)
s = spltty();
(*linesw[tp->t_line].l_close)(tp, flag);
error = (*linesw[t].l_open)(device, tp);
+ if (error == ENODEV && tty_load_disc(t)) /* try KLD */
+ error = (*linesw[t].l_open)(device, tp);
if (error) {
(void)(*linesw[tp->t_line].l_open)(device, tp);
splx(s);
@@ -1225,6 +1246,42 @@ again:
}
/*
+ * Try to load the KLD for the line discipline, if one exists.
+ * Returns 1 on success, zero on failure.
+ */
+static int
+tty_load_disc(int t)
+{
+ struct tty_kldinfo *kld;
+ linker_file_t lf;
+ int error;
+ char *path;
+
+ for (kld = &tty_ldisc_klds[0]; kld->discnum != -1; kld++) {
+ if (kld->discnum == t) {
+
+ /* Don't load the same KLD twice */
+ if (kld->loaded)
+ break;
+
+ /* Try loading the KLD */
+ if ((path = linker_search_path(kld->filename)) == NULL)
+ return 0;
+ error = linker_load_file(path, &lf);
+ FREE(path, M_LINKER);
+ if (error != 0)
+ return 0;
+ lf->userrefs++; /* as if by kldload(2) */
+
+ /* Mark KLD as loaded and return success */
+ kld->loaded = 1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
* Copy in the default termios characters.
*/
void
OpenPOWER on IntegriCloud