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