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