xref: /386bsd/usr/src/kernel/kern/config.c (revision a2142627)
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 $
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 *
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
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
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
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
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
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
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
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
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
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 /*
345  * Kernel interface to device drivers.
346  */
347 
348 #define NDEVIF	100	/* more than adequate */
349 struct devif *chrmajtodevif[NDEVIF], *blkmajtodevif[NDEVIF];
350 
351 /* fill in the name of the supplied device in a supplied string buffer */
352 int
353 devif_name(dev_t dev, devif_type_t typ, char *name, int namelen) {
354 	struct devif *dif;
355 	unsigned major = major(dev);
356 	int minor;
357 	char *fp, tmpbuf[16];
358 
359 	switch (typ) {
360 	case CHRDEV:
361 	    	if (major > sizeof chrmajtodevif / sizeof chrmajtodevif[0] ||
362 		    (dif = chrmajtodevif[major]) == 0)
363 			return (ENODEV);
364 		break;
365 
366 	case BLKDEV:
367 	    	if (major > sizeof blkmajtodevif / sizeof blkmajtodevif[0] ||
368 		    (dif = blkmajtodevif[major]) == 0)
369 			return (ENODEV);
370 		break;
371 
372 	default:
373 		panic("devif_name");	/* unimplemented device type */
374 	}
375 
376 	/* put in device name */
377 	fp = dif->di_name;
378 	while (namelen) {
379 		*name++ = *fp++;
380 		namelen--;
381 	}
382 
383 	/* construct minor device name with unit & subunit */
384 	minor = minor(dev);
385 	tmpbuf[0] = 0;
386 	if (dif->di_minor_unit_mask && dif->di_minor_subunit_mask)
387 		sprintf(tmpbuf,"%d%c",
388 	    	    (minor & dif->di_minor_unit_mask)
389 			>> dif->di_minor_unit_shift,
390 	    	    ((minor & dif->di_minor_subunit_mask)
391 			>> dif->di_minor_subunit_shift) + 'a');
392 
393 	/* ... or construct minor device name with unit */
394 	else if (dif->di_minor_unit_mask && dif->di_minor_subunit_mask)
395 		sprintf(tmpbuf,"%d",
396 	    	    (minor & dif->di_minor_unit_mask)
397 			>> dif->di_minor_unit_shift);
398 
399 	/* put into name */
400 	fp = tmpbuf;
401 	while (namelen && *fp) {
402 		*name++ = *fp++;
403 		namelen--;
404 	}
405 }
406 
407 /* check and adjust a bootdev's parameters so as to create a root device */
408 int
409 devif_root(unsigned major, unsigned unit, unsigned subunit, dev_t *rd)
410 {
411 	struct devif *dif;
412 
413 	/* should we configure this as root? */
414 	if (query("devif_root: major %d unit %d sub %d\n",
415 		major, unit, subunit) == 0)
416 			return (0);
417 
418 	/* is there a device driver for the root? */
419 	if (major >= NDEVIF || (dif = blkmajtodevif[major]) == 0)
420 		return (0);
421 
422 	/* turn a boot dev set of parameters into the root dev */
423 	*rd = makedev(major, ((unit) << dif->di_minor_unit_shift)
424 		+ ((subunit) << dif->di_minor_subunit_shift));
425 
426 	return (1);
427 }
428 
429 /* locate and call a device driver open routine via the device driver interface */
430 int
431 devif_open(dev_t dev, devif_type_t typ, int flag, struct proc *p) {
432 	struct devif *dif;
433 	unsigned major = major(dev);
434 
435 	/* if a BSD UN*X character device ... */
436 	if (typ == CHRDEV &&
437 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
438 		dif = chrmajtodevif[major];
439 		if (dif == console_devif)
440 			dev = makedev(major, console_minor);
441 		if (dif)
442 			return ((dif->di_open)(dev, flag, S_IFCHR, p));
443 
444 		return (ENXIO);
445 	}
446 
447 	/* if a BSD UN*X block device ... */
448 	if (typ == BLKDEV &&
449 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
450 		if (dif = blkmajtodevif[major])
451 			return ((dif->di_open)(dev, flag, S_IFBLK, p));
452 
453 		return (ENXIO);
454 	}
455 
456 	/* add support for new types here */
457 #ifdef	notyet
458 	/* if a 386BSD UNICODE character device ... */
459 	if (typ == WCHRDEV &&
460 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
461 		if (dif = chrmajtodevif[major])
462 			return ((dif->di_open)(dev, flag, S_IFWCHR, p));
463 
464 		return (ENXIO);
465 	}
466 
467 	/* if a 386BSD page i/o device ... */
468 	if (typ == PAGEDEV &&
469 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
470 		if (dif = chrmajtodevif[major])
471 			return ((dif->di_open)(dev, flag, S_IFPAGE, p));
472 
473 		return (ENXIO);
474 	}
475 #endif
476 	panic("devif_open");	/* unimplemented type */
477 }
478 
479 /* locate and call a device driver close routine via the device driver interface */
480 int
481 devif_close(dev_t dev, devif_type_t typ, int flag, struct proc *p) {
482 	struct devif *dif;
483 	unsigned major = major(dev);
484 
485 	/* if a BSD UN*X character device ... */
486 	if (typ == CHRDEV &&
487 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
488 		dif = chrmajtodevif[major];
489 		if (dif == console_devif)
490 			dev = makedev(major, console_minor);
491 		if (dif)
492 			return ((dif->di_close)(dev, flag, S_IFCHR, p));
493 
494 		return (ENODEV);
495 	}
496 
497 	/* if a BSD UN*X block device ... */
498 	if (typ == BLKDEV &&
499 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
500 		if (dif = blkmajtodevif[major])
501 			return ((dif->di_close)(dev, flag, S_IFBLK, p));
502 
503 		return (ENODEV);
504 	}
505 
506 	/* add support for new types here */
507 #ifdef	notyet
508 	/* if a 386BSD UNICODE character device ... */
509 	if (typ == WCHRDEV &&
510 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
511 		if (dif = chrmajtodevif[major])
512 			return ((dif->di_close)(dev, flag, S_IFWCHR, p));
513 		return (ENXIO);
514 	}
515 
516 	/* if a 386BSD page i/o device ... */
517 	if (typ == PAGEDEV &&
518 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
519 		if (dif = chrmajtodevif[major])
520 			return ((dif->di_close)(dev, flag, S_IFPAGE, p));
521 		return (ENXIO);
522 	}
523 #endif
524 	panic("devif_close");	/* unimplemented type */
525 }
526 
527 /* locate and call a device driver ioctl routine via the device driver interface */
528 int
529 devif_ioctl(dev_t dev, devif_type_t typ, int cmd, caddr_t data, int flag,
530     struct proc *p) {
531 	struct devif *dif;
532 	unsigned major = major(dev);
533 
534 	/* if a BSD UN*X character device ... */
535 	if (typ == CHRDEV &&
536 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
537 	chrcase:
538 		dif = chrmajtodevif[major];
539 		if (dif == console_devif)
540 			dev = makedev(major, console_minor);
541 		if (dif)
542 			return ((dif->di_ioctl)(dev, cmd, data, flag, p));
543 
544 		return (ENODEV);
545 	}
546 
547 	/* if a BSD UN*X block device ... */
548 	if (typ == BLKDEV &&
549 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
550 		if (dif = blkmajtodevif[major])
551 			return ((dif->di_ioctl)(dev, cmd, data, flag, p));
552 
553 		return (ENODEV);
554 	}
555 
556 	/* add support for new types here */
557 #ifdef notyet
558 	/* if either a 386BSD UNICODE or page character device ... */
559 	if ((typ == WCHRDEV || typ == PAGEDEV)) &&
560 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
561 		goto chrcase;
562 #endif
563 	panic("devif_ioctl");	/* unimplemented type */
564 }
565 
566 /* locate and call a device driver read routine via the device driver interface */
567 int
568 devif_read(dev_t dev, devif_type_t typ, struct uio *uio, int flag) {
569 	struct devif *dif;
570 	unsigned major = major(dev);
571 
572 	/* if a BSD UN*X character device ... */
573 	if (typ == CHRDEV &&
574 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
575 		dif = chrmajtodevif[major];
576 		if (dif == console_devif)
577 			dev = makedev(major, console_minor);
578 		if (dif)
579 			return ((dif->di_read)(dev, uio, flag));
580 
581 		return (ENODEV);
582 	}
583 
584 	/* add support for new types here */
585 #ifdef notyet
586 	/* if a 386BSD UNICODE character device ... */
587 	if (typ == WCHRDEV &&
588 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
589 		if (dif = chrmajtodevif[major])
590 			return ((dif->di_wcread)(dev, uio, flag));
591 		return (ENODEV);
592 	}
593 
594 	/* if a 386BSD page i/o device ... */
595 	if (typ == PAGEDEV &&
596 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
597 		if (dif = chrmajtodevif[major])
598 			return ((dif->di_pageread)(dev, uio, flag));
599 		return (ENODEV);
600 	}
601 #endif
602 	panic("devif_read");	/* unimplemented type */
603 }
604 
605 /* locate and call a device driver write routine via the device driver interface */
606 int
607 devif_write(dev_t dev, devif_type_t typ, struct uio *uio, int flag) {
608 	struct devif *dif;
609 	unsigned major = major(dev);
610 
611 	/* if a BSD UN*X character device ... */
612 	if (typ == CHRDEV &&
613 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
614 		dif = chrmajtodevif[major];
615 		if (dif == console_devif)
616 			dev = makedev(major, console_minor);
617 		if (dif)
618 			return ((dif->di_write)(dev, uio, flag));
619 
620 		return (ENODEV);
621 	}
622 
623 	/* add support for new types here */
624 #ifdef notyet
625 	/* if a 386BSD UNICODE character device ... */
626 	if (typ == WCHRDEV &&
627 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
628 		if (dif = chrmajtodevif[major])
629 			return ((dif->di_wcwrite)(dev, uio, flag));
630 		return (ENXIO);
631 	}
632 
633 	/* if a 386BSD page i/o device ... */
634 	if (typ == PAGEDEV &&
635 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
636 		if (dif = chrmajtodevif[major])
637 			return ((dif->di_pagewrite)(dev, uio, flag));
638 		return (ENXIO);
639 	}
640 #endif
641 	panic("devif_write");	/* unimplemented type */
642 }
643 
644 /* locate and call a device driver select routine via the device driver interface */
645 int
646 devif_select(dev_t dev, devif_type_t typ, int rw, struct proc *p) {
647 	struct devif *dif;
648 	unsigned major = major(dev);
649 
650 	/* if a BSD UN*X character device ... */
651 	if (typ == CHRDEV &&
652 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
653 	chrcase:
654 		dif = chrmajtodevif[major];
655 		if (dif == console_devif)
656 			dev = makedev(major, console_minor);
657 		if (dif)
658 			return ((dif->di_select)(dev, rw, p));
659 
660 		return (ENODEV);
661 	}
662 
663 	/* add support for new types here */
664 #ifdef notyet
665 	/* if either a 386BSD UNICODE or page character device ... */
666 	if ((typ == WCHRDEV || typ == PAGEDEV)) &&
667 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
668 		goto chrcase;
669 #endif
670 	panic("devif_select");	/* unimplemented type */
671 }
672 
673 /* locate and call a device driver mmap routine via the device driver interface */
674 int
675 devif_mmap(dev_t dev, devif_type_t typ, int offset, int nprot) {
676 	struct devif *dif;
677 	unsigned major = major(dev);
678 
679 	/* if a BSD UN*X character device ... */
680 	if (typ == CHRDEV &&
681 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
682 		dif = chrmajtodevif[major];
683 		if (dif == console_devif)
684 			dev = makedev(major, console_minor);
685 		if (dif)
686 			return ((dif->di_mmap)(dev, offset, nprot));
687 
688 		return (-1);
689 	}
690 
691 	/* add support for new types here */
692 	panic("devif_mmap");	/* unimplemented type */
693 }
694 
695 /* locate and call a device driver strategy routine via the device driver interface */
696 int
697 devif_strategy(devif_type_t typ, struct buf *bp) {
698 	struct devif *dif;
699 	unsigned major = major(bp->b_dev);
700 
701 	/* if a BSD UN*X character device ... */
702 	if (typ == CHRDEV &&
703 	    major < sizeof chrmajtodevif / sizeof chrmajtodevif[0]) {
704 		if (dif = chrmajtodevif[major])
705 			return ((dif->di_strategy)(bp));
706 
707 		return (ENODEV);
708 	}
709 
710 	/* if a BSD UN*X block device ... */
711 	if (typ == BLKDEV &&
712 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
713 		if (dif = blkmajtodevif[major])
714 			return ((dif->di_strategy)(bp));
715 
716 		return (ENODEV);
717 	}
718 
719 	panic("devif_strategy");	/* illegal type */
720 }
721 
722 /* locate and call a device driver size routine via the device driver interface */
723 int
724 devif_psize(dev_t dev, devif_type_t typ) {
725 	struct devif *dif;
726 	unsigned major = major(dev);
727 
728 	/* if a BSD UN*X block device ... */
729 	if (typ == BLKDEV &&
730 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
731 		if (dif = blkmajtodevif[major])
732 			return ((dif->di_psize)(dev));
733 
734 		return (0);
735 	}
736 
737 	panic("devif_psize");	/* illegal type */
738 }
739 
740 /* locate and call a device driver dump routine via the device driver interface */
741 int
742 devif_dump(dev_t dev, devif_type_t typ) {
743 	struct devif *dif;
744 	unsigned major = major(dev);
745 
746 	/* if a BSD UN*X block device ... */
747 	if (typ == BLKDEV &&
748 	    major < sizeof blkmajtodevif / sizeof blkmajtodevif[0]) {
749 		if (dif = blkmajtodevif[major])
750 			return ((dif->di_dump)(dev));
751 	}
752 
753 	return (ENODEV);
754 }
755 
756 /* configure a BSD UN*X device by registering its "devif" interface */
757 int
758 devif_config(char **cfg, struct devif *dif)
759 {
760 	int bmaj, cmaj;
761 	struct devif *odif;
762 	extern int _ENODEV_();
763 
764 	/* configure name? */
765 	if (dif->di_name[0] == 0) {
766 		if (!config_scan(*cfg, cfg))
767 			return (0);
768 		memcpy(dif->di_name, arg, sizeof(arg));
769 	}
770 
771 	/* configure block device? */
772 	if (dif->di_bmajor == -1 && !cfg_number(cfg, &dif->di_bmajor))
773 		return (0);
774 
775 	/* configure character device? */
776 	if (dif->di_cmajor == -1 && !cfg_number(cfg, &dif->di_cmajor))
777 		return (0);
778 
779 	/* have a block device interface ? */
780 	if ((bmaj = dif->di_bmajor) >= 0) {
781 		struct devif *odif;
782 
783 		/* device number out of range */
784 		if (bmaj >= NDEVIF) {
785 			printf("%s: blkdev %d too big, not configured.\n",
786 				arg, bmaj);
787 			return (0);
788 		}
789 
790 		/* device already in use? */
791 		if (odif = blkmajtodevif[bmaj]) {
792 			printf("%s: blkdev %d already used by %s, not configured.\n",
793 				arg, bmaj, odif->di_name);
794 			return (0);
795 		}
796 
797 		if (query("devif: config %s blkdev", arg) == 0)
798 			return(0);
799 
800 		blkmajtodevif[bmaj] = dif;
801 	}
802 
803 	/* have a character device interface ? */
804 	if ((cmaj = dif->di_cmajor) >= 0) {
805 
806 		/* device number out of range */
807 		if (cmaj >= NDEVIF) {
808 			printf("%s: chrdev %d too big, not configured.\n",
809 				arg, cmaj);
810 			return (0);
811 		}
812 
813 		/* device already in use? */
814 		if (odif = chrmajtodevif[cmaj]) {
815 			printf("%s: chrdev %d already used by %s, not configured.\n",
816 				arg, cmaj, odif->di_name);
817 			return (0);
818 		}
819 
820 		if (query("devif: config %s chrdev", arg) == 0)
821 			return(0);
822 
823 		chrmajtodevif[cmaj] = dif;
824 	}
825 
826 	/* check sanity - all devices */
827 	if (cmaj >= 0 || bmaj >= 0) {
828 		if ((int)dif->di_open == 0)
829 			(int *) dif->di_open = (int *)nullop;
830 		if ((int)dif->di_close == 0)
831 			(int *) dif->di_close = (int *)nullop;
832 		if ((int)dif->di_ioctl == 0)
833 			(int *) dif->di_ioctl = (int *)_ENODEV_;
834 	}
835 
836 	/* check sanity - character devices */
837 	if (cmaj >= 0) {
838 		if (dif->di_strategy) {
839 			if (dif->di_read == 0)
840 				dif->di_read = rawread;
841 			if (dif->di_write == 0)
842 				dif->di_write = rawwrite;
843 		}
844 		if ((int)dif->di_select == 0)
845 			dif->di_select = seltrue;
846 		if (dif->di_write == 0)
847 			(int *)dif->di_write = _ENODEV_;
848 		if (dif->di_read == 0)
849 			(int *)dif->di_read = _ENODEV_;
850 	}
851 
852 	/* check sanity - block devices */
853 	if (bmaj >= 0) {
854 		if ((int)dif->di_strategy == 0) {
855 			blkmajtodevif[bmaj] = 0;
856 			printf("%s: blkdev %d no strategy, not configured.\n",
857 				arg, bmaj);
858 			return (0);
859 		}
860 		if ((int)dif->di_dump == 0)
861 			(int *) dif->di_dump = (int *)_ENODEV_;
862 		if ((int)dif->di_psize == 0)
863 			(int *) dif->di_psize = (int *)_ENODEV_;
864 	}
865 
866 	return (1);
867 }
868 
869 /*
870  * Kernel interface to the line discipline drivers via the ldiscif interface.
871  */
872 
873 /* open and initialize the tty associated with the device */
874 int
875 ldiscif_open(dev_t dev, struct tty *tp, int flag) {
876 	struct ldiscif *lif;
877 	unsigned line = tp->t_line;
878 	int val;
879 
880 	/* find line discipline */
881 	for (lif = ldisc; lif && lif->li_disc != line ; lif = lif->li_next)
882 		;
883 
884 	/* not found */
885 	if (lif == 0)
886 		return (ENXIO);
887 
888 	/* if a BSD UN*X line discipline ... */
889 	val = (lif->li_open)(dev, tp, flag);
890 	tp->t_ldiscif = (void *) lif;
891 	return (val);
892 }
893 
894 /* device force close the tty */
895 void
896 ldiscif_close(struct tty *tp, int flag) {
897 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
898 
899 	/* panic if closed line discipline */
900 	if (lif == 0)
901 		panic("ldiscif_close");
902 
903 	/* if a BSD UN*X line discipline ... */
904 	(lif->li_close)(tp, flag);
905 	tp->t_ldiscif = (void *) 0;
906 }
907 
908 /* perform a device read on a tty */
909 int
910 ldiscif_read(struct tty *tp, struct uio *devuio, int devflag) {
911 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
912 
913 	/* panic if closed line discipline */
914 	if (lif == 0)
915 		panic("ldiscif_read");
916 
917 	/* if a BSD UN*X line discipline ... */
918 	return ((lif->li_read)(tp, devuio, devflag));
919 }
920 
921 /* perform a device write on a tty */
922 int
923 ldiscif_write(struct tty *tp, struct uio *devuio, int devflag) {
924 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
925 
926 	/* panic if closed line discipline */
927 	if (lif == 0)
928 		panic("ldiscif_write");
929 
930 	/* if a BSD UN*X line discipline ... */
931 	return ((lif->li_write)(tp, devuio, devflag));
932 }
933 
934 /* perform a device ioctl on a tty */
935 int
936 ldiscif_ioctl(struct tty *tp, int cmd, caddr_t data, int flag, struct proc *p) {
937 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
938 
939 	/* panic if closed line discipline */
940 	if (lif == 0)
941 		panic("ldiscif_ioctl");
942 
943 	/* if a BSD UN*X line discipline ... */
944 	return ((lif->li_ioctl)(tp, cmd, data, flag, p));
945 }
946 
947 /* hand a tty a "character" */
948 void
949 ldiscif_rint(unsigned ch, struct tty *tp) {
950 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
951 
952 	/* if a BSD UN*X line discipline ... */
953 	if (lif)
954 		(lif->li_rint)(ch, tp);
955 }
956 
957 /* output a "character" via a tty */
958 unsigned
959 ldiscif_put(unsigned ch, struct tty *tp) {
960 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
961 
962 	/* if a BSD UN*X line discipline ... */
963 	if (lif)
964 		return((lif->li_put)(ch, tp));
965 	else
966 		return (ch);
967 }
968 
969 /* driver (re)initiates output on tty */
970 void
971 ldiscif_start(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_start)(tp);
977 }
978 
979 /* inform a tty of a change with modem control */
980 int
981 ldiscif_modem(struct tty *tp, int flag) {
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_modem)(tp, flag));
987 
988 	return (1);
989 }
990 
991 /* return the size of a line discipline's queue */
992 int
993 ldiscif_qsize(struct tty *tp, void *q) {
994 	struct ldiscif *lif = (struct ldiscif *)tp->t_ldiscif;
995 
996 	/* if a BSD UN*X line discipline ... */
997 	if (lif)
998 		return ((lif->li_qsize)(tp, q));
999 
1000 	return (0);
1001 }
1002 
1003 /* line discipline module to kernel configuration function */
1004 int
1005 ldiscif_config(char **cfg, struct ldiscif *lif)
1006 {
1007 	int line;
1008 	struct ldiscif *olif;
1009 	extern int _ENODEV_();
1010 
1011 	/* configure name? */
1012 	if (lif->li_name[0] == 0) {
1013 		if (!config_scan(*cfg, cfg))
1014 			return (0);
1015 		memcpy(lif->li_name, arg, sizeof(arg));
1016 	}
1017 
1018 	/* configure line index? */
1019 	if (lif->li_disc == -1 && !cfg_number(cfg, &lif->li_disc))
1020 		return (0);
1021 
1022 	/* have a line discipline interface ? */
1023 	if ((line = lif->li_disc) >= 0) {
1024 
1025 		/* attempt to find line discipline */
1026 		for (olif = ldisc; olif && olif->li_disc != line ;
1027 		    olif = lif->li_next)
1028 			;
1029 
1030 		/* device already in use? */
1031 		if (olif) {
1032 			printf("%s: ldisc %d already used by %s, not configured.\n",
1033 				arg, line, olif->li_name);
1034 			return (0);
1035 		}
1036 
1037 		if (query("ldiscif: config %s", arg) == 0)
1038 			return(0);
1039 
1040 		lif->li_next = ldisc;
1041 		ldisc = lif;
1042 	} else
1043 		return (0);
1044 
1045 	/* check sanity */
1046 	if ((int)lif->li_open == 0)
1047 		(int *) lif->li_open = (int *)_ENODEV_;
1048 	if ((int)lif->li_close == 0)
1049 		(int *) lif->li_close = (int *)_ENODEV_;
1050 	if ((int)lif->li_read == 0)
1051 		(int *) lif->li_read = (int *)_ENODEV_;
1052 	if ((int)lif->li_write == 0)
1053 		(int *) lif->li_write = (int *)_ENODEV_;
1054 	if ((int)lif->li_ioctl == 0)
1055 		(int *) lif->li_ioctl = (int *)_ENODEV_;
1056 	if ((int)lif->li_rint == 0)
1057 		(int *) lif->li_rint = (int *)_ENODEV_;
1058 	if ((int)lif->li_start == 0)
1059 		(int *) lif->li_start = (int *)_ENODEV_;
1060 	if ((int)lif->li_modem == 0)
1061 		(int *) lif->li_modem = (int *)_ENODEV_;
1062 	/* if ((int)lif->li_qsize == 0)
1063 		(int *) lif->li_qsize = def_qsize; */
1064 
1065 	return (1);
1066 }
1067 
1068 /* send a character to a console */
1069 void
1070 console_putchar(unsigned c) {
1071 
1072 	if (console_devif)
1073 	    (console_devif->di_putchar)(
1074 		makedev(console_devif->di_cmajor, console_minor), c);
1075 }
1076 
1077 /* receive a character from the console */
1078 unsigned
1079 console_getchar(void) {
1080 	int ch, s;
1081 
1082 	if (console_devif) {
1083 		/* s = splhigh(); */
1084 	    	ch = (console_devif->di_getchar)
1085 			(makedev(console_devif->di_cmajor, console_minor));
1086 		/* splx(s); */
1087 		return (ch);
1088 	} else
1089 		return (0);
1090 }
1091 
1092 /* console module configuration of a device as a console.  */
1093 int
1094 console_config(char **cons_cfg, char **mod_cfg, struct devif *dif) {
1095 	char *cfg;
1096 	char modname1[80]; /* XXX - should allow arbitrary size... */
1097 	int dummy;
1098 
1099 	/* is this a default console? */
1100 	cfg = *cons_cfg;
1101 
1102 	/* is there a console defined? */
1103 	if (config_scan(cfg, cons_cfg) == 0)
1104 		return (0);
1105 
1106 	/* is there an effective console module? */
1107 	if (cfg_string(cons_cfg, modname1, sizeof(modname1)) == 0)
1108 		return(0);
1109 
1110 	/* is the requested console module configurable? */
1111 	cfg = *mod_cfg;
1112 	if (config_scan(cfg, mod_cfg) == 0)
1113 		return (0);
1114 
1115 	/* default console */
1116 	if (strcmp(modname1, "default") == 0)
1117 		default_console_devif = dif;
1118 
1119 	/* is it the same module? */
1120 	else if (strcmp(modname1, arg) != 0)
1121 		return(0);
1122 
1123 	/* set minor device */
1124 	console_minor = 0;
1125 	(void)cfg_number(cons_cfg, &console_minor);
1126 
1127 	/* consume major unit */
1128 	(void)cfg_number(mod_cfg, &dummy);
1129 
1130 	/* set console device interface */
1131 	/*console_devif = dif;*/
1132 	chrmajtodevif[0] = dif;
1133 
1134 	/* if not default console, record use of console */
1135 	if (default_console_devif == 0) {
1136 		DELAY(10000);
1137 		printf("using console %s\n", dif->di_name);
1138 	}
1139 
1140 	return (1);
1141 }
1142 
1143 int
1144 query(char *s, ...) {
1145 
1146 	return (1);
1147 }
1148 
1149 #ifndef DDB
1150 void
1151 Debugger (char *s) {
1152 	pg(s);
1153 }
1154 #endif
1155