1 /* $NetBSD: tty_conf.c,v 1.35 2001/11/12 15:25:28 lukem 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.35 2001/11/12 15:25:28 lukem 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 103 struct linesw termios_disc = 104 { "termios", 0, ttylopen, ttylclose, ttread, ttwrite, nullioctl, 105 ttyinput, ttstart, ttymodem, ttpoll }; /* 0- termios */ 106 struct linesw defunct_disc = 107 { "defunct", 1, ttynodisc, ttyerrclose, ttyerrio, ttyerrio, nullioctl, 108 ttyerrinput, ttyerrstart, nullmodem, ttyerrpoll }; /* 1- defunct */ 109 #if defined(COMPAT_43) || defined(COMPAT_FREEBSD) 110 struct linesw ntty_disc = 111 { "ntty", 2, ttylopen, ttylclose, ttread, ttwrite, nullioctl, 112 ttyinput, ttstart, ttymodem, ttpoll }; /* 2- old NTTYDISC */ 113 #endif 114 #if NTB > 0 115 struct linesw table_disc = 116 { "tablet", 3, tbopen, tbclose, tbread, ttyerrio, tbtioctl, 117 tbinput, ttstart, nullmodem, ttyerrpoll }; /* 3- TABLDISC */ 118 #endif 119 #if NSL > 0 120 struct linesw slip_disc = 121 { "slip", 4, slopen, slclose, ttyerrio, ttyerrio, sltioctl, 122 slinput, slstart, nullmodem, ttyerrpoll }; /* 4- SLIPDISC */ 123 #endif 124 #if NPPP > 0 125 struct linesw ppp_disc = 126 { "ppp", 5, pppopen, pppclose, pppread, pppwrite, ppptioctl, 127 pppinput, pppstart, ttymodem, ttpoll }; /* 5- PPPDISC */ 128 #endif 129 #if NSTRIP > 0 130 struct linesw strip_disc = 131 { "strip", 6, stripopen, stripclose, ttyerrio, ttyerrio, striptioctl, 132 stripinput, stripstart, nullmodem, ttyerrpoll }; /* 6- STRIPDISC */ 133 #endif 134 135 /* 136 * Registered line disciplines. Don't use this 137 * it will go away. 138 */ 139 #define LSWITCHBRK 20 140 struct linesw **linesw = NULL; 141 int nlinesw = 0; 142 int slinesw = 0; 143 144 /* 145 * Do nothing specific version of line 146 * discipline specific ioctl command. 147 */ 148 /*ARGSUSED*/ 149 int 150 nullioctl(tp, cmd, data, flags, p) 151 struct tty *tp; 152 u_long cmd; 153 char *data; 154 int flags; 155 struct proc *p; 156 { 157 158 #ifdef lint 159 tp = tp; data = data; flags = flags; p = p; 160 #endif 161 return (-1); 162 } 163 164 /* 165 * Register a line discipline, optionally providing a 166 * specific discipline number for compatibility, -1 allocates 167 * a new one. Returns a discipline number, or -1 on 168 * failure. 169 */ 170 int 171 ttyldisc_add(disc, no) 172 struct linesw *disc; 173 int no; 174 { 175 176 /* You are not allowed to exceed TTLINEDNAMELEN */ 177 if (strlen(disc->l_name) > TTLINEDNAMELEN) 178 return (-1); 179 180 /* 181 * You are not allowed to specify a line switch 182 * compatibility number greater than 10. 183 */ 184 if (no > 10) 185 return (-1); 186 187 if (linesw == NULL) 188 panic("adding uninitialized linesw"); 189 190 #ifdef DEBUG 191 /* 192 * XXX: For the benefit of LKMs 193 */ 194 if (disc->l_poll == NULL) 195 panic("line discipline must now provide l_poll() entry point"); 196 #endif 197 198 if (no == -1) { 199 /* Hunt for any slot */ 200 201 for (no = slinesw; no-- > 0;) 202 if (linesw[no] == NULL) 203 break; 204 /* if no == -1 we should realloc linesw, but for now... */ 205 if (no == -1) 206 return (-1); 207 } 208 209 /* Need a specific slot */ 210 if (linesw[no] != NULL) 211 return (-1); 212 213 linesw[no] = disc; 214 disc->l_no = no; 215 216 /* Define size of table */ 217 if (no >= nlinesw) 218 nlinesw = no + 1; 219 220 return (no); 221 } 222 223 /* 224 * Remove a line discipline by its name. Returns the 225 * discipline on success or NULL on failure. 226 */ 227 struct linesw * 228 ttyldisc_remove(name) 229 char *name; 230 { 231 struct linesw *disc; 232 int i; 233 234 if (linesw == NULL) 235 panic("removing uninitialized linesw"); 236 237 for (i = 0; i < nlinesw; i++) { 238 if (linesw[i] && (strcmp(name, linesw[i]->l_name) == 0)) { 239 disc = linesw[i]; 240 linesw[i] = NULL; 241 242 if (nlinesw == i + 1) { 243 /* Need to fix up array sizing */ 244 while (i-- > 0 && linesw[i] == NULL) 245 continue; 246 nlinesw = i + 1; 247 } 248 return (disc); 249 } 250 } 251 return (NULL); 252 } 253 254 /* 255 * Look up a line discipline by its name. 256 */ 257 struct linesw * 258 ttyldisc_lookup(name) 259 char *name; 260 { 261 int i; 262 263 for (i = 0; i < nlinesw; i++) 264 if (linesw[i] && (strcmp(name, linesw[i]->l_name) == 0)) 265 return (linesw[i]); 266 return (NULL); 267 } 268 269 #define TTYLDISCINIT(s, v) \ 270 do { \ 271 if (ttyldisc_add(&(s), (v)) != (v)) \ 272 panic("ttyldisc_init: " __STRING(s)); \ 273 } while (0) 274 275 /* 276 * Register the basic line disciplines. 277 */ 278 void 279 ttyldisc_init() 280 { 281 282 /* Only initialize once */ 283 if (linesw) 284 return; 285 286 slinesw = LSWITCHBRK; 287 linesw = malloc(slinesw * sizeof(struct linesw *), 288 M_TTYS, M_WAITOK); 289 memset(linesw, 0, slinesw * sizeof(struct linesw *)); 290 291 TTYLDISCINIT(termios_disc, 0); 292 /* Do we really need this one? */ 293 TTYLDISCINIT(defunct_disc, 1); 294 295 /* 296 * The following should really be moved to 297 * initialization code for each module. 298 */ 299 300 #if defined(COMPAT_43) || defined(COMPAT_FREEBSD) 301 TTYLDISCINIT(ntty_disc, 2); 302 #endif 303 #if NTB > 0 304 TTYLDISCINIT(table_disc, 3); 305 #endif 306 #if NSL > 0 307 TTYLDISCINIT(slip_disc, 4); 308 #endif 309 #if NPPP > 0 310 TTYLDISCINIT(ppp_disc, 5); 311 #endif 312 #if NSTRIP > 0 313 TTYLDISCINIT(strip_disc, 6); 314 #endif 315 } 316