xref: /386bsd/usr/src/kernel/kern/config.c (revision dc8b130e)
1 /*-
2  * Copyright (c) 1994 William F. Jolitz, TeleMuse
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This software is a component of "386BSD" developed by
16  *	William F. Jolitz, TeleMuse.
17  * 4. Neither the name of the developer nor the name "386BSD"
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  * 5. Non-commercial distribution of this complete file in either source and/or
21  *    binary form at no charge to the user (such as from an official Internet
22  *    archive site) is permitted.
23  * 6. Commercial distribution and sale of this complete file in either source
24  *    and/or binary form on any media, including that of floppies, tape, or
25  *    CD-ROM, or through a per-charge download such as that of a BBS, is not
26  *    permitted without specific prior written permission.
27  * 7. Non-commercial and/or commercial distribution of an incomplete, altered,
28  *    or otherwise modified file in either source and/or binary form is not
29  *    permitted.
30  *
31  * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
32  * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
33  * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
34  * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
35  * NOT MAKE USE OF THIS WORK.
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
38  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
41  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  *
49  * $Id: config.c,v 1.1 94/10/20 00:02:46 bill Exp Locker: bill $
50  * Software module configuration.
51  */
52 
53 #include "sys/param.h"
54 #include "sys/stat.h"
55 #include "sys/ioctl.h"
56 #include "buf.h"	/* devif_strategy ... */
57 #include "tty.h"	/* ldiscif...() ... */
58 #include "modconfig.h"
59 #include "sys/errno.h"
60 #include "prototypes.h"
61 
62 
63 int query(char *s, ...);
64 extern char config_string[];
65 
66 static int console_minor;
67 extern struct devif pc_devif;
68 struct devif *console_devif = &pc_devif;
69 struct devif *default_console_devif = &pc_devif;
70 static struct ldiscif *ldisc;
71 
72 /*
73  * config script language primatives
74  */
75 
76 /* skip over any whitespace in string, including comments */
77 char *
cfg_skipwhite(char ** ptr)78 cfg_skipwhite(char **ptr) {
79 	char *p = *ptr;
80 
81 rescan:
82 	/* white space is any blanks, tabs, newlines or returns */
83 	while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
84 		p++;
85 
86 	/* comments are treated as white space, terminated by a newline */
87 	if (*p == '#') {
88 		while (*p && *p != '\n')
89 			p++;
90 		goto rescan;
91 	}
92 
93 	return (*ptr = p);
94 }
95 
96 /* is character a digit in given base? */
97 static int
isdigit(char c,int base)98 isdigit(char c, int base) {
99 
100 	if (base == 10)
101 		return ((c >= '0' && c <= '9') ? 1 : 0);
102 	if (base == 8)
103 		return ((c >= '0' && c <= '7') ? 1 : 0);
104 	if (base == 16) {
105 		if (c >= '0' && c <= '9')
106 			return (1);
107 		if (c >= 'a' && c <= 'f')
108 			return (1);
109 		if (c >= 'A' && c <= 'F')
110 			return (1);
111 	}
112 	return (0);
113 }
114 
115 /* alphanumeric character? */
116 static int
isalphanum(char c)117 isalphanum(char c) {
118 
119 	if (c >= 'a' && c <= 'z')
120 		return (1);
121 	if (c >= 'A' && c <= 'Z')
122 		return (1);
123 	if (c >= '0' && c <= '9')
124 		return (1);
125 
126 	return (0);
127 }
128 
129 /* value of digit */
130 static int
valdigit(char c)131 valdigit(char c) {
132 
133 	if (c >= '0' && c <= '9')
134 		return (c - '0');
135 	if (c >= 'a' && c <= 'f')
136 		return (c - 'a' + 10);
137 	if (c >= 'A' && c <= 'F')
138 		return (c - 'A' + 10);
139 
140 	return (0);
141 }
142 
143 int
cfg_number(char ** ptr,int * pval)144 cfg_number(char **ptr, int *pval) {
145 	char *p;
146 	int base = 10, val = 0, sign = 0;
147 
148 	/* consume any whitespace */
149 	p = cfg_skipwhite(ptr);
150 
151 	/* sign? */
152 	if (*p == '-') {
153 		p++;
154 		sign = 1;
155 	}
156 
157 	/* must start with at least one decimal numeric character */
158 	if (isdigit(*p, 10)) {
159 
160 		/* base of number */
161 		if (p[0] == '0') {
162 			if (p[1] == 'x') {
163 				p += 2; base = 16;
164 			} else {
165 				p++ ; base = 8;
166 			}
167 		}
168 
169 		/* accumulate number value. */
170 		while (isdigit(*p, base))
171 			val = base * val + valdigit(*p++);
172 
173 		/* return found number, and advance string pointer */
174 		*pval = sign ? -val : val;
175 		*ptr = p;
176 		return (1);
177 
178 	} else
179 		return (0);
180 }
181 
182 /* accept a string token of finite length? */
183 int
cfg_string(char ** ptr,char * sp,int szval)184 cfg_string(char **ptr, char *sp, int szval) {
185 	char *p, *rsp = sp, *lp;
186 	int dummyval;
187 
188 	/* consume any whitespace */
189 	lp = p = cfg_skipwhite(ptr);
190 
191 	/* reserve place in buffer for null */
192 	szval -= 1;
193 
194 	/* accumulate alphanumeric string value. */
195 	while (isalphanum(*p)) {
196 		if (szval-- > 0)
197 			*rsp++ = *p;
198 		p++;
199 	}
200 
201 	/* anything found? */
202 	if (rsp != sp) {
203 
204 		/* return found string, adding terminating null */
205 		*rsp = 0;
206 		*ptr = p;
207 		return (1);
208 
209 	} else
210 		return (0);
211 }
212 
213 /* accept a character token ? */
214 int
cfg_char(char ** ptr,char t)215 cfg_char(char **ptr, char t) {
216 	char *p;
217 
218 	p = cfg_skipwhite(ptr);
219 
220 	if (*p++ == t) {
221 		*ptr = p;
222 		return (1);
223 	} else
224 		return (0);
225 }
226 
227 /* parse and return any name/token pairs found into respective values */
228 int
cfg_namelist(char ** cfg,struct namelist * nmp)229 cfg_namelist(char **cfg, struct namelist *nmp) {
230 	char *lcfg = *cfg;
231 	char val[80];
232 	struct namelist *n;
233 	int any = 0;
234 
235 	while (cfg_string(&lcfg, val, sizeof(val))) {
236 		for (n = nmp; n->name ; n++)
237 			if (strcmp(n->name, val) == 0)
238 				goto found;
239 		return (any);
240 	found:
241 		switch (n->type) {
242 		case NUMBER:
243 			if (cfg_number(&lcfg, (int *)n->value) == 0)
244 				return (any);
245 			break;
246 
247 		case STRING:
248 			/* XXX do I really want a length? */
249 			if (cfg_string(&lcfg, (char *)n->value, 80) == 0)
250 				return (any);
251 			break;
252 
253 		default:
254 			return (any);
255 		}
256 		*cfg = lcfg;	/* reduce */
257 		any++;
258 	}
259 	return (any);
260 }
261 
262 static char arg[32];	/* currently configuring module */
263 
264 /* discover if module should configure itself */
265 int
config_scan(char * cfg,char ** cfg_sp)266 config_scan(char *cfg, char **cfg_sp) {
267 	extern end;
268 	char *lp = (char *)&end /*config_string*/;
269 	char strbuf[32];
270 	int dummy, exclaim;
271 
272 	/* fetch default configuration script */
273 	(void)cfg_string(&cfg, arg, sizeof(arg));
274 
275 	/* if starting string matches, signal configuration state */
276 next_entry:
277 	exclaim = cfg_char(&lp, '!');
278 	if (cfg_string(&lp, strbuf, 32) && strcmp(arg, strbuf) == 0 &&
279 	    query("config: override %s", arg)) {
280 
281 		/* return config string? */
282 		if (cfg_sp)
283 			*cfg_sp = lp;
284 
285 		return (exclaim == 0);
286 	}
287 
288 	/* does not match, consume entry */
289 	for (;; lp++) {
290 
291 		/* consume either kind of token */
292 		while (cfg_number(&lp, &dummy) || cfg_string(&lp, strbuf, 32))
293 				;
294 		/* done with string */
295 		if (cfg_char(&lp, 0))
296 			goto done_all;
297 
298 		/* done with entry */
299 		if (cfg_char(&lp, '.'))
300 			break;
301 	}
302 	goto next_entry;
303 
304 done_all:
305 	/* if not found, and not to be configured if not found, ignore */
306 	if (cfg_char(&cfg, '.'))
307 		return(0);
308 
309 	if (cfg_sp)
310 		*cfg_sp = cfg;
311 
312 	return(query("config: default %s", arg));
313 }
314 
315 /*
316  * Module Communications, by class type.
317  */
318 
319 extern int etext, edata;	/* XXX scan all kernel loaded data segments */
320 
321 /* tell all modules of a class type to initialize themselves */
322 void
modscaninit(modtype_t modtype)323 modscaninit(modtype_t modtype) {
324 	int *sigp;
325 
326 	for (sigp = &etext; sigp < &edata; sigp++)
327 
328 		/* if valid signature ... */
329 		if (*sigp == MODULE_SIGNATURE) {
330 			struct modconfig *mcp = (struct modconfig *)sigp;
331 
332 			/* ... and a valid type ... */
333 			if (MODT_ISVALID(mcp->mod_type)) {
334 
335 				/* either to the supplied arg, or to all */
336 				if ((mcp->mod_type == modtype
337 				    || modtype == __MODT_ALL__)
338 				    && mcp->mod_init)
339 					(mcp->mod_init)();
340 			}
341 		}
342 }
343 
344 void
smodscaninit(modtype_t modtype,int * sstart,int * send)345 smodscaninit(modtype_t modtype, int *sstart, int *send) {
346 	int *sigp;
347 
348 	for (sigp = sstart; sigp < send; sigp++)
349 
350 		/* if valid signature ... */
351 		if (*sigp == MODULE_SIGNATURE) {
352 			struct modconfig *mcp = (struct modconfig *)sigp;
353 
354 			/* ... and a valid type ... */
355 			if (MODT_ISVALID(mcp->mod_type)) {
356 
357 				/* either to the supplied arg, or to all */
358 				if ((mcp->mod_type == modtype
359 				    || modtype == __MODT_ALL__)
360 				    && mcp->mod_init)
361 					(mcp->mod_init)();
362 			}
363 		}
364 }
365 
366 /*
367  * Kernel interface to device drivers.
368  */
369 
370 #define NDEVIF	100	/* more than adequate */
371 struct devif *chrmajtodevif[NDEVIF], *blkmajtodevif[NDEVIF];
372 
373 /* fill in the name of the supplied device in a supplied string buffer */
374 int
devif_name(dev_t dev,devif_type_t typ,char * name,int namelen)375 devif_name(dev_t dev, devif_type_t typ, char *name, int namelen) {
376 	struct devif *dif;
377 	unsigned major = major(dev);
378 	int minor;
379 	char *fp, tmpbuf[16];
380 
381 	switch (typ) {
382 	case CHRDEV:
383 	    	if (major > sizeof chrmajtodevif / sizeof chrmajtodevif[0] ||
384 		    (dif = chrmajtodevif[major]) == 0)
385 			return (ENODEV);
386 		break;
387 
388 	case BLKDEV:
389 	    	if (major > sizeof blkmajtodevif / sizeof blkmajtodevif[0] ||
390 		    (dif = blkmajtodevif[major]) == 0)
391 			return (ENODEV);
392 		break;
393 
394 	default:
395 		panic("devif_name");	/* unimplemented device type */
396 	}
397 
398 	/* put in device name */
399 	fp = dif->di_name;
400 	while (namelen) {
401 		*name++ = *fp++;
402 		namelen--;
403 	}
404 
405 	/* construct minor device name with unit & subunit */
406 	minor = minor(dev);
407 	tmpbuf[0] = 0;
408 	if (dif->di_minor_unit_mask && dif->di_minor_subunit_mask)
409 		sprintf(tmpbuf,"%d%c",
410 	    	    (minor & dif->di_minor_unit_mask)
411 			>> dif->di_minor_unit_shift,
412 	    	    ((minor & dif->di_minor_subunit_mask)
413 			>> dif->di_minor_subunit_shift) + 'a');
414 
415 	/* ... or construct minor device name with unit */
416 	else if (dif->di_minor_unit_mask && dif->di_minor_subunit_mask)
417 		sprintf(tmpbuf,"%d",
418 	    	    (minor & dif->di_minor_unit_mask)
419 			>> dif->di_minor_unit_shift);
420 
421 	/* put into name */
422 	fp = tmpbuf;
423 	while (namelen && *fp) {
424 		*name++ = *fp++;
425 		namelen--;
426 	}
427 }
428 
429 /* check and adjust a bootdev's parameters so as to create a root device */
430 int
devif_root(unsigned major,unsigned unit,unsigned subunit,dev_t * rd)431 devif_root(unsigned major, unsigned unit, unsigned subunit, dev_t *rd)
432 {
433 	struct devif *dif;
434 
435 	/* should we configure this as root? */
436 	if (query("devif_root: major %d unit %d sub %d\n",
437 		major, unit, subunit) == 0)
438 			return (0);
439 
440 	/* is there a device driver for the root? */
441 	if (major >= NDEVIF || (dif = blkmajtodevif[major]) == 0)
442 		return (0);
443 
444 	/* turn a boot dev set of parameters into the root dev */
445 	*rd = makedev(major, ((unit) << dif->di_minor_unit_shift)
446 		+ ((subunit) << dif->di_minor_subunit_shift));
447 
448 	return (1);
449 }
450 
451 /* locate and call a device driver open routine via the device driver interface */
452 int
devif_open(dev_t dev,devif_type_t typ,int flag,struct proc * p)453 devif_open(dev_t dev, devif_type_t typ, int flag, struct proc *p) {
454 	struct devif *dif;
455 	unsigned major = major(dev);
456 
457 	/* if a BSD UN*X character device ... */
458 	if (typ == CHRDEV &&
459 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
460 		dif = chrmajtodevif[major];
461 		if (dif == console_devif)
462 			dev = makedev(major, console_minor);
463 		if (dif)
464 			return ((dif->di_open)(dev, flag, S_IFCHR, p));
465 
466 		return (ENXIO);
467 	}
468 
469 	/* if a BSD UN*X block device ... */
470 	if (typ == BLKDEV &&
471 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
472 		if (dif = blkmajtodevif[major])
473 			return ((dif->di_open)(dev, flag, S_IFBLK, p));
474 
475 		return (ENXIO);
476 	}
477 
478 	/* add support for new types here */
479 #ifdef	notyet
480 	/* if a 386BSD UNICODE character device ... */
481 	if (typ == WCHRDEV &&
482 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
483 		if (dif = chrmajtodevif[major])
484 			return ((dif->di_open)(dev, flag, S_IFWCHR, p));
485 
486 		return (ENXIO);
487 	}
488 
489 	/* if a 386BSD page i/o device ... */
490 	if (typ == PAGEDEV &&
491 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
492 		if (dif = chrmajtodevif[major])
493 			return ((dif->di_open)(dev, flag, S_IFPAGE, p));
494 
495 		return (ENXIO);
496 	}
497 #endif
498 	panic("devif_open");	/* unimplemented type */
499 }
500 
501 /* locate and call a device driver close routine via the device driver interface */
502 int
devif_close(dev_t dev,devif_type_t typ,int flag,struct proc * p)503 devif_close(dev_t dev, devif_type_t typ, int flag, struct proc *p) {
504 	struct devif *dif;
505 	unsigned major = major(dev);
506 
507 	/* if a BSD UN*X character device ... */
508 	if (typ == CHRDEV &&
509 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
510 		dif = chrmajtodevif[major];
511 		if (dif == console_devif)
512 			dev = makedev(major, console_minor);
513 		if (dif)
514 			return ((dif->di_close)(dev, flag, S_IFCHR, p));
515 
516 		return (ENODEV);
517 	}
518 
519 	/* if a BSD UN*X block device ... */
520 	if (typ == BLKDEV &&
521 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
522 		if (dif = blkmajtodevif[major])
523 			return ((dif->di_close)(dev, flag, S_IFBLK, p));
524 
525 		return (ENODEV);
526 	}
527 
528 	/* add support for new types here */
529 #ifdef	notyet
530 	/* if a 386BSD UNICODE character device ... */
531 	if (typ == WCHRDEV &&
532 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
533 		if (dif = chrmajtodevif[major])
534 			return ((dif->di_close)(dev, flag, S_IFWCHR, p));
535 		return (ENXIO);
536 	}
537 
538 	/* if a 386BSD page i/o device ... */
539 	if (typ == PAGEDEV &&
540 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
541 		if (dif = chrmajtodevif[major])
542 			return ((dif->di_close)(dev, flag, S_IFPAGE, p));
543 		return (ENXIO);
544 	}
545 #endif
546 	panic("devif_close");	/* unimplemented type */
547 }
548 
549 /* locate and call a device driver ioctl routine via the device driver interface */
550 int
devif_ioctl(dev_t dev,devif_type_t typ,int cmd,caddr_t data,int flag,struct proc * p)551 devif_ioctl(dev_t dev, devif_type_t typ, int cmd, caddr_t data, int flag,
552     struct proc *p) {
553 	struct devif *dif;
554 	unsigned major = major(dev);
555 
556 	/* if a BSD UN*X character device ... */
557 	if (typ == CHRDEV &&
558 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
559 	chrcase:
560 		dif = chrmajtodevif[major];
561 		if (dif == console_devif)
562 			dev = makedev(major, console_minor);
563 		if (dif)
564 			return ((dif->di_ioctl)(dev, cmd, data, flag, p));
565 
566 		return (ENODEV);
567 	}
568 
569 	/* if a BSD UN*X block device ... */
570 	if (typ == BLKDEV &&
571 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
572 		if (dif = blkmajtodevif[major])
573 			return ((dif->di_ioctl)(dev, cmd, data, flag, p));
574 
575 		return (ENODEV);
576 	}
577 
578 	/* add support for new types here */
579 #ifdef notyet
580 	/* if either a 386BSD UNICODE or page character device ... */
581 	if ((typ == WCHRDEV || typ == PAGEDEV)) &&
582 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
583 		goto chrcase;
584 #endif
585 	panic("devif_ioctl");	/* unimplemented type */
586 }
587 
588 /* locate and call a device driver read routine via the device driver interface */
589 int
590 devif_read(dev_t dev, devif_type_t typ, struct uio *uio, int flag) {
591 	struct devif *dif;
592 	unsigned major = major(dev);
593 
594 	/* if a BSD UN*X character device ... */
595 	if (typ == CHRDEV &&
596 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
597 		dif = chrmajtodevif[major];
598 		if (dif == console_devif)
599 			dev = makedev(major, console_minor);
600 		if (dif)
601 			return ((dif->di_read)(dev, uio, flag));
602 
603 		return (ENODEV);
604 	}
605 
606 	/* add support for new types here */
607 #ifdef notyet
608 	/* if a 386BSD UNICODE character device ... */
609 	if (typ == WCHRDEV &&
610 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
611 		if (dif = chrmajtodevif[major])
612 			return ((dif->di_wcread)(dev, uio, flag));
613 		return (ENODEV);
614 	}
615 
616 	/* if a 386BSD page i/o device ... */
617 	if (typ == PAGEDEV &&
618 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
619 		if (dif = chrmajtodevif[major])
620 			return ((dif->di_pageread)(dev, uio, flag));
621 		return (ENODEV);
622 	}
623 #endif
624 	panic("devif_read");	/* unimplemented type */
625 }
626 
627 /* locate and call a device driver write routine via the device driver interface */
628 int
629 devif_write(dev_t dev, devif_type_t typ, struct uio *uio, int flag) {
630 	struct devif *dif;
631 	unsigned major = major(dev);
632 
633 	/* if a BSD UN*X character device ... */
634 	if (typ == CHRDEV &&
635 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
636 		dif = chrmajtodevif[major];
637 		if (dif == console_devif)
638 			dev = makedev(major, console_minor);
639 		if (dif)
640 			return ((dif->di_write)(dev, uio, flag));
641 
642 		return (ENODEV);
643 	}
644 
645 	/* add support for new types here */
646 #ifdef notyet
647 	/* if a 386BSD UNICODE character device ... */
648 	if (typ == WCHRDEV &&
649 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
650 		if (dif = chrmajtodevif[major])
651 			return ((dif->di_wcwrite)(dev, uio, flag));
652 		return (ENXIO);
653 	}
654 
655 	/* if a 386BSD page i/o device ... */
656 	if (typ == PAGEDEV &&
657 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
658 		if (dif = chrmajtodevif[major])
659 			return ((dif->di_pagewrite)(dev, uio, flag));
660 		return (ENXIO);
661 	}
662 #endif
663 	panic("devif_write");	/* unimplemented type */
664 }
665 
666 /* locate and call a device driver select routine via the device driver interface */
667 int
668 devif_select(dev_t dev, devif_type_t typ, int rw, struct proc *p) {
669 	struct devif *dif;
670 	unsigned major = major(dev);
671 
672 	/* if a BSD UN*X character device ... */
673 	if (typ == CHRDEV &&
674 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
675 	chrcase:
676 		dif = chrmajtodevif[major];
677 		if (dif == console_devif)
678 			dev = makedev(major, console_minor);
679 		if (dif)
680 			return ((dif->di_select)(dev, rw, p));
681 
682 		return (ENODEV);
683 	}
684 
685 	/* add support for new types here */
686 #ifdef notyet
687 	/* if either a 386BSD UNICODE or page character device ... */
688 	if ((typ == WCHRDEV || typ == PAGEDEV)) &&
689 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
690 		goto chrcase;
691 #endif
692 	panic("devif_select");	/* unimplemented type */
693 }
694 
695 /* locate and call a device driver mmap routine via the device driver interface */
696 int
697 devif_mmap(dev_t dev, devif_type_t typ, int offset, int nprot) {
698 	struct devif *dif;
699 	unsigned major = major(dev);
700 
701 	/* if a BSD UN*X character device ... */
702 	if (typ == CHRDEV &&
703 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
704 		dif = chrmajtodevif[major];
705 		if (dif == console_devif)
706 			dev = makedev(major, console_minor);
707 		if (dif)
708 			return ((dif->di_mmap)(dev, offset, nprot));
709 
710 		return (-1);
711 	}
712 
713 	/* add support for new types here */
714 	panic("devif_mmap");	/* unimplemented type */
715 }
716 
717 /* locate and call a device driver strategy routine via the device driver interface */
718 int
719 devif_strategy(devif_type_t typ, struct buf *bp) {
720 	struct devif *dif;
721 	unsigned major = major(bp->b_dev);
722 
723 	/* if a BSD UN*X character device ... */
724 	if (typ == CHRDEV &&
725 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
726 		if (dif = chrmajtodevif[major])
727 			return ((dif->di_strategy)(bp));
728 
729 		return (ENODEV);
730 	}
731 
732 	/* if a BSD UN*X block device ... */
733 	if (typ == BLKDEV &&
734 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
735 		if (dif = blkmajtodevif[major])
736 			return ((dif->di_strategy)(bp));
737 
738 		return (ENODEV);
739 	}
740 
741 	panic("devif_strategy");	/* illegal type */
742 }
743 
744 /* locate and call a device driver size routine via the device driver interface */
745 int
746 devif_psize(dev_t dev, devif_type_t typ) {
747 	struct devif *dif;
748 	unsigned major = major(dev);
749 
750 	/* if a BSD UN*X block device ... */
751 	if (typ == BLKDEV &&
752 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
753 		if (dif = blkmajtodevif[major])
754 			return ((dif->di_psize)(dev));
755 
756 		return (0);
757 	}
758 
759 	panic("devif_psize");	/* illegal type */
760 }
761 
762 /* locate and call a device driver dump routine via the device driver interface */
763 int
764 devif_dump(dev_t dev, devif_type_t typ) {
765 	struct devif *dif;
766 	unsigned major = major(dev);
767 
768 	/* if a BSD UN*X block device ... */
769 	if (typ == BLKDEV &&
770 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
771 		if (dif = blkmajtodevif[major])
772 			return ((dif->di_dump)(dev));
773 	}
774 
775 	return (ENODEV);
776 }
777 
778 /* configure a BSD UN*X device by registering its "devif" interface */
779 int
780 devif_config(char **cfg, struct devif *dif)
781 {
782 	int bmaj, cmaj;
783 	struct devif *odif;
784 	extern int _ENODEV_();
785 
786 	/* configure name? */
787 	if (dif->di_name[0] == 0) {
788 		if (!config_scan(*cfg, cfg))
789 			return (0);
790 		memcpy(dif->di_name, arg, sizeof(arg));
791 	}
792 
793 	/* configure block device? */
794 	if (dif->di_bmajor == -1 && !cfg_number(cfg, &dif->di_bmajor))
795 		return (0);
796 
797 	/* configure character device? */
798 	if (dif->di_cmajor == -1 && !cfg_number(cfg, &dif->di_cmajor))
799 		return (0);
800 
801 	/* have a block device interface ? */
802 	if ((bmaj = dif->di_bmajor) >= 0) {
803 		struct devif *odif;
804 
805 		/* device number out of range */
806 		if (bmaj >= NDEVIF) {
807 			printf("%s: blkdev %d too big, not configured.\n",
808 				arg, bmaj);
809 			return (0);
810 		}
811 
812 		/* device already in use? */
813 		if (odif = blkmajtodevif[bmaj]) {
814 			printf("%s: blkdev %d already used by %s, not configured.\n",
815 				arg, bmaj, odif->di_name);
816 			return (0);
817 		}
818 
819 		if (query("devif: config %s blkdev", arg) == 0)
820 			return(0);
821 
822 		blkmajtodevif[bmaj] = dif;
823 	}
824 
825 	/* have a character device interface ? */
826 	if ((cmaj = dif->di_cmajor) >= 0) {
827 
828 		/* device number out of range */
829 		if (cmaj >= NDEVIF) {
830 			printf("%s: chrdev %d too big, not configured.\n",
831 				arg, cmaj);
832 			return (0);
833 		}
834 
835 		/* device already in use? */
836 		if (odif = chrmajtodevif[cmaj]) {
837 			printf("%s: chrdev %d already used by %s, not configured.\n",
838 				arg, cmaj, odif->di_name);
839 			return (0);
840 		}
841 
842 		if (query("devif: config %s chrdev", arg) == 0)
843 			return(0);
844 
845 		chrmajtodevif[cmaj] = dif;
846 	}
847 
848 	/* check sanity - all devices */
849 	if (cmaj >= 0 || bmaj >= 0) {
850 		if ((int)dif->di_open == 0)
851 			(int *) dif->di_open = (int *)nullop;
852 		if ((int)dif->di_close == 0)
853 			(int *) dif->di_close = (int *)nullop;
854 		if ((int)dif->di_ioctl == 0)
855 			(int *) dif->di_ioctl = (int *)_ENODEV_;
856 	}
857 
858 	/* check sanity - character devices */
859 	if (cmaj >= 0) {
860 		if (dif->di_strategy) {
861 			if (dif->di_read == 0)
862 				dif->di_read = rawread;
863 			if (dif->di_write == 0)
864 				dif->di_write = rawwrite;
865 		}
866 		if ((int)dif->di_select == 0)
867 			dif->di_select = seltrue;
868 		if (dif->di_write == 0)
869 			(int *)dif->di_write = _ENODEV_;
870 		if (dif->di_read == 0)
871 			(int *)dif->di_read = _ENODEV_;
872 	}
873 
874 	/* check sanity - block devices */
875 	if (bmaj >= 0) {
876 		if ((int)dif->di_strategy == 0) {
877 			blkmajtodevif[bmaj] = 0;
878 			printf("%s: blkdev %d no strategy, not configured.\n",
879 				arg, bmaj);
880 			return (0);
881 		}
882 		if ((int)dif->di_dump == 0)
883 			(int *) dif->di_dump = (int *)_ENODEV_;
884 		if ((int)dif->di_psize == 0)
885 			(int *) dif->di_psize = (int *)_ENODEV_;
886 	}
887 
888 	return (1);
889 }
890 
891 /*
892  * Kernel interface to the line discipline drivers via the ldiscif interface.
893  */
894 
895 /* open and initialize the tty associated with the device */
896 int
897 ldiscif_open(dev_t dev, struct tty *tp, int flag) {
898 	struct ldiscif *lif;
899 	unsigned line = tp->t_line;
900 	int val;
901 
902 	/* find line discipline */
903 	for (lif = ldisc; lif && lif->li_disc != line ; lif = lif->li_next)
904 		;
905 
906 	/* not found */
907 	if (lif == 0)
908 		return (ENXIO);
909 
910 	/* if a BSD UN*X line discipline ... */
911 	val = (lif->li_open)(dev, tp, flag);
912 	tp->t_ldiscif = (void *) lif;
913 	return (val);
914 }
915 
916 /* device force close the tty */
917 void
918 ldiscif_close(struct tty *tp, int flag) {
919 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
920 
921 	/* panic if closed line discipline */
922 	if (lif == 0)
923 		panic("ldiscif_close");
924 
925 	/* if a BSD UN*X line discipline ... */
926 	(lif->li_close)(tp, flag);
927 	tp->t_ldiscif = (void *) 0;
928 }
929 
930 /* perform a device read on a tty */
931 int
932 ldiscif_read(struct tty *tp, struct uio *devuio, int devflag) {
933 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
934 
935 	/* panic if closed line discipline */
936 	if (lif == 0)
937 		panic("ldiscif_read");
938 
939 	/* if a BSD UN*X line discipline ... */
940 	return ((lif->li_read)(tp, devuio, devflag));
941 }
942 
943 /* perform a device write on a tty */
944 int
945 ldiscif_write(struct tty *tp, struct uio *devuio, int devflag) {
946 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
947 
948 	/* panic if closed line discipline */
949 	if (lif == 0)
950 		panic("ldiscif_write");
951 
952 	/* if a BSD UN*X line discipline ... */
953 	return ((lif->li_write)(tp, devuio, devflag));
954 }
955 
956 /* perform a device ioctl on a tty */
957 int
958 ldiscif_ioctl(struct tty *tp, int cmd, caddr_t data, int flag, struct proc *p) {
959 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
960 
961 	/* panic if closed line discipline */
962 	if (lif == 0)
963 		panic("ldiscif_ioctl");
964 
965 	/* if a BSD UN*X line discipline ... */
966 	return ((lif->li_ioctl)(tp, cmd, data, flag, p));
967 }
968 
969 /* hand a tty a "character" */
970 void
971 ldiscif_rint(unsigned ch, struct tty *tp) {
972 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
973 
974 	/* if a BSD UN*X line discipline ... */
975 	if (lif)
976 		(lif->li_rint)(ch, tp);
977 }
978 
979 /* output a "character" via a tty */
980 unsigned
981 ldiscif_put(unsigned ch, struct tty *tp) {
982 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
983 
984 	/* if a BSD UN*X line discipline ... */
985 	if (lif)
986 		return((lif->li_put)(ch, tp));
987 	else
988 		return (ch);
989 }
990 
991 /* driver (re)initiates output on tty */
992 void
993 ldiscif_start(struct tty *tp) {
994 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
995 
996 	/* if a BSD UN*X line discipline ... */
997 	if (lif)
998 		(lif->li_start)(tp);
999 }
1000 
1001 /* inform a tty of a change with modem control */
1002 int
1003 ldiscif_modem(struct tty *tp, int flag) {
1004 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
1005 
1006 	/* if a BSD UN*X line discipline ... */
1007 	if (lif)
1008 		return ((lif->li_modem)(tp, flag));
1009 
1010 	return (1);
1011 }
1012 
1013 /* return the size of a line discipline's queue */
1014 int
1015 ldiscif_qsize(struct tty *tp, void *q) {
1016 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
1017 
1018 	/* if a BSD UN*X line discipline ... */
1019 	if (lif)
1020 		return ((lif->li_qsize)(tp, q));
1021 
1022 	return (0);
1023 }
1024 
1025 /* line discipline module to kernel configuration function */
1026 int
1027 ldiscif_config(char **cfg, struct ldiscif *lif)
1028 {
1029 	int line;
1030 	struct ldiscif *olif;
1031 	extern int _ENODEV_();
1032 
1033 	/* configure name? */
1034 	if (lif->li_name[0] == 0) {
1035 		if (!config_scan(*cfg, cfg))
1036 			return (0);
1037 		memcpy(lif->li_name, arg, sizeof(arg));
1038 	}
1039 
1040 	/* configure line index? */
1041 	if (lif->li_disc == -1 && !cfg_number(cfg, &lif->li_disc))
1042 		return (0);
1043 
1044 	/* have a line discipline interface ? */
1045 	if ((line = lif->li_disc) >= 0) {
1046 
1047 		/* attempt to find line discipline */
1048 		for (olif = ldisc; olif && olif->li_disc != line ;
1049 		    olif = lif->li_next)
1050 			;
1051 
1052 		/* device already in use? */
1053 		if (olif) {
1054 			printf("%s: ldisc %d already used by %s, not configured.\n",
1055 				arg, line, olif->li_name);
1056 			return (0);
1057 		}
1058 
1059 		if (query("ldiscif: config %s", arg) == 0)
1060 			return(0);
1061 
1062 		lif->li_next = ldisc;
1063 		ldisc = lif;
1064 	} else
1065 		return (0);
1066 
1067 	/* check sanity */
1068 	if ((int)lif->li_open == 0)
1069 		(int *) lif->li_open = (int *)_ENODEV_;
1070 	if ((int)lif->li_close == 0)
1071 		(int *) lif->li_close = (int *)_ENODEV_;
1072 	if ((int)lif->li_read == 0)
1073 		(int *) lif->li_read = (int *)_ENODEV_;
1074 	if ((int)lif->li_write == 0)
1075 		(int *) lif->li_write = (int *)_ENODEV_;
1076 	if ((int)lif->li_ioctl == 0)
1077 		(int *) lif->li_ioctl = (int *)_ENODEV_;
1078 	if ((int)lif->li_rint == 0)
1079 		(int *) lif->li_rint = (int *)_ENODEV_;
1080 	if ((int)lif->li_start == 0)
1081 		(int *) lif->li_start = (int *)_ENODEV_;
1082 	if ((int)lif->li_modem == 0)
1083 		(int *) lif->li_modem = (int *)_ENODEV_;
1084 	/* if ((int)lif->li_qsize == 0)
1085 		(int *) lif->li_qsize = def_qsize; */
1086 
1087 	return (1);
1088 }
1089 
1090 /* send a character to a console */
1091 void
1092 console_putchar(unsigned c) {
1093 
1094 	if (console_devif)
1095 	    (console_devif->di_putchar)(
1096 		makedev(console_devif->di_cmajor, console_minor), c);
1097 }
1098 
1099 /* receive a character from the console */
1100 unsigned
1101 console_getchar(void) {
1102 	int ch, s;
1103 
1104 	if (console_devif) {
1105 		/* s = splhigh(); */
1106 	    	ch = (console_devif->di_getchar)
1107 			(makedev(console_devif->di_cmajor, console_minor));
1108 		/* splx(s); */
1109 		return (ch);
1110 	} else
1111 		return (0);
1112 }
1113 
1114 /* console module configuration of a device as a console.  */
1115 int
1116 console_config(char **cons_cfg, char **mod_cfg, struct devif *dif) {
1117 	char *cfg;
1118 	char modname1[80]; /* XXX - should allow arbitrary size... */
1119 	int dummy;
1120 
1121 	/* is this a default console? */
1122 	cfg = *cons_cfg;
1123 
1124 	/* is there a console defined? */
1125 	if (config_scan(cfg, cons_cfg) == 0)
1126 		return (0);
1127 
1128 	/* is there an effective console module? */
1129 	if (cfg_string(cons_cfg, modname1, sizeof(modname1)) == 0)
1130 		return(0);
1131 
1132 	/* is the requested console module configurable? */
1133 	cfg = *mod_cfg;
1134 	if (config_scan(cfg, mod_cfg) == 0)
1135 		return (0);
1136 
1137 	/* default console */
1138 	if (strcmp(modname1, "default") == 0)
1139 		default_console_devif = dif;
1140 
1141 	/* is it the same module? */
1142 	else if (strcmp(modname1, arg) != 0)
1143 		return(0);
1144 
1145 	/* set minor device */
1146 	console_minor = 0;
1147 	(void)cfg_number(cons_cfg, &console_minor);
1148 
1149 	/* consume major unit */
1150 	(void)cfg_number(mod_cfg, &dummy);
1151 
1152 	/* set console device interface */
1153 	/*console_devif = dif;*/
1154 	chrmajtodevif[0] = dif;
1155 
1156 	/* if not default console, record use of console */
1157 	if (default_console_devif == 0) {
1158 		DELAY(10000);
1159 		printf("using console %s\n", dif->di_name);
1160 	}
1161 
1162 	return (1);
1163 }
1164 
1165 int
1166 query(char *s, ...) {
1167 
1168 	return (1);
1169 }
1170 
1171 #ifndef DDB
1172 void
1173 Debugger (char *s) {
1174 	pg(s);
1175 }
1176 #endif
1177