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