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