tty_conf.c revision 1.47 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