802 lines
18 KiB
C
802 lines
18 KiB
C
/* $NetBSD: machdep.c,v 1.40 1997/04/03 17:35:56 christos Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 1994 Ludd, University of Lule}, Sweden.
|
|
* Copyright (c) 1993 Adam Glass
|
|
* Copyright (c) 1988 University of Utah.
|
|
* Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
|
|
* All rights reserved.
|
|
*
|
|
* Changed for the VAX port (and for readability) /IC
|
|
*
|
|
* 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. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the University of
|
|
* California, Berkeley and its contributors.
|
|
* 4. 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.63 91/04/24
|
|
*
|
|
* @(#)machdep.c 7.16 (Berkeley) 6/3/91
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/map.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/user.h>
|
|
#include <sys/time.h>
|
|
#include <sys/signal.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/reboot.h>
|
|
#include <sys/msgbuf.h>
|
|
#include <sys/buf.h>
|
|
#include <sys/mbuf.h>
|
|
#include <sys/reboot.h>
|
|
#include <sys/conf.h>
|
|
#include <sys/callout.h>
|
|
#include <sys/device.h>
|
|
#include <sys/exec.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/syscallargs.h>
|
|
#include <sys/ptrace.h>
|
|
#ifdef SYSVMSG
|
|
#include <sys/msg.h>
|
|
#endif
|
|
#ifdef SYSVSEM
|
|
#include <sys/sem.h>
|
|
#endif
|
|
#ifdef SYSVSHM
|
|
#include <sys/shm.h>
|
|
#endif
|
|
|
|
#include <vm/vm_kern.h>
|
|
|
|
#include <net/netisr.h>
|
|
#include <net/if.h>
|
|
|
|
#ifdef INET
|
|
#include <netinet/in.h>
|
|
#include <netinet/if_ether.h>
|
|
#include <netinet/ip_var.h>
|
|
#endif
|
|
#ifdef NETATALK
|
|
#include <netatalk/at_extern.h>
|
|
#endif
|
|
#ifdef NS
|
|
#include <netns/ns_var.h>
|
|
#endif
|
|
#include "ppp.h" /* For NERISR_PPP */
|
|
#if NPPP > 0
|
|
#include <net/ppp_defs.h>
|
|
#include <net/if_ppp.h>
|
|
#endif
|
|
|
|
#include <machine/sid.h>
|
|
#include <machine/pte.h>
|
|
#include <machine/mtpr.h>
|
|
#include <machine/cpu.h>
|
|
#include <machine/macros.h>
|
|
#include <machine/nexus.h>
|
|
#include <machine/trap.h>
|
|
#include <machine/reg.h>
|
|
#include <machine/db_machdep.h>
|
|
#include <vax/vax/gencons.h>
|
|
|
|
#ifdef DDB
|
|
#include <ddb/db_sym.h>
|
|
#include <ddb/db_extern.h>
|
|
#endif
|
|
|
|
void netintr __P((void));
|
|
void machinecheck __P((caddr_t));
|
|
void cmrerr __P((void));
|
|
|
|
extern int virtual_avail, virtual_end;
|
|
/*
|
|
* We do these external declarations here, maybe they should be done
|
|
* somewhere else...
|
|
*/
|
|
int nmcr, nmba, numuba, cold = 1;
|
|
caddr_t mcraddr[MAXNMCR];
|
|
int astpending;
|
|
int want_resched;
|
|
char machine[] = "vax";
|
|
char cpu_model[100];
|
|
int msgbufmapped = 0;
|
|
struct msgbuf *msgbufp;
|
|
int physmem;
|
|
struct cfdriver nexuscd;
|
|
int todrstopped = 0, glurg;
|
|
int dumpsize = 0;
|
|
|
|
caddr_t allocsys __P((caddr_t));
|
|
|
|
#define valloclim(name, type, num, lim) \
|
|
(name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
|
|
|
|
#ifdef BUFPAGES
|
|
int bufpages = BUFPAGES;
|
|
#else
|
|
int bufpages = 0;
|
|
#endif
|
|
int nswbuf = 0;
|
|
#ifdef NBUF
|
|
int nbuf = NBUF;
|
|
#else
|
|
int nbuf = 0;
|
|
#endif
|
|
|
|
void
|
|
cpu_startup()
|
|
{
|
|
caddr_t v;
|
|
extern char version[];
|
|
int base, residual, i, sz;
|
|
vm_offset_t minaddr, maxaddr;
|
|
vm_size_t size;
|
|
extern unsigned int avail_end;
|
|
|
|
/*
|
|
* Initialize error message buffer.
|
|
*/
|
|
msgbufmapped = 1;
|
|
|
|
#if VAX750 || VAX650
|
|
if (vax_cputype == VAX_750 || vax_cputype == VAX_650)
|
|
if (!mfpr(PR_TODR))
|
|
mtpr(todrstopped = 1, PR_TODR);
|
|
#endif
|
|
/*
|
|
* Good {morning,afternoon,evening,night}.
|
|
*/
|
|
printf("%s\n", version);
|
|
printf("realmem = %d\n", avail_end);
|
|
physmem = btoc(avail_end);
|
|
panicstr = NULL;
|
|
mtpr(AST_NO, PR_ASTLVL);
|
|
spl0();
|
|
|
|
dumpsize = physmem + 1;
|
|
|
|
/*
|
|
* Find out how much space we need, allocate it, and then give
|
|
* everything true virtual addresses.
|
|
*/
|
|
|
|
sz = (int) allocsys((caddr_t) 0);
|
|
if ((v = (caddr_t) kmem_alloc(kernel_map, round_page(sz))) == 0)
|
|
panic("startup: no room for tables");
|
|
if (allocsys(v) - v != sz)
|
|
panic("startup: table size inconsistency");
|
|
|
|
/*
|
|
* Now allocate buffers proper. They are different than the above in
|
|
* that they usually occupy more virtual memory than physical.
|
|
*/
|
|
size = MAXBSIZE * nbuf;
|
|
buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *) & buffers,
|
|
&maxaddr, size, TRUE);
|
|
minaddr = (vm_offset_t) buffers;
|
|
if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t) 0,
|
|
&minaddr, size, FALSE) != KERN_SUCCESS)
|
|
panic("startup: cannot allocate buffers");
|
|
if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
|
|
/* don't want to alloc more physical mem than needed */
|
|
bufpages = btoc(MAXBSIZE) * nbuf;
|
|
}
|
|
base = bufpages / nbuf;
|
|
residual = bufpages % nbuf;
|
|
for (i = 0; i < nbuf; i++) {
|
|
vm_size_t curbufsize;
|
|
vm_offset_t curbuf;
|
|
|
|
/*
|
|
* First <residual> buffers get (base+1) physical pages
|
|
* allocated for them. The rest get (base) physical pages.
|
|
*
|
|
* The rest of each buffer occupies virtual space, but has no
|
|
* physical memory allocated for it.
|
|
*/
|
|
curbuf = (vm_offset_t) buffers + i * MAXBSIZE;
|
|
curbufsize = CLBYTES * (i < residual ? base + 1 : base);
|
|
vm_map_pageable(buffer_map, curbuf, curbuf + curbufsize, FALSE);
|
|
vm_map_simplify(buffer_map, curbuf);
|
|
}
|
|
|
|
/*
|
|
* Allocate a submap for exec arguments. This map effectively limits
|
|
* the number of processes exec'ing at any time.
|
|
*/
|
|
exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
|
|
16 * NCARGS, TRUE);
|
|
|
|
/*
|
|
* Finally, allocate mbuf cluster submap.
|
|
*/
|
|
mb_map = kmem_suballoc(kernel_map, (vm_offset_t *) & mbutl, &maxaddr,
|
|
VM_MBUF_SIZE, FALSE);
|
|
|
|
/*
|
|
* Allocate a submap for physio
|
|
*/
|
|
phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
|
|
VM_PHYS_SIZE, TRUE);
|
|
|
|
/*
|
|
* Initialize callouts
|
|
*/
|
|
|
|
callfree = callout;
|
|
for (i = 1; i < ncallout; i++)
|
|
callout[i - 1].c_next = &callout[i];
|
|
callout[i - 1].c_next = NULL;
|
|
|
|
printf("avail mem = %d\n", (int)ptoa(cnt.v_free_count));
|
|
printf("Using %d buffers containing %d bytes of memory.\n",
|
|
nbuf, bufpages * CLBYTES);
|
|
|
|
/*
|
|
* Set up buffers, so they can be used to read disk labels.
|
|
*/
|
|
|
|
bufinit();
|
|
|
|
/*
|
|
* Configure the system.
|
|
*/
|
|
configure();
|
|
}
|
|
|
|
/*
|
|
* 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.
|
|
*
|
|
* We 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(v)
|
|
register caddr_t v;
|
|
{
|
|
|
|
#define valloc(name, type, num) \
|
|
v = (caddr_t)(((name) = (type *)v) + (num))
|
|
|
|
#ifdef REAL_CLISTS
|
|
valloc(cfree, struct cblock, nclist);
|
|
#endif
|
|
valloc(callout, struct callout, ncallout);
|
|
valloc(swapmap, struct map, nswapmap = maxproc * 2);
|
|
#ifdef SYSVSHM
|
|
valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
|
|
#endif
|
|
#ifdef SYSVSEM
|
|
valloc(sema, struct semid_ds, seminfo.semmni);
|
|
valloc(sem, struct sem, seminfo.semmns);
|
|
/* This is pretty disgusting! */
|
|
valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
|
|
#endif
|
|
#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
|
|
|
|
/*
|
|
* Determine how many buffers to allocate (enough to hold 5% of total
|
|
* physical memory, but at least 16). Allocate 1/2 as many swap
|
|
* buffer headers as file i/o buffers.
|
|
*/
|
|
if (bufpages == 0)
|
|
if (physmem < btoc(2 * 1024 * 1024))
|
|
bufpages = (physmem / 10) / CLSIZE;
|
|
else
|
|
bufpages = (physmem / 20) / CLSIZE;
|
|
if (nbuf == 0) {
|
|
nbuf = bufpages;
|
|
if (nbuf < 16)
|
|
nbuf = 16;
|
|
}
|
|
if (nswbuf == 0) {
|
|
nswbuf = (nbuf / 2) & ~1; /* force even */
|
|
if (nswbuf > 256)
|
|
nswbuf = 256; /* sanity */
|
|
}
|
|
valloc(swbuf, struct buf, nswbuf);
|
|
valloc(buf, struct buf, nbuf);
|
|
return v;
|
|
}
|
|
|
|
long dumplo = 0;
|
|
long dumpmag = 0x8fca0101;
|
|
|
|
void
|
|
cpu_dumpconf()
|
|
{
|
|
int nblks;
|
|
extern int dumpdev;
|
|
|
|
/*
|
|
* XXX include the final RAM page which is not included in physmem.
|
|
*/
|
|
dumpsize = physmem + 1;
|
|
if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
|
|
nblks = (*bdevsw[major(dumpdev)].d_psize) (dumpdev);
|
|
if (dumpsize > btoc(dbtob(nblks - dumplo)))
|
|
dumpsize = btoc(dbtob(nblks - dumplo));
|
|
else if (dumplo == 0)
|
|
dumplo = nblks - btodb(ctob(dumpsize));
|
|
}
|
|
/*
|
|
* Don't dump on the first CLBYTES (why CLBYTES?) in case the dump
|
|
* device includes a disk label.
|
|
*/
|
|
if (dumplo < btodb(CLBYTES))
|
|
dumplo = btodb(CLBYTES);
|
|
}
|
|
|
|
void
|
|
cpu_initclocks()
|
|
{
|
|
(*dep_call->cpu_clock) ();
|
|
}
|
|
|
|
int
|
|
cpu_sysctl(a, b, c, d, e, f, g)
|
|
int *a;
|
|
u_int b;
|
|
void *c, *e;
|
|
size_t *d, f;
|
|
struct proc *g;
|
|
{
|
|
return (EOPNOTSUPP);
|
|
}
|
|
|
|
void
|
|
setstatclockrate(hzrate)
|
|
int hzrate;
|
|
{
|
|
panic("setstatclockrate");
|
|
}
|
|
|
|
void
|
|
consinit()
|
|
{
|
|
cninit();
|
|
#ifdef DDB
|
|
/* db_machine_init(); */
|
|
ddb_init();
|
|
#ifdef donotworkbyunknownreason
|
|
if (boothowto & RB_KDB)
|
|
Debugger();
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
int
|
|
sys_sigreturn(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct sys_sigreturn_args /* {
|
|
syscallarg(struct sigcontext *) sigcntxp;
|
|
} */ *uap = v;
|
|
struct trapframe *scf;
|
|
struct sigcontext *cntx;
|
|
|
|
scf = p->p_addr->u_pcb.framep;
|
|
cntx = SCARG(uap, sigcntxp);
|
|
|
|
/* Compatibility mode? */
|
|
if ((cntx->sc_ps & (PSL_IPL | PSL_IS)) ||
|
|
((cntx->sc_ps & (PSL_U | PSL_PREVU)) != (PSL_U | PSL_PREVU)) ||
|
|
(cntx->sc_ps & PSL_CM)) {
|
|
return (EINVAL);
|
|
}
|
|
if (cntx->sc_onstack & 01)
|
|
p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
|
|
else
|
|
p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
|
|
p->p_sigmask = cntx->sc_mask & ~sigcantmask;
|
|
|
|
scf->fp = cntx->sc_fp;
|
|
scf->ap = cntx->sc_ap;
|
|
scf->pc = cntx->sc_pc;
|
|
scf->sp = cntx->sc_sp;
|
|
scf->psl = cntx->sc_ps;
|
|
return (EJUSTRETURN);
|
|
}
|
|
|
|
struct trampframe {
|
|
unsigned sig; /* Signal number */
|
|
unsigned code; /* Info code */
|
|
unsigned scp; /* Pointer to struct sigcontext */
|
|
unsigned r0, r1, r2, r3, r4, r5; /* Registers saved when
|
|
* interrupt */
|
|
unsigned pc; /* Address of signal handler */
|
|
unsigned arg; /* Pointer to first (and only) sigreturn
|
|
* argument */
|
|
};
|
|
|
|
void
|
|
sendsig(catcher, sig, mask, code)
|
|
sig_t catcher;
|
|
int sig, mask;
|
|
u_long code;
|
|
{
|
|
struct proc *p = curproc;
|
|
struct sigacts *psp = p->p_sigacts;
|
|
struct trapframe *syscf;
|
|
struct sigcontext *sigctx;
|
|
struct trampframe *trampf;
|
|
unsigned cursp;
|
|
int oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
|
|
extern char sigcode[], esigcode[];
|
|
/*
|
|
* Allocate and validate space for the signal handler context. Note
|
|
* that if the stack is in P0 space, the call to grow() is a nop, and
|
|
* the useracc() check will fail if the process has not already
|
|
* allocated the space with a `brk'. We shall allocate space on the
|
|
* stack for both struct sigcontext and struct calls...
|
|
*/
|
|
syscf = p->p_addr->u_pcb.framep;
|
|
|
|
/* First check what stack to work on */
|
|
if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
|
|
(psp->ps_sigonstack & sigmask(sig))) {
|
|
cursp = (int)(psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size);
|
|
psp->ps_sigstk.ss_flags |= SS_ONSTACK;
|
|
} else
|
|
cursp = syscf->sp;
|
|
if (cursp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
|
|
(void) grow(p, cursp);
|
|
|
|
/* Set up positions for structs on stack */
|
|
sigctx = (struct sigcontext *) (cursp - sizeof(struct sigcontext));
|
|
trampf = (struct trampframe *) ((unsigned)sigctx -
|
|
sizeof(struct trampframe));
|
|
|
|
/* Place for pointer to arg list in sigreturn */
|
|
cursp = (unsigned)sigctx - 8;
|
|
|
|
if (useracc((caddr_t) cursp, sizeof(struct sigcontext) +
|
|
sizeof(struct trampframe), B_WRITE) == 0) {
|
|
/*
|
|
* Process has trashed its stack; give it an illegal
|
|
* instruction to halt it in its tracks.
|
|
*/
|
|
SIGACTION(p, SIGILL) = SIG_DFL;
|
|
sig = sigmask(SIGILL);
|
|
p->p_sigignore &= ~sig;
|
|
p->p_sigcatch &= ~sig;
|
|
p->p_sigmask &= ~sig;
|
|
psignal(p, SIGILL);
|
|
return;
|
|
}
|
|
/* Set up pointers for sigreturn args */
|
|
trampf->arg = (int) sigctx;
|
|
trampf->pc = (unsigned) catcher;
|
|
trampf->scp = (int) sigctx;
|
|
trampf->code = code;
|
|
trampf->sig = sig;
|
|
|
|
|
|
sigctx->sc_pc = syscf->pc;
|
|
sigctx->sc_ps = syscf->psl;
|
|
sigctx->sc_ap = syscf->ap;
|
|
sigctx->sc_fp = syscf->fp;
|
|
sigctx->sc_sp = syscf->sp;
|
|
sigctx->sc_onstack = oonstack;
|
|
sigctx->sc_mask = mask;
|
|
|
|
syscf->pc = (unsigned) (((char *) PS_STRINGS) - (esigcode - sigcode));
|
|
syscf->psl = PSL_U | PSL_PREVU;
|
|
syscf->ap = cursp;
|
|
syscf->sp = cursp;
|
|
}
|
|
|
|
int waittime = -1;
|
|
static volatile int showto; /* Must be volatile to survive MM on -> MM off */
|
|
|
|
void
|
|
cpu_reboot(howto, bootstr)
|
|
register howto;
|
|
char *bootstr;
|
|
{
|
|
showto = howto;
|
|
if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
|
|
waittime = 0;
|
|
vfs_shutdown();
|
|
/*
|
|
* If we've been adjusting the clock, the todr will be out of
|
|
* synch; adjust it now.
|
|
*/
|
|
resettodr();
|
|
}
|
|
splhigh(); /* extreme priority */
|
|
if (howto & RB_HALT) {
|
|
printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n");
|
|
for ( ; ; )
|
|
;
|
|
} else {
|
|
/*
|
|
* Now it's time to:
|
|
* 0. Save some registers that are needed in new world.
|
|
* 1. Change stack to somewhere that will survive MM off.
|
|
* (RPB page is good page to save things in).
|
|
* 2. Actually turn MM off.
|
|
* 3. Dump away memory to disk, if asked.
|
|
* 4. Reboot as asked.
|
|
* The RPB page is _always_ first page in memory, we can
|
|
* rely on that.
|
|
*/
|
|
asm(" movl sp, (0x80000200)
|
|
movl 0x80000200, sp
|
|
mfpr $0x10, -(sp) # PR_PCBB
|
|
mfpr $0x11, -(sp) # PR_SCBB
|
|
mfpr $0xc, -(sp) # PR_SBR
|
|
mfpr $0xd, -(sp) # PR_SLR
|
|
mtpr $0, $0x38 # PR_MAPEN
|
|
");
|
|
if (showto & RB_DUMP)
|
|
dumpsys();
|
|
|
|
asm("movl %0,r5":: "g" (showto)); /* How to boot */
|
|
|
|
switch (vax_cputype) {
|
|
int state;
|
|
|
|
#if VAX750 || VAX780 || VAX630
|
|
case VAX_780:
|
|
case VAX_750:
|
|
case VAX_TYP_UV2:
|
|
mtpr(GC_BOOT, PR_TXDB); /* boot command */
|
|
break;
|
|
#endif
|
|
#if VAX8600
|
|
case VAX_8600:
|
|
state = mfpr(PR_TXCS);
|
|
gencnputc(0, GC_LT | GC_WRT);
|
|
mtpr(0x2, PR_TXDB); /* XXX */
|
|
gencnputc(0, state | GC_WRT);
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
}
|
|
asm("movl %0, r11":: "r"(showto));
|
|
asm("halt");
|
|
panic("Halt sket sej");
|
|
}
|
|
|
|
void
|
|
netintr()
|
|
{
|
|
#ifdef INET
|
|
if (netisr & (1 << NETISR_ARP)) {
|
|
netisr &= ~(1 << NETISR_ARP);
|
|
arpintr();
|
|
}
|
|
if (netisr & (1 << NETISR_IP)) {
|
|
netisr &= ~(1 << NETISR_IP);
|
|
ipintr();
|
|
}
|
|
#endif
|
|
#ifdef NETATALK
|
|
if (netisr & (1 << NETISR_ATALK)) {
|
|
netisr &= ~(1 << NETISR_ATALK);
|
|
atintr();
|
|
}
|
|
#endif
|
|
#ifdef NS
|
|
if (netisr & (1 << NETISR_NS)) {
|
|
netisr &= ~(1 << NETISR_NS);
|
|
nsintr();
|
|
}
|
|
#endif
|
|
#ifdef ISO
|
|
if (netisr & (1 << NETISR_ISO)) {
|
|
netisr &= ~(1 << NETISR_ISO);
|
|
clnlintr();
|
|
}
|
|
#endif
|
|
#ifdef CCITT
|
|
if (netisr & (1 << NETISR_CCITT)) {
|
|
netisr &= ~(1 << NETISR_CCITT);
|
|
ccittintr();
|
|
}
|
|
#endif
|
|
#if NPPP > 0
|
|
if (netisr & (1 << NETISR_PPP)) {
|
|
pppintr();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void
|
|
machinecheck(frame)
|
|
caddr_t frame;
|
|
{
|
|
if ((*dep_call->cpu_mchk) (frame) == 0)
|
|
return;
|
|
(*dep_call->cpu_memerr) ();
|
|
panic("machine check");
|
|
}
|
|
|
|
void
|
|
dumpsys()
|
|
{
|
|
extern int dumpdev;
|
|
|
|
msgbufmapped = 0;
|
|
if (dumpdev == NODEV)
|
|
return;
|
|
/*
|
|
* For dumps during autoconfiguration, if dump device has already
|
|
* configured...
|
|
*/
|
|
if (dumpsize == 0)
|
|
cpu_dumpconf();
|
|
if (dumplo < 0)
|
|
return;
|
|
printf("\ndumping to dev %x, offset %d\n", dumpdev, (int)dumplo);
|
|
printf("dump ");
|
|
switch ((*bdevsw[major(dumpdev)].d_dump) (dumpdev, 0, 0, 0)) {
|
|
|
|
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;
|
|
|
|
default:
|
|
printf("succeeded\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
int
|
|
fuswintr(addr)
|
|
const void *addr;
|
|
{
|
|
panic("fuswintr: need to be implemented");
|
|
return 0;
|
|
|
|
}
|
|
|
|
int
|
|
suibyte(base, byte)
|
|
void *base;
|
|
short byte;
|
|
{
|
|
panic("suibyte: need to be implemented");
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
suswintr(addr, cnt)
|
|
void *addr;
|
|
short cnt;
|
|
{
|
|
panic("suswintr: need to be implemented");
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
process_read_regs(p, regs)
|
|
struct proc *p;
|
|
struct reg *regs;
|
|
{
|
|
struct trapframe *tf = p->p_addr->u_pcb.framep;
|
|
|
|
bcopy(&tf->r0, ®s->r0, 12 * sizeof(int));
|
|
regs->ap = tf->ap;
|
|
regs->fp = tf->fp;
|
|
regs->sp = tf->sp;
|
|
regs->pc = tf->pc;
|
|
regs->psl = tf->psl;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
process_write_regs(p, regs)
|
|
struct proc *p;
|
|
struct reg *regs;
|
|
{
|
|
struct trapframe *tf = p->p_addr->u_pcb.framep;
|
|
|
|
bcopy(®s->r0, &tf->r0, 12 * sizeof(int));
|
|
tf->ap = regs->ap;
|
|
tf->fp = regs->fp;
|
|
tf->sp = regs->sp;
|
|
tf->pc = regs->pc;
|
|
tf->psl = regs->psl;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
process_set_pc(p, addr)
|
|
struct proc *p;
|
|
caddr_t addr;
|
|
{
|
|
struct trapframe *tf;
|
|
void *ptr;
|
|
|
|
if ((p->p_flag & P_INMEM) == 0)
|
|
return (EIO);
|
|
|
|
ptr = (char *) p->p_addr->u_pcb.framep;
|
|
tf = ptr;
|
|
|
|
tf->pc = (unsigned) addr;
|
|
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
process_sstep(p, sstep)
|
|
struct proc *p;
|
|
{
|
|
void *ptr;
|
|
struct trapframe *tf;
|
|
|
|
if ((p->p_flag & P_INMEM) == 0)
|
|
return (EIO);
|
|
|
|
ptr = p->p_addr->u_pcb.framep;
|
|
tf = ptr;
|
|
|
|
if (sstep)
|
|
tf->psl |= PSL_T;
|
|
else
|
|
tf->psl &= ~PSL_T;
|
|
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
cmrerr()
|
|
{
|
|
(*dep_call->cpu_memerr) ();
|
|
}
|