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