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