File: [local] / sys / arch / mvme68k / mvme68k / machdep.c (download)
Revision 1.1.1.1 (vendor branch), Tue Mar 4 16:07:37 2008 UTC (16 years, 6 months ago) by nbrk
Branch: OPENBSD_4_2_BASE, MAIN
CVS Tags: jornada-partial-support-wip, HEAD Changes since 1.1: +0 -0 lines
Import of OpenBSD 4.2 release kernel tree with initial code to support
Jornada 720/728, StrongARM 1110-based handheld PC.
At this point kernel roots on NFS and boots into vfs_mountroot() and traps.
What is supported:
- glass console, Jornada framebuffer (jfb) works in 16bpp direct color mode
(needs some palette tweaks for non black/white/blue colors, i think)
- saic, SA11x0 interrupt controller (needs cleanup)
- sacom, SA11x0 UART (supported only as boot console for now)
- SA11x0 GPIO controller fully supported (but can't handle multiple interrupt
handlers on one gpio pin)
- sassp, SSP port on SA11x0 that attaches spibus
- Jornada microcontroller (jmcu) to control kbd, battery, etc throught
the SPI bus (wskbd attaches on jmcu, but not tested)
- tod functions seem work
- initial code for SA-1111 (chip companion) : this is TODO
Next important steps, i think:
- gpio and intc on sa1111
- pcmcia support for sa11x0 (and sa1111 help logic)
- REAL root on nfs when we have PCMCIA support (we may use any of supported pccard NICs)
- root on wd0! (using already supported PCMCIA-ATA)
|
/* $OpenBSD: machdep.c,v 1.106 2007/06/06 17:15:12 deraadt Exp $ */
/*
* Copyright (c) 1995 Theo de Raadt
* Copyright (c) 1999 Steve Murphree, Jr. (68060 support)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1982, 1986, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
* Science Department.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: Utah $Hdr: machdep.c 1.74 92/12/20$
*
* @(#)machdep.c 8.10 (Berkeley) 4/20/94
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/signalvar.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/reboot.h>
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/timeout.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/msgbuf.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/mount.h>
#include <sys/user.h>
#include <sys/exec.h>
#include <sys/core.h>
#include <sys/kcore.h>
#include <sys/vnode.h>
#include <sys/sysctl.h>
#include <sys/syscallargs.h>
#ifdef SYSVMSG
#include <sys/msg.h>
#endif
#include <sys/evcount.h>
#include <machine/atomic.h>
#include <machine/autoconf.h>
#include <machine/cpu.h>
#include <machine/kcore.h>
#include <machine/prom.h>
#include <machine/psl.h>
#include <machine/pte.h>
#include <machine/reg.h>
#ifdef MVME147
#include <mvme68k/dev/pccreg.h>
#endif
#include <dev/cons.h>
#include <net/netisr.h>
#ifdef DDB
#include <machine/db_machdep.h>
#include <ddb/db_extern.h>
#include <ddb/db_interface.h>
#include <ddb/db_var.h>
#endif
#include <uvm/uvm_extern.h>
/* the following is used externally (sysctl_hw) */
char machine[] = MACHINE; /* cpu "architecture" */
struct vm_map *exec_map = NULL;
struct vm_map *phys_map = NULL;
extern vaddr_t avail_end;
/*
* Declare these as initialized data so we can patch them.
*/
#ifndef BUFCACHEPERCENT
#define BUFCACHEPERCENT 5
#endif
#ifdef BUFPAGES
int bufpages = BUFPAGES;
#else
int bufpages = 0;
#endif
int bufcachepercent = BUFCACHEPERCENT;
int physmem; /* size of physical memory, in pages */
/*
* safepri is a safe priority for sleep to set for a spin-wait
* during autoconfiguration or after a panic.
*/
int safepri = PSL_LOWIPL;
#ifdef COMPAT_SUNOS
extern struct emul emul_sunos;
#endif
void dumpsys(void);
void initvectors(void);
void mvme68k_init(void);
void identifycpu(void);
int cpu_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *);
void dumpconf(void);
void straytrap(int, u_short);
void netintr(void *);
void myetheraddr(u_char *);
int fpu_gettype(void);
int memsize162(void);
int memsize1x7(void); /* in locore */
int memsize(void);
caddr_t allocsys(caddr_t);
void
mvme68k_init()
{
extern vaddr_t avail_start;
/*
* Tell the VM system about available physical memory. The
* mvme68k only has one segment.
*/
uvmexp.pagesize = NBPG;
uvm_setpagesize();
uvm_page_physload(atop(avail_start), atop(avail_end),
atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
/*
* Put machine specific exception vectors in place.
*/
initvectors();
}
/*
* Console initialization: called early on from main,
* before vm init or startup, but already running virtual.
* Do enough configuration to choose and initialize a console.
*/
void
consinit()
{
/*
* Initialize the console before we print anything out.
*/
cninit();
#ifdef DDB
db_machine_init();
ddb_init();
if (boothowto & RB_KDB)
Debugger();
#endif
}
/*
* cpu_startup: allocate memory for variable-sized tables,
* initialize cpu, and do autoconfiguration.
*/
void
cpu_startup()
{
unsigned i;
caddr_t v;
vaddr_t minaddr, maxaddr;
vsize_t size;
#ifdef DEBUG
extern int pmapdebug;
int opmapdebug = pmapdebug;
pmapdebug = 0;
#endif
/*
* Initialize error message buffer (at end of core).
* avail_end was pre-decremented in pmap_bootstrap to compensate.
*/
for (i = 0; i < btoc(MSGBUFSIZE); i++)
pmap_kenter_pa((vaddr_t)msgbufp + i * PAGE_SIZE,
avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
pmap_update(pmap_kernel());
initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
/*
* Good {morning,afternoon,evening,night}.
*/
printf("%s", version);
identifycpu();
printf("real mem = %u (%uMB)\n", ctob(physmem),
ctob(physmem) / 1024 / 1024);
/*
* Find out how much space we need, allocate it,
* and then give everything true virtual addresses.
*/
size = (vsize_t)allocsys((caddr_t)0);
if ((v = (caddr_t) uvm_km_zalloc(kernel_map, round_page(size))) == 0)
panic("startup: no room for tables");
if (allocsys(v) - v != size)
panic("startup: table size inconsistency");
/*
* Determine how many buffers to allocate.
* We allocate bufcachepercent% of memory for buffer space.
*/
if (bufpages == 0)
bufpages = physmem * bufcachepercent / 100;
/* Restrict to at most 25% filled kvm */
if (bufpages >
(VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
PAGE_SIZE / 4;
/*
* Allocate a submap for exec arguments. This map effectively
* limits the number of processes exec'ing at any time.
*/
minaddr = vm_map_min(kernel_map);
exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
/*
* Allocate a submap for physio.
*/
phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
VM_PHYS_SIZE, 0, FALSE, NULL);
#ifdef DEBUG
pmapdebug = opmapdebug;
#endif
/*
* Set up buffers, so they can be used to read disk labels.
*/
bufinit();
printf("avail mem = %u (%uMB)\n",
ptoa(uvmexp.free), ptoa(uvmexp.free) / 1024 / 1024);
/*
* Configure the system.
*/
if (boothowto & RB_CONFIG) {
#ifdef BOOT_CONFIG
user_config();
#else
printf("kernel does not support -c; continuing..\n");
#endif
}
}
/*
* Allocate space for system data structures. We are given
* a starting virtual address and we return a final virtual
* address; along the way we set each data structure pointer.
*
* You call allocsys() with 0 to find out how much space we want,
* allocate that much and fill it with zeroes, and then call
* allocsys() again with the correct base virtual address.
*/
caddr_t
allocsys(caddr_t v)
{
#define valloc(name, type, num) \
(name) = (type *)v; v = (caddr_t)((name) + (num))
#ifdef SYSVMSG
valloc(msgpool, char, msginfo.msgmax);
valloc(msgmaps, struct msgmap, msginfo.msgseg);
valloc(msghdrs, struct msg, msginfo.msgtql);
valloc(msqids, struct msqid_ds, msginfo.msgmni);
#endif
return (v);
}
/*
* Info for CTL_HW
*/
char cpu_model[120];
int cputyp;
int cpuspeed;
struct mvmeprom_brdid brdid;
void
identifycpu()
{
char mc;
char speed[6];
char suffix[30];
int len;
bzero(suffix, sizeof suffix);
switch (mmutype) {
case MMU_68060:
mc = '6';
break;
case MMU_68040:
mc = '4';
break;
case MMU_68030:
mc = '3';
break;
default:
mc = '2';
}
switch (cputyp) {
#ifdef MVME147
case CPU_147:
snprintf(suffix, sizeof suffix, "MVME%x", brdid.model);
cpuspeed = pccspeed((struct pccreg *)IIOV(0xfffe1000));
snprintf(speed, sizeof speed, "%02d", cpuspeed);
break;
#endif
#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
case CPU_162:
case CPU_167:
case CPU_172:
case CPU_177:
bzero(speed, sizeof speed);
speed[0] = brdid.speed[0];
speed[1] = brdid.speed[1];
if (brdid.speed[2] != '0' &&
brdid.speed[3] != '0') {
speed[2] = '.';
speed[3] = brdid.speed[2];
speed[4] = brdid.speed[3];
}
cpuspeed = (speed[0] - '0') * 10 + (speed[1] - '0');
bcopy(brdid.longname, suffix, sizeof(brdid.longname));
for (len = strlen(suffix)-1; len; len--) {
if (suffix[len] == ' ')
suffix[len] = '\0';
else
break;
}
break;
#endif
}
snprintf(cpu_model, sizeof cpu_model,
"Motorola %s: %sMHz MC680%c0 CPU", suffix, speed, mc);
switch (mmutype) {
#if defined(M68040)
case MMU_68040:
/* FALLTHROUGH */
#endif
#if defined(M68060)
case MMU_68060:
/* FALLTHROUGH */
#endif
case MMU_68030:
strlcat(cpu_model, "+MMU", sizeof cpu_model);
break;
case MMU_68851:
strlcat(cpu_model, ", MC68851 MMU", sizeof cpu_model);
break;
default:
printf("%s\n", cpu_model);
panic("unknown MMU type %d", mmutype);
}
switch (mmutype) {
#if defined(M68060)
case MMU_68060:
strlcat(cpu_model,"+FPU, 8k on-chip physical I/D caches",
sizeof cpu_model);
break;
#endif
#if defined(M68040)
case MMU_68040:
strlcat(cpu_model, "+FPU, 4k on-chip physical I/D caches",
sizeof cpu_model);
break;
#endif
#if defined(M68030) || defined(M68020)
default:
fputype = fpu_gettype();
switch (fputype) {
case FPU_NONE:
break;
case FPU_68881:
case FPU_68882:
len = strlen (cpu_model);
snprintf(cpu_model + len, sizeof cpu_model - len,
", MC6888%d FPU", fputype);
break;
default:
strlcat(cpu_model, ", unknown FPU", sizeof cpu_model);
break;
}
break;
#endif
}
printf("%s\n", cpu_model);
}
/*
* machine dependent system variables.
*/
int
cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
int *name;
u_int namelen;
void *oldp;
size_t *oldlenp;
void *newp;
size_t newlen;
struct proc *p;
{
dev_t consdev;
/* all sysctl names at this level are terminal */
if (namelen != 1)
return (ENOTDIR); /* overloaded */
switch (name[0]) {
case CPU_CONSDEV:
if (cn_tab != NULL)
consdev = cn_tab->cn_dev;
else
consdev = NODEV;
return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
sizeof consdev));
default:
return (EOPNOTSUPP);
}
/* NOTREACHED */
}
int waittime = -1;
__dead void
boot(howto)
int howto;
{
/* If system is cold, just halt. */
if (cold) {
/* (Unless the user explicitly asked for reboot.) */
if ((howto & RB_USERREQ) == 0)
howto |= RB_HALT;
goto haltsys;
}
/* take a snap shot before clobbering any registers */
if (curproc && curproc->p_addr)
savectx(&curproc->p_addr->u_pcb);
boothowto = howto;
if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
extern struct proc proc0;
/* do that another panic fly away */
if (curproc == NULL)
curproc = &proc0;
waittime = 0;
vfs_shutdown();
/*
* If we've been adjusting the clock, the todr
* will be out of synch; adjust it now unless
* the system was sitting in ddb.
*/
if ((howto & RB_TIMEBAD) == 0) {
resettodr();
} else {
printf("WARNING: not updating battery clock\n");
}
}
/* Disable interrupts. */
splhigh();
/* If rebooting and a dump is requested, do it. */
if (howto & RB_DUMP)
dumpsys();
haltsys:
/* Run any shutdown hooks. */
doshutdownhooks();
if (howto & RB_HALT) {
printf("System halted. Press any key to reboot...\n\n");
cngetc();
}
doboot();
for (;;);
/*NOTREACHED*/
}
/*
* These variables are needed by /sbin/savecore
*/
u_long dumpmag = 0x8fca0101; /* magic number */
int dumpsize = 0; /* pages */
long dumplo = 0; /* blocks */
cpu_kcore_hdr_t cpu_kcore_hdr;
/*
* This is called by configure to set dumplo and dumpsize.
* Dumps always skip the first PAGE_SIZE of disk space
* in case there might be a disk label stored there.
* If there is extra space, put dump at the end to
* reduce the chance that swapping trashes it.
*/
void
dumpconf(void)
{
int nblks; /* size of dump area */
if (dumpdev == NODEV ||
(nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
return;
if (nblks <= ctod(1))
return;
dumpsize = physmem;
/* mvme68k only uses a single segment. */
cpu_kcore_hdr.ram_segs[0].start = 0;
cpu_kcore_hdr.ram_segs[0].size = ctob(physmem);
cpu_kcore_hdr.mmutype = mmutype;
cpu_kcore_hdr.kernel_pa = 0;
cpu_kcore_hdr.sysseg_pa = pmap_kernel()->pm_stpa;
/* Always skip the first block, in case there is a label there. */
if (dumplo < ctod(1))
dumplo = ctod(1);
/* Put dump at end of partition, and make it fit. */
if (dumpsize + 1 > dtoc(nblks - dumplo))
dumpsize = dtoc(nblks - dumplo) - 1;
if (dumplo < nblks - ctod(dumpsize) - 1)
dumplo = nblks - ctod(dumpsize) - 1;
}
/*
* Doadump comes here after turning off memory management and
* getting on the dump stack, either when called above, or by
* the auto-restart code.
*/
void
dumpsys()
{
int maj;
int psize;
daddr64_t blkno; /* current block to write */
/* dump routine */
int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
int pg; /* page being dumped */
paddr_t maddr; /* PA being dumped */
int error; /* error code from (*dump)() */
kcore_seg_t *kseg_p;
cpu_kcore_hdr_t *chdr_p;
char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
extern int msgbufmapped;
msgbufmapped = 0;
/* Make sure dump device is valid. */
if (dumpdev == NODEV)
return;
if (dumpsize == 0) {
dumpconf();
if (dumpsize == 0)
return;
}
maj = major(dumpdev);
if (dumplo < 0) {
printf("\ndump to dev %u,%u not possible\n", maj,
minor(dumpdev));
return;
}
dump = bdevsw[maj].d_dump;
blkno = dumplo;
printf("\ndumping to dev %u,%u offset %ld\n", maj,
minor(dumpdev), dumplo);
kseg_p = (kcore_seg_t *)dump_hdr;
chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
bzero(dump_hdr, sizeof(dump_hdr));
/*
* Generate a segment header
*/
CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
/*
* Add the md header
*/
*chdr_p = cpu_kcore_hdr;
printf("dump ");
psize = (*bdevsw[maj].d_psize)(dumpdev);
if (psize == -1) {
printf("area unavailable\n");
return;
}
/* Dump the header. */
error = (*dump) (dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
if (error != 0)
goto abort;
maddr = (paddr_t)0;
for (pg = 0; pg < dumpsize; pg++) {
#define NPGMB (1024 * 1024 / PAGE_SIZE)
/* print out how many MBs we have dumped */
if (pg != 0 && (pg % NPGMB) == 0)
printf("%d ", pg / NPGMB);
#undef NPGMB
pmap_kenter_pa((vaddr_t)vmmap, maddr, VM_PROT_READ);
pmap_update(pmap_kernel());
error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
pmap_kremove((vaddr_t)vmmap, PAGE_SIZE);
pmap_update(pmap_kernel());
if (error == 0) {
maddr += PAGE_SIZE;
blkno += btodb(PAGE_SIZE);
} else
break;
}
abort:
switch (error) {
case 0:
printf("succeeded\n");
break;
case ENXIO:
printf("device bad\n");
break;
case EFAULT:
printf("device not ready\n");
break;
case EINVAL:
printf("area improper\n");
break;
case EIO:
printf("i/o error\n");
break;
case EINTR:
printf("aborted from console\n");
break;
default:
printf("error %d\n", error);
break;
}
}
#if defined(M68060)
int m68060_pcr_init = 0x20 | PCR_SUPERSCALAR; /* make this patchable */
#endif
void
initvectors()
{
typedef void trapfun(void);
extern trapfun *vectab[256];
#if defined(M68060)
#if defined(M060SP)
extern trapfun intemu60, fpiemu60, fpdemu60, fpeaemu60;
extern u_int8_t FP_CALL_TOP[];
#else
extern trapfun illinst;
#endif
extern trapfun fpfault;
#endif
#if defined(M68040) && defined(FPSP)
extern u_long fpvect_tab, fpvect_end, fpsp_tab;
#endif
switch (cputype) {
#ifdef M68060
case CPU_68060:
asm volatile ("movl %0,d0; .word 0x4e7b,0x0808" : :
"d"(m68060_pcr_init):"d0" );
#if defined(M060SP)
/* integer support */
vectab[61] = intemu60/*(trapfun *)&I_CALL_TOP[128 + 0x00]*/;
/* floating point support */
/*
* XXX maybe we really should run-time check for the
* stack frame format here:
*/
vectab[11] = fpiemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x30]*/;
vectab[55] = fpdemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x38]*/;
vectab[60] = fpeaemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x40]*/;
vectab[54] = (trapfun *)&FP_CALL_TOP[128 + 0x00];
vectab[52] = (trapfun *)&FP_CALL_TOP[128 + 0x08];
vectab[53] = (trapfun *)&FP_CALL_TOP[128 + 0x10];
vectab[51] = (trapfun *)&FP_CALL_TOP[128 + 0x18];
vectab[50] = (trapfun *)&FP_CALL_TOP[128 + 0x20];
vectab[49] = (trapfun *)&FP_CALL_TOP[128 + 0x28];
#else
vectab[61] = illinst;
#endif
vectab[48] = fpfault;
break;
#endif
#if defined(M68040) && defined(FPSP)
case CPU_68040:
bcopy(&fpsp_tab, &fpvect_tab,
(&fpvect_end - &fpvect_tab) * sizeof (fpvect_tab));
break;
#endif
default:
break;
}
}
void
straytrap(pc, evec)
int pc;
u_short evec;
{
printf("unexpected trap (vector 0x%x) from %x\n",
(evec & 0xFFF) >> 2, pc);
}
int *nofault;
int
badpaddr(addr, size)
paddr_t addr;
int size;
{
int off = (int)addr & PGOFSET;
vaddr_t v;
paddr_t p = trunc_page(addr);
int x;
v = mapiodev(p, NBPG);
if (v == 0)
return (1);
x = badvaddr(v + off, size);
unmapiodev(v, NBPG);
return (x);
}
int
badvaddr(addr, size)
vaddr_t addr;
int size;
{
int i;
label_t faultbuf;
nofault = (int *) &faultbuf;
if (setjmp((label_t *)nofault)) {
nofault = (int *)0;
return (1);
}
switch (size) {
case 1:
i = *(volatile char *)addr;
break;
case 2:
i = *(volatile short *)addr;
break;
case 4:
i = *(volatile long *)addr;
break;
}
nofault = (int *)0;
return (0);
}
int netisr;
void
netintr(arg)
void *arg;
{
int n;
while ((n = netisr) != 0) {
atomic_clearbits_int(&netisr, n);
#define DONETISR(bit, fn) \
do { \
if (n & (1 << (bit))) \
(fn)(); \
} while (0)
#include <net/netisr_dispatch.h>
#undef DONETISR
}
}
/*
* Level 7 interrupts are normally caused by the ABORT switch,
* drop into ddb.
*/
void
nmihand(frame)
void *frame;
{
#ifdef DDB
printf("NMI ... going to debugger\n");
Debugger();
#else
/* panic?? */
printf("unexpected level 7 interrupt ignored\n");
#endif
}
/*
* cpu_exec_aout_makecmds():
* cpu-dependent a.out format hook for execve().
*
* Determine of the given exec package refers to something which we
* understand and, if so, set up the vmcmds for it.
*/
int
cpu_exec_aout_makecmds(p, epp)
struct proc *p;
struct exec_package *epp;
{
int error = ENOEXEC;
#ifdef COMPAT_SUNOS
{
extern int sunos_exec_aout_makecmds(struct proc *, struct exec_package *);
if ((error = sunos_exec_aout_makecmds(p, epp)) == 0)
return (0);
}
#endif
return (error);
}
u_char myea[6] = { 0x08, 0x00, 0x3e, 0xff, 0xff, 0xff};
void
myetheraddr(ether)
u_char *ether;
{
bcopy(myea, ether, sizeof myea);
}
#if defined(M68030) || defined(M68020)
int
fpu_gettype()
{
/*
* A 68881 idle frame is 28 bytes and a 68882's is 60 bytes.
* We, of course, need to have enough room for either.
*/
int fpframe[60 / sizeof(int)];
label_t faultbuf;
u_char b;
nofault = (int *) &faultbuf;
if (setjmp((label_t *)nofault)) {
nofault = (int *)0;
return (0); /* no FPU */
}
/*
* Synchronize FPU or cause a fault.
* This should leave the 881/882 in the IDLE state,
* state, so we can determine which we have by
* examining the size of the FP state frame
*/
asm("fnop");
nofault = (int *)0;
/*
* Presumably, this will not cause a fault--the fnop should
* have if this will. We save the state in order to get the
* size of the frame.
*/
asm("movl %0, a0; fsave a0@" : : "a" (fpframe) : "a0" );
b = *((u_char *) fpframe + 1);
/*
* Now, restore a NULL state to reset the FPU.
*/
fpframe[0] = fpframe[1] = 0;
m68881_restore((struct fpframe *)fpframe);
if (b == 0x18)
return (FPU_68881); /* The size of a 68881 IDLE frame is 0x18 */
if (b == 0x38)
return (FPU_68882); /* 68882 frame is 0x38 bytes long */
return (FPU_UNKNOWN); /* unknown FPU type */
}
#endif
#if defined(MVME162) || defined(MVME172)
#include <mvme68k/dev/mcreg.h>
/*
* XXX
* used by locore.s to figure out how much memory is on the machine.
* At this stage we only know that our machine is a 162. It is very
* unfortunate that the MCchip's address must be encoded here.
*/
int
memsize162()
{
struct mcreg *mc = (struct mcreg *)0xfff42000;
switch (mc->mc_memoptions & MC_MEMOPTIONS_DRAMMASK) {
case MC_MEMOPTIONS_DRAM1M:
return (1*1024*1024);
case MC_MEMOPTIONS_DRAM2M:
return (2*1024*1024);
case MC_MEMOPTIONS_DRAM4M:
return (4*1024*1024);
case MC_MEMOPTIONS_DRAM4M2:
return (4*1024*1024);
case MC_MEMOPTIONS_DRAM8M:
return (8*1024*1024);
case MC_MEMOPTIONS_DRAM16M:
return (16*1024*1024);
default:
/*
* XXX if the machine has no MC-controlled memory,
* perhaps it has a MCECC or MEMC040 controller?
*/
return (memsize1x7());
}
}
#endif