1 /* $NetBSD: machdep.c,v 1.121 2002/09/25 22:21:12 thorpej 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_altivec.h" 39 #include "opt_multiprocessor.h" 40 #include "adb.h" 41 #include "zsc.h" 42 43 #include <sys/param.h> 44 #include <sys/buf.h> 45 #include <sys/exec.h> 46 #include <sys/malloc.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 #ifdef ALTIVEC 83 #include <powerpc/altivec.h> 84 #endif 85 86 #include <dev/cons.h> 87 #include <dev/ofw/openfirm.h> 88 89 #include <dev/wscons/wsksymvar.h> 90 #include <dev/wscons/wscons_callbacks.h> 91 92 #include <dev/usb/ukbdvar.h> 93 94 #include <macppc/dev/adbvar.h> 95 96 #if NZSC > 0 97 #include <machine/z8530var.h> 98 #endif 99 100 extern int ofmsr; 101 102 char bootpath[256]; 103 static int chosen; 104 struct pmap ofw_pmap; 105 int ofkbd_ihandle; 106 107 #ifdef DDB 108 void *startsym, *endsym; 109 #endif 110 111 struct ofw_translations { 112 vaddr_t va; 113 int len; 114 paddr_t pa; 115 int mode; 116 }; 117 118 int ofkbd_cngetc(dev_t); 119 void cninit_kd(void); 120 int lcsplx(int); 121 int save_ofmap(struct ofw_translations *, int); 122 void restore_ofmap(struct ofw_translations *, int); 123 static void dumpsys(void); 124 125 void 126 initppc(startkernel, endkernel, args) 127 u_int startkernel, endkernel; 128 char *args; 129 { 130 struct ofw_translations *ofmap; 131 int ofmaplen; 132 133 mpc6xx_batinit(0x80000000, BAT_BL_256M, 0xf0000000, BAT_BL_256M, 134 0x90000000, BAT_BL_256M, 0xa0000000, BAT_BL_256M, 135 0xb0000000, BAT_BL_256M, 0); 136 mpc6xx_init(ext_intr); 137 138 chosen = OF_finddevice("/chosen"); 139 140 ofmaplen = save_ofmap(NULL, 0); 141 ofmap = alloca(ofmaplen); 142 save_ofmap(ofmap, ofmaplen); 143 144 #ifdef __notyet__ /* Needs some rethinking regarding real/virtual OFW */ 145 OF_set_callback(callback); 146 #endif 147 148 ofmsr &= ~PSL_IP; 149 150 /* 151 * Parse arg string. 152 */ 153 #ifdef DDB 154 memcpy(&startsym, args + strlen(args) + 1, sizeof(startsym)); 155 memcpy(&endsym, args + strlen(args) + 5, sizeof(endsym)); 156 if (startsym == NULL || endsym == NULL) 157 startsym = endsym = NULL; 158 #endif 159 160 strcpy(bootpath, args); 161 args = bootpath; 162 while (*++args && *args != ' '); 163 if (*args) { 164 *args++ = 0; 165 while (*args) 166 BOOT_FLAG(*args++, boothowto); 167 } 168 169 /* 170 * i386 port says, that this shouldn't be here, 171 * but I really think the console should be initialized 172 * as early as possible. 173 */ 174 consinit(); 175 176 /* 177 * Set the page size. 178 */ 179 uvm_setpagesize(); 180 181 /* 182 * Initialize pmap module. 183 */ 184 pmap_bootstrap(startkernel, endkernel, NULL); 185 186 restore_ofmap(ofmap, ofmaplen); 187 } 188 189 int 190 save_ofmap(ofmap, maxlen) 191 struct ofw_translations *ofmap; 192 int maxlen; 193 { 194 int mmui, mmu, len; 195 196 OF_getprop(chosen, "mmu", &mmui, sizeof mmui); 197 mmu = OF_instance_to_package(mmui); 198 199 if (ofmap) { 200 memset(ofmap, 0, maxlen); /* to be safe */ 201 len = OF_getprop(mmu, "translations", ofmap, maxlen); 202 } else 203 len = OF_getproplen(mmu, "translations"); 204 205 return len; 206 } 207 208 void 209 restore_ofmap(ofmap, len) 210 struct ofw_translations *ofmap; 211 int len; 212 { 213 int n = len / sizeof(struct ofw_translations); 214 int i; 215 216 pmap_pinit(&ofw_pmap); 217 218 ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT; 219 #ifdef KERNEL2_SR 220 ofw_pmap.pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT; 221 #endif 222 223 for (i = 0; i < n; i++) { 224 paddr_t pa = ofmap[i].pa; 225 vaddr_t va = ofmap[i].va; 226 int len = ofmap[i].len; 227 228 if (va < 0xf0000000) /* XXX */ 229 continue; 230 231 while (len > 0) { 232 pmap_enter(&ofw_pmap, va, pa, VM_PROT_ALL, 233 VM_PROT_ALL|PMAP_WIRED); 234 pa += NBPG; 235 va += NBPG; 236 len -= NBPG; 237 } 238 } 239 pmap_update(&ofw_pmap); 240 } 241 242 /* 243 * Machine dependent startup code. 244 */ 245 void 246 cpu_startup() 247 { 248 mpc6xx_startup(NULL); 249 } 250 251 /* 252 * consinit 253 * Initialize system console. 254 */ 255 void 256 consinit() 257 { 258 static int initted; 259 260 if (initted) 261 return; 262 initted = 1; 263 cninit(); 264 265 #ifdef DDB 266 ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 267 if (boothowto & RB_KDB) 268 Debugger(); 269 #endif 270 271 #ifdef IPKDB 272 ipkdb_init(); 273 if (boothowto & RB_KDB) 274 ipkdb_connect(0); 275 #endif 276 277 #ifdef KGDB 278 #if NZSC > 0 279 zs_kgdb_init(); 280 #endif 281 if (boothowto & RB_KDB) 282 kgdb_connect(1); 283 #endif 284 } 285 286 /* 287 * Crash dump handling. 288 */ 289 290 void 291 dumpsys() 292 { 293 printf("dumpsys: TBD\n"); 294 } 295 296 #include "zsc.h" 297 #include "com.h" 298 /* 299 * Soft tty interrupts. 300 */ 301 void 302 softserial() 303 { 304 #if NZSC > 0 305 zssoft(NULL); 306 #endif 307 #if NCOM > 0 308 comsoft(); 309 #endif 310 } 311 312 #if 0 313 /* 314 * Stray interrupts. 315 */ 316 void 317 strayintr(irq) 318 int irq; 319 { 320 log(LOG_ERR, "stray interrupt %d\n", irq); 321 } 322 #endif 323 324 /* 325 * Halt or reboot the machine after syncing/dumping according to howto. 326 */ 327 void 328 cpu_reboot(howto, what) 329 int howto; 330 char *what; 331 { 332 static int syncing; 333 static char str[256]; 334 char *ap = str, *ap1 = ap; 335 336 boothowto = howto; 337 if (!cold && !(howto & RB_NOSYNC) && !syncing) { 338 syncing = 1; 339 vfs_shutdown(); /* sync */ 340 resettodr(); /* set wall clock */ 341 } 342 343 #ifdef MULTIPROCESSOR 344 /* Halt other CPU. XXX for now... */ 345 macppc_send_ipi(&cpu_info[1 - cpu_number()], MACPPC_IPI_HALT); 346 delay(100000); /* XXX */ 347 #endif 348 349 splhigh(); 350 351 if (!cold && (howto & RB_DUMP)) 352 dumpsys(); 353 354 doshutdownhooks(); 355 356 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 357 #if NADB > 0 358 delay(1000000); 359 adb_poweroff(); 360 printf("WARNING: powerdown failed!\n"); 361 #endif 362 } 363 364 if (howto & RB_HALT) { 365 printf("halted\n\n"); 366 367 /* flush cache for msgbuf */ 368 __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); 369 370 ppc_exit(); 371 } 372 373 printf("rebooting\n\n"); 374 if (what && *what) { 375 if (strlen(what) > sizeof str - 5) 376 printf("boot string too large, ignored\n"); 377 else { 378 strcpy(str, what); 379 ap1 = ap = str + strlen(str); 380 *ap++ = ' '; 381 } 382 } 383 *ap++ = '-'; 384 if (howto & RB_SINGLE) 385 *ap++ = 's'; 386 if (howto & RB_KDB) 387 *ap++ = 'd'; 388 *ap++ = 0; 389 if (ap[-2] == '-') 390 *ap1 = 0; 391 392 /* flush cache for msgbuf */ 393 __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); 394 395 #if NADB > 0 396 adb_restart(); /* not return */ 397 #endif 398 ppc_exit(); 399 } 400 401 #if 0 402 /* 403 * OpenFirmware callback routine 404 */ 405 void 406 callback(p) 407 void *p; 408 { 409 panic("callback"); /* for now XXX */ 410 } 411 #endif 412 413 int 414 lcsplx(ipl) 415 int ipl; 416 { 417 return spllower(ipl); /* XXX */ 418 } 419 420 #include "akbd.h" 421 #include "ukbd.h" 422 #include "ofb.h" 423 #include "ite.h" 424 #include "zstty.h" 425 426 void 427 cninit() 428 { 429 #if (NITE > 0 || NZSTTY > 0) 430 struct consdev *cp; 431 #endif /* (NITE > 0 || NZSTTY > 0) */ 432 int stdout, node; 433 char type[16]; 434 435 if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) 436 != sizeof(stdout)) 437 goto nocons; 438 439 node = OF_instance_to_package(stdout); 440 memset(type, 0, sizeof(type)); 441 if (OF_getprop(node, "device_type", type, sizeof(type)) == -1) 442 goto nocons; 443 444 #if NOFB > 0 445 if (strcmp(type, "display") == 0) { 446 cninit_kd(); 447 return; 448 } 449 #endif /* NOFB > 0 */ 450 451 #if NITE > 0 452 if (strcmp(type, "display") == 0) { 453 extern struct consdev consdev_ite; 454 455 cp = &consdev_ite; 456 (*cp->cn_probe)(cp); 457 (*cp->cn_init)(cp); 458 cn_tab = cp; 459 460 return; 461 } 462 #endif 463 464 #if NZSTTY > 0 465 if (strcmp(type, "serial") == 0) { 466 extern struct consdev consdev_zs; 467 468 cp = &consdev_zs; 469 (*cp->cn_probe)(cp); 470 (*cp->cn_init)(cp); 471 cn_tab = cp; 472 473 return; 474 } 475 #endif 476 477 nocons: 478 return; 479 } 480 481 #if NOFB > 0 482 struct usb_kbd_ihandles { 483 struct usb_kbd_ihandles *next; 484 int ihandle; 485 }; 486 487 void 488 cninit_kd() 489 { 490 int stdin, node; 491 char name[16]; 492 #if NAKBD > 0 493 int akbd; 494 #endif 495 #if NUKBD > 0 496 struct usb_kbd_ihandles *ukbds; 497 int ukbd; 498 #endif 499 500 /* 501 * Attach the console output now (so we can see debugging messages, 502 * if any). 503 */ 504 ofb_cnattach(); 505 506 /* 507 * We must determine which keyboard type we have. 508 */ 509 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) 510 != sizeof(stdin)) { 511 printf("WARNING: no `stdin' property in /chosen\n"); 512 return; 513 } 514 515 node = OF_instance_to_package(stdin); 516 memset(name, 0, sizeof(name)); 517 OF_getprop(node, "name", name, sizeof(name)); 518 if (strcmp(name, "keyboard") != 0) { 519 printf("WARNING: stdin is not a keyboard: %s\n", name); 520 return; 521 } 522 523 #if NAKBD > 0 524 memset(name, 0, sizeof(name)); 525 OF_getprop(OF_parent(node), "name", name, sizeof(name)); 526 if (strcmp(name, "adb") == 0) { 527 printf("console keyboard type: ADB\n"); 528 akbd_cnattach(); 529 goto kbd_found; 530 } 531 #endif 532 533 /* 534 * We're not an ADB keyboard; must be USB. Unfortunately, 535 * we have a few problems: 536 * 537 * (1) The stupid Macintosh firmware uses a 538 * `psuedo-hid' (yes, they even spell it 539 * incorrectly!) which apparently merges 540 * all USB keyboard input into a single 541 * input stream. Because of this, we can't 542 * actually determine which USB controller 543 * or keyboard is really the console keyboard! 544 * 545 * (2) Even if we could, USB requires a lot of 546 * the kernel to be running in order for it 547 * to work. 548 * 549 * So, what we do is this: 550 * 551 * (1) Tell the ukbd driver that it is the console. 552 * At autoconfiguration time, it will attach the 553 * first USB keyboard instance as the console 554 * keyboard. 555 * 556 * (2) Until then, so that we have _something_, we 557 * use the OpenFirmware I/O facilities to read 558 * the keyboard. 559 */ 560 561 /* 562 * stdin is /psuedo-hid/keyboard. Test `adb-kbd-ihandle and 563 * `usb-kbd-ihandles to figure out the real keyboard(s). 564 * 565 * XXX This must be called before pmap_bootstrap(). 566 */ 567 568 #if NUKBD > 0 569 if (OF_call_method("`usb-kbd-ihandles", stdin, 0, 1, &ukbds) >= 0 && 570 ukbds != NULL && ukbds->ihandle != 0 && 571 OF_instance_to_package(ukbds->ihandle) != -1) { 572 printf("console keyboard type: USB\n"); 573 ukbd_cnattach(); 574 goto kbd_found; 575 } 576 /* Try old method name. */ 577 if (OF_call_method("`usb-kbd-ihandle", stdin, 0, 1, &ukbd) >= 0 && 578 ukbd != 0 && 579 OF_instance_to_package(ukbd) != -1) { 580 printf("console keyboard type: USB\n"); 581 stdin = ukbd; 582 ukbd_cnattach(); 583 goto kbd_found; 584 } 585 #endif 586 587 #if NAKBD > 0 588 if (OF_call_method("`adb-kbd-ihandle", stdin, 0, 1, &akbd) >= 0 && 589 akbd != 0 && 590 OF_instance_to_package(akbd) != -1) { 591 printf("console keyboard type: ADB\n"); 592 stdin = akbd; 593 akbd_cnattach(); 594 goto kbd_found; 595 } 596 #endif 597 598 #if NUKBD > 0 599 /* 600 * XXX Old firmware does not have `usb-kbd-ihandles method. Assume 601 * XXX USB keyboard anyway. 602 */ 603 printf("console keyboard type: USB\n"); 604 ukbd_cnattach(); 605 goto kbd_found; 606 #endif 607 608 /* 609 * No keyboard is found. Just return. 610 */ 611 printf("no console keyboard\n"); 612 return; 613 614 #if NAKBD + NUKBD > 0 615 kbd_found: 616 /* 617 * XXX This is a little gross, but we don't get to call 618 * XXX wskbd_cnattach() twice. 619 */ 620 ofkbd_ihandle = stdin; 621 wsdisplay_set_cons_kbd(ofkbd_cngetc, NULL, NULL); 622 #endif 623 } 624 #endif 625 626 /* 627 * Bootstrap console keyboard routines, using OpenFirmware I/O. 628 */ 629 int 630 ofkbd_cngetc(dev) 631 dev_t dev; 632 { 633 u_char c = '\0'; 634 int len; 635 636 do { 637 len = OF_read(ofkbd_ihandle, &c, 1); 638 } while (len != 1); 639 640 return c; 641 } 642 643 #ifdef MULTIPROCESSOR 644 /* 645 * Save a process's FPU state to its PCB. The state is in another CPU 646 * (though by the time our IPI is processed, it may have been flushed already). 647 */ 648 void 649 mp_save_fpu_proc(p) 650 struct proc *p; 651 { 652 struct pcb *pcb = &p->p_addr->u_pcb; 653 struct cpu_info *fpcpu; 654 int i; 655 656 /* 657 * Send an IPI to the other CPU with the data and wait for that CPU 658 * to flush the data. Note that the other CPU might have switched 659 * to a different proc's FPU state by the time it receives the IPI, 660 * but that will only result in an unnecessary reload. 661 */ 662 663 fpcpu = pcb->pcb_fpcpu; 664 if (fpcpu == NULL) { 665 return; 666 } 667 macppc_send_ipi(fpcpu, MACPPC_IPI_FLUSH_FPU); 668 669 /* Wait for flush. */ 670 #if 0 671 while (pcb->pcb_fpcpu) 672 ; 673 #else 674 for (i = 0; i < 0x3fffffff; i++) { 675 if (pcb->pcb_fpcpu == NULL) 676 return; 677 } 678 printf("mp_save_fpu_proc{%d} pid = %d, fpcpu->ci_cpuid = %d\n", 679 cpu_number(), p->p_pid, fpcpu->ci_cpuid); 680 panic("mp_save_fpu_proc"); 681 #endif 682 } 683 684 #ifdef ALTIVEC 685 /* 686 * Save a process's AltiVEC state to its PCB. The state may be in any CPU. 687 * The process must either be curproc or traced by curproc (and stopped). 688 * (The point being that the process must not run on another CPU during 689 * this function). 690 */ 691 void 692 mp_save_vec_proc(p) 693 struct proc *p; 694 { 695 struct pcb *pcb = &p->p_addr->u_pcb; 696 struct cpu_info *veccpu; 697 int i; 698 699 /* 700 * Send an IPI to the other CPU with the data and wait for that CPU 701 * to flush the data. Note that the other CPU might have switched 702 * to a different proc's AltiVEC state by the time it receives the IPI, 703 * but that will only result in an unnecessary reload. 704 */ 705 706 veccpu = pcb->pcb_veccpu; 707 if (veccpu == NULL) { 708 return; 709 } 710 macppc_send_ipi(veccpu, MACPPC_IPI_FLUSH_VEC); 711 712 /* Wait for flush. */ 713 #if 0 714 while (pcb->pcb_veccpu) 715 ; 716 #else 717 for (i = 0; i < 0x3fffffff; i++) { 718 if (pcb->pcb_veccpu == NULL) 719 return; 720 } 721 printf("mp_save_vec_proc{%d} pid = %d, veccpu->ci_cpuid = %d\n", 722 cpu_number(), p->p_pid, veccpu->ci_cpuid); 723 panic("mp_save_vec_proc"); 724 #endif 725 } 726 #endif /* ALTIVEC */ 727 #endif /* MULTIPROCESSOR */ 728