Annotation of sys/arch/mac68k/mac68k/machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: machdep.c,v 1.142 2007/07/29 21:24:05 miod Exp $ */
! 2: /* $NetBSD: machdep.c,v 1.207 1998/07/08 04:39:34 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1988 University of Utah.
! 6: * Copyright (c) 1982, 1990 The Regents of the University of California.
! 7: * All rights reserved.
! 8: *
! 9: * This code is derived from software contributed to Berkeley by
! 10: * the Systems Programming Group of the University of Utah Computer
! 11: * Science Department.
! 12: *
! 13: * Redistribution and use in source and binary forms, with or without
! 14: * modification, are permitted provided that the following conditions
! 15: * are met:
! 16: * 1. Redistributions of source code must retain the above copyright
! 17: * notice, this list of conditions and the following disclaimer.
! 18: * 2. Redistributions in binary form must reproduce the above copyright
! 19: * notice, this list of conditions and the following disclaimer in the
! 20: * documentation and/or other materials provided with the distribution.
! 21: * 3. Neither the name of the University nor the names of its contributors
! 22: * may be used to endorse or promote products derived from this software
! 23: * without specific prior written permission.
! 24: *
! 25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 35: * SUCH DAMAGE.
! 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/param.h>
! 77: #include <sys/systm.h>
! 78: #include <sys/signalvar.h>
! 79: #include <sys/kernel.h>
! 80: #include <sys/proc.h>
! 81: #include <sys/buf.h>
! 82: #include <sys/exec.h>
! 83: #include <sys/core.h>
! 84: #include <sys/kcore.h>
! 85: #include <sys/vnode.h>
! 86: #include <sys/reboot.h>
! 87: #include <sys/conf.h>
! 88: #include <sys/file.h>
! 89: #include <sys/timeout.h>
! 90: #include <sys/malloc.h>
! 91: #include <sys/mbuf.h>
! 92: #include <sys/msgbuf.h>
! 93: #include <sys/user.h>
! 94: #include <sys/mount.h>
! 95: #include <sys/extent.h>
! 96: #include <sys/syscallargs.h>
! 97: #ifdef SYSVMSG
! 98: #include <sys/msg.h>
! 99: #endif
! 100:
! 101: #include <machine/db_machdep.h>
! 102: #include <ddb/db_sym.h>
! 103: #include <ddb/db_extern.h>
! 104: #include <ddb/db_var.h>
! 105:
! 106: #include <machine/autoconf.h>
! 107: #include <machine/cpu.h>
! 108: #include <machine/reg.h>
! 109: #include <machine/psl.h>
! 110: #include <machine/pte.h>
! 111: #include <machine/kcore.h>
! 112: #include <machine/bus.h>
! 113: #include <machine/pmap.h>
! 114:
! 115: #include <uvm/uvm_extern.h>
! 116:
! 117: #include <sys/sysctl.h>
! 118:
! 119: #include <dev/cons.h>
! 120: #include <mac68k/dev/adbvar.h>
! 121:
! 122: #include <machine/iop.h>
! 123: #include <machine/psc.h>
! 124: #include <machine/viareg.h>
! 125:
! 126: #include "wsdisplay.h"
! 127:
! 128: /* The following is used externally (sysctl_hw) */
! 129: char machine[] = MACHINE; /* from <machine/param.h> */
! 130:
! 131: struct mac68k_machine_S mac68k_machine;
! 132:
! 133: volatile u_char *Via1Base, *Via2Base, *PSCBase = NULL;
! 134: u_long NuBusBase = NBBASE;
! 135: u_long IOBase;
! 136:
! 137: vaddr_t SCSIBase;
! 138:
! 139: /* These are used to map kernel space: */
! 140: extern int numranges;
! 141: extern u_long low[8];
! 142: extern u_long high[8];
! 143:
! 144: /* These are used to map NuBus space: */
! 145: #define NBMAXRANGES 16
! 146: int nbnumranges; /* = 0 == don't use the ranges */
! 147: u_long nbphys[NBMAXRANGES]; /* Start physical addr of this range */
! 148: u_long nblog[NBMAXRANGES]; /* Start logical addr of this range */
! 149: long nblen[NBMAXRANGES]; /* Length of this range If the length is */
! 150: /* negative, all phys addrs are the same. */
! 151:
! 152: /* From Booter via locore */
! 153: long videoaddr; /* Addr used in kernel for video. */
! 154: long videorowbytes; /* Used in kernel for video. */
! 155: long videobitdepth; /* Number of bihs per pixel */
! 156: u_long videosize; /* height = 31:16, width 15:0 */
! 157:
! 158: /*
! 159: * Values for IIvx-like internal video
! 160: * -- should be zero if it is not used (usual case).
! 161: */
! 162: u_int32_t mac68k_vidlog; /* logical addr */
! 163: u_int32_t mac68k_vidphys; /* physical addr */
! 164: u_int32_t mac68k_vidlen; /* mem length */
! 165:
! 166: /* Callback and cookie to run bell */
! 167: int (*mac68k_bell_callback)(void *, int, int, int);
! 168: caddr_t mac68k_bell_cookie;
! 169:
! 170: struct vm_map *exec_map = NULL;
! 171: struct vm_map *phys_map = NULL;
! 172:
! 173: /*
! 174: * Declare these as initialized data so we can patch them.
! 175: */
! 176: #ifndef BUFCACHEPERCENT
! 177: #define BUFCACHEPERCENT 5
! 178: #endif
! 179:
! 180: #ifdef BUFPAGES
! 181: int bufpages = BUFPAGES;
! 182: #else
! 183: int bufpages = 0;
! 184: #endif
! 185: int bufcachepercent = BUFCACHEPERCENT;
! 186:
! 187: int physmem; /* size of physical memory, in pages */
! 188:
! 189: /*
! 190: * safepri is a safe priority for sleep to set for a spin-wait
! 191: * during autoconfiguration or after a panic.
! 192: */
! 193: int safepri = PSL_LOWIPL;
! 194:
! 195: /*
! 196: * Extent maps to manage all memory space, including I/O ranges. Allocate
! 197: * storage for 8 regions in each, initially. Later, iomem_malloc_safe
! 198: * will indicate that it's safe to use malloc() to dynamically allocate
! 199: * region descriptors.
! 200: *
! 201: * The extent maps are not static! Machine-dependent NuBus and on-board
! 202: * I/O routines need access to them for bus address space allocation.
! 203: */
! 204: long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
! 205: struct extent *iomem_ex;
! 206: int iomem_malloc_safe;
! 207:
! 208: /* XXX should be in locore.s for consistency */
! 209: int astpending = 0;
! 210:
! 211: void identifycpu(void);
! 212: u_long get_physical(u_int, u_long *);
! 213:
! 214: caddr_t allocsys(caddr_t);
! 215: void initcpu(void);
! 216: int cpu_dumpsize(void);
! 217: int cpu_dump(int (*)(dev_t, daddr64_t, caddr_t, size_t), daddr64_t *);
! 218: void cpu_init_kcore_hdr(void);
! 219: int fpu_probe(void);
! 220:
! 221: /* functions called from locore.s */
! 222: void dumpsys(void);
! 223: void mac68k_init(void);
! 224: void straytrap(int, int);
! 225: void nmihand(struct frame);
! 226:
! 227: /*
! 228: * Machine-dependent crash dump header info.
! 229: */
! 230: cpu_kcore_hdr_t cpu_kcore_hdr;
! 231:
! 232: /*
! 233: * Early initialization, before main() is called.
! 234: */
! 235: void
! 236: mac68k_init()
! 237: {
! 238: int i;
! 239: extern vaddr_t avail_start;
! 240:
! 241: /*
! 242: * Tell the VM system about available physical memory.
! 243: * Notice that we don't need to worry about avail_end here
! 244: * since it's equal to high[numranges-1].
! 245: */
! 246: for (i = 0; i < numranges; i++) {
! 247: if (low[i] <= avail_start && avail_start < high[i])
! 248: uvm_page_physload(atop(avail_start), atop(high[i]),
! 249: atop(avail_start), atop(high[i]),
! 250: VM_FREELIST_DEFAULT);
! 251: else
! 252: uvm_page_physload(atop(low[i]), atop(high[i]),
! 253: atop(low[i]), atop(high[i]),
! 254: VM_FREELIST_DEFAULT);
! 255: }
! 256:
! 257: /*
! 258: * Initialize the I/O mem extent map.
! 259: * Note: we don't have to check the return value since
! 260: * creation of a fixed extent map will never fail (since
! 261: * descriptor storage has already been allocated).
! 262: *
! 263: * N.B. The iomem extent manages _all_ physical addresses
! 264: * on the machine. When the amount of RAM is found, all
! 265: * extents of RAM are allocated from the map.
! 266: */
! 267: iomem_ex = extent_create("iomem", 0x0, 0xffffffff, M_DEVBUF,
! 268: (caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
! 269: EX_NOCOALESCE|EX_NOWAIT);
! 270:
! 271: /* Initialize the interrupt handlers. */
! 272: intr_init();
! 273:
! 274: /* Initialize the VIAs */
! 275: via_init();
! 276:
! 277: /* Initialize the PSC (if present) */
! 278: psc_init();
! 279: }
! 280:
! 281: /*
! 282: * Console initialization: called early on from main,
! 283: * before vm init or startup. Do enough configuration
! 284: * to choose and initialize a console.
! 285: */
! 286: void
! 287: consinit(void)
! 288: {
! 289: /*
! 290: * Generic console: sys/dev/cons.c
! 291: * Initializes either ite or ser as console.
! 292: * Can be called from locore.s and init_main.c. (Ugh.)
! 293: */
! 294: static int init; /* = 0 */
! 295:
! 296: if (!init) {
! 297: cninit();
! 298: #ifdef DDB
! 299: /*
! 300: * Initialize kernel debugger, if compiled in.
! 301: */
! 302: ddb_init();
! 303: #endif
! 304: init = 1;
! 305: } else {
! 306: #if NWSDISPLAY > 0
! 307: /*
! 308: * XXX This is an evil hack on top of an evil hack!
! 309: *
! 310: * With the graybar stuff, we've got a catch-22: we need
! 311: * to do at least some console setup really early on, even
! 312: * before we're running with the mappings we need. On
! 313: * the other hand, we're not nearly ready to do anything
! 314: * with wscons or the ADB driver at that point.
! 315: *
! 316: * To get around this, wscninit() ignores the first call
! 317: * it gets (from cninit(), if not on a serial console).
! 318: * Once we're here, we call wscninit() again, which sets
! 319: * up the console devices and does the appropriate wscons
! 320: * initialization.
! 321: */
! 322: if (mac68k_machine.serial_console == 0) {
! 323: cons_decl(ws);
! 324: wscninit(NULL);
! 325: }
! 326: #endif
! 327:
! 328: mac68k_calibrate_delay();
! 329:
! 330: #if NZSC > 0 && defined(KGDB)
! 331: zs_kgdb_init();
! 332: #endif
! 333:
! 334: if (boothowto & RB_KDB) {
! 335: #ifdef KGDB
! 336: /* XXX - Ask on console for kgdb_dev? */
! 337: /* Note: this will just return if kgdb_dev==NODEV */
! 338: kgdb_connect(1);
! 339: #else /* KGDB */
! 340: #ifdef DDB
! 341: /* Enter DDB. We don't have a monitor PROM. */
! 342: Debugger();
! 343: #endif /* DDB */
! 344: #endif /* KGDB */
! 345: }
! 346: }
! 347: }
! 348:
! 349: #define CURRENTBOOTERVER 111
! 350:
! 351: /*
! 352: * cpu_startup: allocate memory for variable-sized tables,
! 353: * initialize cpu, and do autoconfiguration.
! 354: */
! 355: void
! 356: cpu_startup(void)
! 357: {
! 358: caddr_t v;
! 359: unsigned i;
! 360: int vers;
! 361: vaddr_t minaddr, maxaddr;
! 362: vsize_t size = 0; /* To avoid compiler warning */
! 363: int delay;
! 364:
! 365: /*
! 366: * Initialize the kernel crash dump header.
! 367: */
! 368: cpu_init_kcore_hdr();
! 369:
! 370: /*
! 371: * Initialize error message buffer (at end of core).
! 372: * high[numranges-1] was decremented in pmap_bootstrap.
! 373: */
! 374: for (i = 0; i < btoc(MSGBUFSIZE); i++)
! 375: pmap_enter(pmap_kernel(), (vaddr_t)msgbufp + i * NBPG,
! 376: high[numranges - 1] + i * NBPG,
! 377: VM_PROT_READ|VM_PROT_WRITE,
! 378: VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
! 379: pmap_update(pmap_kernel());
! 380: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
! 381:
! 382: /*
! 383: * Good {morning,afternoon,evening,night}.
! 384: */
! 385: printf(version);
! 386: identifycpu();
! 387:
! 388: vers = mac68k_machine.booter_version;
! 389: if (vers < CURRENTBOOTERVER) {
! 390: /* fix older booters with indices, not versions */
! 391: if (vers < 100)
! 392: vers += 99;
! 393:
! 394: printf("\nYou booted with booter version %d.%d.\n",
! 395: vers / 100, vers % 100);
! 396: printf("Booter version %d.%d is necessary to fully support\n",
! 397: CURRENTBOOTERVER / 100, CURRENTBOOTERVER % 100);
! 398: printf("this kernel.\n\n");
! 399: for (delay = 0; delay < 1000000; delay++);
! 400: }
! 401: printf("real mem = %u (%uMB)\n", ctob(physmem),
! 402: ctob(physmem)/1024/1024);
! 403:
! 404: /*
! 405: * Find out how much space we need, allocate it,
! 406: * and then give everything true virtual addressses.
! 407: */
! 408: size = (vsize_t)allocsys((caddr_t)0);
! 409: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(size))) == 0)
! 410: panic("startup: no room for tables");
! 411: if ((allocsys(v) - v) != size)
! 412: panic("startup: table size inconsistency");
! 413:
! 414: /*
! 415: * Determine how many buffers to allocate.
! 416: * We allocate bufcachepercent% of memory for buffer space.
! 417: */
! 418: if (bufpages == 0)
! 419: bufpages = physmem * bufcachepercent / 100;
! 420:
! 421: /* Restrict to at most 25% filled kvm */
! 422: if (bufpages >
! 423: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 424: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 425: PAGE_SIZE / 4;
! 426:
! 427: /*
! 428: * Allocate a submap for exec arguments. This map effectively
! 429: * limits the number of processes exec'ing at any time.
! 430: */
! 431: minaddr = vm_map_min(kernel_map);
! 432: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 433: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 434:
! 435: /*
! 436: * Allocate a submap for physio
! 437: */
! 438: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 439: VM_PHYS_SIZE, 0, FALSE, NULL);
! 440:
! 441: printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
! 442: ptoa(uvmexp.free) / 1024 / 1024);
! 443:
! 444: /*
! 445: * Set up CPU-specific registers, cache, etc.
! 446: */
! 447: initcpu();
! 448:
! 449: /*
! 450: * Set up buffers, so they can be used to read disk labels.
! 451: */
! 452: bufinit();
! 453:
! 454: /*
! 455: * Configure the system.
! 456: */
! 457: if (boothowto & RB_CONFIG) {
! 458: #ifdef BOOT_CONFIG
! 459: user_config();
! 460: #else
! 461: printf("kernel does not support -c; continuing..\n");
! 462: #endif
! 463: }
! 464:
! 465: /* Safe for extent allocation to use malloc now. */
! 466: iomem_malloc_safe = 1;
! 467: }
! 468:
! 469: /*
! 470: * Allocate space for system data structures. We are given
! 471: * a starting virtual address and we return a final virtual
! 472: * address; along the way we set each data structure pointer.
! 473: *
! 474: * We call allocsys() with 0 to find out how much space we want,
! 475: * allocate that much and fill it with zeroes, and then call
! 476: * allocsys() again with the correct base virtual address.
! 477: */
! 478: caddr_t
! 479: allocsys(v)
! 480: caddr_t v;
! 481: {
! 482:
! 483: #define valloc(name, type, num) \
! 484: (name) = (type *)v; v = (caddr_t)((name)+(num))
! 485: #define valloclim(name, type, num, lim) \
! 486: (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
! 487:
! 488: #ifdef SYSVMSG
! 489: valloc(msgpool, char, msginfo.msgmax);
! 490: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 491: valloc(msghdrs, struct msg, msginfo.msgtql);
! 492: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 493: #endif
! 494:
! 495: return (v);
! 496: }
! 497:
! 498: void
! 499: initcpu()
! 500: {
! 501: #if defined(M68040)
! 502: extern void (*vectab[256])(void);
! 503: void addrerr4060(void);
! 504: #endif
! 505: #ifdef M68040
! 506: void buserr40(void);
! 507: #endif
! 508: #ifdef FPSP
! 509: extern u_long fpvect_tab, fpvect_end, fpsp_tab;
! 510: #endif
! 511:
! 512: switch (cputype) {
! 513: #ifdef M68040
! 514: case CPU_68040:
! 515: vectab[2] = buserr40;
! 516: vectab[3] = addrerr4060;
! 517: #ifdef FPSP
! 518: bcopy(&fpsp_tab, &fpvect_tab,
! 519: (&fpvect_end - &fpvect_tab) * sizeof (fpvect_tab));
! 520: #endif
! 521: break;
! 522: #endif
! 523: default:
! 524: break;
! 525: }
! 526:
! 527: DCIS();
! 528: }
! 529:
! 530: void doboot(void)
! 531: __attribute__((__noreturn__));
! 532:
! 533: int waittime = -1;
! 534:
! 535: void
! 536: boot(howto)
! 537: int howto;
! 538: {
! 539: extern u_long maxaddr;
! 540:
! 541: /* take a snap shot before clobbering any registers */
! 542: if (curproc && curproc->p_addr)
! 543: savectx(&curproc->p_addr->u_pcb);
! 544:
! 545: /* If system is cold, just halt. */
! 546: if (cold) {
! 547: /* (Unless the user explicitly asked for reboot.) */
! 548: if ((howto & RB_USERREQ) == 0)
! 549: howto |= RB_HALT;
! 550: goto haltsys;
! 551: }
! 552:
! 553: boothowto = howto;
! 554: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
! 555: waittime = 0;
! 556: vfs_shutdown();
! 557:
! 558: if (mac68k_machine.aux_interrupts != 0) {
! 559: /*
! 560: * If we've been adjusting the clock, the todr
! 561: * will be out of synch; adjust it now unless
! 562: * the system was sitting in ddb.
! 563: */
! 564: if ((howto & RB_TIMEBAD) == 0) {
! 565: resettodr();
! 566: } else {
! 567: printf("WARNING: not updating battery clock\n");
! 568: }
! 569: } else {
! 570: #ifdef DIAGNOSTIC
! 571: printf("OpenBSD/mac68k does not trust itself to update"
! 572: " the clock on shutdown on this machine.\n");
! 573: #endif
! 574: }
! 575: }
! 576:
! 577: /* Disable interrupts. */
! 578: splhigh();
! 579:
! 580: /* If rebooting and a dump is requested, do it. */
! 581: if (howto & RB_DUMP) {
! 582: dumpsys();
! 583: }
! 584:
! 585: haltsys:
! 586: /* Run any shutdown hooks. */
! 587: doshutdownhooks();
! 588:
! 589: if (howto & RB_HALT) {
! 590: if (howto & RB_POWERDOWN) {
! 591: printf("\nAttempting to power down...\n");
! 592: via_powerdown();
! 593: /*
! 594: * Shut down machines whose power functions
! 595: * are accessed via modified ADB calls.
! 596: */
! 597: adb_poweroff();
! 598: }
! 599: printf("\nThe operating system has halted.\n");
! 600: printf("Please press any key to reboot.\n\n");
! 601: (void)cngetc();
! 602: }
! 603:
! 604: /* Map the last physical page VA = PA for doboot() */
! 605: pmap_enter(pmap_kernel(), (vaddr_t)maxaddr, (vaddr_t)maxaddr,
! 606: VM_PROT_ALL, VM_PROT_ALL|PMAP_WIRED);
! 607: pmap_update(pmap_kernel());
! 608:
! 609: printf("rebooting...\n");
! 610: DELAY(1000000);
! 611: doboot();
! 612: /* NOTREACHED */
! 613: }
! 614:
! 615: /*
! 616: * Initialize the kernel crash dump header.
! 617: */
! 618: void
! 619: cpu_init_kcore_hdr()
! 620: {
! 621: cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
! 622: int i;
! 623:
! 624: bzero(&cpu_kcore_hdr, sizeof(cpu_kcore_hdr));
! 625:
! 626: h->mmutype = mmutype;
! 627: h->kernel_pa = low[0];
! 628: h->sysseg_pa = pmap_kernel()->pm_stpa;
! 629:
! 630: /*
! 631: * mac68k has multiple RAM segments on some models.
! 632: */
! 633: for (i = 0; i < numranges; i++) {
! 634: h->ram_segs[i].start = low[i];
! 635: h->ram_segs[i].size = high[i] - low[i];
! 636: }
! 637: }
! 638:
! 639: /*
! 640: * Compute the size of the machine-dependent crash dump header.
! 641: * Returns size in disk blocks.
! 642: */
! 643: int
! 644: cpu_dumpsize()
! 645: {
! 646: int size;
! 647:
! 648: size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t));
! 649: return (btodb(roundup(size, dbtob(1))));
! 650: }
! 651:
! 652: /*
! 653: * Called by dumpsys() to dump the machine-dependent header.
! 654: */
! 655: int
! 656: cpu_dump(dump, blknop)
! 657: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 658: daddr64_t *blknop;
! 659: {
! 660: int buf[dbtob(1) / sizeof(int)];
! 661: cpu_kcore_hdr_t *chdr;
! 662: kcore_seg_t *kseg;
! 663: int error;
! 664:
! 665: kseg = (kcore_seg_t *)buf;
! 666: chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
! 667: sizeof(int)];
! 668:
! 669: /* Create the segment header. */
! 670: CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
! 671: kseg->c_size = dbtob(1) - ALIGN(sizeof(kcore_seg_t));
! 672:
! 673: bcopy(&cpu_kcore_hdr, chdr, sizeof(cpu_kcore_hdr_t));
! 674: error = (*dump)(dumpdev, *blknop, (caddr_t)buf, sizeof(buf));
! 675: *blknop += btodb(sizeof(buf));
! 676: return (error);
! 677: }
! 678:
! 679: /*
! 680: * These variables are needed by /sbin/savecore
! 681: */
! 682: u_long dumpmag = 0x8fca0101; /* magic number */
! 683: int dumpsize = 0; /* pages */
! 684: long dumplo = 0; /* blocks */
! 685:
! 686: /*
! 687: * This is called by main to set dumplo and dumpsize.
! 688: * Dumps always skip the first block of disk space in
! 689: * case there might be a disk label stored there. If there
! 690: * is extra space, put dump at the end to reduce the chance
! 691: * that swapping trashes it.
! 692: */
! 693: void
! 694: dumpconf(void)
! 695: {
! 696: cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
! 697: int nblks; /* size of dump area */
! 698: int i;
! 699:
! 700: if (dumpdev == NODEV ||
! 701: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
! 702: return;
! 703: if (nblks <= ctod(1))
! 704: return;
! 705:
! 706: dumpsize = 0;
! 707: for (i = 0; h->ram_segs[i].size && i < NPHYS_RAM_SEGS; i++)
! 708: dumpsize += btoc(h->ram_segs[i].size);
! 709: dumpsize += cpu_dumpsize();
! 710:
! 711: /* Always skip the first block, in case there is a label there. */
! 712: if (dumplo < ctod(1))
! 713: dumplo = ctod(1);
! 714:
! 715: /* Put dump at end of partition, and make it fit. */
! 716: if (dumpsize > dtoc(nblks - dumplo))
! 717: dumpsize = dtoc(nblks - dumplo);
! 718: if (dumplo < nblks - ctod(dumpsize))
! 719: dumplo = nblks - ctod(dumpsize);
! 720: }
! 721:
! 722: void
! 723: dumpsys()
! 724: {
! 725: cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
! 726: daddr64_t blkno; /* current block to write */
! 727: /* dump routine */
! 728: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
! 729: int pg; /* page being dumped */
! 730: vaddr_t maddr; /* PA being dumped */
! 731: int seg; /* RAM segment being dumped */
! 732: int error; /* error code from (*dump)() */
! 733: extern int msgbufmapped;
! 734:
! 735: /* XXX initialized here because of gcc lossage */
! 736: seg = 0;
! 737: maddr = h->ram_segs[seg].start;
! 738: pg = 0;
! 739:
! 740: /* Don't record dump msgs in msgbuf. */
! 741: msgbufmapped = 0;
! 742:
! 743: /* Make sure dump device is valid. */
! 744: if (dumpdev == NODEV)
! 745: return;
! 746: if (dumpsize == 0) {
! 747: dumpconf();
! 748: if (dumpsize == 0)
! 749: return;
! 750: }
! 751: if (dumplo <= 0) {
! 752: printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
! 753: minor(dumpdev));
! 754: return;
! 755: }
! 756: dump = bdevsw[major(dumpdev)].d_dump;
! 757: blkno = dumplo;
! 758:
! 759: printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
! 760: minor(dumpdev), dumplo);
! 761:
! 762: printf("dump ");
! 763:
! 764: /* Write the dump header. */
! 765: error = cpu_dump(dump, &blkno);
! 766: if (error)
! 767: goto bad;
! 768:
! 769: for (pg = 0; pg < dumpsize; pg++) {
! 770: #define NPGMB (1024*1024/NBPG)
! 771: /* print out how many MBs we have dumped */
! 772: if (pg && (pg % NPGMB) == 0)
! 773: printf("%d ", pg / NPGMB);
! 774: #undef NPGMB
! 775: while (maddr >=
! 776: (h->ram_segs[seg].start + h->ram_segs[seg].size)) {
! 777: if (++seg >= NPHYS_RAM_SEGS ||
! 778: h->ram_segs[seg].size == 0) {
! 779: error = EINVAL; /* XXX ?? */
! 780: goto bad;
! 781: }
! 782: maddr = h->ram_segs[seg].start;
! 783: }
! 784: pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
! 785: VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
! 786: pmap_update(pmap_kernel());
! 787:
! 788: error = (*dump)(dumpdev, blkno, vmmap, NBPG);
! 789: bad:
! 790: switch (error) {
! 791: case 0:
! 792: maddr += NBPG;
! 793: blkno += btodb(NBPG);
! 794: break;
! 795:
! 796: case ENXIO:
! 797: printf("device bad\n");
! 798: return;
! 799:
! 800: case EFAULT:
! 801: printf("device not ready\n");
! 802: return;
! 803:
! 804: case EINVAL:
! 805: printf("area improper\n");
! 806: return;
! 807:
! 808: case EIO:
! 809: printf("i/o error\n");
! 810: return;
! 811:
! 812: case EINTR:
! 813: printf("aborted from console\n");
! 814: return;
! 815:
! 816: default:
! 817: printf("error %d\n", error);
! 818: return;
! 819: }
! 820: }
! 821: printf("succeeded\n");
! 822: }
! 823:
! 824: /*
! 825: * Return the best possible estimate of the time in the timeval
! 826: * to which tvp points. We do this by returning the current time
! 827: * plus the amount of time since the last clock interrupt (clock.c:clkread).
! 828: *
! 829: * Check that this time is no less than any previously-reported time,
! 830: * which could happen around the time of a clock adjustment. Just for fun,
! 831: * we guarantee that the time will be greater than the value obtained by a
! 832: * previous call.
! 833: */
! 834: void
! 835: microtime(tvp)
! 836: register struct timeval *tvp;
! 837: {
! 838: int s = splhigh();
! 839: static struct timeval lasttime;
! 840:
! 841: *tvp = time;
! 842: tvp->tv_usec += clkread();
! 843: while (tvp->tv_usec >= 1000000) {
! 844: tvp->tv_sec++;
! 845: tvp->tv_usec -= 1000000;
! 846: }
! 847: if (tvp->tv_sec == lasttime.tv_sec &&
! 848: tvp->tv_usec <= lasttime.tv_usec &&
! 849: (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
! 850: tvp->tv_sec++;
! 851: tvp->tv_usec -= 1000000;
! 852: }
! 853: lasttime = *tvp;
! 854: splx(s);
! 855: }
! 856:
! 857: void
! 858: straytrap(pc, evec)
! 859: int pc;
! 860: int evec;
! 861: {
! 862: printf("unexpected trap; vector offset 0x%x from 0x%x.\n",
! 863: (int) (evec & 0xfff), pc);
! 864: #ifdef DEBUG
! 865: #ifdef DDB
! 866: Debugger();
! 867: #endif
! 868: #endif
! 869: }
! 870:
! 871: int *nofault;
! 872:
! 873: /*
! 874: * Level 7 interrupts can be caused by the keyboard or parity errors.
! 875: */
! 876: void nmihand(struct frame);
! 877:
! 878: void
! 879: nmihand(frame)
! 880: struct frame frame;
! 881: {
! 882: static int nmihanddeep = 0;
! 883:
! 884: if (nmihanddeep)
! 885: return;
! 886: nmihanddeep = 1;
! 887:
! 888: #ifdef DDB
! 889: if (db_console)
! 890: Debugger();
! 891: #endif
! 892:
! 893: nmihanddeep = 0;
! 894: }
! 895:
! 896: /*
! 897: * It should be possible to probe for the top of RAM, but Apple has
! 898: * memory structured so that in at least some cases, it's possible
! 899: * for RAM to be aliased across all memory--or for it to appear that
! 900: * there is more RAM than there really is.
! 901: */
! 902: int get_top_of_ram(void);
! 903:
! 904: int
! 905: get_top_of_ram()
! 906: {
! 907: return ((mac68k_machine.mach_memsize * (1024 * 1024)) - 4096);
! 908: }
! 909:
! 910: /*
! 911: * machine dependent system variables.
! 912: */
! 913: int
! 914: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 915: int *name;
! 916: u_int namelen;
! 917: void *oldp;
! 918: size_t *oldlenp;
! 919: void *newp;
! 920: size_t newlen;
! 921: struct proc *p;
! 922: {
! 923: dev_t consdev;
! 924:
! 925: /* all sysctl names at this level are terminal */
! 926: if (namelen != 1)
! 927: return (ENOTDIR); /* overloaded */
! 928:
! 929: switch (name[0]) {
! 930: case CPU_CONSDEV:
! 931: if (cn_tab != NULL)
! 932: consdev = cn_tab->cn_dev;
! 933: else
! 934: consdev = NODEV;
! 935: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
! 936: sizeof consdev));
! 937: default:
! 938: return (EOPNOTSUPP);
! 939: }
! 940: /* NOTREACHED */
! 941: }
! 942:
! 943: int
! 944: cpu_exec_aout_makecmds(p, epp)
! 945: struct proc *p;
! 946: struct exec_package *epp;
! 947: {
! 948: int error = ENOEXEC;
! 949:
! 950: #ifdef COMPAT_SUNOS
! 951: {
! 952: extern int sunos_exec_aout_makecmds(struct proc *,
! 953: struct exec_package *);
! 954: if ((error = sunos_exec_aout_makecmds(p, epp)) == 0)
! 955: return 0;
! 956: }
! 957: #endif
! 958: return error;
! 959: }
! 960:
! 961: static char *envbuf = NULL;
! 962:
! 963: /*
! 964: * getenvvars: Grab a few useful variables
! 965: */
! 966: void getenvvars(u_long, char *);
! 967: long getenv(char *);
! 968:
! 969: void
! 970: getenvvars(flag, buf)
! 971: u_long flag;
! 972: char *buf;
! 973: {
! 974: extern u_long bootdev;
! 975: #if defined(DDB) || NKSYMS > 0
! 976: extern u_long end, esym;
! 977: #endif
! 978: extern u_long macos_boottime;
! 979: extern vaddr_t MacOSROMBase;
! 980: extern long macos_gmtbias;
! 981: extern u_short ADBDelay;
! 982: extern u_int32_t HwCfgFlags3;
! 983: int root_scsi_id;
! 984: vaddr_t ROMBase;
! 985:
! 986: /*
! 987: * If flag & 0x80000000 == 0, then we're booting with the old booter
! 988: * and we should freak out.
! 989: */
! 990: if ((flag & 0x80000000) == 0) {
! 991: /* Freak out; print something if that becomes available */
! 992: } else
! 993: envbuf = buf;
! 994:
! 995: /* These next two should give us mapped video & serial */
! 996: /* We need these for pre-mapping graybars & echo, but probably */
! 997: /* only on MacII or LC. -- XXX */
! 998: /* videoaddr = getenv("MACOS_VIDEO"); */
! 999:
! 1000: /*
! 1001: * The following are not in a structure so that they can be
! 1002: * accessed more quickly.
! 1003: */
! 1004: videoaddr = getenv("VIDEO_ADDR");
! 1005: videorowbytes = getenv("ROW_BYTES");
! 1006: videobitdepth = getenv("SCREEN_DEPTH");
! 1007: videosize = getenv("DIMENSIONS");
! 1008:
! 1009: /*
! 1010: * More misc stuff from booter.
! 1011: */
! 1012: mac68k_machine.machineid = getenv("MACHINEID");
! 1013: mac68k_machine.mach_memsize = getenv("MEMSIZE");
! 1014: mac68k_machine.do_graybars = getenv("GRAYBARS");
! 1015: mac68k_machine.serial_boot_echo = getenv("SERIALECHO");
! 1016: mac68k_machine.serial_console = getenv("SERIALCONSOLE");
! 1017:
! 1018: mac68k_machine.modem_flags = getenv("SERIAL_MODEM_FLAGS");
! 1019: mac68k_machine.modem_cts_clk = getenv("SERIAL_MODEM_HSKICLK");
! 1020: mac68k_machine.modem_dcd_clk = getenv("SERIAL_MODEM_GPICLK");
! 1021: mac68k_machine.modem_flags = getenv("SERIAL_MODEM_DSPEED");
! 1022: mac68k_machine.print_flags = getenv("SERIAL_PRINT_FLAGS");
! 1023: mac68k_machine.print_cts_clk = getenv("SERIAL_PRINT_HSKICLK");
! 1024: mac68k_machine.print_dcd_clk = getenv("SERIAL_PRINT_GPICLK");
! 1025: mac68k_machine.print_d_speed = getenv("SERIAL_PRINT_DSPEED");
! 1026: mac68k_machine.booter_version = getenv("BOOTERVER");
! 1027:
! 1028: /*
! 1029: * For now, we assume that the boot device is off the first controller.
! 1030: * Booter versions 1.11.0 and later set a flag to tell us to construct
! 1031: * bootdev using the SCSI ID passed in via the environment.
! 1032: */
! 1033: root_scsi_id = getenv("ROOT_SCSI_ID");
! 1034: if (((mac68k_machine.booter_version < CURRENTBOOTERVER) ||
! 1035: (flag & 0x40000)) && bootdev == 0)
! 1036: bootdev = MAKEBOOTDEV(4, 0, 0, root_scsi_id, 0);
! 1037:
! 1038: /*
! 1039: * Booter 1.11.3 and later pass a BOOTHOWTO variable with the
! 1040: * appropriate bits set.
! 1041: */
! 1042: boothowto = getenv("BOOTHOWTO");
! 1043: if (boothowto == 0)
! 1044: boothowto = getenv("SINGLE_USER");
! 1045:
! 1046: /*
! 1047: * Get end of symbols for kernel debugging
! 1048: */
! 1049: #if defined(DDB) || NKSYMS > 0
! 1050: esym = getenv("END_SYM");
! 1051: if (esym == 0)
! 1052: esym = (long) &end;
! 1053: #endif
! 1054:
! 1055: /* Get MacOS time */
! 1056: macos_boottime = getenv("BOOTTIME");
! 1057:
! 1058: /* Save GMT BIAS saved in Booter parameters dialog box */
! 1059: macos_gmtbias = getenv("GMTBIAS");
! 1060:
! 1061: /*
! 1062: * Save globals stolen from MacOS
! 1063: */
! 1064:
! 1065: ROMBase = (vaddr_t)getenv("ROMBASE");
! 1066: if (ROMBase != 0)
! 1067: MacOSROMBase = ROMBase;
! 1068: ADBDelay = (u_short) getenv("ADBDELAY");
! 1069: HwCfgFlags3 = getenv("HWCFGFLAG3");
! 1070: }
! 1071:
! 1072: char toupper(char);
! 1073:
! 1074: char
! 1075: toupper(c)
! 1076: char c;
! 1077: {
! 1078: if (c >= 'a' && c <= 'z') {
! 1079: return c - 'a' + 'A';
! 1080: } else {
! 1081: return c;
! 1082: }
! 1083: }
! 1084:
! 1085: long
! 1086: getenv(str)
! 1087: char *str;
! 1088: {
! 1089: /*
! 1090: * Returns the value of the environment variable "str".
! 1091: *
! 1092: * Format of the buffer is "var=val\0var=val\0...\0var=val\0\0".
! 1093: *
! 1094: * Returns 0 if the variable is not there, and 1 if the variable is
! 1095: * there without an "=val".
! 1096: */
! 1097:
! 1098: char *s, *s1;
! 1099: int val, base;
! 1100:
! 1101: s = envbuf;
! 1102: while (1) {
! 1103: for (s1 = str; *s1 && *s && *s != '='; s1++, s++) {
! 1104: if (toupper(*s1) != toupper(*s)) {
! 1105: break;
! 1106: }
! 1107: }
! 1108: if (*s1) { /* No match */
! 1109: while (*s) {
! 1110: s++;
! 1111: }
! 1112: s++;
! 1113: if (*s == '\0') { /* Not found */
! 1114: /* Boolean flags are FALSE (0) if not there */
! 1115: return 0;
! 1116: }
! 1117: continue;
! 1118: }
! 1119: if (*s == '=') {/* Has a value */
! 1120: s++;
! 1121: val = 0;
! 1122: base = 10;
! 1123: if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) {
! 1124: base = 16;
! 1125: s += 2;
! 1126: } else
! 1127: if (*s == '0') {
! 1128: base = 8;
! 1129: }
! 1130: while (*s) {
! 1131: if (toupper(*s) >= 'A' && toupper(*s) <= 'F') {
! 1132: val = val * base + toupper(*s) - 'A' + 10;
! 1133: } else {
! 1134: val = val * base + (*s - '0');
! 1135: }
! 1136: s++;
! 1137: }
! 1138: return val;
! 1139: } else { /* TRUE (1) */
! 1140: return 1;
! 1141: }
! 1142: }
! 1143: }
! 1144:
! 1145: struct cpu_model_info cpu_models[] = {
! 1146:
! 1147: /* The first four. */
! 1148: { MACH_MACII, "II", MACH_CLASSII },
! 1149: { MACH_MACIIX, "IIx", MACH_CLASSII },
! 1150: { MACH_MACIICX, "IIcx", MACH_CLASSII },
! 1151: { MACH_MACSE30, "SE/30", MACH_CLASSII },
! 1152:
! 1153: /* The rest of the II series... */
! 1154: { MACH_MACIICI, "IIci", MACH_CLASSIIci },
! 1155: { MACH_MACIISI, "IIsi", MACH_CLASSIIsi },
! 1156: { MACH_MACIIVI, "IIvi", MACH_CLASSIIvx },
! 1157: { MACH_MACIIVX, "IIvx", MACH_CLASSIIvx },
! 1158: { MACH_MACIIFX, "IIfx", MACH_CLASSIIfx },
! 1159:
! 1160: /* The Centris/Quadra series. */
! 1161: { MACH_MACQ700, "Quadra 700", MACH_CLASSQ },
! 1162: { MACH_MACQ900, "Quadra 900", MACH_CLASSQ },
! 1163: { MACH_MACQ950, "Quadra 950", MACH_CLASSQ },
! 1164: { MACH_MACQ800, "Quadra 800", MACH_CLASSQ },
! 1165: { MACH_MACQ650, "Quadra 650", MACH_CLASSQ },
! 1166: { MACH_MACC650, "Centris 650", MACH_CLASSQ },
! 1167: { MACH_MACQ605, "Quadra 605", MACH_CLASSQ },
! 1168: { MACH_MACQ605_33, "Quadra 605/33", MACH_CLASSQ },
! 1169: { MACH_MACC610, "Centris 610", MACH_CLASSQ },
! 1170: { MACH_MACQ610, "Quadra 610", MACH_CLASSQ },
! 1171: { MACH_MACQ630, "Quadra 630", MACH_CLASSQ2 },
! 1172: { MACH_MACC660AV, "Centris 660AV", MACH_CLASSAV },
! 1173: { MACH_MACQ840AV, "Quadra 840AV", MACH_CLASSAV },
! 1174:
! 1175: /* The Powerbooks/Duos... */
! 1176: { MACH_MACPB100, "PowerBook 100", MACH_CLASSPB },
! 1177: /* PB 100 has no MMU! */
! 1178: { MACH_MACPB140, "PowerBook 140", MACH_CLASSPB },
! 1179: { MACH_MACPB145, "PowerBook 145", MACH_CLASSPB },
! 1180: { MACH_MACPB150, "PowerBook 150", MACH_CLASSDUO },
! 1181: { MACH_MACPB160, "PowerBook 160", MACH_CLASSPB },
! 1182: { MACH_MACPB165, "PowerBook 165", MACH_CLASSPB },
! 1183: { MACH_MACPB165C, "PowerBook 165c", MACH_CLASSPB },
! 1184: { MACH_MACPB170, "PowerBook 170", MACH_CLASSPB },
! 1185: { MACH_MACPB180, "PowerBook 180", MACH_CLASSPB },
! 1186: { MACH_MACPB180C, "PowerBook 180c", MACH_CLASSPB },
! 1187: { MACH_MACPB190, "PowerBook 190", MACH_CLASSPB },
! 1188: { MACH_MACPB190CS, "PowerBook 190cs", MACH_CLASSPB },
! 1189: { MACH_MACPB500, "PowerBook 500", MACH_CLASSPB },
! 1190:
! 1191: /* The Duos */
! 1192: { MACH_MACPB210, "PowerBook Duo 210", MACH_CLASSDUO },
! 1193: { MACH_MACPB230, "PowerBook Duo 230", MACH_CLASSDUO },
! 1194: { MACH_MACPB250, "PowerBook Duo 250", MACH_CLASSDUO },
! 1195: { MACH_MACPB270, "PowerBook Duo 270C", MACH_CLASSDUO },
! 1196: { MACH_MACPB280, "PowerBook Duo 280", MACH_CLASSDUO },
! 1197: { MACH_MACPB280C, "PowerBook Duo 280C", MACH_CLASSDUO },
! 1198:
! 1199: /* The Performas... */
! 1200: { MACH_MACP600, "Performa 600", MACH_CLASSIIvx },
! 1201: { MACH_MACP460, "Performa 460", MACH_CLASSLC },
! 1202: { MACH_MACP550, "Performa 550", MACH_CLASSLC },
! 1203: { MACH_MACP580, "Performa 580", MACH_CLASSQ2 },
! 1204: { MACH_MACTV, "TV", MACH_CLASSLC },
! 1205:
! 1206: /* The LCs... */
! 1207: { MACH_MACLCII, "LC II", MACH_CLASSLC },
! 1208: { MACH_MACLCIII, "LC III", MACH_CLASSLC },
! 1209: { MACH_MACLC475, "LC 475", MACH_CLASSQ },
! 1210: { MACH_MACLC475_33, "LC 475/33", MACH_CLASSQ },
! 1211: { MACH_MACLC520, "LC 520", MACH_CLASSLC },
! 1212: { MACH_MACLC575, "LC 575", MACH_CLASSQ2 },
! 1213: { MACH_MACCCLASSIC, "Color Classic", MACH_CLASSLC },
! 1214: { MACH_MACCCLASSICII, "Color ClassicII", MACH_CLASSLC },
! 1215: /* Does this belong here? */
! 1216: { MACH_MACCLASSICII, "Classic II", MACH_CLASSLC },
! 1217:
! 1218: /* The unknown one and the end... */
! 1219: { 0, "Unknown", MACH_CLASSII }
! 1220: }; /* End of cpu_models[] initialization. */
! 1221:
! 1222: struct intvid_info_t {
! 1223: int machineid;
! 1224: u_long fbbase;
! 1225: u_long fbmask;
! 1226: u_long fblen;
! 1227: } intvid_info[] = {
! 1228: { MACH_MACCLASSICII, 0x009f9a80, 0x0, 21888 },
! 1229: { MACH_MACPB140, 0xfee08000, 0x0, 32 * 1024 },
! 1230: { MACH_MACPB145, 0xfee08000, 0x0, 32 * 1024 },
! 1231: { MACH_MACPB170, 0xfee08000, 0x0, 32 * 1024 },
! 1232: { MACH_MACPB150, 0x60000000, 0x0, 128 * 1024 },
! 1233: { MACH_MACPB160, 0x60000000, 0x0ffe0000, 128 * 1024 },
! 1234: { MACH_MACPB165, 0x60000000, 0x0ffe0000, 128 * 1024 },
! 1235: { MACH_MACPB180, 0x60000000, 0x0ffe0000, 128 * 1024 },
! 1236: { MACH_MACPB210, 0x60000000, 0x0, 128 * 1024 },
! 1237: { MACH_MACPB230, 0x60000000, 0x0, 128 * 1024 },
! 1238: { MACH_MACPB250, 0x60000000, 0x0, 128 * 1024 },
! 1239: { MACH_MACPB270, 0x60000000, 0x0, 128 * 1024 },
! 1240: { MACH_MACPB280, 0x60000000, 0x0, 128 * 1024 },
! 1241: { MACH_MACPB280C, 0x60000000, 0x0, 128 * 1024 },
! 1242: { MACH_MACIICI, 0x0, 0x0, 320 * 1024 },
! 1243: { MACH_MACIISI, 0x0, 0x0, 320 * 1024 },
! 1244: { MACH_MACCCLASSIC, 0x50f40000, 0x0, 512 * 1024 },
! 1245: /*??*/ { MACH_MACLCII, 0x50f40000, 0x0, 512 * 1024 },
! 1246: { MACH_MACPB165C, 0xfc040000, 0x0, 512 * 1024 },
! 1247: { MACH_MACPB180C, 0xfc040000, 0x0, 512 * 1024 },
! 1248: { MACH_MACPB190, 0x60000000, 0x0, 512 * 1024 },
! 1249: { MACH_MACPB190CS, 0x60000000, 0x0, 512 * 1024 },
! 1250: { MACH_MACPB500, 0x60000000, 0x0, 512 * 1024 },
! 1251: { MACH_MACLCIII, 0x60b00000, 0x0, 768 * 1024 },
! 1252: { MACH_MACLC520, 0x60000000, 0x0, 1024 * 1024 },
! 1253: { MACH_MACP550, 0x60000000, 0x0, 1024 * 1024 },
! 1254: { MACH_MACTV, 0x60000000, 0x0, 1024 * 1024 },
! 1255: { MACH_MACLC475, 0xf9000000, 0x0, 1024 * 1024 },
! 1256: { MACH_MACLC475_33, 0xf9000000, 0x0, 1024 * 1024 },
! 1257: { MACH_MACLC575, 0xf9000000, 0x0, 1024 * 1024 },
! 1258: { MACH_MACC610, 0xf9000000, 0x0, 1024 * 1024 },
! 1259: { MACH_MACC650, 0xf9000000, 0x0, 1024 * 1024 },
! 1260: { MACH_MACP580, 0xf9000000, 0x0, 1024 * 1024 },
! 1261: { MACH_MACQ605, 0xf9000000, 0x0, 1024 * 1024 },
! 1262: { MACH_MACQ605_33, 0xf9000000, 0x0, 1024 * 1024 },
! 1263: { MACH_MACQ610, 0xf9000000, 0x0, 1024 * 1024 },
! 1264: { MACH_MACQ630, 0xf9000000, 0x0, 1024 * 1024 },
! 1265: { MACH_MACQ650, 0xf9000000, 0x0, 1024 * 1024 },
! 1266: { MACH_MACC660AV, 0x50100000, 0x0, 1024 * 1024 },
! 1267: { MACH_MACQ700, 0xf9000000, 0x0, 1024 * 1024 },
! 1268: { MACH_MACQ800, 0xf9000000, 0x0, 1024 * 1024 },
! 1269: { MACH_MACQ900, 0xf9000000, 0x0, 1024 * 1024 },
! 1270: { MACH_MACQ950, 0xf9000000, 0x0, 1024 * 1024 },
! 1271: { MACH_MACQ840AV, 0x50100000, 0x0, 2048 * 1024 },
! 1272: { 0, 0x0, 0x0, 0 },
! 1273: }; /* End of intvid_info[] initialization. */
! 1274:
! 1275: /*
! 1276: * Missing Mac Models:
! 1277: * PowerMac 6100
! 1278: * PowerMac 7100
! 1279: * PowerMac 8100
! 1280: * PowerBook 540
! 1281: * PowerBook 520
! 1282: * PowerBook 150
! 1283: * Duo 280
! 1284: * Performa 6000s
! 1285: * ...?
! 1286: */
! 1287:
! 1288: char cpu_model[120]; /* for sysctl() */
! 1289:
! 1290: int
! 1291: fpu_probe()
! 1292: {
! 1293: /*
! 1294: * A 68881 idle frame is 28 bytes and a 68882's is 60 bytes.
! 1295: * We, of course, need to have enough room for either.
! 1296: */
! 1297: int fpframe[60 / sizeof(int)];
! 1298: label_t faultbuf;
! 1299: u_char b;
! 1300:
! 1301: nofault = (int *) &faultbuf;
! 1302: if (setjmp(&faultbuf)) {
! 1303: nofault = (int *) 0;
! 1304: return (FPU_NONE);
! 1305: }
! 1306:
! 1307: /*
! 1308: * Synchronize FPU or cause a fault.
! 1309: * This should leave the 881/882 in the IDLE state,
! 1310: * state, so we can determine which we have by
! 1311: * examining the size of the FP state frame
! 1312: */
! 1313: asm("fnop");
! 1314:
! 1315: nofault = (int *) 0;
! 1316:
! 1317: /*
! 1318: * Presumably, if we're an 040 and did not take exception
! 1319: * above, we have an FPU. Don't bother probing.
! 1320: */
! 1321: if (mmutype == MMU_68040)
! 1322: return (FPU_68040);
! 1323:
! 1324: /*
! 1325: * Presumably, this will not cause a fault--the fnop should
! 1326: * have if this will. We save the state in order to get the
! 1327: * size of the frame.
! 1328: */
! 1329: asm("movl %0, a0; fsave a0@" : : "a" (fpframe) : "a0" );
! 1330:
! 1331: b = *((u_char *) fpframe + 1);
! 1332:
! 1333: /*
! 1334: * Now, restore a NULL state to reset the FPU.
! 1335: */
! 1336: fpframe[0] = fpframe[1] = 0;
! 1337: m68881_restore((struct fpframe *) fpframe);
! 1338:
! 1339: /*
! 1340: * The size of a 68881 IDLE frame is 0x18
! 1341: * and a 68882 frame is 0x38
! 1342: */
! 1343: if (b == 0x18)
! 1344: return (FPU_68881);
! 1345: if (b == 0x38)
! 1346: return (FPU_68882);
! 1347:
! 1348: /*
! 1349: * If it's not one of the above, we have no clue what it is.
! 1350: */
! 1351: return (FPU_UNKNOWN);
! 1352: }
! 1353:
! 1354: void
! 1355: identifycpu()
! 1356: {
! 1357: #ifdef DEBUG
! 1358: extern u_int delay_factor;
! 1359: #endif
! 1360:
! 1361: /*
! 1362: * Print the machine type...
! 1363: */
! 1364: snprintf(cpu_model, sizeof cpu_model, "Apple Macintosh %s",
! 1365: cpu_models[mac68k_machine.cpu_model_index].model);
! 1366:
! 1367: /*
! 1368: * ... and the CPU type...
! 1369: */
! 1370: switch (cputype) {
! 1371: case CPU_68040:
! 1372: strlcat(cpu_model, ", 68040 CPU", sizeof cpu_model);
! 1373: break;
! 1374: case CPU_68030:
! 1375: strlcat(cpu_model, ", 68030 CPU", sizeof cpu_model);
! 1376: break;
! 1377: case CPU_68020:
! 1378: strlcat(cpu_model, ", 68020 CPU", sizeof cpu_model);
! 1379: break;
! 1380: default:
! 1381: strlcat(cpu_model, ", unknown CPU", sizeof cpu_model);
! 1382: break;
! 1383: }
! 1384:
! 1385: /*
! 1386: * ... and the MMU type...
! 1387: */
! 1388: switch (mmutype) {
! 1389: case MMU_68040:
! 1390: case MMU_68030:
! 1391: strlcat(cpu_model, "+MMU", sizeof cpu_model);
! 1392: break;
! 1393: case MMU_68851:
! 1394: strlcat(cpu_model, ", MC68851 MMU", sizeof cpu_model);
! 1395: break;
! 1396: default:
! 1397: printf("%s\n", cpu_model);
! 1398: panic("unknown MMU type %d", mmutype);
! 1399: /* NOTREACHED */
! 1400: }
! 1401:
! 1402: /*
! 1403: * ... and the FPU type...
! 1404: */
! 1405: fputype = fpu_probe(); /* should eventually move to locore */
! 1406:
! 1407: switch (fputype) {
! 1408: case FPU_68040:
! 1409: strlcat(cpu_model, "+FPU", sizeof cpu_model);
! 1410: break;
! 1411: case FPU_68882:
! 1412: strlcat(cpu_model, ", MC6882 FPU", sizeof cpu_model);
! 1413: break;
! 1414: case FPU_68881:
! 1415: strlcat(cpu_model, ", MC6881 FPU", sizeof cpu_model);
! 1416: break;
! 1417: case FPU_UNKNOWN:
! 1418: strlcat(cpu_model, ", unknown FPU", sizeof cpu_model);
! 1419: break;
! 1420: default:
! 1421: /*strlcat(cpu_model, ", no FPU", sizeof cpu_model);*/
! 1422: break;
! 1423: }
! 1424:
! 1425: /*
! 1426: * ... and finally, the cache type.
! 1427: */
! 1428: if (cputype == CPU_68040)
! 1429: strlcat(cpu_model, ", 4k on-chip physical I/D caches", sizeof cpu_model);
! 1430:
! 1431: printf("%s\n", cpu_model);
! 1432: #ifdef DEBUG
! 1433: printf("cpu: delay factor %d\n", delay_factor);
! 1434: #endif
! 1435: }
! 1436:
! 1437: void get_machine_info(void);
! 1438:
! 1439: void
! 1440: get_machine_info()
! 1441: {
! 1442: int i;
! 1443:
! 1444: for (i = 0; cpu_models[i].machineid != 0; i++)
! 1445: if (mac68k_machine.machineid == cpu_models[i].machineid)
! 1446: break;
! 1447:
! 1448: mac68k_machine.cpu_model_index = i;
! 1449: }
! 1450:
! 1451: const struct cpu_model_info *current_mac_model;
! 1452:
! 1453: /*
! 1454: * Sets a bunch of machine-specific variables
! 1455: */
! 1456: void setmachdep(void);
! 1457:
! 1458: void
! 1459: setmachdep()
! 1460: {
! 1461: struct cpu_model_info *cpui;
! 1462:
! 1463: /*
! 1464: * First, set things that need to be set on the first pass only
! 1465: * Ideally, we'd only call this once, but for some reason, the
! 1466: * VIAs need interrupts turned off twice !?
! 1467: */
! 1468: get_machine_info();
! 1469:
! 1470: load_addr = 0;
! 1471: cpui = &(cpu_models[mac68k_machine.cpu_model_index]);
! 1472: current_mac_model = cpui;
! 1473:
! 1474: mac68k_machine.via1_ipl = 1;
! 1475: mac68k_machine.aux_interrupts = 0;
! 1476:
! 1477: /*
! 1478: * Set up any machine specific stuff that we have to before
! 1479: * ANYTHING else happens
! 1480: */
! 1481: switch (cpui->class) { /* Base this on class of machine... */
! 1482: case MACH_CLASSII:
! 1483: VIA2 = VIA2OFF;
! 1484: IOBase = 0x50f00000;
! 1485: Via1Base = (volatile u_char *)IOBase;
! 1486: mac68k_machine.scsi80 = 1;
! 1487: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
! 1488: via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
! 1489: break;
! 1490: case MACH_CLASSPB:
! 1491: VIA2 = VIA2OFF;
! 1492: IOBase = 0x50f00000;
! 1493: Via1Base = (volatile u_char *)IOBase;
! 1494: mac68k_machine.scsi80 = 1;
! 1495: /* Disable everything but PM; we need it. */
! 1496: via_reg(VIA1, vIER) = 0x6f; /* disable VIA1 int */
! 1497: /* Are we disabling something important? */
! 1498: via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
! 1499: if (cputype == CPU_68040)
! 1500: mac68k_machine.sonic = 1;
! 1501: break;
! 1502: case MACH_CLASSDUO:
! 1503: /*
! 1504: * The Duo definitely does not use a VIA2, but it looks
! 1505: * like the VIA2 functions might be on the MSC at the RBV
! 1506: * locations. The rest is copied from the Powerbooks.
! 1507: */
! 1508: VIA2 = RBVOFF;
! 1509: IOBase = 0x50f00000;
! 1510: Via1Base = (volatile u_char *)IOBase;
! 1511: mac68k_machine.scsi80 = 1;
! 1512: /* Disable everything but PM; we need it. */
! 1513: via_reg(VIA1, vIER) = 0x6f; /* disable VIA1 int */
! 1514: /* Are we disabling something important? */
! 1515: via_reg(VIA2, rIER) = 0x7f; /* disable VIA2 int */
! 1516: break;
! 1517: case MACH_CLASSQ:
! 1518: case MACH_CLASSQ2:
! 1519: VIA2 = VIA2OFF;
! 1520: IOBase = 0x50f00000;
! 1521: Via1Base = (volatile u_char *)IOBase;
! 1522: mac68k_machine.sonic = 1;
! 1523: mac68k_machine.scsi96 = 1;
! 1524: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
! 1525: via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
! 1526:
! 1527: /* Enable A/UX interrupt scheme */
! 1528: mac68k_machine.aux_interrupts = 1;
! 1529: via_reg(VIA1, vBufB) &= (0xff ^ DB1O_AuxIntEnb);
! 1530: via_reg(VIA1, vDirB) |= DB1O_AuxIntEnb;
! 1531: mac68k_machine.via1_ipl = 6;
! 1532:
! 1533: break;
! 1534: case MACH_CLASSAV:
! 1535: VIA2 = VIA2OFF;
! 1536: IOBase = 0x50f00000;
! 1537: Via1Base = (volatile u_char *)IOBase;
! 1538: mac68k_machine.scsi96 = 1;
! 1539: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
! 1540: via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
! 1541: break;
! 1542: case MACH_CLASSIIci:
! 1543: VIA2 = RBVOFF;
! 1544: IOBase = 0x50f00000;
! 1545: Via1Base = (volatile u_char *)IOBase;
! 1546: mac68k_machine.scsi80 = 1;
! 1547: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
! 1548: via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
! 1549: break;
! 1550: case MACH_CLASSIIsi:
! 1551: VIA2 = RBVOFF;
! 1552: IOBase = 0x50f00000;
! 1553: Via1Base = (volatile u_char *)IOBase;
! 1554: mac68k_machine.scsi80 = 1;
! 1555: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
! 1556: via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
! 1557: break;
! 1558: case MACH_CLASSIIvx:
! 1559: VIA2 = RBVOFF;
! 1560: IOBase = 0x50f00000;
! 1561: Via1Base = (volatile u_char *)IOBase;
! 1562: mac68k_machine.scsi80 = 1;
! 1563: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
! 1564: via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
! 1565: break;
! 1566: case MACH_CLASSLC:
! 1567: VIA2 = RBVOFF;
! 1568: IOBase = 0x50f00000;
! 1569: Via1Base = (volatile u_char *)IOBase;
! 1570: mac68k_machine.scsi80 = 1;
! 1571: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
! 1572: via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
! 1573: break;
! 1574: case MACH_CLASSIIfx:
! 1575: VIA2 = OSSOFF;
! 1576: IOBase = 0x50f00000;
! 1577: Via1Base = (volatile u_char *)IOBase;
! 1578: mac68k_machine.scsi80 = 1;
! 1579: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
! 1580: break;
! 1581: default:
! 1582: case MACH_CLASSH:
! 1583: break;
! 1584: }
! 1585: }
! 1586:
! 1587: /*
! 1588: * Set IO offsets.
! 1589: */
! 1590: void
! 1591: mac68k_set_io_offsets(base)
! 1592: vaddr_t base;
! 1593: {
! 1594: extern volatile u_char *sccA;
! 1595:
! 1596: switch (current_mac_model->class) {
! 1597: case MACH_CLASSQ:
! 1598: Via1Base = (volatile u_char *)base;
! 1599:
! 1600: /* The following two may be overriden. */
! 1601: sccA = (volatile u_char *)base + 0xc000;
! 1602: SCSIBase = base + 0xf000;
! 1603:
! 1604: switch (current_mac_model->machineid) {
! 1605: case MACH_MACQ900:
! 1606: case MACH_MACQ950:
! 1607: sccA = (volatile u_char *)base + 0xc020;
! 1608: iop_serial_compatible();
! 1609: mac68k_machine.scsi96_2 = 1;
! 1610: break;
! 1611: case MACH_MACQ700:
! 1612: break;
! 1613: default:
! 1614: SCSIBase = base + 0x10000;
! 1615: break;
! 1616: }
! 1617: break;
! 1618: case MACH_CLASSQ2:
! 1619: /*
! 1620: * Note the different offset for sccA for this class of
! 1621: * machines. This seems to be common on many of the
! 1622: * Quadra-type machines.
! 1623: */
! 1624: Via1Base = (volatile u_char *)base;
! 1625: sccA = (volatile u_char *)base + 0xc020;
! 1626: SCSIBase = base + 0x10000;
! 1627: break;
! 1628: case MACH_CLASSAV:
! 1629: Via1Base = (volatile u_char *)base;
! 1630: sccA = (volatile u_char *)base + 0x4000;
! 1631: SCSIBase = base + 0x18000;
! 1632: PSCBase = (volatile u_char *)base + 0x31000;
! 1633: break;
! 1634: case MACH_CLASSII:
! 1635: case MACH_CLASSPB:
! 1636: case MACH_CLASSDUO:
! 1637: case MACH_CLASSIIci:
! 1638: case MACH_CLASSIIsi:
! 1639: case MACH_CLASSIIvx:
! 1640: case MACH_CLASSLC:
! 1641: Via1Base = (volatile u_char *)base;
! 1642: sccA = (volatile u_char *)base + 0x4000;
! 1643: SCSIBase = base;
! 1644: break;
! 1645: case MACH_CLASSIIfx:
! 1646: Via1Base = (volatile u_char *)base;
! 1647: sccA = (volatile u_char *)base + 0x4020;
! 1648: iop_serial_compatible();
! 1649: SCSIBase = base;
! 1650: break;
! 1651: default:
! 1652: case MACH_CLASSH:
! 1653: panic("Unknown/unsupported machine class (%d).",
! 1654: current_mac_model->class);
! 1655: break;
! 1656: }
! 1657:
! 1658: Via2Base = Via1Base + 0x2000 * VIA2;
! 1659: }
! 1660:
! 1661: #if GRAYBARS
! 1662: u_long gray_nextaddr = 0;
! 1663:
! 1664: void
! 1665: gray_bar()
! 1666: {
! 1667: static int i = 0;
! 1668: static int flag = 0;
! 1669:
! 1670: /* MF basic premise as I see it:
! 1671: 1) Save the scratch regs as they are not saved by the compilier.
! 1672: 2) Check to see if we want gray bars, if so,
! 1673: display some lines of gray,
! 1674: a couple of lines of white(about 8),
! 1675: and loop to slow this down.
! 1676: 3) restore regs
! 1677: */
! 1678:
! 1679: __asm __volatile (" movl a0,sp@-;
! 1680: movl a1,sp@-;
! 1681: movl d0,sp@-;
! 1682: movl d1,sp@-");
! 1683:
! 1684: /* check to see if gray bars are turned off */
! 1685: if (mac68k_machine.do_graybars) {
! 1686: /* MF the 10*rowbytes/4 is done lots, but we want this to be
! 1687: * slow */
! 1688: for (i = 0; i < 10 * videorowbytes / 4; i++)
! 1689: ((u_long *)videoaddr)[gray_nextaddr++] = 0xaaaaaaaa;
! 1690: for (i = 0; i < 2 * videorowbytes / 4; i++)
! 1691: ((u_long *)videoaddr)[gray_nextaddr++] = 0x00000000;
! 1692: }
! 1693:
! 1694: __asm __volatile (" movl sp@+,d1;
! 1695: movl sp@+,d0;
! 1696: movl sp@+,a1;
! 1697: movl sp@+,a0");
! 1698: }
! 1699: #endif
! 1700:
! 1701: /* in locore */
! 1702: extern u_long ptest040(caddr_t addr, u_int fc);
! 1703: extern int get_pte(u_int addr, u_long pte[2], u_short * psr);
! 1704:
! 1705: /*
! 1706: * LAK (7/24/94): given a logical address, puts the physical address
! 1707: * in *phys and return 1, or returns 0 on failure. This is intended
! 1708: * to look through MacOS page tables.
! 1709: */
! 1710:
! 1711: u_long
! 1712: get_physical(u_int addr, u_long * phys)
! 1713: {
! 1714: extern u_int macos_tc;
! 1715: u_long pte[2], ph, mask;
! 1716: u_short psr;
! 1717: int i, numbits;
! 1718:
! 1719: if (mmutype == MMU_68040) {
! 1720: ph = ptest040((caddr_t)addr, FC_SUPERD);
! 1721: if ((ph & MMU40_RES) == 0) {
! 1722: ph = ptest040((caddr_t)addr, FC_USERD);
! 1723: if ((ph & MMU40_RES) == 0)
! 1724: return 0;
! 1725: }
! 1726: if ((ph & MMU40_TTR) != 0)
! 1727: ph = addr;
! 1728:
! 1729: mask = (macos_tc & 0x4000) ? 0x00001fff : 0x00000fff;
! 1730: ph &= (~mask);
! 1731: } else {
! 1732: i = get_pte(addr, pte, &psr);
! 1733:
! 1734: switch (i) {
! 1735: case -1:
! 1736: return 0;
! 1737: case 0:
! 1738: ph = pte[0] & 0xFFFFFF00;
! 1739: break;
! 1740: case 1:
! 1741: ph = pte[1] & 0xFFFFFF00;
! 1742: break;
! 1743: default:
! 1744: panic("get_physical(): bad get_pte()");
! 1745: }
! 1746:
! 1747: /*
! 1748: * We must now figure out how many levels down we went and
! 1749: * mask the bits appropriately -- the returned value may only
! 1750: * be the upper n bits, and we have to take the rest from addr.
! 1751: */
! 1752: numbits = 0;
! 1753: psr &= 0x0007; /* Number of levels we went */
! 1754: for (i = 0; i < psr; i++)
! 1755: numbits += (macos_tc >> (12 - i * 4)) & 0x0f;
! 1756:
! 1757: /*
! 1758: * We have to take the most significant "numbits" from
! 1759: * the returned value "ph", and the rest from our addr.
! 1760: * Assume that numbits != 0.
! 1761: */
! 1762: mask = (1 << (32 - numbits)) - 1;
! 1763: }
! 1764: *phys = ph + (addr & mask);
! 1765:
! 1766: return 1;
! 1767: }
! 1768:
! 1769: void check_video(char *, u_long, u_long);
! 1770:
! 1771: void
! 1772: check_video(id, limit, maxm)
! 1773: char *id;
! 1774: u_long limit, maxm;
! 1775: {
! 1776: u_long addr, phys;
! 1777:
! 1778: if (!get_physical(videoaddr, &phys)) {
! 1779: if (mac68k_machine.do_graybars)
! 1780: printf("get_mapping(): %s. False start.\n", id);
! 1781: } else {
! 1782: mac68k_vidlog = videoaddr;
! 1783: mac68k_vidphys = phys;
! 1784: mac68k_vidlen = 32768;
! 1785: addr = videoaddr + 32768;
! 1786: while (get_physical(addr, &phys)) {
! 1787: if ((phys - mac68k_vidphys) != mac68k_vidlen)
! 1788: break;
! 1789: if (mac68k_vidlen + 32768 > limit) {
! 1790: if (mac68k_machine.do_graybars) {
! 1791: printf("mapping: %s. Does it never end?\n",
! 1792: id);
! 1793: printf(" Forcing VRAM size ");
! 1794: printf("to a conservative %ldK.\n",
! 1795: maxm/1024);
! 1796: }
! 1797: mac68k_vidlen = maxm;
! 1798: break;
! 1799: }
! 1800: mac68k_vidlen += 32768;
! 1801: addr += 32768;
! 1802: }
! 1803: if (mac68k_machine.do_graybars) {
! 1804: printf(" %s internal video at paddr 0x%x, len 0x%x.\n",
! 1805: id, mac68k_vidphys, mac68k_vidlen);
! 1806: }
! 1807: }
! 1808: }
! 1809:
! 1810: /*
! 1811: * Find out how MacOS has mapped itself so we can do the same thing.
! 1812: * Returns the address of logical 0 so that locore can map the kernel
! 1813: * properly.
! 1814: */
! 1815: u_int
! 1816: get_mapping(void)
! 1817: {
! 1818: struct intvid_info_t *iip;
! 1819: u_long addr, lastpage, phys, len, limit;
! 1820: int i, last, same;
! 1821:
! 1822: numranges = 0;
! 1823: for (i = 0; i < 8; i++) {
! 1824: low[i] = 0;
! 1825: high[i] = 0;
! 1826: }
! 1827:
! 1828: lastpage = get_top_of_ram();
! 1829:
! 1830: get_physical(0, &load_addr);
! 1831:
! 1832: last = 0;
! 1833: for (addr = 0; addr <= lastpage && get_physical(addr, &phys);
! 1834: addr += PAGE_SIZE) {
! 1835: if (numranges > 0 && phys != high[last]) {
! 1836: /*
! 1837: * Attempt to find if this page is already
! 1838: * accounted for in an existing physical segment.
! 1839: */
! 1840: for (i = 0; i < numranges; i++) {
! 1841: if (low[i] <= phys && phys <= high[i]) {
! 1842: last = i;
! 1843: break;
! 1844: }
! 1845: }
! 1846: if (i >= numranges)
! 1847: last = numranges - 1;
! 1848:
! 1849: if (low[last] <= phys && phys < high[last])
! 1850: continue; /* Skip pages we've seen. */
! 1851: }
! 1852:
! 1853: if (numranges > 0 && phys == high[last]) {
! 1854: /* Common case: extend existing segment on high end */
! 1855: high[last] += PAGE_SIZE;
! 1856: } else {
! 1857: /* This is a new physical segment. */
! 1858: for (last = 0; last < numranges; last++)
! 1859: if (phys < low[last])
! 1860: break;
! 1861:
! 1862: /* Create space for segment, if necessary */
! 1863: if (last < numranges && phys < low[last]) {
! 1864: for (i = numranges; i > last; i--) {
! 1865: low[i] = low[i - 1];
! 1866: high[i] = high[i - 1];
! 1867: }
! 1868: }
! 1869:
! 1870: numranges++;
! 1871: low[last] = phys;
! 1872: high[last] = phys + PAGE_SIZE;
! 1873: }
! 1874:
! 1875: /* Coalesce adjoining segments as appropriate */
! 1876: if (last < (numranges - 1) && high[last] == low[last + 1] &&
! 1877: low[last + 1] != load_addr) {
! 1878: high[last] = high[last + 1];
! 1879: for (i = last + 1; i < numranges; i++) {
! 1880: low[i] = low[i + 1];
! 1881: high[i] = high[i + 1];
! 1882: }
! 1883: --numranges;
! 1884: }
! 1885: }
! 1886: if (mac68k_machine.do_graybars) {
! 1887: printf("System RAM: %ld bytes in %ld pages.\n",
! 1888: addr, addr / PAGE_SIZE);
! 1889: for (i = 0; i < numranges; i++) {
! 1890: printf(" Low = 0x%lx, high = 0x%lx\n",
! 1891: low[i], high[i]);
! 1892: }
! 1893: }
! 1894:
! 1895: /*
! 1896: * If we can't figure out the PA of the frame buffer by groveling
! 1897: * the page tables, assume that we already have the correct
! 1898: * address. This is the case on several of the PowerBook 1xx
! 1899: * series, in particular.
! 1900: */
! 1901: if (!get_physical(videoaddr, &phys))
! 1902: phys = videoaddr;
! 1903:
! 1904: /*
! 1905: * Find on-board video, if we have an idea of where to look
! 1906: * on this system.
! 1907: */
! 1908: for (iip = intvid_info; iip->machineid != 0; iip++)
! 1909: if (mac68k_machine.machineid == iip->machineid)
! 1910: break;
! 1911:
! 1912: if (mac68k_machine.machineid == iip->machineid &&
! 1913: (phys & ~iip->fbmask) >= iip->fbbase &&
! 1914: (phys & ~iip->fbmask) < (iip->fbbase + iip->fblen)) {
! 1915: mac68k_vidphys = phys & ~iip->fbmask;
! 1916: mac68k_vidlen = 32768 - (phys & 0x7fff);
! 1917:
! 1918: limit = iip->fbbase + iip->fblen - mac68k_vidphys;
! 1919: if (mac68k_vidlen > limit) {
! 1920: mac68k_vidlen = limit;
! 1921: } else {
! 1922: addr = videoaddr + mac68k_vidlen;
! 1923: while (get_physical(addr, &phys)) {
! 1924: if ((phys - mac68k_vidphys) != mac68k_vidlen)
! 1925: break;
! 1926: if (mac68k_vidlen + 32768 > limit) {
! 1927: mac68k_vidlen = limit;
! 1928: break;
! 1929: }
! 1930: mac68k_vidlen += 32768;
! 1931: addr += 32768;
! 1932: }
! 1933: }
! 1934: }
! 1935:
! 1936: if (mac68k_vidlen > 0) {
! 1937: /*
! 1938: * We've already figured out where internal video is.
! 1939: * Tell the user what we know.
! 1940: */
! 1941: if (mac68k_machine.do_graybars)
! 1942: printf("On-board video at addr 0x%lx (phys 0x%x), len 0x%x.\n",
! 1943: videoaddr, mac68k_vidphys, mac68k_vidlen);
! 1944: } else {
! 1945: /*
! 1946: * We should now look through all of NuBus space to find where
! 1947: * the internal video is being mapped. Just to be sure we
! 1948: * handle all the cases, we simply map our NuBus space exactly
! 1949: * how MacOS did it. As above, we find a bunch of ranges that
! 1950: * are contiguously mapped. Since there are a lot of pages
! 1951: * that are all mapped to 0, we handle that as a special case
! 1952: * where the length is negative. We search in increments of
! 1953: * 32768 because that's the page size that MacOS uses.
! 1954: */
! 1955: nbnumranges = 0;
! 1956: for (i = 0; i < NBMAXRANGES; i++) {
! 1957: nbphys[i] = 0;
! 1958: nblog[i] = 0;
! 1959: nblen[i] = 0;
! 1960: }
! 1961:
! 1962: same = 0;
! 1963: for (addr = NBBASE; addr < NBTOP; addr += 32768) {
! 1964: if (!get_physical(addr, &phys)) {
! 1965: continue;
! 1966: }
! 1967: len = nbnumranges == 0 ? 0 : nblen[nbnumranges - 1];
! 1968:
! 1969: #if DEBUG
! 1970: if (mac68k_machine.do_graybars)
! 1971: printf ("0x%lx --> 0x%lx\n", addr, phys);
! 1972: #endif
! 1973: if (nbnumranges > 0
! 1974: && addr == nblog[nbnumranges - 1] + len
! 1975: && phys == nbphys[nbnumranges - 1]) {
! 1976: /* Same as last one */
! 1977: nblen[nbnumranges - 1] += 32768;
! 1978: same = 1;
! 1979: } else {
! 1980: if ((nbnumranges > 0)
! 1981: && !same
! 1982: && (addr == nblog[nbnumranges - 1] + len)
! 1983: && (phys == nbphys[nbnumranges - 1] + len))
! 1984: nblen[nbnumranges - 1] += 32768;
! 1985: else {
! 1986: if (same) {
! 1987: nblen[nbnumranges - 1] = -len;
! 1988: same = 0;
! 1989: }
! 1990: if (nbnumranges == NBMAXRANGES) {
! 1991: if (mac68k_machine.do_graybars)
! 1992: printf("get_mapping(): "
! 1993: "Too many NuBus ranges.\n");
! 1994: break;
! 1995: }
! 1996: nbnumranges++;
! 1997: nblog[nbnumranges - 1] = addr;
! 1998: nbphys[nbnumranges - 1] = phys;
! 1999: nblen[nbnumranges - 1] = 32768;
! 2000: }
! 2001: }
! 2002: }
! 2003: if (same) {
! 2004: nblen[nbnumranges - 1] = -nblen[nbnumranges - 1];
! 2005: same = 0;
! 2006: }
! 2007: if (mac68k_machine.do_graybars) {
! 2008: printf("Non-system RAM (nubus, etc.):\n");
! 2009: for (i = 0; i < nbnumranges; i++) {
! 2010: printf(" Log = 0x%lx, Phys = 0x%lx, Len = 0x%lx (%lu)\n",
! 2011: nblog[i], nbphys[i], nblen[i], nblen[i]);
! 2012: }
! 2013: }
! 2014:
! 2015: /*
! 2016: * We must now find the logical address of internal video in the
! 2017: * ranges we made above. Internal video is at physical 0, but
! 2018: * a lot of pages map there. Instead, we look for the logical
! 2019: * page that maps to 32768 and go back one page.
! 2020: */
! 2021: for (i = 0; i < nbnumranges; i++) {
! 2022: if (nblen[i] > 0
! 2023: && nbphys[i] <= 32768
! 2024: && 32768 <= nbphys[i] + nblen[i]) {
! 2025: mac68k_vidlog = nblog[i] - nbphys[i];
! 2026: mac68k_vidlen = nblen[i] + nbphys[i];
! 2027: mac68k_vidphys = 0;
! 2028: break;
! 2029: }
! 2030: }
! 2031: if (i == nbnumranges) {
! 2032: if (0x60000000 <= videoaddr && videoaddr < 0x70000000) {
! 2033: if (mac68k_machine.do_graybars)
! 2034: printf("Checking for Internal Video ");
! 2035: /*
! 2036: * Kludge for IIvx internal video (60b0 0000).
! 2037: * PB 520 (6000 0000)
! 2038: */
! 2039: check_video("PB/IIvx (0x60?00000)",
! 2040: 1 * 1024 * 1024, 1 * 1024 * 1024);
! 2041: } else if (0x50F40000 <= videoaddr
! 2042: && videoaddr < 0x50FBFFFF) {
! 2043: /*
! 2044: * Kludge for LC internal video
! 2045: */
! 2046: check_video("LC video (0x50f40000)",
! 2047: 512 * 1024, 512 * 1024);
! 2048: } else if (0x50100100 <= videoaddr
! 2049: && videoaddr < 0x50400000) {
! 2050: /*
! 2051: * Kludge for AV internal video
! 2052: */
! 2053: check_video("AV video (0x50100100)",
! 2054: 1 * 1024 * 1024, 1 * 1024 * 1024);
! 2055: } else {
! 2056: if (mac68k_machine.do_graybars)
! 2057: printf( " no internal video at address 0 -- "
! 2058: "videoaddr is 0x%lx.\n", videoaddr);
! 2059: }
! 2060: } else {
! 2061: if (mac68k_machine.do_graybars) {
! 2062: printf(" Video address = 0x%lx\n", videoaddr);
! 2063: printf(" Int video starts at 0x%x\n",
! 2064: mac68k_vidlog);
! 2065: printf(" Length = 0x%x (%d) bytes\n",
! 2066: mac68k_vidlen, mac68k_vidlen);
! 2067: }
! 2068: }
! 2069: }
! 2070:
! 2071: return load_addr; /* Return physical address of logical 0 */
! 2072: }
! 2073:
! 2074: #ifdef DEBUG
! 2075: /*
! 2076: * Debugging code for locore page-traversal routine.
! 2077: */
! 2078: void printstar(void);
! 2079: void
! 2080: printstar(void)
! 2081: {
! 2082: /*
! 2083: * Be careful as we assume that no registers are clobbered
! 2084: * when we call this from assembly.
! 2085: */
! 2086: __asm __volatile (" movl a0,sp@-;
! 2087: movl a1,sp@-;
! 2088: movl d0,sp@-;
! 2089: movl d1,sp@-");
! 2090:
! 2091: /* printf("*"); */
! 2092:
! 2093: __asm __volatile (" movl sp@+,d1;
! 2094: movl sp@+,d0;
! 2095: movl sp@+,a1;
! 2096: movl sp@+,a0");
! 2097: }
! 2098: #endif
! 2099:
! 2100: /*
! 2101: * Console bell callback; modularizes the console terminal emulator
! 2102: * and the audio system, so neither requires direct knowledge of the
! 2103: * other.
! 2104: */
! 2105:
! 2106: void
! 2107: mac68k_set_bell_callback(callback, cookie)
! 2108: int (*callback)(void *, int, int, int);
! 2109: void *cookie;
! 2110: {
! 2111: mac68k_bell_callback = callback;
! 2112: mac68k_bell_cookie = (caddr_t)cookie;
! 2113: }
! 2114:
! 2115: int
! 2116: mac68k_ring_bell(freq, length, volume)
! 2117: int freq, length, volume;
! 2118: {
! 2119: if (mac68k_bell_callback)
! 2120: return ((*mac68k_bell_callback)(mac68k_bell_cookie,
! 2121: freq, length, volume));
! 2122: else
! 2123: return (ENXIO);
! 2124: }
CVSweb