1 /* $NetBSD: machdep.c,v 1.21 2025/11/30 01:46:00 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. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 38 * from: Utah Hdr: machdep.c 1.63 91/04/24 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.21 2025/11/30 01:46:00 thorpej Exp $"); 43 44 #include "opt_ddb.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/buf.h> 50 #include <sys/mbuf.h> 51 #include <sys/reboot.h> 52 #include <sys/mount.h> 53 #include <sys/kcore.h> 54 #include <sys/boot_flag.h> 55 #include <sys/ksyms.h> 56 #include <sys/proc.h> 57 #include <sys/device.h> 58 #include <sys/cpu.h> 59 #include <sys/vmem.h> 60 #include <sys/vmem_impl.h> 61 62 #include <uvm/uvm_extern.h> 63 64 #include <dev/cons.h> 65 66 #include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 67 68 #include <mips/cache.h> 69 #include <machine/psl.h> 70 #include <machine/autoconf.h> 71 #include <emips/stand/common/prom_iface.h> 72 #include <machine/sysconf.h> 73 #include <machine/bootinfo.h> 74 #include <machine/locore.h> 75 #include <emips/emips/machdep.h> 76 #include <machine/emipsreg.h> 77 78 #define _EMIPS_BUS_DMA_PRIVATE 79 #include <machine/bus.h> 80 81 #if NKSYMS || defined(DDB) || defined(MODULAR) 82 #include <machine/db_machdep.h> 83 #include <ddb/db_extern.h> 84 #endif 85 86 vaddr_t iospace; 87 vsize_t iospace_size = 64 * 1024; /* BUGBUG make it an option? */ 88 89 #include "ksyms.h" 90 91 /* 92 * Vmem arena to manage I/O register space. We allocate storage for 93 * 32 regions in the map. 94 */ 95 #define IOMAP_BTAG_COUNT VMEM_EST_BTCOUNT(1, 32) 96 static struct vmem iomap_arena_store; 97 static struct vmem_btag iomap_btag_store[IOMAP_BTAG_COUNT]; 98 static vmem_t *iomap_arena; 99 100 /* maps for VM objects */ 101 struct vm_map *phys_map = NULL; 102 103 int systype; /* mother board type */ 104 char *bootinfo = NULL; /* pointer to bootinfo structure */ 105 int cpuspeed = 30; /* approx # instr per usec. */ 106 intptr_t 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 void mach_init (int, char *[], int, intptr_t, u_int, char *); /* XXX */ 111 112 /* Motherboard or system-specific initialization vector */ 113 static void unimpl_bus_reset(void); 114 static void unimpl_cons_init(void); 115 static void unimpl_iointr(uint32_t, vaddr_t, uint32_t); 116 static void unimpl_intr_establish(device_t, void *, int, 117 int (*)(void *, void *), void *); 118 static int unimpl_memsize(void *); 119 120 struct platform platform = { 121 "iobus not set", 122 unimpl_bus_reset, 123 unimpl_cons_init, 124 unimpl_iointr, 125 unimpl_intr_establish, 126 unimpl_memsize 127 }; 128 129 extern char *esym; /* XXX */ 130 extern struct consdev promcd; /* XXX */ 131 extern const struct callback *callv; 132 extern const struct callback callvec; 133 134 /* 135 * Do all the stuff that locore normally does before calling main(). 136 * The first 4 arguments are passed by PROM monitor, and remaining two 137 * are built on temporary stack by our boot loader. 138 */ 139 void 140 mach_init(int argc, char *argv[], int code, intptr_t cv, u_int bim, char *bip) 141 { 142 char *cp; 143 const char *bootinfo_msg; 144 u_long first, last; 145 int i, howtoboot; 146 #if NKSYMS || defined(DDB) || defined(MODULAR) 147 void *ssym = 0; 148 struct btinfo_symtab *bi_syms; 149 #endif 150 void *kernend; 151 extern char edata[], end[]; /* XXX */ 152 153 /* Set up bootinfo structure looking at stack. */ 154 if (bim == BOOTINFO_MAGIC) { 155 struct btinfo_magic *bi_magic; 156 157 bootinfo = bip; 158 bi_magic = lookup_bootinfo(BTINFO_MAGIC); 159 if (bi_magic == NULL || bi_magic->magic != BOOTINFO_MAGIC) 160 bootinfo_msg = 161 "invalid magic number in bootinfo structure.\n"; 162 else 163 bootinfo_msg = NULL; 164 } else 165 bootinfo_msg = "invalid bootinfo pointer (old bootblocks?)\n"; 166 167 /* 168 * Look at arguments passed to us and compute boothowto. 169 * Do it before we decide to keep symbols. 170 * NB: "boothowto" is in the BSS. 171 */ 172 howtoboot = 0; 173 #ifdef KADB 174 howtoboot |= RB_KDB; 175 #endif 176 for (i = 1; i < argc; i++) { 177 for (cp = argv[i]; *cp; cp++) { 178 switch (*cp) { 179 180 #define RB_NOSYMBOLS 0x10000000 181 case 'e': /* empty the symtable */ 182 howtoboot |= RB_NOSYMBOLS; 183 break; 184 185 case 'n': /* ask for names */ 186 howtoboot |= RB_ASKNAME; 187 break; 188 189 case 'N': /* don't ask for names */ 190 howtoboot &= ~RB_ASKNAME; 191 break; 192 193 default: 194 BOOT_FLAG(*cp, howtoboot); /* see sys/boot_flag.h */ 195 break; 196 } 197 } 198 } 199 200 /* clear the BSS segment */ 201 #if NKSYMS || defined(DDB) || defined(MODULAR) 202 bi_syms = lookup_bootinfo(BTINFO_SYMTAB); 203 204 /* Was it a valid bootinfo symtab info? */ 205 if ((bi_syms != NULL) && (!(howtoboot & RB_NOSYMBOLS))) { 206 ssym = (void *)(intptr_t)bi_syms->ssym; 207 esym = (void *)(intptr_t)bi_syms->esym; 208 kernend = (void *)mips_round_page(esym); 209 memset(edata, 0, end - edata); 210 } else 211 #endif 212 { 213 kernend = (char *)mips_round_page(end); 214 /* should be done by bootloader? */ 215 memset(edata, 0, (char *)kernend - (char *)edata); 216 } 217 218 /* Initialize callv so we can do PROM output... */ 219 callv = (code == PROM_MAGIC) ? (void *)cv : &callvec; 220 221 /* Use PROM console output until we initialize a console driver. */ 222 cn_tab = &promcd; 223 224 #if 1 225 if (bootinfo_msg != NULL) 226 printf(bootinfo_msg); 227 #endif 228 uvm_md_init(); 229 230 /* 231 * Copy exception-dispatch code down to exception vector. 232 * Initialize locore-function vector. 233 * Clear out the I and D caches. 234 */ 235 mips_vector_init(NULL, false); 236 237 /* 238 * We know the CPU type now. Initialize our DMA tags (might 239 * need this early, for certain types of console devices!!). 240 */ 241 emips_bus_dma_init(); 242 243 /* Look at argv[0] and compute bootdev */ 244 makebootdev(argv[0]); 245 246 boothowto = howtoboot & ~RB_NOSYMBOLS; 247 248 /* 249 * Check to see if a mini-root was loaded into memory. It resides 250 * at the start of the next page just after the end of BSS. 251 */ 252 if (boothowto & RB_MINIROOT) 253 kernend = (char *)kernend 254 + round_page(mfs_initminiroot(kernend)); 255 256 #if NKSYMS || defined(DDB) || defined(MODULAR) 257 /* init symbols if present */ 258 if (esym) { 259 ksyms_addsyms_elf((char *)esym - (char *)ssym, ssym, esym); 260 } 261 #endif 262 #ifdef DDB 263 if (boothowto & RB_KDB) 264 Debugger(); 265 #endif 266 267 /* 268 * Initialize physmem_boardmax; assume no SIMM-bank limits. 269 * Adjust later in model-specific code if necessary. 270 */ 271 physmem_boardmax = MIPS_MAX_MEM_ADDR; 272 273 /* 274 * Determine what model of computer we are running on. 275 */ 276 systype = ((prom_systype() >> 16) & 0xff); 277 if (systype >= nsysinit) { 278 platform_not_supported(); 279 /* NOTREACHED */ 280 } 281 282 /* Machine specific initialization. */ 283 (*sysinit[systype].init)(); 284 285 /* Find out how much memory is available. */ 286 physmem = (*platform.memsize)(kernend); 287 288 /* 289 * Load the rest of the available pages into the VM system. 290 * NB: The kernel can span multiple segments. 291 */ 292 for (i = 0, physmem = 0; i < mem_cluster_cnt; ++i) { 293 first = mem_clusters[i].start; 294 if (first < round_page(MIPS_KSEG0_TO_PHYS(kernend))) 295 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 296 last = mem_clusters[i].start + mem_clusters[i].size; 297 physmem += atop(mem_clusters[i].size); 298 299 /* if the kernel spans multiple segments (does on ML40x) */ 300 if (last <= first) 301 continue; 302 303 uvm_page_physload(atop(first), atop(last), atop(first), 304 atop(last), VM_FREELIST_DEFAULT); 305 } 306 307 /* 308 * Initialize error message buffer (at end of core). 309 */ 310 mips_init_msgbuf(); 311 312 /* 313 * Initialize the virtual memory system. 314 */ 315 iospace = pmap_limits.virtual_start; 316 pmap_limits.virtual_start += iospace_size; 317 pmap_bootstrap(); 318 319 mips_init_lwp0_uarea(); 320 } 321 322 void 323 mips_machdep_cache_config(void) 324 { 325 } 326 327 void 328 consinit(void) 329 { 330 /* 331 * Init I/O memory vmem arena. Must be done before cninit() 332 * is called; we may want to use iospace in the console routines. 333 */ 334 KASSERT(iospace != 0); 335 iomap_arena = vmem_init(&iomap_arena_store, 336 "iomap", /* name */ 337 0, /* addr */ 338 0, /* size */ 339 PAGE_SIZE, /* quantum */ 340 NULL, /* importfn */ 341 NULL, /* releasefn */ 342 NULL, /* source */ 343 0, /* qcache_max */ 344 VM_NOSLEEP | VM_PRIVTAGS, 345 IPL_NONE); 346 KASSERT(iomap_arena != NULL); 347 348 vmem_add_bts(iomap_arena, iomap_btag_store, IOMAP_BTAG_COUNT); 349 int error = vmem_add(iomap_arena, iospace, iospace_size, 350 VM_NOSLEEP); 351 KASSERT(error == 0); 352 353 /* 354 * Up until now we have kept the TLB disabled, 355 * and that allowed the "PROM" to work. 356 * Specifically, romputc() and the debugger's getc() functions worked. 357 * Now is the last chance we get to turn it on. 358 * That means no more console I/O until autoconf() [sigh!], or.. 359 * The platform-specific code will have to map [1:1 probably] 360 * the I/O registers. 361 */ 362 register_t s = mips_cp0_status_read(); 363 s &= ~MIPS_SR_TS; 364 mips_cp0_status_write(s); 365 366 (*platform.cons_init)(); 367 368 /* 369 * Do NOT call cninit(); It will clobber cn_tab using constab[] 370 * which we do not use 371 */ 372 } 373 374 /* 375 * Allocates a virtual range suitable for mapping in physical memory. 376 * Uses a vmem arena when allocating space, which is allocated from 377 * the IOMAP submap. SIZE is a linear range (NOT vax-pages like the VAX). 378 * If the page requested is bigger than a logical page, space is 379 * allocated from the kernel map instead. 380 */ 381 vaddr_t 382 mips_map_physmem(paddr_t phys, vsize_t size) 383 { 384 vmem_addr_t addr; 385 int error; 386 static int warned = 0; 387 388 size += phys & PAGE_MASK; 389 if (size > PAGE_SIZE) { 390 addr = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY); 391 if (addr == 0) 392 panic("mips_map_physmem: kernel map full"); 393 } else { 394 error = vmem_alloc(iomap_arena, mips_round_page(size), 395 VM_BESTFIT | VM_NOSLEEP, &addr); 396 if (error) { 397 if (warned++ == 0) /* Warn only once */ 398 printf("mips_map_physmem: iomap too small"); 399 return 0; 400 } 401 } 402 ioaccess(addr, phys, size); 403 #ifdef PHYSMEMDEBUG 404 printf("mips_map_physmem: alloc'ed %x bytes for paddr %x, at %x\n", 405 size, phys, addr); 406 #endif 407 return addr | (phys & PAGE_MASK); 408 } 409 410 /* 411 * Unmaps the previous mapped (addr, size) pair. 412 */ 413 void 414 mips_unmap_physmem(vaddr_t addr, vsize_t size) 415 { 416 #ifdef PHYSMEMDEBUG 417 printf("mips_unmap_physmem: unmapping %x bytes at addr %x\n", 418 size, addr); 419 #endif 420 size += addr & PAGE_MASK; 421 addr &= ~PAGE_MASK; 422 423 iounaccess(addr, size); 424 if (size > PAGE_SIZE) 425 uvm_km_free(kernel_map, addr, size, UVM_KMF_VAONLY); 426 else 427 vmem_free(iomap_arena, addr, mips_round_page(size)); 428 } 429 430 /* 431 * Machine-dependent startup code: allocate memory for variable-sized 432 * tables. 433 */ 434 void 435 cpu_startup(void) 436 { 437 vaddr_t minaddr, maxaddr; 438 char pbuf[9]; 439 #ifdef DEBUG 440 extern int pmapdebug; /* XXX */ 441 int opmapdebug = pmapdebug; 442 443 pmapdebug = 0; 444 #endif 445 446 /* 447 * Good {morning,afternoon,evening,night}. 448 */ 449 printf("%s%s", copyright, version); 450 printf("%s\n", cpu_getmodel()); 451 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 452 printf("total memory = %s\n", pbuf); 453 454 minaddr = 0; 455 456 /* 457 * Allocate a submap for physio 458 */ 459 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 460 VM_PHYS_SIZE, 0, false, NULL); 461 462 /* 463 * No need to allocate an mbuf cluster submap. Mbuf clusters 464 * are allocated via the pool allocator, and we use KSEG to 465 * map those pages. 466 */ 467 468 #ifdef DEBUG 469 pmapdebug = opmapdebug; 470 #endif 471 format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 472 printf("avail memory = %s\n", pbuf); 473 } 474 475 /* 476 * Look up information in bootinfo of boot loader. 477 */ 478 void * 479 lookup_bootinfo(int type) 480 { 481 struct btinfo_common *bt; 482 char *help = bootinfo; 483 484 /* Check for a bootinfo record first. */ 485 if (help == NULL) 486 return (NULL); 487 488 do { 489 bt = (struct btinfo_common *)help; 490 if (bt->type == type) 491 return ((void *)help); 492 help += bt->next; 493 } while (bt->next != 0 && 494 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 495 496 return (NULL); 497 } 498 499 void 500 cpu_reboot(volatile int howto, /* XXX volatile to keep gcc happy */ 501 char *bootstr) 502 { 503 504 /* take a snap shot before clobbering any registers */ 505 if (curlwp) 506 savectx(curpcb); 507 508 #ifdef DEBUG 509 if (panicstr) 510 stacktrace(); 511 #endif 512 513 /* If system is cold, just halt. */ 514 if (cold) { 515 howto |= RB_HALT; 516 goto haltsys; 517 } 518 519 /* If "always halt" was specified as a boot flag, obey. */ 520 if ((boothowto & RB_HALT) != 0) 521 howto |= RB_HALT; 522 523 boothowto = howto; 524 if ((howto & RB_NOSYNC) == 0) { 525 /* 526 * Synchronize the disks.... 527 */ 528 vfs_shutdown(); 529 } 530 531 /* Disable interrupts. */ 532 splhigh(); 533 534 /* If rebooting and a dump is requested do it. */ 535 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 536 dumpsys(); 537 538 haltsys: 539 /* run any shutdown hooks */ 540 doshutdownhooks(); 541 542 pmf_system_shutdown(boothowto); 543 544 /* Finally, halt/reboot the system. */ 545 printf("%s\n\n", ((howto & RB_HALT) != 0) ? "halted." : "rebooting..."); 546 547 prom_halt(howto); 548 for (;;) ; 549 /*NOTREACHED*/ 550 } 551 552 #if defined(MIPS_4GB_PHYSICAL_MEMORY) 553 #define trim_memory(n) n 554 #else 555 #if 0 556 #define TOO_MUCH (MIPS_PHYS_MASK+1) 557 #else 558 #define TOO_MUCH (2*64*1024*1024) 559 #endif 560 u_long trim_memory(uint32_t nbytes);/*cheat*/ 561 u_long trim_memory(uint32_t nbytes) 562 { 563 int i; 564 u_long first, last; 565 566 nbytes *= 4096; 567 if (nbytes <= TOO_MUCH) 568 return nbytes; 569 570 /* We have more memory than we can handle */ 571 572 mem_clusters[mem_cluster_cnt].start = 0;/* sentinel record */ 573 mem_clusters[mem_cluster_cnt].size = 0; 574 for (i = 0; i < mem_cluster_cnt;) { 575 first = mem_clusters[i].start; 576 last = mem_clusters[i].start + mem_clusters[i].size; 577 578 if (first > TOO_MUCH) { 579 printf("Too much memory, ignoring memory " 580 "range %08lx..%08lx\n", first, last); 581 memcpy(mem_clusters+i,mem_clusters+i+1, 582 (sizeof(mem_clusters[0])*(mem_cluster_cnt-i))); 583 mem_cluster_cnt--; 584 continue; 585 } 586 587 if (last > TOO_MUCH) { 588 last = TOO_MUCH; 589 printf("Too much memory in cluster %d, trimming " 590 "memory to range %08lx..%08lx\n", 591 i, first, last); 592 mem_clusters[i].size = last - mem_clusters[i].start; 593 } 594 i++; 595 } 596 return TOO_MUCH; 597 } 598 #endif 599 600 /* 601 * Find out how much memory is available by testing memory. 602 */ 603 int 604 memsize_scan(void *first) 605 { 606 int i, mem; 607 char *cp; 608 609 mem = btoc((paddr_t)first - MIPS_KSEG0_START); 610 cp = (char *)MIPS_PHYS_TO_KSEG1(mem << PGSHIFT); 611 while (cp < (char *)physmem_boardmax) { 612 int j; 613 if (badaddr(cp, 4)) 614 break; 615 i = *(int *)cp; 616 j = ((int *)cp)[4]; 617 *(int *)cp = 0xa5a5a5a5; 618 /* 619 * Data will persist on the bus if we read it right away. 620 * Have to be tricky here. 621 */ 622 ((int *)cp)[4] = 0x5a5a5a5a; 623 wbflush(); 624 if (*(int *)cp != 0xa5a5a5a5) 625 break; 626 *(int *)cp = i; 627 ((int *)cp)[4] = j; 628 cp += PAGE_SIZE; 629 mem++; 630 } 631 632 /* 633 * Now that we know how much memory we have, initialize the 634 * mem cluster array. 635 */ 636 mem_clusters[0].start = 0; /* XXX is this correct? */ 637 mem_clusters[0].size = ctob(mem); 638 mem_cluster_cnt = 1; 639 640 /* clear any memory error conditions possibly caused by probe */ 641 (*platform.bus_reset)(); 642 return (mem); 643 } 644 645 /* 646 * Find out how much memory is available by testing memory, starting at first. 647 * Returns the total number of pages. 648 */ 649 int 650 memsize_pmt(void * first) 651 { 652 int i, mem; 653 struct _Pmt *Pmt = ThePmt; 654 struct _Sram *ram; 655 uint32_t addr, len; 656 657 /* 658 * Build the RAM memory map from the PMT. 659 */ 660 mem = 0; 661 for (i = 0; i < VM_PHYSSEG_MAX; Pmt--) { 662 uint16_t tag = Pmt->Tag; 663 664 if (tag == PMTTAG_END_OF_TABLE) 665 break; 666 667 if ((tag != PMTTAG_SRAM) && (tag != PMTTAG_DDRAM)) 668 continue; 669 670 /* 671 * Got a memory controller segment, 672 * scan all the controllers in it 673 */ 674 ram = (struct _Sram *)(Pmt->TopOfPhysicalAddress << 16); 675 676 for (;(ram->BaseAddressAndTag & SRAMBT_TAG) == tag;) { 677 addr = ram->BaseAddressAndTag & SRAMBT_BASE; 678 len = ram->Control & SRAMST_SIZE; 679 680 mem_clusters[i].start = addr; 681 mem_clusters[i].size = len; 682 printf("memory segment %2d start %08lx size %08lx\n", i, 683 (long)mem_clusters[i].start, 684 (long)mem_clusters[i].size); 685 i++; 686 mem += len; 687 688 /* SRAM and DDRAM have different sizes */ 689 ram = (tag == PMTTAG_SRAM) ? ram+1 : ram+2; 690 } 691 } 692 mem_cluster_cnt = i; 693 694 return trim_memory(btoc(mem)); 695 } 696 /* 697 * Ensure all platform vectors are always initialized. 698 */ 699 static void 700 unimpl_bus_reset(void) 701 { 702 703 panic("sysconf.init didn't set bus_reset"); 704 } 705 706 static void 707 unimpl_cons_init(void) 708 { 709 710 panic("sysconf.init didn't set cons_init"); 711 } 712 713 static void 714 unimpl_iointr(uint32_t status, vaddr_t pc, uint32_t ipending) 715 { 716 717 panic("sysconf.init didn't set intr"); 718 } 719 720 static void 721 unimpl_intr_establish(device_t dev, void *cookie, int level, 722 int (*handler) (void *,void *), void *arg) 723 { 724 725 panic("sysconf.init didn't set intr_establish"); 726 } 727 728 static int 729 unimpl_memsize(void * first) 730 { 731 732 panic("sysconf.init didn't set memsize"); 733 } 734 735 /* 736 * Wait "n" microseconds. 737 */ 738 void 739 delay(int n) 740 { 741 742 DELAY(n); 743 } 744