1 /* $NetBSD: machdep.c,v 1.72 2002/05/13 06:26:45 matt Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 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 by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "opt_compat_netbsd.h" 35 #include "opt_ddb.h" 36 #include "opt_ipkdb.h" 37 38 #include <sys/param.h> 39 #include <sys/buf.h> 40 #include <sys/conf.h> 41 #include <sys/device.h> 42 #include <sys/exec.h> 43 #include <sys/kernel.h> 44 #include <sys/malloc.h> 45 #include <sys/map.h> 46 #include <sys/mbuf.h> 47 #include <sys/mount.h> 48 #include <sys/msgbuf.h> 49 #include <sys/proc.h> 50 #include <sys/reboot.h> 51 #include <sys/syscallargs.h> 52 #include <sys/syslog.h> 53 #include <sys/systm.h> 54 #include <sys/user.h> 55 56 #ifdef DDB 57 #include <machine/db_machdep.h> 58 #include <ddb/db_extern.h> 59 #endif 60 61 #include <uvm/uvm_extern.h> 62 63 #include <net/netisr.h> 64 65 #include <powerpc/mpc6xx/bat.h> 66 #include <machine/bootinfo.h> 67 #include <machine/autoconf.h> 68 #define _POWERPC_BUS_DMA_PRIVATE 69 #include <machine/bus.h> 70 #include <machine/intr.h> 71 #include <machine/pmap.h> 72 #include <machine/powerpc.h> 73 #include <machine/trap.h> 74 75 #include <dev/cons.h> 76 77 #include "pfb.h" 78 79 #include "pc.h" 80 #if (NPC > 0) 81 #include <machine/pccons.h> 82 #endif 83 84 #include "vga.h" 85 #if (NVGA > 0) 86 #include <dev/ic/mc6845reg.h> 87 #include <dev/ic/pcdisplayvar.h> 88 #include <dev/ic/vgareg.h> 89 #include <dev/ic/vgavar.h> 90 #endif 91 92 #include "pckbc.h" 93 #if (NPCKBC > 0) 94 #include <dev/isa/isareg.h> 95 #include <dev/ic/i8042reg.h> 96 #include <dev/ic/pckbcvar.h> 97 #endif 98 99 #include "com.h" 100 #if (NCOM > 0) 101 #include <sys/termios.h> 102 #include <dev/ic/comreg.h> 103 #include <dev/ic/comvar.h> 104 #endif 105 106 /* 107 * Global variables used here and there 108 */ 109 struct vm_map *exec_map = NULL; 110 struct vm_map *mb_map = NULL; 111 struct vm_map *phys_map = NULL; 112 113 char bootinfo[BOOTINFO_MAXSIZE]; 114 115 char machine[] = MACHINE; /* machine */ 116 char machine_arch[] = MACHINE_ARCH; /* machine architecture */ 117 118 struct pcb *curpcb; 119 struct pmap *curpm; 120 struct proc *fpuproc; 121 122 extern struct user *proc0paddr; 123 124 struct bat battable[16]; 125 126 paddr_t bebox_mb_reg; /* BeBox MotherBoard register */ 127 128 #define OFMEMREGIONS 32 129 struct mem_region physmemr[OFMEMREGIONS], availmemr[OFMEMREGIONS]; 130 131 char *bootpath; 132 133 paddr_t msgbuf_paddr; 134 vaddr_t msgbuf_vaddr; 135 136 paddr_t avail_end; /* XXX temporary */ 137 138 void install_extint __P((void (*)(void))); 139 140 void 141 initppc(startkernel, endkernel, args, btinfo) 142 u_int startkernel, endkernel, args; 143 void *btinfo; 144 { 145 extern int trapcode, trapsize; 146 extern int alitrap, alisize; 147 extern int dsitrap, dsisize; 148 extern int isitrap, isisize; 149 extern int decrint, decrsize; 150 extern int tlbimiss, tlbimsize; 151 extern int tlbdlmiss, tlbdlmsize; 152 extern int tlbdsmiss, tlbdsmsize; 153 #ifdef DDB 154 extern int ddblow, ddbsize; 155 extern void *startsym, *endsym; 156 #endif 157 #ifdef IPKDB 158 extern int ipkdblow, ipkdbsize; 159 #endif 160 extern void consinit __P((void)); 161 extern void ext_intr __P((void)); 162 int exc, scratch; 163 164 /* 165 * copy bootinfo 166 */ 167 memcpy(bootinfo, btinfo, sizeof (bootinfo)); 168 169 /* 170 * BeBox memory region set 171 */ 172 { 173 struct btinfo_memory *meminfo; 174 175 meminfo = 176 (struct btinfo_memory *)lookup_bootinfo(BTINFO_MEMORY); 177 if (!meminfo) 178 panic("not found memory information in bootinfo"); 179 physmemr[0].start = 0; 180 physmemr[0].size = meminfo->memsize & ~PGOFSET; 181 availmemr[0].start = (endkernel + PGOFSET) & ~PGOFSET; 182 availmemr[0].size = meminfo->memsize - availmemr[0].start; 183 } 184 avail_end = physmemr[0].start + physmemr[0].size; /* XXX temporary */ 185 186 /* 187 * Get CPU clock 188 */ 189 { 190 struct btinfo_clock *clockinfo; 191 extern u_long ticks_per_sec, ns_per_tick; 192 193 clockinfo = 194 (struct btinfo_clock *)lookup_bootinfo(BTINFO_CLOCK); 195 if (!clockinfo) 196 panic("not found clock information in bootinfo"); 197 ticks_per_sec = clockinfo->ticks_per_sec; 198 ns_per_tick = 1000000000 / ticks_per_sec; 199 } 200 201 /* 202 * BeBox MotherBoard's Register 203 * Interrupt Mask Reset 204 */ 205 *(volatile u_int *)(MOTHER_BOARD_REG + CPU0_INT_MASK) = 0x0ffffffc; 206 *(volatile u_int *)(MOTHER_BOARD_REG + CPU0_INT_MASK) = 0x80000023; 207 *(volatile u_int *)(MOTHER_BOARD_REG + CPU1_INT_MASK) = 0x0ffffffc; 208 209 proc0.p_addr = proc0paddr; 210 memset(proc0.p_addr, 0, sizeof *proc0.p_addr); 211 212 curpcb = &proc0paddr->u_pcb; 213 214 curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel(); 215 216 /* 217 * boothowto 218 */ 219 boothowto = args; 220 221 /* 222 * Init the I/O stuff before the console 223 */ 224 bebox_bus_space_init(); 225 226 /* 227 * i386 port says, that this shouldn't be here, 228 * but I really think the console should be initialized 229 * as early as possible. 230 */ 231 consinit(); 232 233 /* 234 * Initialize BAT registers to unmapped to not generate 235 * overlapping mappings below. 236 */ 237 asm volatile ("mtibatu 0,%0" :: "r"(0)); 238 asm volatile ("mtibatu 1,%0" :: "r"(0)); 239 asm volatile ("mtibatu 2,%0" :: "r"(0)); 240 asm volatile ("mtibatu 3,%0" :: "r"(0)); 241 asm volatile ("mtdbatu 0,%0" :: "r"(0)); 242 asm volatile ("mtdbatu 1,%0" :: "r"(0)); 243 asm volatile ("mtdbatu 2,%0" :: "r"(0)); 244 asm volatile ("mtdbatu 3,%0" :: "r"(0)); 245 246 /* 247 * Set up initial BAT table 248 */ 249 /* map the lowest 256M area */ 250 battable[0x0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); 251 battable[0x0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); 252 253 /* map the PCI/ISA I/O 256M area */ 254 battable[0x8].batl = BATL(BEBOX_BUS_SPACE_IO, BAT_I, BAT_PP_RW); 255 battable[0x8].batu = BATU(BEBOX_BUS_SPACE_IO, BAT_BL_256M, BAT_Vs); 256 257 /* map the PCI/ISA MEMORY 256M area */ 258 battable[0xc].batl = BATL(BEBOX_BUS_SPACE_MEM, BAT_I, BAT_PP_RW); 259 battable[0xc].batu = BATU(BEBOX_BUS_SPACE_MEM, BAT_BL_256M, BAT_Vs); 260 261 /* 262 * Now setup fixed bat registers 263 */ 264 asm volatile ("mtibatl 0,%0; mtibatu 0,%1" 265 :: "r"(battable[0x0].batl), "r"(battable[0x0].batu)); 266 asm volatile ("mtibatl 1,%0; mtibatu 1,%1" 267 :: "r"(battable[0x8].batl), "r"(battable[0x8].batu)); 268 asm volatile ("mtibatl 2,%0; mtibatu 2,%1" 269 :: "r"(battable[0xc].batl), "r"(battable[0xc].batu)); 270 271 asm volatile ("mtdbatl 0,%0; mtdbatu 0,%1" 272 :: "r"(battable[0x0].batl), "r"(battable[0x0].batu)); 273 asm volatile ("mtdbatl 1,%0; mtdbatu 1,%1" 274 :: "r"(battable[0x8].batl), "r"(battable[0x8].batu)); 275 asm volatile ("mtdbatl 2,%0; mtdbatu 2,%1" 276 :: "r"(battable[0xc].batl), "r"(battable[0xc].batu)); 277 278 /* 279 * Set up trap vectors 280 */ 281 for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) 282 switch (exc) { 283 default: 284 memcpy((void *)exc, &trapcode, (size_t)&trapsize); 285 break; 286 case EXC_EXI: 287 /* 288 * This one is (potentially) installed during autoconf 289 */ 290 break; 291 case EXC_ALI: 292 memcpy((void *)EXC_ALI, &alitrap, (size_t)&alisize); 293 break; 294 case EXC_DSI: 295 memcpy((void *)EXC_DSI, &dsitrap, (size_t)&dsisize); 296 break; 297 case EXC_ISI: 298 memcpy((void *)EXC_ISI, &isitrap, (size_t)&isisize); 299 break; 300 case EXC_DECR: 301 memcpy((void *)EXC_DECR, &decrint, (size_t)&decrsize); 302 break; 303 case EXC_IMISS: 304 memcpy((void *)EXC_IMISS, &tlbimiss, 305 (size_t)&tlbimsize); 306 break; 307 case EXC_DLMISS: 308 memcpy((void *)EXC_DLMISS, &tlbdlmiss, 309 (size_t)&tlbdlmsize); 310 break; 311 case EXC_DSMISS: 312 memcpy((void *)EXC_DSMISS, &tlbdsmiss, 313 (size_t)&tlbdsmsize); 314 break; 315 #if defined(DDB) || defined(IPKDB) 316 case EXC_PGM: 317 case EXC_TRC: 318 case EXC_BPT: 319 #if defined(DDB) 320 memcpy((void *)exc, &ddblow, (size_t)&ddbsize); 321 #else 322 memcpy((void *)exc, &ipkdblow, (size_t)&ipkdbsize); 323 #endif 324 break; 325 #endif /* DDB || IPKDB */ 326 } 327 328 __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); 329 330 /* 331 * external interrupt handler install 332 */ 333 install_extint(ext_intr); 334 335 /* 336 * Now enable translation (and machine checks/recoverable interrupts). 337 */ 338 asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync" 339 : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI)); 340 341 /* 342 * Set the page size. 343 */ 344 uvm_setpagesize(); 345 346 /* 347 * Initialize pmap module. 348 */ 349 pmap_bootstrap(startkernel, endkernel, NULL); 350 351 #ifdef DDB 352 ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 353 #endif 354 #ifdef IPKDB 355 /* 356 * Now trap to IPKDB 357 */ 358 ipkdb_init(); 359 if (boothowto & RB_KDB) 360 ipkdb_connect(0); 361 #endif 362 } 363 364 void 365 mem_regions(mem, avail) 366 struct mem_region **mem, **avail; 367 { 368 *mem = physmemr; 369 *avail = availmemr; 370 } 371 372 /* 373 * This should probably be in autoconf! XXX 374 */ 375 376 void 377 install_extint(handler) 378 void (*handler) __P((void)); 379 { 380 extern int extint, extsize; 381 extern u_long extint_call; 382 u_long offset = (u_long)handler - (u_long)&extint_call; 383 int omsr, msr; 384 385 #ifdef DIAGNOSTIC 386 if (offset > 0x1ffffff) 387 panic("install_extint: too far away"); 388 #endif 389 asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1" 390 : "=r"(omsr), "=r"(msr) : "K"((u_short)~PSL_EE)); 391 extint_call = (extint_call & 0xfc000003) | offset; 392 memcpy((void *)EXC_EXI, &extint, (size_t)&extsize); 393 __syncicache((void *)&extint_call, sizeof extint_call); 394 __syncicache((void *)EXC_EXI, (int)&extsize); 395 asm volatile ("mtmsr %0" :: "r"(omsr)); 396 } 397 398 /* 399 * Machine dependent startup code. 400 */ 401 void 402 cpu_startup() 403 { 404 int sz, i; 405 caddr_t v; 406 vaddr_t minaddr, maxaddr; 407 int base, residual; 408 char pbuf[9]; 409 410 proc0.p_addr = proc0paddr; 411 v = (caddr_t)proc0paddr + USPACE; 412 413 /* 414 * BeBox Mother Board's Register Mapping 415 */ 416 if (!(bebox_mb_reg = uvm_km_valloc(kernel_map, round_page(NBPG)))) 417 panic("initppc: no room for interrupt register"); 418 pmap_enter(pmap_kernel(), bebox_mb_reg, MOTHER_BOARD_REG, 419 VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 420 pmap_update(pmap_kernel()); 421 422 /* 423 * Initialize error message buffer (at end of core). 424 */ 425 if (!(msgbuf_vaddr = uvm_km_alloc(kernel_map, round_page(MSGBUFSIZE)))) 426 panic("startup: no room for message buffer"); 427 for (i = 0; i < btoc(MSGBUFSIZE); i++) 428 pmap_enter(pmap_kernel(), msgbuf_vaddr + i * NBPG, 429 msgbuf_paddr + i * NBPG, VM_PROT_READ|VM_PROT_WRITE, 430 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 431 pmap_update(pmap_kernel()); 432 initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE)); 433 434 printf("%s", version); 435 cpu_identify(NULL, 0); 436 437 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 438 printf("total memory = %s\n", pbuf); 439 440 /* 441 * Find out how much space we need, allocate it, 442 * and then give everything true virtual addresses. 443 */ 444 sz = (int)allocsys(NULL, NULL); 445 if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0) 446 panic("startup: no room for tables"); 447 if (allocsys(v, NULL) - v != sz) 448 panic("startup: table size inconsistency"); 449 450 /* 451 * Now allocate buffers proper. They are different than the above 452 * in that they usually occupy more virtual memory than physical. 453 */ 454 sz = MAXBSIZE * nbuf; 455 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(sz), 456 NULL, UVM_UNKNOWN_OFFSET, 0, 457 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 458 UVM_ADV_NORMAL, 0)) != 0) 459 panic("startup: cannot allocate VM for buffers"); 460 minaddr = (vaddr_t)buffers; 461 base = bufpages / nbuf; 462 residual = bufpages % nbuf; 463 if (base >= MAXBSIZE) { 464 /* Don't want to alloc more physical mem than ever needed */ 465 base = MAXBSIZE; 466 residual = 0; 467 } 468 for (i = 0; i < nbuf; i++) { 469 vsize_t curbufsize; 470 vaddr_t curbuf; 471 struct vm_page *pg; 472 473 /* 474 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 475 * that MAXBSIZE space, we allocate and map (base+1) pages 476 * for the first "residual" buffers, and then we allocate 477 * "base" pages for the rest. 478 */ 479 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 480 curbufsize = NBPG * ((i < residual) ? (base+1) : base); 481 482 while (curbufsize) { 483 pg = uvm_pagealloc(NULL, 0, NULL, 0); 484 if (pg == NULL) 485 panic("startup: not enough memory for " 486 "buffer cache"); 487 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 488 VM_PROT_READ | VM_PROT_WRITE); 489 curbuf += PAGE_SIZE; 490 curbufsize -= PAGE_SIZE; 491 } 492 } 493 pmap_update(kernel_map->pmap); 494 495 /* 496 * Allocate a submap for exec arguments. This map effectively 497 * limits the number of processes exec'ing at any time. 498 */ 499 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 500 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 501 502 /* 503 * Allocate a submap for physio 504 */ 505 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 506 VM_PHYS_SIZE, 0, FALSE, NULL); 507 508 #ifndef PMAP_MAP_POOLPAGE 509 /* 510 * No need to allocate an mbuf cluster submap. Mbuf clusters 511 * are allocated via the pool allocator, and we use direct-mapped 512 * pool pages. 513 */ 514 mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 515 mclbytes*nmbclusters, VM_MAP_INTRSAFE, FALSE, NULL); 516 #endif 517 518 /* 519 * Now that we have VM, malloc's are OK in bus_space. 520 */ 521 bebox_bus_space_mallocok(); 522 523 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 524 printf("avail memory = %s\n", pbuf); 525 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 526 printf("using %d buffers containing %s of memory\n", nbuf, pbuf); 527 528 /* 529 * Set up the buffers. 530 */ 531 bufinit(); 532 533 /* 534 * Now allow hardware interrupts. 535 */ 536 { 537 int msr; 538 539 splhigh(); 540 asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0" 541 : "=r"(msr) : "K"(PSL_EE)); 542 } 543 } 544 545 /* 546 * lookup_bootinfo: 547 * Look up information in bootinfo of boot loader. 548 */ 549 void * 550 lookup_bootinfo(type) 551 int type; 552 { 553 struct btinfo_common *bt; 554 struct btinfo_common *help = (struct btinfo_common *)bootinfo; 555 556 do { 557 bt = help; 558 if (bt->type == type) 559 return (help); 560 help = (struct btinfo_common *)((char*)help + bt->next); 561 } while (bt->next && 562 (size_t)help < (size_t)bootinfo + sizeof (bootinfo)); 563 564 return (NULL); 565 } 566 567 /* 568 * consinit 569 * Initialize system console. 570 */ 571 void 572 consinit() 573 { 574 struct btinfo_console *consinfo; 575 static int initted; 576 577 if (initted) 578 return; 579 initted = 1; 580 581 consinfo = (struct btinfo_console *)lookup_bootinfo(BTINFO_CONSOLE); 582 if (!consinfo) 583 panic("not found console information in bootinfo"); 584 585 #if (NPFB > 0) 586 if (!strcmp(consinfo->devname, "be")) { 587 pfb_cnattach(consinfo->addr); 588 #if (NPCKBC > 0) 589 pckbc_cnattach(&bebox_isa_io_bs_tag, IO_KBD, KBCMDP, 590 PCKBC_KBD_SLOT); 591 #endif 592 return; 593 } 594 #endif 595 596 #if (NPC > 0) || (NVGA > 0) 597 if (!strcmp(consinfo->devname, "vga")) { 598 #if (NVGA > 0) 599 if (!vga_cnattach(&bebox_io_bs_tag, &bebox_mem_bs_tag, 600 -1, 1)) 601 goto dokbd; 602 #endif 603 #if (NPC > 0) 604 pccnattach(); 605 #endif 606 dokbd: 607 #if (NPCKBC > 0) 608 pckbc_cnattach(&bebox_isa_io_bs_tag, IO_KBD, KBCMDP, 609 PCKBC_KBD_SLOT); 610 #endif 611 return; 612 } 613 #endif /* PC | VGA */ 614 615 #if (NCOM > 0) 616 if (!strcmp(consinfo->devname, "com")) { 617 bus_space_tag_t tag = &bebox_isa_io_bs_tag; 618 619 if(comcnattach(tag, consinfo->addr, consinfo->speed, COM_FREQ, 620 ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8))) 621 panic("can't init serial console"); 622 623 return; 624 } 625 #endif 626 panic("invalid console device %s", consinfo->devname); 627 } 628 629 #if (NPCKBC > 0) && (NPCKBD == 0) 630 /* 631 * glue code to support old console code with the 632 * mi keyboard controller driver 633 */ 634 int 635 pckbc_machdep_cnattach(kbctag, kbcslot) 636 pckbc_tag_t kbctag; 637 pckbc_slot_t kbcslot; 638 { 639 #if (NPC > 0) 640 return (pcconskbd_cnattach(kbctag, kbcslot)); 641 #else 642 return (ENXIO); 643 #endif 644 } 645 #endif 646 647 648 void 649 dumpsys() 650 { 651 printf("dumpsys: TBD\n"); 652 } 653 654 /* 655 * Soft networking interrupts. 656 */ 657 void 658 softnet(isr) 659 int isr; 660 { 661 #define DONETISR(bit, fn) do { \ 662 if (isr & (1 << bit)) \ 663 fn(); \ 664 } while (0) 665 666 #include <net/netisr_dispatch.h> 667 668 #undef DONETISR 669 } 670 671 /* 672 * Stray interrupts. 673 */ 674 void 675 strayintr(irq) 676 int irq; 677 { 678 log(LOG_ERR, "stray interrupt %d\n", irq); 679 } 680 681 /* 682 * Halt or reboot the machine after syncing/dumping according to howto. 683 */ 684 void 685 cpu_reboot(howto, what) 686 int howto; 687 char *what; 688 { 689 static int syncing; 690 static char str[256]; 691 char *ap = str, *ap1 = ap; 692 693 boothowto = howto; 694 if (!cold && !(howto & RB_NOSYNC) && !syncing) { 695 syncing = 1; 696 vfs_shutdown(); /* sync */ 697 resettodr(); /* set wall clock */ 698 } 699 splhigh(); 700 if (howto & RB_HALT) { 701 doshutdownhooks(); 702 printf("halted\n\n"); 703 #if 0 704 ppc_exit(); 705 #endif 706 } 707 if (!cold && (howto & RB_DUMP)) 708 dumpsys(); 709 doshutdownhooks(); 710 printf("rebooting\n\n"); 711 if (what && *what) { 712 if (strlen(what) > sizeof str - 5) 713 printf("boot string too large, ignored\n"); 714 else { 715 strcpy(str, what); 716 ap1 = ap = str + strlen(str); 717 *ap++ = ' '; 718 } 719 } 720 *ap++ = '-'; 721 if (howto & RB_SINGLE) 722 *ap++ = 's'; 723 if (howto & RB_KDB) 724 *ap++ = 'd'; 725 *ap++ = 0; 726 if (ap[-2] == '-') 727 *ap1 = 0; 728 #if 0 729 ppc_boot(str); 730 #endif 731 while (1); 732 } 733 734 void 735 lcsplx(ipl) 736 int ipl; 737 { 738 splx(ipl); 739 } 740 741 /* 742 * Allocate vm space and mapin the I/O address 743 */ 744 void * 745 mapiodev(pa, len) 746 paddr_t pa; 747 psize_t len; 748 { 749 paddr_t faddr; 750 vaddr_t taddr, va; 751 int off; 752 753 faddr = trunc_page(pa); 754 off = pa - faddr; 755 len = round_page(off + len); 756 va = taddr = uvm_km_valloc(kernel_map, len); 757 758 if (va == 0) 759 return NULL; 760 761 for (; len > 0; len -= NBPG) { 762 pmap_enter(pmap_kernel(), taddr, faddr, 763 VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED); 764 faddr += NBPG; 765 taddr += NBPG; 766 } 767 pmap_update(pmap_kernel()); 768 return (void *)(va + off); 769 } 770