xref: /netbsd-src/sys/kern/tty_conf.c (revision 5b84b3983f71fd20a534cfa5d1556623a8aaa717)
1 /*	$NetBSD: tty_conf.c,v 1.47 2005/06/21 14:01:13 ws Exp $	*/
2 
3 /*-
4  * Copyright (c) 1982, 1986, 1991, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  * (c) UNIX System Laboratories, Inc.
7  * All or some portions of this file are derived from material licensed
8  * to the University of California by American Telephone and Telegraph
9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10  * the permission of UNIX System Laboratories, Inc.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	@(#)tty_conf.c	8.5 (Berkeley) 1/9/95
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: tty_conf.c,v 1.47 2005/06/21 14:01:13 ws Exp $");
41 
42 #include "opt_compat_freebsd.h"
43 #include "opt_compat_43.h"
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/buf.h>
48 #include <sys/ioctl.h>
49 #include <sys/poll.h>
50 #include <sys/proc.h>
51 #include <sys/tty.h>
52 #include <sys/ioctl.h>
53 #include <sys/ttycom.h>
54 #include <sys/conf.h>
55 #include <sys/malloc.h>
56 
57 #include "tb.h"
58 #if NTB > 0
59 int	tbopen(dev_t dev, struct tty *tp);
60 int	tbclose(struct tty *tp, int flags);
61 int	tbread(struct tty *tp, struct uio *uio, int flags);
62 int	tbtioctl(struct tty *tp, u_long cmd, caddr_t data,
63 		 int flag, struct proc *p);
64 int	tbinput(int c, struct tty *tp);
65 #endif
66 
67 #include "sl.h"
68 #if NSL > 0
69 int	slopen(dev_t dev, struct tty *tp);
70 int	slclose(struct tty *tp, int flags);
71 int	sltioctl(struct tty *tp, u_long cmd, caddr_t data,
72 		 int flag, struct proc *p);
73 int	slinput(int c, struct tty *tp);
74 int	slstart(struct tty *tp);
75 #endif
76 
77 #include "ppp.h"
78 #if NPPP > 0
79 int	pppopen(dev_t dev, struct tty *tp);
80 int	pppclose(struct tty *tp, int flags);
81 int	ppptioctl(struct tty *tp, u_long cmd, caddr_t data,
82 		  int flag, struct proc *p);
83 int	pppinput(int c, struct tty *tp);
84 int	pppstart(struct tty *tp);
85 int	pppread(struct tty *tp, struct uio *uio, int flag);
86 int	pppwrite(struct tty *tp, struct uio *uio, int flag);
87 #endif
88 
89 #include "strip.h"
90 #if NSTRIP > 0
91 int	stripopen(dev_t dev, struct tty *tp);
92 int	stripclose(struct tty *tp, int flags);
93 int	striptioctl(struct tty *tp, u_long cmd, caddr_t data,
94 		    int flag, struct proc *p);
95 int	stripinput(int c, struct tty *tp);
96 int	stripstart(struct tty *tp);
97 #endif
98 
99 #include "irframetty.h"
100 #if NIRFRAMETTY > 0
101 int	irframetopen(dev_t dev, struct tty *tp);
102 int	irframetclose(struct tty *tp, int flags);
103 int	irframetioctl(struct tty *tp, u_long cmd, caddr_t data,
104 		      int flag, struct proc *p);
105 int	irframetinput(int c, struct tty *tp);
106 int	irframetstart(struct tty *tp);
107 int	irframetread(struct tty *tp, struct uio *uio, int flag);
108 int	irframetwrite(struct tty *tp, struct uio *uio, int flag);
109 int	irframetpoll(struct tty *tp, int events, struct proc *p);
110 #endif
111 
112 
113 struct  linesw termios_disc =
114 	{ "termios", TTYDISC, ttylopen, ttylclose, ttread, ttwrite,
115 	  ttynullioctl, ttyinput, ttstart, ttymodem, ttpoll };	/* 0- termios */
116 struct  linesw defunct_disc =
117 	{ "defunct", 1, ttynodisc, ttyerrclose, ttyerrio, ttyerrio,
118 	  ttynullioctl, ttyerrinput, ttyerrstart, nullmodem, ttyerrpoll }; /* 1- defunct */
119 #if defined(COMPAT_43) || defined(COMPAT_FREEBSD)
120 struct  linesw ntty_disc =
121 	{ "ntty", 2, ttylopen, ttylclose, ttread, ttwrite, ttynullioctl,
122 	  ttyinput, ttstart, ttymodem, ttpoll };	/* 2- old NTTYDISC */
123 #endif
124 #if NTB > 0
125 struct  linesw table_disc =
126 	{ "tablet", TABLDISC, tbopen, tbclose, tbread, ttyerrio, tbtioctl,
127 	  tbinput, ttstart, nullmodem, ttyerrpoll };	/* 3- TABLDISC */
128 #endif
129 #if NSL > 0
130 struct  linesw slip_disc =
131 	{ "slip", SLIPDISC, slopen, slclose, ttyerrio, ttyerrio, sltioctl,
132 	  slinput, slstart, nullmodem, ttyerrpoll };	/* 4- SLIPDISC */
133 #endif
134 #if NPPP > 0
135 struct  linesw ppp_disc =
136 	{ "ppp", PPPDISC, pppopen, pppclose, pppread, pppwrite, ppptioctl,
137 	  pppinput, pppstart, ttymodem, ttpoll };	/* 5- PPPDISC */
138 #endif
139 #if NSTRIP > 0
140 struct  linesw strip_disc =
141 	{ "strip", STRIPDISC, stripopen, stripclose, ttyerrio, ttyerrio,
142 	  striptioctl, stripinput, stripstart, nullmodem, ttyerrpoll };
143 							/* 6- STRIPDISC */
144 #endif
145 #if NIRFRAMETTY > 0
146 struct  linesw irframet_disc =
147 	{ "irframe", -1, irframetopen, irframetclose, ttyerrio,
148 	  ttyerrio, irframetioctl, irframetinput, irframetstart,
149 	  ttymodem, ttyerrpoll };			/* irframe */
150 #endif
151 
152 /*
153  * Registered line disciplines.  Don't use this
154  * it will go away.
155  */
156 #define LSWITCHBRK	20
157 struct	linesw **linesw = NULL;
158 int	nlinesw = 0;
159 int	slinesw = 0;
160 
161 /*
162  * Do nothing specific version of line
163  * discipline specific ioctl command.
164  */
165 /*ARGSUSED*/
166 int
167 ttynullioctl(tp, cmd, data, flags, p)
168 	struct tty *tp;
169 	u_long cmd;
170 	char *data;
171 	int flags;
172 	struct proc *p;
173 {
174 
175 #ifdef lint
176 	tp = tp; data = data; flags = flags; p = p;
177 #endif
178 	return (EPASSTHROUGH);
179 }
180 
181 /*
182  * Return error to line discipline
183  * specific poll call.
184  */
185 /*ARGSUSED*/
186 int
187 ttyerrpoll(tp, events, p)
188 	struct tty *tp;
189 	int events;
190 	struct proc *p;
191 {
192 
193 #ifdef lint
194 	tp = tp; events = events; p = p;
195 #endif
196 	return (POLLERR);
197 }
198 
199 /*
200  * Register a line discipline, optionally providing a
201  * specific discipline number for compatibility, -1 allocates
202  * a new one.  Returns a discipline number, or -1 on
203  * failure.
204  */
205 int
206 ttyldisc_add(disc, no)
207 	struct linesw *disc;
208 	int no;
209 {
210 
211 	/* You are not allowed to exceed TTLINEDNAMELEN */
212 	if (strlen(disc->l_name) >= TTLINEDNAMELEN)
213 		return (-1);
214 
215 	/*
216 	 * You are not allowed to specify a line switch
217 	 * compatibility number greater than 10.
218 	 */
219 	if (no > 10)
220 		return (-1);
221 
222 	if (linesw == NULL)
223 		panic("adding uninitialized linesw");
224 
225 #ifdef DEBUG
226 	/*
227 	 * XXX: For the benefit of LKMs
228 	 */
229 	if (disc->l_poll == NULL)
230 		panic("line discipline must now provide l_poll() entry point");
231 #endif
232 
233 	if (no == -1) {
234 		/* Hunt for any slot */
235 
236 		for (no = slinesw; no-- > 0;)
237 			if (linesw[no] == NULL)
238 				break;
239 		/* if no == -1 we should realloc linesw, but for now... */
240 		if (no == -1)
241 			return (-1);
242 	}
243 
244 	/* Need a specific slot */
245 	if (linesw[no] != NULL)
246 		return (-1);
247 
248 	linesw[no] = disc;
249 	disc->l_no = no;
250 
251 	/* Define size of table */
252 	if (no >= nlinesw)
253 		nlinesw = no + 1;
254 
255 	return (no);
256 }
257 
258 /*
259  * Remove a line discipline by its name.  Returns the
260  * discipline on success or NULL on failure.
261  */
262 struct linesw *
263 ttyldisc_remove(name)
264 	const char *name;
265 {
266 	struct linesw *disc;
267 	int i;
268 
269 	if (linesw == NULL)
270 		panic("removing uninitialized linesw");
271 
272 	for (i = 0; i < nlinesw; i++) {
273 		if (linesw[i] && (strcmp(name, linesw[i]->l_name) == 0)) {
274 			disc = linesw[i];
275 			linesw[i] = NULL;
276 
277 			if (nlinesw == i + 1) {
278 				/* Need to fix up array sizing */
279 				while (i-- > 0 && linesw[i] == NULL)
280 					continue;
281 				nlinesw = i + 1;
282 			}
283 			return (disc);
284 		}
285 	}
286 	return (NULL);
287 }
288 
289 /*
290  * Look up a line discipline by its name.
291  */
292 struct linesw *
293 ttyldisc_lookup(name)
294 	const char *name;
295 {
296 	int i;
297 
298 	for (i = 0; i < nlinesw; i++)
299 		if (linesw[i] && (strcmp(name, linesw[i]->l_name) == 0))
300 			return (linesw[i]);
301 	return (NULL);
302 }
303 
304 #define TTYLDISCINIT(s, v) \
305 	do { \
306 		if (ttyldisc_add(&(s), (v)) != (v)) \
307 			panic("ttyldisc_init: " __STRING(s)); \
308 	} while (/*CONSTCOND*/ 0)
309 
310 /*
311  * Register the basic line disciplines.
312  */
313 void
314 ttyldisc_init()
315 {
316 
317 	/* Only initialize once */
318 	if (linesw)
319 		return;
320 
321 	slinesw = LSWITCHBRK;
322 	linesw = malloc(slinesw * sizeof(struct linesw *),
323 	    M_TTYS, M_WAITOK);
324 	memset(linesw, 0, slinesw * sizeof(struct linesw *));
325 
326 	TTYLDISCINIT(termios_disc, 0);
327 	/* Do we really need this one? */
328 	TTYLDISCINIT(defunct_disc, 1);
329 
330 	/*
331 	 * The following should really be moved to
332 	 * initialization code for each module.
333 	 */
334 
335 #if defined(COMPAT_43) || defined(COMPAT_FREEBSD)
336 	TTYLDISCINIT(ntty_disc, 2);
337 #endif
338 #if NTB > 0
339 	TTYLDISCINIT(table_disc, 3);
340 #endif
341 #if NSL > 0
342 	TTYLDISCINIT(slip_disc, 4);
343 #endif
344 #if NPPP > 0
345 	TTYLDISCINIT(ppp_disc, 5);
346 #endif
347 #if NSTRIP > 0
348 	TTYLDISCINIT(strip_disc, 6);
349 #endif
350 #if NIRFRAMETTY > 0
351 	ttyldisc_add(&irframet_disc, -1);
352 #endif
353 }
354