Annotation of sys/arch/mac68k/mac68k/machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: machdep.c,v 1.142 2007/07/29 21:24:05 miod Exp $ */
2: /* $NetBSD: machdep.c,v 1.207 1998/07/08 04:39:34 thorpej Exp $ */
3:
4: /*
5: * Copyright (c) 1988 University of Utah.
6: * Copyright (c) 1982, 1990 The Regents of the University of California.
7: * All rights reserved.
8: *
9: * This code is derived from software contributed to Berkeley by
10: * the Systems Programming Group of the University of Utah Computer
11: * Science Department.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: */
37: /*-
38: * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
39: * Michael L. Finch, Bradley A. Grantham, and
40: * Lawrence A. Kesteloot
41: * All rights reserved.
42: *
43: * Redistribution and use in source and binary forms, with or without
44: * modification, are permitted provided that the following conditions
45: * are met:
46: * 1. Redistributions of source code must retain the above copyright
47: * notice, this list of conditions and the following disclaimer.
48: * 2. Redistributions in binary form must reproduce the above copyright
49: * notice, this list of conditions and the following disclaimer in the
50: * documentation and/or other materials provided with the distribution.
51: * 3. All advertising materials mentioning features or use of this software
52: * must display the following acknowledgement:
53: * This product includes software developed by the Alice Group.
54: * 4. The names of the Alice Group or any of its members may not be used
55: * to endorse or promote products derived from this software without
56: * specific prior written permission.
57: *
58: * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
59: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61: * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
62: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
67: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68: *
69: */
70: /*
71: * from: Utah $Hdr: machdep.c 1.63 91/04/24$
72: *
73: * @(#)machdep.c 7.16 (Berkeley) 6/3/91
74: */
75:
76: #include <sys/param.h>
77: #include <sys/systm.h>
78: #include <sys/signalvar.h>
79: #include <sys/kernel.h>
80: #include <sys/proc.h>
81: #include <sys/buf.h>
82: #include <sys/exec.h>
83: #include <sys/core.h>
84: #include <sys/kcore.h>
85: #include <sys/vnode.h>
86: #include <sys/reboot.h>
87: #include <sys/conf.h>
88: #include <sys/file.h>
89: #include <sys/timeout.h>
90: #include <sys/malloc.h>
91: #include <sys/mbuf.h>
92: #include <sys/msgbuf.h>
93: #include <sys/user.h>
94: #include <sys/mount.h>
95: #include <sys/extent.h>
96: #include <sys/syscallargs.h>
97: #ifdef SYSVMSG
98: #include <sys/msg.h>
99: #endif
100:
101: #include <machine/db_machdep.h>
102: #include <ddb/db_sym.h>
103: #include <ddb/db_extern.h>
104: #include <ddb/db_var.h>
105:
106: #include <machine/autoconf.h>
107: #include <machine/cpu.h>
108: #include <machine/reg.h>
109: #include <machine/psl.h>
110: #include <machine/pte.h>
111: #include <machine/kcore.h>
112: #include <machine/bus.h>
113: #include <machine/pmap.h>
114:
115: #include <uvm/uvm_extern.h>
116:
117: #include <sys/sysctl.h>
118:
119: #include <dev/cons.h>
120: #include <mac68k/dev/adbvar.h>
121:
122: #include <machine/iop.h>
123: #include <machine/psc.h>
124: #include <machine/viareg.h>
125:
126: #include "wsdisplay.h"
127:
128: /* The following is used externally (sysctl_hw) */
129: char machine[] = MACHINE; /* from <machine/param.h> */
130:
131: struct mac68k_machine_S mac68k_machine;
132:
133: volatile u_char *Via1Base, *Via2Base, *PSCBase = NULL;
134: u_long NuBusBase = NBBASE;
135: u_long IOBase;
136:
137: vaddr_t SCSIBase;
138:
139: /* These are used to map kernel space: */
140: extern int numranges;
141: extern u_long low[8];
142: extern u_long high[8];
143:
144: /* These are used to map NuBus space: */
145: #define NBMAXRANGES 16
146: int nbnumranges; /* = 0 == don't use the ranges */
147: u_long nbphys[NBMAXRANGES]; /* Start physical addr of this range */
148: u_long nblog[NBMAXRANGES]; /* Start logical addr of this range */
149: long nblen[NBMAXRANGES]; /* Length of this range If the length is */
150: /* negative, all phys addrs are the same. */
151:
152: /* From Booter via locore */
153: long videoaddr; /* Addr used in kernel for video. */
154: long videorowbytes; /* Used in kernel for video. */
155: long videobitdepth; /* Number of bihs per pixel */
156: u_long videosize; /* height = 31:16, width 15:0 */
157:
158: /*
159: * Values for IIvx-like internal video
160: * -- should be zero if it is not used (usual case).
161: */
162: u_int32_t mac68k_vidlog; /* logical addr */
163: u_int32_t mac68k_vidphys; /* physical addr */
164: u_int32_t mac68k_vidlen; /* mem length */
165:
166: /* Callback and cookie to run bell */
167: int (*mac68k_bell_callback)(void *, int, int, int);
168: caddr_t mac68k_bell_cookie;
169:
170: struct vm_map *exec_map = NULL;
171: struct vm_map *phys_map = NULL;
172:
173: /*
174: * Declare these as initialized data so we can patch them.
175: */
176: #ifndef BUFCACHEPERCENT
177: #define BUFCACHEPERCENT 5
178: #endif
179:
180: #ifdef BUFPAGES
181: int bufpages = BUFPAGES;
182: #else
183: int bufpages = 0;
184: #endif
185: int bufcachepercent = BUFCACHEPERCENT;
186:
187: int physmem; /* size of physical memory, in pages */
188:
189: /*
190: * safepri is a safe priority for sleep to set for a spin-wait
191: * during autoconfiguration or after a panic.
192: */
193: int safepri = PSL_LOWIPL;
194:
195: /*
196: * Extent maps to manage all memory space, including I/O ranges. Allocate
197: * storage for 8 regions in each, initially. Later, iomem_malloc_safe
198: * will indicate that it's safe to use malloc() to dynamically allocate
199: * region descriptors.
200: *
201: * The extent maps are not static! Machine-dependent NuBus and on-board
202: * I/O routines need access to them for bus address space allocation.
203: */
204: long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
205: struct extent *iomem_ex;
206: int iomem_malloc_safe;
207:
208: /* XXX should be in locore.s for consistency */
209: int astpending = 0;
210:
211: void identifycpu(void);
212: u_long get_physical(u_int, u_long *);
213:
214: caddr_t allocsys(caddr_t);
215: void initcpu(void);
216: int cpu_dumpsize(void);
217: int cpu_dump(int (*)(dev_t, daddr64_t, caddr_t, size_t), daddr64_t *);
218: void cpu_init_kcore_hdr(void);
219: int fpu_probe(void);
220:
221: /* functions called from locore.s */
222: void dumpsys(void);
223: void mac68k_init(void);
224: void straytrap(int, int);
225: void nmihand(struct frame);
226:
227: /*
228: * Machine-dependent crash dump header info.
229: */
230: cpu_kcore_hdr_t cpu_kcore_hdr;
231:
232: /*
233: * Early initialization, before main() is called.
234: */
235: void
236: mac68k_init()
237: {
238: int i;
239: extern vaddr_t avail_start;
240:
241: /*
242: * Tell the VM system about available physical memory.
243: * Notice that we don't need to worry about avail_end here
244: * since it's equal to high[numranges-1].
245: */
246: for (i = 0; i < numranges; i++) {
247: if (low[i] <= avail_start && avail_start < high[i])
248: uvm_page_physload(atop(avail_start), atop(high[i]),
249: atop(avail_start), atop(high[i]),
250: VM_FREELIST_DEFAULT);
251: else
252: uvm_page_physload(atop(low[i]), atop(high[i]),
253: atop(low[i]), atop(high[i]),
254: VM_FREELIST_DEFAULT);
255: }
256:
257: /*
258: * Initialize the I/O mem extent map.
259: * Note: we don't have to check the return value since
260: * creation of a fixed extent map will never fail (since
261: * descriptor storage has already been allocated).
262: *
263: * N.B. The iomem extent manages _all_ physical addresses
264: * on the machine. When the amount of RAM is found, all
265: * extents of RAM are allocated from the map.
266: */
267: iomem_ex = extent_create("iomem", 0x0, 0xffffffff, M_DEVBUF,
268: (caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
269: EX_NOCOALESCE|EX_NOWAIT);
270:
271: /* Initialize the interrupt handlers. */
272: intr_init();
273:
274: /* Initialize the VIAs */
275: via_init();
276:
277: /* Initialize the PSC (if present) */
278: psc_init();
279: }
280:
281: /*
282: * Console initialization: called early on from main,
283: * before vm init or startup. Do enough configuration
284: * to choose and initialize a console.
285: */
286: void
287: consinit(void)
288: {
289: /*
290: * Generic console: sys/dev/cons.c
291: * Initializes either ite or ser as console.
292: * Can be called from locore.s and init_main.c. (Ugh.)
293: */
294: static int init; /* = 0 */
295:
296: if (!init) {
297: cninit();
298: #ifdef DDB
299: /*
300: * Initialize kernel debugger, if compiled in.
301: */
302: ddb_init();
303: #endif
304: init = 1;
305: } else {
306: #if NWSDISPLAY > 0
307: /*
308: * XXX This is an evil hack on top of an evil hack!
309: *
310: * With the graybar stuff, we've got a catch-22: we need
311: * to do at least some console setup really early on, even
312: * before we're running with the mappings we need. On
313: * the other hand, we're not nearly ready to do anything
314: * with wscons or the ADB driver at that point.
315: *
316: * To get around this, wscninit() ignores the first call
317: * it gets (from cninit(), if not on a serial console).
318: * Once we're here, we call wscninit() again, which sets
319: * up the console devices and does the appropriate wscons
320: * initialization.
321: */
322: if (mac68k_machine.serial_console == 0) {
323: cons_decl(ws);
324: wscninit(NULL);
325: }
326: #endif
327:
328: mac68k_calibrate_delay();
329:
330: #if NZSC > 0 && defined(KGDB)
331: zs_kgdb_init();
332: #endif
333:
334: if (boothowto & RB_KDB) {
335: #ifdef KGDB
336: /* XXX - Ask on console for kgdb_dev? */
337: /* Note: this will just return if kgdb_dev==NODEV */
338: kgdb_connect(1);
339: #else /* KGDB */
340: #ifdef DDB
341: /* Enter DDB. We don't have a monitor PROM. */
342: Debugger();
343: #endif /* DDB */
344: #endif /* KGDB */
345: }
346: }
347: }
348:
349: #define CURRENTBOOTERVER 111
350:
351: /*
352: * cpu_startup: allocate memory for variable-sized tables,
353: * initialize cpu, and do autoconfiguration.
354: */
355: void
356: cpu_startup(void)
357: {
358: caddr_t v;
359: unsigned i;
360: int vers;
361: vaddr_t minaddr, maxaddr;
362: vsize_t size = 0; /* To avoid compiler warning */
363: int delay;
364:
365: /*
366: * Initialize the kernel crash dump header.
367: */
368: cpu_init_kcore_hdr();
369:
370: /*
371: * Initialize error message buffer (at end of core).
372: * high[numranges-1] was decremented in pmap_bootstrap.
373: */
374: for (i = 0; i < btoc(MSGBUFSIZE); i++)
375: pmap_enter(pmap_kernel(), (vaddr_t)msgbufp + i * NBPG,
376: high[numranges - 1] + i * NBPG,
377: VM_PROT_READ|VM_PROT_WRITE,
378: VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
379: pmap_update(pmap_kernel());
380: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
381:
382: /*
383: * Good {morning,afternoon,evening,night}.
384: */
385: printf(version);
386: identifycpu();
387:
388: vers = mac68k_machine.booter_version;
389: if (vers < CURRENTBOOTERVER) {
390: /* fix older booters with indices, not versions */
391: if (vers < 100)
392: vers += 99;
393:
394: printf("\nYou booted with booter version %d.%d.\n",
395: vers / 100, vers % 100);
396: printf("Booter version %d.%d is necessary to fully support\n",
397: CURRENTBOOTERVER / 100, CURRENTBOOTERVER % 100);
398: printf("this kernel.\n\n");
399: for (delay = 0; delay < 1000000; delay++);
400: }
401: printf("real mem = %u (%uMB)\n", ctob(physmem),
402: ctob(physmem)/1024/1024);
403:
404: /*
405: * Find out how much space we need, allocate it,
406: * and then give everything true virtual addressses.
407: */
408: size = (vsize_t)allocsys((caddr_t)0);
409: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(size))) == 0)
410: panic("startup: no room for tables");
411: if ((allocsys(v) - v) != size)
412: panic("startup: table size inconsistency");
413:
414: /*
415: * Determine how many buffers to allocate.
416: * We allocate bufcachepercent% of memory for buffer space.
417: */
418: if (bufpages == 0)
419: bufpages = physmem * bufcachepercent / 100;
420:
421: /* Restrict to at most 25% filled kvm */
422: if (bufpages >
423: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
424: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
425: PAGE_SIZE / 4;
426:
427: /*
428: * Allocate a submap for exec arguments. This map effectively
429: * limits the number of processes exec'ing at any time.
430: */
431: minaddr = vm_map_min(kernel_map);
432: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
433: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
434:
435: /*
436: * Allocate a submap for physio
437: */
438: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
439: VM_PHYS_SIZE, 0, FALSE, NULL);
440:
441: printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
442: ptoa(uvmexp.free) / 1024 / 1024);
443:
444: /*
445: * Set up CPU-specific registers, cache, etc.
446: */
447: initcpu();
448:
449: /*
450: * Set up buffers, so they can be used to read disk labels.
451: */
452: bufinit();
453:
454: /*
455: * Configure the system.
456: */
457: if (boothowto & RB_CONFIG) {
458: #ifdef BOOT_CONFIG
459: user_config();
460: #else
461: printf("kernel does not support -c; continuing..\n");
462: #endif
463: }
464:
465: /* Safe for extent allocation to use malloc now. */
466: iomem_malloc_safe = 1;
467: }
468:
469: /*
470: * Allocate space for system data structures. We are given
471: * a starting virtual address and we return a final virtual
472: * address; along the way we set each data structure pointer.
473: *
474: * We call allocsys() with 0 to find out how much space we want,
475: * allocate that much and fill it with zeroes, and then call
476: * allocsys() again with the correct base virtual address.
477: */
478: caddr_t
479: allocsys(v)
480: caddr_t v;
481: {
482:
483: #define valloc(name, type, num) \
484: (name) = (type *)v; v = (caddr_t)((name)+(num))
485: #define valloclim(name, type, num, lim) \
486: (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
487:
488: #ifdef SYSVMSG
489: valloc(msgpool, char, msginfo.msgmax);
490: valloc(msgmaps, struct msgmap, msginfo.msgseg);
491: valloc(msghdrs, struct msg, msginfo.msgtql);
492: valloc(msqids, struct msqid_ds, msginfo.msgmni);
493: #endif
494:
495: return (v);
496: }
497:
498: void
499: initcpu()
500: {
501: #if defined(M68040)
502: extern void (*vectab[256])(void);
503: void addrerr4060(void);
504: #endif
505: #ifdef M68040
506: void buserr40(void);
507: #endif
508: #ifdef FPSP
509: extern u_long fpvect_tab, fpvect_end, fpsp_tab;
510: #endif
511:
512: switch (cputype) {
513: #ifdef M68040
514: case CPU_68040:
515: vectab[2] = buserr40;
516: vectab[3] = addrerr4060;
517: #ifdef FPSP
518: bcopy(&fpsp_tab, &fpvect_tab,
519: (&fpvect_end - &fpvect_tab) * sizeof (fpvect_tab));
520: #endif
521: break;
522: #endif
523: default:
524: break;
525: }
526:
527: DCIS();
528: }
529:
530: void doboot(void)
531: __attribute__((__noreturn__));
532:
533: int waittime = -1;
534:
535: void
536: boot(howto)
537: int howto;
538: {
539: extern u_long maxaddr;
540:
541: /* take a snap shot before clobbering any registers */
542: if (curproc && curproc->p_addr)
543: savectx(&curproc->p_addr->u_pcb);
544:
545: /* If system is cold, just halt. */
546: if (cold) {
547: /* (Unless the user explicitly asked for reboot.) */
548: if ((howto & RB_USERREQ) == 0)
549: howto |= RB_HALT;
550: goto haltsys;
551: }
552:
553: boothowto = howto;
554: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
555: waittime = 0;
556: vfs_shutdown();
557:
558: if (mac68k_machine.aux_interrupts != 0) {
559: /*
560: * If we've been adjusting the clock, the todr
561: * will be out of synch; adjust it now unless
562: * the system was sitting in ddb.
563: */
564: if ((howto & RB_TIMEBAD) == 0) {
565: resettodr();
566: } else {
567: printf("WARNING: not updating battery clock\n");
568: }
569: } else {
570: #ifdef DIAGNOSTIC
571: printf("OpenBSD/mac68k does not trust itself to update"
572: " the clock on shutdown on this machine.\n");
573: #endif
574: }
575: }
576:
577: /* Disable interrupts. */
578: splhigh();
579:
580: /* If rebooting and a dump is requested, do it. */
581: if (howto & RB_DUMP) {
582: dumpsys();
583: }
584:
585: haltsys:
586: /* Run any shutdown hooks. */
587: doshutdownhooks();
588:
589: if (howto & RB_HALT) {
590: if (howto & RB_POWERDOWN) {
591: printf("\nAttempting to power down...\n");
592: via_powerdown();
593: /*
594: * Shut down machines whose power functions
595: * are accessed via modified ADB calls.
596: */
597: adb_poweroff();
598: }
599: printf("\nThe operating system has halted.\n");
600: printf("Please press any key to reboot.\n\n");
601: (void)cngetc();
602: }
603:
604: /* Map the last physical page VA = PA for doboot() */
605: pmap_enter(pmap_kernel(), (vaddr_t)maxaddr, (vaddr_t)maxaddr,
606: VM_PROT_ALL, VM_PROT_ALL|PMAP_WIRED);
607: pmap_update(pmap_kernel());
608:
609: printf("rebooting...\n");
610: DELAY(1000000);
611: doboot();
612: /* NOTREACHED */
613: }
614:
615: /*
616: * Initialize the kernel crash dump header.
617: */
618: void
619: cpu_init_kcore_hdr()
620: {
621: cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
622: int i;
623:
624: bzero(&cpu_kcore_hdr, sizeof(cpu_kcore_hdr));
625:
626: h->mmutype = mmutype;
627: h->kernel_pa = low[0];
628: h->sysseg_pa = pmap_kernel()->pm_stpa;
629:
630: /*
631: * mac68k has multiple RAM segments on some models.
632: */
633: for (i = 0; i < numranges; i++) {
634: h->ram_segs[i].start = low[i];
635: h->ram_segs[i].size = high[i] - low[i];
636: }
637: }
638:
639: /*
640: * Compute the size of the machine-dependent crash dump header.
641: * Returns size in disk blocks.
642: */
643: int
644: cpu_dumpsize()
645: {
646: int size;
647:
648: size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t));
649: return (btodb(roundup(size, dbtob(1))));
650: }
651:
652: /*
653: * Called by dumpsys() to dump the machine-dependent header.
654: */
655: int
656: cpu_dump(dump, blknop)
657: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
658: daddr64_t *blknop;
659: {
660: int buf[dbtob(1) / sizeof(int)];
661: cpu_kcore_hdr_t *chdr;
662: kcore_seg_t *kseg;
663: int error;
664:
665: kseg = (kcore_seg_t *)buf;
666: chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
667: sizeof(int)];
668:
669: /* Create the segment header. */
670: CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
671: kseg->c_size = dbtob(1) - ALIGN(sizeof(kcore_seg_t));
672:
673: bcopy(&cpu_kcore_hdr, chdr, sizeof(cpu_kcore_hdr_t));
674: error = (*dump)(dumpdev, *blknop, (caddr_t)buf, sizeof(buf));
675: *blknop += btodb(sizeof(buf));
676: return (error);
677: }
678:
679: /*
680: * These variables are needed by /sbin/savecore
681: */
682: u_long dumpmag = 0x8fca0101; /* magic number */
683: int dumpsize = 0; /* pages */
684: long dumplo = 0; /* blocks */
685:
686: /*
687: * This is called by main to set dumplo and dumpsize.
688: * Dumps always skip the first block of disk space in
689: * case there might be a disk label stored there. If there
690: * is extra space, put dump at the end to reduce the chance
691: * that swapping trashes it.
692: */
693: void
694: dumpconf(void)
695: {
696: cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
697: int nblks; /* size of dump area */
698: int i;
699:
700: if (dumpdev == NODEV ||
701: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
702: return;
703: if (nblks <= ctod(1))
704: return;
705:
706: dumpsize = 0;
707: for (i = 0; h->ram_segs[i].size && i < NPHYS_RAM_SEGS; i++)
708: dumpsize += btoc(h->ram_segs[i].size);
709: dumpsize += cpu_dumpsize();
710:
711: /* Always skip the first block, in case there is a label there. */
712: if (dumplo < ctod(1))
713: dumplo = ctod(1);
714:
715: /* Put dump at end of partition, and make it fit. */
716: if (dumpsize > dtoc(nblks - dumplo))
717: dumpsize = dtoc(nblks - dumplo);
718: if (dumplo < nblks - ctod(dumpsize))
719: dumplo = nblks - ctod(dumpsize);
720: }
721:
722: void
723: dumpsys()
724: {
725: cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
726: daddr64_t blkno; /* current block to write */
727: /* dump routine */
728: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
729: int pg; /* page being dumped */
730: vaddr_t maddr; /* PA being dumped */
731: int seg; /* RAM segment being dumped */
732: int error; /* error code from (*dump)() */
733: extern int msgbufmapped;
734:
735: /* XXX initialized here because of gcc lossage */
736: seg = 0;
737: maddr = h->ram_segs[seg].start;
738: pg = 0;
739:
740: /* Don't record dump msgs in msgbuf. */
741: msgbufmapped = 0;
742:
743: /* Make sure dump device is valid. */
744: if (dumpdev == NODEV)
745: return;
746: if (dumpsize == 0) {
747: dumpconf();
748: if (dumpsize == 0)
749: return;
750: }
751: if (dumplo <= 0) {
752: printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
753: minor(dumpdev));
754: return;
755: }
756: dump = bdevsw[major(dumpdev)].d_dump;
757: blkno = dumplo;
758:
759: printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
760: minor(dumpdev), dumplo);
761:
762: printf("dump ");
763:
764: /* Write the dump header. */
765: error = cpu_dump(dump, &blkno);
766: if (error)
767: goto bad;
768:
769: for (pg = 0; pg < dumpsize; pg++) {
770: #define NPGMB (1024*1024/NBPG)
771: /* print out how many MBs we have dumped */
772: if (pg && (pg % NPGMB) == 0)
773: printf("%d ", pg / NPGMB);
774: #undef NPGMB
775: while (maddr >=
776: (h->ram_segs[seg].start + h->ram_segs[seg].size)) {
777: if (++seg >= NPHYS_RAM_SEGS ||
778: h->ram_segs[seg].size == 0) {
779: error = EINVAL; /* XXX ?? */
780: goto bad;
781: }
782: maddr = h->ram_segs[seg].start;
783: }
784: pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
785: VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
786: pmap_update(pmap_kernel());
787:
788: error = (*dump)(dumpdev, blkno, vmmap, NBPG);
789: bad:
790: switch (error) {
791: case 0:
792: maddr += NBPG;
793: blkno += btodb(NBPG);
794: break;
795:
796: case ENXIO:
797: printf("device bad\n");
798: return;
799:
800: case EFAULT:
801: printf("device not ready\n");
802: return;
803:
804: case EINVAL:
805: printf("area improper\n");
806: return;
807:
808: case EIO:
809: printf("i/o error\n");
810: return;
811:
812: case EINTR:
813: printf("aborted from console\n");
814: return;
815:
816: default:
817: printf("error %d\n", error);
818: return;
819: }
820: }
821: printf("succeeded\n");
822: }
823:
824: /*
825: * Return the best possible estimate of the time in the timeval
826: * to which tvp points. We do this by returning the current time
827: * plus the amount of time since the last clock interrupt (clock.c:clkread).
828: *
829: * Check that this time is no less than any previously-reported time,
830: * which could happen around the time of a clock adjustment. Just for fun,
831: * we guarantee that the time will be greater than the value obtained by a
832: * previous call.
833: */
834: void
835: microtime(tvp)
836: register struct timeval *tvp;
837: {
838: int s = splhigh();
839: static struct timeval lasttime;
840:
841: *tvp = time;
842: tvp->tv_usec += clkread();
843: while (tvp->tv_usec >= 1000000) {
844: tvp->tv_sec++;
845: tvp->tv_usec -= 1000000;
846: }
847: if (tvp->tv_sec == lasttime.tv_sec &&
848: tvp->tv_usec <= lasttime.tv_usec &&
849: (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
850: tvp->tv_sec++;
851: tvp->tv_usec -= 1000000;
852: }
853: lasttime = *tvp;
854: splx(s);
855: }
856:
857: void
858: straytrap(pc, evec)
859: int pc;
860: int evec;
861: {
862: printf("unexpected trap; vector offset 0x%x from 0x%x.\n",
863: (int) (evec & 0xfff), pc);
864: #ifdef DEBUG
865: #ifdef DDB
866: Debugger();
867: #endif
868: #endif
869: }
870:
871: int *nofault;
872:
873: /*
874: * Level 7 interrupts can be caused by the keyboard or parity errors.
875: */
876: void nmihand(struct frame);
877:
878: void
879: nmihand(frame)
880: struct frame frame;
881: {
882: static int nmihanddeep = 0;
883:
884: if (nmihanddeep)
885: return;
886: nmihanddeep = 1;
887:
888: #ifdef DDB
889: if (db_console)
890: Debugger();
891: #endif
892:
893: nmihanddeep = 0;
894: }
895:
896: /*
897: * It should be possible to probe for the top of RAM, but Apple has
898: * memory structured so that in at least some cases, it's possible
899: * for RAM to be aliased across all memory--or for it to appear that
900: * there is more RAM than there really is.
901: */
902: int get_top_of_ram(void);
903:
904: int
905: get_top_of_ram()
906: {
907: return ((mac68k_machine.mach_memsize * (1024 * 1024)) - 4096);
908: }
909:
910: /*
911: * machine dependent system variables.
912: */
913: int
914: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
915: int *name;
916: u_int namelen;
917: void *oldp;
918: size_t *oldlenp;
919: void *newp;
920: size_t newlen;
921: struct proc *p;
922: {
923: dev_t consdev;
924:
925: /* all sysctl names at this level are terminal */
926: if (namelen != 1)
927: return (ENOTDIR); /* overloaded */
928:
929: switch (name[0]) {
930: case CPU_CONSDEV:
931: if (cn_tab != NULL)
932: consdev = cn_tab->cn_dev;
933: else
934: consdev = NODEV;
935: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
936: sizeof consdev));
937: default:
938: return (EOPNOTSUPP);
939: }
940: /* NOTREACHED */
941: }
942:
943: int
944: cpu_exec_aout_makecmds(p, epp)
945: struct proc *p;
946: struct exec_package *epp;
947: {
948: int error = ENOEXEC;
949:
950: #ifdef COMPAT_SUNOS
951: {
952: extern int sunos_exec_aout_makecmds(struct proc *,
953: struct exec_package *);
954: if ((error = sunos_exec_aout_makecmds(p, epp)) == 0)
955: return 0;
956: }
957: #endif
958: return error;
959: }
960:
961: static char *envbuf = NULL;
962:
963: /*
964: * getenvvars: Grab a few useful variables
965: */
966: void getenvvars(u_long, char *);
967: long getenv(char *);
968:
969: void
970: getenvvars(flag, buf)
971: u_long flag;
972: char *buf;
973: {
974: extern u_long bootdev;
975: #if defined(DDB) || NKSYMS > 0
976: extern u_long end, esym;
977: #endif
978: extern u_long macos_boottime;
979: extern vaddr_t MacOSROMBase;
980: extern long macos_gmtbias;
981: extern u_short ADBDelay;
982: extern u_int32_t HwCfgFlags3;
983: int root_scsi_id;
984: vaddr_t ROMBase;
985:
986: /*
987: * If flag & 0x80000000 == 0, then we're booting with the old booter
988: * and we should freak out.
989: */
990: if ((flag & 0x80000000) == 0) {
991: /* Freak out; print something if that becomes available */
992: } else
993: envbuf = buf;
994:
995: /* These next two should give us mapped video & serial */
996: /* We need these for pre-mapping graybars & echo, but probably */
997: /* only on MacII or LC. -- XXX */
998: /* videoaddr = getenv("MACOS_VIDEO"); */
999:
1000: /*
1001: * The following are not in a structure so that they can be
1002: * accessed more quickly.
1003: */
1004: videoaddr = getenv("VIDEO_ADDR");
1005: videorowbytes = getenv("ROW_BYTES");
1006: videobitdepth = getenv("SCREEN_DEPTH");
1007: videosize = getenv("DIMENSIONS");
1008:
1009: /*
1010: * More misc stuff from booter.
1011: */
1012: mac68k_machine.machineid = getenv("MACHINEID");
1013: mac68k_machine.mach_memsize = getenv("MEMSIZE");
1014: mac68k_machine.do_graybars = getenv("GRAYBARS");
1015: mac68k_machine.serial_boot_echo = getenv("SERIALECHO");
1016: mac68k_machine.serial_console = getenv("SERIALCONSOLE");
1017:
1018: mac68k_machine.modem_flags = getenv("SERIAL_MODEM_FLAGS");
1019: mac68k_machine.modem_cts_clk = getenv("SERIAL_MODEM_HSKICLK");
1020: mac68k_machine.modem_dcd_clk = getenv("SERIAL_MODEM_GPICLK");
1021: mac68k_machine.modem_flags = getenv("SERIAL_MODEM_DSPEED");
1022: mac68k_machine.print_flags = getenv("SERIAL_PRINT_FLAGS");
1023: mac68k_machine.print_cts_clk = getenv("SERIAL_PRINT_HSKICLK");
1024: mac68k_machine.print_dcd_clk = getenv("SERIAL_PRINT_GPICLK");
1025: mac68k_machine.print_d_speed = getenv("SERIAL_PRINT_DSPEED");
1026: mac68k_machine.booter_version = getenv("BOOTERVER");
1027:
1028: /*
1029: * For now, we assume that the boot device is off the first controller.
1030: * Booter versions 1.11.0 and later set a flag to tell us to construct
1031: * bootdev using the SCSI ID passed in via the environment.
1032: */
1033: root_scsi_id = getenv("ROOT_SCSI_ID");
1034: if (((mac68k_machine.booter_version < CURRENTBOOTERVER) ||
1035: (flag & 0x40000)) && bootdev == 0)
1036: bootdev = MAKEBOOTDEV(4, 0, 0, root_scsi_id, 0);
1037:
1038: /*
1039: * Booter 1.11.3 and later pass a BOOTHOWTO variable with the
1040: * appropriate bits set.
1041: */
1042: boothowto = getenv("BOOTHOWTO");
1043: if (boothowto == 0)
1044: boothowto = getenv("SINGLE_USER");
1045:
1046: /*
1047: * Get end of symbols for kernel debugging
1048: */
1049: #if defined(DDB) || NKSYMS > 0
1050: esym = getenv("END_SYM");
1051: if (esym == 0)
1052: esym = (long) &end;
1053: #endif
1054:
1055: /* Get MacOS time */
1056: macos_boottime = getenv("BOOTTIME");
1057:
1058: /* Save GMT BIAS saved in Booter parameters dialog box */
1059: macos_gmtbias = getenv("GMTBIAS");
1060:
1061: /*
1062: * Save globals stolen from MacOS
1063: */
1064:
1065: ROMBase = (vaddr_t)getenv("ROMBASE");
1066: if (ROMBase != 0)
1067: MacOSROMBase = ROMBase;
1068: ADBDelay = (u_short) getenv("ADBDELAY");
1069: HwCfgFlags3 = getenv("HWCFGFLAG3");
1070: }
1071:
1072: char toupper(char);
1073:
1074: char
1075: toupper(c)
1076: char c;
1077: {
1078: if (c >= 'a' && c <= 'z') {
1079: return c - 'a' + 'A';
1080: } else {
1081: return c;
1082: }
1083: }
1084:
1085: long
1086: getenv(str)
1087: char *str;
1088: {
1089: /*
1090: * Returns the value of the environment variable "str".
1091: *
1092: * Format of the buffer is "var=val\0var=val\0...\0var=val\0\0".
1093: *
1094: * Returns 0 if the variable is not there, and 1 if the variable is
1095: * there without an "=val".
1096: */
1097:
1098: char *s, *s1;
1099: int val, base;
1100:
1101: s = envbuf;
1102: while (1) {
1103: for (s1 = str; *s1 && *s && *s != '='; s1++, s++) {
1104: if (toupper(*s1) != toupper(*s)) {
1105: break;
1106: }
1107: }
1108: if (*s1) { /* No match */
1109: while (*s) {
1110: s++;
1111: }
1112: s++;
1113: if (*s == '\0') { /* Not found */
1114: /* Boolean flags are FALSE (0) if not there */
1115: return 0;
1116: }
1117: continue;
1118: }
1119: if (*s == '=') {/* Has a value */
1120: s++;
1121: val = 0;
1122: base = 10;
1123: if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) {
1124: base = 16;
1125: s += 2;
1126: } else
1127: if (*s == '0') {
1128: base = 8;
1129: }
1130: while (*s) {
1131: if (toupper(*s) >= 'A' && toupper(*s) <= 'F') {
1132: val = val * base + toupper(*s) - 'A' + 10;
1133: } else {
1134: val = val * base + (*s - '0');
1135: }
1136: s++;
1137: }
1138: return val;
1139: } else { /* TRUE (1) */
1140: return 1;
1141: }
1142: }
1143: }
1144:
1145: struct cpu_model_info cpu_models[] = {
1146:
1147: /* The first four. */
1148: { MACH_MACII, "II", MACH_CLASSII },
1149: { MACH_MACIIX, "IIx", MACH_CLASSII },
1150: { MACH_MACIICX, "IIcx", MACH_CLASSII },
1151: { MACH_MACSE30, "SE/30", MACH_CLASSII },
1152:
1153: /* The rest of the II series... */
1154: { MACH_MACIICI, "IIci", MACH_CLASSIIci },
1155: { MACH_MACIISI, "IIsi", MACH_CLASSIIsi },
1156: { MACH_MACIIVI, "IIvi", MACH_CLASSIIvx },
1157: { MACH_MACIIVX, "IIvx", MACH_CLASSIIvx },
1158: { MACH_MACIIFX, "IIfx", MACH_CLASSIIfx },
1159:
1160: /* The Centris/Quadra series. */
1161: { MACH_MACQ700, "Quadra 700", MACH_CLASSQ },
1162: { MACH_MACQ900, "Quadra 900", MACH_CLASSQ },
1163: { MACH_MACQ950, "Quadra 950", MACH_CLASSQ },
1164: { MACH_MACQ800, "Quadra 800", MACH_CLASSQ },
1165: { MACH_MACQ650, "Quadra 650", MACH_CLASSQ },
1166: { MACH_MACC650, "Centris 650", MACH_CLASSQ },
1167: { MACH_MACQ605, "Quadra 605", MACH_CLASSQ },
1168: { MACH_MACQ605_33, "Quadra 605/33", MACH_CLASSQ },
1169: { MACH_MACC610, "Centris 610", MACH_CLASSQ },
1170: { MACH_MACQ610, "Quadra 610", MACH_CLASSQ },
1171: { MACH_MACQ630, "Quadra 630", MACH_CLASSQ2 },
1172: { MACH_MACC660AV, "Centris 660AV", MACH_CLASSAV },
1173: { MACH_MACQ840AV, "Quadra 840AV", MACH_CLASSAV },
1174:
1175: /* The Powerbooks/Duos... */
1176: { MACH_MACPB100, "PowerBook 100", MACH_CLASSPB },
1177: /* PB 100 has no MMU! */
1178: { MACH_MACPB140, "PowerBook 140", MACH_CLASSPB },
1179: { MACH_MACPB145, "PowerBook 145", MACH_CLASSPB },
1180: { MACH_MACPB150, "PowerBook 150", MACH_CLASSDUO },
1181: { MACH_MACPB160, "PowerBook 160", MACH_CLASSPB },
1182: { MACH_MACPB165, "PowerBook 165", MACH_CLASSPB },
1183: { MACH_MACPB165C, "PowerBook 165c", MACH_CLASSPB },
1184: { MACH_MACPB170, "PowerBook 170", MACH_CLASSPB },
1185: { MACH_MACPB180, "PowerBook 180", MACH_CLASSPB },
1186: { MACH_MACPB180C, "PowerBook 180c", MACH_CLASSPB },
1187: { MACH_MACPB190, "PowerBook 190", MACH_CLASSPB },
1188: { MACH_MACPB190CS, "PowerBook 190cs", MACH_CLASSPB },
1189: { MACH_MACPB500, "PowerBook 500", MACH_CLASSPB },
1190:
1191: /* The Duos */
1192: { MACH_MACPB210, "PowerBook Duo 210", MACH_CLASSDUO },
1193: { MACH_MACPB230, "PowerBook Duo 230", MACH_CLASSDUO },
1194: { MACH_MACPB250, "PowerBook Duo 250", MACH_CLASSDUO },
1195: { MACH_MACPB270, "PowerBook Duo 270C", MACH_CLASSDUO },
1196: { MACH_MACPB280, "PowerBook Duo 280", MACH_CLASSDUO },
1197: { MACH_MACPB280C, "PowerBook Duo 280C", MACH_CLASSDUO },
1198:
1199: /* The Performas... */
1200: { MACH_MACP600, "Performa 600", MACH_CLASSIIvx },
1201: { MACH_MACP460, "Performa 460", MACH_CLASSLC },
1202: { MACH_MACP550, "Performa 550", MACH_CLASSLC },
1203: { MACH_MACP580, "Performa 580", MACH_CLASSQ2 },
1204: { MACH_MACTV, "TV", MACH_CLASSLC },
1205:
1206: /* The LCs... */
1207: { MACH_MACLCII, "LC II", MACH_CLASSLC },
1208: { MACH_MACLCIII, "LC III", MACH_CLASSLC },
1209: { MACH_MACLC475, "LC 475", MACH_CLASSQ },
1210: { MACH_MACLC475_33, "LC 475/33", MACH_CLASSQ },
1211: { MACH_MACLC520, "LC 520", MACH_CLASSLC },
1212: { MACH_MACLC575, "LC 575", MACH_CLASSQ2 },
1213: { MACH_MACCCLASSIC, "Color Classic", MACH_CLASSLC },
1214: { MACH_MACCCLASSICII, "Color ClassicII", MACH_CLASSLC },
1215: /* Does this belong here? */
1216: { MACH_MACCLASSICII, "Classic II", MACH_CLASSLC },
1217:
1218: /* The unknown one and the end... */
1219: { 0, "Unknown", MACH_CLASSII }
1220: }; /* End of cpu_models[] initialization. */
1221:
1222: struct intvid_info_t {
1223: int machineid;
1224: u_long fbbase;
1225: u_long fbmask;
1226: u_long fblen;
1227: } intvid_info[] = {
1228: { MACH_MACCLASSICII, 0x009f9a80, 0x0, 21888 },
1229: { MACH_MACPB140, 0xfee08000, 0x0, 32 * 1024 },
1230: { MACH_MACPB145, 0xfee08000, 0x0, 32 * 1024 },
1231: { MACH_MACPB170, 0xfee08000, 0x0, 32 * 1024 },
1232: { MACH_MACPB150, 0x60000000, 0x0, 128 * 1024 },
1233: { MACH_MACPB160, 0x60000000, 0x0ffe0000, 128 * 1024 },
1234: { MACH_MACPB165, 0x60000000, 0x0ffe0000, 128 * 1024 },
1235: { MACH_MACPB180, 0x60000000, 0x0ffe0000, 128 * 1024 },
1236: { MACH_MACPB210, 0x60000000, 0x0, 128 * 1024 },
1237: { MACH_MACPB230, 0x60000000, 0x0, 128 * 1024 },
1238: { MACH_MACPB250, 0x60000000, 0x0, 128 * 1024 },
1239: { MACH_MACPB270, 0x60000000, 0x0, 128 * 1024 },
1240: { MACH_MACPB280, 0x60000000, 0x0, 128 * 1024 },
1241: { MACH_MACPB280C, 0x60000000, 0x0, 128 * 1024 },
1242: { MACH_MACIICI, 0x0, 0x0, 320 * 1024 },
1243: { MACH_MACIISI, 0x0, 0x0, 320 * 1024 },
1244: { MACH_MACCCLASSIC, 0x50f40000, 0x0, 512 * 1024 },
1245: /*??*/ { MACH_MACLCII, 0x50f40000, 0x0, 512 * 1024 },
1246: { MACH_MACPB165C, 0xfc040000, 0x0, 512 * 1024 },
1247: { MACH_MACPB180C, 0xfc040000, 0x0, 512 * 1024 },
1248: { MACH_MACPB190, 0x60000000, 0x0, 512 * 1024 },
1249: { MACH_MACPB190CS, 0x60000000, 0x0, 512 * 1024 },
1250: { MACH_MACPB500, 0x60000000, 0x0, 512 * 1024 },
1251: { MACH_MACLCIII, 0x60b00000, 0x0, 768 * 1024 },
1252: { MACH_MACLC520, 0x60000000, 0x0, 1024 * 1024 },
1253: { MACH_MACP550, 0x60000000, 0x0, 1024 * 1024 },
1254: { MACH_MACTV, 0x60000000, 0x0, 1024 * 1024 },
1255: { MACH_MACLC475, 0xf9000000, 0x0, 1024 * 1024 },
1256: { MACH_MACLC475_33, 0xf9000000, 0x0, 1024 * 1024 },
1257: { MACH_MACLC575, 0xf9000000, 0x0, 1024 * 1024 },
1258: { MACH_MACC610, 0xf9000000, 0x0, 1024 * 1024 },
1259: { MACH_MACC650, 0xf9000000, 0x0, 1024 * 1024 },
1260: { MACH_MACP580, 0xf9000000, 0x0, 1024 * 1024 },
1261: { MACH_MACQ605, 0xf9000000, 0x0, 1024 * 1024 },
1262: { MACH_MACQ605_33, 0xf9000000, 0x0, 1024 * 1024 },
1263: { MACH_MACQ610, 0xf9000000, 0x0, 1024 * 1024 },
1264: { MACH_MACQ630, 0xf9000000, 0x0, 1024 * 1024 },
1265: { MACH_MACQ650, 0xf9000000, 0x0, 1024 * 1024 },
1266: { MACH_MACC660AV, 0x50100000, 0x0, 1024 * 1024 },
1267: { MACH_MACQ700, 0xf9000000, 0x0, 1024 * 1024 },
1268: { MACH_MACQ800, 0xf9000000, 0x0, 1024 * 1024 },
1269: { MACH_MACQ900, 0xf9000000, 0x0, 1024 * 1024 },
1270: { MACH_MACQ950, 0xf9000000, 0x0, 1024 * 1024 },
1271: { MACH_MACQ840AV, 0x50100000, 0x0, 2048 * 1024 },
1272: { 0, 0x0, 0x0, 0 },
1273: }; /* End of intvid_info[] initialization. */
1274:
1275: /*
1276: * Missing Mac Models:
1277: * PowerMac 6100
1278: * PowerMac 7100
1279: * PowerMac 8100
1280: * PowerBook 540
1281: * PowerBook 520
1282: * PowerBook 150
1283: * Duo 280
1284: * Performa 6000s
1285: * ...?
1286: */
1287:
1288: char cpu_model[120]; /* for sysctl() */
1289:
1290: int
1291: fpu_probe()
1292: {
1293: /*
1294: * A 68881 idle frame is 28 bytes and a 68882's is 60 bytes.
1295: * We, of course, need to have enough room for either.
1296: */
1297: int fpframe[60 / sizeof(int)];
1298: label_t faultbuf;
1299: u_char b;
1300:
1301: nofault = (int *) &faultbuf;
1302: if (setjmp(&faultbuf)) {
1303: nofault = (int *) 0;
1304: return (FPU_NONE);
1305: }
1306:
1307: /*
1308: * Synchronize FPU or cause a fault.
1309: * This should leave the 881/882 in the IDLE state,
1310: * state, so we can determine which we have by
1311: * examining the size of the FP state frame
1312: */
1313: asm("fnop");
1314:
1315: nofault = (int *) 0;
1316:
1317: /*
1318: * Presumably, if we're an 040 and did not take exception
1319: * above, we have an FPU. Don't bother probing.
1320: */
1321: if (mmutype == MMU_68040)
1322: return (FPU_68040);
1323:
1324: /*
1325: * Presumably, this will not cause a fault--the fnop should
1326: * have if this will. We save the state in order to get the
1327: * size of the frame.
1328: */
1329: asm("movl %0, a0; fsave a0@" : : "a" (fpframe) : "a0" );
1330:
1331: b = *((u_char *) fpframe + 1);
1332:
1333: /*
1334: * Now, restore a NULL state to reset the FPU.
1335: */
1336: fpframe[0] = fpframe[1] = 0;
1337: m68881_restore((struct fpframe *) fpframe);
1338:
1339: /*
1340: * The size of a 68881 IDLE frame is 0x18
1341: * and a 68882 frame is 0x38
1342: */
1343: if (b == 0x18)
1344: return (FPU_68881);
1345: if (b == 0x38)
1346: return (FPU_68882);
1347:
1348: /*
1349: * If it's not one of the above, we have no clue what it is.
1350: */
1351: return (FPU_UNKNOWN);
1352: }
1353:
1354: void
1355: identifycpu()
1356: {
1357: #ifdef DEBUG
1358: extern u_int delay_factor;
1359: #endif
1360:
1361: /*
1362: * Print the machine type...
1363: */
1364: snprintf(cpu_model, sizeof cpu_model, "Apple Macintosh %s",
1365: cpu_models[mac68k_machine.cpu_model_index].model);
1366:
1367: /*
1368: * ... and the CPU type...
1369: */
1370: switch (cputype) {
1371: case CPU_68040:
1372: strlcat(cpu_model, ", 68040 CPU", sizeof cpu_model);
1373: break;
1374: case CPU_68030:
1375: strlcat(cpu_model, ", 68030 CPU", sizeof cpu_model);
1376: break;
1377: case CPU_68020:
1378: strlcat(cpu_model, ", 68020 CPU", sizeof cpu_model);
1379: break;
1380: default:
1381: strlcat(cpu_model, ", unknown CPU", sizeof cpu_model);
1382: break;
1383: }
1384:
1385: /*
1386: * ... and the MMU type...
1387: */
1388: switch (mmutype) {
1389: case MMU_68040:
1390: case MMU_68030:
1391: strlcat(cpu_model, "+MMU", sizeof cpu_model);
1392: break;
1393: case MMU_68851:
1394: strlcat(cpu_model, ", MC68851 MMU", sizeof cpu_model);
1395: break;
1396: default:
1397: printf("%s\n", cpu_model);
1398: panic("unknown MMU type %d", mmutype);
1399: /* NOTREACHED */
1400: }
1401:
1402: /*
1403: * ... and the FPU type...
1404: */
1405: fputype = fpu_probe(); /* should eventually move to locore */
1406:
1407: switch (fputype) {
1408: case FPU_68040:
1409: strlcat(cpu_model, "+FPU", sizeof cpu_model);
1410: break;
1411: case FPU_68882:
1412: strlcat(cpu_model, ", MC6882 FPU", sizeof cpu_model);
1413: break;
1414: case FPU_68881:
1415: strlcat(cpu_model, ", MC6881 FPU", sizeof cpu_model);
1416: break;
1417: case FPU_UNKNOWN:
1418: strlcat(cpu_model, ", unknown FPU", sizeof cpu_model);
1419: break;
1420: default:
1421: /*strlcat(cpu_model, ", no FPU", sizeof cpu_model);*/
1422: break;
1423: }
1424:
1425: /*
1426: * ... and finally, the cache type.
1427: */
1428: if (cputype == CPU_68040)
1429: strlcat(cpu_model, ", 4k on-chip physical I/D caches", sizeof cpu_model);
1430:
1431: printf("%s\n", cpu_model);
1432: #ifdef DEBUG
1433: printf("cpu: delay factor %d\n", delay_factor);
1434: #endif
1435: }
1436:
1437: void get_machine_info(void);
1438:
1439: void
1440: get_machine_info()
1441: {
1442: int i;
1443:
1444: for (i = 0; cpu_models[i].machineid != 0; i++)
1445: if (mac68k_machine.machineid == cpu_models[i].machineid)
1446: break;
1447:
1448: mac68k_machine.cpu_model_index = i;
1449: }
1450:
1451: const struct cpu_model_info *current_mac_model;
1452:
1453: /*
1454: * Sets a bunch of machine-specific variables
1455: */
1456: void setmachdep(void);
1457:
1458: void
1459: setmachdep()
1460: {
1461: struct cpu_model_info *cpui;
1462:
1463: /*
1464: * First, set things that need to be set on the first pass only
1465: * Ideally, we'd only call this once, but for some reason, the
1466: * VIAs need interrupts turned off twice !?
1467: */
1468: get_machine_info();
1469:
1470: load_addr = 0;
1471: cpui = &(cpu_models[mac68k_machine.cpu_model_index]);
1472: current_mac_model = cpui;
1473:
1474: mac68k_machine.via1_ipl = 1;
1475: mac68k_machine.aux_interrupts = 0;
1476:
1477: /*
1478: * Set up any machine specific stuff that we have to before
1479: * ANYTHING else happens
1480: */
1481: switch (cpui->class) { /* Base this on class of machine... */
1482: case MACH_CLASSII:
1483: VIA2 = VIA2OFF;
1484: IOBase = 0x50f00000;
1485: Via1Base = (volatile u_char *)IOBase;
1486: mac68k_machine.scsi80 = 1;
1487: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
1488: via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
1489: break;
1490: case MACH_CLASSPB:
1491: VIA2 = VIA2OFF;
1492: IOBase = 0x50f00000;
1493: Via1Base = (volatile u_char *)IOBase;
1494: mac68k_machine.scsi80 = 1;
1495: /* Disable everything but PM; we need it. */
1496: via_reg(VIA1, vIER) = 0x6f; /* disable VIA1 int */
1497: /* Are we disabling something important? */
1498: via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
1499: if (cputype == CPU_68040)
1500: mac68k_machine.sonic = 1;
1501: break;
1502: case MACH_CLASSDUO:
1503: /*
1504: * The Duo definitely does not use a VIA2, but it looks
1505: * like the VIA2 functions might be on the MSC at the RBV
1506: * locations. The rest is copied from the Powerbooks.
1507: */
1508: VIA2 = RBVOFF;
1509: IOBase = 0x50f00000;
1510: Via1Base = (volatile u_char *)IOBase;
1511: mac68k_machine.scsi80 = 1;
1512: /* Disable everything but PM; we need it. */
1513: via_reg(VIA1, vIER) = 0x6f; /* disable VIA1 int */
1514: /* Are we disabling something important? */
1515: via_reg(VIA2, rIER) = 0x7f; /* disable VIA2 int */
1516: break;
1517: case MACH_CLASSQ:
1518: case MACH_CLASSQ2:
1519: VIA2 = VIA2OFF;
1520: IOBase = 0x50f00000;
1521: Via1Base = (volatile u_char *)IOBase;
1522: mac68k_machine.sonic = 1;
1523: mac68k_machine.scsi96 = 1;
1524: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
1525: via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
1526:
1527: /* Enable A/UX interrupt scheme */
1528: mac68k_machine.aux_interrupts = 1;
1529: via_reg(VIA1, vBufB) &= (0xff ^ DB1O_AuxIntEnb);
1530: via_reg(VIA1, vDirB) |= DB1O_AuxIntEnb;
1531: mac68k_machine.via1_ipl = 6;
1532:
1533: break;
1534: case MACH_CLASSAV:
1535: VIA2 = VIA2OFF;
1536: IOBase = 0x50f00000;
1537: Via1Base = (volatile u_char *)IOBase;
1538: mac68k_machine.scsi96 = 1;
1539: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
1540: via_reg(VIA2, vIER) = 0x7f; /* disable VIA2 int */
1541: break;
1542: case MACH_CLASSIIci:
1543: VIA2 = RBVOFF;
1544: IOBase = 0x50f00000;
1545: Via1Base = (volatile u_char *)IOBase;
1546: mac68k_machine.scsi80 = 1;
1547: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
1548: via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
1549: break;
1550: case MACH_CLASSIIsi:
1551: VIA2 = RBVOFF;
1552: IOBase = 0x50f00000;
1553: Via1Base = (volatile u_char *)IOBase;
1554: mac68k_machine.scsi80 = 1;
1555: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
1556: via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
1557: break;
1558: case MACH_CLASSIIvx:
1559: VIA2 = RBVOFF;
1560: IOBase = 0x50f00000;
1561: Via1Base = (volatile u_char *)IOBase;
1562: mac68k_machine.scsi80 = 1;
1563: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
1564: via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
1565: break;
1566: case MACH_CLASSLC:
1567: VIA2 = RBVOFF;
1568: IOBase = 0x50f00000;
1569: Via1Base = (volatile u_char *)IOBase;
1570: mac68k_machine.scsi80 = 1;
1571: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
1572: via_reg(VIA2, rIER) = 0x7f; /* disable RBV int */
1573: break;
1574: case MACH_CLASSIIfx:
1575: VIA2 = OSSOFF;
1576: IOBase = 0x50f00000;
1577: Via1Base = (volatile u_char *)IOBase;
1578: mac68k_machine.scsi80 = 1;
1579: via_reg(VIA1, vIER) = 0x7f; /* disable VIA1 int */
1580: break;
1581: default:
1582: case MACH_CLASSH:
1583: break;
1584: }
1585: }
1586:
1587: /*
1588: * Set IO offsets.
1589: */
1590: void
1591: mac68k_set_io_offsets(base)
1592: vaddr_t base;
1593: {
1594: extern volatile u_char *sccA;
1595:
1596: switch (current_mac_model->class) {
1597: case MACH_CLASSQ:
1598: Via1Base = (volatile u_char *)base;
1599:
1600: /* The following two may be overriden. */
1601: sccA = (volatile u_char *)base + 0xc000;
1602: SCSIBase = base + 0xf000;
1603:
1604: switch (current_mac_model->machineid) {
1605: case MACH_MACQ900:
1606: case MACH_MACQ950:
1607: sccA = (volatile u_char *)base + 0xc020;
1608: iop_serial_compatible();
1609: mac68k_machine.scsi96_2 = 1;
1610: break;
1611: case MACH_MACQ700:
1612: break;
1613: default:
1614: SCSIBase = base + 0x10000;
1615: break;
1616: }
1617: break;
1618: case MACH_CLASSQ2:
1619: /*
1620: * Note the different offset for sccA for this class of
1621: * machines. This seems to be common on many of the
1622: * Quadra-type machines.
1623: */
1624: Via1Base = (volatile u_char *)base;
1625: sccA = (volatile u_char *)base + 0xc020;
1626: SCSIBase = base + 0x10000;
1627: break;
1628: case MACH_CLASSAV:
1629: Via1Base = (volatile u_char *)base;
1630: sccA = (volatile u_char *)base + 0x4000;
1631: SCSIBase = base + 0x18000;
1632: PSCBase = (volatile u_char *)base + 0x31000;
1633: break;
1634: case MACH_CLASSII:
1635: case MACH_CLASSPB:
1636: case MACH_CLASSDUO:
1637: case MACH_CLASSIIci:
1638: case MACH_CLASSIIsi:
1639: case MACH_CLASSIIvx:
1640: case MACH_CLASSLC:
1641: Via1Base = (volatile u_char *)base;
1642: sccA = (volatile u_char *)base + 0x4000;
1643: SCSIBase = base;
1644: break;
1645: case MACH_CLASSIIfx:
1646: Via1Base = (volatile u_char *)base;
1647: sccA = (volatile u_char *)base + 0x4020;
1648: iop_serial_compatible();
1649: SCSIBase = base;
1650: break;
1651: default:
1652: case MACH_CLASSH:
1653: panic("Unknown/unsupported machine class (%d).",
1654: current_mac_model->class);
1655: break;
1656: }
1657:
1658: Via2Base = Via1Base + 0x2000 * VIA2;
1659: }
1660:
1661: #if GRAYBARS
1662: u_long gray_nextaddr = 0;
1663:
1664: void
1665: gray_bar()
1666: {
1667: static int i = 0;
1668: static int flag = 0;
1669:
1670: /* MF basic premise as I see it:
1671: 1) Save the scratch regs as they are not saved by the compilier.
1672: 2) Check to see if we want gray bars, if so,
1673: display some lines of gray,
1674: a couple of lines of white(about 8),
1675: and loop to slow this down.
1676: 3) restore regs
1677: */
1678:
1679: __asm __volatile (" movl a0,sp@-;
1680: movl a1,sp@-;
1681: movl d0,sp@-;
1682: movl d1,sp@-");
1683:
1684: /* check to see if gray bars are turned off */
1685: if (mac68k_machine.do_graybars) {
1686: /* MF the 10*rowbytes/4 is done lots, but we want this to be
1687: * slow */
1688: for (i = 0; i < 10 * videorowbytes / 4; i++)
1689: ((u_long *)videoaddr)[gray_nextaddr++] = 0xaaaaaaaa;
1690: for (i = 0; i < 2 * videorowbytes / 4; i++)
1691: ((u_long *)videoaddr)[gray_nextaddr++] = 0x00000000;
1692: }
1693:
1694: __asm __volatile (" movl sp@+,d1;
1695: movl sp@+,d0;
1696: movl sp@+,a1;
1697: movl sp@+,a0");
1698: }
1699: #endif
1700:
1701: /* in locore */
1702: extern u_long ptest040(caddr_t addr, u_int fc);
1703: extern int get_pte(u_int addr, u_long pte[2], u_short * psr);
1704:
1705: /*
1706: * LAK (7/24/94): given a logical address, puts the physical address
1707: * in *phys and return 1, or returns 0 on failure. This is intended
1708: * to look through MacOS page tables.
1709: */
1710:
1711: u_long
1712: get_physical(u_int addr, u_long * phys)
1713: {
1714: extern u_int macos_tc;
1715: u_long pte[2], ph, mask;
1716: u_short psr;
1717: int i, numbits;
1718:
1719: if (mmutype == MMU_68040) {
1720: ph = ptest040((caddr_t)addr, FC_SUPERD);
1721: if ((ph & MMU40_RES) == 0) {
1722: ph = ptest040((caddr_t)addr, FC_USERD);
1723: if ((ph & MMU40_RES) == 0)
1724: return 0;
1725: }
1726: if ((ph & MMU40_TTR) != 0)
1727: ph = addr;
1728:
1729: mask = (macos_tc & 0x4000) ? 0x00001fff : 0x00000fff;
1730: ph &= (~mask);
1731: } else {
1732: i = get_pte(addr, pte, &psr);
1733:
1734: switch (i) {
1735: case -1:
1736: return 0;
1737: case 0:
1738: ph = pte[0] & 0xFFFFFF00;
1739: break;
1740: case 1:
1741: ph = pte[1] & 0xFFFFFF00;
1742: break;
1743: default:
1744: panic("get_physical(): bad get_pte()");
1745: }
1746:
1747: /*
1748: * We must now figure out how many levels down we went and
1749: * mask the bits appropriately -- the returned value may only
1750: * be the upper n bits, and we have to take the rest from addr.
1751: */
1752: numbits = 0;
1753: psr &= 0x0007; /* Number of levels we went */
1754: for (i = 0; i < psr; i++)
1755: numbits += (macos_tc >> (12 - i * 4)) & 0x0f;
1756:
1757: /*
1758: * We have to take the most significant "numbits" from
1759: * the returned value "ph", and the rest from our addr.
1760: * Assume that numbits != 0.
1761: */
1762: mask = (1 << (32 - numbits)) - 1;
1763: }
1764: *phys = ph + (addr & mask);
1765:
1766: return 1;
1767: }
1768:
1769: void check_video(char *, u_long, u_long);
1770:
1771: void
1772: check_video(id, limit, maxm)
1773: char *id;
1774: u_long limit, maxm;
1775: {
1776: u_long addr, phys;
1777:
1778: if (!get_physical(videoaddr, &phys)) {
1779: if (mac68k_machine.do_graybars)
1780: printf("get_mapping(): %s. False start.\n", id);
1781: } else {
1782: mac68k_vidlog = videoaddr;
1783: mac68k_vidphys = phys;
1784: mac68k_vidlen = 32768;
1785: addr = videoaddr + 32768;
1786: while (get_physical(addr, &phys)) {
1787: if ((phys - mac68k_vidphys) != mac68k_vidlen)
1788: break;
1789: if (mac68k_vidlen + 32768 > limit) {
1790: if (mac68k_machine.do_graybars) {
1791: printf("mapping: %s. Does it never end?\n",
1792: id);
1793: printf(" Forcing VRAM size ");
1794: printf("to a conservative %ldK.\n",
1795: maxm/1024);
1796: }
1797: mac68k_vidlen = maxm;
1798: break;
1799: }
1800: mac68k_vidlen += 32768;
1801: addr += 32768;
1802: }
1803: if (mac68k_machine.do_graybars) {
1804: printf(" %s internal video at paddr 0x%x, len 0x%x.\n",
1805: id, mac68k_vidphys, mac68k_vidlen);
1806: }
1807: }
1808: }
1809:
1810: /*
1811: * Find out how MacOS has mapped itself so we can do the same thing.
1812: * Returns the address of logical 0 so that locore can map the kernel
1813: * properly.
1814: */
1815: u_int
1816: get_mapping(void)
1817: {
1818: struct intvid_info_t *iip;
1819: u_long addr, lastpage, phys, len, limit;
1820: int i, last, same;
1821:
1822: numranges = 0;
1823: for (i = 0; i < 8; i++) {
1824: low[i] = 0;
1825: high[i] = 0;
1826: }
1827:
1828: lastpage = get_top_of_ram();
1829:
1830: get_physical(0, &load_addr);
1831:
1832: last = 0;
1833: for (addr = 0; addr <= lastpage && get_physical(addr, &phys);
1834: addr += PAGE_SIZE) {
1835: if (numranges > 0 && phys != high[last]) {
1836: /*
1837: * Attempt to find if this page is already
1838: * accounted for in an existing physical segment.
1839: */
1840: for (i = 0; i < numranges; i++) {
1841: if (low[i] <= phys && phys <= high[i]) {
1842: last = i;
1843: break;
1844: }
1845: }
1846: if (i >= numranges)
1847: last = numranges - 1;
1848:
1849: if (low[last] <= phys && phys < high[last])
1850: continue; /* Skip pages we've seen. */
1851: }
1852:
1853: if (numranges > 0 && phys == high[last]) {
1854: /* Common case: extend existing segment on high end */
1855: high[last] += PAGE_SIZE;
1856: } else {
1857: /* This is a new physical segment. */
1858: for (last = 0; last < numranges; last++)
1859: if (phys < low[last])
1860: break;
1861:
1862: /* Create space for segment, if necessary */
1863: if (last < numranges && phys < low[last]) {
1864: for (i = numranges; i > last; i--) {
1865: low[i] = low[i - 1];
1866: high[i] = high[i - 1];
1867: }
1868: }
1869:
1870: numranges++;
1871: low[last] = phys;
1872: high[last] = phys + PAGE_SIZE;
1873: }
1874:
1875: /* Coalesce adjoining segments as appropriate */
1876: if (last < (numranges - 1) && high[last] == low[last + 1] &&
1877: low[last + 1] != load_addr) {
1878: high[last] = high[last + 1];
1879: for (i = last + 1; i < numranges; i++) {
1880: low[i] = low[i + 1];
1881: high[i] = high[i + 1];
1882: }
1883: --numranges;
1884: }
1885: }
1886: if (mac68k_machine.do_graybars) {
1887: printf("System RAM: %ld bytes in %ld pages.\n",
1888: addr, addr / PAGE_SIZE);
1889: for (i = 0; i < numranges; i++) {
1890: printf(" Low = 0x%lx, high = 0x%lx\n",
1891: low[i], high[i]);
1892: }
1893: }
1894:
1895: /*
1896: * If we can't figure out the PA of the frame buffer by groveling
1897: * the page tables, assume that we already have the correct
1898: * address. This is the case on several of the PowerBook 1xx
1899: * series, in particular.
1900: */
1901: if (!get_physical(videoaddr, &phys))
1902: phys = videoaddr;
1903:
1904: /*
1905: * Find on-board video, if we have an idea of where to look
1906: * on this system.
1907: */
1908: for (iip = intvid_info; iip->machineid != 0; iip++)
1909: if (mac68k_machine.machineid == iip->machineid)
1910: break;
1911:
1912: if (mac68k_machine.machineid == iip->machineid &&
1913: (phys & ~iip->fbmask) >= iip->fbbase &&
1914: (phys & ~iip->fbmask) < (iip->fbbase + iip->fblen)) {
1915: mac68k_vidphys = phys & ~iip->fbmask;
1916: mac68k_vidlen = 32768 - (phys & 0x7fff);
1917:
1918: limit = iip->fbbase + iip->fblen - mac68k_vidphys;
1919: if (mac68k_vidlen > limit) {
1920: mac68k_vidlen = limit;
1921: } else {
1922: addr = videoaddr + mac68k_vidlen;
1923: while (get_physical(addr, &phys)) {
1924: if ((phys - mac68k_vidphys) != mac68k_vidlen)
1925: break;
1926: if (mac68k_vidlen + 32768 > limit) {
1927: mac68k_vidlen = limit;
1928: break;
1929: }
1930: mac68k_vidlen += 32768;
1931: addr += 32768;
1932: }
1933: }
1934: }
1935:
1936: if (mac68k_vidlen > 0) {
1937: /*
1938: * We've already figured out where internal video is.
1939: * Tell the user what we know.
1940: */
1941: if (mac68k_machine.do_graybars)
1942: printf("On-board video at addr 0x%lx (phys 0x%x), len 0x%x.\n",
1943: videoaddr, mac68k_vidphys, mac68k_vidlen);
1944: } else {
1945: /*
1946: * We should now look through all of NuBus space to find where
1947: * the internal video is being mapped. Just to be sure we
1948: * handle all the cases, we simply map our NuBus space exactly
1949: * how MacOS did it. As above, we find a bunch of ranges that
1950: * are contiguously mapped. Since there are a lot of pages
1951: * that are all mapped to 0, we handle that as a special case
1952: * where the length is negative. We search in increments of
1953: * 32768 because that's the page size that MacOS uses.
1954: */
1955: nbnumranges = 0;
1956: for (i = 0; i < NBMAXRANGES; i++) {
1957: nbphys[i] = 0;
1958: nblog[i] = 0;
1959: nblen[i] = 0;
1960: }
1961:
1962: same = 0;
1963: for (addr = NBBASE; addr < NBTOP; addr += 32768) {
1964: if (!get_physical(addr, &phys)) {
1965: continue;
1966: }
1967: len = nbnumranges == 0 ? 0 : nblen[nbnumranges - 1];
1968:
1969: #if DEBUG
1970: if (mac68k_machine.do_graybars)
1971: printf ("0x%lx --> 0x%lx\n", addr, phys);
1972: #endif
1973: if (nbnumranges > 0
1974: && addr == nblog[nbnumranges - 1] + len
1975: && phys == nbphys[nbnumranges - 1]) {
1976: /* Same as last one */
1977: nblen[nbnumranges - 1] += 32768;
1978: same = 1;
1979: } else {
1980: if ((nbnumranges > 0)
1981: && !same
1982: && (addr == nblog[nbnumranges - 1] + len)
1983: && (phys == nbphys[nbnumranges - 1] + len))
1984: nblen[nbnumranges - 1] += 32768;
1985: else {
1986: if (same) {
1987: nblen[nbnumranges - 1] = -len;
1988: same = 0;
1989: }
1990: if (nbnumranges == NBMAXRANGES) {
1991: if (mac68k_machine.do_graybars)
1992: printf("get_mapping(): "
1993: "Too many NuBus ranges.\n");
1994: break;
1995: }
1996: nbnumranges++;
1997: nblog[nbnumranges - 1] = addr;
1998: nbphys[nbnumranges - 1] = phys;
1999: nblen[nbnumranges - 1] = 32768;
2000: }
2001: }
2002: }
2003: if (same) {
2004: nblen[nbnumranges - 1] = -nblen[nbnumranges - 1];
2005: same = 0;
2006: }
2007: if (mac68k_machine.do_graybars) {
2008: printf("Non-system RAM (nubus, etc.):\n");
2009: for (i = 0; i < nbnumranges; i++) {
2010: printf(" Log = 0x%lx, Phys = 0x%lx, Len = 0x%lx (%lu)\n",
2011: nblog[i], nbphys[i], nblen[i], nblen[i]);
2012: }
2013: }
2014:
2015: /*
2016: * We must now find the logical address of internal video in the
2017: * ranges we made above. Internal video is at physical 0, but
2018: * a lot of pages map there. Instead, we look for the logical
2019: * page that maps to 32768 and go back one page.
2020: */
2021: for (i = 0; i < nbnumranges; i++) {
2022: if (nblen[i] > 0
2023: && nbphys[i] <= 32768
2024: && 32768 <= nbphys[i] + nblen[i]) {
2025: mac68k_vidlog = nblog[i] - nbphys[i];
2026: mac68k_vidlen = nblen[i] + nbphys[i];
2027: mac68k_vidphys = 0;
2028: break;
2029: }
2030: }
2031: if (i == nbnumranges) {
2032: if (0x60000000 <= videoaddr && videoaddr < 0x70000000) {
2033: if (mac68k_machine.do_graybars)
2034: printf("Checking for Internal Video ");
2035: /*
2036: * Kludge for IIvx internal video (60b0 0000).
2037: * PB 520 (6000 0000)
2038: */
2039: check_video("PB/IIvx (0x60?00000)",
2040: 1 * 1024 * 1024, 1 * 1024 * 1024);
2041: } else if (0x50F40000 <= videoaddr
2042: && videoaddr < 0x50FBFFFF) {
2043: /*
2044: * Kludge for LC internal video
2045: */
2046: check_video("LC video (0x50f40000)",
2047: 512 * 1024, 512 * 1024);
2048: } else if (0x50100100 <= videoaddr
2049: && videoaddr < 0x50400000) {
2050: /*
2051: * Kludge for AV internal video
2052: */
2053: check_video("AV video (0x50100100)",
2054: 1 * 1024 * 1024, 1 * 1024 * 1024);
2055: } else {
2056: if (mac68k_machine.do_graybars)
2057: printf( " no internal video at address 0 -- "
2058: "videoaddr is 0x%lx.\n", videoaddr);
2059: }
2060: } else {
2061: if (mac68k_machine.do_graybars) {
2062: printf(" Video address = 0x%lx\n", videoaddr);
2063: printf(" Int video starts at 0x%x\n",
2064: mac68k_vidlog);
2065: printf(" Length = 0x%x (%d) bytes\n",
2066: mac68k_vidlen, mac68k_vidlen);
2067: }
2068: }
2069: }
2070:
2071: return load_addr; /* Return physical address of logical 0 */
2072: }
2073:
2074: #ifdef DEBUG
2075: /*
2076: * Debugging code for locore page-traversal routine.
2077: */
2078: void printstar(void);
2079: void
2080: printstar(void)
2081: {
2082: /*
2083: * Be careful as we assume that no registers are clobbered
2084: * when we call this from assembly.
2085: */
2086: __asm __volatile (" movl a0,sp@-;
2087: movl a1,sp@-;
2088: movl d0,sp@-;
2089: movl d1,sp@-");
2090:
2091: /* printf("*"); */
2092:
2093: __asm __volatile (" movl sp@+,d1;
2094: movl sp@+,d0;
2095: movl sp@+,a1;
2096: movl sp@+,a0");
2097: }
2098: #endif
2099:
2100: /*
2101: * Console bell callback; modularizes the console terminal emulator
2102: * and the audio system, so neither requires direct knowledge of the
2103: * other.
2104: */
2105:
2106: void
2107: mac68k_set_bell_callback(callback, cookie)
2108: int (*callback)(void *, int, int, int);
2109: void *cookie;
2110: {
2111: mac68k_bell_callback = callback;
2112: mac68k_bell_cookie = (caddr_t)cookie;
2113: }
2114:
2115: int
2116: mac68k_ring_bell(freq, length, volume)
2117: int freq, length, volume;
2118: {
2119: if (mac68k_bell_callback)
2120: return ((*mac68k_bell_callback)(mac68k_bell_cookie,
2121: freq, length, volume));
2122: else
2123: return (ENXIO);
2124: }
CVSweb