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