1 /* $NetBSD: machdep.c,v 1.201 2002/08/25 20:21:40 thorpej 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 * from: Utah Hdr: machdep.c 1.63 91/04/24 43 */ 44 45 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 46 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.201 2002/08/25 20:21:40 thorpej Exp $"); 47 48 #include "fs_mfs.h" 49 #include "opt_ddb.h" 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/kernel.h> 54 #include <sys/buf.h> 55 #include <sys/reboot.h> 56 #include <sys/user.h> 57 #include <sys/mount.h> 58 #include <sys/kcore.h> 59 #include <sys/boot_flag.h> 60 61 #include <uvm/uvm_extern.h> 62 63 #include <dev/cons.h> 64 65 #include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 66 67 #include <mips/cache.h> 68 #include <machine/psl.h> 69 #include <machine/autoconf.h> 70 #include <machine/dec_prom.h> 71 #include <machine/sysconf.h> 72 #include <machine/bootinfo.h> 73 #include <machine/locore.h> 74 #include <pmax/pmax/machdep.h> 75 76 #define _PMAX_BUS_DMA_PRIVATE 77 #include <machine/bus.h> 78 79 #ifdef DDB 80 #include <sys/exec_aout.h> /* XXX backwards compatilbity for DDB */ 81 #include <machine/db_machdep.h> 82 #include <ddb/db_extern.h> 83 #endif 84 85 #include "opt_dec_3min.h" 86 #include "opt_dec_maxine.h" 87 #include "opt_dec_3maxplus.h" 88 89 /* the following is used externally (sysctl_hw) */ 90 extern char cpu_model[]; 91 92 unsigned ssir; /* simulated interrupt register */ 93 94 /* Our exported CPU info; we can have only one. */ 95 struct cpu_info cpu_info_store; 96 97 /* maps for VM objects */ 98 struct vm_map *exec_map = NULL; 99 struct vm_map *mb_map = NULL; 100 struct vm_map *phys_map = NULL; 101 102 int systype; /* mother board type */ 103 char *bootinfo = NULL; /* pointer to bootinfo structure */ 104 int cpuspeed = 30; /* approx # instr per usec. */ 105 int physmem; /* max supported memory, changes to actual */ 106 int physmem_boardmax; /* {model,SIMM}-specific bound on physmem */ 107 int mem_cluster_cnt; 108 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 109 110 /* 111 * During autoconfiguration or after a panic, a sleep will simply 112 * lower the priority briefly to allow interrupts, then return. 113 * The priority to be used (safepri) is machine-dependent, thus this 114 * value is initialized and maintained in the machine-dependent layers. 115 * This priority will typically be 0, or the lowest priority 116 * that is safe for use on the interrupt stack; it can be made 117 * higher to block network software interrupts after panics. 118 */ 119 /* 120 * safepri is a safe priority for sleep to set for a spin-wait 121 * during autoconfiguration or after a panic. 122 * Used as an argument to splx(). 123 * XXX disables interrupt 5 to disable mips3 on-chip clock, which also 124 * disables mips1 FPU interrupts. 125 */ 126 int safepri = MIPS3_PSL_LOWIPL; /* XXX */ 127 128 struct splvec splvec; /* XXX will go XXX */ 129 130 void mach_init __P((int, char *[], int, int, u_int, char *)); /* XXX */ 131 132 /* Motherboard or system-specific initialization vector */ 133 static void unimpl_bus_reset __P((void)); 134 static void unimpl_cons_init __P((void)); 135 static void unimpl_iointr __P((unsigned, unsigned, unsigned, unsigned)); 136 static void unimpl_intr_establish __P((struct device *, void *, int, 137 int (*)(void *), void *)); 138 static int unimpl_memsize __P((caddr_t)); 139 static unsigned nullwork __P((void)); 140 141 struct platform platform = { 142 "iobus not set", 143 unimpl_bus_reset, 144 unimpl_cons_init, 145 unimpl_iointr, 146 unimpl_intr_establish, 147 unimpl_memsize, 148 (void *)nullwork, 149 }; 150 151 extern caddr_t esym; /* XXX */ 152 extern struct user *proc0paddr; /* XXX */ 153 extern struct consdev promcd; /* XXX */ 154 155 /* 156 * Do all the stuff that locore normally does before calling main(). 157 * The first 4 argments are passed by PROM monitor, and remaining two 158 * are built on temporary stack by our boot loader. 159 */ 160 void 161 mach_init(argc, argv, code, cv, bim, bip) 162 int argc; 163 char *argv[]; 164 int code, cv; 165 u_int bim; 166 char *bip; 167 { 168 char *cp, *bootinfo_msg; 169 u_long first, last; 170 int i; 171 caddr_t kernend, v; 172 unsigned size; 173 #ifdef DDB 174 int nsym = 0; 175 caddr_t ssym = 0; 176 struct btinfo_symtab *bi_syms; 177 struct exec *aout; /* XXX backwards compatilbity for DDB */ 178 #endif 179 extern char edata[], end[]; /* XXX */ 180 181 /* Set up bootinfo structure looking at stack. */ 182 if (bim == BOOTINFO_MAGIC) { 183 struct btinfo_magic *bi_magic; 184 185 bootinfo = bip; 186 bi_magic = lookup_bootinfo(BTINFO_MAGIC); 187 if (bi_magic == NULL || bi_magic->magic != BOOTINFO_MAGIC) 188 bootinfo_msg = 189 "invalid magic number in bootinfo structure.\n"; 190 else 191 bootinfo_msg = NULL; 192 } 193 else 194 bootinfo_msg = "invalid bootinfo pointer (old bootblocks?)\n"; 195 196 /* clear the BSS segment */ 197 #ifdef DDB 198 bi_syms = lookup_bootinfo(BTINFO_SYMTAB); 199 aout = (struct exec *)edata; 200 201 /* Was it a valid bootinfo symtab info? */ 202 if (bi_syms != NULL) { 203 nsym = bi_syms->nsym; 204 ssym = (caddr_t)bi_syms->ssym; 205 esym = (caddr_t)bi_syms->esym; 206 kernend = (caddr_t)mips_round_page(esym); 207 memset(edata, 0, end - edata); 208 } 209 /* XXX: Backwards compatibility with old bootblocks - this should 210 * go soon... 211 */ 212 /* Exec header and symbols? */ 213 else if (aout->a_midmag == 0x07018b00 && (i = aout->a_syms) != 0) { 214 nsym = *(long *)end = i; 215 ssym = end; 216 i += (*(long *)(end + i + 4) + 3) & ~3; /* strings */ 217 esym = end + i + 4; 218 kernend = (caddr_t)mips_round_page(esym); 219 memset(edata, 0, end - edata); 220 } else 221 #endif 222 { 223 kernend = (caddr_t)mips_round_page(end); 224 memset(edata, 0, kernend - edata); 225 } 226 227 /* Initialize callv so we can do PROM output... */ 228 callv = (code == DEC_PROM_MAGIC) ? (void *)cv : &callvec; 229 230 /* Use PROM console output until we initialize a console driver. */ 231 cn_tab = &promcd; 232 233 #if 0 234 if (bootinfo_msg != NULL) 235 printf(bootinfo_msg); 236 #endif 237 /* 238 * Set the VM page size. 239 */ 240 uvm_setpagesize(); 241 242 /* 243 * Copy exception-dispatch code down to exception vector. 244 * Initialize locore-function vector. 245 * Clear out the I and D caches. 246 */ 247 mips_vector_init(); 248 249 /* 250 * We know the CPU type now. Initialize our DMA tags (might 251 * need this early, for certain types of console devices!!). 252 */ 253 pmax_bus_dma_init(); 254 255 /* Check for direct boot from DS5000 REX monitor */ 256 if (argc > 0 && strcmp(argv[0], "boot") == 0) { 257 argc--; 258 argv++; 259 } 260 261 /* Look at argv[0] and compute bootdev */ 262 makebootdev(argv[0]); 263 264 /* 265 * Look at arguments passed to us and compute boothowto. 266 */ 267 boothowto = RB_SINGLE; 268 #ifdef KADB 269 boothowto |= RB_KDB; 270 #endif 271 for (i = 1; i < argc; i++) { 272 for (cp = argv[i]; *cp; cp++) { 273 switch (*cp) { 274 case 'a': /* autoboot */ 275 boothowto &= ~RB_SINGLE; 276 break; 277 278 case 'n': /* ask for names */ 279 boothowto |= RB_ASKNAME; 280 break; 281 282 case 'N': /* don't ask for names */ 283 boothowto &= ~RB_ASKNAME; 284 break; 285 286 default: 287 BOOT_FLAG(*cp, boothowto); 288 break; 289 } 290 } 291 } 292 293 #ifdef MFS 294 /* 295 * Check to see if a mini-root was loaded into memory. It resides 296 * at the start of the next page just after the end of BSS. 297 */ 298 if (boothowto & RB_MINIROOT) 299 kernend += round_page(mfs_initminiroot(kernend)); 300 #endif 301 302 #ifdef DDB 303 /* init symbols if present */ 304 if (esym) 305 ddb_init(esym - ssym, ssym, esym); 306 if (boothowto & RB_KDB) 307 Debugger(); 308 #endif 309 310 /* 311 * Alloc u pages for proc0 stealing KSEG0 memory. 312 */ 313 proc0.p_addr = proc0paddr = (struct user *)kernend; 314 proc0.p_md.md_regs = (struct frame *)(kernend + USPACE) - 1; 315 memset(proc0.p_addr, 0, USPACE); 316 curpcb = &proc0.p_addr->u_pcb; 317 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 318 319 kernend += USPACE; 320 321 /* 322 * Initialize physmem_boardmax; assume no SIMM-bank limits. 323 * Adjust later in model-specific code if necessary. 324 */ 325 physmem_boardmax = MIPS_MAX_MEM_ADDR; 326 327 /* 328 * Determine what model of computer we are running on. 329 */ 330 systype = ((prom_systype() >> 16) & 0xff); 331 if (systype >= nsysinit) { 332 platform_not_supported(); 333 /* NOTREACHED */ 334 } 335 336 /* Machine specific initialization. */ 337 (*sysinit[systype].init)(); 338 339 /* Find out how much memory is available. */ 340 physmem = (*platform.memsize)(kernend); 341 342 /* 343 * Load the rest of the available pages into the VM system. 344 * Put the first 8M of RAM onto a lower-priority free list, since 345 * some TC boards (e.g. PixelStamp boards) are only able to DMA 346 * into this region, and we want them to have a fighting chance of 347 * allocating their DMA memory during autoconfiguration. 348 */ 349 for (i = 0, physmem = 0; i < mem_cluster_cnt; ++i) { 350 first = mem_clusters[i].start; 351 if (first == 0) 352 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 353 last = mem_clusters[i].start + mem_clusters[i].size; 354 physmem += atop(mem_clusters[i].size); 355 if (i != 0 || last <= (8 * 1024 * 1024)) { 356 uvm_page_physload(atop(first), atop(last), atop(first), 357 atop(last), VM_FREELIST_DEFAULT); 358 } else { 359 uvm_page_physload(atop(first), atop(8 * 1024 * 1024), 360 atop(first), atop(8 * 1024 * 1024), VM_FREELIST_FIRST8); 361 uvm_page_physload(atop(8 * 1024 * 1024), atop(last), 362 atop(8 * 1024 * 1024), atop(last), VM_FREELIST_DEFAULT); 363 } 364 } 365 366 /* 367 * Initialize error message buffer (at end of core). 368 */ 369 mips_init_msgbuf(); 370 371 /* 372 * Compute the size of system data structures. pmap_bootstrap() 373 * needs some of this information. 374 */ 375 size = (unsigned)allocsys(NULL, NULL); 376 377 /* 378 * Initialize the virtual memory system. 379 */ 380 pmap_bootstrap(); 381 382 /* 383 * Allocate space for system data structures. These data structures 384 * are allocated here instead of cpu_startup() because physical memory 385 * is directly addressable. We don't have to map these into virtual 386 * address space. 387 */ 388 v = (caddr_t)uvm_pageboot_alloc(size); 389 if ((allocsys(v, NULL) - v) != size) 390 panic("mach_init: table size inconsistency"); 391 } 392 393 void 394 mips_machdep_cache_config(void) 395 { 396 /* All r4k pmaxen have a 1MB L2 cache. */ 397 if (CPUISMIPS3) 398 mips_sdcache_size = 1024 * 1024; 399 } 400 401 void 402 consinit() 403 { 404 405 (*platform.cons_init)(); 406 } 407 408 /* 409 * Machine-dependent startup code: allocate memory for variable-sized 410 * tables. 411 */ 412 void 413 cpu_startup() 414 { 415 u_int i, base, residual; 416 vaddr_t minaddr, maxaddr; 417 vsize_t size; 418 char pbuf[9]; 419 #ifdef DEBUG 420 extern int pmapdebug; /* XXX */ 421 int opmapdebug = pmapdebug; 422 423 pmapdebug = 0; 424 #endif 425 426 /* 427 * Good {morning,afternoon,evening,night}. 428 */ 429 printf(version); 430 printf("%s\n", cpu_model); 431 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 432 printf("total memory = %s\n", pbuf); 433 434 /* 435 * Allocate virtual address space for file I/O buffers. 436 * Note they are different than the array of headers, 'buf', 437 * and usually occupy more virtual memory than physical. 438 */ 439 size = MAXBSIZE * nbuf; 440 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size), 441 NULL, UVM_UNKNOWN_OFFSET, 0, 442 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 443 UVM_ADV_NORMAL, 0)) != 0) 444 panic("cpu_startup: cannot allocate VM for buffers"); 445 446 minaddr = (vaddr_t)buffers; 447 if ((bufpages / nbuf) >= btoc(MAXBSIZE)) { 448 bufpages = btoc(MAXBSIZE) * nbuf; /* do not overallocate RAM */ 449 } 450 base = bufpages / nbuf; 451 residual = bufpages % nbuf; 452 453 /* now allocate RAM for buffers */ 454 for (i = 0; i < nbuf; i++) { 455 vsize_t curbufsize; 456 vaddr_t curbuf; 457 struct vm_page *pg; 458 459 /* 460 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 461 * that MAXBSIZE space, we allocate and map (base+1) pages 462 * for the first "residual" buffers, and then we allocate 463 * "base" pages for the rest. 464 */ 465 curbuf = (vaddr_t)buffers + (i * MAXBSIZE); 466 curbufsize = NBPG * ((i < residual) ? (base+1) : base); 467 468 while (curbufsize) { 469 pg = uvm_pagealloc(NULL, 0, NULL, 0); 470 if (pg == NULL) 471 panic("cpu_startup: not enough memory for " 472 "buffer cache"); 473 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 474 VM_PROT_READ|VM_PROT_WRITE); 475 curbuf += PAGE_SIZE; 476 curbufsize -= PAGE_SIZE; 477 } 478 } 479 pmap_update(pmap_kernel()); 480 481 /* 482 * Allocate a submap for exec arguments. This map effectively 483 * limits the number of processes exec'ing at any time. 484 */ 485 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 486 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 487 488 /* 489 * Allocate a submap for physio 490 */ 491 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 492 VM_PHYS_SIZE, 0, FALSE, NULL); 493 494 /* 495 * No need to allocate an mbuf cluster submap. Mbuf clusters 496 * are allocated via the pool allocator, and we use KSEG to 497 * map those pages. 498 */ 499 500 #ifdef DEBUG 501 pmapdebug = opmapdebug; 502 #endif 503 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 504 printf("avail memory = %s\n", pbuf); 505 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 506 printf("using %u buffers containing %s of memory\n", nbuf, pbuf); 507 508 /* 509 * Set up buffers, so they can be used to read disk labels. 510 */ 511 bufinit(); 512 } 513 514 /* 515 * Look up information in bootinfo of boot loader. 516 */ 517 void * 518 lookup_bootinfo(type) 519 int type; 520 { 521 struct btinfo_common *bt; 522 char *help = bootinfo; 523 524 /* Check for a bootinfo record first. */ 525 if (help == NULL) 526 return (NULL); 527 528 do { 529 bt = (struct btinfo_common *)help; 530 if (bt->type == type) 531 return ((void *)help); 532 help += bt->next; 533 } while (bt->next != 0 && 534 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 535 536 return (NULL); 537 } 538 539 void 540 cpu_reboot(howto, bootstr) 541 volatile int howto; /* XXX volatile to keep gcc happy */ 542 char *bootstr; 543 { 544 545 /* take a snap shot before clobbering any registers */ 546 if (curproc) 547 savectx((struct user *)curpcb); 548 549 #ifdef DEBUG 550 if (panicstr) 551 stacktrace(); 552 #endif 553 554 /* If system is cold, just halt. */ 555 if (cold) { 556 howto |= RB_HALT; 557 goto haltsys; 558 } 559 560 /* If "always halt" was specified as a boot flag, obey. */ 561 if ((boothowto & RB_HALT) != 0) 562 howto |= RB_HALT; 563 564 boothowto = howto; 565 if ((howto & RB_NOSYNC) == 0) { 566 /* 567 * Synchronize the disks.... 568 */ 569 vfs_shutdown(); 570 571 /* 572 * If we've been adjusting the clock, the todr 573 * will be out of synch; adjust it now. 574 */ 575 resettodr(); 576 } 577 578 /* Disable interrupts. */ 579 splhigh(); 580 581 /* If rebooting and a dump is requested do it. */ 582 #if 0 583 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 584 #else 585 if ((howto & RB_DUMP) != 0) 586 #endif 587 dumpsys(); 588 589 haltsys: 590 591 /* run any shutdown hooks */ 592 doshutdownhooks(); 593 594 /* Finally, halt/reboot the system. */ 595 printf("%s\n\n", ((howto & RB_HALT) != 0) ? "halted." : "rebooting..."); 596 prom_halt(howto & RB_HALT, bootstr); 597 /*NOTREACHED*/ 598 } 599 600 /* 601 * Find out how much memory is available by testing memory. 602 * Be careful to save and restore the original contents for msgbuf. 603 */ 604 int 605 memsize_scan(first) 606 caddr_t first; 607 { 608 int i, mem; 609 char *cp; 610 611 mem = btoc((paddr_t)first - MIPS_KSEG0_START); 612 cp = (char *)MIPS_PHYS_TO_KSEG1(mem << PGSHIFT); 613 while (cp < (char *)physmem_boardmax) { 614 int j; 615 if (badaddr(cp, 4)) 616 break; 617 i = *(int *)cp; 618 j = ((int *)cp)[4]; 619 *(int *)cp = 0xa5a5a5a5; 620 /* 621 * Data will persist on the bus if we read it right away. 622 * Have to be tricky here. 623 */ 624 ((int *)cp)[4] = 0x5a5a5a5a; 625 wbflush(); 626 if (*(int *)cp != 0xa5a5a5a5) 627 break; 628 *(int *)cp = i; 629 ((int *)cp)[4] = j; 630 cp += NBPG; 631 mem++; 632 } 633 634 /* 635 * Now that we know how much memory we have, initialize the 636 * mem cluster array. 637 */ 638 mem_clusters[0].start = 0; /* XXX is this correct? */ 639 mem_clusters[0].size = ctob(mem); 640 mem_cluster_cnt = 1; 641 642 /* clear any memory error conditions possibly caused by probe */ 643 (*platform.bus_reset)(); 644 return (mem); 645 } 646 647 /* 648 * Find out how much memory is available by using the PROM bitmap. 649 */ 650 int 651 memsize_bitmap(first) 652 caddr_t first; 653 { 654 memmap *prom_memmap = (memmap *)first; 655 int i, mapbytes; 656 int segstart, curaddr, xsize, segnum; 657 658 mapbytes = prom_getbitmap(prom_memmap); 659 if (mapbytes == 0) 660 return (memsize_scan(first)); 661 662 segstart = curaddr = i = segnum = 0; 663 xsize = prom_memmap->pagesize * 8; 664 while (i < mapbytes) { 665 while (prom_memmap->bitmap[i] == 0xff && i < mapbytes) { 666 ++i; 667 curaddr += xsize; 668 } 669 if (curaddr > segstart) { 670 mem_clusters[segnum].start = segstart; 671 mem_clusters[segnum].size = curaddr - segstart; 672 ++segnum; 673 } 674 while (i < mapbytes && prom_memmap->bitmap[i] != 0xff) { 675 ++i; 676 curaddr += xsize; 677 } 678 segstart = curaddr; 679 } 680 mem_cluster_cnt = segnum; 681 for (i = 0; i < segnum; ++i) { 682 printf("segment %2d start %08lx size %08lx\n", i, 683 (long)mem_clusters[i].start, (long)mem_clusters[i].size); 684 } 685 return (mapbytes * 8); 686 } 687 688 /* 689 * Ensure all platform vectors are always initialized. 690 */ 691 static void 692 unimpl_bus_reset() 693 { 694 695 panic("sysconf.init didn't set bus_reset"); 696 } 697 698 static void 699 unimpl_cons_init() 700 { 701 702 panic("sysconf.init didn't set cons_init"); 703 } 704 705 static void 706 unimpl_iointr(mask, pc, statusreg, causereg) 707 u_int mask; 708 u_int pc; 709 u_int statusreg; 710 u_int causereg; 711 { 712 713 panic("sysconf.init didn't set intr"); 714 } 715 716 static void 717 unimpl_intr_establish(dev, cookie, level, handler, arg) 718 struct device *dev; 719 void *cookie; 720 int level; 721 int (*handler) __P((void *)); 722 void *arg; 723 { 724 panic("sysconf.init didn't set intr_establish"); 725 } 726 727 static int 728 unimpl_memsize(first) 729 caddr_t first; 730 { 731 732 panic("sysconf.init didn't set memsize"); 733 } 734 735 static unsigned 736 nullwork() 737 { 738 739 return (0); 740 } 741 742 /* 743 * Return the best possible estimate of the time in the timeval to 744 * which tvp points. We guarantee that the time will be greater than 745 * the value obtained by a previous call. Some models of DECstations 746 * provide a high resolution timer circuit. 747 */ 748 void 749 microtime(tvp) 750 struct timeval *tvp; 751 { 752 int s = splclock(); 753 static struct timeval lasttime; 754 755 *tvp = time; 756 #if defined(DEC_3MIN) || defined(DEC_MAXINE) || defined(DEC_3MAXPLUS) 757 tvp->tv_usec += (*platform.clkread)(); 758 #endif 759 if (tvp->tv_usec >= 1000000) { 760 tvp->tv_usec -= 1000000; 761 tvp->tv_sec++; 762 } 763 764 if (tvp->tv_sec == lasttime.tv_sec && 765 tvp->tv_usec <= lasttime.tv_usec && 766 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 767 tvp->tv_sec++; 768 tvp->tv_usec -= 1000000; 769 } 770 lasttime = *tvp; 771 splx(s); 772 } 773 774 /* 775 * Wait "n" microseconds. (scsi code needs this). 776 */ 777 void 778 delay(n) 779 int n; 780 { 781 782 DELAY(n); 783 } 784