1 /* $NetBSD: machdep.c,v 1.30 2001/09/15 01:19:38 wdk Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department, The Mach Operating System project at 11 * Carnegie-Mellon University and Ralph Campbell. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 42 */ 43 44 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 45 46 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.30 2001/09/15 01:19:38 wdk Exp $"); 47 48 /* from: Utah Hdr: machdep.c 1.63 91/04/24 */ 49 50 #include "opt_ddb.h" 51 #include "opt_kgdb.h" 52 53 #include <sys/param.h> 54 #include <sys/signalvar.h> 55 #include <sys/kernel.h> 56 #include <sys/map.h> 57 #include <sys/proc.h> 58 #include <sys/buf.h> 59 #include <sys/reboot.h> 60 #include <sys/conf.h> 61 #include <sys/file.h> 62 #include <sys/callout.h> 63 #include <sys/malloc.h> 64 #include <sys/mbuf.h> 65 #include <sys/msgbuf.h> 66 #include <sys/ioctl.h> 67 #include <sys/device.h> 68 #include <sys/user.h> 69 #include <sys/exec.h> 70 #include <sys/sysctl.h> 71 #include <sys/mount.h> 72 #include <sys/syscallargs.h> 73 #include <sys/kcore.h> 74 75 #include <uvm/uvm_extern.h> 76 77 #include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 78 79 #include <machine/cpu.h> 80 #include <machine/reg.h> 81 #include <machine/psl.h> 82 #include <machine/pte.h> 83 84 #ifdef DDB 85 #include <machine/db_machdep.h> 86 #include <ddb/db_extern.h> 87 #endif 88 89 #include <machine/intr.h> 90 #include <machine/mainboard.h> 91 #include <machine/sysconf.h> 92 #include <machine/autoconf.h> 93 #include <machine/bootinfo.h> 94 #include <machine/prom.h> 95 #include <dev/clock_subr.h> 96 #include <dev/cons.h> 97 98 #include <sys/boot_flag.h> 99 100 #include "fs_mfs.h" 101 #include "opt_ddb.h" 102 #include "opt_execfmt.h" 103 104 #include "zsc.h" /* XXX */ 105 #include "com.h" /* XXX */ 106 107 /* the following is used externally (sysctl_hw) */ 108 char machine[] = MACHINE; /* from <machine/param.h> */ 109 char machine_arch[] = MACHINE_ARCH; 110 char cpu_model[40]; 111 112 /* Our exported CPU info; we can have only one. */ 113 struct cpu_info cpu_info_store; 114 115 /* maps for VM objects */ 116 117 struct vm_map *exec_map = NULL; 118 struct vm_map *mb_map = NULL; 119 struct vm_map *phys_map = NULL; 120 121 int physmem; /* max supported memory, changes to actual */ 122 char *bootinfo = NULL; /* pointer to bootinfo structure */ 123 124 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 125 int mem_cluster_cnt; 126 127 void to_monitor __P((int)) __attribute__((__noreturn__)); 128 void prom_halt __P((int)) __attribute__((__noreturn__)); 129 130 #ifdef KGDB 131 void zs_kgdb_init __P((void)); 132 void kgdb_connect __P((int)); 133 #endif 134 135 struct evcnt soft_evcnt[IPL_NSOFT]; 136 137 /* 138 * Local functions. 139 */ 140 int initcpu __P((void)); 141 void configure __P((void)); 142 143 void mach_init __P((int, char *[], char*[], u_int, char *)); 144 int memsize_scan __P((caddr_t)); 145 146 #ifdef DEBUG 147 /* stacktrace code violates prototypes to get callee's registers */ 148 extern void stacktrace __P((void)); /*XXX*/ 149 #endif 150 151 /* 152 * safepri is a safe priority for sleep to set for a spin-wait 153 * during autoconfiguration or after a panic. Used as an argument to splx(). 154 * XXX disables interrupt 5 to disable mips3 on-chip clock, which also 155 * disables mips1 FPU interrupts. 156 */ 157 int safepri = MIPS3_PSL_LOWIPL; /* XXX */ 158 extern struct user *proc0paddr; 159 160 /* locore callback-vector setup */ 161 extern void mips_vector_init __P((void)); 162 extern void prom_init __P((void)); 163 extern void pizazz_init __P((void)); 164 165 /* platform-specific initialization vector */ 166 static void unimpl_cons_init __P((void)); 167 static void unimpl_iointr __P((unsigned, unsigned, unsigned, unsigned)); 168 static int unimpl_memsize __P((caddr_t)); 169 static unsigned unimpl_clkread __P((void)); 170 static void unimpl_todr __P((struct clock_ymdhms *)); 171 static void unimpl_intr_establish __P((int, int (*)__P((void *)), void *)); 172 173 struct platform platform = { 174 "iobus not set", 175 unimpl_cons_init, 176 unimpl_iointr, 177 unimpl_memsize, 178 unimpl_clkread, 179 unimpl_todr, 180 unimpl_todr, 181 unimpl_intr_establish, 182 }; 183 184 struct consdev *cn_tab = NULL; 185 extern struct consdev consdev_prom; 186 extern struct consdev consdev_zs; 187 188 static void null_cnprobe __P((struct consdev *)); 189 static void prom_cninit __P((struct consdev *)); 190 static int prom_cngetc __P((dev_t)); 191 static void prom_cnputc __P((dev_t, int)); 192 static void null_cnpollc __P((dev_t, int)); 193 194 struct consdev consdev_prom = { 195 null_cnprobe, 196 prom_cninit, 197 prom_cngetc, 198 prom_cnputc, 199 null_cnpollc, 200 }; 201 202 203 /* 204 * Do all the stuff that locore normally does before calling main(). 205 * Process arguments passed to us by the prom monitor. 206 * Return the first page address following the system. 207 */ 208 void 209 mach_init(argc, argv, envp, bim, bip) 210 int argc; 211 char *argv[]; 212 char *envp[]; 213 u_int bim; 214 char *bip; 215 { 216 u_long first, last; 217 caddr_t kernend, v; 218 vsize_t size; 219 char *cp; 220 int i, howto; 221 extern char edata[], end[]; 222 char *bi_msg; 223 #ifdef DDB 224 int nsym = 0; 225 caddr_t ssym = 0; 226 caddr_t esym = 0; 227 struct btinfo_symtab *bi_syms; 228 #endif 229 230 231 /* Check for valid bootinfo passed from bootstrap */ 232 if (bim == BOOTINFO_MAGIC) { 233 struct btinfo_magic *bi_magic; 234 235 bootinfo = (char *)BOOTINFO_ADDR; /* XXX */ 236 bi_magic = lookup_bootinfo(BTINFO_MAGIC); 237 if (bi_magic == NULL || bi_magic->magic != BOOTINFO_MAGIC) 238 bi_msg = "invalid bootinfo structure.\n"; 239 else 240 bi_msg = NULL; 241 } else 242 bi_msg = "invalid bootinfo (standalone boot?)\n"; 243 244 /* clear the BSS segment */ 245 kernend = (caddr_t)mips_round_page(end); 246 memset(edata, 0, end - edata); 247 248 #ifdef DDB 249 bi_syms = lookup_bootinfo(BTINFO_SYMTAB); 250 251 /* Load sysmbol table if present */ 252 if (bi_syms != NULL) { 253 nsym = bi_syms->nsym; 254 ssym = (caddr_t)bi_syms->ssym; 255 esym = (caddr_t)bi_syms->esym; 256 kernend = (caddr_t)mips_round_page(esym); 257 } 258 #endif 259 260 prom_init(); 261 consinit(); 262 263 if (bi_msg != NULL) 264 printf(bi_msg); 265 266 /* 267 * Set the VM page size. 268 */ 269 uvm_setpagesize(); 270 271 /* Find out how much memory is available. */ 272 physmem = memsize_scan(kernend); 273 274 /* 275 * Now that we know how much memory we have, initialize the 276 * mem cluster array. 277 */ 278 mem_clusters[0].start = 0; /* XXX is this correct? */ 279 mem_clusters[0].size = ctob(physmem); 280 mem_cluster_cnt = 1; 281 282 /* 283 * Copy exception-dispatch code down to exception vector. 284 * Initialize locore-function vector. 285 * Clear out the I and D caches. 286 */ 287 mips_vector_init(); 288 289 /* Look at argv[0] and compute bootdev */ 290 makebootdev(argv[0]); 291 292 /* 293 * Look at arguments passed to us and compute boothowto. 294 */ 295 boothowto = RB_AUTOBOOT; 296 for (i = 1; i < argc; i++) { 297 for (cp = argv[i]; *cp; cp++) { 298 /* Ignore superfluous '-', if there is one */ 299 if (*cp == '-') 300 continue; 301 302 howto = 0; 303 BOOT_FLAG(*cp, howto); 304 if (! howto) 305 printf("bootflag '%c' not recognised\n", *cp); 306 else 307 boothowto |= howto; 308 } 309 } 310 311 312 #ifdef DDB 313 /* init symbols if present */ 314 if (esym) 315 ddb_init(esym - ssym, ssym, esym); 316 if (boothowto & RB_KDB) 317 Debugger(); 318 #endif 319 #ifdef KGDB 320 zs_kgdb_init(); /* XXX */ 321 if (boothowto & RB_KDB) 322 kgdb_connect(0); 323 #endif 324 325 #ifdef MFS 326 /* 327 * Check to see if a mini-root was loaded into memory. It resides 328 * at the start of the next page just after the end of BSS. 329 */ 330 if (boothowto & RB_MINIROOT) 331 kernend += round_page(mfs_initminiroot(kernend)); 332 #endif 333 334 /* 335 * Load the rest of the available pages into the VM system. 336 */ 337 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 338 last = mem_clusters[0].start + mem_clusters[0].size; 339 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 340 VM_FREELIST_DEFAULT); 341 342 /* 343 * Initialize error message buffer (at end of core). 344 */ 345 mips_init_msgbuf(); 346 347 /* 348 * Compute the size of system data structures. pmap_bootstrap() 349 * needs some of this information. 350 */ 351 size = (vsize_t)allocsys(NULL, NULL); 352 353 /* 354 * Initialize the virtual memory system. 355 */ 356 pmap_bootstrap(); 357 358 /* 359 * Allocate space for proc0's USPACE. 360 */ 361 v = (caddr_t)uvm_pageboot_alloc(USPACE); 362 proc0.p_addr = proc0paddr = (struct user *)v; 363 proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1; 364 curpcb = &proc0.p_addr->u_pcb; 365 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 366 367 /* 368 * Allocate space for system data structures. These data structures 369 * are allocated here instead of cpu_startup() because physical 370 * memory is directly addressable. We don't have to map these into 371 * virtual address space. 372 */ 373 v = (caddr_t)uvm_pageboot_alloc(size); 374 if ((allocsys(v, NULL) - v) != size) 375 panic("mach_init: table size inconsistency"); 376 /* 377 * Set up interrupt handling and I/O addresses. 378 */ 379 380 pizazz_init(); 381 } 382 383 384 385 /* 386 * cpu_startup: allocate memory for variable-sized tables, 387 * initialize cpu, and do autoconfiguration. 388 */ 389 void 390 cpu_startup() 391 { 392 register unsigned i; 393 int base, residual; 394 vaddr_t minaddr, maxaddr; 395 vsize_t size; 396 char pbuf[9]; 397 #ifdef DEBUG 398 extern int pmapdebug; 399 int opmapdebug = pmapdebug; 400 401 pmapdebug = 0; 402 #endif 403 404 /* 405 * Good {morning,afternoon,evening,night}. 406 */ 407 printf(version); 408 printf("%s\n", cpu_model); 409 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 410 printf("total memory = %s\n", pbuf); 411 412 /* 413 * Allocate virtual address space for file I/O buffers. 414 * Note they are different than the array of headers, 'buf', 415 * and usually occupy more virtual memory than physical. 416 */ 417 size = MAXBSIZE * nbuf; 418 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size), 419 NULL, UVM_UNKNOWN_OFFSET, 0, 420 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 421 UVM_ADV_NORMAL, 0)) != 0) 422 panic("startup: cannot allocate VM for buffers"); 423 minaddr = (vaddr_t)buffers; 424 base = bufpages / nbuf; 425 residual = bufpages % nbuf; 426 for (i = 0; i < nbuf; i++) { 427 vsize_t curbufsize; 428 vaddr_t curbuf; 429 struct vm_page *pg; 430 431 /* 432 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 433 * that MAXBSIZE space, we allocate and map (base+1) pages 434 * for the first "residual" buffers, and then we allocate 435 * "base" pages for the rest. 436 */ 437 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 438 curbufsize = NBPG * ((i < residual) ? (base+1) : base); 439 440 while (curbufsize) { 441 pg = uvm_pagealloc(NULL, 0, NULL, 0); 442 if (pg == NULL) 443 panic("cpu_startup: not enough memory for " 444 "buffer cache"); 445 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 446 VM_PROT_READ|VM_PROT_WRITE); 447 curbuf += PAGE_SIZE; 448 curbufsize -= PAGE_SIZE; 449 } 450 } 451 pmap_update(pmap_kernel()); 452 453 /* 454 * Allocate a submap for exec arguments. This map effectively 455 * limits the number of processes exec'ing at any time. 456 */ 457 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 458 16 * NCARGS, TRUE, FALSE, NULL); 459 /* 460 * Allocate a submap for physio 461 */ 462 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 463 VM_PHYS_SIZE, TRUE, FALSE, NULL); 464 465 /* 466 * No need to allocate an mbuf cluster submap. Mbuf clusters 467 * are allocated via the pool allocator, and we use KSEG to 468 * map those pages. 469 */ 470 471 #ifdef DEBUG 472 pmapdebug = opmapdebug; 473 #endif 474 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 475 printf("avail memory = %s\n", pbuf); 476 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 477 printf("using %d buffers containing %s of memory\n", nbuf, pbuf); 478 479 /* 480 * Set up buffers, so they can be used to read disk labels. 481 */ 482 bufinit(); 483 } 484 485 /* 486 * machine dependent system variables. 487 */ 488 int 489 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 490 int *name; 491 u_int namelen; 492 void *oldp; 493 size_t *oldlenp; 494 void *newp; 495 size_t newlen; 496 struct proc *p; 497 { 498 /* all sysctl names at this level are terminal */ 499 if (namelen != 1) 500 return (ENOTDIR); /* overloaded */ 501 502 switch (name[0]) { 503 default: 504 return (EOPNOTSUPP); 505 } 506 /* NOTREACHED */ 507 } 508 509 /* 510 * Look up information in bootinfo of boot loader. 511 */ 512 void * 513 lookup_bootinfo(type) 514 int type; 515 { 516 struct btinfo_common *bt; 517 char *help = bootinfo; 518 519 /* Check for a bootinfo record first. */ 520 if (help == NULL) 521 return (NULL); 522 523 do { 524 bt = (struct btinfo_common *)help; 525 if (bt->type == type) 526 return ((void *)help); 527 help += bt->next; 528 } while (bt->next != 0 && 529 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 530 531 return (NULL); 532 } 533 534 int waittime = -1; 535 536 /* 537 * call PROM to halt or reboot. 538 */ 539 void 540 prom_halt(howto) 541 int howto; 542 { 543 if (howto & RB_HALT) 544 MIPS_PROM(reinit)(); 545 MIPS_PROM(reboot)(); 546 /* NOTREACHED */ 547 } 548 549 void 550 cpu_reboot(howto, bootstr) 551 volatile int howto; 552 char *bootstr; 553 { 554 /* take a snap shot before clobbering any registers */ 555 if (curproc) 556 savectx((struct user *)curpcb); 557 558 #ifdef DEBUG 559 if (panicstr) 560 stacktrace(); 561 #endif 562 563 /* If system is cold, just halt. */ 564 if (cold) { 565 howto |= RB_HALT; 566 goto haltsys; 567 } 568 569 /* If "always halt" was specified as a boot flag, obey. */ 570 if ((boothowto & RB_HALT) != 0) 571 howto |= RB_HALT; 572 573 boothowto = howto; 574 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 575 /* 576 * Synchronize the disks.... 577 */ 578 waittime = 0; 579 vfs_shutdown(); 580 581 /* 582 * If we've been adjusting the clock, the todr 583 * will be out of synch; adjust it now. 584 */ 585 resettodr(); 586 } 587 588 /* Disable interrupts. */ 589 splhigh(); 590 591 /* If rebooting and a dump is requested do it. */ 592 #if 0 593 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 594 #else 595 if (howto & RB_DUMP) 596 #endif 597 dumpsys(); 598 599 haltsys: 600 601 /* run any shutdown hooks */ 602 doshutdownhooks(); 603 604 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 605 prom_halt(0x80); /* rom monitor RB_PWOFF */ 606 607 /* Finally, halt/reboot the system. */ 608 printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 609 prom_halt(howto & RB_HALT); 610 /*NOTREACHED*/ 611 } 612 613 /* 614 * Return the best possible estimate of the time in the timeval 615 * to which tvp points. Unfortunately, we can't read the hardware registers. 616 * We guarantee that the time will be greater than the value obtained by a 617 * previous call. 618 */ 619 void 620 microtime(tvp) 621 register struct timeval *tvp; 622 { 623 static struct timeval lasttime; 624 int s = splclock(); 625 626 *tvp = time; 627 628 tvp->tv_usec += (*platform.clkread)(); 629 630 while (tvp->tv_usec >= 1000000) { 631 tvp->tv_usec -= 1000000; 632 tvp->tv_sec++; 633 } 634 635 if (tvp->tv_sec == lasttime.tv_sec && 636 tvp->tv_usec <= lasttime.tv_usec && 637 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { 638 tvp->tv_sec++; 639 tvp->tv_usec -= 1000000; 640 } 641 lasttime = *tvp; 642 splx(s); 643 } 644 645 int 646 initcpu() 647 { 648 spl0(); /* safe to turn interrupts on now */ 649 return 0; 650 } 651 652 static void 653 unimpl_cons_init() 654 { 655 656 panic("sysconf.init didn't set cons_init"); 657 } 658 659 static void 660 unimpl_iointr(mask, pc, statusreg, causereg) 661 u_int mask; 662 u_int pc; 663 u_int statusreg; 664 u_int causereg; 665 { 666 667 panic("sysconf.init didn't set intr"); 668 } 669 670 static int 671 unimpl_memsize(first) 672 caddr_t first; 673 { 674 675 panic("sysconf.init didn't set memsize"); 676 } 677 678 static unsigned 679 unimpl_clkread() 680 { 681 return 0; /* No microtime available */ 682 } 683 684 static void 685 unimpl_todr(dt) 686 struct clock_ymdhms *dt; 687 { 688 panic("sysconf.init didn't init TOD"); 689 } 690 691 void 692 unimpl_intr_establish(level, func, arg) 693 int level; 694 int (*func) __P((void *)); 695 void *arg; 696 { 697 panic("sysconf.init didn't init intr_establish\n"); 698 } 699 700 void 701 delay(n) 702 int n; 703 { 704 DELAY(n); 705 } 706 707 /* 708 * Find out how much memory is available by testing memory. 709 * Be careful to save and restore the original contents for msgbuf. 710 */ 711 int 712 memsize_scan(first) 713 caddr_t first; 714 { 715 volatile int *vp, *vp0; 716 int mem, tmp, tmp0; 717 718 #define PATTERN1 0xa5a5a5a5 719 #define PATTERN2 ~PATTERN1 720 721 /* 722 * Non destructive scan of memory to determine the size 723 * Use the first page to test for memory aliases. This 724 * also has the side effect of flushing the bus alignment 725 * buffer 726 */ 727 mem = btoc((paddr_t)first - MIPS_KSEG0_START); 728 vp = (int *)MIPS_PHYS_TO_KSEG1(mem << PGSHIFT); 729 vp0 = (int *)MIPS_PHYS_TO_KSEG1(0); /* Start of physical memory */ 730 tmp0 = *vp0; 731 while (vp < (int *)MIPS_MAX_MEM_ADDR) { 732 tmp = *vp; 733 *vp = PATTERN1; 734 *vp0 = PATTERN2; 735 wbflush(); 736 if (*vp != PATTERN1) 737 break; 738 *vp = PATTERN2; 739 *vp0 = PATTERN1; 740 wbflush(); 741 if (*vp != PATTERN2) 742 break; 743 *vp = tmp; 744 vp += NBPG/sizeof(int); 745 mem++; 746 } 747 *vp0 = tmp0; 748 return mem; 749 } 750 751 /* 752 * Console initialization: called early on from main, 753 * before vm init or startup. Do enough configuration 754 * to choose and initialize a console. 755 */ 756 757 static void 758 null_cnprobe(cn) 759 struct consdev *cn; 760 { 761 } 762 763 static void 764 prom_cninit(cn) 765 struct consdev *cn; 766 { 767 cn->cn_dev = makedev(0, 0); 768 cn->cn_pri = CN_REMOTE; 769 } 770 771 static int 772 prom_cngetc(dev) 773 dev_t dev; 774 { 775 return MIPS_PROM(getchar)(); 776 } 777 778 static void 779 prom_cnputc(dev, c) 780 dev_t dev; 781 int c; 782 { 783 MIPS_PROM(putchar)(c); 784 } 785 786 static void 787 null_cnpollc(dev, on) 788 dev_t dev; 789 int on; 790 { 791 } 792 793 void 794 consinit() 795 { 796 int zs_unit; 797 798 zs_unit = 0; 799 cn_tab = &consdev_zs; 800 801 (*cn_tab->cn_init)(cn_tab); 802 } 803