Annotation of sys/arch/mvme68k/mvme68k/machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: machdep.c,v 1.106 2007/06/06 17:15:12 deraadt Exp $ */
2:
3: /*
4: * Copyright (c) 1995 Theo de Raadt
5: * Copyright (c) 1999 Steve Murphree, Jr. (68060 support)
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: *
28: * Copyright (c) 1988 University of Utah.
29: * Copyright (c) 1982, 1986, 1990, 1993
30: * The Regents of the University of California. All rights reserved.
31: *
32: * This code is derived from software contributed to Berkeley by
33: * the Systems Programming Group of the University of Utah Computer
34: * Science Department.
35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: * 3. Neither the name of the University nor the names of its contributors
45: * may be used to endorse or promote products derived from this software
46: * without specific prior written permission.
47: *
48: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58: * SUCH DAMAGE.
59: *
60: * from: Utah $Hdr: machdep.c 1.74 92/12/20$
61: *
62: * @(#)machdep.c 8.10 (Berkeley) 4/20/94
63: */
64:
65: #include <sys/param.h>
66: #include <sys/systm.h>
67: #include <sys/signalvar.h>
68: #include <sys/kernel.h>
69: #include <sys/proc.h>
70: #include <sys/buf.h>
71: #include <sys/reboot.h>
72: #include <sys/conf.h>
73: #include <sys/file.h>
74: #include <sys/timeout.h>
75: #include <sys/malloc.h>
76: #include <sys/mbuf.h>
77: #include <sys/msgbuf.h>
78: #include <sys/ioctl.h>
79: #include <sys/tty.h>
80: #include <sys/mount.h>
81: #include <sys/user.h>
82: #include <sys/exec.h>
83: #include <sys/core.h>
84: #include <sys/kcore.h>
85: #include <sys/vnode.h>
86: #include <sys/sysctl.h>
87: #include <sys/syscallargs.h>
88: #ifdef SYSVMSG
89: #include <sys/msg.h>
90: #endif
91: #include <sys/evcount.h>
92:
93: #include <machine/atomic.h>
94: #include <machine/autoconf.h>
95: #include <machine/cpu.h>
96: #include <machine/kcore.h>
97: #include <machine/prom.h>
98: #include <machine/psl.h>
99: #include <machine/pte.h>
100: #include <machine/reg.h>
101:
102: #ifdef MVME147
103: #include <mvme68k/dev/pccreg.h>
104: #endif
105:
106: #include <dev/cons.h>
107:
108: #include <net/netisr.h>
109:
110: #ifdef DDB
111: #include <machine/db_machdep.h>
112: #include <ddb/db_extern.h>
113: #include <ddb/db_interface.h>
114: #include <ddb/db_var.h>
115: #endif
116:
117: #include <uvm/uvm_extern.h>
118:
119: /* the following is used externally (sysctl_hw) */
120: char machine[] = MACHINE; /* cpu "architecture" */
121:
122: struct vm_map *exec_map = NULL;
123: struct vm_map *phys_map = NULL;
124:
125: extern vaddr_t avail_end;
126:
127: /*
128: * Declare these as initialized data so we can patch them.
129: */
130: #ifndef BUFCACHEPERCENT
131: #define BUFCACHEPERCENT 5
132: #endif
133:
134: #ifdef BUFPAGES
135: int bufpages = BUFPAGES;
136: #else
137: int bufpages = 0;
138: #endif
139: int bufcachepercent = BUFCACHEPERCENT;
140:
141: int physmem; /* size of physical memory, in pages */
142: /*
143: * safepri is a safe priority for sleep to set for a spin-wait
144: * during autoconfiguration or after a panic.
145: */
146: int safepri = PSL_LOWIPL;
147:
148: #ifdef COMPAT_SUNOS
149: extern struct emul emul_sunos;
150: #endif
151:
152: void dumpsys(void);
153: void initvectors(void);
154: void mvme68k_init(void);
155: void identifycpu(void);
156: int cpu_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *);
157: void dumpconf(void);
158: void straytrap(int, u_short);
159: void netintr(void *);
160: void myetheraddr(u_char *);
161: int fpu_gettype(void);
162: int memsize162(void);
163: int memsize1x7(void); /* in locore */
164: int memsize(void);
165: caddr_t allocsys(caddr_t);
166:
167: void
168: mvme68k_init()
169: {
170: extern vaddr_t avail_start;
171:
172: /*
173: * Tell the VM system about available physical memory. The
174: * mvme68k only has one segment.
175: */
176:
177: uvmexp.pagesize = NBPG;
178: uvm_setpagesize();
179: uvm_page_physload(atop(avail_start), atop(avail_end),
180: atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
181:
182: /*
183: * Put machine specific exception vectors in place.
184: */
185: initvectors();
186: }
187:
188: /*
189: * Console initialization: called early on from main,
190: * before vm init or startup, but already running virtual.
191: * Do enough configuration to choose and initialize a console.
192: */
193: void
194: consinit()
195: {
196: /*
197: * Initialize the console before we print anything out.
198: */
199: cninit();
200:
201: #ifdef DDB
202: db_machine_init();
203: ddb_init();
204:
205: if (boothowto & RB_KDB)
206: Debugger();
207: #endif
208: }
209:
210: /*
211: * cpu_startup: allocate memory for variable-sized tables,
212: * initialize cpu, and do autoconfiguration.
213: */
214: void
215: cpu_startup()
216: {
217: unsigned i;
218: caddr_t v;
219: vaddr_t minaddr, maxaddr;
220: vsize_t size;
221: #ifdef DEBUG
222: extern int pmapdebug;
223: int opmapdebug = pmapdebug;
224:
225: pmapdebug = 0;
226: #endif
227:
228: /*
229: * Initialize error message buffer (at end of core).
230: * avail_end was pre-decremented in pmap_bootstrap to compensate.
231: */
232: for (i = 0; i < btoc(MSGBUFSIZE); i++)
233: pmap_kenter_pa((vaddr_t)msgbufp + i * PAGE_SIZE,
234: avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
235: pmap_update(pmap_kernel());
236: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
237:
238: /*
239: * Good {morning,afternoon,evening,night}.
240: */
241: printf("%s", version);
242: identifycpu();
243: printf("real mem = %u (%uMB)\n", ctob(physmem),
244: ctob(physmem) / 1024 / 1024);
245:
246: /*
247: * Find out how much space we need, allocate it,
248: * and then give everything true virtual addresses.
249: */
250: size = (vsize_t)allocsys((caddr_t)0);
251: if ((v = (caddr_t) uvm_km_zalloc(kernel_map, round_page(size))) == 0)
252: panic("startup: no room for tables");
253: if (allocsys(v) - v != size)
254: panic("startup: table size inconsistency");
255:
256: /*
257: * Determine how many buffers to allocate.
258: * We allocate bufcachepercent% of memory for buffer space.
259: */
260: if (bufpages == 0)
261: bufpages = physmem * bufcachepercent / 100;
262:
263: /* Restrict to at most 25% filled kvm */
264: if (bufpages >
265: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
266: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
267: PAGE_SIZE / 4;
268:
269: /*
270: * Allocate a submap for exec arguments. This map effectively
271: * limits the number of processes exec'ing at any time.
272: */
273: minaddr = vm_map_min(kernel_map);
274: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
275: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
276:
277: /*
278: * Allocate a submap for physio.
279: */
280: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
281: VM_PHYS_SIZE, 0, FALSE, NULL);
282:
283: #ifdef DEBUG
284: pmapdebug = opmapdebug;
285: #endif
286:
287: /*
288: * Set up buffers, so they can be used to read disk labels.
289: */
290: bufinit();
291:
292: printf("avail mem = %u (%uMB)\n",
293: ptoa(uvmexp.free), ptoa(uvmexp.free) / 1024 / 1024);
294:
295: /*
296: * Configure the system.
297: */
298: if (boothowto & RB_CONFIG) {
299: #ifdef BOOT_CONFIG
300: user_config();
301: #else
302: printf("kernel does not support -c; continuing..\n");
303: #endif
304: }
305: }
306:
307: /*
308: * Allocate space for system data structures. We are given
309: * a starting virtual address and we return a final virtual
310: * address; along the way we set each data structure pointer.
311: *
312: * You call allocsys() with 0 to find out how much space we want,
313: * allocate that much and fill it with zeroes, and then call
314: * allocsys() again with the correct base virtual address.
315: */
316: caddr_t
317: allocsys(caddr_t v)
318: {
319:
320: #define valloc(name, type, num) \
321: (name) = (type *)v; v = (caddr_t)((name) + (num))
322: #ifdef SYSVMSG
323: valloc(msgpool, char, msginfo.msgmax);
324: valloc(msgmaps, struct msgmap, msginfo.msgseg);
325: valloc(msghdrs, struct msg, msginfo.msgtql);
326: valloc(msqids, struct msqid_ds, msginfo.msgmni);
327: #endif
328:
329: return (v);
330: }
331:
332: /*
333: * Info for CTL_HW
334: */
335: char cpu_model[120];
336:
337: int cputyp;
338: int cpuspeed;
339:
340: struct mvmeprom_brdid brdid;
341:
342: void
343: identifycpu()
344: {
345: char mc;
346: char speed[6];
347: char suffix[30];
348: int len;
349:
350: bzero(suffix, sizeof suffix);
351:
352: switch (mmutype) {
353: case MMU_68060:
354: mc = '6';
355: break;
356: case MMU_68040:
357: mc = '4';
358: break;
359: case MMU_68030:
360: mc = '3';
361: break;
362: default:
363: mc = '2';
364: }
365:
366: switch (cputyp) {
367: #ifdef MVME147
368: case CPU_147:
369: snprintf(suffix, sizeof suffix, "MVME%x", brdid.model);
370: cpuspeed = pccspeed((struct pccreg *)IIOV(0xfffe1000));
371: snprintf(speed, sizeof speed, "%02d", cpuspeed);
372: break;
373: #endif
374: #if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
375: case CPU_162:
376: case CPU_167:
377: case CPU_172:
378: case CPU_177:
379: bzero(speed, sizeof speed);
380: speed[0] = brdid.speed[0];
381: speed[1] = brdid.speed[1];
382: if (brdid.speed[2] != '0' &&
383: brdid.speed[3] != '0') {
384: speed[2] = '.';
385: speed[3] = brdid.speed[2];
386: speed[4] = brdid.speed[3];
387: }
388: cpuspeed = (speed[0] - '0') * 10 + (speed[1] - '0');
389: bcopy(brdid.longname, suffix, sizeof(brdid.longname));
390: for (len = strlen(suffix)-1; len; len--) {
391: if (suffix[len] == ' ')
392: suffix[len] = '\0';
393: else
394: break;
395: }
396: break;
397: #endif
398: }
399: snprintf(cpu_model, sizeof cpu_model,
400: "Motorola %s: %sMHz MC680%c0 CPU", suffix, speed, mc);
401: switch (mmutype) {
402: #if defined(M68040)
403: case MMU_68040:
404: /* FALLTHROUGH */
405: #endif
406: #if defined(M68060)
407: case MMU_68060:
408: /* FALLTHROUGH */
409: #endif
410: case MMU_68030:
411: strlcat(cpu_model, "+MMU", sizeof cpu_model);
412: break;
413: case MMU_68851:
414: strlcat(cpu_model, ", MC68851 MMU", sizeof cpu_model);
415: break;
416: default:
417: printf("%s\n", cpu_model);
418: panic("unknown MMU type %d", mmutype);
419: }
420:
421: switch (mmutype) {
422: #if defined(M68060)
423: case MMU_68060:
424: strlcat(cpu_model,"+FPU, 8k on-chip physical I/D caches",
425: sizeof cpu_model);
426: break;
427: #endif
428: #if defined(M68040)
429: case MMU_68040:
430: strlcat(cpu_model, "+FPU, 4k on-chip physical I/D caches",
431: sizeof cpu_model);
432: break;
433: #endif
434: #if defined(M68030) || defined(M68020)
435: default:
436: fputype = fpu_gettype();
437:
438: switch (fputype) {
439: case FPU_NONE:
440: break;
441: case FPU_68881:
442: case FPU_68882:
443: len = strlen (cpu_model);
444: snprintf(cpu_model + len, sizeof cpu_model - len,
445: ", MC6888%d FPU", fputype);
446: break;
447: default:
448: strlcat(cpu_model, ", unknown FPU", sizeof cpu_model);
449: break;
450: }
451: break;
452: #endif
453: }
454: printf("%s\n", cpu_model);
455: }
456:
457: /*
458: * machine dependent system variables.
459: */
460: int
461: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
462: int *name;
463: u_int namelen;
464: void *oldp;
465: size_t *oldlenp;
466: void *newp;
467: size_t newlen;
468: struct proc *p;
469: {
470: dev_t consdev;
471:
472: /* all sysctl names at this level are terminal */
473: if (namelen != 1)
474: return (ENOTDIR); /* overloaded */
475:
476: switch (name[0]) {
477: case CPU_CONSDEV:
478: if (cn_tab != NULL)
479: consdev = cn_tab->cn_dev;
480: else
481: consdev = NODEV;
482: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
483: sizeof consdev));
484: default:
485: return (EOPNOTSUPP);
486: }
487: /* NOTREACHED */
488: }
489:
490: int waittime = -1;
491:
492: __dead void
493: boot(howto)
494: int howto;
495: {
496: /* If system is cold, just halt. */
497: if (cold) {
498: /* (Unless the user explicitly asked for reboot.) */
499: if ((howto & RB_USERREQ) == 0)
500: howto |= RB_HALT;
501: goto haltsys;
502: }
503:
504: /* take a snap shot before clobbering any registers */
505: if (curproc && curproc->p_addr)
506: savectx(&curproc->p_addr->u_pcb);
507:
508: boothowto = howto;
509: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
510: extern struct proc proc0;
511: /* do that another panic fly away */
512: if (curproc == NULL)
513: curproc = &proc0;
514: waittime = 0;
515: vfs_shutdown();
516: /*
517: * If we've been adjusting the clock, the todr
518: * will be out of synch; adjust it now unless
519: * the system was sitting in ddb.
520: */
521: if ((howto & RB_TIMEBAD) == 0) {
522: resettodr();
523: } else {
524: printf("WARNING: not updating battery clock\n");
525: }
526: }
527:
528: /* Disable interrupts. */
529: splhigh();
530:
531: /* If rebooting and a dump is requested, do it. */
532: if (howto & RB_DUMP)
533: dumpsys();
534:
535: haltsys:
536: /* Run any shutdown hooks. */
537: doshutdownhooks();
538:
539: if (howto & RB_HALT) {
540: printf("System halted. Press any key to reboot...\n\n");
541: cngetc();
542: }
543:
544: doboot();
545:
546: for (;;);
547: /*NOTREACHED*/
548: }
549:
550: /*
551: * These variables are needed by /sbin/savecore
552: */
553: u_long dumpmag = 0x8fca0101; /* magic number */
554: int dumpsize = 0; /* pages */
555: long dumplo = 0; /* blocks */
556: cpu_kcore_hdr_t cpu_kcore_hdr;
557:
558: /*
559: * This is called by configure to set dumplo and dumpsize.
560: * Dumps always skip the first PAGE_SIZE of disk space
561: * in case there might be a disk label stored there.
562: * If there is extra space, put dump at the end to
563: * reduce the chance that swapping trashes it.
564: */
565: void
566: dumpconf(void)
567: {
568: int nblks; /* size of dump area */
569:
570: if (dumpdev == NODEV ||
571: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
572: return;
573: if (nblks <= ctod(1))
574: return;
575:
576: dumpsize = physmem;
577:
578: /* mvme68k only uses a single segment. */
579: cpu_kcore_hdr.ram_segs[0].start = 0;
580: cpu_kcore_hdr.ram_segs[0].size = ctob(physmem);
581: cpu_kcore_hdr.mmutype = mmutype;
582: cpu_kcore_hdr.kernel_pa = 0;
583: cpu_kcore_hdr.sysseg_pa = pmap_kernel()->pm_stpa;
584:
585: /* Always skip the first block, in case there is a label there. */
586: if (dumplo < ctod(1))
587: dumplo = ctod(1);
588:
589: /* Put dump at end of partition, and make it fit. */
590: if (dumpsize + 1 > dtoc(nblks - dumplo))
591: dumpsize = dtoc(nblks - dumplo) - 1;
592: if (dumplo < nblks - ctod(dumpsize) - 1)
593: dumplo = nblks - ctod(dumpsize) - 1;
594: }
595:
596: /*
597: * Doadump comes here after turning off memory management and
598: * getting on the dump stack, either when called above, or by
599: * the auto-restart code.
600: */
601: void
602: dumpsys()
603: {
604: int maj;
605: int psize;
606: daddr64_t blkno; /* current block to write */
607: /* dump routine */
608: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
609: int pg; /* page being dumped */
610: paddr_t maddr; /* PA being dumped */
611: int error; /* error code from (*dump)() */
612: kcore_seg_t *kseg_p;
613: cpu_kcore_hdr_t *chdr_p;
614: char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
615:
616: extern int msgbufmapped;
617:
618: msgbufmapped = 0;
619:
620: /* Make sure dump device is valid. */
621: if (dumpdev == NODEV)
622: return;
623: if (dumpsize == 0) {
624: dumpconf();
625: if (dumpsize == 0)
626: return;
627: }
628: maj = major(dumpdev);
629: if (dumplo < 0) {
630: printf("\ndump to dev %u,%u not possible\n", maj,
631: minor(dumpdev));
632: return;
633: }
634: dump = bdevsw[maj].d_dump;
635: blkno = dumplo;
636:
637: printf("\ndumping to dev %u,%u offset %ld\n", maj,
638: minor(dumpdev), dumplo);
639:
640: kseg_p = (kcore_seg_t *)dump_hdr;
641: chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
642: bzero(dump_hdr, sizeof(dump_hdr));
643:
644: /*
645: * Generate a segment header
646: */
647: CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
648: kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
649:
650: /*
651: * Add the md header
652: */
653: *chdr_p = cpu_kcore_hdr;
654:
655: printf("dump ");
656: psize = (*bdevsw[maj].d_psize)(dumpdev);
657: if (psize == -1) {
658: printf("area unavailable\n");
659: return;
660: }
661:
662: /* Dump the header. */
663: error = (*dump) (dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
664: if (error != 0)
665: goto abort;
666:
667: maddr = (paddr_t)0;
668: for (pg = 0; pg < dumpsize; pg++) {
669: #define NPGMB (1024 * 1024 / PAGE_SIZE)
670: /* print out how many MBs we have dumped */
671: if (pg != 0 && (pg % NPGMB) == 0)
672: printf("%d ", pg / NPGMB);
673: #undef NPGMB
674: pmap_kenter_pa((vaddr_t)vmmap, maddr, VM_PROT_READ);
675: pmap_update(pmap_kernel());
676: error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
677: pmap_kremove((vaddr_t)vmmap, PAGE_SIZE);
678: pmap_update(pmap_kernel());
679:
680: if (error == 0) {
681: maddr += PAGE_SIZE;
682: blkno += btodb(PAGE_SIZE);
683: } else
684: break;
685: }
686: abort:
687: switch (error) {
688: case 0:
689: printf("succeeded\n");
690: break;
691:
692: case ENXIO:
693: printf("device bad\n");
694: break;
695:
696: case EFAULT:
697: printf("device not ready\n");
698: break;
699:
700: case EINVAL:
701: printf("area improper\n");
702: break;
703:
704: case EIO:
705: printf("i/o error\n");
706: break;
707:
708: case EINTR:
709: printf("aborted from console\n");
710: break;
711:
712: default:
713: printf("error %d\n", error);
714: break;
715: }
716: }
717:
718: #if defined(M68060)
719: int m68060_pcr_init = 0x20 | PCR_SUPERSCALAR; /* make this patchable */
720: #endif
721:
722: void
723: initvectors()
724: {
725: typedef void trapfun(void);
726: extern trapfun *vectab[256];
727: #if defined(M68060)
728: #if defined(M060SP)
729: extern trapfun intemu60, fpiemu60, fpdemu60, fpeaemu60;
730: extern u_int8_t FP_CALL_TOP[];
731: #else
732: extern trapfun illinst;
733: #endif
734: extern trapfun fpfault;
735: #endif
736: #if defined(M68040) && defined(FPSP)
737: extern u_long fpvect_tab, fpvect_end, fpsp_tab;
738: #endif
739:
740: switch (cputype) {
741: #ifdef M68060
742: case CPU_68060:
743: asm volatile ("movl %0,d0; .word 0x4e7b,0x0808" : :
744: "d"(m68060_pcr_init):"d0" );
745:
746: #if defined(M060SP)
747: /* integer support */
748: vectab[61] = intemu60/*(trapfun *)&I_CALL_TOP[128 + 0x00]*/;
749:
750: /* floating point support */
751: /*
752: * XXX maybe we really should run-time check for the
753: * stack frame format here:
754: */
755: vectab[11] = fpiemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x30]*/;
756:
757: vectab[55] = fpdemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x38]*/;
758: vectab[60] = fpeaemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x40]*/;
759:
760: vectab[54] = (trapfun *)&FP_CALL_TOP[128 + 0x00];
761: vectab[52] = (trapfun *)&FP_CALL_TOP[128 + 0x08];
762: vectab[53] = (trapfun *)&FP_CALL_TOP[128 + 0x10];
763: vectab[51] = (trapfun *)&FP_CALL_TOP[128 + 0x18];
764: vectab[50] = (trapfun *)&FP_CALL_TOP[128 + 0x20];
765: vectab[49] = (trapfun *)&FP_CALL_TOP[128 + 0x28];
766: #else
767: vectab[61] = illinst;
768: #endif
769: vectab[48] = fpfault;
770: break;
771: #endif
772: #if defined(M68040) && defined(FPSP)
773: case CPU_68040:
774: bcopy(&fpsp_tab, &fpvect_tab,
775: (&fpvect_end - &fpvect_tab) * sizeof (fpvect_tab));
776: break;
777: #endif
778: default:
779: break;
780: }
781: }
782:
783: void
784: straytrap(pc, evec)
785: int pc;
786: u_short evec;
787: {
788: printf("unexpected trap (vector 0x%x) from %x\n",
789: (evec & 0xFFF) >> 2, pc);
790: }
791:
792: int *nofault;
793:
794: int
795: badpaddr(addr, size)
796: paddr_t addr;
797: int size;
798: {
799: int off = (int)addr & PGOFSET;
800: vaddr_t v;
801: paddr_t p = trunc_page(addr);
802: int x;
803:
804: v = mapiodev(p, NBPG);
805: if (v == 0)
806: return (1);
807: x = badvaddr(v + off, size);
808: unmapiodev(v, NBPG);
809: return (x);
810: }
811:
812: int
813: badvaddr(addr, size)
814: vaddr_t addr;
815: int size;
816: {
817: int i;
818: label_t faultbuf;
819:
820: nofault = (int *) &faultbuf;
821: if (setjmp((label_t *)nofault)) {
822: nofault = (int *)0;
823: return (1);
824: }
825: switch (size) {
826: case 1:
827: i = *(volatile char *)addr;
828: break;
829: case 2:
830: i = *(volatile short *)addr;
831: break;
832: case 4:
833: i = *(volatile long *)addr;
834: break;
835: }
836: nofault = (int *)0;
837: return (0);
838: }
839:
840: int netisr;
841:
842: void
843: netintr(arg)
844: void *arg;
845: {
846: int n;
847:
848: while ((n = netisr) != 0) {
849: atomic_clearbits_int(&netisr, n);
850:
851: #define DONETISR(bit, fn) \
852: do { \
853: if (n & (1 << (bit))) \
854: (fn)(); \
855: } while (0)
856:
857: #include <net/netisr_dispatch.h>
858:
859: #undef DONETISR
860: }
861: }
862:
863: /*
864: * Level 7 interrupts are normally caused by the ABORT switch,
865: * drop into ddb.
866: */
867: void
868: nmihand(frame)
869: void *frame;
870: {
871: #ifdef DDB
872: printf("NMI ... going to debugger\n");
873: Debugger();
874: #else
875: /* panic?? */
876: printf("unexpected level 7 interrupt ignored\n");
877: #endif
878: }
879:
880: /*
881: * cpu_exec_aout_makecmds():
882: * cpu-dependent a.out format hook for execve().
883: *
884: * Determine of the given exec package refers to something which we
885: * understand and, if so, set up the vmcmds for it.
886: */
887: int
888: cpu_exec_aout_makecmds(p, epp)
889: struct proc *p;
890: struct exec_package *epp;
891: {
892: int error = ENOEXEC;
893:
894: #ifdef COMPAT_SUNOS
895: {
896: extern int sunos_exec_aout_makecmds(struct proc *, struct exec_package *);
897: if ((error = sunos_exec_aout_makecmds(p, epp)) == 0)
898: return (0);
899: }
900: #endif
901: return (error);
902: }
903:
904: u_char myea[6] = { 0x08, 0x00, 0x3e, 0xff, 0xff, 0xff};
905:
906: void
907: myetheraddr(ether)
908: u_char *ether;
909: {
910: bcopy(myea, ether, sizeof myea);
911: }
912:
913: #if defined(M68030) || defined(M68020)
914: int
915: fpu_gettype()
916: {
917: /*
918: * A 68881 idle frame is 28 bytes and a 68882's is 60 bytes.
919: * We, of course, need to have enough room for either.
920: */
921: int fpframe[60 / sizeof(int)];
922: label_t faultbuf;
923: u_char b;
924:
925: nofault = (int *) &faultbuf;
926: if (setjmp((label_t *)nofault)) {
927: nofault = (int *)0;
928: return (0); /* no FPU */
929: }
930:
931: /*
932: * Synchronize FPU or cause a fault.
933: * This should leave the 881/882 in the IDLE state,
934: * state, so we can determine which we have by
935: * examining the size of the FP state frame
936: */
937: asm("fnop");
938:
939: nofault = (int *)0;
940:
941: /*
942: * Presumably, this will not cause a fault--the fnop should
943: * have if this will. We save the state in order to get the
944: * size of the frame.
945: */
946: asm("movl %0, a0; fsave a0@" : : "a" (fpframe) : "a0" );
947: b = *((u_char *) fpframe + 1);
948:
949: /*
950: * Now, restore a NULL state to reset the FPU.
951: */
952: fpframe[0] = fpframe[1] = 0;
953: m68881_restore((struct fpframe *)fpframe);
954:
955: if (b == 0x18)
956: return (FPU_68881); /* The size of a 68881 IDLE frame is 0x18 */
957: if (b == 0x38)
958: return (FPU_68882); /* 68882 frame is 0x38 bytes long */
959: return (FPU_UNKNOWN); /* unknown FPU type */
960: }
961: #endif
962:
963:
964: #if defined(MVME162) || defined(MVME172)
965: #include <mvme68k/dev/mcreg.h>
966: /*
967: * XXX
968: * used by locore.s to figure out how much memory is on the machine.
969: * At this stage we only know that our machine is a 162. It is very
970: * unfortunate that the MCchip's address must be encoded here.
971: */
972: int
973: memsize162()
974: {
975: struct mcreg *mc = (struct mcreg *)0xfff42000;
976:
977: switch (mc->mc_memoptions & MC_MEMOPTIONS_DRAMMASK) {
978: case MC_MEMOPTIONS_DRAM1M:
979: return (1*1024*1024);
980: case MC_MEMOPTIONS_DRAM2M:
981: return (2*1024*1024);
982: case MC_MEMOPTIONS_DRAM4M:
983: return (4*1024*1024);
984: case MC_MEMOPTIONS_DRAM4M2:
985: return (4*1024*1024);
986: case MC_MEMOPTIONS_DRAM8M:
987: return (8*1024*1024);
988: case MC_MEMOPTIONS_DRAM16M:
989: return (16*1024*1024);
990: default:
991: /*
992: * XXX if the machine has no MC-controlled memory,
993: * perhaps it has a MCECC or MEMC040 controller?
994: */
995: return (memsize1x7());
996: }
997: }
998: #endif
CVSweb