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