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