1 /* $NetBSD: machdep.c,v 1.42 2002/11/09 19:20:18 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Soren S. Jorvang 5 * Copyright (c) 2001, 2002 Rafal K. Boni 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed for the 19 * NetBSD Project. See http://www.netbsd.org/ for 20 * information about NetBSD. 21 * 4. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include "opt_ddb.h" 37 #include "opt_kgdb.h" 38 #include "opt_execfmt.h" 39 #include "opt_cputype.h" 40 #include "opt_machtypes.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/proc.h> 46 #include <sys/buf.h> 47 #include <sys/reboot.h> 48 #include <sys/conf.h> 49 #include <sys/file.h> 50 #include <sys/malloc.h> 51 #include <sys/mbuf.h> 52 #include <sys/msgbuf.h> 53 #include <sys/device.h> 54 #include <sys/user.h> 55 #include <sys/exec.h> 56 #include <sys/mount.h> 57 #include <sys/syscallargs.h> 58 #include <sys/kcore.h> 59 60 #include <uvm/uvm_extern.h> 61 62 #include <machine/cpu.h> 63 #include <machine/reg.h> 64 #include <machine/psl.h> 65 #include <machine/pte.h> 66 #include <machine/autoconf.h> 67 #include <machine/machtype.h> 68 #include <machine/sysconf.h> 69 #include <machine/intr.h> 70 #include <machine/bootinfo.h> 71 #include <mips/locore.h> 72 73 #include <dev/arcbios/arcbios.h> 74 #include <dev/arcbios/arcbiosvar.h> 75 76 #if defined(DDB) || defined(KGDB) 77 #include <machine/db_machdep.h> 78 #include <ddb/db_access.h> 79 #include <ddb/db_sym.h> 80 #include <ddb/db_extern.h> 81 #ifndef DB_ELFSIZE 82 #error Must define DB_ELFSIZE! 83 #endif 84 #define ELFSIZE DB_ELFSIZE 85 #include <sys/exec_elf.h> 86 #endif 87 88 #include <dev/cons.h> 89 90 /* For sysctl_hw. */ 91 extern char cpu_model[]; 92 93 struct sgimips_intrhand intrtab[NINTR]; 94 95 /* Our exported CPU info; we can have only one. */ 96 struct cpu_info cpu_info_store; 97 98 /* Maps for VM objects. */ 99 struct vm_map *exec_map = NULL; 100 struct vm_map *mb_map = NULL; 101 struct vm_map *phys_map = NULL; 102 103 int mach_type; /* IPxx type */ 104 int mach_subtype; /* subtype: eg., Guiness/Fullhouse for IP22 */ 105 int mach_boardrev; /* machine board revision, in case it matters */ 106 107 int physmem; /* Total physical memory */ 108 int arcsmem; /* Memory used by the ARCS firmware */ 109 110 int ncpus; 111 112 /* CPU interrupt masks */ 113 u_int32_t biomask; 114 u_int32_t netmask; 115 u_int32_t ttymask; 116 u_int32_t clockmask; 117 118 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 119 int mem_cluster_cnt; 120 121 #ifdef IP20 122 void ip20_init(void); 123 #endif 124 125 #ifdef IP22 126 void ip22_init(void); 127 #endif 128 129 #ifdef IP32 130 void ip32_init(void); 131 #endif 132 133 void * cpu_intr_establish(int, int, int (*)(void *), void *); 134 135 void mach_init(int, char **, int, struct btinfo_common *); 136 void unconfigured_system_type(int); 137 138 void sgimips_count_cpus(struct arcbios_component *, 139 struct arcbios_treewalk_context *); 140 141 #ifdef KGDB 142 void zs_kgdb_init(void); 143 void kgdb_connect(int); 144 #endif 145 146 /* Motherboard or system-specific initialization vector */ 147 static void unimpl_bus_reset(void); 148 static void unimpl_cons_init(void); 149 static void unimpl_iointr(unsigned, unsigned, unsigned, unsigned); 150 static void unimpl_intr_establish(int, int, int (*)(void *), void *); 151 static unsigned long nullwork(void); 152 153 void ddb_trap_hook(int where); 154 155 struct platform platform = { 156 unimpl_bus_reset, 157 unimpl_cons_init, 158 unimpl_iointr, 159 unimpl_intr_establish, 160 (void *)nullwork, 161 }; 162 163 /* 164 * safepri is a safe priority for sleep to set for a spin-wait during 165 * autoconfiguration or after a panic. Used as an argument to splx(). 166 */ 167 int safepri = MIPS1_PSL_LOWIPL; 168 169 extern caddr_t esym; 170 extern u_int32_t ssir; 171 extern struct user *proc0paddr; 172 173 static struct btinfo_common *bootinfo; 174 175 /* 176 * Do all the stuff that locore normally does before calling main(). 177 * Process arguments passed to us by the ARCS firmware. 178 */ 179 void 180 mach_init(argc, argv, magic, btinfo) 181 int argc; 182 char **argv; 183 int magic; 184 struct btinfo_common *btinfo; 185 { 186 extern char kernel_text[], _end[]; 187 paddr_t first, last; 188 int firstpfn, lastpfn; 189 caddr_t v; 190 vsize_t size; 191 struct arcbios_mem *mem; 192 char *cpufreq; 193 struct btinfo_symtab *bi_syms; 194 caddr_t ssym; 195 vaddr_t kernend; 196 int kernstartpfn, kernendpfn; 197 int i, nsym; 198 199 #if 0 200 /* Clear the BSS segment. XXX Is this really necessary? */ 201 memset(_edata, 0, _end - _edata); 202 #endif 203 204 /* 205 * Initialize ARCS. This will set up the bootstrap console. 206 */ 207 arcbios_init(MIPS_PHYS_TO_KSEG0(0x00001000)); 208 strcpy(cpu_model, arcbios_system_identifier); 209 210 uvm_setpagesize(); 211 212 if (magic == BOOTINFO_MAGIC && btinfo != NULL) { 213 #ifdef DEBUG 214 printf("Found bootinfo at %p\n", btinfo); 215 #endif 216 bootinfo = btinfo; 217 } 218 219 bi_syms = lookup_bootinfo(BTINFO_SYMTAB); 220 if (bi_syms != NULL) { 221 nsym = bi_syms->nsym; 222 ssym = (caddr_t) bi_syms->ssym; 223 esym = (caddr_t) bi_syms->esym; 224 kernend = round_page((vaddr_t) esym); 225 } else { 226 nsym = 0; 227 ssym = esym = NULL; 228 kernend = round_page((vaddr_t) _end); 229 } 230 231 kernstartpfn = atop(MIPS_KSEG0_TO_PHYS((vaddr_t) kernel_text)); 232 kernendpfn = atop(MIPS_KSEG0_TO_PHYS(kernend)); 233 234 /* 235 * Now set up the real console. 236 * XXX Should be done later after we determine systype. 237 */ 238 consinit(); 239 240 #if 1 /* skidt? */ 241 ARCBIOS->FlushAllCaches(); 242 #endif 243 244 cpufreq = ARCBIOS->GetEnvironmentVariable("cpufreq"); 245 246 if (cpufreq == 0) 247 panic("no $cpufreq"); 248 249 /* 250 * Note initial estimate of CPU speed... If we care enough, we'll 251 * use the RTC to get a better estimate later. 252 */ 253 curcpu()->ci_cpu_freq = strtoul(cpufreq, NULL, 10) * 1000000; 254 255 /* 256 * argv[0] can be either the bootloader loaded by the PROM, or a 257 * kernel loaded directly by the PROM. 258 * 259 * If argv[0] is the bootloader, then argv[1] might be the kernel 260 * that was loaded. How to tell which one to use? 261 * 262 * If argv[1] isn't an environment string, try to use it to set the 263 * boot device. 264 */ 265 if (strchr(argv[1], '=') != 0) 266 makebootdev(argv[1]); 267 268 boothowto = RB_SINGLE; 269 270 /* 271 * Single- or multi-user ('auto' in SGI terms). 272 */ 273 for (i = 0; i < argc; i++) { 274 if (strcmp(argv[i], "OSLoadOptions=auto") == 0) 275 boothowto &= ~RB_SINGLE; 276 277 /* 278 * The case where the kernel has been loaded by a 279 * boot loader will usually have been catched by 280 * the first makebootdev() case earlier on, but 281 * we still use OSLoadPartition to get the preferred 282 * root filesystem location, even if it's not 283 * actually the location of the loaded kernel. 284 */ 285 if (strncmp(argv[i], "OSLoadPartition=", 15) == 0) 286 makebootdev(argv[i] + 16); 287 } 288 289 /* 290 * When the kernel is loaded directly by the firmware, and 291 * no explicit OSLoadPartition is set, we fall back on 292 * SystemPartition for the boot device. 293 */ 294 for (i = 0; i < argc; i++) { 295 if (strncmp(argv[i], "SystemPartition", 15) == 0) 296 makebootdev(argv[i] + 16); 297 298 #ifdef DEBUG 299 printf("argv[%d]: %s\n", i, argv[i]); 300 #endif 301 } 302 303 #if defined(KGDB) || defined(DDB) 304 /* Set up DDB hook to turn off watchdog on entry */ 305 db_trap_callback = ddb_trap_hook; 306 307 #ifdef DDB 308 ddb_init(nsym, ssym, esym); 309 if (boothowto & RB_KDB) 310 Debugger(); 311 #endif 312 #ifdef KGDB 313 zs_kgdb_init(); /* XXX */ 314 if (boothowto & RB_KDB) 315 kgdb_connect(0); 316 #endif 317 #endif 318 319 for (i = 0; arcbios_system_identifier[i] != '\0'; i++) { 320 if (arcbios_system_identifier[i] >= '0' && 321 arcbios_system_identifier[i] <= '9') { 322 mach_type = strtoul(&arcbios_system_identifier[i], 323 NULL, 10); 324 break; 325 } 326 } 327 328 if (mach_type <= 0) 329 panic("invalid architecture"); 330 331 switch (mach_type) { 332 case MACH_SGI_IP20: 333 #ifdef IP20 334 ip20_init(); 335 #else 336 unconfigured_system_type(mach_type); 337 #endif 338 break; 339 340 case MACH_SGI_IP22: 341 #ifdef IP22 342 ip22_init(); 343 #else 344 unconfigured_system_type(mach_type); 345 #endif 346 break; 347 348 case MACH_SGI_IP32: 349 #ifdef IP32 350 ip32_init(); 351 #else 352 unconfigured_system_type(mach_type); 353 #endif 354 break; 355 356 default: 357 panic("IP%d architecture not yet supported", mach_type); 358 break; 359 } 360 361 physmem = arcsmem = 0; 362 mem_cluster_cnt = 0; 363 mem = NULL; 364 365 #ifdef DEBUG 366 i = 0; 367 mem = NULL; 368 369 do { 370 if ((mem = ARCBIOS->GetMemoryDescriptor(mem)) != NULL) { 371 i++; 372 printf("Mem block %d: type %d, base 0x%x, size 0x%x\n", 373 i, mem->Type, mem->BasePage, mem->PageCount); 374 } 375 } while (mem != NULL); 376 #endif 377 378 /* 379 * XXX This code assumes that ARCS provides the memory 380 * XXX sorted in ascending order. 381 */ 382 mem = NULL; 383 for (i = 0; mem_cluster_cnt < VM_PHYSSEG_MAX; i++) { 384 mem = ARCBIOS->GetMemoryDescriptor(mem); 385 386 if (mem == NULL) 387 break; 388 389 first = round_page(mem->BasePage * ARCBIOS_PAGESIZE); 390 last = trunc_page(first + mem->PageCount * ARCBIOS_PAGESIZE); 391 size = last - first; 392 393 firstpfn = atop(first); 394 lastpfn = atop(last); 395 396 switch (mem->Type) { 397 case ARCBIOS_MEM_FreeContiguous: 398 case ARCBIOS_MEM_FreeMemory: 399 case ARCBIOS_MEM_LoadedProgram: 400 if (firstpfn <= kernstartpfn && 401 kernendpfn <= lastpfn) { 402 /* 403 * Must compute the location of the kernel 404 * within the segment. 405 */ 406 #ifdef DEBUG 407 printf("Cluster %d contains kernel\n", i); 408 #endif 409 if (firstpfn < kernstartpfn) { 410 /* 411 * There is a chunk before the kernel. 412 */ 413 #ifdef DEBUG 414 printf("Loading chunk before kernel: " 415 "0x%x / 0x%x\n", firstpfn, 416 kernstartpfn); 417 #endif 418 uvm_page_physload(firstpfn, 419 kernstartpfn, 420 firstpfn, kernstartpfn, 421 VM_FREELIST_DEFAULT); 422 } 423 if (kernendpfn < lastpfn) { 424 /* 425 * There is a chunk after the kernel. 426 */ 427 #ifdef DEBUG 428 printf("Loading chunk after kernel: " 429 "0x%x / 0x%x\n", kernendpfn, 430 lastpfn); 431 #endif 432 uvm_page_physload(kernendpfn, 433 lastpfn, kernendpfn, 434 lastpfn, VM_FREELIST_DEFAULT); 435 } 436 } else { 437 /* 438 * Just load this cluster as one chunk. 439 */ 440 #ifdef DEBUG 441 printf("Loading cluster %d: 0x%x / 0x%x\n", i, 442 firstpfn, lastpfn); 443 #endif 444 uvm_page_physload(firstpfn, lastpfn, 445 firstpfn, lastpfn, VM_FREELIST_DEFAULT); 446 } 447 mem_clusters[mem_cluster_cnt].start = first; 448 mem_clusters[mem_cluster_cnt].size = size; 449 mem_cluster_cnt++; 450 break; 451 452 case ARCBIOS_MEM_FirmwareTemporary: 453 case ARCBIOS_MEM_FirmwarePermanent: 454 arcsmem += btoc(size); 455 break; 456 457 case ARCBIOS_MEM_ExecptionBlock: 458 case ARCBIOS_MEM_SystemParameterBlock: 459 case ARCBIOS_MEM_BadMemory: 460 break; 461 462 default: 463 panic("unknown memory descriptor %d type %d", 464 i, mem->Type); 465 } 466 467 physmem += btoc(size); 468 469 } 470 471 if (mem_cluster_cnt == 0) 472 panic("no free memory descriptors found"); 473 474 /* We can now no longer use bootinfo. */ 475 bootinfo = NULL; 476 477 /* 478 * Walk the component tree and count the number of CPUs 479 * present in the system. 480 */ 481 arcbios_tree_walk(sgimips_count_cpus, NULL); 482 483 /* 484 * Copy exception-dispatch code down to exception vector. 485 * Initialize locore-function vector. 486 * Clear out the I and D caches. 487 */ 488 mips_vector_init(); 489 490 /* 491 * Initialize error message buffer (at end of core). 492 */ 493 mips_init_msgbuf(); 494 495 /* 496 * Compute the size of system data structures. pmap_bootstrap() 497 * needs some of this information. 498 */ 499 size = (vsize_t)allocsys(NULL, NULL); 500 501 pmap_bootstrap(); 502 503 /* 504 * Allocate space for proc0's USPACE. 505 */ 506 v = (caddr_t)uvm_pageboot_alloc(USPACE); 507 proc0.p_addr = proc0paddr = (struct user *)v; 508 proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1; 509 curpcb = &proc0.p_addr->u_pcb; 510 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 511 512 /* 513 * Allocate space for system data structures. These data structures 514 * are allocated here instead of cpu_startup() because physical 515 * memory is directly addressable. We don't have to map these into 516 * virtual address space. 517 */ 518 v = (caddr_t)uvm_pageboot_alloc(size); 519 if ((vsize_t) (allocsys(v, NULL) - v) != size) 520 panic("mach_init: table size inconsistency"); 521 } 522 523 void 524 sgimips_count_cpus(struct arcbios_component *node, 525 struct arcbios_treewalk_context *atc) 526 { 527 528 switch (node->Class) { 529 case COMPONENT_CLASS_ProcessorClass: 530 if (node->Type == COMPONENT_TYPE_CPU) 531 ncpus++; 532 break; 533 534 default: 535 break; 536 } 537 } 538 539 /* 540 * Allocate memory for variable-sized tables. 541 */ 542 void 543 cpu_startup() 544 { 545 u_int i, base, residual; 546 vaddr_t minaddr, maxaddr; 547 vsize_t size; 548 char pbuf[9]; 549 550 printf(version); 551 552 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 553 printf("%s memory", pbuf); 554 555 /* 556 * Allocate virtual address space for file I/O buffers. 557 * Note they are different than the array of headers, 'buf', 558 * and usually occupy more virtual memory than physical. 559 */ 560 size = MAXBSIZE * nbuf; 561 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size), 562 NULL, UVM_UNKNOWN_OFFSET, 0, 563 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 564 UVM_ADV_NORMAL, 0)) != 0) 565 panic("startup: cannot allocate VM for buffers"); 566 minaddr = (vaddr_t)buffers; 567 base = bufpages / nbuf; 568 residual = bufpages % nbuf; 569 for (i = 0; i < nbuf; i++) { 570 vsize_t curbufsize; 571 vaddr_t curbuf; 572 struct vm_page *pg; 573 574 /* 575 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 576 * that MAXBSIZE space, we allocate and map (base+1) pages 577 * for the first "residual" buffers, and then we allocate 578 * "base" pages for the rest. 579 */ 580 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 581 curbufsize = NBPG * ((i < residual) ? (base + 1) : base); 582 583 while (curbufsize) { 584 pg = uvm_pagealloc(NULL, 0, NULL, 0); 585 if (pg == NULL) 586 panic("cpu_startup: not enough memory for " 587 "buffer cache"); 588 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 589 VM_PROT_READ|VM_PROT_WRITE); 590 curbuf += PAGE_SIZE; 591 curbufsize -= PAGE_SIZE; 592 } 593 } 594 pmap_update(pmap_kernel()); 595 596 /* 597 * Allocate a submap for exec arguments. This map effectively 598 * limits the number of processes exec'ing at any time. 599 */ 600 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 601 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 602 /* 603 * Allocate a submap for physio. 604 */ 605 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 606 VM_PHYS_SIZE, 0, FALSE, NULL); 607 608 /* 609 * (No need to allocate an mbuf cluster submap. Mbuf clusters 610 * are allocated via the pool allocator, and we use KSEG to 611 * map those pages.) 612 */ 613 614 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 615 printf(", %s free", pbuf); 616 format_bytes(pbuf, sizeof(pbuf), ctob(arcsmem)); 617 printf(", %s for ARCS", pbuf); 618 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 619 printf(", %s in %u buffers\n", pbuf, nbuf); 620 621 /* 622 * Set up buffers, so they can be used to read disk labels. 623 */ 624 bufinit(); 625 } 626 627 int waittime = -1; 628 629 void 630 cpu_reboot(howto, bootstr) 631 int howto; 632 char *bootstr; 633 { 634 /* Take a snapshot before clobbering any registers. */ 635 if (curproc) 636 savectx((struct user *)curpcb); 637 638 #if 1 639 /* Clear and disable watchdog timer. */ 640 switch (mach_type) { 641 case MACH_SGI_IP22: 642 *(volatile u_int32_t *)0xbfa00014 = 0; 643 *(volatile u_int32_t *)0xbfa00004 &= ~0x100; 644 break; 645 646 case MACH_SGI_IP32: 647 *(volatile u_int32_t *)0xb4000034 = 0; 648 *(volatile u_int32_t *)0xb400000c &= ~0x200; 649 break; 650 } 651 #endif 652 653 if (cold) { 654 howto |= RB_HALT; 655 goto haltsys; 656 } 657 658 /* If "always halt" was specified as a boot flag, obey. */ 659 if (boothowto & RB_HALT) 660 howto |= RB_HALT; 661 662 boothowto = howto; 663 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 664 waittime = 0; 665 vfs_shutdown(); 666 667 /* 668 * If we've been adjusting the clock, the todr 669 * will be out of synch; adjust it now. 670 */ 671 resettodr(); 672 } 673 674 splhigh(); 675 676 if (howto & RB_DUMP) 677 dumpsys(); 678 679 haltsys: 680 681 doshutdownhooks(); 682 683 /* 684 * Calling ARCBIOS->PowerDown() results in a "CP1 unusable trap" 685 * which lands me back in DDB, at least on my Indy. So, enable 686 * the FPU before asking the PROM to power down to avoid this.. 687 * It seems to want the FPU to play the `poweroff tune' 8-/ 688 */ 689 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 690 /* Set CP1 usable bit in SR */ 691 mips_cp0_status_write(mips_cp0_status_read() | 692 MIPS_SR_COP_1_BIT); 693 694 printf("powering off...\n\n"); 695 delay(500000); 696 ARCBIOS->PowerDown(); 697 printf("WARNING: powerdown failed\n"); 698 /* 699 * RB_POWERDOWN implies RB_HALT... fall into it... 700 */ 701 } 702 703 if (howto & RB_HALT) { 704 printf("halting...\n\n"); 705 ARCBIOS->EnterInteractiveMode(); 706 } 707 708 printf("rebooting...\n\n"); 709 ARCBIOS->Reboot(); 710 711 for (;;); 712 } 713 714 void 715 microtime(tvp) 716 struct timeval *tvp; 717 { 718 int s = splclock(); 719 static struct timeval lasttime; 720 721 *tvp = time; 722 tvp->tv_usec += (*platform.clkread)(); 723 724 /* 725 * Make sure that the time returned is always greater 726 * than that returned by the previous call. 727 */ 728 if (tvp->tv_sec == lasttime.tv_sec && 729 tvp->tv_usec <= lasttime.tv_usec && 730 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { 731 tvp->tv_sec++; 732 tvp->tv_usec -= 1000000; 733 } 734 lasttime = *tvp; 735 splx(s); 736 } 737 738 __inline void 739 delay(n) 740 unsigned long n; 741 { 742 u_long i; 743 long divisor = curcpu()->ci_divisor_delay; 744 745 while (n-- > 0) 746 for (i = divisor; i > 0; i--) 747 ; 748 } 749 750 /* 751 * Ensure all platform vectors are always initialized. 752 */ 753 static void 754 unimpl_bus_reset() 755 { 756 757 panic("target init didn't set bus_reset"); 758 } 759 760 static void 761 unimpl_cons_init() 762 { 763 764 panic("target init didn't set cons_init"); 765 } 766 767 static void 768 unimpl_iointr(mask, pc, statusreg, causereg) 769 u_int mask; 770 u_int pc; 771 u_int statusreg; 772 u_int causereg; 773 { 774 775 panic("target init didn't set intr"); 776 } 777 778 static void 779 unimpl_intr_establish(level, ipl, handler, arg) 780 int level; 781 int ipl; 782 int (*handler) __P((void *)); 783 void *arg; 784 { 785 panic("target init didn't set intr_establish"); 786 } 787 788 static unsigned long 789 nullwork() 790 { 791 792 return (0); 793 } 794 795 void * 796 cpu_intr_establish(level, ipl, func, arg) 797 int level; 798 int ipl; 799 int (*func)(void *); 800 void *arg; 801 { 802 (*platform.intr_establish)(level, ipl, func, arg); 803 return (void *) -1; 804 } 805 806 void 807 cpu_intr(status, cause, pc, ipending) 808 u_int32_t status; 809 u_int32_t cause; 810 u_int32_t pc; 811 u_int32_t ipending; 812 { 813 uvmexp.intrs++; 814 815 if (ipending & MIPS_HARD_INT_MASK) 816 (*platform.iointr)(status, cause, pc, ipending); 817 818 /* 819 * Service pending soft interrupts -- make sure to re-enable 820 * only those hardware interrupts that are not masked and 821 * that weren't pending on the current invocation of the 822 * interrupt handler, else we risk infinite stack growth 823 * due to nested interrupts. 824 */ 825 /* software simulated interrupt */ 826 if ((ipending & MIPS_SOFT_INT_MASK_1) || 827 (ssir && (status & MIPS_SOFT_INT_MASK_1))) { 828 _splset(MIPS_SR_INT_IE | 829 (status & ~ipending & MIPS_HARD_INT_MASK)); 830 _clrsoftintr(MIPS_SOFT_INT_MASK_1); 831 softintr_dispatch(); 832 } 833 } 834 835 void unconfigured_system_type(int ipnum) 836 { 837 printf("Kernel not configured for IP%d support. Add options `IP%d'\n", 838 ipnum, ipnum); 839 printf("to kernel configuration file to enable IP%d support!\n", 840 ipnum); 841 printf("\n"); 842 843 panic("Kernel not configured for current hardware!"); 844 } 845 846 void * 847 lookup_bootinfo(int type) 848 { 849 struct btinfo_common *b = bootinfo; 850 851 while (bootinfo != NULL) { 852 if (b->type == type) 853 return (b); 854 b = b->next; 855 } 856 857 return (NULL); 858 } 859 860 #if defined(DDB) || defined(KGDB) 861 862 void ddb_trap_hook(int where) 863 { 864 switch (where) { 865 case 1: /* Entry to DDB, turn watchdog off */ 866 switch (mach_type) { 867 case MACH_SGI_IP32: 868 *(volatile u_int32_t *)0xb4000034 = 0; 869 *(volatile u_int32_t *)0xb400000c &= ~0x200; 870 break; 871 872 case MACH_SGI_IP22: 873 *(volatile u_int32_t *)0xbfa00014 = 0; 874 *(volatile u_int32_t *)0xbfa00004 &= ~0x100; 875 break; 876 } 877 break; 878 879 case 0: /* Exit from DDB, turn watchdog back on */ 880 switch (mach_type) { 881 case MACH_SGI_IP32: 882 *(volatile u_int32_t *)0xb400000c |= 0x200; 883 *(volatile u_int32_t *)0xb4000034 = 0; 884 break; 885 886 case MACH_SGI_IP22: 887 *(volatile u_int32_t *)0xbfa00004 |= 0x100; 888 *(volatile u_int32_t *)0xbfa00014 = 0; 889 890 break; 891 } 892 break; 893 } 894 } 895 896 #endif 897