[BACK]Return to machdep.c CVS log [TXT][DIR] Up to [local] / sys / arch / mac68k / mac68k

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