1 /* $NetBSD: machdep.c,v 1.113 2002/05/13 06:05:33 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_kgdb.h" 37 #include "opt_ipkdb.h" 38 #include "opt_multiprocessor.h" 39 #include "adb.h" 40 #include "zsc.h" 41 42 #include <sys/param.h> 43 #include <sys/buf.h> 44 #include <sys/exec.h> 45 #include <sys/malloc.h> 46 #include <sys/map.h> 47 #include <sys/mbuf.h> 48 #include <sys/mount.h> 49 #include <sys/msgbuf.h> 50 #include <sys/proc.h> 51 #include <sys/reboot.h> 52 #include <sys/syscallargs.h> 53 #include <sys/syslog.h> 54 #include <sys/systm.h> 55 #include <sys/kernel.h> 56 #include <sys/user.h> 57 #include <sys/boot_flag.h> 58 59 #include <uvm/uvm_extern.h> 60 61 #include <net/netisr.h> 62 63 #ifdef DDB 64 #include <machine/db_machdep.h> 65 #include <ddb/db_extern.h> 66 #endif 67 68 #ifdef KGDB 69 #include <sys/kgdb.h> 70 #endif 71 72 #ifdef IPKDB 73 #include <ipkdb/ipkdb.h> 74 #endif 75 76 #include <machine/autoconf.h> 77 #include <machine/bat.h> 78 #include <machine/powerpc.h> 79 #include <machine/trap.h> 80 #include <machine/bus.h> 81 #include <machine/fpu.h> 82 83 #include <dev/cons.h> 84 #include <dev/ofw/openfirm.h> 85 86 #include <dev/wscons/wsksymvar.h> 87 #include <dev/wscons/wscons_callbacks.h> 88 89 #include <dev/usb/ukbdvar.h> 90 91 #include <macppc/dev/adbvar.h> 92 93 #if NZSC > 0 94 #include <machine/z8530var.h> 95 #endif 96 97 struct vm_map *exec_map = NULL; 98 struct vm_map *mb_map = NULL; 99 struct vm_map *phys_map = NULL; 100 101 /* 102 * Global variables used here and there 103 */ 104 #ifndef MULTIPROCESSOR 105 struct pcb *curpcb; 106 struct pmap *curpm; 107 struct proc *fpuproc; 108 #endif 109 110 extern struct user *proc0paddr; 111 extern int ofmsr; 112 113 struct bat battable[16]; 114 char bootpath[256]; 115 paddr_t msgbuf_paddr; 116 static int chosen; 117 struct pmap ofw_pmap; 118 int ofkbd_ihandle; 119 120 #ifdef DDB 121 void *startsym, *endsym; 122 #endif 123 124 struct ofw_translations { 125 vaddr_t va; 126 int len; 127 paddr_t pa; 128 int mode; 129 }; 130 131 int ofkbd_cngetc(dev_t); 132 void cninit_kd(void); 133 int lcsplx(int); 134 int save_ofmap(struct ofw_translations *, int); 135 void restore_ofmap(struct ofw_translations *, int); 136 static void dumpsys(void); 137 138 void 139 initppc(startkernel, endkernel, args) 140 u_int startkernel, endkernel; 141 char *args; 142 { 143 extern int trapcode, trapsize; 144 extern int alitrap, alisize; 145 extern int dsitrap, dsisize; 146 extern int isitrap, isisize; 147 extern int decrint, decrsize; 148 extern int tlbimiss, tlbimsize; 149 extern int tlbdlmiss, tlbdlmsize; 150 extern int tlbdsmiss, tlbdsmsize; 151 #if defined(DDB) || defined(KGDB) 152 extern int ddblow, ddbsize; 153 #endif 154 #ifdef IPKDB 155 extern int ipkdblow, ipkdbsize; 156 #endif 157 int exc, scratch; 158 struct mem_region *allmem, *availmem, *mp; 159 struct ofw_translations *ofmap; 160 int ofmaplen; 161 #ifdef MULTIPROCESSOR 162 struct cpu_info *ci = &cpu_info[0]; 163 #else 164 struct cpu_info *ci = &cpu_info_store; 165 #endif 166 167 asm volatile ("mtsprg 0,%0" :: "r"(ci)); 168 169 /* 170 * Initialize BAT registers to unmapped to not generate 171 * overlapping mappings below. 172 */ 173 asm volatile ("mtibatu 0,%0" :: "r"(0)); 174 asm volatile ("mtibatu 1,%0" :: "r"(0)); 175 asm volatile ("mtibatu 2,%0" :: "r"(0)); 176 asm volatile ("mtibatu 3,%0" :: "r"(0)); 177 asm volatile ("mtdbatu 0,%0" :: "r"(0)); 178 asm volatile ("mtdbatu 1,%0" :: "r"(0)); 179 asm volatile ("mtdbatu 2,%0" :: "r"(0)); 180 asm volatile ("mtdbatu 3,%0" :: "r"(0)); 181 182 /* 183 * Set up BAT0 to only map the lowest 256 MB area 184 */ 185 battable[0x0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); 186 battable[0x0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); 187 188 /* 189 * Map PCI memory space. 190 */ 191 battable[0x8].batl = BATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW); 192 battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); 193 194 battable[0x9].batl = BATL(0x90000000, BAT_I|BAT_G, BAT_PP_RW); 195 battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs); 196 197 battable[0xa].batl = BATL(0xa0000000, BAT_I|BAT_G, BAT_PP_RW); 198 battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs); 199 200 battable[0xb].batl = BATL(0xb0000000, BAT_I|BAT_G, BAT_PP_RW); 201 battable[0xb].batu = BATU(0xb0000000, BAT_BL_256M, BAT_Vs); 202 203 /* 204 * Map obio devices. 205 */ 206 battable[0xf].batl = BATL(0xf0000000, BAT_I|BAT_G, BAT_PP_RW); 207 battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs); 208 209 /* 210 * Now setup fixed bat registers 211 * 212 * Note that we still run in real mode, and the BAT 213 * registers were cleared above. 214 */ 215 /* BAT0 used for initial 256 MB segment */ 216 asm volatile ("mtibatl 0,%0; mtibatu 0,%1;" 217 "mtdbatl 0,%0; mtdbatu 0,%1;" 218 :: "r"(battable[0].batl), "r"(battable[0].batu)); 219 /* BAT1 used for primary I/O 256 MB segment */ 220 asm volatile ("mtdbatl 1,%0; mtdbatu 1,%1;" 221 :: "r"(battable[8].batl), "r"(battable[8].batu)); 222 223 /* 224 * Set up battable to map all RAM regions. 225 * This is here because mem_regions() call needs bat0 set up. 226 */ 227 mem_regions(&allmem, &availmem); 228 for (mp = allmem; mp->size; mp++) { 229 paddr_t pa = mp->start & 0xf0000000; 230 paddr_t end = mp->start + mp->size; 231 232 do { 233 u_int n = pa >> 28; 234 235 battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW); 236 battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs); 237 pa += 0x10000000; 238 } while (pa < end); 239 } 240 241 chosen = OF_finddevice("/chosen"); 242 243 ofmaplen = save_ofmap(NULL, 0); 244 ofmap = alloca(ofmaplen); 245 save_ofmap(ofmap, ofmaplen); 246 247 proc0.p_cpu = ci; 248 proc0.p_addr = proc0paddr; 249 memset(proc0.p_addr, 0, sizeof *proc0.p_addr); 250 251 curpcb = &proc0paddr->u_pcb; 252 253 curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel(); 254 255 #ifdef __notyet__ /* Needs some rethinking regarding real/virtual OFW */ 256 OF_set_callback(callback); 257 #endif 258 259 /* 260 * Set up trap vectors 261 */ 262 for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) 263 switch (exc) { 264 default: 265 memcpy((void *)exc, &trapcode, (size_t)&trapsize); 266 break; 267 case EXC_EXI: 268 /* 269 * This one is (potentially) installed during autoconf 270 */ 271 break; 272 case EXC_ALI: 273 memcpy((void *)EXC_ALI, &alitrap, (size_t)&alisize); 274 break; 275 case EXC_DSI: 276 memcpy((void *)EXC_DSI, &dsitrap, (size_t)&dsisize); 277 break; 278 case EXC_ISI: 279 memcpy((void *)EXC_ISI, &isitrap, (size_t)&isisize); 280 break; 281 case EXC_DECR: 282 memcpy((void *)EXC_DECR, &decrint, (size_t)&decrsize); 283 break; 284 case EXC_IMISS: 285 memcpy((void *)EXC_IMISS, &tlbimiss, (size_t)&tlbimsize); 286 break; 287 case EXC_DLMISS: 288 memcpy((void *)EXC_DLMISS, &tlbdlmiss, (size_t)&tlbdlmsize); 289 break; 290 case EXC_DSMISS: 291 memcpy((void *)EXC_DSMISS, &tlbdsmiss, (size_t)&tlbdsmsize); 292 break; 293 #if defined(DDB) || defined(IPKDB) || defined(KGDB) 294 case EXC_PGM: 295 case EXC_TRC: 296 case EXC_BPT: 297 #if defined(DDB) || defined(KGDB) 298 memcpy((void *)exc, &ddblow, (size_t)&ddbsize); 299 #if defined(IPKDB) 300 #error "cannot enable IPKDB with DDB or KGDB" 301 #endif 302 #else 303 memcpy((void *)exc, &ipkdblow, (size_t)&ipkdbsize); 304 #endif 305 break; 306 #endif /* DDB || IPKDB || KGDB */ 307 } 308 309 /* 310 * external interrupt handler install 311 */ 312 install_extint(ext_intr); 313 314 __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); 315 316 /* 317 * Now enable translation (and machine checks/recoverable interrupts). 318 */ 319 asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync" 320 : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI)); 321 322 ofmsr &= ~PSL_IP; 323 324 /* 325 * Parse arg string. 326 */ 327 #ifdef DDB 328 memcpy(&startsym, args + strlen(args) + 1, sizeof(startsym)); 329 memcpy(&endsym, args + strlen(args) + 5, sizeof(endsym)); 330 if (startsym == NULL || endsym == NULL) 331 startsym = endsym = NULL; 332 #endif 333 334 strcpy(bootpath, args); 335 args = bootpath; 336 while (*++args && *args != ' '); 337 if (*args) { 338 *args++ = 0; 339 while (*args) 340 BOOT_FLAG(*args++, boothowto); 341 } 342 343 /* 344 * If the bootpath doesn't start with a / then it isn't 345 * an OFW path and probably is an alias, so look up the alias 346 * and regenerate the full bootpath so device_register will work. 347 */ 348 if (bootpath[0] != '/' && bootpath[0] != '\0') { 349 int aliases = OF_finddevice("/aliases"); 350 char tmpbuf[100]; 351 char aliasbuf[256]; 352 if (aliases != 0) { 353 char *cp1, *cp2, *cp; 354 char saved_ch = 0; 355 int len; 356 cp1 = strchr(bootpath, ':'); 357 cp2 = strchr(bootpath, ','); 358 cp = cp1; 359 if (cp1 == NULL || (cp2 != NULL && cp2 < cp1)) 360 cp = cp2; 361 tmpbuf[0] = '\0'; 362 if (cp != NULL) { 363 strcpy(tmpbuf, cp); 364 saved_ch = *cp; 365 *cp = '\0'; 366 } 367 len = OF_getprop(aliases, bootpath, aliasbuf, 368 sizeof(aliasbuf)); 369 if (len > 0) { 370 if (aliasbuf[len-1] == '\0') 371 len--; 372 memcpy(bootpath, aliasbuf, len); 373 strcpy(&bootpath[len], tmpbuf); 374 } else { 375 *cp = saved_ch; 376 } 377 } 378 } 379 380 /* 381 * i386 port says, that this shouldn't be here, 382 * but I really think the console should be initialized 383 * as early as possible. 384 */ 385 consinit(); 386 387 /* 388 * Set the page size. 389 */ 390 uvm_setpagesize(); 391 392 /* 393 * Initialize pmap module. 394 */ 395 pmap_bootstrap(startkernel, endkernel, NULL); 396 397 restore_ofmap(ofmap, ofmaplen); 398 } 399 400 int 401 save_ofmap(ofmap, maxlen) 402 struct ofw_translations *ofmap; 403 int maxlen; 404 { 405 int mmui, mmu, len; 406 407 OF_getprop(chosen, "mmu", &mmui, sizeof mmui); 408 mmu = OF_instance_to_package(mmui); 409 410 if (ofmap) { 411 memset(ofmap, 0, maxlen); /* to be safe */ 412 len = OF_getprop(mmu, "translations", ofmap, maxlen); 413 } else 414 len = OF_getproplen(mmu, "translations"); 415 416 return len; 417 } 418 419 void 420 restore_ofmap(ofmap, len) 421 struct ofw_translations *ofmap; 422 int len; 423 { 424 int n = len / sizeof(struct ofw_translations); 425 int i; 426 427 pmap_pinit(&ofw_pmap); 428 429 ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT; 430 431 for (i = 0; i < n; i++) { 432 paddr_t pa = ofmap[i].pa; 433 vaddr_t va = ofmap[i].va; 434 int len = ofmap[i].len; 435 436 if (va < 0xf0000000) /* XXX */ 437 continue; 438 439 while (len > 0) { 440 pmap_enter(&ofw_pmap, va, pa, VM_PROT_ALL, 441 VM_PROT_ALL|PMAP_WIRED); 442 pa += NBPG; 443 va += NBPG; 444 len -= NBPG; 445 } 446 } 447 pmap_update(&ofw_pmap); 448 } 449 450 /* 451 * This should probably be in autoconf! XXX 452 */ 453 char machine[] = MACHINE; /* from <machine/param.h> */ 454 char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ 455 456 void 457 install_extint(handler) 458 void (*handler) __P((void)); 459 { 460 extern int extint, extsize; 461 extern u_long extint_call; 462 u_long offset = (u_long)handler - (u_long)&extint_call; 463 int omsr, msr; 464 465 #ifdef DIAGNOSTIC 466 if (offset > 0x1ffffff) 467 panic("install_extint: too far away"); 468 #endif 469 asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1" 470 : "=r"(omsr), "=r"(msr) : "K"((u_short)~PSL_EE)); 471 extint_call = (extint_call & 0xfc000003) | offset; 472 memcpy((void *)EXC_EXI, &extint, (size_t)&extsize); 473 __syncicache((void *)&extint_call, sizeof extint_call); 474 __syncicache((void *)EXC_EXI, (int)&extsize); 475 asm volatile ("mtmsr %0" :: "r"(omsr)); 476 } 477 478 /* 479 * Machine dependent startup code. 480 */ 481 void 482 cpu_startup() 483 { 484 int sz, i; 485 caddr_t v; 486 vaddr_t minaddr, maxaddr; 487 int base, residual; 488 char pbuf[9]; 489 490 initmsgbuf((caddr_t)msgbuf_paddr, round_page(MSGBUFSIZE)); 491 492 proc0.p_addr = proc0paddr; 493 v = (caddr_t)proc0paddr + USPACE; 494 495 printf("%s", version); 496 cpu_identify(NULL, 0); 497 498 format_bytes(pbuf, sizeof(pbuf), ctob((u_int)physmem)); 499 printf("total memory = %s\n", pbuf); 500 501 /* 502 * Find out how much space we need, allocate it, 503 * and then give everything true virtual addresses. 504 */ 505 sz = (int)allocsys(NULL, NULL); 506 if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0) 507 panic("startup: no room for tables"); 508 if (allocsys(v, NULL) - v != sz) 509 panic("startup: table size inconsistency"); 510 511 /* 512 * Now allocate buffers proper. They are different than the above 513 * in that they usually occupy more virtual memory than physical. 514 */ 515 sz = MAXBSIZE * nbuf; 516 minaddr = 0; 517 if (uvm_map(kernel_map, (vaddr_t *)&minaddr, round_page(sz), 518 NULL, UVM_UNKNOWN_OFFSET, 0, 519 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 520 UVM_ADV_NORMAL, 0)) != 0) 521 panic("startup: cannot allocate VM for buffers"); 522 buffers = (char *)minaddr; 523 base = bufpages / nbuf; 524 residual = bufpages % nbuf; 525 if (base >= MAXBSIZE) { 526 /* Don't want to alloc more physical mem than ever needed */ 527 base = MAXBSIZE; 528 residual = 0; 529 } 530 for (i = 0; i < nbuf; i++) { 531 vsize_t curbufsize; 532 vaddr_t curbuf; 533 struct vm_page *pg; 534 535 curbuf = (vaddr_t)buffers + i * MAXBSIZE; 536 curbufsize = NBPG * (i < residual ? base + 1 : base); 537 538 while (curbufsize) { 539 pg = uvm_pagealloc(NULL, 0, NULL, 0); 540 if (pg == NULL) 541 panic("cpu_startup: not enough memory for " 542 "buffer cache"); 543 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 544 VM_PROT_READ|VM_PROT_WRITE); 545 curbuf += PAGE_SIZE; 546 curbufsize -= PAGE_SIZE; 547 } 548 } 549 pmap_update(pmap_kernel()); 550 551 /* 552 * Allocate a submap for exec arguments. This map effectively 553 * limits the number of processes exec'ing at any time. 554 */ 555 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 556 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 557 558 /* 559 * Allocate a submap for physio 560 */ 561 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 562 VM_PHYS_SIZE, 0, FALSE, NULL); 563 564 #ifndef PMAP_MAP_POOLPAGE 565 /* 566 * No need to allocate an mbuf cluster submap. Mbuf clusters 567 * are allocated via the pool allocator, and we use direct-mapped 568 * pool pages. 569 */ 570 mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 571 mclbytes*nmbclusters, VM_MAP_INTRSAFE, FALSE, NULL); 572 #endif 573 574 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 575 printf("avail memory = %s\n", pbuf); 576 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 577 printf("using %d buffers containing %s of memory\n", nbuf, pbuf); 578 579 /* 580 * Set up the buffers. 581 */ 582 bufinit(); 583 } 584 585 /* 586 * consinit 587 * Initialize system console. 588 */ 589 void 590 consinit() 591 { 592 static int initted; 593 594 if (initted) 595 return; 596 initted = 1; 597 cninit(); 598 599 #ifdef DDB 600 ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 601 if (boothowto & RB_KDB) 602 Debugger(); 603 #endif 604 605 #ifdef IPKDB 606 ipkdb_init(); 607 if (boothowto & RB_KDB) 608 ipkdb_connect(0); 609 #endif 610 611 #ifdef KGDB 612 #if NZSC > 0 613 zs_kgdb_init(); 614 #endif 615 if (boothowto & RB_KDB) 616 kgdb_connect(1); 617 #endif 618 } 619 620 /* 621 * Crash dump handling. 622 */ 623 624 void 625 dumpsys() 626 { 627 printf("dumpsys: TBD\n"); 628 } 629 630 /* 631 * Soft networking interrupts. 632 */ 633 void 634 softnet() 635 { 636 extern volatile int netisr; 637 int isr; 638 639 isr = netisr; 640 netisr = 0; 641 642 #define DONETISR(bit, fn) do { \ 643 if (isr & (1 << bit)) \ 644 fn(); \ 645 } while (0) 646 647 #include <net/netisr_dispatch.h> 648 649 #undef DONETISR 650 651 } 652 653 #include "zsc.h" 654 #include "com.h" 655 /* 656 * Soft tty interrupts. 657 */ 658 void 659 softserial() 660 { 661 #if NZSC > 0 662 zssoft(NULL); 663 #endif 664 #if NCOM > 0 665 comsoft(); 666 #endif 667 } 668 669 #if 0 670 /* 671 * Stray interrupts. 672 */ 673 void 674 strayintr(irq) 675 int irq; 676 { 677 log(LOG_ERR, "stray interrupt %d\n", irq); 678 } 679 #endif 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 700 #ifdef MULTIPROCESSOR 701 /* Halt other CPU. XXX for now... */ 702 macppc_send_ipi(&cpu_info[1 - cpu_number()], MACPPC_IPI_HALT); 703 delay(100000); /* XXX */ 704 #endif 705 706 splhigh(); 707 708 if (!cold && (howto & RB_DUMP)) 709 dumpsys(); 710 711 doshutdownhooks(); 712 713 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 714 #if NADB > 0 715 delay(1000000); 716 adb_poweroff(); 717 printf("WARNING: powerdown failed!\n"); 718 #endif 719 } 720 721 if (howto & RB_HALT) { 722 printf("halted\n\n"); 723 724 /* flush cache for msgbuf */ 725 __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); 726 727 ppc_exit(); 728 } 729 730 printf("rebooting\n\n"); 731 if (what && *what) { 732 if (strlen(what) > sizeof str - 5) 733 printf("boot string too large, ignored\n"); 734 else { 735 strcpy(str, what); 736 ap1 = ap = str + strlen(str); 737 *ap++ = ' '; 738 } 739 } 740 *ap++ = '-'; 741 if (howto & RB_SINGLE) 742 *ap++ = 's'; 743 if (howto & RB_KDB) 744 *ap++ = 'd'; 745 *ap++ = 0; 746 if (ap[-2] == '-') 747 *ap1 = 0; 748 749 /* flush cache for msgbuf */ 750 __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); 751 752 #if NADB > 0 753 adb_restart(); /* not return */ 754 #endif 755 ppc_exit(); 756 } 757 758 #if 0 759 /* 760 * OpenFirmware callback routine 761 */ 762 void 763 callback(p) 764 void *p; 765 { 766 panic("callback"); /* for now XXX */ 767 } 768 #endif 769 770 int 771 lcsplx(ipl) 772 int ipl; 773 { 774 return spllower(ipl); /* XXX */ 775 } 776 777 /* 778 * Convert kernel VA to physical address 779 */ 780 int 781 kvtop(addr) 782 caddr_t addr; 783 { 784 vaddr_t va; 785 paddr_t pa; 786 int off; 787 extern char end[]; 788 789 if (addr < end) 790 return (int)addr; 791 792 va = trunc_page((vaddr_t)addr); 793 off = (int)addr - va; 794 795 if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) { 796 /*printf("kvtop: zero page frame (va=0x%x)\n", addr);*/ 797 return (int)addr; 798 } 799 800 return((int)pa + off); 801 } 802 803 /* 804 * Allocate vm space and mapin the I/O address 805 */ 806 void * 807 mapiodev(pa, len) 808 paddr_t pa; 809 psize_t len; 810 { 811 paddr_t faddr; 812 vaddr_t taddr, va; 813 int off; 814 815 faddr = trunc_page(pa); 816 off = pa - faddr; 817 len = round_page(off + len); 818 va = taddr = uvm_km_valloc(kernel_map, len); 819 820 if (va == 0) 821 return NULL; 822 823 for (; len > 0; len -= NBPG) { 824 pmap_kenter_pa(taddr, faddr, VM_PROT_READ | VM_PROT_WRITE); 825 faddr += NBPG; 826 taddr += NBPG; 827 } 828 pmap_update(pmap_kernel()); 829 return (void *)(va + off); 830 } 831 832 #include "akbd.h" 833 #include "ukbd.h" 834 #include "ofb.h" 835 #include "ite.h" 836 #include "zstty.h" 837 838 void 839 cninit() 840 { 841 struct consdev *cp; 842 int stdout, node; 843 char type[16]; 844 845 if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) 846 != sizeof(stdout)) 847 goto nocons; 848 849 node = OF_instance_to_package(stdout); 850 memset(type, 0, sizeof(type)); 851 if (OF_getprop(node, "device_type", type, sizeof(type)) == -1) 852 goto nocons; 853 854 #if NOFB > 0 855 if (strcmp(type, "display") == 0) { 856 cninit_kd(); 857 return; 858 } 859 #endif /* NOFB > 0 */ 860 861 #if NITE > 0 862 if (strcmp(type, "display") == 0) { 863 extern struct consdev consdev_ite; 864 865 cp = &consdev_ite; 866 (*cp->cn_probe)(cp); 867 (*cp->cn_init)(cp); 868 cn_tab = cp; 869 870 return; 871 } 872 #endif 873 874 #if NZSTTY > 0 875 if (strcmp(type, "serial") == 0) { 876 extern struct consdev consdev_zs; 877 878 cp = &consdev_zs; 879 (*cp->cn_probe)(cp); 880 (*cp->cn_init)(cp); 881 cn_tab = cp; 882 883 return; 884 } 885 #endif 886 887 nocons: 888 return; 889 } 890 891 #if NOFB > 0 892 struct usb_kbd_ihandles { 893 struct usb_kbd_ihandles *next; 894 int ihandle; 895 }; 896 897 void 898 cninit_kd() 899 { 900 int stdin, node; 901 char name[16]; 902 #if NAKBD > 0 903 int akbd; 904 #endif 905 #if NUKBD > 0 906 struct usb_kbd_ihandles *ukbds; 907 int ukbd; 908 #endif 909 910 /* 911 * Attach the console output now (so we can see debugging messages, 912 * if any). 913 */ 914 ofb_cnattach(); 915 916 /* 917 * We must determine which keyboard type we have. 918 */ 919 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) 920 != sizeof(stdin)) { 921 printf("WARNING: no `stdin' property in /chosen\n"); 922 return; 923 } 924 925 node = OF_instance_to_package(stdin); 926 memset(name, 0, sizeof(name)); 927 OF_getprop(node, "name", name, sizeof(name)); 928 if (strcmp(name, "keyboard") != 0) { 929 printf("WARNING: stdin is not a keyboard: %s\n", name); 930 return; 931 } 932 933 #if NAKBD > 0 934 memset(name, 0, sizeof(name)); 935 OF_getprop(OF_parent(node), "name", name, sizeof(name)); 936 if (strcmp(name, "adb") == 0) { 937 printf("console keyboard type: ADB\n"); 938 akbd_cnattach(); 939 goto kbd_found; 940 } 941 #endif 942 943 /* 944 * We're not an ADB keyboard; must be USB. Unfortunately, 945 * we have a few problems: 946 * 947 * (1) The stupid Macintosh firmware uses a 948 * `psuedo-hid' (yes, they even spell it 949 * incorrectly!) which apparently merges 950 * all USB keyboard input into a single 951 * input stream. Because of this, we can't 952 * actually determine which USB controller 953 * or keyboard is really the console keyboard! 954 * 955 * (2) Even if we could, USB requires a lot of 956 * the kernel to be running in order for it 957 * to work. 958 * 959 * So, what we do is this: 960 * 961 * (1) Tell the ukbd driver that it is the console. 962 * At autoconfiguration time, it will attach the 963 * first USB keyboard instance as the console 964 * keyboard. 965 * 966 * (2) Until then, so that we have _something_, we 967 * use the OpenFirmware I/O facilities to read 968 * the keyboard. 969 */ 970 971 /* 972 * stdin is /psuedo-hid/keyboard. Test `adb-kbd-ihandle and 973 * `usb-kbd-ihandles to figure out the real keyboard(s). 974 * 975 * XXX This must be called before pmap_bootstrap(). 976 */ 977 978 #if NUKBD > 0 979 if (OF_call_method("`usb-kbd-ihandles", stdin, 0, 1, &ukbds) != -1 && 980 ukbds != NULL && ukbds->ihandle != 0 && 981 OF_instance_to_package(ukbds->ihandle) != -1) { 982 printf("console keyboard type: USB\n"); 983 ukbd_cnattach(); 984 goto kbd_found; 985 } 986 /* Try old method name. */ 987 if (OF_call_method("`usb-kbd-ihandle", stdin, 0, 1, &ukbd) != -1 && 988 ukbd != 0 && 989 OF_instance_to_package(ukbd) != -1) { 990 printf("console keyboard type: USB\n"); 991 stdin = ukbd; 992 ukbd_cnattach(); 993 goto kbd_found; 994 } 995 #endif 996 997 #if NAKBD > 0 998 if (OF_call_method("`adb-kbd-ihandle", stdin, 0, 1, &akbd) != -1 && 999 akbd != 0 && 1000 OF_instance_to_package(akbd) != -1) { 1001 printf("console keyboard type: ADB\n"); 1002 stdin = akbd; 1003 akbd_cnattach(); 1004 goto kbd_found; 1005 } 1006 #endif 1007 1008 #if NUKBD > 0 1009 /* 1010 * XXX Old firmware does not have `usb-kbd-ihandles method. Assume 1011 * XXX USB keyboard anyway. 1012 */ 1013 printf("console keyboard type: USB\n"); 1014 ukbd_cnattach(); 1015 goto kbd_found; 1016 #endif 1017 1018 /* 1019 * No keyboard is found. Just return. 1020 */ 1021 printf("no console keyboard\n"); 1022 return; 1023 1024 #if NAKBD + NUKBD > 0 1025 kbd_found: 1026 /* 1027 * XXX This is a little gross, but we don't get to call 1028 * XXX wskbd_cnattach() twice. 1029 */ 1030 ofkbd_ihandle = stdin; 1031 wsdisplay_set_cons_kbd(ofkbd_cngetc, NULL, NULL); 1032 #endif 1033 } 1034 #endif 1035 1036 /* 1037 * Bootstrap console keyboard routines, using OpenFirmware I/O. 1038 */ 1039 int 1040 ofkbd_cngetc(dev) 1041 dev_t dev; 1042 { 1043 u_char c = '\0'; 1044 int len; 1045 1046 do { 1047 len = OF_read(ofkbd_ihandle, &c, 1); 1048 } while (len != 1); 1049 1050 return c; 1051 } 1052 1053 #ifdef MULTIPROCESSOR 1054 void 1055 save_fpu_proc(p) 1056 struct proc *p; 1057 { 1058 volatile struct cpu_info *fpcpu; 1059 int i; 1060 extern volatile int IPI[]; /* XXX */ 1061 1062 fpcpu = p->p_addr->u_pcb.pcb_fpcpu; 1063 if (fpcpu == curcpu()) { 1064 save_fpu(p); 1065 return; 1066 } 1067 1068 #if 0 1069 printf("save_fpu_proc{%d} pid = %d, fpcpu->ci_cpuid = %d\n", 1070 cpu_number(), p->p_pid, fpcpu->ci_cpuid); 1071 #endif 1072 1073 macppc_send_ipi(fpcpu, MACPPC_IPI_FLUSH_FPU); 1074 1075 /* Wait for flush. */ 1076 #if 0 1077 while (fpcpu->ci_fpuproc); 1078 #else 1079 for (i = 0; i < 0x3fffffff; i++) { 1080 if (fpcpu->ci_fpuproc == NULL) 1081 goto done; 1082 } 1083 printf("save_fpu_proc{%d} pid = %d, fpcpu->ci_cpuid = %d\n", 1084 cpu_number(), p->p_pid, fpcpu->ci_cpuid); 1085 printf("IPI[0] = 0x%x, IPI[1] = 0x%x\n", IPI[0], IPI[1]); 1086 printf("cpl 0x%x 0x%x\n", cpu_info[0].ci_cpl, cpu_info[1].ci_cpl); 1087 printf("ipending 0x%x 0x%x\n", cpu_info[0].ci_ipending, cpu_info[1].ci_ipending); 1088 panic("save_fpu_proc"); 1089 done:; 1090 1091 #endif 1092 } 1093 #endif /* MULTIPROCESSOR */ 1094