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