1 /* $NetBSD: machdep.c,v 1.389 2026/06/13 15:28:09 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1990 The Regents of the University of California. 6 * 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. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 /*- 38 * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, 39 * Michael L. Finch, Bradley A. Grantham, and 40 * Lawrence A. Kesteloot 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by the Alice Group. 54 * 4. The names of the Alice Group or any of its members may not be used 55 * to endorse or promote products derived from this software without 56 * specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR 59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 61 * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT, 62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 67 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 68 * 69 */ 70 /* 71 * from: Utah $Hdr: machdep.c 1.63 91/04/24$ 72 * 73 * @(#)machdep.c 7.16 (Berkeley) 6/3/91 74 */ 75 76 #include <sys/cdefs.h> 77 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.389 2026/06/13 15:28:09 thorpej Exp $"); 78 79 #include "opt_adb.h" 80 #include "opt_copy_symtab.h" 81 #include "opt_ddb.h" 82 #include "opt_ddbparam.h" 83 #include "opt_kgdb.h" 84 #include "opt_mac68k.h" 85 #include "opt_modular.h" 86 87 #include "akbd.h" 88 #include "audio.h" 89 #include "genfb.h" 90 #include "macfb.h" 91 #include "zsc.h" 92 93 #include <sys/param.h> 94 #include <sys/systm.h> 95 #include <sys/buf.h> 96 #include <sys/conf.h> 97 #include <sys/core.h> 98 #include <sys/exec.h> 99 #include <sys/extent.h> 100 #include <sys/file.h> 101 #include <sys/kcore.h> 102 #include <sys/kernel.h> 103 #include <sys/malloc.h> 104 #include <sys/mbuf.h> 105 #include <sys/mount.h> 106 #include <sys/msgbuf.h> 107 #include <sys/pool.h> 108 #include <sys/proc.h> 109 #include <sys/queue.h> 110 #include <sys/reboot.h> 111 #include <sys/signalvar.h> 112 #include <sys/syscallargs.h> 113 #include <sys/vnode.h> 114 #include <sys/ksyms.h> 115 #include <sys/module.h> 116 #ifdef KGDB 117 #include <sys/kgdb.h> 118 #endif 119 #include <sys/exec_elf.h> 120 #include <sys/device.h> 121 #include <sys/cpu.h> 122 123 #include <m68k/cacheops.h> 124 #include <m68k/mmu_40.h> 125 126 #include <machine/db_machdep.h> 127 #include <ddb/db_sym.h> 128 #include <ddb/db_extern.h> 129 130 #include <machine/autoconf.h> 131 #include <machine/cpu.h> 132 #include <machine/reg.h> 133 #include <machine/pcb.h> 134 #include <machine/psl.h> 135 #include <machine/pte.h> 136 #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ 137 #include <machine/video.h> 138 139 #define MAXMEM 64*1024 /* XXX - from cmap.h */ 140 #include <uvm/uvm_extern.h> 141 142 #include <sys/sysctl.h> 143 144 #include <dev/cons.h> 145 #include <dev/mm.h> 146 147 #include <machine/iopreg.h> 148 #include <machine/psc.h> 149 #include <machine/viareg.h> 150 #include <mac68k/mac68k/macrom.h> 151 #include <mac68k/dev/adbvar.h> 152 #if NAKBD > 0 153 #include <mac68k/dev/akbdvar.h> 154 #endif 155 #if NMACFB > 0 156 #include <mac68k/dev/macfbvar.h> 157 #endif 158 #include <mac68k/dev/pm_direct.h> 159 #include <mac68k/dev/zs_cons.h> 160 161 #include "ksyms.h" 162 163 int symsize, end, *ssym, *esym; 164 165 struct mac68k_machine_S mac68k_machine; 166 167 volatile u_char *Via1Base, *Via2Base, *PSCBase = NULL; 168 u_long NuBusBase = NBBASE; 169 u_long IOBase; 170 171 vaddr_t SCSIBase; 172 173 /* These are used to map kernel space: */ 174 int numranges; 175 u_long low[8]; 176 u_long high[8]; 177 u_long last_page; /* PA of last physical page */ 178 vaddr_t newvideoaddr; 179 int vidlen; 180 181 extern paddr_t avail_start, avail_end; 182 183 extern int machineid; 184 185 /* These are used to map NuBus space: */ 186 #define NBMAXRANGES 16 187 int nbnumranges; /* = 0 == don't use the ranges */ 188 u_long nbphys[NBMAXRANGES]; /* Start physical addr of this range */ 189 u_long nblog[NBMAXRANGES]; /* Start logical addr of this range */ 190 long nblen[NBMAXRANGES]; /* Length of this range If the length is */ 191 /* negative, all phys addrs are the same. */ 192 193 /* Definitions for the variables defined in machine/video.h */ 194 struct mac68k_video mac68k_video; 195 196 /* Callback and cookie to run bell */ 197 int (*mac68k_bell_callback)(void *, int, int, int); 198 void * mac68k_bell_cookie; 199 200 int maxmem; /* max memory per process */ 201 202 /* 203 * Extent maps to manage all memory space, including I/O ranges. Allocate 204 * storage for 8 regions in each, initially. Later, iomem_malloc_safe 205 * will indicate that it's safe to use malloc() to dynamically allocate 206 * region descriptors. 207 * 208 * The extent maps are not static! Machine-dependent NuBus and on-board 209 * I/O routines need access to them for bus address space allocation. 210 */ 211 static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)]; 212 struct extent *iomem_ex; 213 int iomem_malloc_safe; 214 215 static u_long get_physical(u_int, u_long *); 216 217 void initcpu(void); 218 int cpu_dumpsize(void); 219 int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *); 220 void cpu_init_kcore_hdr(void); 221 222 void getenvvars(u_long, char *); 223 static long getenv(const char *); 224 225 /* functions called from locore.s */ 226 void dumpsys(void); 227 void machine_init(paddr_t); 228 void nmihand(struct frame); 229 230 /* 231 * Machine-dependent crash dump header info. 232 */ 233 cpu_kcore_hdr_t cpu_kcore_hdr; 234 235 /* 236 * XXX: For zs serial driver. We always initialize the base address 237 * to avoid a bunch of #ifdefs. 238 */ 239 volatile unsigned char *sccA = 0; 240 241 /* 242 * Early initialization, before main() is called. 243 */ 244 void 245 machine_init(paddr_t nextpa) 246 { 247 int i; 248 249 /* 250 * Tell the VM system about available physical memory. 251 * Notice that we don't need to worry about avail_end here 252 * since it's equal to high[numranges-1]. 253 */ 254 for (i = 0; i < numranges; i++) { 255 if (low[i] <= avail_start && avail_start < high[i]) 256 uvm_page_physload(atop(avail_start), atop(high[i]), 257 atop(avail_start), atop(high[i]), 258 VM_FREELIST_DEFAULT); 259 else 260 uvm_page_physload(atop(low[i]), atop(high[i]), 261 atop(low[i]), atop(high[i]), 262 VM_FREELIST_DEFAULT); 263 } 264 265 #ifdef __HAVE_NEW_PMAP_68K 266 /* 267 * We mapped the kernel text read/write in pmap_bootstrap1() to 268 * deal with the vectors and Mac ROM variable region. Go ahead 269 * and write-protect &start - &etext here. 270 */ 271 extern char start[], etext[]; 272 pmap_protect(pmap_kernel(), m68k_round_page((vaddr_t)start), 273 m68k_trunc_page((vaddr_t)etext), 274 UVM_PROT_READ | UVM_PROT_EXEC); 275 pmap_update(pmap_kernel()); 276 #endif /* __HAVE_NEW_PMAP_68K */ 277 278 /* 279 * Initialize the I/O mem extent map. 280 * Note: we don't have to check the return value since 281 * creation of a fixed extent map will never fail (since 282 * descriptor storage has already been allocated). 283 * 284 * N.B. The iomem extent manages _all_ physical addresses 285 * on the machine. When the amount of RAM is found, all 286 * extents of RAM are allocated from the map. 287 */ 288 iomem_ex = extent_create("iomem", 0x0, 0xffffffff, 289 (void *)iomem_ex_storage, sizeof(iomem_ex_storage), 290 EX_NOCOALESCE|EX_NOWAIT); 291 292 /* Initialize the interrupt handlers. */ 293 intr_init(); 294 295 /* Initialize the IOPs (if present) */ 296 iop_init(1); 297 298 /* 299 * Initialize error message buffer (at end of core). 300 * high[numranges-1] was decremented in pmap_bootstrap. 301 */ 302 for (i = 0; i < btoc(MSGBUFSIZE); i++) 303 pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * PAGE_SIZE, 304 high[numranges - 1] + i * PAGE_SIZE, 305 VM_PROT_READ|VM_PROT_WRITE, 306 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 307 initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 308 pmap_update(pmap_kernel()); 309 } 310 311 /* 312 * Console initialization: called early on from main, 313 * before vm init or startup. Do enough configuration 314 * to choose and initialize a console. 315 */ 316 void 317 consinit(void) 318 { 319 /* 320 * Generic console: sys/dev/cons.c 321 * Initializes either ite or ser as console. 322 * Can be called from locore.s and init_main.c. (Ugh.) 323 */ 324 static int init; /* = 0 */ 325 326 if (!init) { 327 cninit(); 328 init = 1; 329 } else { 330 #if NAKBD > 0 && (NMACFB + NGENFB) > 0 331 /* 332 * XXX This is an evil hack on top of an evil hack! 333 * 334 * With the graybar stuff, we've got a catch-22: we need 335 * to do at least some console setup really early on, even 336 * before we're running with the mappings we need. On 337 * the other hand, we're not nearly ready to do anything 338 * with wscons or the ADB driver at that point. 339 * 340 * To get around this, maccninit() ignores the first call 341 * it gets (from cninit(), if not on a serial console). 342 * Once we're here, we call maccninit() again, which sets 343 * up the console devices and does the appropriate wscons 344 * initialization. 345 */ 346 if (mac68k_machine.serial_console == 0) { 347 void maccninit(struct consdev *); 348 maccninit(NULL); 349 } 350 #endif 351 352 mac68k_calibrate_delay(); 353 354 #if NZSC > 0 && defined(KGDB) 355 zs_kgdb_init(); 356 #endif 357 #if NKSYMS || defined(DDB) || defined(MODULAR) 358 /* 359 * Initialize kernel debugger, if compiled in. 360 */ 361 362 ksyms_addsyms_elf(symsize, ssym, esym); 363 #endif 364 365 if (boothowto & RB_KDB) { 366 #ifdef KGDB 367 /* XXX - Ask on console for kgdb_dev? */ 368 /* Note: this will just return if kgdb_dev==NODEV */ 369 kgdb_connect(1); 370 #else /* KGDB */ 371 #ifdef DDB 372 /* Enter DDB. We don't have a monitor PROM. */ 373 Debugger(); 374 #endif /* DDB */ 375 #endif /* KGDB */ 376 } 377 } 378 } 379 380 #define CURRENTBOOTERVER 111 381 382 /* 383 * cpu_startup: allocate memory for variable-sized tables, make 384 * (most of) kernel text read-only, and other miscellaneous bits 385 */ 386 void 387 cpu_startup(void) 388 { 389 int vers; 390 int xdelay; 391 392 /* 393 * Initialize the kernel crash dump header. 394 */ 395 cpu_init_kcore_hdr(); 396 397 cpu_startup_common(); 398 399 vers = mac68k_machine.booter_version; 400 if (vers < CURRENTBOOTERVER) { 401 /* fix older booters with indices, not versions */ 402 if (vers < 100) 403 vers += 99; 404 405 printf("\nYou booted with booter version %d.%d.\n", 406 vers / 100, vers % 100); 407 printf("Booter version %d.%d is necessary to fully support\n", 408 CURRENTBOOTERVER / 100, CURRENTBOOTERVER % 100); 409 printf("this kernel.\n\n"); 410 for (xdelay = 0; xdelay < 1000000; xdelay++); 411 } 412 413 extern u_int delay_factor; 414 printf("cpu: delay factor %d\n", delay_factor); 415 416 /* 417 * Set up CPU-specific registers, cache, etc. 418 */ 419 initcpu(); 420 421 /* Safe for extent allocation to use malloc now. */ 422 iomem_malloc_safe = 1; 423 } 424 425 void 426 initcpu(void) 427 { 428 /* Invalidate supervisor mode data cache. */ 429 DCIS(); 430 } 431 432 void doboot(void) __attribute__((__noreturn__)); 433 434 struct pcb dumppcb; 435 436 void 437 machine_powerdown(void) 438 { 439 /* First try to power down under VIA control. */ 440 via_powerdown(); 441 442 #ifndef MRG_ADB 443 /* 444 * Shut down machines whose power functions are accessed 445 * via modified ADB calls. adb_poweroff() is available 446 * only when the MRG ADB is not being used. 447 */ 448 adb_poweroff(); 449 #endif 450 /* 451 * Try to shutdown via the power manager (PowerBooks mainly). 452 */ 453 pm_poweroff(); 454 } 455 456 void 457 machine_reboot(int howto, char *bootstr) 458 { 459 extern u_long last_page; 460 461 /* Map the last physical page VA = PA for doboot() */ 462 pmap_enter(pmap_kernel(), (vaddr_t)last_page, (vaddr_t)last_page, 463 VM_PROT_ALL, VM_PROT_ALL|PMAP_WIRED); 464 pmap_update(pmap_kernel()); 465 doboot(); 466 } 467 468 /* 469 * Initialize the kernel crash dump header. 470 */ 471 void 472 cpu_init_kcore_hdr(void) 473 { 474 phys_ram_seg_t *ram_segs = pmap_init_kcore_hdr(&cpu_kcore_hdr); 475 int i; 476 477 /* mac68k has multiple RAM segments on some models. */ 478 for (i = 0; i < numranges; i++) { 479 ram_segs[i].start = low[i]; 480 ram_segs[i].size = high[i] - low[i]; 481 } 482 } 483 484 /* 485 * Compute the size of the machine-dependent crash dump header. 486 * Returns size in disk blocks. 487 */ 488 489 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) 490 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) 491 492 int 493 cpu_dumpsize(void) 494 { 495 496 return btodb(MDHDRSIZE); 497 } 498 499 /* 500 * Called by dumpsys() to dump the machine-dependent header. 501 */ 502 int 503 cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop) 504 { 505 int buf[MDHDRSIZE / sizeof(int)]; 506 cpu_kcore_hdr_t *chdr; 507 kcore_seg_t *kseg; 508 int error; 509 510 kseg = (kcore_seg_t *)buf; 511 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / 512 sizeof(int)]; 513 514 /* Create the segment header. */ 515 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 516 kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t)); 517 518 memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t)); 519 error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf)); 520 *blknop += btodb(sizeof(buf)); 521 return (error); 522 } 523 524 /* 525 * These variables are needed by /sbin/savecore 526 */ 527 u_int32_t dumpmag = 0x8fca0101; /* magic number */ 528 int dumpsize = 0; /* pages */ 529 long dumplo = 0; /* blocks */ 530 531 /* 532 * This is called by main to set dumplo and dumpsize. 533 * Dumps always skip the first PAGE_SIZE of disk space in 534 * case there might be a disk label stored there. If there 535 * is extra space, put dump at the end to reduce the chance 536 * that swapping trashes it. 537 */ 538 void 539 cpu_dumpconf(void) 540 { 541 cpu_kcore_hdr_t *h = &cpu_kcore_hdr; 542 struct m68k_kcore_hdr *m = &h->un._m68k; 543 int chdrsize; /* size of dump header */ 544 int nblks; /* size of dump area */ 545 int i; 546 547 if (dumpdev == NODEV) 548 return; 549 550 nblks = bdev_size(dumpdev); 551 chdrsize = cpu_dumpsize(); 552 553 dumpsize = 0; 554 for (i = 0; i < M68K_NPHYS_RAM_SEGS && m->ram_segs[i].size; i++) 555 dumpsize += btoc(m->ram_segs[i].size); 556 557 /* 558 * Check to see if we will fit. Note we always skip the 559 * first PAGE_SIZE in case there is a disk label there. 560 */ 561 if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) { 562 dumpsize = 0; 563 dumplo = -1; 564 return; 565 } 566 567 /* 568 * Put dump at the end of the partition. 569 */ 570 dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize; 571 } 572 573 void 574 dumpsys(void) 575 { 576 cpu_kcore_hdr_t *h = &cpu_kcore_hdr; 577 struct m68k_kcore_hdr *m = &h->un._m68k; 578 const struct bdevsw *bdev; 579 daddr_t blkno; /* current block to write */ 580 /* dump routine */ 581 int (*dump)(dev_t, daddr_t, void *, size_t); 582 int pg; /* page being dumped */ 583 paddr_t maddr; /* PA being dumped */ 584 int seg; /* RAM segment being dumped */ 585 int error; /* error code from (*dump)() */ 586 587 /* XXX initialized here because of gcc lossage */ 588 seg = 0; 589 maddr = m->ram_segs[seg].start; 590 pg = 0; 591 592 /* Make sure dump device is valid. */ 593 if (dumpdev == NODEV) 594 return; 595 bdev = bdevsw_lookup(dumpdev); 596 if (bdev == NULL) 597 return; 598 if (dumpsize == 0) { 599 cpu_dumpconf(); 600 if (dumpsize == 0) 601 return; 602 } 603 if (dumplo <= 0) { 604 printf("\ndump to dev %u,%u not possible\n", 605 major(dumpdev), minor(dumpdev)); 606 return; 607 } 608 dump = bdev->d_dump; 609 blkno = dumplo; 610 611 printf("\ndumping to dev %u,%u offset %ld\n", 612 major(dumpdev), minor(dumpdev), dumplo); 613 614 printf("dump "); 615 616 /* Write the dump header. */ 617 error = cpu_dump(dump, &blkno); 618 if (error) 619 goto bad; 620 621 for (pg = 0; pg < dumpsize; pg++) { 622 #define NPGMB (1024*1024/PAGE_SIZE) 623 /* print out how many MBs we have dumped */ 624 if (pg && (pg % NPGMB) == 0) 625 printf("%d ", pg / NPGMB); 626 #undef NPGMB 627 while (maddr >= 628 (m->ram_segs[seg].start + m->ram_segs[seg].size)) { 629 if (++seg >= M68K_NPHYS_RAM_SEGS || 630 m->ram_segs[seg].size == 0) { 631 error = EINVAL; /* XXX ?? */ 632 goto bad; 633 } 634 maddr = m->ram_segs[seg].start; 635 } 636 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, 637 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 638 pmap_update(pmap_kernel()); 639 640 error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE); 641 bad: 642 switch (error) { 643 case 0: 644 maddr += PAGE_SIZE; 645 blkno += btodb(PAGE_SIZE); 646 break; 647 648 case ENXIO: 649 printf("device bad\n"); 650 return; 651 652 case EFAULT: 653 printf("device not ready\n"); 654 return; 655 656 case EINVAL: 657 printf("area improper\n"); 658 return; 659 660 case EIO: 661 printf("i/o error\n"); 662 return; 663 664 case EINTR: 665 printf("aborted from console\n"); 666 return; 667 668 default: 669 printf("error %d\n", error); 670 return; 671 } 672 } 673 printf("succeeded\n"); 674 } 675 676 /* 677 * Level 7 interrupts can be caused by the keyboard or parity errors. 678 */ 679 void nmihand(struct frame); 680 681 void 682 nmihand(struct frame frame) 683 { 684 static int nmihanddeep = 0; 685 686 if (nmihanddeep++) 687 return; 688 /* regdump((struct trapframe *)&frame, 128); 689 dumptrace(); */ 690 #ifdef DDB 691 printf("Panic switch: PC is 0x%x.\n", frame.f_pc); 692 Debugger(); 693 #endif 694 nmihanddeep = 0; 695 } 696 697 /* 698 * It should be possible to probe for the top of RAM, but Apple has 699 * memory structured so that in at least some cases, it's possible 700 * for RAM to be aliased across all memory--or for it to appear that 701 * there is more RAM than there really is. 702 */ 703 int get_top_of_ram(void); 704 705 int 706 get_top_of_ram(void) 707 { 708 return ((mac68k_machine.mach_memsize * (1024 * 1024)) - PAGE_SIZE); 709 } 710 711 /* 712 * machine dependent system variables. 713 */ 714 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 715 { 716 717 sysctl_createv(clog, 0, NULL, NULL, 718 CTLFLAG_PERMANENT, 719 CTLTYPE_NODE, "machdep", NULL, 720 NULL, 0, NULL, 0, 721 CTL_MACHDEP, CTL_EOL); 722 723 sysctl_createv(clog, 0, NULL, NULL, 724 CTLFLAG_PERMANENT, 725 CTLTYPE_STRUCT, "console_device", NULL, 726 sysctl_consdev, 0, NULL, sizeof(dev_t), 727 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 728 } 729 730 static char *envbuf = NULL; 731 732 /* 733 * getenvvars: Grab a few useful variables 734 */ 735 736 void 737 getenvvars(u_long flag, char *buf) 738 { 739 extern u_long bootdev; 740 extern u_long macos_boottime, MacOSROMBase; 741 extern long macos_gmtbias; 742 int root_scsi_id; 743 u_long root_ata_dev; 744 int i; 745 Elf_Ehdr *ehdr; 746 Elf_Shdr *shp; 747 vaddr_t minsym; 748 749 /* 750 * If flag & 0x80000000 == 0, then we're booting with the old booter 751 * and we should freak out. 752 */ 753 if ((flag & 0x80000000) == 0) { 754 /* Freak out; print something if that becomes available */ 755 } else 756 envbuf = buf; 757 758 /* These next two should give us mapped video & serial */ 759 /* We need these for pre-mapping graybars & echo, but probably */ 760 /* only on MacII or LC. -- XXX */ 761 /* mac68k_video.mv_kvaddr = getenv("MACOS_VIDEO"); */ 762 763 mac68k_video.mv_kvaddr = getenv("VIDEO_ADDR"); 764 mac68k_video.mv_stride = getenv("ROW_BYTES"); 765 mac68k_video.mv_depth = getenv("SCREEN_DEPTH"); 766 mac68k_video.mv_width = getenv("DIMENSIONS") & 0xffff; 767 mac68k_video.mv_height = (getenv("DIMENSIONS") >> 16) & 0xffff; 768 769 /* 770 * More misc stuff from booter. 771 */ 772 mac68k_machine.machineid = machineid = getenv("MACHINEID"); 773 mac68k_machine.mach_processor = getenv("PROCESSOR"); 774 #ifndef MAC68K_MEMSIZE 775 mac68k_machine.mach_memsize = getenv("MEMSIZE"); 776 #else 777 mac68k_machine.mach_memsize = MAC68K_MEMSIZE; 778 #endif 779 mac68k_machine.do_graybars = getenv("GRAYBARS"); 780 mac68k_machine.serial_boot_echo = getenv("SERIALECHO"); 781 mac68k_machine.serial_console = getenv("SERIALCONSOLE"); 782 783 mac68k_machine.modem_flags = getenv("SERIAL_MODEM_FLAGS"); 784 mac68k_machine.modem_cts_clk = getenv("SERIAL_MODEM_HSKICLK"); 785 mac68k_machine.modem_dcd_clk = getenv("SERIAL_MODEM_GPICLK"); 786 mac68k_machine.modem_d_speed = getenv("SERIAL_MODEM_DSPEED"); 787 mac68k_machine.print_flags = getenv("SERIAL_PRINT_FLAGS"); 788 mac68k_machine.print_cts_clk = getenv("SERIAL_PRINT_HSKICLK"); 789 mac68k_machine.print_dcd_clk = getenv("SERIAL_PRINT_GPICLK"); 790 mac68k_machine.print_d_speed = getenv("SERIAL_PRINT_DSPEED"); 791 mac68k_machine.booter_version = getenv("BOOTERVER"); 792 793 /* 794 * For now, we assume that the boot device is off the first controller. 795 * Booter versions 1.11.0 and later set a flag to tell us to construct 796 * bootdev using the SCSI ID passed in via the environment. 797 */ 798 root_scsi_id = getenv("ROOT_SCSI_ID"); 799 root_ata_dev = getenv("ROOT_ATA_DEV"); 800 if (((mac68k_machine.booter_version < CURRENTBOOTERVER) || 801 (flag & 0x40000)) && bootdev == 0) { 802 if (root_ata_dev) { 803 /* 804 * Consider only internal IDE drive. 805 * Buses(=channel) will be always 0. 806 * Because 68k Mac has only single channel. 807 */ 808 switch (root_ata_dev) { 809 default: /* fall through */ 810 case 0xffffffe0: /* buses,drive = 0,0 */ 811 case 0x20: /* buses,drive = 1,0 */ 812 case 0x21: /* buses,drive = 1,1 */ 813 bootdev = MAKEBOOTDEV(22, 0, 0, 0, 0); 814 break; 815 case 0xffffffe1: /* buses,drive = 0,1 */ 816 bootdev = MAKEBOOTDEV(22, 0, 0, 1, 0); 817 break; 818 } 819 } else { 820 bootdev = MAKEBOOTDEV(4, 0, 0, root_scsi_id, 0); 821 } 822 } 823 824 /* 825 * Booter 1.11.3 and later pass a BOOTHOWTO variable with the 826 * appropriate bits set. 827 */ 828 boothowto = getenv("BOOTHOWTO"); 829 if (boothowto == 0) 830 boothowto = getenv("SINGLE_USER"); 831 832 /* 833 * Get end of symbols for kernel debugging 834 */ 835 esym = (int *)getenv("END_SYM"); 836 #ifndef makeoptions_COPY_SYMTAB 837 if (esym == (int *)0) 838 #endif 839 esym = (int *)&end; 840 841 /* Get MacOS time */ 842 macos_boottime = getenv("BOOTTIME"); 843 844 /* Save GMT BIAS saved in Booter parameters dialog box */ 845 macos_gmtbias = getenv("GMTBIAS"); 846 847 /* 848 * Save globals stolen from MacOS 849 */ 850 851 ROMBase = (void *)getenv("ROMBASE"); 852 if (ROMBase == (void *)0) { 853 ROMBase = (void *)ROMBASE; 854 } 855 MacOSROMBase = (unsigned long)ROMBase; 856 TimeDBRA = getenv("TIMEDBRA"); 857 ADBDelay = (u_short)getenv("ADBDELAY"); 858 HwCfgFlags = getenv("HWCFGFLAGS"); 859 HwCfgFlags2 = getenv("HWCFGFLAG2"); 860 HwCfgFlags3 = getenv("HWCFGFLAG3"); 861 ADBReInit_JTBL = getenv("ADBREINIT_JTBL"); 862 mrg_ADBIntrPtr = (void *)getenv("ADBINTERRUPT"); 863 864 /* 865 * Check the ELF headers. 866 */ 867 868 ehdr = (void *)getenv("MARK_SYM"); 869 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0 || 870 ehdr->e_ident[EI_CLASS] != ELFCLASS32) { 871 return; 872 } 873 874 /* 875 * Find the end of the symbols and strings. 876 */ 877 878 minsym = ~0; 879 shp = (Elf_Shdr *)(end + ehdr->e_shoff); 880 for (i = 0; i < ehdr->e_shnum; i++) { 881 if (shp[i].sh_type != SHT_SYMTAB && 882 shp[i].sh_type != SHT_STRTAB) { 883 continue; 884 } 885 minsym = MIN(minsym, (vaddr_t)end + shp[i].sh_offset); 886 } 887 888 symsize = 1; 889 ssym = (int *)ehdr; 890 } 891 892 static long 893 getenv(const char *str) 894 { 895 /* 896 * Returns the value of the environment variable "str". 897 * 898 * Format of the buffer is "var=val\0var=val\0...\0var=val\0\0". 899 * 900 * Returns 0 if the variable is not there, and 1 if the variable is 901 * there without an "=val". 902 */ 903 904 char *s; 905 const char *s1; 906 int val, base; 907 908 s = envbuf; 909 while (1) { 910 for (s1 = str; *s1 && *s && *s != '='; s1++, s++) { 911 if (toupper(*s1) != toupper(*s)) { 912 break; 913 } 914 } 915 if (*s1) { /* No match */ 916 while (*s) { 917 s++; 918 } 919 s++; 920 if (*s == '\0') { /* Not found */ 921 /* Boolean flags are false (0) if not there */ 922 return 0; 923 } 924 continue; 925 } 926 if (*s == '=') {/* Has a value */ 927 s++; 928 val = 0; 929 base = 10; 930 if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) { 931 base = 16; 932 s += 2; 933 } else 934 if (*s == '0') { 935 base = 8; 936 } 937 while (*s) { 938 if (toupper(*s) >= 'A' && toupper(*s) <= 'F') { 939 val = val * base + toupper(*s) - 'A' + 10; 940 } else { 941 val = val * base + (*s - '0'); 942 } 943 s++; 944 } 945 return val; 946 } else { /* TRUE (1) */ 947 return 1; 948 } 949 } 950 } 951 952 /* 953 * ROM Vector information for calling drivers in ROMs 954 * 955 * According to information published on the Web by Apple, there have 956 * been 9 different ROM families used in the Mac since the introduction 957 * of the Lisa/XL through the latest PowerMacs (May 96). Each family 958 * has zero or more version variants and in some cases a version variant 959 * may exist in one than one length format. Generally any one specific 960 * Mac will use a common set of routines within the ROM and a model-specific 961 * set also in the ROM. Luckily most of the routines used by NetBSD fall 962 * into the common set and can therefore be defined in the ROM Family. 963 * The offset addresses (address minus the ROM Base) of these common routines 964 * is the same for all machines which use that ROM. The offset addresses of 965 * the machine-specific routines is generally different for each machine. 966 * The machine-specific routines currently used by NetBSD/mac68k include: 967 * ADB_interrupt, PM_interrupt, ADBBase+130_interrupt, 968 * PMgrOp, jClkNoMem, Egret, InitEgret, and ADBReInit_JTBL 969 * 970 * It is possible that the routine at "jClkNoMem" is a common routine, but 971 * some variation in addresses has been seen. Also, execept for the very 972 * earliest machines which used Egret, the machine-specific value of the 973 * Egret routine may be unimportant as the machine-specific InitEgret code 974 * seems to always set the OS Trap vector for Egret. 975 * 976 * Only three of the nine different ROMs are important to NetBSD/mac68k. 977 * All other ROMs are used in early model Macs which are unable to run 978 * NetBSD due to other hardware limitations such as 68000 CPU, no MMU 979 * capability, or used only in PowerMacs. The three that we are interested 980 * in are: 981 * 982 * ROM Family $0178 - used in the II, IIx, IIcx, and SE/30 983 * All machines which use this ROM are now supported by NetBSD. 984 * There are no machine-dependent routines in these ROMs used by 985 * NetBSD/mac68k. This ROM is always 256K in length. 986 * 987 * ROM Family $067c - used in Classic, Color Classic, Color Classic II, 988 * IIci, IIsi, IIvi, IIvx, IIfx, LC, LC II, LC III, 989 * LC III+, LC475, LC520, LC550, LC575, LC580, LC630, 990 * MacTV, P200, P250, P275, P400/405/410/430, P450, 991 * P460/466/467, P475/476, P520, P550/560, P575/577/578, 992 * P580/588, P600, P630/631/635/636/637/638/640, Q605, 993 * Q610, C610, Q630, C650, Q650, Q700, Q800, Q900, Q950, 994 * PB140, PB145/145B, PB150, PB160, PB165, PB165c, PB170, 995 * PB180, PB180c, Duo 210, Duo 230, Duo 250, Duo 270c, 996 * Duo280, Duo 280c, PB 520/520c/540/540c/550 997 * This is the so-called "Universal" ROM used in almost all 68K 998 * machines. There are machine-dependent and machine-independent 999 * routines used by NetBSD/mac68k in this ROM, and except for the 1000 * PowerBooks and the Duos, this ROM seems to be fairly well 1001 * known by NetBSD/mac68k. Desktop machines listed here that are 1002 * not yet running NetBSD probably only lack the necessary 1003 * addresses for the machine-dependent routines, or are waiting 1004 * for IDE disk support. This ROM is generally 1Meg in length, 1005 * however when used in the IIci, IIfx, IIsi, LC, Classic II, and 1006 * P400/405/410/430 it is 512K in length, and when used in the 1007 * PB 520/520c/540/540c/550 it is 2Meg in length. 1008 * 1009 * ROM Family - $077d - used in C660AV/Q660AV, Q840AV 1010 * The "Universal" ROM used on the PowerMacs and used in the 1011 * 68K line for the AV Macs only. When used in the 68K AV 1012 * machines the ROM is 2Meg in length; all uses in the PowerMac 1013 * use a length of 4Meg. 1014 * 1015 * Bob Nestor - <rnestor (at) metronet.com> 1016 */ 1017 static romvec_t romvecs[] = 1018 { 1019 /* Vectors verified for II, IIx, IIcx, SE/30 */ 1020 { /* 0 */ 1021 "Mac II class ROMs", 1022 (void *)0x40807002, /* where does ADB interrupt */ 1023 (void *)0x0, /* PM interrupt (?) */ 1024 (void *)0x4080a4d8, /* ADBBase + 130 interrupt; whatzit? */ 1025 (void *)0x40807778, /* CountADBs */ 1026 (void *)0x40807792, /* GetIndADB */ 1027 (void *)0x408077be, /* GetADBInfo */ 1028 (void *)0x408077c4, /* SetADBInfo */ 1029 (void *)0x40807704, /* ADBReInit */ 1030 (void *)0x408072fa, /* ADBOp */ 1031 (void *)0x0, /* PMgrOp */ 1032 (void *)0x4080d6d0, /* WriteParam */ 1033 (void *)0x4080d6fa, /* SetDateTime */ 1034 (void *)0x4080dbe8, /* InitUtil */ 1035 (void *)0x4080dd78, /* ReadXPRam */ 1036 (void *)0x4080dd82, /* WriteXPRam */ 1037 (void *)0x4080ddd6, /* jClkNoMem */ 1038 (void *)0x0, /* ADBAlternateInit */ 1039 (void *)0x0, /* Egret */ 1040 (void *)0x0, /* InitEgret */ 1041 (void *)0x0, /* ADBReInit_JTBL */ 1042 (void *)0x0, /* ROMResourceMap List Head */ 1043 (void *)0x40814c58, /* FixDiv */ 1044 (void *)0x40814b64, /* FixMul */ 1045 }, 1046 /* 1047 * Vectors verified for PB 140, PB 145, PB 170 1048 * (PB 100?) 1049 */ 1050 { /* 1 */ 1051 "Powerbook class ROMs", 1052 (void *)0x4088ae5e, /* ADB interrupt */ 1053 (void *)0x408885ec, /* PB ADB interrupt */ 1054 (void *)0x4088ae0e, /* ADBBase + 130 interrupt; whatzit? */ 1055 (void *)0x4080a360, /* CountADBs */ 1056 (void *)0x4080a37a, /* GetIndADB */ 1057 (void *)0x4080a3a6, /* GetADBInfo */ 1058 (void *)0x4080a3ac, /* SetADBInfo */ 1059 (void *)0x4080a752, /* ADBReInit */ 1060 (void *)0x4080a3dc, /* ADBOp */ 1061 (void *)0x408888ec, /* PMgrOp */ 1062 (void *)0x4080c05c, /* WriteParam */ 1063 (void *)0x4080c086, /* SetDateTime */ 1064 (void *)0x4080c5cc, /* InitUtil */ 1065 (void *)0x4080b186, /* ReadXPRam */ 1066 (void *)0x4080b190, /* WriteXPRam */ 1067 (void *)0x4080b1e4, /* jClkNoMem */ 1068 (void *)0x4080a818, /* ADBAlternateInit */ 1069 (void *)0x40814800, /* Egret */ 1070 (void *)0x408147c4, /* InitEgret */ 1071 (void *)0x0, /* ADBReInit_JTBL */ 1072 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1073 (void *)0x4081c406, /* FixDiv */ 1074 (void *)0x4081c312, /* FixMul */ 1075 }, 1076 /* 1077 * Vectors verified for IIsi, IIvx, IIvi 1078 */ 1079 { /* 2 */ 1080 "Mac IIsi class ROMs", 1081 (void *)0x40814912, /* ADB interrupt */ 1082 (void *)0x0, /* PM ADB interrupt */ 1083 (void *)0x408150f0, /* ADBBase + 130 interrupt; whatzit? */ 1084 (void *)0x4080a360, /* CountADBs */ 1085 (void *)0x4080a37a, /* GetIndADB */ 1086 (void *)0x4080a3a6, /* GetADBInfo */ 1087 (void *)0x4080a3ac, /* SetADBInfo */ 1088 (void *)0x4080a752, /* ADBReInit */ 1089 (void *)0x4080a3dc, /* ADBOp */ 1090 (void *)0x0, /* PMgrOp */ 1091 (void *)0x4080c05c, /* WriteParam */ 1092 (void *)0x4080c086, /* SetDateTime */ 1093 (void *)0x4080c5cc, /* InitUtil */ 1094 (void *)0x4080b186, /* ReadXPRam */ 1095 (void *)0x4080b190, /* WriteXPRam */ 1096 (void *)0x4080b1e4, /* jClkNoMem */ 1097 (void *)0x4080a818, /* ADBAlternateInit */ 1098 (void *)0x40814800, /* Egret */ 1099 (void *)0x408147c4, /* InitEgret */ 1100 (void *)0x0, /* ADBReInit_JTBL */ 1101 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1102 (void *)0x4081c406, /* FixDiv */ 1103 (void *)0x4081c312, /* FixMul */ 1104 }, 1105 /* 1106 * Vectors verified for Mac Classic II and LC II 1107 * (Other LC's? 680x0 Performas?) 1108 */ 1109 { /* 3 */ 1110 "Mac Classic II ROMs", 1111 (void *)0x40a14912, /* ADB interrupt */ 1112 (void *)0x0, /* PM ADB interrupt */ 1113 (void *)0x40a150f0, /* ADBBase + 130 interrupt; whatzit? */ 1114 (void *)0x40a0a360, /* CountADBs */ 1115 (void *)0x40a0a37a, /* GetIndADB */ 1116 (void *)0x40a0a3a6, /* GetADBInfo */ 1117 (void *)0x40a0a3ac, /* SetADBInfo */ 1118 (void *)0x40a0a752, /* ADBReInit */ 1119 (void *)0x40a0a3dc, /* ADBOp */ 1120 (void *)0x0, /* PMgrOp */ 1121 (void *)0x40a0c05c, /* WriteParam */ 1122 (void *)0x40a0c086, /* SetDateTime */ 1123 (void *)0x40a0c5cc, /* InitUtil */ 1124 (void *)0x40a0b186, /* ReadXPRam */ 1125 (void *)0x40a0b190, /* WriteXPRam */ 1126 (void *)0x40a0b1e4, /* jClkNoMem */ 1127 (void *)0x40a0a818, /* ADBAlternateInit */ 1128 (void *)0x40a14800, /* Egret */ 1129 (void *)0x40a147c4, /* InitEgret */ 1130 (void *)0x40a03ba6, /* ADBReInit_JTBL */ 1131 (void *)0x40a7eb90, /* ROMResourceMap List Head */ 1132 (void *)0x40a1c406, /* FixDiv, wild guess */ 1133 (void *)0x40a1c312, /* FixMul, wild guess */ 1134 }, 1135 /* 1136 * Vectors verified for IIci, Q700 1137 */ 1138 { /* 4 */ 1139 "Mac IIci/Q700 ROMs", 1140 (void *)0x4080a700, /* ADB interrupt */ 1141 (void *)0x0, /* PM ADB interrupt */ 1142 (void *)0x4080a5aa, /* ADBBase + 130 interrupt; whatzit? */ 1143 (void *)0x4080a360, /* CountADBs */ 1144 (void *)0x4080a37a, /* GetIndADB */ 1145 (void *)0x4080a3a6, /* GetADBInfo */ 1146 (void *)0x4080a3ac, /* SetADBInfo */ 1147 (void *)0x4080a752, /* ADBReInit */ 1148 (void *)0x4080a3dc, /* ADBOp */ 1149 (void *)0x0, /* PMgrOp */ 1150 (void *)0x4080c05c, /* WriteParam */ 1151 (void *)0x4080c086, /* SetDateTime */ 1152 (void *)0x4080c5cc, /* InitUtil */ 1153 (void *)0x4080b186, /* ReadXPRam */ 1154 (void *)0x4080b190, /* WriteXPRam */ 1155 (void *)0x4080b1e4, /* jClkNoMem */ 1156 (void *)0x4080a818, /* ADBAlternateInit */ 1157 (void *)0x0, /* Egret */ 1158 (void *)0x408147c4, /* InitEgret */ 1159 (void *)0x0, /* ADBReInit_JTBL */ 1160 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1161 (void *)0x4081c406, /* FixDiv */ 1162 (void *)0x4081c312, /* FixMul */ 1163 }, 1164 /* 1165 * Vectors verified for Duo 230, PB 180, PB 160, PB 165/165C 1166 * (Duo 210? Duo 250? Duo 270?) 1167 */ 1168 { /* 5 */ 1169 "2nd Powerbook class ROMs", 1170 (void *)0x408b2eec, /* ADB interrupt */ 1171 (void *)0x408885ec, /* PB ADB interrupt */ 1172 (void *)0x408b2e76, /* ADBBase + 130 interrupt; whatzit? */ 1173 (void *)0x4080a360, /* CountADBs */ 1174 (void *)0x4080a37a, /* GetIndADB */ 1175 (void *)0x4080a3a6, /* GetADBInfo */ 1176 (void *)0x4080a3ac, /* SetADBInfo */ 1177 (void *)0x4080a752, /* ADBReInit */ 1178 (void *)0x4080a3dc, /* ADBOp */ 1179 (void *)0x408888ec, /* PMgrOp */ 1180 (void *)0x4080c05c, /* WriteParam */ 1181 (void *)0x4080c086, /* SetDateTime */ 1182 (void *)0x4080c5cc, /* InitUtil */ 1183 (void *)0x4080b186, /* ReadXPRam */ 1184 (void *)0x4080b190, /* WriteXPRam */ 1185 (void *)0x408b39b2, /* jClkNoMem */ /* From PB180 */ 1186 (void *)0x4080a818, /* ADBAlternateInit */ 1187 (void *)0x40814800, /* Egret */ 1188 (void *)0x40888400, /* InitPwrMgr */ /* From PB180 */ 1189 (void *)0x408cce28, /* ADBReInit_JTBL -- from PB160*/ 1190 (void *)0x4087eb90, /* ROMRsrcMap List Head -- from PB160*/ 1191 (void *)0x4081c406, /* FixDiv, wild guess */ 1192 (void *)0x4081c312, /* FixMul, wild guess */ 1193 }, 1194 /* 1195 * Vectors verified for the Quadra, Centris 650 1196 * (610, Q800?) 1197 */ 1198 { /* 6 */ 1199 "Quadra/Centris ROMs", 1200 (void *)0x408b2dea, /* ADB int */ 1201 (void *)0x0, /* PM intr */ 1202 (void *)0x408b2c72, /* ADBBase + 130 */ 1203 (void *)0x4080a360, /* CountADBs */ 1204 (void *)0x4080a37a, /* GetIndADB */ 1205 (void *)0x4080a3a6, /* GetADBInfo */ 1206 (void *)0x4080a3ac, /* SetADBInfo */ 1207 (void *)0x4080a752, /* ADBReInit */ 1208 (void *)0x4080a3dc, /* ADBOp */ 1209 (void *)0x40809ae6, /* PMgrOp */ 1210 (void *)0x4080c05c, /* WriteParam */ 1211 (void *)0x4080c086, /* SetDateTime */ 1212 (void *)0x4080c5cc, /* InitUtil */ 1213 (void *)0x4080b186, /* ReadXPRam */ 1214 (void *)0x4080b190, /* WriteXPRam */ 1215 (void *)0x408b39b6, /* jClkNoMem */ 1216 (void *)0x4080a818, /* ADBAlternateInit */ 1217 (void *)0x40814800, /* Egret */ 1218 (void *)0x408147c4, /* InitEgret */ 1219 (void *)0x408d2b64, /* ADBReInit_JTBL */ 1220 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1221 (void *)0x4081c406, /* FixDiv, wild guess */ 1222 (void *)0x4081c312, /* FixMul, wild guess */ 1223 }, 1224 /* 1225 * Vectors verified for the Quadra 660AV 1226 * (Quadra 840AV?) 1227 */ 1228 { /* 7 */ 1229 "Quadra AV ROMs", 1230 (void *)0x4080cac6, /* ADB int */ 1231 (void *)0x0, /* PM int */ 1232 (void *)0x40805cd4, /* ADBBase + 130 */ 1233 (void *)0x40839600, /* CountADBs */ 1234 (void *)0x4083961a, /* GetIndADB */ 1235 (void *)0x40839646, /* GetADBInfo */ 1236 (void *)0x4083964c, /* SetADBInfo */ 1237 (void *)0x408397b8, /* ADBReInit */ 1238 (void *)0x4083967c, /* ADBOp */ 1239 (void *)0x0, /* PMgrOp */ 1240 (void *)0x4081141c, /* WriteParam */ 1241 (void *)0x4081144e, /* SetDateTime */ 1242 (void *)0x40811930, /* InitUtil */ 1243 (void *)0x4080b624, /* ReadXPRam */ 1244 (void *)0x4080b62e, /* WriteXPRam */ 1245 (void *)0x40806884, /* jClkNoMem */ 1246 (void *)0x408398c2, /* ADBAlternateInit */ 1247 (void *)0x4080cada, /* Egret */ 1248 (void *)0x4080de14, /* InitEgret */ 1249 (void *)0x408143b8, /* ADBReInit_JTBL */ 1250 (void *)0x409bdb60, /* ROMResourceMap List Head */ 1251 (void *)0x4083b3d8, /* FixDiv */ 1252 (void *)0x4083b2e4, /* FixMul */ 1253 }, 1254 /* 1255 * PB 540, PB 550 1256 * (PB 520? Duo 280?) 1257 */ 1258 { /* 8 */ 1259 "68040 PowerBook ROMs", 1260 (void *)0x400b2efc, /* ADB int */ 1261 (void *)0x400d8e66, /* PM int */ 1262 (void *)0x400b2e86, /* ADBBase + 130 */ 1263 (void *)0x4000a360, /* CountADBs */ 1264 (void *)0x4000a37a, /* GetIndADB */ 1265 (void *)0x4000a3a6, /* GetADBInfo */ 1266 (void *)0x4000a3ac, /* SetADBInfo */ 1267 (void *)0x4000a752, /* ADBReInit */ 1268 (void *)0x4000a3dc, /* ADBOp */ 1269 (void *)0x400d9302, /* PmgrOp */ 1270 (void *)0x4000c05c, /* WriteParam */ 1271 (void *)0x4000c086, /* SetDateTime */ 1272 (void *)0x4000c5cc, /* InitUtil */ 1273 (void *)0x4000b186, /* ReadXPRam */ 1274 (void *)0x4000b190, /* WriteXPRam */ 1275 (void *)0x400b3c08, /* jClkNoMem */ 1276 (void *)0x4000a818, /* ADBAlternateInit */ 1277 (void *)0x40009ae6, /* Egret */ /* From PB520 */ 1278 (void *)0x400147c4, /* InitEgret */ 1279 (void *)0x400a7a5c, /* ADBReInit_JTBL */ 1280 (void *)0x4007eb90, /* ROMResourceMap List Head */ 1281 (void *)0x4001c406, /* FixDiv, wild guess */ 1282 (void *)0x4001c312, /* FixMul, wild guess */ 1283 }, 1284 /* 1285 * Verified for the Q605 1286 */ 1287 { /* 9 */ 1288 "Quadra/Centris 605 ROMs", 1289 (void *)0x408a9b56, /* ADB int */ 1290 (void *)0x0, /* PM int */ 1291 (void *)0x408b2f94, /* ADBBase + 130 */ 1292 (void *)0x4080a360, /* CountADBs */ 1293 (void *)0x4080a37a, /* GetIndADB */ 1294 (void *)0x4080a3a6, /* GetADBInfo */ 1295 (void *)0x4080a3ac, /* SetADBInfo */ 1296 (void *)0x4080a752, /* ADBReInit */ 1297 (void *)0x4080a3dc, /* ADBOp */ 1298 (void *)0x0, /* PmgrOp */ 1299 (void *)0x4080c05c, /* WriteParam */ 1300 (void *)0x4080c086, /* SetDateTime */ 1301 (void *)0x4080c5cc, /* InitUtil */ 1302 (void *)0x4080b186, /* ReadXPRam */ 1303 (void *)0x4080b190, /* WriteXPRam */ 1304 (void *)0x408b3bf8, /* jClkNoMem */ 1305 (void *)0x4080a818, /* ADBAlternateInit */ 1306 (void *)0x408a99c0, /* Egret */ 1307 (void *)0x408147c4, /* InitEgret */ 1308 (void *)0x408a82c0, /* ADBReInit_JTBL */ 1309 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1310 (void *)0x4081c406, /* FixDiv */ 1311 (void *)0x4081c312, /* FixMul */ 1312 }, 1313 /* 1314 * Vectors verified for Duo 270c, PB150 1315 */ 1316 { /* 10 */ 1317 "Duo 270C ROMs", 1318 (void *)0x408b2efc, /* ADB interrupt */ 1319 (void *)0x408885ec, /* PB ADB interrupt */ 1320 (void *)0x408b2e86, /* ADBBase + 130 interrupt; whatzit? */ 1321 (void *)0x4080a360, /* CountADBs */ 1322 (void *)0x4080a37a, /* GetIndADB */ 1323 (void *)0x4080a3a6, /* GetADBInfo */ 1324 (void *)0x4080a3ac, /* SetADBInfo */ 1325 (void *)0x4080a752, /* ADBReInit */ 1326 (void *)0x4080a3dc, /* ADBOp */ 1327 (void *)0x408888ec, /* PMgrOp */ 1328 (void *)0x4080c05c, /* WriteParam */ 1329 (void *)0x4080c086, /* SetDateTime */ 1330 (void *)0x4080c5cc, /* InitUtil */ 1331 (void *)0x4080b186, /* ReadXPRam */ 1332 (void *)0x4080b190, /* WriteXPRam */ 1333 (void *)0x408b3bf8, /* jClkNoMem */ /* from PB 150 */ 1334 (void *)0x4080a818, /* ADBAlternateInit */ 1335 (void *)0x40814800, /* Egret */ 1336 (void *)0x408147c4, /* InitEgret */ 1337 (void *)0x0, /* ADBReInit_JTBL */ 1338 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1339 (void *)0x4081c406, /* FixDiv, wild guess */ 1340 (void *)0x4081c312, /* FixMul, wild guess */ 1341 }, 1342 /* 1343 * Vectors verified for Performa/LC 550 1344 */ 1345 { /* 11 */ 1346 "P/LC 550 ROMs", 1347 (void *)0x408d16d6, /* ADB interrupt */ 1348 (void *)0x0, /* PB ADB interrupt */ 1349 (void *)0x408b2f84, /* ADBBase + 130 interrupt; whatzit? */ 1350 (void *)0x4080a360, /* CountADBs */ 1351 (void *)0x4080a37a, /* GetIndADB */ 1352 (void *)0x4080a3a6, /* GetADBInfo */ 1353 (void *)0x4080a3ac, /* SetADBInfo */ 1354 (void *)0x4080a752, /* ADBReInit */ 1355 (void *)0x4080a3dc, /* ADBOp */ 1356 (void *)0x0, /* PMgrOp */ 1357 (void *)0x4080c05c, /* WriteParam */ 1358 (void *)0x4080c086, /* SetDateTime */ 1359 (void *)0x4080c5cc, /* InitUtil */ 1360 (void *)0x4080b186, /* ReadXPRam */ 1361 (void *)0x4080b190, /* WriteXPRam */ 1362 (void *)0x408b3c04, /* jClkNoMem */ 1363 (void *)0x4080a818, /* ADBAlternateInit */ 1364 (void *)0x408d1450, /* Egret */ 1365 (void *)0x408147c4, /* InitEgret */ 1366 (void *)0x408d24a4, /* ADBReInit_JTBL */ 1367 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1368 (void *)0x4081c406, /* FixDiv for P550 */ 1369 (void *)0x4081c312, /* FixMul for P550 */ 1370 }, 1371 /* 1372 * Vectors verified for the MacTV 1373 */ 1374 { /* 12 */ 1375 "MacTV ROMs", 1376 (void *)0x40acfed6, /* ADB interrupt */ 1377 (void *)0x0, /* PB ADB interrupt */ 1378 (void *)0x40ab2f84, /* ADBBase + 130 interrupt; whatzit? */ 1379 (void *)0x40a0a360, /* CountADBs */ 1380 (void *)0x40a0a37a, /* GetIndADB */ 1381 (void *)0x40a0a3a6, /* GetADBInfo */ 1382 (void *)0x40a0a3ac, /* SetADBInfo */ 1383 (void *)0x40a0a752, /* ADBReInit */ 1384 (void *)0x40a0a3dc, /* ADBOp */ 1385 (void *)0x0, /* PMgrOp */ 1386 (void *)0x40a0c05c, /* WriteParam */ 1387 (void *)0x40a0c086, /* SetDateTime */ 1388 (void *)0x40a0c5cc, /* InitUtil */ 1389 (void *)0x40a0b186, /* ReadXPRam */ 1390 (void *)0x40a0b190, /* WriteXPRam */ 1391 (void *)0x40ab3bf4, /* jClkNoMem */ 1392 (void *)0x40a0a818, /* ADBAlternateInit */ 1393 (void *)0x40acfd40, /* Egret */ 1394 (void *)0x40a147c4, /* InitEgret */ 1395 (void *)0x40a038a0, /* ADBReInit_JTBL */ 1396 (void *)0x40a7eb90, /* ROMResourceMap List Head */ 1397 (void *)0x40a1c406, /* FixDiv */ 1398 (void *)0x40a1c312, /* FixMul */ 1399 }, 1400 /* 1401 * Vectors verified for the Quadra630 1402 */ 1403 { /* 13 */ 1404 "Quadra630 ROMs", 1405 (void *)0x408a9bd2, /* ADB int */ 1406 (void *)0x0, /* PM intr */ 1407 (void *)0x408b2f94, /* ADBBase + 130 */ 1408 (void *)0x4080a360, /* CountADBs */ 1409 (void *)0x4080a37a, /* GetIndADB */ 1410 (void *)0x4080a3a6, /* GetADBInfo */ 1411 (void *)0x4080a3ac, /* SetADBInfo */ 1412 (void *)0x4080a752, /* ADBReInit */ 1413 (void *)0x4080a3dc, /* ADBOp */ 1414 (void *)0, /* PMgrOp */ 1415 (void *)0x4080c05c, /* WriteParam */ 1416 (void *)0x4080c086, /* SetDateTime */ 1417 (void *)0x4080c5cc, /* InitUtil */ 1418 (void *)0x4080b186, /* Wild guess at ReadXPRam */ 1419 (void *)0x4080b190, /* Wild guess at WriteXPRam */ 1420 (void *)0x408b39f4, /* jClkNoMem */ 1421 (void *)0x4080a818, /* ADBAlternateInit */ 1422 (void *)0x408a99c0, /* Egret */ 1423 (void *)0x408147c8, /* InitEgret */ 1424 (void *)0x408a7ef8, /* ADBReInit_JTBL */ 1425 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1426 (void *)0x4081c406, /* FixDiv */ 1427 (void *)0x4081c312, /* FixMul */ 1428 }, 1429 /* 1430 * Vectors verified for LC III 1431 */ 1432 { /* 14 */ 1433 "LC III ROMs", 1434 (void *)0x40814912, /* ADB interrupt */ 1435 (void *)0x0, /* PM ADB interrupt */ 1436 (void *)0x408b2f94, /* ADBBase + 130 interrupt */ 1437 (void *)0x4080a360, /* CountADBs */ 1438 (void *)0x4080a37a, /* GetIndADB */ 1439 (void *)0x4080a3a6, /* GetADBInfo */ 1440 (void *)0x4080a3ac, /* SetADBInfo */ 1441 (void *)0x4080a752, /* ADBReInit */ 1442 (void *)0x4080a3dc, /* ADBOp */ 1443 (void *)0x0, /* PMgrOp */ 1444 (void *)0x4080c05c, /* WriteParam */ 1445 (void *)0x4080c086, /* SetDateTime */ 1446 (void *)0x4080c5cc, /* InitUtil */ 1447 (void *)0x4080b186, /* ReadXPRam */ 1448 (void *)0x4080b190, /* WriteXPRam */ 1449 (void *)0x408b39b6, /* jClkNoMem */ 1450 (void *)0x4080a818, /* ADBAlternateInit */ 1451 (void *)0x40814800, /* Egret */ 1452 (void *)0x408147c4, /* InitEgret */ 1453 (void *)0x408d2918, /* ADBReInit_JTBL */ 1454 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1455 (void *)0x4081c406, /* FixDiv */ 1456 (void *)0x4081c312, /* FixMul */ 1457 }, 1458 /* 1459 * Vectors verified for the LC520 1460 */ 1461 { /* 15 */ 1462 "MacLC520 ROMs", 1463 (void *)0x408d16d6, /* ADB interrupt */ 1464 (void *)0x0, /* PB ADB interrupt */ 1465 (void *)0x408b2f84, /* ADBBase + 130 interrupt; whatzit? */ 1466 (void *)0x4080a360, /* CountADBs */ 1467 (void *)0x4080a37a, /* GetIndADB */ 1468 (void *)0x4080a3a6, /* GetADBInfo */ 1469 (void *)0x4080a3ac, /* SetADBInfo */ 1470 (void *)0x4080a752, /* ADBReInit */ 1471 (void *)0x4080a3dc, /* ADBOp */ 1472 (void *)0x0, /* PMgrOp */ 1473 (void *)0x4080c05c, /* WriteParam */ 1474 (void *)0x4080c086, /* SetDateTime */ 1475 (void *)0x4080c5cc, /* InitUtil */ 1476 (void *)0x4080b186, /* ReadXPRam */ 1477 (void *)0x4080b190, /* WriteXPRam */ 1478 (void *)0x408b3c04, /* jClkNoMem */ 1479 (void *)0x4080a818, /* ADBAlternateInit */ 1480 (void *)0x408d1450, /* Egret */ 1481 (void *)0x408147c4, /* InitEgret */ 1482 (void *)0x408d2460, /* ADBReInit_JTBL */ 1483 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1484 (void *)0x4081c406, /* FixDiv for P520 */ 1485 (void *)0x4081c312, /* FixMul for P520 */ 1486 }, 1487 /* 1488 * Vectors verified for the LC 575/577/578 1489 */ 1490 { /* 16 */ 1491 "MacLC575 ROMs", 1492 (void *)0x408a9b56, /* ADB interrupt */ 1493 (void *)0x0, /* PB ADB interrupt */ 1494 (void *)0x408b2f94, /* ADBBase + 130 interrupt; whatzit? */ 1495 (void *)0x4080a360, /* CountADBs */ 1496 (void *)0x4080a37a, /* GetIndADB */ 1497 (void *)0x4080a3a6, /* GetADBInfo */ 1498 (void *)0x4080a3ac, /* SetADBInfo */ 1499 (void *)0x4080a752, /* ADBReInit */ 1500 (void *)0x4080a3dc, /* ADBOp */ 1501 (void *)0x0, /* PMgrOp */ 1502 (void *)0x4080c05c, /* WriteParam */ 1503 (void *)0x4080c086, /* SetDateTime */ 1504 (void *)0x4080c5cc, /* InitUtil */ 1505 (void *)0x4080b186, /* ReadXPRam */ 1506 (void *)0x4080b190, /* WriteXPRam */ 1507 (void *)0x408b3bf8, /* jClkNoMem */ 1508 (void *)0x4080a818, /* ADBAlternateInit */ 1509 (void *)0x408a99c0, /* Egret */ 1510 (void *)0x408147c4, /* InitEgret */ 1511 (void *)0x408a81a0, /* ADBReInit_JTBL */ 1512 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1513 (void *)0x4081c406, /* FixDiv for P520 */ 1514 (void *)0x4081c312, /* FixMul for P520 */ 1515 }, 1516 /* 1517 * Vectors verified for the Quadra 950 1518 */ 1519 { /* 17 */ 1520 "Quadra950 class ROMs", 1521 (void *)0x40814912, /* ADB interrupt */ 1522 (void *)0x0, /* PM ADB interrupt */ 1523 (void *)0x4080a4d8, /* ADBBase + 130 interrupt; whatzit? */ 1524 (void *)0x4080a360, /* CountADBs */ 1525 (void *)0x4080a37a, /* GetIndADB */ 1526 (void *)0x4080a3a6, /* GetADBInfo */ 1527 (void *)0x4080a3ac, /* SetADBInfo */ 1528 (void *)0x4080a752, /* ADBReInit */ 1529 (void *)0x4080a3dc, /* ADBOp */ 1530 (void *)0x0, /* PMgrOp */ 1531 (void *)0x4080c05c, /* WriteParam */ 1532 (void *)0x4080c086, /* SetDateTime */ 1533 (void *)0x4080c5cc, /* InitUtil */ 1534 (void *)0x4080b186, /* ReadXPRam */ 1535 (void *)0x4080b190, /* WriteXPRam */ 1536 (void *)0x4080b1e4, /* jClkNoMem */ 1537 (void *)0x4080a818, /* ADBAlternateInit */ 1538 (void *)0x40814800, /* Egret */ 1539 (void *)0x408147c4, /* InitEgret */ 1540 (void *)0x408038bc, /* ADBReInit_JTBL */ 1541 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1542 (void *)0x4081c406, /* FixDiv */ 1543 (void *)0x4081c312, /* FixMul */ 1544 }, 1545 /* 1546 * Vectors verified for the Mac IIfx 1547 */ 1548 { /* 18 */ 1549 "Mac IIfx ROMs", 1550 (void *)0x40809f4a, /* ADB interrupt */ 1551 (void *)0x0, /* PM ADB interrupt */ 1552 (void *)0x4080a4d8, /* ADBBase + 130 interrupt */ 1553 (void *)0x4080a360, /* CountADBs */ 1554 (void *)0x4080a37a, /* GetIndADB */ 1555 (void *)0x4080a3a6, /* GetADBInfo */ 1556 (void *)0x4080a3ac, /* SetADBInfo */ 1557 (void *)0x4080a752, /* ADBReInit */ 1558 (void *)0x4080a3dc, /* ADBOp */ 1559 (void *)0x0, /* PMgrOp */ 1560 (void *)0x4080c05c, /* WriteParam */ 1561 (void *)0x4080c086, /* SetDateTime */ 1562 (void *)0x4080c5cc, /* InitUtil */ 1563 (void *)0x4080b186, /* ReadXPRam */ 1564 (void *)0x4080b190, /* WriteXPRam */ 1565 (void *)0x4080b1e4, /* jClkNoMem */ 1566 (void *)0x4080a818, /* ADBAlternateInit */ 1567 (void *)0x0, /* Egret */ 1568 (void *)0x0, /* InitEgret */ 1569 (void *)0x408037c0, /* ADBReInit_JTBL */ 1570 (void *)0x4087eb90, /* ROMResourceMap List Head */ 1571 (void *)0x4081c406, /* FixDiv */ 1572 (void *)0x4081c312, /* FixMul */ 1573 }, 1574 /* 1575 * Vectors verified for the Performa 588 (and 580?) 1576 */ 1577 { /* 19 */ 1578 "Performa 580 ROMs", 1579 (void *) 0x4089a8be, /* ADB interrupt */ 1580 (void *) 0x0, /* PM ADB interrupt */ 1581 (void *) 0x408b2f94, /* ADBBase + 130 interrupt */ 1582 (void *) 0x4080a360, /* CountADBs */ 1583 (void *) 0x4080a37a, /* GetIndADB */ 1584 (void *) 0x4080a3a6, /* GetADBInfo */ 1585 (void *) 0x4080a3ac, /* SetADBInfo */ 1586 (void *) 0x4080a752, /* ADBReInit */ 1587 (void *) 0x4080a3dc, /* ADBOp */ 1588 (void *) 0x0, /* PMgrOp */ 1589 (void *) 0x4080c05c, /* WriteParam */ 1590 (void *) 0x4080c086, /* SetDateTime */ 1591 (void *) 0x4080c5cc, /* InitUtil */ 1592 (void *) 0x4080b186, /* ReadXPRam */ 1593 (void *) 0x4080b190, /* WriteXPRam */ 1594 (void *) 0x408b3bf4, /* jClkNoMem */ 1595 (void *) 0x4080a818, /* ADBAlternateInit */ 1596 (void *) 0x408a99c0, /* Egret */ 1597 (void *) 0x408147c8, /* InitEgret */ 1598 (void *) 0x408a7f74, /* ADBReInit_JTBL */ 1599 (void *) 0x4087eb90, /* ROMResourceMap List Head */ 1600 (void *) 0x4081c406, /* FixDiv */ 1601 (void *) 0x4081c312, /* FixMul */ 1602 }, 1603 /* Please fill these in! -BG */ 1604 }; 1605 1606 1607 struct cpu_model_info cpu_models[] = { 1608 1609 /* The first four. */ 1610 {MACH_MACII, "II ", "", MACH_CLASSII, &romvecs[0]}, 1611 {MACH_MACIIX, "IIx ", "", MACH_CLASSII, &romvecs[0]}, 1612 {MACH_MACIICX, "IIcx ", "", MACH_CLASSII, &romvecs[0]}, 1613 {MACH_MACSE30, "SE/30 ", "", MACH_CLASSII, &romvecs[0]}, 1614 1615 /* The rest of the II series... */ 1616 {MACH_MACIICI, "IIci ", "", MACH_CLASSIIci, &romvecs[4]}, 1617 {MACH_MACIISI, "IIsi ", "", MACH_CLASSIIsi, &romvecs[2]}, 1618 {MACH_MACIIVI, "IIvi ", "", MACH_CLASSIIvx, &romvecs[2]}, 1619 {MACH_MACIIVX, "IIvx ", "", MACH_CLASSIIvx, &romvecs[2]}, 1620 {MACH_MACIIFX, "IIfx ", "", MACH_CLASSIIfx, &romvecs[18]}, 1621 1622 /* The Centris/Quadra series. */ 1623 {MACH_MACQ700, "Quadra", " 700 ", MACH_CLASSQ, &romvecs[4]}, 1624 {MACH_MACQ900, "Quadra", " 900 ", MACH_CLASSQ, &romvecs[6]}, 1625 {MACH_MACQ950, "Quadra", " 950 ", MACH_CLASSQ, &romvecs[17]}, 1626 {MACH_MACQ800, "Quadra", " 800 ", MACH_CLASSQ, &romvecs[6]}, 1627 {MACH_MACQ650, "Quadra", " 650 ", MACH_CLASSQ, &romvecs[6]}, 1628 {MACH_MACC650, "Centris", " 650 ", MACH_CLASSQ, &romvecs[6]}, 1629 {MACH_MACQ605, "Quadra", " 605 ", MACH_CLASSQ, &romvecs[9]}, 1630 {MACH_MACQ605_33, "Quadra", " 605/33 ", MACH_CLASSQ, &romvecs[9]}, 1631 {MACH_MACC610, "Centris", " 610 ", MACH_CLASSQ, &romvecs[6]}, 1632 {MACH_MACQ610, "Quadra", " 610 ", MACH_CLASSQ, &romvecs[6]}, 1633 {MACH_MACQ630, "Quadra", " 630 ", MACH_CLASSQ2, &romvecs[13]}, 1634 {MACH_MACC660AV, "Centris", " 660AV ", MACH_CLASSAV, &romvecs[7]}, 1635 {MACH_MACQ840AV, "Quadra", " 840AV ", MACH_CLASSAV, &romvecs[7]}, 1636 1637 /* The Powerbooks/Duos... */ 1638 {MACH_MACPB100, "PowerBook", " 100 ", MACH_CLASSPB, &romvecs[1]}, 1639 /* PB 100 has no MMU! */ 1640 {MACH_MACPB140, "PowerBook", " 140 ", MACH_CLASSPB, &romvecs[1]}, 1641 {MACH_MACPB145, "PowerBook", " 145 ", MACH_CLASSPB, &romvecs[1]}, 1642 {MACH_MACPB150, "PowerBook", " 150 ", MACH_CLASSDUO, &romvecs[10]}, 1643 {MACH_MACPB160, "PowerBook", " 160 ", MACH_CLASSPB, &romvecs[5]}, 1644 {MACH_MACPB165, "PowerBook", " 165 ", MACH_CLASSPB, &romvecs[5]}, 1645 {MACH_MACPB165C, "PowerBook", " 165c ", MACH_CLASSPB, &romvecs[5]}, 1646 {MACH_MACPB170, "PowerBook", " 170 ", MACH_CLASSPB, &romvecs[1]}, 1647 {MACH_MACPB180, "PowerBook", " 180 ", MACH_CLASSPB, &romvecs[5]}, 1648 {MACH_MACPB180C, "PowerBook", " 180c ", MACH_CLASSPB, &romvecs[5]}, 1649 {MACH_MACPB190, "PowerBook", " 190 ", MACH_CLASSPB, &romvecs[8]}, 1650 {MACH_MACPB190CS, "PowerBook", " 190cs ", MACH_CLASSPB, &romvecs[8]}, 1651 {MACH_MACPB500, "PowerBook", " 500 ", MACH_CLASSPB, &romvecs[8]}, 1652 1653 /* The Duos */ 1654 {MACH_MACPB210, "PowerBook Duo", " 210 ", MACH_CLASSDUO, &romvecs[5]}, 1655 {MACH_MACPB230, "PowerBook Duo", " 230 ", MACH_CLASSDUO, &romvecs[5]}, 1656 {MACH_MACPB250, "PowerBook Duo", " 250 ", MACH_CLASSDUO, &romvecs[5]}, 1657 {MACH_MACPB270, "PowerBook Duo", " 270C ", MACH_CLASSDUO, &romvecs[5]}, 1658 {MACH_MACPB280, "PowerBook Duo", " 280 ", MACH_CLASSDUO, &romvecs[5]}, 1659 {MACH_MACPB280C, "PowerBook Duo", " 280C ", MACH_CLASSDUO, &romvecs[5]}, 1660 1661 /* The Performas... */ 1662 {MACH_MACP600, "Performa", " 600 ", MACH_CLASSIIvx, &romvecs[2]}, 1663 {MACH_MACP460, "Performa", " 460 ", MACH_CLASSLC, &romvecs[14]}, 1664 {MACH_MACP550, "Performa", " 550 ", MACH_CLASSLC, &romvecs[11]}, 1665 {MACH_MACP580, "Performa", " 580 ", MACH_CLASSQ2, &romvecs[19]}, 1666 {MACH_MACTV, "TV ", "", MACH_CLASSLC, &romvecs[12]}, 1667 1668 /* The LCs... */ 1669 {MACH_MACLCII, "LC", " II ", MACH_CLASSLC, &romvecs[3]}, 1670 {MACH_MACLCIII, "LC", " III ", MACH_CLASSLC, &romvecs[14]}, 1671 {MACH_MACLC475, "LC", " 475 ", MACH_CLASSQ, &romvecs[9]}, 1672 {MACH_MACLC475_33, "LC", " 475/33 ", MACH_CLASSQ, &romvecs[9]}, 1673 {MACH_MACLC520, "LC", " 520 ", MACH_CLASSLC, &romvecs[15]}, 1674 {MACH_MACLC575, "LC", " 575 ", MACH_CLASSQ2, &romvecs[16]}, 1675 {MACH_MACCCLASSIC, "Color Classic ", "", MACH_CLASSLC, &romvecs[3]}, 1676 {MACH_MACCCLASSICII, "Color Classic"," II ", MACH_CLASSLC, &romvecs[3]}, 1677 /* Does this belong here? */ 1678 {MACH_MACCLASSICII, "Classic", " II ", MACH_CLASSLC, &romvecs[3]}, 1679 1680 /* The unknown one and the end... */ 1681 {0, "Unknown", "", MACH_CLASSII, NULL}, 1682 {0, NULL, NULL, 0, NULL}, 1683 }; /* End of cpu_models[] initialization. */ 1684 1685 struct intvid_info_t { 1686 int machineid; 1687 u_long fbbase; 1688 u_long fbmask; 1689 u_long fblen; 1690 } intvid_info[] = { 1691 { MACH_MACCLASSICII, 0x009f9a80, 0x0, 21888 }, 1692 { MACH_MACPB140, 0xfee08000, 0x0, 32 * 1024 }, 1693 { MACH_MACPB145, 0xfee08000, 0x0, 32 * 1024 }, 1694 { MACH_MACPB170, 0xfee08000, 0x0, 32 * 1024 }, 1695 { MACH_MACPB150, 0x60000000, 0x0, 128 * 1024 }, 1696 { MACH_MACPB160, 0x60000000, 0x0ffe0000, 128 * 1024 }, 1697 { MACH_MACPB165, 0x60000000, 0x0ffe0000, 128 * 1024 }, 1698 { MACH_MACPB180, 0x60000000, 0x0ffe0000, 128 * 1024 }, 1699 { MACH_MACPB210, 0x60000000, 0x0, 128 * 1024 }, 1700 { MACH_MACPB230, 0x60000000, 0x0, 128 * 1024 }, 1701 { MACH_MACPB250, 0x60000000, 0x0, 128 * 1024 }, 1702 { MACH_MACPB270, 0x60000000, 0x0, 128 * 1024 }, 1703 { MACH_MACPB280, 0x60000000, 0x0, 128 * 1024 }, 1704 { MACH_MACPB280C, 0x60000000, 0x0, 128 * 1024 }, 1705 { MACH_MACIICI, 0x0, 0x0, 320 * 1024 }, 1706 { MACH_MACIISI, 0x0, 0x0, 320 * 1024 }, 1707 { MACH_MACCCLASSIC, 0x50f40000, 0x0, 512 * 1024 }, 1708 /*??*/ { MACH_MACLCII, 0x50f40000, 0x0, 512 * 1024 }, 1709 { MACH_MACPB165C, 0xfc040000, 0x0, 512 * 1024 }, 1710 { MACH_MACPB180C, 0xfc040000, 0x0, 512 * 1024 }, 1711 { MACH_MACPB190, 0x60000000, 0x0, 512 * 1024 }, 1712 { MACH_MACPB190CS, 0x60000000, 0x0, 512 * 1024 }, 1713 { MACH_MACPB500, 0x60000000, 0x0, 512 * 1024 }, 1714 { MACH_MACLCIII, 0x60b00000, 0x0, 768 * 1024 }, 1715 { MACH_MACLC520, 0x60000000, 0x0, 1024 * 1024 }, 1716 { MACH_MACP550, 0x60000000, 0x0, 1024 * 1024 }, 1717 { MACH_MACTV, 0x60000000, 0x0, 1024 * 1024 }, 1718 { MACH_MACLC475, 0xf9000000, 0x0, 1024 * 1024 }, 1719 { MACH_MACLC475_33, 0xf9000000, 0x0, 1024 * 1024 }, 1720 { MACH_MACLC575, 0xf9000000, 0x0, 1024 * 1024 }, 1721 { MACH_MACC610, 0xf9000000, 0x0, 1024 * 1024 }, 1722 { MACH_MACC650, 0xf9000000, 0x0, 1024 * 1024 }, 1723 { MACH_MACP580, 0xf9000000, 0x0, 1024 * 1024 }, 1724 { MACH_MACQ605, 0xf9000000, 0x0, 1024 * 1024 }, 1725 { MACH_MACQ605_33, 0xf9000000, 0x0, 1024 * 1024 }, 1726 { MACH_MACQ610, 0xf9000000, 0x0, 1024 * 1024 }, 1727 { MACH_MACQ630, 0xf9000000, 0x0, 1024 * 1024 }, 1728 { MACH_MACQ650, 0xf9000000, 0x0, 1024 * 1024 }, 1729 { MACH_MACC660AV, 0x50100000, 0x0, 1024 * 1024 }, 1730 { MACH_MACQ700, 0xf9000000, 0x0, 1024 * 1024 }, 1731 { MACH_MACQ800, 0xf9000000, 0x0, 1024 * 1024 }, 1732 { MACH_MACQ900, 0xf9000000, 0x0, 1024 * 1024 }, 1733 { MACH_MACQ950, 0xf9000000, 0x0, 1024 * 1024 }, 1734 { MACH_MACQ840AV, 0x50100000, 0x0, 2048 * 1024 }, 1735 { 0, 0x0, 0x0, 0 }, 1736 }; /* End of intvid_info[] initialization. */ 1737 1738 /* 1739 * Missing Mac Models: 1740 * PowerMac 6100 1741 * PowerMac 7100 1742 * PowerMac 8100 1743 * PowerBook 540 1744 * PowerBook 520 1745 * PowerBook 150 1746 * Duo 280 1747 * Performa 6000s 1748 * ...? 1749 */ 1750 1751 int mach_cputype(void); 1752 1753 int 1754 mach_cputype(void) 1755 { 1756 return (mac68k_machine.mach_processor); 1757 } 1758 1759 void 1760 machine_set_model(void) 1761 { 1762 cpu_setmodel("Apple Macintosh %s%s", 1763 cpu_models[mac68k_machine.cpu_model_index].model_major, 1764 cpu_models[mac68k_machine.cpu_model_index].model_minor); 1765 } 1766 1767 static void get_machine_info(void); 1768 1769 static void 1770 get_machine_info(void) 1771 { 1772 int i; 1773 1774 for (i = 0; cpu_models[i].model_major; i++) 1775 if (mac68k_machine.machineid == cpu_models[i].machineid) 1776 break; 1777 1778 if (cpu_models[i].model_major == NULL) 1779 i--; 1780 1781 mac68k_machine.cpu_model_index = i; 1782 } 1783 1784 struct cpu_model_info *current_mac_model; 1785 romvec_t *mrg_MacOSROMVectors = 0; 1786 1787 /* 1788 * Sets a bunch of machine-specific variables 1789 */ 1790 void setmachdep(void); 1791 1792 void 1793 setmachdep(void) 1794 { 1795 struct cpu_model_info *cpui; 1796 1797 /* 1798 * First, set things that need to be set on the first pass only 1799 * Ideally, we'd only call this once, but for some reason, the 1800 * VIAs need interrupts turned off twice !? 1801 */ 1802 get_machine_info(); 1803 1804 load_addr = 0; 1805 cpui = &(cpu_models[mac68k_machine.cpu_model_index]); 1806 current_mac_model = cpui; 1807 1808 mac68k_machine.via1_ipl = 1; 1809 mac68k_machine.via2_ipl = 2; 1810 mac68k_machine.aux_interrupts = 0; 1811 1812 /* 1813 * Set up any machine specific stuff that we have to before 1814 * ANYTHING else happens 1815 */ 1816 switch (cpui->class) { /* Base this on class of machine... */ 1817 case MACH_CLASSII: 1818 VIA2 = VIA2OFF; 1819 IOBase = 0x50f00000; 1820 Via1Base = (volatile u_char *)IOBase; 1821 mac68k_machine.scsi80 = 1; 1822 mac68k_machine.zs_chip = 0; 1823 via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */ 1824 via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */ 1825 break; 1826 case MACH_CLASSPB: 1827 VIA2 = VIA2OFF; 1828 IOBase = 0x50f00000; 1829 Via1Base = (volatile u_char *)IOBase; 1830 mac68k_machine.scsi80 = 1; 1831 mac68k_machine.zs_chip = 0; 1832 /* Disable everything but PM; we need it. */ 1833 via_reg(VIA1, vIER) = 0x6f; /* disable VIA1 int */ 1834 /* Are we disabling something important? */ 1835 via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */ 1836 if (cputype == CPU_68040) 1837 mac68k_machine.sonic = 1; 1838 break; 1839 case MACH_CLASSDUO: 1840 /* 1841 * The Duo definitely does not use a VIA2, but it looks 1842 * like the VIA2 functions might be on the MSC at the RBV 1843 * locations. The rest is copied from the Powerbooks. 1844 */ 1845 VIA2 = RBVOFF; 1846 IOBase = 0x50f00000; 1847 Via1Base = (volatile u_char *)IOBase; 1848 mac68k_machine.scsi80 = 1; 1849 mac68k_machine.zs_chip = 0; 1850 /* Disable everything but PM; we need it. */ 1851 via_reg(VIA1, vIER) = 0x6f; /* disable VIA1 int */ 1852 /* Are we disabling something important? */ 1853 via_reg(VIA2, rIER) = 0x7f; /* disable VIA2 int */ 1854 break; 1855 case MACH_CLASSQ: 1856 case MACH_CLASSQ2: 1857 VIA2 = VIA2OFF; 1858 IOBase = 0x50f00000; 1859 Via1Base = (volatile u_char *)IOBase; 1860 mac68k_machine.sonic = 1; 1861 mac68k_machine.scsi96 = 1; 1862 mac68k_machine.zs_chip = 0; 1863 via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */ 1864 via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */ 1865 1866 #if 1 1867 switch (current_mac_model->machineid) { 1868 default: 1869 /* case MACH_MACQ900: These three, at least, support the 1870 case MACH_MACQ950: A/UX interrupts. What Quadras don't? 1871 case MACH_MACQ700: */ 1872 /* Enable A/UX interrupt scheme */ 1873 mac68k_machine.aux_interrupts = 1; 1874 1875 via_reg(VIA1, vBufB) &= (0xff ^ DB1O_AuxIntEnb); 1876 via_reg(VIA1, vDirB) |= DB1O_AuxIntEnb; 1877 mac68k_machine.via1_ipl = 6; 1878 mac68k_machine.via2_ipl = 2; 1879 break; 1880 } 1881 #endif 1882 1883 break; 1884 case MACH_CLASSAV: 1885 case MACH_CLASSP580: 1886 VIA2 = VIA2OFF; 1887 IOBase = 0x50f00000; 1888 Via1Base = (volatile u_char *)IOBase; 1889 mac68k_machine.scsi96 = 1; 1890 mac68k_machine.zs_chip = 0; 1891 via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */ 1892 via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */ 1893 break; 1894 case MACH_CLASSIIci: 1895 VIA2 = RBVOFF; 1896 IOBase = 0x50f00000; 1897 Via1Base = (volatile u_char *)IOBase; 1898 mac68k_machine.scsi80 = 1; 1899 mac68k_machine.zs_chip = 0; 1900 via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */ 1901 via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */ 1902 break; 1903 case MACH_CLASSIIsi: 1904 VIA2 = RBVOFF; 1905 IOBase = 0x50f00000; 1906 Via1Base = (volatile u_char *)IOBase; 1907 mac68k_machine.scsi80 = 1; 1908 mac68k_machine.zs_chip = 0; 1909 via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */ 1910 via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */ 1911 break; 1912 case MACH_CLASSIIvx: 1913 VIA2 = RBVOFF; 1914 IOBase = 0x50f00000; 1915 Via1Base = (volatile u_char *)IOBase; 1916 mac68k_machine.scsi80 = 1; 1917 mac68k_machine.zs_chip = 0; 1918 via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */ 1919 via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */ 1920 break; 1921 case MACH_CLASSLC: 1922 VIA2 = RBVOFF; 1923 IOBase = 0x50f00000; 1924 Via1Base = (volatile u_char *)IOBase; 1925 mac68k_machine.scsi80 = 1; 1926 mac68k_machine.zs_chip = 0; 1927 via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */ 1928 via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */ 1929 break; 1930 case MACH_CLASSIIfx: 1931 VIA2 = OSSOFF; 1932 IOBase = 0x50f00000; 1933 Via1Base = (volatile u_char *)IOBase; 1934 mac68k_machine.scsi80 = 1; 1935 mac68k_machine.zs_chip = 0; 1936 via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */ 1937 break; 1938 default: 1939 case MACH_CLASSH: 1940 break; 1941 } 1942 1943 /* 1944 * Set up current ROM Glue vectors. Actually now all we do 1945 * is save the address of the ROM Glue Vector table. This gets 1946 * used later when we re-map the vectors from MacOS Address 1947 * Space to NetBSD Address Space. 1948 */ 1949 mrg_MacOSROMVectors = cpui->rom_vectors; 1950 } 1951 1952 /* 1953 * Set IO offsets. 1954 */ 1955 void 1956 mac68k_set_io_offsets(vaddr_t base) 1957 { 1958 1959 Via1Base = (volatile u_char *)base; 1960 Via2Base = Via1Base + 0x2000 * VIA2; 1961 switch (current_mac_model->class) { 1962 case MACH_CLASSQ: 1963 switch (current_mac_model->machineid) { 1964 case MACH_MACQ900: 1965 case MACH_MACQ950: 1966 sccA = (volatile u_char *)base + 0xc020; 1967 SCSIBase = base + 0xf000; 1968 mac68k_machine.scsi96_2 = 1; 1969 iop_init(0); /* For console */ 1970 break; 1971 case MACH_MACQ800: 1972 /* 1973 * The H/W partially decode address for sccA; it is 1974 * available at offsets 0xc000, 0xc020, .... Here, 1975 * we choose 0xc020, where Mac toolbox ROM uses. 1976 */ 1977 sccA = (volatile u_char *)base + 0xc020; 1978 SCSIBase = base + 0x10000; 1979 break; 1980 case MACH_MACQ700: 1981 sccA = (volatile u_char *)base + 0xc000; 1982 SCSIBase = base + 0xf000; 1983 break; 1984 default: 1985 sccA = (volatile u_char *)base + 0xc000; 1986 SCSIBase = base + 0x10000; 1987 break; 1988 } 1989 break; 1990 case MACH_CLASSQ2: 1991 /* 1992 * Note the different offset for sccA for this class of 1993 * machines. This seems to be common on many of the 1994 * Quadra-type machines. 1995 */ 1996 sccA = (volatile u_char *)base + 0xc020; 1997 SCSIBase = base + 0x10000; 1998 break; 1999 case MACH_CLASSP580: 2000 /* 2001 * Here's a queer bird... it seems to be a cross between 2002 * the two different Quadra classes. 2003 */ 2004 sccA = (volatile u_char *)base + 0xc020; 2005 SCSIBase = base; 2006 break; 2007 case MACH_CLASSAV: 2008 sccA = (volatile u_char *)base + 0x4000; 2009 SCSIBase = base + 0x18000; 2010 PSCBase = (volatile u_char *)base + 0x31000; 2011 break; 2012 case MACH_CLASSII: 2013 case MACH_CLASSPB: 2014 case MACH_CLASSDUO: 2015 case MACH_CLASSIIci: 2016 case MACH_CLASSIIsi: 2017 case MACH_CLASSIIvx: 2018 case MACH_CLASSLC: 2019 sccA = (volatile u_char *)base + 0x4000; 2020 SCSIBase = base; 2021 break; 2022 case MACH_CLASSIIfx: 2023 /* 2024 * Note that sccA base address is based on having 2025 * the serial port in `compatible' mode (set in 2026 * the Serial Switch control panel before booting). 2027 */ 2028 sccA = (volatile u_char *)base + 0x4020; 2029 SCSIBase = base; 2030 iop_init(0); /* For console */ 2031 break; 2032 default: 2033 case MACH_CLASSH: 2034 panic("Unknown/unsupported machine class (%d).", 2035 current_mac_model->class); 2036 break; 2037 } 2038 } 2039 2040 #if GRAYBARS 2041 static u_long gray_nextaddr = 0; 2042 2043 void 2044 gray_bar(void) 2045 { 2046 static int i = 0; 2047 static int flag = 0; 2048 2049 /* MF basic premise as I see it: 2050 1) Save the scratch regs as they are not saved by the compilier. 2051 2) Check to see if we want gray bars, if so, 2052 display some lines of gray, 2053 a couple of lines of white(about 8), 2054 and loop to slow this down. 2055 3) restore regs 2056 */ 2057 2058 __asm volatile ( 2059 " movl %a0,%sp@-;" 2060 " movl %a1,%sp@-;" 2061 " movl %d0,%sp@-;" 2062 " movl %d1,%sp@-"); 2063 2064 /* check to see if gray bars are turned off */ 2065 if (mac68k_machine.do_graybars) { 2066 /* MF the 10*stride/4 is done lots, but we want this to be 2067 * slow */ 2068 for (i = 0; i < 10 * mac68k_video.mv_stride / 4; i++) 2069 ((u_long *)mac68k_video.mv_kvaddr) 2070 [gray_nextaddr++] = 0xaaaaaaaa; 2071 for (i = 0; i < 2 * mac68k_video.mv_stride / 4; i++) 2072 ((u_long *)mac68k_video.mv_kvaddr) 2073 [gray_nextaddr++] = 0x00000000; 2074 } 2075 2076 __asm volatile ( 2077 " movl %sp@+,%d1;" 2078 " movl %sp@+,%d0;" 2079 " movl %sp@+,%a1;" 2080 " movl %sp@+,%a0"); 2081 } 2082 #endif 2083 2084 /* in locore */ 2085 extern u_long ptest040(void *, u_int); 2086 extern u_long plpar060(void *, u_int); 2087 extern int get_pte(u_int, u_long *, u_short *); 2088 2089 /* 2090 * LAK (7/24/94): given a logical address, puts the physical address 2091 * in *phys and return 1, or returns 0 on failure. This is intended 2092 * to look through MacOS page tables. 2093 */ 2094 2095 static u_long 2096 get_physical(u_int addr, u_long * phys) 2097 { 2098 extern u_int macos_tc; 2099 u_long pte[2], ph, mask; 2100 u_short psr; 2101 int i, numbits; 2102 2103 if (cputype == CPU_68060) { 2104 ph = plpar060((void *)addr, FC_SUPERD); 2105 if (ph == (u_long)-1) { 2106 ph = plpar060((void *)addr, FC_USERD); 2107 if (ph == (u_long)-1) { 2108 return 0; 2109 } 2110 } 2111 *phys = ph; 2112 return 1; 2113 } else if (mmutype == MMU_68040) { 2114 ph = ptest040((void *)addr, FC_SUPERD); 2115 if ((ph & MMUSR40_R) == 0) { 2116 ph = ptest040((void *)addr, FC_USERD); 2117 if ((ph & MMUSR40_R) == 0) 2118 return 0; 2119 } 2120 if ((ph & MMUSR40_T) != 0) 2121 ph = addr; 2122 2123 mask = (macos_tc & TCR40_P) ? 0x00001fff : 0x00000fff; 2124 ph &= (~mask); 2125 } else { 2126 switch (get_pte(addr, pte, &psr)) { 2127 case (-1): 2128 return 0; 2129 case 0: 2130 ph = pte[0] & 0xFFFFFF00; 2131 break; 2132 case 1: 2133 ph = pte[1] & 0xFFFFFF00; 2134 break; 2135 default: 2136 panic("get_physical(): bad get_pte()"); 2137 } 2138 2139 /* 2140 * We must now figure out how many levels down we went and 2141 * mask the bits appropriately -- the returned value may only 2142 * be the upper n bits, and we have to take the rest from addr. 2143 */ 2144 numbits = 0; 2145 psr &= 0x0007; /* Number of levels we went */ 2146 for (i = 0; i < psr; i++) 2147 numbits += (macos_tc >> (12 - i * 4)) & 0x0f; 2148 2149 /* 2150 * We have to take the most significant "numbits" from 2151 * the returned value "ph", and the rest from our addr. 2152 * Assume that numbits != 0. 2153 */ 2154 mask = (1 << (32 - numbits)) - 1; 2155 } 2156 *phys = ph + (addr & mask); 2157 2158 return 1; 2159 } 2160 2161 static void check_video(const char *, u_long, u_long); 2162 2163 static void 2164 check_video(const char *id, u_long limit, u_long maxm) 2165 { 2166 u_long addr, phys; 2167 2168 if (!get_physical(mac68k_video.mv_kvaddr, &phys)) { 2169 if (mac68k_machine.do_graybars) 2170 printf("get_mapping(): %s. False start.\n", id); 2171 } else { 2172 mac68k_video.mv_log = mac68k_video.mv_kvaddr; 2173 mac68k_video.mv_phys = phys; 2174 mac68k_video.mv_len = 32768; 2175 addr = mac68k_video.mv_kvaddr + 32768; 2176 while (get_physical(addr, &phys)) { 2177 if ((phys - mac68k_video.mv_phys) 2178 != mac68k_video.mv_len) 2179 break; 2180 if (mac68k_video.mv_len + 32768 > limit) { 2181 if (mac68k_machine.do_graybars) { 2182 printf("mapping: %s. Does it never end?\n", 2183 id); 2184 printf(" Forcing VRAM size "); 2185 printf("to a conservative %ldK.\n", 2186 maxm/1024); 2187 } 2188 mac68k_video.mv_len = maxm; 2189 break; 2190 } 2191 mac68k_video.mv_len += 32768; 2192 addr += 32768; 2193 } 2194 if (mac68k_machine.do_graybars) { 2195 printf(" %s internal video at addr %p (phys %p), ", 2196 id, (void *)mac68k_video.mv_log, 2197 (void *)mac68k_video.mv_phys); 2198 printf("len 0x%x.\n", mac68k_video.mv_len); 2199 } 2200 } 2201 } 2202 2203 /* 2204 * Find out how MacOS has mapped itself so we can do the same thing. 2205 * Returns the address of logical 0 so that locore can map the kernel 2206 * properly. 2207 */ 2208 u_int 2209 get_mapping(void) 2210 { 2211 struct intvid_info_t *iip; 2212 u_long addr, lastpage, phys, len, limit; 2213 int i, last, same; 2214 2215 numranges = 0; 2216 for (i = 0; i < 8; i++) { 2217 low[i] = 0; 2218 high[i] = 0; 2219 } 2220 2221 lastpage = get_top_of_ram(); 2222 2223 get_physical(0, &load_addr); 2224 2225 if (mac68k_machine.do_graybars) 2226 printf("Loaded at 0x%0lx\n", load_addr); 2227 2228 last = 0; 2229 for (addr = 0; addr <= lastpage && get_physical(addr, &phys); 2230 addr += PAGE_SIZE) { 2231 if (numranges > 0 && phys != high[last]) { 2232 /* 2233 * Attempt to find if this page is already 2234 * accounted for in an existing physical segment. 2235 */ 2236 for (i = 0; i < numranges; i++) { 2237 if (low[i] <= phys && phys <= high[i]) { 2238 last = i; 2239 break; 2240 } 2241 } 2242 if (i >= numranges) 2243 last = numranges - 1; 2244 2245 if (low[last] <= phys && phys < high[last]) 2246 continue; /* Skip pages we've seen. */ 2247 } 2248 2249 if (numranges > 0 && phys == high[last]) { 2250 /* Common case: extend existing segment on high end */ 2251 high[last] += PAGE_SIZE; 2252 } else { 2253 /* This is a new physical segment. */ 2254 for (last = 0; last < numranges; last++) 2255 if (phys < low[last]) 2256 break; 2257 2258 /* Create space for segment, if necessary */ 2259 if (last < numranges && phys < low[last]) { 2260 for (i = numranges; i > last; i--) { 2261 low[i] = low[i - 1]; 2262 high[i] = high[i - 1]; 2263 } 2264 } 2265 2266 numranges++; 2267 low[last] = phys; 2268 high[last] = phys + PAGE_SIZE; 2269 } 2270 2271 /* Coalesce adjoining segments as appropriate */ 2272 if (last < (numranges - 1) && high[last] == low[last + 1] && 2273 low[last + 1] != load_addr) { 2274 high[last] = high[last + 1]; 2275 for (i = last + 1; i < numranges; i++) { 2276 low[i] = low[i + 1]; 2277 high[i] = high[i + 1]; 2278 } 2279 --numranges; 2280 } 2281 } 2282 if (mac68k_machine.do_graybars) { 2283 printf("System RAM: %ld bytes in %ld pages.\n", 2284 addr, addr / PAGE_SIZE); 2285 for (i = 0; i < numranges; i++) { 2286 printf(" Low = 0x%lx, high = 0x%lx\n", 2287 low[i], high[i]); 2288 } 2289 } 2290 2291 /* 2292 * If we can't figure out the PA of the frame buffer by groveling 2293 * the page tables, assume that we already have the correct 2294 * address. This is the case on several of the PowerBook 1xx 2295 * series, in particular. 2296 */ 2297 if (!get_physical(mac68k_video.mv_kvaddr, &phys)) 2298 phys = mac68k_video.mv_kvaddr; 2299 2300 /* 2301 * Find on-board video, if we have an idea of where to look 2302 * on this system. 2303 */ 2304 for (iip = intvid_info; iip->machineid; iip++) 2305 if (mac68k_machine.machineid == iip->machineid) 2306 break; 2307 2308 if (mac68k_machine.machineid == iip->machineid && 2309 (phys & ~iip->fbmask) >= iip->fbbase && 2310 (phys & ~iip->fbmask) < (iip->fbbase + iip->fblen)) { 2311 mac68k_video.mv_phys = phys & ~iip->fbmask; 2312 mac68k_video.mv_len = 32768 - (phys & 0x7fff); 2313 2314 limit = iip->fbbase + iip->fblen - mac68k_video.mv_phys; 2315 if (mac68k_video.mv_len > limit) { 2316 mac68k_video.mv_len = limit; 2317 } else { 2318 addr = mac68k_video.mv_kvaddr + mac68k_video.mv_len; 2319 while (get_physical(addr, &phys)) { 2320 phys &= ~iip->fbmask; 2321 if ((phys - mac68k_video.mv_phys) != 2322 mac68k_video.mv_len) 2323 break; 2324 if ((mac68k_video.mv_phys + 32768) > limit) { 2325 mac68k_video.mv_len = limit; 2326 break; 2327 } 2328 mac68k_video.mv_len += 32768; 2329 addr += 32768; 2330 } 2331 } 2332 } 2333 2334 if (mac68k_video.mv_len > 0) { 2335 /* 2336 * We've already figured out where internal video is. 2337 * Tell the user what we know. 2338 */ 2339 if (mac68k_machine.do_graybars) 2340 printf("On-board video at addr %p (phys %p), " 2341 "len 0x%x.\n", 2342 (void *)mac68k_video.mv_kvaddr, 2343 (void *)mac68k_video.mv_phys, 2344 mac68k_video.mv_len); 2345 } else { 2346 /* 2347 * We should now look through all of NuBus space to find where 2348 * the internal video is being mapped. Just to be sure we 2349 * handle all the cases, we simply map our NuBus space exactly 2350 * how MacOS did it. As above, we find a bunch of ranges that 2351 * are contiguously mapped. Since there are a lot of pages 2352 * that are all mapped to 0, we handle that as a special case 2353 * where the length is negative. We search in increments of 2354 * 32768 because that's the page size that MacOS uses. 2355 */ 2356 nbnumranges = 0; 2357 for (i = 0; i < NBMAXRANGES; i++) { 2358 nbphys[i] = 0; 2359 nblog[i] = 0; 2360 nblen[i] = 0; 2361 } 2362 2363 same = 0; 2364 for (addr = 0xF9000000; addr < 0xFF000000; addr += 32768) { 2365 if (!get_physical(addr, &phys)) { 2366 continue; 2367 } 2368 len = nbnumranges == 0 ? 0 : nblen[nbnumranges - 1]; 2369 2370 #ifdef __debug_mondo_verbose__ 2371 if (mac68k_machine.do_graybars) 2372 printf ("0x%lx --> 0x%lx\n", addr, phys); 2373 #endif 2374 2375 if (nbnumranges > 0 2376 && addr == nblog[nbnumranges - 1] + len 2377 && phys == nbphys[nbnumranges - 1]) { 2378 /* Same as last one */ 2379 nblen[nbnumranges - 1] += 32768; 2380 same = 1; 2381 } else { 2382 if ((nbnumranges > 0) 2383 && !same 2384 && (addr == nblog[nbnumranges - 1] + len) 2385 && (phys == nbphys[nbnumranges - 1] + len)) 2386 nblen[nbnumranges - 1] += 32768; 2387 else { 2388 if (same && 2389 nbnumranges > 0 /* XXXGCC14 */) { 2390 nblen[nbnumranges - 1] = -len; 2391 same = 0; 2392 } 2393 if (nbnumranges == NBMAXRANGES) { 2394 if (mac68k_machine.do_graybars) 2395 printf("get_mapping(): Too many NuBus ranges.\n"); 2396 break; 2397 } 2398 nbnumranges++; 2399 nblog[nbnumranges - 1] = addr; 2400 nbphys[nbnumranges - 1] = phys; 2401 nblen[nbnumranges - 1] = 32768; 2402 } 2403 } 2404 } 2405 if (same) { 2406 nblen[nbnumranges - 1] = -nblen[nbnumranges - 1]; 2407 same = 0; 2408 } 2409 if (mac68k_machine.do_graybars) { 2410 printf("Non-system RAM (nubus, etc.):\n"); 2411 for (i = 0; i < nbnumranges; i++) { 2412 printf(" Log = 0x%lx, Phys = 0x%lx, Len = 0x%lx (%lu)\n", 2413 nblog[i], nbphys[i], nblen[i], nblen[i]); 2414 } 2415 } 2416 2417 /* 2418 * We must now find the logical address of internal video in the 2419 * ranges we made above. Internal video is at physical 0, but 2420 * a lot of pages map there. Instead, we look for the logical 2421 * page that maps to 32768 and go back one page. 2422 */ 2423 for (i = 0; i < nbnumranges; i++) { 2424 if (nblen[i] > 0 2425 && nbphys[i] <= 32768 2426 && 32768 <= nbphys[i] + nblen[i]) { 2427 mac68k_video.mv_log = nblog[i] - nbphys[i]; 2428 mac68k_video.mv_len = nblen[i] + nbphys[i]; 2429 mac68k_video.mv_phys = 0; 2430 break; 2431 } 2432 } 2433 if (i == nbnumranges) { 2434 if (0x60000000 <= mac68k_video.mv_kvaddr 2435 && mac68k_video.mv_kvaddr < 0x70000000) { 2436 if (mac68k_machine.do_graybars) 2437 printf("Checking for Internal Video "); 2438 /* 2439 * Kludge for IIvx internal video (60b0 0000). 2440 * PB 520 (6000 0000) 2441 */ 2442 check_video("PB/IIvx (0x60?00000)", 2443 1 * 1024 * 1024, 1 * 1024 * 1024); 2444 } else if (0x50F40000 <= mac68k_video.mv_kvaddr 2445 && mac68k_video.mv_kvaddr < 0x50FBFFFF) { 2446 /* 2447 * Kludge for LC internal video 2448 */ 2449 check_video("LC video (0x50f40000)", 2450 512 * 1024, 512 * 1024); 2451 } else if (0x50100100 <= mac68k_video.mv_kvaddr 2452 && mac68k_video.mv_kvaddr < 0x50400000) { 2453 /* 2454 * Kludge for AV internal video 2455 */ 2456 check_video("AV video (0x50100100)", 2457 1 * 1024 * 1024, 1 * 1024 * 1024); 2458 } else { 2459 if (mac68k_machine.do_graybars) 2460 printf(" no internal video at " 2461 "address 0 -- " 2462 "mac68k_video.mv_kvaddr is " 2463 "0x%lx.\n", 2464 mac68k_video.mv_kvaddr); 2465 } 2466 } else if (mac68k_machine.do_graybars) { 2467 printf(" Video address = %p\n", 2468 (void *)mac68k_video.mv_kvaddr); 2469 printf(" Int video starts at %p\n", 2470 (void *)mac68k_video.mv_log); 2471 printf(" Length = 0x%x (%d) bytes\n", 2472 mac68k_video.mv_len, mac68k_video.mv_len); 2473 } 2474 } 2475 /* mv_len sanity check */ 2476 int reqsize = mac68k_video.mv_height * mac68k_video.mv_stride; 2477 if (mac68k_video.mv_len < reqsize) 2478 mac68k_video.mv_len = reqsize; 2479 2480 return load_addr; /* Return physical address of logical 0 */ 2481 } 2482 2483 /* 2484 * Debugging code for locore page-traversal routine. 2485 */ 2486 void printstar(void); 2487 void 2488 printstar(void) 2489 { 2490 /* 2491 * Be careful as we assume that no registers are clobbered 2492 * when we call this from assembly. 2493 */ 2494 __asm volatile ( 2495 " movl %a0,%sp@-;" 2496 " movl %a1,%sp@-;" 2497 " movl %d0,%sp@-;" 2498 " movl %d1,%sp@-"); 2499 2500 /* printf("*"); */ 2501 2502 __asm volatile ( 2503 " movl %sp@+,%d1;" 2504 " movl %sp@+,%d0;" 2505 " movl %sp@+,%a1;" 2506 " movl %sp@+,%a0"); 2507 } 2508 2509 /* 2510 * Console bell callback; modularizes the console terminal emulator 2511 * and the audio system, so neither requires direct knowledge of the 2512 * other. 2513 */ 2514 2515 void 2516 mac68k_set_bell_callback(int (*callback)(void *, int, int, int), void *cookie) 2517 { 2518 mac68k_bell_callback = callback; 2519 mac68k_bell_cookie = (void *)cookie; 2520 } 2521 2522 int 2523 mac68k_ring_bell(int freq, int length, int volume) 2524 { 2525 if (mac68k_bell_callback) 2526 return ((*mac68k_bell_callback)(mac68k_bell_cookie, 2527 freq, length, volume)); 2528 else 2529 return (ENXIO); 2530 } 2531 2532 int 2533 mm_md_physacc(paddr_t pa, vm_prot_t prot) 2534 { 2535 extern u_long last_page; 2536 2537 return (pa < last_page) ? 0 : EFAULT; 2538 } 2539 2540 void __attribute__((no_instrument_function)) 2541 pmap_machine_check_bootstrap_allocations(paddr_t nextpa, paddr_t firstpa) 2542 { 2543 int i; 2544 2545 for (i = 0; i < numranges; i++) { 2546 if (low[i] <= firstpa && firstpa < high[i]) { 2547 break; 2548 } 2549 } 2550 if (i >= numranges || nextpa > high[i]) { 2551 if (mac68k_machine.do_graybars) { 2552 printf("Failure in NetBSD boot; "); 2553 if (i < numranges) { 2554 printf("nextpa=0x%lx, high[%d]=0x%lx.\n", 2555 nextpa, i, high[i]); 2556 } else { 2557 printf("can't find kernel RAM segment.\n"); 2558 } 2559 printf("You're hosed! Try booting with 32-bit "); 2560 printf("addressing enabled in the memory control "); 2561 printf("panel.\n"); 2562 printf("Older machines may need Mode32 to get that "); 2563 printf("option.\n"); 2564 } 2565 panic("Cannot work with the current memory mappings."); 2566 } 2567 } 2568 2569 #define PMBM_IOBase 0 2570 #define PMBM_ROMBase 1 2571 #define PMBM_VIDBase 2 2572 struct pmap_bootmap machine_bootmap[] = { 2573 /* 2574 * Map the I/O region VA==PA; some of the ROM routines 2575 * have hard-coded addresses for e.g. VIA1. 2576 */ 2577 { .pmbm_vaddr = 0, /* initialized below */ 2578 .pmbm_paddr = 0, /* initialized below */ 2579 .pmbm_size = m68k_ptob(IIOMAPSIZE), 2580 .pmbm_flags = PMBM_F_FIXEDVA | PMBM_F_CI }, 2581 2582 { .pmbm_vaddr_ptr = (vaddr_t *)&ROMBase, 2583 .pmbm_paddr = 0, /* initialized below */ 2584 .pmbm_size = m68k_ptob(ROMMAPSIZE), 2585 .pmbm_flags = PMBM_F_RO }, 2586 2587 { .pmbm_vaddr_ptr = &newvideoaddr, 2588 .pmbm_paddr = 0, /* initialized below */ 2589 .pmbm_size = 0, /* initialized below */ 2590 .pmbm_flags = PMBM_F_CI }, 2591 2592 { .pmbm_vaddr = -1 }, 2593 }; 2594 2595 paddr_t bootstrap_mac68k(int); 2596 2597 paddr_t __attribute__((no_instrument_function)) 2598 bootstrap_mac68k(int tc) 2599 { 2600 #if NZSC > 0 2601 extern int zsinited; 2602 extern void zs_init(void); 2603 #endif 2604 extern int *esym; 2605 paddr_t nextpa; 2606 void *oldROMBase; 2607 char use_bootmem = 0; 2608 int i; 2609 2610 #ifdef DJMEMCMAX 2611 if(mac68k_machine.machineid == MACH_MACC650 || 2612 mac68k_machine.machineid == MACH_MACQ650 || 2613 mac68k_machine.machineid == MACH_MACQ610 || 2614 mac68k_machine.machineid == MACH_MACC610 || 2615 mac68k_machine.machineid == MACH_MACQ800) { 2616 use_bootmem = 1; 2617 } 2618 #endif 2619 2620 if (mac68k_machine.do_graybars) 2621 printf("Bootstrapping NetBSD/mac68k.\n"); 2622 2623 oldROMBase = ROMBase; 2624 mac68k_video.mv_phys = mac68k_video.mv_kvaddr; 2625 2626 if ((!use_bootmem) && (((tc & 0x80000000) && (mmutype == MMU_68030)) || 2627 ((tc & 0x8000) && (mmutype == MMU_68040)))) { 2628 if (mac68k_machine.do_graybars) 2629 printf("Getting mapping from MMU.\n"); 2630 (void) get_mapping(); 2631 if (mac68k_machine.do_graybars) 2632 printf("Done.\n"); 2633 } else { 2634 /* MMU not enabled. Fake up ranges. */ 2635 numranges = 1; 2636 low[0] = 0; 2637 high[0] = mac68k_machine.mach_memsize * (1024 * 1024); 2638 if (mac68k_machine.do_graybars) 2639 printf("Faked range to byte 0x%lx.\n", high[0]); 2640 } 2641 nextpa = load_addr + m68k_round_page(esym); 2642 2643 if (mac68k_machine.do_graybars) 2644 printf("Bootstrapping the pmap system.\n"); 2645 2646 vidlen = m68k_round_page(mac68k_video.mv_height * 2647 mac68k_video.mv_stride + m68k_page_offset(mac68k_video.mv_phys)); 2648 2649 /* Sum up the memory for pmap_bootstrap1(). */ 2650 vsize_t mem_size = 0; 2651 for (i = 0; i < numranges; i++) 2652 mem_size += high[i] - low[i]; 2653 physmem = m68k_btop(mem_size); 2654 2655 #ifdef __HAVE_NEW_PMAP_68K 2656 /* Initialize machine_bootmap[] for pmap_bootstrap1(). */ 2657 machine_bootmap[PMBM_IOBase].pmbm_vaddr = (vaddr_t)IOBase; 2658 machine_bootmap[PMBM_IOBase].pmbm_paddr = (paddr_t)IOBase; 2659 machine_bootmap[PMBM_ROMBase].pmbm_paddr = (paddr_t)ROMBase; 2660 machine_bootmap[PMBM_VIDBase].pmbm_paddr = 2661 m68k_trunc_page(mac68k_video.mv_phys); 2662 machine_bootmap[PMBM_VIDBase].pmbm_size = vidlen; 2663 #endif 2664 2665 nextpa = pmap_bootstrap1(nextpa, load_addr); 2666 2667 #ifdef __HAVE_NEW_PMAP_68K 2668 /* 2669 * machine_bootmap[] deals in whole pages; fixup newvideoaddr to 2670 * include the page offset. 2671 */ 2672 if (vidlen) { 2673 newvideoaddr += m68k_page_offset(mac68k_video.mv_phys); 2674 } 2675 #endif 2676 2677 /* 2678 * VM data structures are now initialized, set up data for 2679 * the pmap module. 2680 * 2681 * Note about avail_end: msgbuf is initialized just after 2682 * avail_end in machdep.c. Since the last page is used 2683 * for rebooting the system (code is copied there and 2684 * execution continues from copied code before the MMU 2685 * is disabled), the msgbuf will get trounced between 2686 * reboots if it's placed in the last physical page. 2687 * To work around this, we move avail_end back one more 2688 * page so the msgbuf can be preserved. 2689 */ 2690 avail_start = m68k_round_page(nextpa); 2691 last_page = high[numranges - 1] - m68k_ptob(1); 2692 #if NAUDIO > 0 2693 /* 2694 * Reduce high by an extra 7 pages which are used by the EASC on some 2695 * machines. last_page is unchanged as the last page can still be 2696 * safetly used to reboot the system. 2697 */ 2698 high[numranges - 1] -= (m68k_round_page(MSGBUFSIZE) + m68k_ptob(8)); 2699 #else 2700 high[numranges - 1] -= (m68k_round_page(MSGBUFSIZE) + m68k_ptob(1)); 2701 #endif 2702 avail_end = high[numranges - 1]; 2703 2704 if (mac68k_machine.do_graybars) 2705 printf("Pmap bootstrapped.\n"); 2706 2707 if (!vidlen) 2708 panic("Don't know how to relocate video!"); 2709 2710 if (mac68k_machine.do_graybars) 2711 printf("Moving ROMBase from %p to %p.\n", oldROMBase, ROMBase); 2712 2713 mrg_fixupROMBase(oldROMBase, ROMBase); 2714 2715 if (mac68k_machine.do_graybars) 2716 printf("Video address %p -> %p.\n", 2717 (void *)mac68k_video.mv_kvaddr, (void *)newvideoaddr); 2718 2719 mac68k_set_io_offsets(IOBase); 2720 2721 /* 2722 * If the serial ports are going (for console or 'echo'), then 2723 * we need to make sure the IO change gets propagated properly. 2724 * This resets the base addresses for the 8530 (serial) driver. 2725 * 2726 * WARNING!!! No printfs() (etc) BETWEEN zs_init() and the end 2727 * of this function (where we start using the MMU, so the new 2728 * address is correct. 2729 */ 2730 #if NZSC > 0 2731 if (zsinited != 0) 2732 zs_init(); 2733 #endif 2734 2735 mac68k_video.mv_kvaddr = newvideoaddr; 2736 2737 return nextpa; 2738 } 2739