diff options
author | dfr <dfr@FreeBSD.org> | 1998-06-10 10:57:29 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1998-06-10 10:57:29 +0000 |
commit | 224577d6cf4d0daf37dddd81b9f9c646ad2be083 (patch) | |
tree | 345e0ea224736af311f2e28c0acb268d809bff9c | |
parent | 2e6fba7d51b32033eec1fc27efaa0f8e840825fe (diff) | |
download | FreeBSD-src-224577d6cf4d0daf37dddd81b9f9c646ad2be083.zip FreeBSD-src-224577d6cf4d0daf37dddd81b9f9c646ad2be083.tar.gz |
Add initial support for the FreeBSD/alpha kernel. This is very much a
work in progress and has never booted a real machine. Initial
development and testing was done using SimOS (see
http://simos.stanford.edu for details). On the SimOS simulator, this
port successfully reaches single-user mode and has been tested with
loads as high as one copy of /bin/ls :-).
Obtained from: partly from NetBSD/alpha
113 files changed, 21627 insertions, 176 deletions
diff --git a/sys/alpha/alpha/autoconf.c b/sys/alpha/alpha/autoconf.c new file mode 100644 index 0000000..f70e85d --- /dev/null +++ b/sys/alpha/alpha/autoconf.c @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/disklabel.h> +#include <sys/diskslice.h> /* for BASE_SLICE, MAX_SLICES */ +#include <sys/reboot.h> +#include <sys/kernel.h> +#include <sys/mount.h> +#include <sys/sysctl.h> +#include <sys/bus.h> + +#include <machine/cons.h> +#include <machine/ipl.h> +#include <machine/md_var.h> +#include <machine/cpuconf.h> + +#include "scbus.h" +#if NSCBUS > 0 +#include <scsi/scsiconf.h> +#endif + +static void configure __P((void *)); +SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) + +static void configure_finish __P((void)); +static void configure_start __P((void)); + +static void +configure_start() +{ +#if NSCBUS > 0 + scsi_configure_start(); +#endif +} + +static void +configure_finish() +{ +#if NSCBUS > 0 + scsi_configure_finish(); +#endif +} + +/* + * Determine i/o configuration for a machine. + */ +static void +configure(void *dummy) +{ + configure_start(); + + bus_add_device(root_bus, platform.iobus, 0, 0); + root_bus_configure(); + + pci_configure(); + + configure_finish(); + + cninit_finish(); + + /* + * Now we're ready to handle (pending) interrupts. + * XXX this is slightly misplaced. + */ + spl0(); + + cold = 0; +} + +void +cpu_rootconf() +{ + mountrootfsname = "ufs"; + rootdevs[0] = makedev(4, dkmakeminor(0, COMPATIBILITY_SLICE, 0)); + rootdevnames[0] = "sd0c"; +} + +void +cpu_dumpconf() +{ +} diff --git a/sys/alpha/alpha/clock.c b/sys/alpha/alpha/clock.c new file mode 100644 index 0000000..24eb3c8 --- /dev/null +++ b/sys/alpha/alpha/clock.c @@ -0,0 +1,355 @@ +/* $Id$ */ +/* $NetBSD: clock.c,v 1.20 1998/01/31 10:32:47 ross Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 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 and Ralph Campbell. + * + * 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: clock.c 1.18 91/01/21 + * + * @(#)clock.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <machine/cpuconf.h> + +#include <dev/dec/clockvar.h> + +#define SECMIN ((unsigned)60) /* seconds per minute */ +#define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */ +#define SECDAY ((unsigned)(24*SECHOUR)) /* seconds per day */ +#define SECYR ((unsigned)(365*SECDAY)) /* seconds per common year */ + +#define LEAPYEAR(year) (((year) % 4) == 0) + +device_t clockdev; +const struct clockfns *clockfns; +int clockinitted; +int tickfix; +int tickfixinterval; +int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ + +extern cycles_per_sec; + +static timecounter_get_t alpha_get_timecount; +static timecounter_pps_t alpha_poll_pps; + +static struct timecounter alpha_timecounter[3] = { + alpha_get_timecount, /* get_timecount */ + 0, /* no poll_pps */ + ~0u, /* counter_mask */ + 0, /* frequency */ + "alpha" /* name */ +}; + +SYSCTL_OPAQUE(_debug, OID_AUTO, alpha_timecounter, CTLFLAG_RD, + alpha_timecounter, sizeof(alpha_timecounter), "S,timecounter", ""); + +/* + * Algorithm for missed clock ticks from Linux/alpha. + */ + +/* + * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting + * by 48 gives us 16 bits for HZ while keeping the accuracy good even + * for large CPU clock rates. + */ +#define FIX_SHIFT 48 + +static u_int64_t scaled_ticks_per_cycle; +static u_int32_t max_cycles_per_tick; +static u_int32_t last_time; + +static void handleclock(void* arg); + +void +clockattach(dev, fns) + struct device *dev; + const struct clockfns *fns; +{ + + /* + * Just bookkeeping. + */ + if (clockfns != NULL) + panic("clockattach: multiple clocks"); + clockdev = dev; + clockfns = fns; +#ifdef EVCNT_COUNTERS + evcnt_attach(dev, "intr", &clock_intr_evcnt); +#endif +} + +/* + * Machine-dependent clock routines. + * + * Startrtclock restarts the real-time clock, which provides + * hardclock interrupts to kern_clock.c. + * + * Inittodr initializes the time of day hardware which provides + * date functions. Its primary function is to use some file + * system information in case the hardare clock lost state. + * + * Resettodr restores the time of day hardware after a time change. + */ + +/* + * Start the real-time and statistics clocks. Leave stathz 0 since there + * are no other timers available. + */ +void +cpu_initclocks() +{ + if (clockfns == NULL) + panic("cpu_initclocks: no clock attached"); + + tick = 1000000 / hz; /* number of microseconds between interrupts */ + tickfix = 1000000 - (hz * tick); + if (tickfix) { + int ftp; + + ftp = min(ffs(tickfix), ffs(hz)); + tickfix >>= (ftp - 1); + tickfixinterval = hz >> (ftp - 1); + } + + /* + * Establish the clock interrupt; it's a special case. + * + * We establish the clock interrupt this late because if + * we do it at clock attach time, we may have never been at + * spl0() since taking over the system. Some versions of + * PALcode save a clock interrupt, which would get delivered + * when we spl0() in autoconf.c. If established the clock + * interrupt handler earlier, that interrupt would go to + * hardclock, which would then fall over because p->p_stats + * isn't set at that time. + */ + last_time = alpha_rpcc(); + scaled_ticks_per_cycle = ((u_int64_t)hz << FIX_SHIFT) / cycles_per_sec; + max_cycles_per_tick = 2*cycles_per_sec / hz; + + alpha_timecounter[0].tc_frequency = cycles_per_sec; + init_timecounter(alpha_timecounter); + + platform.clockintr = (void (*) __P((void *))) handleclock; + + /* + * Get the clock started. + */ + (*clockfns->cf_init)(clockdev); +} + +static void +handleclock(void* arg) +{ + u_int32_t now = alpha_rpcc(); + u_int32_t delta = now - last_time; + last_time = now; + + if (delta > max_cycles_per_tick) { + int i, missed_ticks; + missed_ticks = (delta * scaled_ticks_per_cycle) >> FIX_SHIFT; + for (i = 0; i < missed_ticks; i++) + hardclock(arg); + } + hardclock(arg); +} + +/* + * We assume newhz is either stathz or profhz, and that neither will + * change after being set up above. Could recalculate intervals here + * but that would be a drag. + */ +void +setstatclockrate(newhz) + int newhz; +{ + + /* nothing we can do */ +} + +/* + * This code is defunct after 2099. + * Will Unix still be here then?? + */ +static short dayyr[12] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 +}; + +/* + * Initialze the time of day register, based on the time base which is, e.g. + * from a filesystem. Base provides the time to within six months, + * and the time of year clock (if any) provides the rest. + */ +void +inittodr(base) + time_t base; +{ + register int days, yr; + struct clocktime ct; + time_t deltat; + int badbase; + int s; + struct timespec ts; + + if (base < 5*SECYR) { + printf("WARNING: preposterous time in file system"); + /* read the system clock anyway */ + base = 6*SECYR + 186*SECDAY + SECDAY/2; + badbase = 1; + } else + badbase = 0; + + (*clockfns->cf_get)(clockdev, base, &ct); + clockinitted = 1; + + /* simple sanity checks */ + if (ct.year < 70 || ct.mon < 1 || ct.mon > 12 || ct.day < 1 || + ct.day > 31 || ct.hour > 23 || ct.min > 59 || ct.sec > 59) { + /* + * Believe the time in the file system for lack of + * anything better, resetting the TODR. + */ + s = splclock(); + ts.tv_sec = base; + ts.tv_nsec = 0; + set_timecounter(&ts); + splx(s); + if (!badbase) { + printf("WARNING: preposterous clock chip time\n"); + resettodr(); + } + goto bad; + } + days = 0; + for (yr = 70; yr < ct.year; yr++) + days += LEAPYEAR(yr) ? 366 : 365; + days += dayyr[ct.mon - 1] + ct.day - 1; + if (LEAPYEAR(yr) && ct.mon > 2) + days++; + /* now have days since Jan 1, 1970; the rest is easy... */ + s = splclock(); + ts.tv_sec = + days * SECDAY + ct.hour * SECHOUR + ct.min * SECMIN + ct.sec; + ts.tv_nsec = 0; + set_timecounter(&ts); + splx(s); + + if (!badbase) { + /* + * See if we gained/lost two or more days; + * if so, assume something is amiss. + */ + deltat = ts.tv_sec - base; + if (deltat < 0) + deltat = -deltat; + if (deltat < 2 * SECDAY) + return; + printf("WARNING: clock %s %d days", + ts.tv_sec < base ? "lost" : "gained", deltat / SECDAY); + } +bad: + printf(" -- CHECK AND RESET THE DATE!\n"); +} + +/* + * Reset the TODR based on the time value; used when the TODR + * has a preposterous value and also when the time is reset + * by the stime system call. Also called when the TODR goes past + * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) + * to wrap the TODR around. + */ +void +resettodr() +{ + register int t, t2, s; + struct clocktime ct; + unsigned long tm; + + s = splclock(); + tm = time_second; + splx(s); + + if (!clockinitted) + return; + + /* compute the day of week. */ + t2 = tm / SECDAY; + ct.dow = (t2 + 4) % 7; /* 1/1/1970 was thursday */ + + /* compute the year */ + ct.year = 69; + t = t2; /* XXX ? */ + while (t2 >= 0) { /* whittle off years */ + t = t2; + ct.year++; + t2 -= LEAPYEAR(ct.year) ? 366 : 365; + } + + /* t = month + day; separate */ + t2 = LEAPYEAR(ct.year); + for (ct.mon = 1; ct.mon < 12; ct.mon++) + if (t < dayyr[ct.mon] + (t2 && ct.mon > 1)) + break; + + ct.day = t - dayyr[ct.mon - 1] + 1; + if (t2 && ct.mon > 2) + ct.day--; + + /* the rest is easy */ + t = tm % SECDAY; + ct.hour = t / SECHOUR; + t %= 3600; + ct.min = t / SECMIN; + ct.sec = t % SECMIN; + + (*clockfns->cf_set)(clockdev, &ct); +} + +static unsigned +alpha_get_timecount(struct timecounter* tc) +{ + return alpha_rpcc(); +} + diff --git a/sys/alpha/alpha/cons.c b/sys/alpha/alpha/cons.c new file mode 100644 index 0000000..511f370 --- /dev/null +++ b/sys/alpha/alpha/cons.c @@ -0,0 +1,448 @@ +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1991 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. 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: @(#)cons.c 7.2 (Berkeley) 5/9/91 + * $Id: cons.c,v 1.57 1998/03/28 10:32:56 bde Exp $ + */ + +#include "opt_devfs.h" + +#include <sys/param.h> +#ifdef DEVFS +#include <sys/devfsext.h> +#endif /*DEVFS*/ +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/reboot.h> +#include <sys/sysctl.h> +#include <sys/proc.h> +#include <sys/tty.h> +#include <sys/uio.h> + +#include <machine/cpu.h> +#include <machine/cons.h> + +/* XXX this should be config(8)ed. */ +#if 0 +#include "sc.h" +#include "vt.h" +#include "sio.h" +#endif +static struct consdev constab[] = { +#if NSC > 0 + { sccnprobe, sccninit, sccngetc, sccncheckc, sccnputc }, +#endif +#if NVT > 0 + { pccnprobe, pccninit, pccngetc, pccncheckc, pccnputc }, +#endif +#if NSIO > 0 + { siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc }, +#endif + { 0 }, +}; + +static d_open_t cnopen; +static d_close_t cnclose; +static d_read_t cnread; +static d_write_t cnwrite; +static d_ioctl_t cnioctl; +static d_poll_t cnpoll; + +#define CDEV_MAJOR 0 +static struct cdevsw cn_cdevsw = + { cnopen, cnclose, cnread, cnwrite, /*0*/ + cnioctl, nullstop, nullreset, nodevtotty,/* console */ + cnpoll, nommap, NULL, "console", NULL, -1 }; + +static dev_t cn_dev_t; /* seems to be never really used */ +SYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLTYPE_OPAQUE|CTLFLAG_RD, + &cn_dev_t, sizeof cn_dev_t, "T,dev_t", ""); + +static int cn_mute; + +int cons_unavail = 0; /* XXX: + * physical console not available for + * input (i.e., it is in graphics mode) + */ + +static u_char cn_is_open; /* nonzero if logical console is open */ +static int openmode, openflag; /* how /dev/console was openned */ +static u_char cn_phys_is_open; /* nonzero if physical device is open */ +static d_close_t *cn_phys_close; /* physical device close function */ +static d_open_t *cn_phys_open; /* physical device open function */ +struct consdev *cn_tab; /* physical console device info */ +static struct tty *cn_tp; /* physical console tty struct */ +#ifdef DEVFS +static void *cn_devfs_token; /* represents the devfs entry */ +#endif /* DEVFS */ + +void +cninit() +{ + struct consdev *best_cp, *cp; + + /* + * Find the first console with the highest priority. + */ + best_cp = NULL; + for (cp = constab; cp->cn_probe; cp++) { + (*cp->cn_probe)(cp); + if (cp->cn_pri > CN_DEAD && + (best_cp == NULL || cp->cn_pri > best_cp->cn_pri)) + best_cp = cp; + } + + /* + * Check if we should mute the console (for security reasons perhaps) + * It can be changes dynamically using sysctl kern.consmute + * once we are up and going. + * + */ + cn_mute = ((boothowto & (RB_MUTE + |RB_SINGLE + |RB_VERBOSE + |RB_ASKNAME + |RB_CONFIG)) == RB_MUTE); + + /* + * If no console, give up. + */ + if (best_cp == NULL) { + cn_tab = best_cp; + return; + } + + /* + * Initialize console, then attach to it. This ordering allows + * debugging using the previous console, if any. + * XXX if there was a previous console, then its driver should + * be informed when we forget about it. + */ + (*best_cp->cn_init)(best_cp); + cn_tab = best_cp; +} + +void +cninit_finish() +{ + struct cdevsw *cdp; + + if ((cn_tab == NULL) || cn_mute) + return; + + /* + * Hook the open and close functions. + */ + cdp = cdevsw[major(cn_tab->cn_dev)]; + cn_phys_close = cdp->d_close; + cdp->d_close = cnclose; + cn_phys_open = cdp->d_open; + cdp->d_open = cnopen; + cn_tp = (*cdp->d_devtotty)(cn_tab->cn_dev); + cn_dev_t = cn_tp->t_dev; +} + +static void +cnuninit(void) +{ + struct cdevsw *cdp; + + if (cn_tab == NULL) + return; + + /* + * Unhook the open and close functions. + */ + cdp = cdevsw[major(cn_tab->cn_dev)]; + cdp->d_close = cn_phys_close; + cn_phys_close = NULL; + cdp->d_open = cn_phys_open; + cn_phys_open = NULL; + cn_tp = NULL; + cn_dev_t = 0; +} + +/* + * User has changed the state of the console muting. + * This may require us to open or close the device in question. + */ +static int +sysctl_kern_consmute SYSCTL_HANDLER_ARGS +{ + int error; + int ocn_mute; + + ocn_mute = cn_mute; + error = sysctl_handle_int(oidp, &cn_mute, 0, req); + if((error == 0) && (cn_tab != NULL) && (req->newptr != NULL)) { + if(ocn_mute && !cn_mute) { + /* + * going from muted to unmuted.. open the physical dev + * if the console has been openned + */ + cninit_finish(); + if(cn_is_open) + /* XXX curproc is not what we want really */ + error = cnopen(cn_dev_t, openflag, + openmode, curproc); + /* if it failed, back it out */ + if ( error != 0) cnuninit(); + } else if (!ocn_mute && cn_mute) { + /* + * going from unmuted to muted.. close the physical dev + * if it's only open via /dev/console + */ + if(cn_is_open) + error = cnclose(cn_dev_t, openflag, + openmode, curproc); + if ( error == 0) cnuninit(); + } + if (error != 0) { + /* + * back out the change if there was an error + */ + cn_mute = ocn_mute; + } + } + return (error); +} + +SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW, + 0, sizeof cn_mute, sysctl_kern_consmute, "I", ""); + +static int +cnopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + dev_t cndev, physdev; + int retval = 0; + + if (cn_tab == NULL) + return (0); + cndev = cn_tab->cn_dev; + physdev = (major(dev) == major(cndev) ? dev : cndev); + /* + * If mute is active, then non console opens don't get here + * so we don't need to check for that. They + * bypass this and go straight to the device. + */ + if(!cn_mute) + retval = (*cn_phys_open)(physdev, flag, mode, p); + if (retval == 0) { + /* + * check if we openned it via /dev/console or + * via the physical entry (e.g. /dev/sio0). + */ + if (dev == cndev) + cn_phys_is_open = 1; + else if (physdev == cndev) { + openmode = mode; + openflag = flag; + cn_is_open = 1; + } + } + return (retval); +} + +static int +cnclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + dev_t cndev; + + if (cn_tab == NULL) + return (0); + cndev = cn_tab->cn_dev; + /* + * act appropriatly depending on whether it's /dev/console + * or the pysical device (e.g. /dev/sio) that's being closed. + * in either case, don't actually close the device unless + * both are closed. + */ + if (dev == cndev) { + /* the physical device is about to be closed */ + cn_phys_is_open = 0; + if (cn_is_open) { + if (cn_tp) { + /* perform a ttyhalfclose() */ + /* reset session and proc group */ + cn_tp->t_pgrp = NULL; + cn_tp->t_session = NULL; + } + return (0); + } + } else if (major(dev) != major(cndev)) { + /* the logical console is about to be closed */ + cn_is_open = 0; + if (cn_phys_is_open) + return (0); + dev = cndev; + } + if(cn_phys_close) + return ((*cn_phys_close)(dev, flag, mode, p)); + return (0); +} + +static int +cnread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + if ((cn_tab == NULL) || cn_mute) + return (0); + dev = cn_tab->cn_dev; + return ((*cdevsw[major(dev)]->d_read)(dev, uio, flag)); +} + +static int +cnwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + if ((cn_tab == NULL) || cn_mute) { + uio->uio_resid = 0; /* dump the data */ + return (0); + } + if (constty) + dev = constty->t_dev; + else + dev = cn_tab->cn_dev; + return ((*cdevsw[major(dev)]->d_write)(dev, uio, flag)); +} + +static int +cnioctl(dev, cmd, data, flag, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + int error; + + if ((cn_tab == NULL) || cn_mute) + return (0); + /* + * Superuser can always use this to wrest control of console + * output from the "virtual" console. + */ + if (cmd == TIOCCONS && constty) { + error = suser(p->p_ucred, (u_short *) NULL); + if (error) + return (error); + constty = NULL; + return (0); + } + dev = cn_tab->cn_dev; + return ((*cdevsw[major(dev)]->d_ioctl)(dev, cmd, data, flag, p)); +} + +static int +cnpoll(dev, events, p) + dev_t dev; + int events; + struct proc *p; +{ + if ((cn_tab == NULL) || cn_mute) + return (1); + + dev = cn_tab->cn_dev; + + return ((*cdevsw[major(dev)]->d_poll)(dev, events, p)); +} + +int +cngetc() +{ + int c; + if ((cn_tab == NULL) || cn_mute) + return (-1); + c = (*cn_tab->cn_getc)(cn_tab->cn_dev); + if (c == '\r') c = '\n'; /* console input is always ICRNL */ + return (c); +} + +int +cncheckc() +{ + if ((cn_tab == NULL) || cn_mute) + return (-1); + return ((*cn_tab->cn_checkc)(cn_tab->cn_dev)); +} + +void +cnputc(c) + register int c; +{ + if ((cn_tab == NULL) || cn_mute) + return; + if (c) { + if (c == '\n') + (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r'); + (*cn_tab->cn_putc)(cn_tab->cn_dev, c); + } +} + +static cn_devsw_installed = 0; + +static void +cn_drvinit(void *unused) +{ + dev_t dev; + + if( ! cn_devsw_installed ) { + dev = makedev(CDEV_MAJOR,0); + cdevsw_add(&dev,&cn_cdevsw,NULL); + cn_devsw_installed = 1; +#ifdef DEVFS + cn_devfs_token = devfs_add_devswf(&cn_cdevsw, 0, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, + "console"); +#endif + } +} + +SYSINIT(cndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cn_drvinit,NULL) + + diff --git a/sys/alpha/alpha/cpuconf.c b/sys/alpha/alpha/cpuconf.c new file mode 100644 index 0000000..9e395ae --- /dev/null +++ b/sys/alpha/alpha/cpuconf.c @@ -0,0 +1,161 @@ +/* $Id$ */ +/* $NetBSD: cpuconf.c,v 1.10 1998/03/20 21:48:21 thorpej Exp $ */ + +/* + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * 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 Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * 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. + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <machine/cpuconf.h> +#include <machine/rpb.h> + +#include "opt_cpu.h" + +#ifdef DEC_3000_500 +extern void dec_3000_500_init __P((int)); +#else +#define dec_3000_500_init platform_not_configured +#endif + +#ifdef DEC_3000_300 +extern void dec_3000_300_init __P((int)); +#else +#define dec_3000_300_init platform_not_configured +#endif + +#ifdef DEC_AXPPCI_33 +extern void dec_axppci_33_init __P((int)); +#else +#define dec_axppci_33_init platform_not_configured +#endif + +#ifdef DEC_KN8AE +extern void dec_kn8ae_init __P((int)); +#else +#define dec_kn8ae_init platform_not_configured +#endif + +#ifdef DEC_2100_A50 +extern void dec_2100_a50_init __P((int)); +#else +#define dec_2100_a50_init platform_not_configured +#endif + +#ifdef DEC_KN20AA +extern void dec_kn20aa_init __P((int)); +#else +#define dec_kn20aa_init platform_not_configured +#endif + +#ifdef DEC_EB64PLUS +extern void dec_eb64plus_init __P((int)); +#else +#define dec_eb64plus_init platform_not_configured +#endif + +#ifdef DEC_EB164 +extern void dec_eb164_init __P((int)); +#else +#define dec_eb164_init platform_not_configured +#endif + +#ifdef AVALON_A12 +extern void avalon_a12_init __P((int)); +#else +#define avalon_a12_init platform_not_configured +#endif + +struct cpuinit cpuinit[] = { + cpu_notsupp("???"), /* 0: ??? */ + cpu_notsupp("ST_ADU"), /* 1: ST_ADU */ + cpu_notsupp("ST_DEC_4000"), /* 2: ST_DEC_4000 */ + cpu_notsupp("ST_DEC_7000"), /* 3: ST_DEC_7000 */ + cpu_init(dec_3000_500_init,"DEC_3000_500"), /* 4: ST_DEC_3000_500 */ + cpu_notsupp("???"), /* 5: ??? */ + cpu_notsupp("ST_DEC_2000_300"), /* 6: ST_DEC_2000_300 */ + cpu_init(dec_3000_300_init,"DEC_3000_300"), /* 7: ST_DEC_3000_300 */ + cpu_init(avalon_a12_init,"ST_AVALON_A12"), /* 8: ST_AVALON_A12 */ + cpu_notsupp("ST_DEC_2100_A500"), /* 9: ST_DEC_2100_A500 */ + cpu_notsupp("ST_DEC_APXVME_64"), /* 10: ST_DEC_APXVME_64 */ + cpu_init(dec_axppci_33_init,"DEC_AXPPCI_33"),/* 11: ST_DEC_AXPPCI_33 */ + cpu_init(dec_kn8ae_init,"DEC_KN8AE"), /* 12: ST_DEC_21000 */ + cpu_init(dec_2100_a50_init,"DEC_2100_A50"), /* 13: ST_DEC_2100_A50 */ + cpu_notsupp("ST_DEC_MUSTANG"), /* 14: ST_DEC_MUSTANG */ + cpu_init(dec_kn20aa_init,"DEC_KN20AA"), /* 15: ST_DEC_KN20AA */ + cpu_notsupp("???"), /* 16: ??? */ + cpu_notsupp("ST_DEC_1000"), /* 17: ST_DEC_1000 */ + cpu_notsupp("???"), /* 18: ??? */ + cpu_notsupp("ST_EB66"), /* 19: ST_EB66 */ + cpu_init(dec_eb64plus_init,"DEC_EB64PLUS"), /* 20: ST_EB64P */ + cpu_notsupp("ST_ALPHABOOK1"), /* 21: ST_ALPHABOOK1 */ + cpu_notsupp("ST_DEC_4100"), /* 22: ST_DEC_4100 */ + cpu_notsupp("ST_DEC_EV45_PBP"), /* 23: ST_DEC_EV45_PBP */ + cpu_notsupp("ST_DEC_2100A_A500"), /* 24: ST_DEC_2100A_A500 */ + cpu_notsupp("???"), /* 25: ??? */ + cpu_init(dec_eb164_init,"DEC_EB164"), /* 26: ST_EB164 */ + cpu_notsupp("ST_DEC_1000A"), /* 27: ST_DEC_1000A */ + cpu_notsupp("ST_DEC_ALPHAVME_224"), /* 28: ST_DEC_ALPHAVME_224 */ + cpu_notsupp("???"), /* 29: ??? */ + cpu_notsupp("???"), /* 30: ??? */ + cpu_notsupp("???"), /* 31: ??? */ + cpu_notsupp("ST_DEC_EV56_PBP"), /* 32: ST_DEC_EV56_PBP */ + cpu_notsupp("ST_DEC_ALPHAVME_320"), /* 33: ST_DEC_ALPHAVME_320 */ +}; +int ncpuinit = (sizeof(cpuinit) / sizeof(cpuinit[0])); + +void +platform_not_configured(int cputype) +{ + printf("\n"); + printf("Support for system type %d is not present in this kernel.\n", + cputype); + printf("Please build a kernel with \"options %s\" and reboot.\n", + cpuinit[cputype].option); + printf("\n"); + panic("platform not configured\n"); +} + +void +platform_not_supported(int cputype) +{ + const char *typestr; + + if (cputype >= ncpuinit) + typestr = "???"; + else + typestr = cpuinit[cputype].option; + + printf("\n"); + printf("NetBSD does not yet support system type %d (%s).\n", cputype, + typestr); + printf("\n"); + panic("platform not supported"); +} diff --git a/sys/alpha/alpha/db_disasm.c b/sys/alpha/alpha/db_disasm.c new file mode 100644 index 0000000..94df6fa --- /dev/null +++ b/sys/alpha/alpha/db_disasm.c @@ -0,0 +1,1095 @@ +/* $NetBSD: db_disasm.c,v 1.4 1997/09/16 22:52:40 thorpej Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + * File: db_disasm.c + * Author: Alessandro Forin, Carnegie Mellon University + * Date: 11/91 + * + * Disassembler for Alpha + * + * Modified for NetBSD/alpha by: + * + * Christopher G. Demetriou, Carnegie Mellon University + * + * Jason R. Thorpe, Numerical Aerospace Simulation Facility, + * NASA Ames Research Center + * + * This code was derived exclusively from information available in + * "Alpha Architecture Reference Manual", Richard L. Sites ed. + * Digital Press, Burlington, MA 01803 + * ISBN 1-55558-098-X, Order no. EY-L520E-DP + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +/* __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.4 1997/09/16 22:52:40 thorpej Exp $"); */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <machine/db_machdep.h> +#include <alpha/alpha/db_instruction.h> + +#include <machine/pal.h> + +#include <ddb/ddb.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_output.h> + +/* + * This would belong in a header file, except noone else needs it + */ +typedef union { + /* + * All instructions are 32 bits wide, PAL included + */ + unsigned int bits; + + /* + * Internal processor register access instrs + * specify the IPR index, doubly specify the + * (same) GP register as src/dest, and qualifiers + * for the IPR set involved (abox/ibox/tmp) + */ + struct { + unsigned index : 5, + regset : 3, /* a,i,p */ + xxx : 8, + rs : 5, + rd : 5, + opcode : 6; + } mXpr_format; + + /* + * Load/store instructions have a 12 bit displacement, + * and two register specifiers just as normal ld/st. + * Four bits have special meanings: + * phy: bypass the MMU (physical access) + * alt: use mode in ALT register for checks, + * or if PHY is also on locked/linked access + * rwc: read-with-write-check (probew) + * qw: quadword access + */ + struct { + signed int displacement : 12; + unsigned qw : 1, + qualif : 3, + rs : 5, + rd : 5, + opcode : 6; + } mem_format; + + /* + * Return from exception or interrupt has + * a branch-like encoding, but only one + * instantiation is actually usable. + */ + struct { + unsigned xxx : 14, + zero : 1, /* branch prediction! */ + one : 1, + rb : 5, /* r31 or stall */ + ra : 5, /* r31 or stall */ + opcode : 6; + } rei_format; + +} pal_instruction; + + +/* + * Major opcodes + */ +static char *op_name[64] = { +/* 0 */ "call_pal", "op1", "op2", "op3", "op4", "op5", "op6", "op7", +/* 8 */ "lda", "ldah", "ldbu", "ldq_u","ldwu", "stw", "stb", "stq_u", +/*16 */ "arit", "logical","bit","mul", "op20", "vaxf", "ieeef","anyf", +/*24 */ "spec", "hw_mfpr","jump","hw_ld","intmisc","hw_mtpr","hw_rei","hw_st", +/*32 */ "ldf", "ldg", "lds", "ldt", "stf", "stg", "sts", "stt", +/*40 */ "ldl", "ldq", "ldl_l","ldq_l","stl", "stq", "stl_c","stq_c", +/*48 */ "br", "fbeq", "fblt", "fble", "bsr", "fbne", "fbge", "fbgt", +/*56 */ "blbc", "beq", "blt", "ble", "blbs", "bne", "bge", "bgt" +}; + +/* + * The function field is too big (7 or 11 bits), so the sub-tables + * are addressed in a somewhat complicated manner to save + * space. After all, alu operations is what RISCs are good at. + */ + +struct tbl { + const char *name; + int code; +}; + +static const struct tbl pal_op_tbl[] = { + /* Common PAL function codes. */ + { "halt", PAL_halt }, + { "cflush", PAL_cflush }, + { "draina", PAL_draina }, + { "cserve", PAL_cserve, }, + { "swppal", PAL_swppal }, + { "ipir", PAL_ipir }, + { "bpt", PAL_bpt }, + { "bugchk", PAL_bugchk }, + { "imb", PAL_imb }, + { "rdunique", PAL_rdunique }, + { "wrunique", PAL_wrunique }, + { "gentrap", PAL_gentrap }, + + /* OSF/1 PAL function codes. */ + { "osf1_rdmces", PAL_OSF1_rdmces }, + { "osf1_wrmces", PAL_OSF1_wrmces }, + { "osf1_wrfen", PAL_OSF1_wrfen }, + { "osf1_wrvptptr", PAL_OSF1_wrvptptr }, + { "osf1_swpctx", PAL_OSF1_swpctx }, + { "osf1_wrval", PAL_OSF1_wrval }, + { "osf1_rdval", PAL_OSF1_rdval }, + { "osf1_tbi", PAL_OSF1_tbi }, + { "osf1_wrent", PAL_OSF1_wrent }, + { "osf1_swpipl", PAL_OSF1_swpipl }, + { "osf1_rdps", PAL_OSF1_rdps }, + { "osf1_wrkgp", PAL_OSF1_wrkgp }, + { "osf1_wrusp", PAL_OSF1_wrusp }, + { "osf1_wrperfmon", PAL_OSF1_wrperfmon }, + { "osf1_rdusp", PAL_OSF1_rdusp }, + { "osf1_whami", PAL_OSF1_whami }, + { "osf1_retsys", PAL_OSF1_retsys }, + { "osf1_rti", PAL_OSF1_rti }, + { "osf1_callsys", PAL_OSF1_callsys }, + + { NULL, -1 }, +}; + +static const char *pal_opname __P((int)); + +static const char * +pal_opname(op) + int op; +{ + static char unk[8]; + int i; + + for (i = 0; pal_op_tbl[i].name != NULL; i++) { + if (pal_op_tbl[i].code == op) + return (pal_op_tbl[i].name); + } + + sprintf(unk, "0x%x", op); + return (unk); +} + +/* HW (PAL) instruction qualifiers, stright tables */ +static const char *mXpr_name[8] = { + "", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai" +}; +static const char *hwlds_name[8] = { + "", "/r", "/a", "/ar", "/p", "/p?r", "_l-c", "_l-c/?r" +}; + +/* + * For this one we take the low nibble (valid values 0/2/9/b/d) + * and shift it down one to get the row index. Within a row + * we can just take the high nibble deprived of the high bit + * (valid values 0/1/2/3/4/6). We could have used a flat 64 + * entry array, but in this way we use just 48 pointers. + * BUGFIX: the 'cmpbge 0x0f' opcode fits in here too + */ +static const char *arit_c0[8] = { + "addl", 0, "addq", 0, "addl/v", 0, "addq/v", +}; +static const char *arit_c2[8] = { + "s4addl", "s8addl", "s4addq", "s8addq", +}; +static const char *arit_c9[8] = { + "subl", 0, "subq", 0, "subl/v", 0, "subq/v", +}; +static const char *arit_cB[8] = { + "s4subl", "s8subl", "s4subq", "s8subq", +}; +static const char *arit_cD[8] = { + 0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple", +}; +static const char *arit_cF[1] = { + "cmpbge" +}; +static const char **arit_opname[8] = { + arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF +}; + +static __inline const char *arit_name __P((int)); +static __inline const char * +arit_name(op) + int op; +{ + static char unk[32]; + const char *name = NULL; + + if (arit_opname[((op)&0xe)>>1]) + name = arit_opname[((op)&0xe)>>1][((op)&0x70)>>4]; + + if (name != NULL) + return (name); + + sprintf(unk, "?arit 0x%x?", op); + return (unk); +} + +/* + * Something similar for this one, except there are only + * 16 entries so the row indexing is done by enumeration + * of the low nibble (valid values 0/4/6/8). Then we can + * just shift the high nibble to index inside the row + * (valid values are 0/2/4 or 1/2/4/6) + * + * There are two functions that don't play by these simple rules, + * so we special-case them. + */ +static const char *logical_c0[4] = { + "and", "or", "xor", 0 +}; +static const char *logical_c4[4] = { + "cmovlbs", "cmoveq", "cmovlt", "cmovle" +}; +static const char *logical_c6[4] = { + "cmovlbc", "cmovne", "cmovge", "cmovgt" +}; +static const char *logical_c8[4] = { + "andnot", "ornot", "xornot", 0 +}; + +static __inline const char *logical_name __P((int)); +static __inline const char * +logical_name(op) + int op; +{ + static char unk[32]; + const char *name = NULL; + + if (op == op_amask) + return ("amask"); + else if (op == op_implver) + return ("implver"); + + switch (op & 0xf) { + case 0: name = logical_c0[((op)>>5)&3]; break; + case 4: name = logical_c4[((op)>>5)&3]; break; + case 6: name = logical_c6[((op)>>5)&3]; break; + case 8: name = logical_c8[((op)>>5)&3]; break; + } + + if (name != NULL) + return (name); + + sprintf(unk, "?logical 0x%x?", op); + return (unk); +} + +/* + * This is the messy one. First, we single out the dense + * case of a 3 in the high nibble (valid values 0/1/2/4/6/9/b/c). + * Then the case of a 2 in the low nibble (valid values 0/1/2/5/6/7). + * For the remaining codes (6/7/a/b) we do as above: high + * nibble has valid values 0/1/2 or 5/6/7. The low nibble + * can be used as row index picking bits 0 and 2, for the + * high one just the lower two bits. + */ +static const char *bitop_c3[8] = { + "zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0 +}; +static const char *bitop_c2[8] = { + "mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh" +}; +static const char *bitop_c67ab[4][4] = { +/* a */ { 0, "extwh", "extlh", "extqh"}, +/* b */ { "insbl", "inswl", "insll", 0 }, +/* 6 */ { "extbl", "extwl", "extll", 0 }, +/* 7 */ { 0, "inswh", "inslh", "insqh" }, +}; + +static __inline const char *bitop_name __P((int)); +static __inline const char * +bitop_name(op) + int op; +{ + static char unk[32]; + const char *name = NULL; + + if ((op & 0x70) == 0x30) + name = (op == op_zap) ? "zap" : bitop_c3[((op)&0xe)>>1]; + else if ((op & 0xf) == 0x02) + name = bitop_c2[(op)>>4]; + else + name = + bitop_c67ab[(((op)&1)|(((op)&0x4)>>1))][(((op)&0x30)>>4)]; + + if (name != NULL) + return (name); + + sprintf(unk, "?bit 0x%x?", op); + return (unk); +} + +/* + * Only 5 entries in this one + */ +static const char *mul_opname[4] = { + "mull", "mulq", "mull/v", "mulq/v" +}; + +static __inline const char *mul_name __P((int)); +static __inline const char * +mul_name(op) + int op; +{ + static char unk[32]; + const char *name = NULL; + + name = (op == op_umulh) ? "umulh" : mul_opname[((op)>>5)&3]; + + if (name != NULL) + return (name); + + sprintf(unk, "?mul 0x%x?", op); + return (unk); +} + +/* + * These are few, the high nibble is enough to dispatch. + * We single out the "f" case to halve the table size. + */ +static const char *special_opname[8] = { + "drain_t", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc" +}; + +static __inline const char *special_name __P((int)); +static __inline const char * +special_name(op) + int op; +{ + static char unk[32]; + const char *name; + + name = (op == op_rs) ? "rs" : special_opname[(op)>>13]; + + if (name != NULL) + return (name); + + sprintf(unk, "?special 0x%x?", op); + return (unk); +} + +/* + * This is trivial + */ +static const char *jump_opname[4] = { + "jmp", "jsr", "ret", "jcr" +}; +#define jump_name(ix) jump_opname[ix] + +/* + * For all but 4 of these, we can dispatch on the lower nibble of + * the "function". + */ +static const char *intmisc_opname_3x[16] = { + "ctpop", "perr", "ctlz", "cttz", "unpkbw", "unpkbl", "pkwb", + "pklb", "minsb8", "minsw4", "minub8", "minuw4", "maxub8", + "maxuw4", "maxsb8", "maxsw4", +}; + +static __inline const char *intmisc_name __P((int)); +static __inline const char * +intmisc_name(op) + int op; +{ + static char unk[32]; + + if ((op & 0xf0) == 0x30) + return (intmisc_opname_3x[op & 0x0f]); + + switch (op) { + case op_sextb: return ("sextb"); + case op_sextw: return ("sextw"); + case op_ftoit: return ("ftoit"); + case op_ftois: return ("ftois"); + } + + sprintf(unk, "?intmisc 0x%x?", op); + return (unk); +} + +static const char *float_name __P((const struct tbl[], int, const char *type)); + +static const char * +float_name(tbl, op, type) + const struct tbl tbl[]; + int op; + const char *type; +{ + static char unk[32]; + int i; + + for (i = 0; tbl[i].name != NULL; i++) { + if (tbl[i].code == op) + return (tbl[i].name); + } + + sprintf(unk, "?%s 0x%x?", type, op); + return (unk); +} + +#define vaxf_name(op) float_name(vaxf_tbl, op, "vaxfl") +#define ieeef_name(op) float_name(ieeef_tbl, op, "ieeefl") +#define anyf_name(op) float_name(anyf_tbl, op, "anyfl") + +static const struct tbl anyf_tbl[] = { + { "cvtlq", 0x010}, + { "cpys", 0x020}, + { "cpysn", 0x021}, + { "cpyse", 0x022}, + { "mt_fpcr", 0x024}, + { "mf_fpcr", 0x025}, + { "fcmoveq", 0x02a}, + { "fcmovne", 0x02b}, + { "fcmovlt", 0x02c}, + { "fcmovge", 0x02d}, + { "fcmovle", 0x02e}, + { "fcmovgt", 0x02f}, + { "cvtql", 0x030}, + { "cvtql/v", 0x130}, + { "cvtql/sv", 0x330}, + { 0, 0}, +}; + +static const struct tbl ieeef_tbl[] = { + { "adds/c", 0x000}, + { "subs/c", 0x001}, + { "muls/c", 0x002}, + { "divs/c", 0x003}, + { "addt/c", 0x020}, + { "subt/c", 0x021}, + { "mult/c", 0x022}, + { "divt/c", 0x023}, + { "cvtts/c", 0x02c}, + { "cvttq/c", 0x02f}, + { "cvtqs/c", 0x03c}, + { "cvtqt/c", 0x03e}, + { "adds/m", 0x040}, + { "subs/m", 0x041}, + { "muls/m", 0x042}, + { "divs/m", 0x043}, + { "addt/m", 0x060}, + { "subt/m", 0x061}, + { "mult/m", 0x062}, + { "divt/m", 0x063}, + { "cvtts/m", 0x06c}, + { "cvtqs/m", 0x07c}, + { "cvtqt/m", 0x07e}, + { "adds", 0x080}, + { "subs", 0x081}, + { "muls", 0x082}, + { "divs", 0x083}, + { "addt", 0x0a0}, + { "subt", 0x0a1}, + { "mult", 0x0a2}, + { "divt", 0x0a3}, + { "cmptun", 0x0a4}, + { "cmpteq", 0x0a5}, + { "cmptlt", 0x0a6}, + { "cmptle", 0x0a7}, + { "cvtts", 0x0ac}, + { "cvttq", 0x0af}, + { "cvtqs", 0x0bc}, + { "cvtqt", 0x0be}, + { "adds/d", 0x0c0}, + { "subs/d", 0x0c1}, + { "muls/d", 0x0c2}, + { "divs/d", 0x0c3}, + { "addt/d", 0x0e0}, + { "subt/d", 0x0e1}, + { "mult/d", 0x0e2}, + { "divt/d", 0x0e3}, + { "cvtts/d", 0x0ec}, + { "cvtqs/d", 0x0fc}, + { "cvtqt/d", 0x0fe}, + { "adds/uc", 0x100}, + { "subs/uc", 0x101}, + { "muls/uc", 0x102}, + { "divs/uc", 0x103}, + { "addt/uc", 0x120}, + { "subt/uc", 0x121}, + { "mult/uc", 0x122}, + { "divt/uc", 0x123}, + { "cvtts/uc", 0x12c}, + { "cvttq/vc", 0x12f}, + { "adds/um", 0x140}, + { "subs/um", 0x141}, + { "muls/um", 0x142}, + { "divs/um", 0x143}, + { "addt/um", 0x160}, + { "subt/um", 0x161}, + { "mult/um", 0x162}, + { "divt/um", 0x163}, + { "cvtts/um", 0x16c}, + { "adds/u", 0x180}, + { "subs/u", 0x181}, + { "muls/u", 0x182}, + { "divs/u", 0x183}, + { "addt/u", 0x1a0}, + { "subt/u", 0x1a1}, + { "mult/u", 0x1a2}, + { "divt/u", 0x1a3}, + { "cvtts/u", 0x1ac}, + { "cvttq/v", 0x1af}, + { "adds/ud", 0x1c0}, + { "subs/ud", 0x1c1}, + { "muls/ud", 0x1c2}, + { "divs/ud", 0x1c3}, + { "addt/ud", 0x1e0}, + { "subt/ud", 0x1e1}, + { "mult/ud", 0x1e2}, + { "divt/ud", 0x1e3}, + { "cvtts/ud", 0x1ec}, + { "adds/suc", 0x500}, + { "subs/suc", 0x501}, + { "muls/suc", 0x502}, + { "divs/suc", 0x503}, + { "addt/suc", 0x520}, + { "subt/suc", 0x521}, + { "mult/suc", 0x522}, + { "divt/suc", 0x523}, + { "cvtts/suc", 0x52c}, + { "cvttq/svc", 0x52f}, + { "adds/sum", 0x540}, + { "subs/sum", 0x541}, + { "muls/sum", 0x542}, + { "divs/sum", 0x543}, + { "addt/sum", 0x560}, + { "subt/sum", 0x561}, + { "mult/sum", 0x562}, + { "divt/sum", 0x563}, + { "cvtts/sum", 0x56c}, + { "adds/su", 0x580}, + { "subs/su", 0x581}, + { "muls/su", 0x582}, + { "divs/su", 0x583}, + { "addt/su", 0x5a0}, + { "subt/su", 0x5a1}, + { "mult/su", 0x5a2}, + { "divt/su", 0x5a3}, + { "cmptun/su", 0x5a4}, + { "cmpteq/su", 0x5a5}, + { "cmptlt/su", 0x5a6}, + { "cmptle/su", 0x5a7}, + { "cvtts/su", 0x5ac}, + { "cvttq/sv", 0x5af}, + { "adds/sud", 0x5c0}, + { "subs/sud", 0x5c1}, + { "muls/sud", 0x5c2}, + { "divs/sud", 0x5c3}, + { "addt/sud", 0x5e0}, + { "subt/sud", 0x5e1}, + { "mult/sud", 0x5e2}, + { "divt/sud", 0x5e3}, + { "cvtts/sud", 0x5ec}, + { "adds/suic", 0x700}, + { "subs/suic", 0x701}, + { "muls/suic", 0x702}, + { "divs/suic", 0x703}, + { "addt/suic", 0x720}, + { "subt/suic", 0x721}, + { "mult/suic", 0x722}, + { "divt/suic", 0x723}, + { "cvtts/suic", 0x72c}, + { "cvttq/svic", 0x72f}, + { "cvtqs/suic", 0x73c}, + { "cvtqt/suic", 0x73e}, + { "adds/suim", 0x740}, + { "subs/suim", 0x741}, + { "muls/suim", 0x742}, + { "divs/suim", 0x743}, + { "addt/suim", 0x760}, + { "subt/suim", 0x761}, + { "mult/suim", 0x762}, + { "divt/suim", 0x763}, + { "cvtts/suim", 0x76c}, + { "cvtqs/suim", 0x77c}, + { "cvtqt/suim", 0x77e}, + { "adds/sui", 0x780}, + { "subs/sui", 0x781}, + { "muls/sui", 0x782}, + { "divs/sui", 0x783}, + { "addt/sui", 0x7a0}, + { "subt/sui", 0x7a1}, + { "mult/sui", 0x7a2}, + { "divt/sui", 0x7a3}, + { "cvtts/sui", 0x7ac}, + { "cvttq/svi", 0x7af}, + { "cvtqs/sui", 0x7bc}, + { "cvtqt/sui", 0x7be}, + { "adds/suid", 0x7c0}, + { "subs/suid", 0x7c1}, + { "muls/suid", 0x7c2}, + { "divs/suid", 0x7c3}, + { "addt/suid", 0x7e0}, + { "subt/suid", 0x7e1}, + { "mult/suid", 0x7e2}, + { "divt/suid", 0x7e3}, + { "cvtts/suid", 0x7ec}, + { "cvtqs/suid", 0x7fc}, + { "cvtqt/suid", 0x7fe}, + { 0, 0} +}; + +static const struct tbl vaxf_tbl[] = { + { "addf/c", 0x000}, + { "subf/c", 0x001}, + { "mulf/c", 0x002}, + { "divf/c", 0x003}, + { "cvtdg/c", 0x01e}, + { "addg/c", 0x020}, + { "subg/c", 0x021}, + { "mulg/c", 0x022}, + { "divg/c", 0x023}, + { "cvtgf/c", 0x02c}, + { "cvtgd/c", 0x02d}, + { "cvtgq/c", 0x02f}, + { "cvtqf/c", 0x03c}, + { "cvtqg/c", 0x03e}, + { "addf", 0x080}, + { "subf", 0x081}, + { "mulf", 0x082}, + { "divf", 0x083}, + { "cvtdg", 0x09e}, + { "addg", 0x0a0}, + { "subg", 0x0a1}, + { "mulg", 0x0a2}, + { "divg", 0x0a3}, + { "cmpgeq", 0x0a5}, + { "cmpglt", 0x0a6}, + { "cmpgle", 0x0a7}, + { "cvtgf", 0x0ac}, + { "cvtgd", 0x0ad}, + { "cvtgq", 0x0af}, + { "cvtqf", 0x0bc}, + { "cvtqg", 0x0be}, + { "addf/uc", 0x100}, + { "subf/uc", 0x101}, + { "mulf/uc", 0x102}, + { "divf/uc", 0x103}, + { "cvtdg/uc", 0x11e}, + { "addg/uc", 0x120}, + { "subg/uc", 0x121}, + { "mulg/uc", 0x122}, + { "divg/uc", 0x123}, + { "cvtgf/uc", 0x12c}, + { "cvtgd/uc", 0x12d}, + { "cvtgq/vc", 0x12f}, + { "addf/u", 0x180}, + { "subf/u", 0x181}, + { "mulf/u", 0x182}, + { "divf/u", 0x183}, + { "cvtdg/u", 0x19e}, + { "addg/u", 0x1a0}, + { "subg/u", 0x1a1}, + { "mulg/u", 0x1a2}, + { "divg/u", 0x1a3}, + { "cvtgf/u", 0x1ac}, + { "cvtgd/u", 0x1ad}, + { "cvtgq/v", 0x1af}, + { "addf/sc", 0x400}, + { "subf/sc", 0x401}, + { "mulf/sc", 0x402}, + { "divf/sc", 0x403}, + { "cvtdg/sc", 0x41e}, + { "addg/sc", 0x420}, + { "subg/sc", 0x421}, + { "mulg/sc", 0x422}, + { "divg/sc", 0x423}, + { "cvtgf/sc", 0x42c}, + { "cvtgd/sc", 0x42d}, + { "cvtgq/sc", 0x42f}, + { "cvtqf/sc", 0x43c}, + { "cvtqg/sc", 0x43e}, + { "addf/s", 0x480}, + { "subf/s", 0x481}, + { "mulf/s", 0x482}, + { "divf/s", 0x483}, + { "cvtdg/s", 0x49e}, + { "addg/s", 0x4a0}, + { "subg/s", 0x4a1}, + { "mulg/s", 0x4a2}, + { "divg/s", 0x4a3}, + { "cmpgeq/s", 0x4a5}, + { "cmpglt/s", 0x4a6}, + { "cmpgle/s", 0x4a7}, + { "cvtgf/s", 0x4ac}, + { "cvtgd/s", 0x4ad}, + { "cvtgq/s", 0x4af}, + { "cvtqf/s", 0x4bc}, + { "cvtqg/s", 0x4be}, + { "addf/suc", 0x500}, + { "subf/suc", 0x501}, + { "mulf/suc", 0x502}, + { "divf/suc", 0x503}, + { "cvtdg/suc", 0x51e}, + { "addg/suc", 0x520}, + { "subg/suc", 0x521}, + { "mulg/suc", 0x522}, + { "divg/suc", 0x523}, + { "cvtgf/suc", 0x52c}, + { "cvtgd/suc", 0x52d}, + { "cvtgq/svc", 0x52f}, + { "addf/su", 0x580}, + { "subf/su", 0x581}, + { "mulf/su", 0x582}, + { "divf/su", 0x583}, + { "cvtdg/su", 0x59e}, + { "addg/su", 0x5a0}, + { "subg/su", 0x5a1}, + { "mulg/su", 0x5a2}, + { "divg/su", 0x5a3}, + { "cvtgf/su", 0x5ac}, + { "cvtgd/su", 0x5ad}, + { "cvtgq/sv", 0x5af}, + { 0, 0} +}; + +/* + * General purpose registers + */ +static const char *name_of_register[32] = { + "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", + "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", + "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", + "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero" +}; + +static int regcount; /* how many regs used in this inst */ +static int regnum[3]; /* which regs used in this inst */ + +static const char *register_name __P((int)); + +static const char * +register_name (ireg) + int ireg; +{ + int i; + + for (i = 0; i < regcount; i++) + if (regnum[i] == ireg) + break; + if (i >= regcount) + regnum[regcount++] = ireg; + return (name_of_register[ireg]); +} + +/* + * Disassemble instruction at 'loc'. 'altfmt' specifies an + * (optional) alternate format. Return address of start of + * next instruction. + */ +int alpha_print_instruction __P((db_addr_t, alpha_instruction, boolean_t)); + +db_addr_t +db_disasm(loc, altfmt) + db_addr_t loc; + boolean_t altfmt; +{ + alpha_instruction inst; + + inst.bits = db_get_value(loc, 4, 0); + + loc += alpha_print_instruction(loc, inst, altfmt); + return (loc); +} + +int +alpha_print_instruction(iadr, i, showregs) + db_addr_t iadr; + alpha_instruction i; + boolean_t showregs; +{ + const char *opcode; + int ireg; + long signed_immediate; + boolean_t fstore; + pal_instruction p; + + regcount = 0; + fstore = FALSE; + opcode = op_name[i.mem_format.opcode]; + + /* + * Dispatch directly on the opcode, save code + * duplication sometimes via "harmless gotos". + */ + switch (i.mem_format.opcode) { + case op_pal: + /* "call_pal" is a long string; just use a space. */ + db_printf("%s %s", opcode, pal_opname(i.pal_format.function)); + break; + case op_lda: + case op_ldah: + case op_ldbu: + case op_ldq_u: + case op_ldwu: + case op_stw: + case op_stb: + case op_stq_u: + /* + * These loadstores are here to make compiling the + * switch a bit easier. Could embellish the output + * someday, too. + */ + goto loadstore; + break; + case op_arit: + /* + * For this and the following three groups we + * just need different opcode strings + */ + opcode = arit_name(i.operate_lit_format.function); + goto operate; + break; + case op_logical: + opcode = logical_name(i.operate_lit_format.function); + goto operate; + break; + case op_bit: + opcode = bitop_name(i.operate_lit_format.function); + goto operate; + break; + case op_mul: + opcode = mul_name(i.operate_lit_format.function); +operate: + /* + * Nice and uniform, just check for literals + */ + db_printf("%s\t%s,", opcode, + register_name(i.operate_lit_format.rs)); + if (i.operate_lit_format.one) + db_printf("#0x%x", i.operate_lit_format.literal); + else + db_printf("%s", register_name(i.operate_reg_format.rt)); + db_printf(",%s", register_name(i.operate_lit_format.rd)); + break; + case op_vax_float: + /* + * The three floating point groups are even simpler + */ + opcode = vaxf_name(i.float_format.function); + goto foperate; + break; + case op_ieee_float: + opcode = ieeef_name(i.float_format.function); + goto foperate; + break; + case op_any_float: + opcode = anyf_name(i.float_format.function); +foperate: + db_printf("%s\tf%d,f%d,f%d", opcode, + i.float_format.fs, + i.float_format.ft, + i.float_format.fd); + break; + case op_special: + /* + * Miscellaneous. + */ + { + register unsigned int code; + + code = (i.mem_format.displacement)&0xffff; + opcode = special_name(code); + + switch (code) { + case op_fetch: + case op_fetch_m: + db_printf("%s\t0(%s)", opcode, + register_name(i.mem_format.rs)); + break; + case op_rpcc: + case op_rc: + case op_rs: + db_printf("%s\t%s", opcode, + register_name(i.mem_format.rd)); + break; + case op_draint: + case op_mb: + default: + db_printf("%s", opcode); + break; + } + } + break; + case op_j: + /* + * Jump instructions really are of two sorts, + * depending on the use of the hint info. + */ + opcode = jump_name(i.jump_format.action); + switch (i.jump_format.action) { + case op_jmp: + case op_jsr: + db_printf("%s\t%s,(%s),", opcode, + register_name(i.jump_format.rd), + register_name(i.jump_format.rs)); + signed_immediate = i.jump_format.hint; + goto branch_displacement; + break; + case op_ret: + case op_jcr: + db_printf("%s\t%s,(%s)", opcode, + register_name(i.jump_format.rd), + register_name(i.jump_format.rs)); + break; + } + break; + case op_intmisc: + /* + * These are just in "operate" format. + */ + opcode = intmisc_name(i.operate_lit_format.function); + goto operate; + break; + /* HW instructions, possibly chip-specific XXXX */ + case op_pal19: /* "hw_mfpr" */ + case op_pal1d: /* "hw_mtpr" */ + p.bits = i.bits; + db_printf("\t%s%s\t%s, %d", opcode, + mXpr_name[p.mXpr_format.regset], + register_name(p.mXpr_format.rd), + p.mXpr_format.index); + break; + case op_pal1b: /* "hw_ld" */ + case op_pal1f: /* "hw_st" */ + p.bits = i.bits; + db_printf("\t%s%c%s\t%s,", opcode, + (p.mem_format.qw) ? 'q' : 'l', + hwlds_name[p.mem_format.qualif], + register_name(p.mem_format.rd)); + signed_immediate = (long)p.mem_format.displacement; + goto loadstore_address; + + case op_pal1e: /* "hw_rei" */ + db_printf("\t%s", opcode); + break; + + case op_ldf: + case op_ldg: + case op_lds: + case op_ldt: + case op_stf: + case op_stg: + case op_sts: + case op_stt: + fstore = TRUE; + /* fall through */ + case op_ldl: + case op_ldq: + case op_ldl_l: + case op_ldq_l: + case op_stl: + case op_stq: + case op_stl_c: + case op_stq_c: + /* + * Memory operations, including floats + */ +loadstore: + if (fstore) + db_printf("%s\tf%d,", opcode, i.mem_format.rd); + else + db_printf("%s\t%s,", opcode, + register_name(i.mem_format.rd)); + signed_immediate = (long)i.mem_format.displacement; +loadstore_address: + db_printf("%+#lx(%s)", signed_immediate, + register_name(i.mem_format.rs)); + /* + * For convenience, do the address computation + */ + if (showregs) { + if (i.mem_format.opcode == op_ldah) + signed_immediate <<= 16; + db_printf(" <0x%x>", signed_immediate + + db_register_value(DDB_REGS, i.mem_format.rs)); + } + break; + case op_br: + case op_fbeq: + case op_fblt: + case op_fble: + case op_bsr: + case op_fbne: + case op_fbge: + case op_fbgt: + case op_blbc: + case op_beq: + case op_blt: + case op_ble: + case op_blbs: + case op_bne: + case op_bge: + case op_bgt: + /* + * We want to know where we are branching to + */ + signed_immediate = (long)i.branch_format.displacement; + db_printf("%s\t%s,", opcode, + register_name(i.branch_format.rd)); +branch_displacement: + db_printsym(iadr + sizeof(alpha_instruction) + + (signed_immediate << 2), DB_STGY_PROC); + break; + default: + /* + * Shouldn't happen + */ + db_printf("? 0x%x ?", i.bits); + } + + /* + * Print out the registers used in this instruction + */ + if (showregs && regcount > 0) { + db_printf("\t<"); + for (ireg = 0; ireg < regcount; ireg++) { + if (ireg != 0) + db_printf(","); + db_printf("%s=0x%lx", + name_of_register[regnum[ireg]], + db_register_value(DDB_REGS, regnum[ireg])); + } + db_printf(">"); + } + db_printf("\n"); + return (sizeof(alpha_instruction)); +} diff --git a/sys/alpha/alpha/db_instruction.h b/sys/alpha/alpha/db_instruction.h new file mode 100644 index 0000000..54d9d11 --- /dev/null +++ b/sys/alpha/alpha/db_instruction.h @@ -0,0 +1,672 @@ +/* $NetBSD: db_instruction.h,v 1.4 1997/09/16 22:53:32 thorpej Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1993,1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + * File: alpha_instruction.h + * Author: Alessandro Forin, Carnegie Mellon University + * Date: 11/91 + * + * Alpha Instruction set definition + * + * Reference: "Alpha System Reference Manual", V4.0, April 1991 + * + */ + +#ifndef _ALPHA_INSTRUCTION_H_ +#define _ALPHA_INSTRUCTION_H_ 1 + +#if !defined(ASSEMBLER) + +/* + * All instructions are in one of five formats: + * Memory, Branch, Operate, Floating-point Operate, PAL + * + * One minor departure from DEC's conventions is we use names + * for registers that are more akin their software use, e.g. + * rather then bluntly call them Ra/Rb/Rc we make clear which + * one is a source (Rs) and which one is a destination (Rd). + * When a second source register is defined we call it Rt. + */ + + +typedef union { + /* + * All instructions are 32 bits wide + */ + unsigned int bits; + + /* + * Memory instructions contain a 16 bit + * signed immediate value and two register + * specifiers + */ + struct { + signed short displacement; + unsigned rs : 5, + rd : 5, + opcode : 6; + } mem_format; + + /* + * Branch instruction contain a 21 bit offset, + * which is sign-extended, shifted and combined + * with the PC to form a 64 bit destination address. + * + * In computed jump instructions the opcode is further + * specified in the offset field, the rest of it is + * used as branch target hint. The destination of the + * jump is the source register. + */ + struct { + signed int displacement : 21; + unsigned rd : 5, + opcode : 6; + } branch_format; + + struct { + signed int hint : 14; + unsigned action : 2, + rs : 5, + rd : 5, + opcode : 6; + } jump_format; + + + /* + * Operate instructions are of two types, with + * a second source register or with a literal + * specifier. Bit 12 sez which is which. + */ + struct { + unsigned rd : 5, + function : 7, + sbz : 4, + rt : 5, + rs : 5, + opcode : 6; + } operate_reg_format; + + struct { + unsigned rd : 5, + function : 7, + one : 1, + literal : 8, + rs : 5, + opcode : 6; + } operate_lit_format; + + + /* + * Floating point operate instruction are quite + * uniform in the encoding. As for the semantics.. + */ + struct { + unsigned fd : 5, + function : 11, + ft : 5, + fs : 5, + opcode : 6; + } float_format; + + + /* + * PAL instructions just define the major opcode + */ + + struct { + unsigned function : 26, + opcode : 6; + } pal_format; + +} alpha_instruction; + +#endif !defined(ASSEMBLER) + +/* + * + * Encoding of regular instructions (Appendix C op cit) + * + */ + + /* OPCODE, bits 26..31 */ + +#define op_pal 0x00 /* see PAL sub-table */ + /* 1..7 reserved */ +#define op_lda 0x08 +#define op_ldah 0x09 +#define op_ldbu 0x0a +#define op_ldq_u 0x0b +#define op_ldwu 0x0c +#define op_stw 0x0d +#define op_stb 0x0e +#define op_stq_u 0x0f + +#define op_arit 0x10 /* see ARIT sub-table */ +#define op_logical 0x11 /* see LOGICAL sub-table */ +#define op_bit 0x12 /* see BIT sub-table */ +#define op_mul 0x13 /* see MUL sub-table */ + /* reserved */ +#define op_vax_float 0x15 /* see FLOAT sub-table */ +#define op_ieee_float 0x16 /* see FLOAT sub-table */ +#define op_any_float 0x17 /* see FLOAT sub-table */ + +#define op_special 0x18 /* see SPECIAL sub-table */ +#define op_pal19 0x19 /* reserved for pal code */ +#define op_j 0x1a /* see JUMP sub-table */ +#define op_pal1b 0x1b /* reserved for pal code */ +#define op_intmisc 0x1c /* see INTMISC sub-table */ +#define op_pal1d 0x1d /* reserved for pal code */ +#define op_pal1e 0x1e /* reserved for pal code */ +#define op_pal1f 0x1f /* reserved for pal code */ + +#define op_ldf 0x20 +#define op_ldg 0x21 +#define op_lds 0x22 +#define op_ldt 0x23 +#define op_stf 0x24 +#define op_stg 0x25 +#define op_sts 0x26 +#define op_stt 0x27 +#define op_ldl 0x28 +#define op_ldq 0x29 +#define op_ldl_l 0x2a +#define op_ldq_l 0x2b +#define op_stl 0x2c +#define op_stq 0x2d +#define op_stl_c 0x2e +#define op_stq_c 0x2f +#define op_br 0x30 +#define op_fbeq 0x31 +#define op_fblt 0x32 +#define op_fble 0x33 +#define op_bsr 0x34 +#define op_fbne 0x35 +#define op_fbge 0x36 +#define op_fbgt 0x37 +#define op_blbc 0x38 +#define op_beq 0x39 +#define op_blt 0x3a +#define op_ble 0x3b +#define op_blbs 0x3c +#define op_bne 0x3d +#define op_bge 0x3e +#define op_bgt 0x3f + + + /* PAL, "function" opcodes (bits 0..25) */ +/* + * What we will implement is TBD. These are the unprivileged ones + * that we probably have to support for compat reasons. + */ + +/* See <machine/pal.h> */ + + /* ARIT, "function" opcodes (bits 5..11) */ + +#define op_addl 0x00 +#define op_s4addl 0x02 +#define op_subl 0x09 +#define op_s4subl 0x0b +#define op_cmpbge 0x0f +#define op_s8addl 0x12 +#define op_s8subl 0x1b +#define op_cmpult 0x1d +#define op_addq 0x20 +#define op_s4addq 0x22 +#define op_subq 0x29 +#define op_s4subq 0x2b +#define op_cmpeq 0x2d +#define op_s8addq 0x32 +#define op_s8subq 0x3b +#define op_cmpule 0x3d +#define op_addl_v 0x40 +#define op_subl_v 0x49 +#define op_cmplt 0x4d +#define op_addq_v 0x60 +#define op_subq_v 0x69 +#define op_cmple 0x6d + + + /* LOGICAL, "function" opcodes (bits 5..11) */ + +#define op_and 0x00 +#define op_andnot 0x08 /* bic */ +#define op_cmovlbs 0x14 +#define op_cmovlbc 0x16 +#define op_or 0x20 /* bis */ +#define op_cmoveq 0x24 +#define op_cmovne 0x26 +#define op_ornot 0x28 +#define op_xor 0x40 +#define op_cmovlt 0x44 +#define op_cmovge 0x46 +#define op_xornot 0x48 /* eqv */ +#define op_amask 0x61 +#define op_cmovle 0x64 +#define op_cmovgt 0x66 +#define op_implver 0x6c + + /* BIT, "function" opcodes (bits 5..11) */ + +#define op_mskbl 0x02 +#define op_extbl 0x06 +#define op_insbl 0x0b +#define op_mskwl 0x12 +#define op_extwl 0x16 +#define op_inswl 0x1b +#define op_mskll 0x22 +#define op_extll 0x26 +#define op_insll 0x2b +#define op_zap 0x30 +#define op_zapnot 0x31 +#define op_mskql 0x32 +#define op_srl 0x34 +#define op_extql 0x36 +#define op_sll 0x39 +#define op_insql 0x3b +#define op_sra 0x3c +#define op_mskwh 0x52 +#define op_inswh 0x57 +#define op_extwh 0x5a +#define op_msklh 0x62 +#define op_inslh 0x67 +#define op_extlh 0x6a +#define op_extqh 0x7a +#define op_insqh 0x77 +#define op_mskqh 0x72 + + /* MUL, "function" opcodes (bits 5..11) */ + +#define op_mull 0x00 +#define op_mulq_v 0x60 +#define op_mull_v 0x40 +#define op_umulh 0x30 +#define op_mulq 0x20 + + + /* SPECIAL, "displacement" opcodes (bits 0..15) */ + +#define op_draint 0x0000 +#define op_mb 0x4000 +#define op_fetch 0x8000 +#define op_fetch_m 0xa000 +#define op_rpcc 0xc000 +#define op_rc 0xe000 +#define op_rs 0xf000 + + /* JUMP, "action" opcodes (bits 14..15) */ + +#define op_jmp 0x0 +#define op_jsr 0x1 +#define op_ret 0x2 +#define op_jcr 0x3 + + /* INTMISC, "function" opcodes (operate format) */ + +#define op_sextb 0x00 +#define op_sextw 0x01 +#define op_ctpop 0x30 +#define op_perr 0x31 +#define op_ctlz 0x32 +#define op_cttz 0x33 +#define op_unpkbw 0x34 +#define op_unpkbl 0x35 +#define op_pkwb 0x36 +#define op_pklb 0x37 +#define op_minsb8 0x38 +#define op_minsw4 0x39 +#define op_minub8 0x3a +#define op_minuw4 0x3b +#define op_maxub8 0x3c +#define op_maxuw4 0x3d +#define op_maxsb8 0x3e +#define op_maxsw4 0x3f +#define op_ftoit 0x70 +#define op_ftois 0x78 + +/* + * + * Encoding of floating point instructions (pagg. C-5..6 op cit) + * + * Load and store operations use opcodes op_ldf..op_stt + */ + + /* any FLOAT, "function" opcodes (bits 5..11) */ + +#define op_cvtlq 0x010 +#define op_cpys 0x020 +#define op_cpysn 0x021 +#define op_cpyse 0x022 +#define op_mt_fpcr 0x024 +#define op_mf_fpcr 0x025 +#define op_fcmoveq 0x02a +#define op_fcmovne 0x02b +#define op_fcmovlt 0x02c +#define op_fcmovge 0x02d +#define op_fcmovle 0x02e +#define op_fcmovgt 0x02f +#define op_cvtql 0x030 +#define op_cvtql_v 0x130 +#define op_cvtql_sv 0x330 + + + /* ieee FLOAT, "function" opcodes (bits 5..11) */ + +#define op_adds_c 0x000 +#define op_subs_c 0x001 +#define op_muls_c 0x002 +#define op_divs_c 0x003 +#define op_addt_c 0x020 +#define op_subt_c 0x021 +#define op_mult_c 0x022 +#define op_divt_c 0x023 +#define op_cvtts_c 0x02c +#define op_cvttq_c 0x02f +#define op_cvtqs_c 0x03c +#define op_cvtqt_c 0x03e +#define op_adds_m 0x040 +#define op_subs_m 0x041 +#define op_muls_m 0x042 +#define op_divs_m 0x043 +#define op_addt_m 0x060 +#define op_subt_m 0x061 +#define op_mult_m 0x062 +#define op_divt_m 0x063 +#define op_cvtts_m 0x06c +#define op_cvtqs_m 0x07c +#define op_cvtqt_m 0x07e +#define op_adds 0x080 +#define op_subs 0x081 +#define op_muls 0x082 +#define op_divs 0x083 +#define op_addt 0x0a0 +#define op_subt 0x0a1 +#define op_mult 0x0a2 +#define op_divt 0x0a3 +#define op_cmptun 0x0a4 +#define op_cmpteq 0x0a5 +#define op_cmptlt 0x0a6 +#define op_cmptle 0x0a7 +#define op_cvtts 0x0ac +#define op_cvttq 0x0af +#define op_cvtqs 0x0bc +#define op_cvtqt 0x0be +#define op_adds_d 0x0c0 +#define op_subs_d 0x0c1 +#define op_muls_d 0x0c2 +#define op_divs_d 0x0c3 +#define op_addt_d 0x0e0 +#define op_subt_d 0x0e1 +#define op_mult_d 0x0e2 +#define op_divt_d 0x0e3 +#define op_cvtts_d 0x0ec +#define op_cvtqs_d 0x0fc +#define op_cvtqt_d 0x0fe +#define op_adds_uc 0x100 +#define op_subs_uc 0x101 +#define op_muls_uc 0x102 +#define op_divs_uc 0x103 +#define op_addt_uc 0x120 +#define op_subt_uc 0x121 +#define op_mult_uc 0x122 +#define op_divt_uc 0x123 +#define op_cvtts_uc 0x12c +#define op_cvttq_vc 0x12f +#define op_adds_um 0x140 +#define op_subs_um 0x141 +#define op_muls_um 0x142 +#define op_divs_um 0x143 +#define op_addt_um 0x160 +#define op_subt_um 0x161 +#define op_mult_um 0x162 +#define op_divt_um 0x163 +#define op_cvtts_um 0x16c +#define op_adds_u 0x180 +#define op_subs_u 0x181 +#define op_muls_u 0x182 +#define op_divs_u 0x183 +#define op_addt_u 0x1a0 +#define op_subt_u 0x1a1 +#define op_mult_u 0x1a2 +#define op_divt_u 0x1a3 +#define op_cvtts_u 0x1ac +#define op_cvttq_v 0x1af +#define op_adds_ud 0x1c0 +#define op_subs_ud 0x1c1 +#define op_muls_ud 0x1c2 +#define op_divs_ud 0x1c3 +#define op_addt_ud 0x1e0 +#define op_subt_ud 0x1e1 +#define op_mult_ud 0x1e2 +#define op_divt_ud 0x1e3 +#define op_cvtts_ud 0x1ec +#define op_adds_suc 0x500 +#define op_subs_suc 0x501 +#define op_muls_suc 0x502 +#define op_divs_suc 0x503 +#define op_addt_suc 0x520 +#define op_subt_suc 0x521 +#define op_mult_suc 0x522 +#define op_divt_suc 0x523 +#define op_cvtts_suc 0x52c +#define op_cvttq_svc 0x52f +#define op_adds_sum 0x540 +#define op_subs_sum 0x541 +#define op_muls_sum 0x542 +#define op_divs_sum 0x543 +#define op_addt_sum 0x560 +#define op_subt_sum 0x561 +#define op_mult_sum 0x562 +#define op_divt_sum 0x563 +#define op_cvtts_sum 0x56c +#define op_adds_su 0x580 +#define op_subs_su 0x581 +#define op_muls_su 0x582 +#define op_divs_su 0x583 +#define op_addt_su 0x5a0 +#define op_subt_su 0x5a1 +#define op_mult_su 0x5a2 +#define op_divt_su 0x5a3 +#define op_cmptun_su 0x5a4 +#define op_cmpteq_su 0x5a5 +#define op_cmptlt_su 0x5a6 +#define op_cmptle_su 0x5a7 +#define op_cvtts_su 0x5ac +#define op_cvttq_sv 0x5af +#define op_adds_sud 0x5c0 +#define op_subs_sud 0x5c1 +#define op_muls_sud 0x5c2 +#define op_divs_sud 0x5c3 +#define op_addt_sud 0x5e0 +#define op_subt_sud 0x5e1 +#define op_mult_sud 0x5e2 +#define op_divt_sud 0x5e3 +#define op_cvtts_sud 0x5ec +#define op_adds_suic 0x700 +#define op_subs_suic 0x701 +#define op_muls_suic 0x702 +#define op_divs_suic 0x703 +#define op_addt_suic 0x720 +#define op_subt_suic 0x721 +#define op_mult_suic 0x722 +#define op_divt_suic 0x723 +#define op_cvtts_suic 0x72c +#define op_cvttq_svic 0x72f +#define op_cvtqs_suic 0x73c +#define op_cvtqt_suic 0x73e +#define op_adds_suim 0x740 +#define op_subs_suim 0x741 +#define op_muls_suim 0x742 +#define op_divs_suim 0x743 +#define op_addt_suim 0x760 +#define op_subt_suim 0x761 +#define op_mult_suim 0x762 +#define op_divt_suim 0x763 +#define op_cvtts_suim 0x76c +#define op_cvtqs_suim 0x77c +#define op_cvtqt_suim 0x77e +#define op_adds_sui 0x780 +#define op_subs_sui 0x781 +#define op_muls_sui 0x782 +#define op_divs_sui 0x783 +#define op_addt_sui 0x7a0 +#define op_subt_sui 0x7a1 +#define op_mult_sui 0x7a2 +#define op_divt_sui 0x7a3 +#define op_cvtts_sui 0x7ac +#define op_cvttq_svi 0x7af +#define op_cvtqs_sui 0x7bc +#define op_cvtqt_sui 0x7be +#define op_adds_suid 0x7c0 +#define op_subs_suid 0x7c1 +#define op_muls_suid 0x7c2 +#define op_divs_suid 0x7c3 +#define op_addt_suid 0x7e0 +#define op_subt_suid 0x7e1 +#define op_mult_suid 0x7e2 +#define op_divt_suid 0x7e3 +#define op_cvtts_suid 0x7ec +#define op_cvtqs_suid 0x7fc +#define op_cvtqt_suid 0x7fe + + + /* vax FLOAT, "function" opcodes (bits 5..11) */ + +#define op_addf_c 0x000 +#define op_subf_c 0x001 +#define op_mulf_c 0x002 +#define op_divf_c 0x003 +#define op_cvtdg_c 0x01e +#define op_addg_c 0x020 +#define op_subg_c 0x021 +#define op_mulg_c 0x022 +#define op_divg_c 0x023 +#define op_cvtgf_c 0x02c +#define op_cvtgd_c 0x02d +#define op_cvtgqg_c 0x02f +#define op_cvtqf_c 0x03c +#define op_cvtqg_c 0x03e +#define op_addf 0x080 +#define op_subf 0x081 +#define op_mulf 0x082 +#define op_divf 0x083 +#define op_cvtdg 0x09e +#define op_addg 0x0a0 +#define op_subg 0x0a1 +#define op_mulg 0x0a2 +#define op_divg 0x0a3 +#define op_cmpgeq 0x0a5 +#define op_cmpglt 0x0a6 +#define op_cmpgle 0x0a7 +#define op_cvtgf 0x0ac +#define op_cvtgd 0x0ad +#define op_cvtgq 0x0af +#define op_cvtqf 0x0bc +#define op_cvtqg 0x0be +#define op_addf_uc 0x100 +#define op_subf_uc 0x101 +#define op_mulf_uc 0x102 +#define op_divf_uc 0x103 +#define op_cvtdg_uc 0x11e +#define op_addg_uc 0x120 +#define op_subg_uc 0x121 +#define op_mulg_uc 0x122 +#define op_divg_uc 0x123 +#define op_cvtgf_uc 0x12c +#define op_cvtgd_uc 0x12d +#define op_cvtgqg_vc 0x12f +#define op_addf_u 0x180 +#define op_subf_u 0x181 +#define op_mulf_u 0x182 +#define op_divf_u 0x183 +#define op_cvtdg_u 0x19e +#define op_addg_u 0x1a0 +#define op_subg_u 0x1a1 +#define op_mulg_u 0x1a2 +#define op_divg_u 0x1a3 +#define op_cvtgf_u 0x1ac +#define op_cvtgd_u 0x1ad +#define op_cvtgqg_v 0x1af +#define op_addf_sc 0x400 +#define op_subf_sc 0x401 +#define op_mulf_sc 0x402 +#define op_divf_sc 0x403 +#define op_cvtdg_sc 0x41e +#define op_addg_sc 0x420 +#define op_subg_sc 0x421 +#define op_mulg_sc 0x422 +#define op_divg_sc 0x423 +#define op_cvtgf_sc 0x42c +#define op_cvtgd_sc 0x42d +#define op_cvtgqg_sc 0x42f +#define op_cvtqf_sc 0x43c +#define op_cvtqg_sc 0x43e +#define op_addf_s 0x480 +#define op_subf_s 0x481 +#define op_mulf_s 0x482 +#define op_divf_s 0x483 +#define op_cvtdg_s 0x49e +#define op_addg_s 0x4a0 +#define op_subg_s 0x4a1 +#define op_mulg_s 0x4a2 +#define op_divg_s 0x4a3 +#define op_cmpgeq_s 0x4a5 +#define op_cmpglt_s 0x4a6 +#define op_cmpgle_s 0x4a7 +#define op_cvtgf_s 0x4ac +#define op_cvtgd_s 0x4ad +#define op_cvtgqg_s 0x4af +#define op_cvtqf_s 0x4bc +#define op_cvtqg_s 0x4be +#define op_addf_suc 0x500 +#define op_subf_suc 0x501 +#define op_mulf_suc 0x502 +#define op_divf_suc 0x503 +#define op_cvtdg_suc 0x51e +#define op_addg_suc 0x520 +#define op_subg_suc 0x521 +#define op_mulg_suc 0x522 +#define op_divg_suc 0x523 +#define op_cvtgf_suc 0x52c +#define op_cvtgd_suc 0x52d +#define op_cvtgqg_svc 0x52f +#define op_addf_su 0x580 +#define op_subf_su 0x581 +#define op_mulf_su 0x582 +#define op_divf_su 0x583 +#define op_cvtdg_su 0x59e +#define op_addg_su 0x5a0 +#define op_subg_su 0x5a1 +#define op_mulg_su 0x5a2 +#define op_divg_su 0x5a3 +#define op_cvtgf_su 0x5ac +#define op_cvtgd_su 0x5ad +#define op_cvtgqg_sv 0x5af + + +#endif /* _ALPHA_INSTRUCTION_H_ */ diff --git a/sys/alpha/alpha/db_interface.c b/sys/alpha/alpha/db_interface.c new file mode 100644 index 0000000..c93e506 --- /dev/null +++ b/sys/alpha/alpha/db_interface.c @@ -0,0 +1,536 @@ +/* $NetBSD: db_interface.c,v 1.2 1997/09/16 19:07:19 thorpej Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1992,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) + */ + +/* + * Parts of this file are derived from Mach 3: + * + * File: alpha_instruction.c + * Author: Alessandro Forin, Carnegie Mellon University + * Date: 6/92 + */ + +/* + * Interface to DDB. + * + * Modified for NetBSD/alpha by: + * + * Christopher G. Demetriou, Carnegie Mellon University + * + * Jason R. Thorpe, Numerical Aerospace Simulation Facility, + * NASA Ames Research Center + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +/* __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.2 1997/09/16 19:07:19 thorpej Exp $"); */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/reboot.h> +#include <sys/systm.h> +#include <sys/kernel.h> + +#include <vm/vm.h> + +#include <machine/cons.h> + +#include <machine/db_machdep.h> +#include <machine/pal.h> +#include <machine/prom.h> + +#include <alpha/alpha/db_instruction.h> + +#include <ddb/ddb.h> + +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_variables.h> + +extern label_t *db_recover; + +#if 0 +extern char *trap_type[]; +extern int trap_types; +#endif + +int db_active = 0; + +void ddbprinttrap __P((unsigned long, unsigned long, unsigned long, + unsigned long)); + +struct db_variable db_regs[] = { + { "v0", &ddb_regs.tf_regs[FRAME_V0], FCN_NULL }, + { "t0", &ddb_regs.tf_regs[FRAME_T0], FCN_NULL }, + { "t1", &ddb_regs.tf_regs[FRAME_T1], FCN_NULL }, + { "t2", &ddb_regs.tf_regs[FRAME_T2], FCN_NULL }, + { "t3", &ddb_regs.tf_regs[FRAME_T3], FCN_NULL }, + { "t4", &ddb_regs.tf_regs[FRAME_T4], FCN_NULL }, + { "t5", &ddb_regs.tf_regs[FRAME_T5], FCN_NULL }, + { "t6", &ddb_regs.tf_regs[FRAME_T6], FCN_NULL }, + { "t7", &ddb_regs.tf_regs[FRAME_T7], FCN_NULL }, + { "s0", &ddb_regs.tf_regs[FRAME_S0], FCN_NULL }, + { "s1", &ddb_regs.tf_regs[FRAME_S1], FCN_NULL }, + { "s2", &ddb_regs.tf_regs[FRAME_S2], FCN_NULL }, + { "s3", &ddb_regs.tf_regs[FRAME_S3], FCN_NULL }, + { "s4", &ddb_regs.tf_regs[FRAME_S4], FCN_NULL }, + { "s5", &ddb_regs.tf_regs[FRAME_S5], FCN_NULL }, + { "s6", &ddb_regs.tf_regs[FRAME_S6], FCN_NULL }, + { "a0", &ddb_regs.tf_regs[FRAME_A0], FCN_NULL }, + { "a1", &ddb_regs.tf_regs[FRAME_A1], FCN_NULL }, + { "a2", &ddb_regs.tf_regs[FRAME_A2], FCN_NULL }, + { "a3", &ddb_regs.tf_regs[FRAME_A3], FCN_NULL }, + { "a4", &ddb_regs.tf_regs[FRAME_A4], FCN_NULL }, + { "a5", &ddb_regs.tf_regs[FRAME_A5], FCN_NULL }, + { "t8", &ddb_regs.tf_regs[FRAME_T8], FCN_NULL }, + { "t9", &ddb_regs.tf_regs[FRAME_T9], FCN_NULL }, + { "t10", &ddb_regs.tf_regs[FRAME_T10], FCN_NULL }, + { "t11", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL }, + { "ra", &ddb_regs.tf_regs[FRAME_RA], FCN_NULL }, + { "t12", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL }, + { "at", &ddb_regs.tf_regs[FRAME_AT], FCN_NULL }, + { "gp", &ddb_regs.tf_regs[FRAME_GP], FCN_NULL }, + { "sp", &ddb_regs.tf_regs[FRAME_SP], FCN_NULL }, + { "pc", &ddb_regs.tf_regs[FRAME_PC], FCN_NULL }, + { "ps", &ddb_regs.tf_regs[FRAME_PS], FCN_NULL }, + { "ai", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL }, + { "pv", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL }, +}; +struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); + +/* + * Print trap reason. + */ +void +ddbprinttrap(a0, a1, a2, entry) + unsigned long a0, a1, a2, entry; +{ + + /* XXX Implement. */ + + printf("ddbprinttrap(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", a0, a1, a2, + entry); +} + +/* + * ddb_trap - field a kernel trap + */ +int +ddb_trap(a0, a1, a2, entry, regs) + unsigned long a0, a1, a2, entry; + db_regs_t *regs; +{ + int s; + + /* + * Don't bother checking for usermode, since a benign entry + * by the kernel (call to Debugger() or a breakpoint) has + * already checked for usermode. If neither of those + * conditions exist, something Bad has happened. + */ + + if (entry != ALPHA_KENTRY_IF || + (a0 != ALPHA_IF_CODE_BUGCHK && a0 != ALPHA_IF_CODE_BPT)) { + db_printf("ddbprinttrap from 0x%lx\n", /* XXX */ + regs->tf_regs[FRAME_PC]); + ddbprinttrap(a0, a1, a2, entry); +#if 0 + if (db_recover != 0) { + /* + * XXX Sould longjump back into command loop! + */ + db_printf("Faulted in DDB; continuing...\n"); + alpha_pal_halt(); /* XXX */ + db_error("Faulted in DDB; continuing...\n"); + /* NOTREACHED */ + } +#endif + + /* + * Tell caller "We did NOT handle the trap." + * Caller should panic, or whatever. + */ + return (0); + } + + /* + * XXX Should switch to DDB's own stack, here. + */ + + ddb_regs = *regs; + + s = splhigh(); + + db_active++; + cnpollc(TRUE); /* Set polling mode, unblank video */ + + db_trap(entry, a0); /* Where the work happens */ + + cnpollc(FALSE); /* Resume interrupt mode */ + db_active--; + + splx(s); + + *regs = ddb_regs; + + /* + * Tell caller "We HAVE handled the trap." + */ + return (1); +} + +/* + * Read bytes from kernel address space for debugger. + */ +void +db_read_bytes(addr, size, data) + vm_offset_t addr; + register size_t size; + register char *data; +{ + register char *src; + + src = (char *)addr; + while (size-- > 0) + *data++ = *src++; +} + +/* + * Write bytes to kernel address space for debugger. + */ +void +db_write_bytes(addr, size, data) + vm_offset_t addr; + register size_t size; + register char *data; +{ + register char *dst; + + dst = (char *)addr; + while (size-- > 0) + *dst++ = *data++; + alpha_pal_imb(); +} + +void +Debugger(const char* msg) +{ + printf("%s\n", msg); + __asm("call_pal 0x81"); /* XXX bugchk */ +} + +/* + * Alpha-specific ddb commands: + * + * halt set halt bit in rpb and halt + * reboot set reboot bit in rpb and halt + */ + +DB_COMMAND(halt, db_mach_halt) +{ + + prom_halt(1); +} + +DB_COMMAND(reboot, db_mach_reboot) +{ + prom_halt(0); +} + +/* + * Map Alpha register numbers to trapframe/db_regs_t offsets. + */ +static int reg_to_frame[32] = { + FRAME_V0, + FRAME_T0, + FRAME_T1, + FRAME_T2, + FRAME_T3, + FRAME_T4, + FRAME_T5, + FRAME_T6, + FRAME_T7, + + FRAME_S0, + FRAME_S1, + FRAME_S2, + FRAME_S3, + FRAME_S4, + FRAME_S5, + FRAME_S6, + + FRAME_A0, + FRAME_A1, + FRAME_A2, + FRAME_A3, + FRAME_A4, + FRAME_A5, + + FRAME_T8, + FRAME_T9, + FRAME_T10, + FRAME_T11, + FRAME_RA, + FRAME_T12, + FRAME_AT, + FRAME_GP, + FRAME_SP, + -1, /* zero */ +}; + +u_long +db_register_value(regs, regno) + db_regs_t *regs; + int regno; +{ + + if (regno > 31 || regno < 0) { + db_printf(" **** STRANGE REGISTER NUMBER %d **** ", regno); + return (0); + } + + if (regno == 31) + return (0); + + return (regs->tf_regs[reg_to_frame[regno]]); +} + +/* + * Support functions for software single-step. + */ + +boolean_t +db_inst_call(ins) + int ins; +{ + alpha_instruction insn; + + insn.bits = ins; + return ((insn.branch_format.opcode == op_bsr) || + ((insn.jump_format.opcode == op_j) && + (insn.jump_format.action & 1))); +} + +boolean_t +db_inst_return(ins) + int ins; +{ + alpha_instruction insn; + + insn.bits = ins; + return ((insn.jump_format.opcode == op_j) && + (insn.jump_format.action == op_ret)); +} + +boolean_t +db_inst_trap_return(ins) + int ins; +{ + alpha_instruction insn; + + insn.bits = ins; + return ((insn.pal_format.opcode == op_pal) && + (insn.pal_format.function == PAL_OSF1_rti)); +} + +boolean_t +db_inst_branch(ins) + int ins; +{ + alpha_instruction insn; + + insn.bits = ins; + switch (insn.branch_format.opcode) { + case op_j: + case op_br: + case op_fbeq: + case op_fblt: + case op_fble: + case op_fbne: + case op_fbge: + case op_fbgt: + case op_blbc: + case op_beq: + case op_blt: + case op_ble: + case op_blbs: + case op_bne: + case op_bge: + case op_bgt: + return (TRUE); + } + + return (FALSE); +} + +boolean_t +db_inst_unconditional_flow_transfer(ins) + int ins; +{ + alpha_instruction insn; + + insn.bits = ins; + switch (insn.branch_format.opcode) { + case op_j: + case op_br: + return (TRUE); + + case op_pal: + switch (insn.pal_format.function) { + case PAL_OSF1_retsys: + case PAL_OSF1_rti: + case PAL_OSF1_callsys: + return (TRUE); + } + } + + return (FALSE); +} + +#if 0 +boolean_t +db_inst_spill(ins, regn) + int ins, regn; +{ + alpha_instruction insn; + + insn.bits = ins; + return ((insn.mem_format.opcode == op_stq) && + (insn.mem_format.rd == regn)); +} +#endif + +boolean_t +db_inst_load(ins) + int ins; +{ + alpha_instruction insn; + + insn.bits = ins; + + /* Loads. */ + if (insn.mem_format.opcode == op_ldbu || + insn.mem_format.opcode == op_ldq_u || + insn.mem_format.opcode == op_ldwu) + return (TRUE); + if ((insn.mem_format.opcode >= op_ldf) && + (insn.mem_format.opcode <= op_ldt)) + return (TRUE); + if ((insn.mem_format.opcode >= op_ldl) && + (insn.mem_format.opcode <= op_ldq_l)) + return (TRUE); + + /* Prefetches. */ + if (insn.mem_format.opcode == op_special) { + /* Note: MB is treated as a store. */ + if ((insn.mem_format.displacement == (short)op_fetch) || + (insn.mem_format.displacement == (short)op_fetch_m)) + return (TRUE); + } + + return (FALSE); +} + +boolean_t +db_inst_store(ins) + int ins; +{ + alpha_instruction insn; + + insn.bits = ins; + + /* Stores. */ + if (insn.mem_format.opcode == op_stw || + insn.mem_format.opcode == op_stb || + insn.mem_format.opcode == op_stq_u) + return (TRUE); + if ((insn.mem_format.opcode >= op_stf) && + (insn.mem_format.opcode <= op_stt)) + return (TRUE); + if ((insn.mem_format.opcode >= op_stl) && + (insn.mem_format.opcode <= op_stq_c)) + return (TRUE); + + /* Barriers. */ + if (insn.mem_format.opcode == op_special) { + if (insn.mem_format.displacement == op_mb) + return (TRUE); + } + + return (FALSE); +} + +db_addr_t +db_branch_taken(ins, pc, regs) + int ins; + db_addr_t pc; + db_regs_t *regs; +{ + alpha_instruction insn; + db_addr_t newpc; + + insn.bits = ins; + switch (insn.branch_format.opcode) { + /* + * Jump format: target PC is (contents of instruction's "RB") & ~3. + */ + case op_j: + newpc = db_register_value(regs, insn.jump_format.rs) & ~3; + break; + + /* + * Branch format: target PC is + * (new PC) + (4 * sign-ext(displacement)). + */ + case op_br: + case op_fbeq: + case op_fblt: + case op_fble: + case op_bsr: + case op_fbne: + case op_fbge: + case op_fbgt: + case op_blbc: + case op_beq: + case op_blt: + case op_ble: + case op_blbs: + case op_bne: + case op_bge: + case op_bgt: + newpc = (insn.branch_format.displacement << 2) + (pc + 4); + break; + + default: + printf("DDB: db_inst_branch_taken on non-branch!\n"); + newpc = pc; /* XXX */ + } + + return (newpc); +} diff --git a/sys/alpha/alpha/db_trace.c b/sys/alpha/alpha/db_trace.c new file mode 100644 index 0000000..944e171 --- /dev/null +++ b/sys/alpha/alpha/db_trace.c @@ -0,0 +1,25 @@ +/* $NetBSD: db_trace.c,v 1.1 1997/09/06 02:00:50 thorpej Exp $ */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +/* __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.1 1997/09/06 02:00:50 thorpej Exp $"); */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <machine/db_machdep.h> + +#include <ddb/ddb.h> +#include <ddb/db_sym.h> +#include <ddb/db_access.h> +#include <ddb/db_variables.h> +#include <ddb/db_output.h> + +void +db_stack_trace_cmd(addr, have_addr, count, modif) + db_expr_t addr; + boolean_t have_addr; + db_expr_t count; + char *modif; +{ + /* nothing, yet. */ +} diff --git a/sys/alpha/alpha/dec_kn8ae.c b/sys/alpha/alpha/dec_kn8ae.c new file mode 100644 index 0000000..aad572b --- /dev/null +++ b/sys/alpha/alpha/dec_kn8ae.c @@ -0,0 +1,89 @@ +/* $Id$ */ +/* $NetBSD: dec_kn8ae.c,v 1.15 1998/02/13 00:12:50 thorpej Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include "opt_simos.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/termios.h> + +#include <machine/rpb.h> +#include <machine/conf.h> +#include <machine/cpuconf.h> + +#include <alpha/tlsb/tlsbreg.h> +#include <alpha/tlsb/gbusreg.h> + +void dec_kn8ae_init(int); +static void dec_kn8ae_cons_init(void); + +static const struct alpha_variation_table dec_kn8ae_variations[] = { + { 0, "AlphaServer 8400" }, + { 0, NULL }, +}; + +void +dec_kn8ae_init(int cputype) +{ + u_int64_t variation; + + platform.family = "AlphaServer 8400"; + + if ((platform.model = alpha_dsr_sysname()) == NULL) { + variation = hwrpb->rpb_variation & SV_ST_MASK; + if ((platform.model = alpha_variation_name(variation, + dec_kn8ae_variations)) == NULL) + platform.model = alpha_unknown_sysname(); + } + + platform.iobus = "tlsb"; + platform.cons_init = dec_kn8ae_cons_init; +} + +/* + * dec_kn8ae_cons_init- not needed right now. XXX hack in SimOS console + * + * Info to retain: + * + * The AXP 8X00 seems to encode the + * type of console in the ctb_type field, + * not the ctb_term_type field. + */ +static void +dec_kn8ae_cons_init(void) +{ +#ifdef SIMOS + zs_cnattach(TLSB_GBUS_BASE, GBUS_DUART0_OFFSET); +#endif +} diff --git a/sys/alpha/alpha/diskslice_machdep.c b/sys/alpha/alpha/diskslice_machdep.c new file mode 100644 index 0000000..ada18dc --- /dev/null +++ b/sys/alpha/alpha/diskslice_machdep.c @@ -0,0 +1,461 @@ +/*- + * Copyright (c) 1994 Bruce D. Evans. + * All rights reserved. + * + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. + * + * 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: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $ + * $Id: diskslice_machdep.c,v 1.27 1997/12/02 21:06:20 phk Exp $ + */ + +#include <stddef.h> +#include <sys/param.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/disklabel.h> +#define DOSPTYP_EXTENDED 5 +#define DOSPTYP_ONTRACK 84 +#include <sys/diskslice.h> +#include <sys/malloc.h> +#include <sys/syslog.h> +#include <sys/systm.h> + +#define TRACE(str) do { if (dsi_debug) printf str; } while (0) + +static volatile u_char dsi_debug; + +static struct dos_partition historical_bogus_partition_table[NDOSPART] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, }, +}; + +static int check_part __P((char *sname, struct dos_partition *dp, + u_long offset, int nsectors, int ntracks, + u_long mbr_offset)); +static void extended __P((char *dname, dev_t dev, d_strategy_t *strat, + struct disklabel *lp, struct diskslices *ssp, + u_long ext_offset, u_long ext_size, + u_long base_ext_offset, int nsectors, int ntracks, + u_long mbr_offset)); + +static int +check_part(sname, dp, offset, nsectors, ntracks, mbr_offset ) + char *sname; + struct dos_partition *dp; + u_long offset; + int nsectors; + int ntracks; + u_long mbr_offset; +{ + int chs_ecyl; + int chs_esect; + int chs_scyl; + int chs_ssect; + int error; + u_long esector; + u_long esector1; + u_long secpercyl; + u_long ssector; + u_long ssector1; + + secpercyl = (u_long)nsectors * ntracks; + chs_scyl = DPCYL(dp->dp_scyl, dp->dp_ssect); + chs_ssect = DPSECT(dp->dp_ssect); + ssector = chs_ssect - 1 + dp->dp_shd * nsectors + chs_scyl * secpercyl + + mbr_offset; + ssector1 = offset + dp->dp_start; + + /* + * If ssector1 is on a cylinder >= 1024, then ssector can't be right. + * Allow the C/H/S for it to be 1023/ntracks-1/nsectors, or correct + * apart from the cylinder being reduced modulo 1024. Always allow + * 1023/255/63. + */ + if (ssector < ssector1 + && ((chs_ssect == nsectors && dp->dp_shd == ntracks - 1 + && chs_scyl == 1023) + || (secpercyl != 0 + && (ssector1 - ssector) % (1024 * secpercyl) == 0)) + || (dp->dp_scyl == 255 && dp->dp_shd == 255 + && dp->dp_ssect == 255)) { + TRACE(("%s: C/H/S start %d/%d/%d, start %lu: allow\n", + sname, chs_scyl, dp->dp_shd, chs_ssect, ssector1)); + ssector = ssector1; + } + + chs_ecyl = DPCYL(dp->dp_ecyl, dp->dp_esect); + chs_esect = DPSECT(dp->dp_esect); + esector = chs_esect - 1 + dp->dp_ehd * nsectors + chs_ecyl * secpercyl + + mbr_offset; + esector1 = ssector1 + dp->dp_size - 1; + + /* Allow certain bogus C/H/S values for esector, as above. */ + if (esector < esector1 + && ((chs_esect == nsectors && dp->dp_ehd == ntracks - 1 + && chs_ecyl == 1023) + || (secpercyl != 0 + && (esector1 - esector) % (1024 * secpercyl) == 0)) + || (dp->dp_ecyl == 255 && dp->dp_ehd == 255 + && dp->dp_esect == 255)) { + TRACE(("%s: C/H/S end %d/%d/%d, end %lu: allow\n", + sname, chs_ecyl, dp->dp_ehd, chs_esect, esector1)); + esector = esector1; + } + + error = (ssector == ssector1 && esector == esector1) ? 0 : EINVAL; + if (bootverbose) + printf("%s: type 0x%x, start %lu, end = %lu, size %lu %s\n", + sname, dp->dp_typ, ssector1, esector1, dp->dp_size, + error ? "" : ": OK"); + if (ssector != ssector1 && bootverbose) + printf("%s: C/H/S start %d/%d/%d (%lu) != start %lu: invalid\n", + sname, chs_scyl, dp->dp_shd, chs_ssect, + ssector, ssector1); + if (esector != esector1 && bootverbose) + printf("%s: C/H/S end %d/%d/%d (%lu) != end %lu: invalid\n", + sname, chs_ecyl, dp->dp_ehd, chs_esect, + esector, esector1); + return (error); +} + +int +dsinit(dname, dev, strat, lp, sspp) + char *dname; + dev_t dev; + d_strategy_t *strat; + struct disklabel *lp; + struct diskslices **sspp; +{ + struct buf *bp; + u_char *cp; + int dospart; + struct dos_partition *dp; + struct dos_partition *dp0; + int error; + int max_ncyls; + int max_nsectors; + int max_ntracks; + u_long mbr_offset; + char partname[2]; + u_long secpercyl; + char *sname; + struct diskslice *sp; + struct diskslices *ssp; + + /* + * Allocate a dummy slices "struct" and initialize it to contain + * only an empty compatibility slice (pointing to itself) and a + * whole disk slice (covering the disk as described by the label). + * If there is an error, then the dummy struct becomes final. + */ + ssp = malloc(offsetof(struct diskslices, dss_slices) + + BASE_SLICE * sizeof *sp, M_DEVBUF, M_WAITOK); + *sspp = ssp; + ssp->dss_first_bsd_slice = COMPATIBILITY_SLICE; + ssp->dss_nslices = BASE_SLICE; + sp = &ssp->dss_slices[0]; + bzero(sp, BASE_SLICE * sizeof *sp); + sp[WHOLE_DISK_SLICE].ds_size = lp->d_secperunit; + + mbr_offset = DOSBBSECTOR; +reread_mbr: + /* Read master boot record. */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); + bp->b_blkno = mbr_offset; + bp->b_bcount = lp->d_secsize; + bp->b_flags |= B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp) != 0) { + diskerr(bp, dname, "error reading primary partition table", + LOG_PRINTF, 0, lp); + printf("\n"); + error = EIO; + goto done; + } + + /* Weakly verify it. */ + cp = bp->b_data; + sname = dsname(dname, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, + partname); + if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) { + if (bootverbose) + printf("%s: invalid primary partition table: no magic\n", + sname); + error = EINVAL; + goto done; + } + dp0 = (struct dos_partition *)(cp + DOSPARTOFF); + + /* Check for "Ontrack Diskmanager". */ + for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) { + if (dp->dp_typ == DOSPTYP_ONTRACK) { + if (bootverbose) + printf( + "%s: Found \"Ontrack Disk Manager\" on this disk.\n", sname); + bp->b_flags |= B_INVAL | B_AGE; + brelse(bp); + mbr_offset = 63; + goto reread_mbr; + } + } + + if (bcmp(dp0, historical_bogus_partition_table, + sizeof historical_bogus_partition_table) == 0) { + TRACE(("%s: invalid primary partition table: historical\n", + sname)); + error = EINVAL; + goto done; + } + + /* Guess the geometry. */ + /* + * TODO: + * Perhaps skip entries with 0 size. + * Perhaps only look at entries of type DOSPTYP_386BSD. + */ + max_ncyls = 0; + max_nsectors = 0; + max_ntracks = 0; + for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) { + int ncyls; + int nsectors; + int ntracks; + + ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect) + 1; + if (max_ncyls < ncyls) + max_ncyls = ncyls; + nsectors = DPSECT(dp->dp_esect); + if (max_nsectors < nsectors) + max_nsectors = nsectors; + ntracks = dp->dp_ehd + 1; + if (max_ntracks < ntracks) + max_ntracks = ntracks; + } + + /* + * Check that we have guessed the geometry right by checking the + * partition entries. + */ + /* + * TODO: + * As above. + * Check for overlaps. + * Check against d_secperunit if the latter is reliable. + */ + error = 0; + for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) { + if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0 + && dp->dp_start == 0 && dp->dp_size == 0) + continue; + sname = dsname(dname, dkunit(dev), BASE_SLICE + dospart, + RAW_PART, partname); + + /* + * Temporarily ignore errors from this check. We could + * simplify things by accepting the table eariler if we + * always ignore errors here. Perhaps we should always + * accept the table if the magic is right but not let + * bad entries affect the geometry. + */ + check_part(sname, dp, mbr_offset, max_nsectors, max_ntracks, + mbr_offset); + } + if (error != 0) + goto done; + + /* + * Accept the DOS partition table. + * First adjust the label (we have been careful not to change it + * before we can guarantee success). + */ + secpercyl = (u_long)max_nsectors * max_ntracks; + if (secpercyl != 0) { + u_long secperunit; + + lp->d_nsectors = max_nsectors; + lp->d_ntracks = max_ntracks; + lp->d_secpercyl = secpercyl; + secperunit = secpercyl * max_ncyls; + if (lp->d_secperunit < secperunit) + lp->d_secperunit = secperunit; + lp->d_ncylinders = lp->d_secperunit / secpercyl; + } + + /* + * Free the dummy slices "struct" and allocate a real new one. + * Initialize special slices as above. + */ + free(ssp, M_DEVBUF); + ssp = malloc(offsetof(struct diskslices, dss_slices) +#define MAX_SLICES_SUPPORTED MAX_SLICES /* was (BASE_SLICE + NDOSPART) */ + + MAX_SLICES_SUPPORTED * sizeof *sp, M_DEVBUF, M_WAITOK); + *sspp = ssp; + ssp->dss_first_bsd_slice = COMPATIBILITY_SLICE; + sp = &ssp->dss_slices[0]; + bzero(sp, MAX_SLICES_SUPPORTED * sizeof *sp); + sp[WHOLE_DISK_SLICE].ds_size = lp->d_secperunit; + + /* Initialize normal slices. */ + sp += BASE_SLICE; + for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) { + sp->ds_offset = mbr_offset + dp->dp_start; + sp->ds_size = dp->dp_size; + sp->ds_type = dp->dp_typ; +#if 0 + lp->d_subtype |= (lp->d_subtype & 3) | dospart + | DSTYPE_INDOSPART; +#endif + } + ssp->dss_nslices = BASE_SLICE + NDOSPART; + + /* Handle extended partitions. */ + sp -= NDOSPART; + for (dospart = 0; dospart < NDOSPART; dospart++, sp++) + if (sp->ds_type == DOSPTYP_EXTENDED) + extended(dname, bp->b_dev, strat, lp, ssp, + sp->ds_offset, sp->ds_size, sp->ds_offset, + max_nsectors, max_ntracks, mbr_offset); + +done: + bp->b_flags |= B_INVAL | B_AGE; + brelse(bp); + if (error == EINVAL) + error = 0; + return (error); +} + +void +extended(dname, dev, strat, lp, ssp, ext_offset, ext_size, base_ext_offset, + nsectors, ntracks, mbr_offset) + char *dname; + dev_t dev; + struct disklabel *lp; + d_strategy_t *strat; + struct diskslices *ssp; + u_long ext_offset; + u_long ext_size; + u_long base_ext_offset; + int nsectors; + int ntracks; + u_long mbr_offset; +{ + struct buf *bp; + u_char *cp; + int dospart; + struct dos_partition *dp; + u_long ext_offsets[NDOSPART]; + u_long ext_sizes[NDOSPART]; + char partname[2]; + int slice; + char *sname; + struct diskslice *sp; + + /* Read extended boot record. */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + bp->b_blkno = ext_offset; + bp->b_bcount = lp->d_secsize; + bp->b_flags |= B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp) != 0) { + diskerr(bp, dname, "error reading extended partition table", + LOG_PRINTF, 0, lp); + printf("\n"); + goto done; + } + + /* Weakly verify it. */ + cp = bp->b_data; + if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) { + sname = dsname(dname, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, + partname); + if (bootverbose) + printf("%s: invalid extended partition table: no magic\n", + sname); + goto done; + } + + for (dospart = 0, + dp = (struct dos_partition *)(bp->b_data + DOSPARTOFF), + slice = ssp->dss_nslices, sp = &ssp->dss_slices[slice]; + dospart < NDOSPART; dospart++, dp++) { + ext_sizes[dospart] = 0; + if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0 + && dp->dp_start == 0 && dp->dp_size == 0) + continue; + if (dp->dp_typ == DOSPTYP_EXTENDED) { + char buf[32]; + + sname = dsname(dname, dkunit(dev), WHOLE_DISK_SLICE, + RAW_PART, partname); + strcpy(buf, sname); + if (strlen(buf) < sizeof buf - 11) + strcat(buf, "<extended>"); + check_part(buf, dp, base_ext_offset, nsectors, + ntracks, mbr_offset); + ext_offsets[dospart] = base_ext_offset + dp->dp_start; + ext_sizes[dospart] = dp->dp_size; + } else { + sname = dsname(dname, dkunit(dev), slice, RAW_PART, + partname); + check_part(sname, dp, ext_offset, nsectors, ntracks, + mbr_offset); + if (slice >= MAX_SLICES) { + printf("%s: too many slices\n", sname); + slice++; + continue; + } + sp->ds_offset = ext_offset + dp->dp_start; + sp->ds_size = dp->dp_size; + sp->ds_type = dp->dp_typ; + ssp->dss_nslices++; + slice++; + sp++; + } + } + + /* If we found any more slices, recursively find all the subslices. */ + for (dospart = 0; dospart < NDOSPART; dospart++) + if (ext_sizes[dospart] != 0) + extended(dname, dev, strat, lp, ssp, + ext_offsets[dospart], ext_sizes[dospart], + base_ext_offset, nsectors, ntracks, + mbr_offset); + +done: + bp->b_flags |= B_INVAL | B_AGE; + brelse(bp); +} diff --git a/sys/alpha/alpha/divrem.m4 b/sys/alpha/alpha/divrem.m4 new file mode 100644 index 0000000..c24689f --- /dev/null +++ b/sys/alpha/alpha/divrem.m4 @@ -0,0 +1,197 @@ +/* $NetBSD: divrem.m4,v 1.5 1996/10/17 04:26:25 cgd Exp $ */ + +/* + * Copyright (c) 1994, 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Division and remainder. + * + * The use of m4 is modeled after the sparc code, but the algorithm is + * simple binary long division. + * + * Note that the loops could probably benefit from unrolling. + */ + +/* + * M4 Parameters + * NAME name of function to generate + * OP OP=div: t10 / t11 -> t12; OP=rem: t10 % t11 -> t12 + * S S=true: signed; S=false: unsigned + * WORDSIZE total number of bits + */ + +define(A, `t10') +define(B, `t11') +define(RESULT, `t12') + +define(BIT, `t0') +define(I, `t1') +define(CC, `t2') +define(T_0, `t3') +ifelse(S, `true', `define(NEG, `t4')') + +#include <machine/asm.h> + +LEAF(NAME, 0) /* XXX */ + lda sp, -64(sp) + stq BIT, 0(sp) + stq I, 8(sp) + stq CC, 16(sp) + stq T_0, 24(sp) +ifelse(S, `true', +` stq NEG, 32(sp)') + stq A, 40(sp) + stq B, 48(sp) + mov zero, RESULT /* Initialize result to zero */ + +ifelse(S, `true', +` + /* Compute sign of result. If either is negative, this is easy. */ + or A, B, NEG /* not the sign, but... */ + srl NEG, WORDSIZE - 1, NEG /* rather, or of high bits */ + blbc NEG, Ldoit /* neither negative? do it! */ + +ifelse(OP, `div', +` xor A, B, NEG /* THIS is the sign! */ +', ` mov A, NEG /* sign follows A. */ +') + srl NEG, WORDSIZE - 1, NEG /* make negation the low bit. */ + + srl A, WORDSIZE - 1, I /* is A negative? */ + blbc I, LnegB /* no. */ + /* A is negative; flip it. */ +ifelse(WORDSIZE, `32', ` + /* top 32 bits may be random junk */ + zap A, 0xf0, A +') + subq zero, A, A + srl B, WORDSIZE - 1, I /* is B negative? */ + blbc I, Ldoit /* no. */ +LnegB: + /* B is definitely negative, no matter how we got here. */ +ifelse(WORDSIZE, `32', ` + /* top 32 bits may be random junk */ + zap B, 0xf0, B +') + subq zero, B, B +Ldoit: +') +ifelse(WORDSIZE, `32', ` + /* + * Clear the top 32 bits of each operand, as they may + * sign extension (if negated above), or random junk. + */ + zap A, 0xf0, A + zap B, 0xf0, B +') + + /* kill the special cases. */ + beq B, Ldotrap /* division by zero! */ + + cmpult A, B, CC /* A < B? */ + /* RESULT is already zero, from above. A is untouched. */ + bne CC, Lret_result + + cmpeq A, B, CC /* A == B? */ + cmovne CC, 1, RESULT + cmovne CC, zero, A + bne CC, Lret_result + + /* + * Find out how many bits of zeros are at the beginning of the divisor. + */ +LBbits: + ldiq T_0, 1 /* I = 0; BIT = 1<<WORDSIZE-1 */ + mov zero, I + sll T_0, WORDSIZE-1, BIT +LBloop: + and B, BIT, CC /* if bit in B is set, done. */ + bne CC, LAbits + addq I, 1, I /* increment I, shift bit */ + srl BIT, 1, BIT + cmplt I, WORDSIZE-1, CC /* if I leaves one bit, done. */ + bne CC, LBloop + +LAbits: + beq I, Ldodiv /* If I = 0, divide now. */ + ldiq T_0, 1 /* BIT = 1<<WORDSIZE-1 */ + sll T_0, WORDSIZE-1, BIT + +LAloop: + and A, BIT, CC /* if bit in A is set, done. */ + bne CC, Ldodiv + subq I, 1, I /* decrement I, shift bit */ + srl BIT, 1, BIT + bne I, LAloop /* If I != 0, loop again */ + +Ldodiv: + sll B, I, B /* B <<= i */ + ldiq T_0, 1 + sll T_0, I, BIT + +Ldivloop: + cmpult A, B, CC + or RESULT, BIT, T_0 + cmoveq CC, T_0, RESULT + subq A, B, T_0 + cmoveq CC, T_0, A + srl BIT, 1, BIT + srl B, 1, B + beq A, Lret_result + bne BIT, Ldivloop + +Lret_result: +ifelse(OP, `div', +`', ` mov A, RESULT +') +ifelse(S, `true', +` + /* Check to see if we should negate it. */ + subqv zero, RESULT, T_0 + cmovlbs NEG, T_0, RESULT +') + + ldq BIT, 0(sp) + ldq I, 8(sp) + ldq CC, 16(sp) + ldq T_0, 24(sp) +ifelse(S, `true', +` ldq NEG, 32(sp)') + ldq A, 40(sp) + ldq B, 48(sp) + lda sp, 64(sp) + ret zero, (t9), 1 + +Ldotrap: + ldiq a0, -2 /* This is the signal to SIGFPE! */ + call_pal PAL_gentrap +ifelse(OP, `div', +`', ` mov zero, A /* so that zero will be returned */ +') + br zero, Lret_result + +END(NAME) diff --git a/sys/alpha/alpha/exception.s b/sys/alpha/alpha/exception.s new file mode 100644 index 0000000..8bfc571 --- /dev/null +++ b/sys/alpha/alpha/exception.s @@ -0,0 +1,200 @@ +/* $NetBSD: locore.s,v 1.47 1998/03/22 07:26:32 thorpej Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <machine/asm.h> +#include <assym.s> + +/**************************************************************************/ + +/* + * XentArith: + * System arithmetic trap entry point. + */ + + PALVECT(XentArith) /* setup frame, save registers */ + + /* a0, a1, & a2 already set up */ + ldiq a3, ALPHA_KENTRY_ARITH + mov sp, a4 ; .loc 1 __LINE__ + CALL(trap) + + jmp zero, exception_return + END(XentArith) + +/**************************************************************************/ + +/* + * XentIF: + * System instruction fault trap entry point. + */ + + PALVECT(XentIF) /* setup frame, save registers */ + + /* a0, a1, & a2 already set up */ + ldiq a3, ALPHA_KENTRY_IF + mov sp, a4 ; .loc 1 __LINE__ + CALL(trap) + jmp zero, exception_return + END(XentIF) + +/**************************************************************************/ + +/* + * XentInt: + * System interrupt entry point. + */ + + PALVECT(XentInt) /* setup frame, save registers */ + + /* a0, a1, & a2 already set up */ + mov sp, a3 ; .loc 1 __LINE__ + CALL(interrupt) + jmp zero, exception_return + END(XentInt) + +/**************************************************************************/ + +/* + * XentMM: + * System memory management fault entry point. + */ + + PALVECT(XentMM) /* setup frame, save registers */ + + /* a0, a1, & a2 already set up */ + ldiq a3, ALPHA_KENTRY_MM + mov sp, a4 ; .loc 1 __LINE__ + CALL(trap) + + jmp zero, exception_return + END(XentMM) + +/**************************************************************************/ + +/* + * XentSys: + * System call entry point. + */ + + ESETUP(XentSys) ; .loc 1 __LINE__ + + stq v0,(FRAME_V0*8)(sp) /* in case we need to restart */ + stq s0,(FRAME_S0*8)(sp) + stq s1,(FRAME_S1*8)(sp) + stq s2,(FRAME_S2*8)(sp) + stq s3,(FRAME_S3*8)(sp) + stq s4,(FRAME_S4*8)(sp) + stq s5,(FRAME_S5*8)(sp) + stq s6,(FRAME_S6*8)(sp) + stq a0,(FRAME_A0*8)(sp) + stq a1,(FRAME_A1*8)(sp) + stq a2,(FRAME_A2*8)(sp) + stq a3,(FRAME_A3*8)(sp) + stq a4,(FRAME_A4*8)(sp) + stq a5,(FRAME_A5*8)(sp) + stq ra,(FRAME_RA*8)(sp) + + /* syscall number, passed in v0, is first arg, frame pointer second */ + mov v0,a0 + mov sp,a1 ; .loc 1 __LINE__ + CALL(syscall) + + jmp zero, exception_return + END(XentSys) + +/**************************************************************************/ + +/* + * XentUna: + * System unaligned access entry point. + */ + +LEAF(XentUna, 3) /* XXX should be NESTED */ + .set noat + lda sp,-(FRAME_SW_SIZE*8)(sp) + stq at_reg,(FRAME_AT*8)(sp) + .set at + stq ra,(FRAME_RA*8)(sp) + bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */ + + /* a0, a1, & a2 already set up */ + ldiq a3, ALPHA_KENTRY_UNA + mov sp, a4 ; .loc 1 __LINE__ + CALL(trap) + + jmp zero, exception_return + END(XentUna) + + +/**************************************************************************/ + +/* + * console 'restart' routine to be placed in HWRPB. + */ +LEAF(XentRestart, 1) /* XXX should be NESTED */ + .set noat + lda sp,-(FRAME_SIZE*8)(sp) + stq at_reg,(FRAME_AT*8)(sp) + .set at + stq v0,(FRAME_V0*8)(sp) + stq a3,(FRAME_A3*8)(sp) + stq a4,(FRAME_A4*8)(sp) + stq a5,(FRAME_A5*8)(sp) + stq s0,(FRAME_S0*8)(sp) + stq s1,(FRAME_S1*8)(sp) + stq s2,(FRAME_S2*8)(sp) + stq s3,(FRAME_S3*8)(sp) + stq s4,(FRAME_S4*8)(sp) + stq s5,(FRAME_S5*8)(sp) + stq s6,(FRAME_S6*8)(sp) + stq t0,(FRAME_T0*8)(sp) + stq t1,(FRAME_T1*8)(sp) + stq t2,(FRAME_T2*8)(sp) + stq t3,(FRAME_T3*8)(sp) + stq t4,(FRAME_T4*8)(sp) + stq t5,(FRAME_T5*8)(sp) + stq t6,(FRAME_T6*8)(sp) + stq t7,(FRAME_T7*8)(sp) + stq t8,(FRAME_T8*8)(sp) + stq t9,(FRAME_T9*8)(sp) + stq t10,(FRAME_T10*8)(sp) + stq t11,(FRAME_T11*8)(sp) + stq t12,(FRAME_T12*8)(sp) + stq ra,(FRAME_RA*8)(sp) + + br pv,LXconsole_restart1 +LXconsole_restart1: LDGP(pv) + + ldq a0,(FRAME_RA*8)(sp) /* a0 = ra */ + ldq a1,(FRAME_T11*8)(sp) /* a1 = ai */ + ldq a2,(FRAME_T12*8)(sp) /* a2 = pv */ + CALL(console_restart) + + call_pal PAL_halt + END(XentRestart) diff --git a/sys/alpha/alpha/genassym.c b/sys/alpha/alpha/genassym.c new file mode 100644 index 0000000..520bd41 --- /dev/null +++ b/sys/alpha/alpha/genassym.c @@ -0,0 +1,212 @@ +/*- + * Copyright (c) 1982, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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: @(#)genassym.c 5.11 (Berkeley) 5/10/91 + * $Id: genassym.c,v 1.54 1998/04/06 18:59:14 peter Exp $ + */ + +#include <sys/param.h> +#include <sys/buf.h> +#include <sys/errno.h> +#include <sys/proc.h> +#include <sys/mount.h> +#include <sys/socket.h> +#include <sys/resource.h> +#include <sys/resourcevar.h> +#include <machine/frame.h> +#include <sys/vmmeter.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#define KERNEL /* XXX avoid user headers */ +#include <sys/user.h> +#undef KERNEL +#include <net/if.h> +#include <netinet/in.h> +#include <nfs/nfsv2.h> +#include <nfs/rpcv2.h> +#include <nfs/nfs.h> +#include <nfs/nfsdiskless.h> + +int main __P((void)); +int printf __P((const char *, ...)); + +#define P(name, val) \ + printf(val > 999 ? "#define\t%s 0x%lx\n" : "#define\t%s %ld\n", name, val) + +/* XXX Danger Will Robinson */ +struct prochd { + struct proc *ph_link; /* Linked list of running processes. */ + struct proc *ph_rlink; +}; + +#define OFF(name, type, elem) P(#name, (long)&((type*)0)->elem) +#define CONST2(name, val) P(#name, val) +#define CONST1(name) P(#name, name) + +int +main() +{ + OFF(P_FORW, struct proc, p_procq.tqe_next); + OFF(P_BACK, struct proc, p_procq.tqe_prev); + OFF(P_VMSPACE, struct proc, p_vmspace); + OFF(P_ADDR, struct proc, p_addr); + OFF(P_PRI, struct proc, p_priority); + OFF(P_RTPRIO_TYPE, struct proc, p_rtprio.type); + OFF(P_RTPRIO_PRIO, struct proc, p_rtprio.prio); + OFF(P_STAT, struct proc, p_stat); + OFF(P_WCHAN, struct proc, p_wchan); + OFF(P_FLAG, struct proc, p_flag); + OFF(P_PID, struct proc, p_pid); + OFF(P_RUNTIME, struct proc, p_runtime); + OFF(P_MD_PCBPADDR, struct proc, p_md.md_pcbpaddr); + + OFF(PH_LINK, struct prochd, ph_link); + OFF(PH_RLINK, struct prochd, ph_rlink); + + CONST1(SSLEEP); + CONST1(SRUN); + + OFF(VM_PMAP, struct vmspace, vm_pmap); + OFF(V_TRAP, struct vmmeter, v_trap); + OFF(V_SYSCALL, struct vmmeter, v_trap); + OFF(V_INTR, struct vmmeter, v_trap); + + CONST1(UPAGES); + CONST1(PAGE_SIZE); + CONST1(PAGE_SHIFT); + CONST1(PAGE_MASK); + CONST1(USRSTACK); + CONST1(VM_MAXUSER_ADDRESS); + CONST1(KERNBASE); + CONST1(PTLEV1I); + CONST1(PTESIZE); + + OFF(U_PCB_ONFAULT, struct user, u_pcb.pcb_onfault); + OFF(U_PCB_HWPCB_KSP, struct user, u_pcb.pcb_hw.apcb_ksp); + OFF(U_PCB_CONTEXT, struct user, u_pcb.pcb_context); + OFF(U_PROFSCALE, struct user, u_stats.p_prof.pr_scale); + + OFF(PR_BASE, struct uprof, pr_base); + OFF(PR_SIZE, struct uprof, pr_size); + OFF(PR_OFF, struct uprof, pr_off); + OFF(PR_SCALE, struct uprof, pr_scale); + + OFF(RU_MINFLT, struct rusage, ru_minflt); + + OFF(PCB_HW, struct pcb, pcb_hw); + OFF(PCB_CONTEXT, struct pcb, pcb_context); + OFF(PCB_FP, struct pcb, pcb_fp); + OFF(PCB_ONFAULT, struct pcb, pcb_onfault); + OFF(PCB_ACCESSADDR, struct pcb, pcb_accessaddr); + + OFF(FPREG_FPR_REGS, struct fpreg, fpr_regs); + OFF(FPREG_FPR_CR, struct fpreg, fpr_cr); + + CONST1(B_READ); + CONST1(ENOENT); + CONST1(EFAULT); + CONST1(ENAMETOOLONG); + CONST1(MAXPATHLEN); + + /* Register offsets, for stack frames. */ + CONST1(FRAME_V0), + CONST1(FRAME_T0), + CONST1(FRAME_T1), + CONST1(FRAME_T2), + CONST1(FRAME_T3), + CONST1(FRAME_T4), + CONST1(FRAME_T5), + CONST1(FRAME_T6), + CONST1(FRAME_T7), + CONST1(FRAME_S0), + CONST1(FRAME_S1), + CONST1(FRAME_S2), + CONST1(FRAME_S3), + CONST1(FRAME_S4), + CONST1(FRAME_S5), + CONST1(FRAME_S6), + CONST1(FRAME_A3), + CONST1(FRAME_A4), + CONST1(FRAME_A5), + CONST1(FRAME_T8), + CONST1(FRAME_T9), + CONST1(FRAME_T10), + CONST1(FRAME_T11), + CONST1(FRAME_RA), + CONST1(FRAME_T12), + CONST1(FRAME_AT), + CONST1(FRAME_SP), + + CONST1(FRAME_SW_SIZE), + + CONST1(FRAME_PS), + CONST1(FRAME_PC), + CONST1(FRAME_GP), + CONST1(FRAME_A0), + CONST1(FRAME_A1), + CONST1(FRAME_A2), + + CONST1(FRAME_SIZE), + + /* bits of the PS register */ + CONST1(ALPHA_PSL_USERMODE); + CONST1(ALPHA_PSL_IPL_MASK); + CONST1(ALPHA_PSL_IPL_0); + CONST1(ALPHA_PSL_IPL_SOFT); + CONST1(ALPHA_PSL_IPL_HIGH); + + /* pte bits */ + CONST1(ALPHA_L1SHIFT); + CONST1(ALPHA_L2SHIFT); + CONST1(ALPHA_L3SHIFT); + CONST1(ALPHA_K1SEG_BASE); + CONST1(ALPHA_PTE_VALID); + CONST1(ALPHA_PTE_ASM); + CONST1(ALPHA_PTE_KR); + CONST1(ALPHA_PTE_KW); + + /* Kernel entries */ + CONST1(ALPHA_KENTRY_ARITH); + CONST1(ALPHA_KENTRY_MM); + + CONST1(ALPHA_KENTRY_IF); + CONST1(ALPHA_KENTRY_UNA); + + CONST1(VPTBASE); + + return (0); +} diff --git a/sys/alpha/alpha/gensetdefs.c b/sys/alpha/alpha/gensetdefs.c new file mode 100644 index 0000000..0e446345 --- /dev/null +++ b/sys/alpha/alpha/gensetdefs.c @@ -0,0 +1,313 @@ +/*- + * Copyright (c) 1997 John D. Polstra. + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id: gensetdefs.c,v 1.1 1997/05/21 23:21:25 jdp Exp $ + */ + +#include <sys/types.h> +#include <machine/elf.h> + +#include <err.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define HASHSIZE 1009u /* Number of hash chains. */ +#define PREFIX ".set." /* Section name prefix for linker sets. */ + +/* One entry in the hash table. */ +typedef struct hashent { + struct hashent *next; /* Next entry with the same hash. */ + char *name; /* Name of the linker set. */ + size_t size; /* Size in bytes. */ +} hashent; + +/* Allocate storage for "count" objects of type "type". */ +#define NEW(type, count) ((type *) xmalloc((count) * sizeof(type))) + +static hashent *hashtab[HASHSIZE]; /* Hash chain heads. */ + +static void enter(const char *, size_t); +static int enter_sets(const char *); +static unsigned int hash(const char *); +static hashent *merge(void); +static int my_byte_order(void); +static void *xmalloc(size_t); +static char *xstrdup(const char *); + +/* + * This is a special-purpose program to generate the linker set definitions + * needed when building an ELF kernel. Its arguments are the names of + * ELF object files. It scans the section names of the object files, + * building a table of those that begin with ".set.", which represent + * linker sets. Finally, for each set "foo" with "count" elements, it + * writes a line "DEFINE_SET(foo, count);" to the standard output. + */ +int +main(int argc, char **argv) +{ + int i; + int status = EXIT_SUCCESS; + hashent *list; + + for (i = 1; i < argc; i++) + if (enter_sets(argv[i]) == -1) + status = EXIT_FAILURE; + + list = merge(); + while (list != NULL) { + hashent *next; + + printf("DEFINE_SET(%s, %lu);\n", list->name, + (unsigned long) (list->size / sizeof (void *))); + next = list->next; + free(list->name); + free(list); + list = next; + } + + return (status); +} + +/* + * Enter the given string into the hash table, if it is not already there. + * Each hash chain is kept sorted, so that it will be easy to merge the + * chains to get a single sorted list. + */ +static void +enter(const char *name, size_t size) +{ + int c = 0; + hashent *entp; + hashent **linkp; + hashent *newp; + + linkp = &hashtab[hash(name) % HASHSIZE]; + while ((entp = *linkp) != NULL && (c = strcmp(name, entp->name)) > 0) + linkp = &entp->next; + + if (entp == NULL || c != 0) { /* Not found; create a new entry. */ + newp = NEW(hashent, 1); + newp->name = xstrdup(name); + newp->size = 0; + newp->next = entp; + *linkp = newp; + entp = newp; + } + + entp->size += size; +} + +/* + * Return a hash value for the given string. + */ +static unsigned int +hash(const char *s) +{ + unsigned char ch; + unsigned int h = 0; + + while((ch = *s) != '\0') { + h = 9*h + ch; + s++; + } + return (h); +} + +/* + * Enter the linker sets from the given ELF object file. Returns 0 on + * success, or -1 if an error occurred. + */ +static int +enter_sets(const char *filename) +{ + int i; + FILE *iop; + Elf64_Shdr *shdr; + char *shstr; + Elf64_Ehdr ehdr; + + if ((iop = fopen(filename, "rb")) == NULL) { + warn("%s", filename); + return (-1); + } + if (fread(&ehdr, sizeof ehdr, 1, iop) != 1 || + ehdr.e_ident[EI_MAG0] != ELFMAG0 || + ehdr.e_ident[EI_MAG1] != ELFMAG1 || + ehdr.e_ident[EI_MAG2] != ELFMAG2 || + ehdr.e_ident[EI_MAG3] != ELFMAG3) { + warnx("%s: not an ELF file", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) { + warnx("%s: unsupported ELF version", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_ident[EI_DATA] != my_byte_order()) { + warnx("%s: unsupported byte order", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_shoff == 0) { + warnx("%s: no section table", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_shstrndx == SHN_UNDEF) { + warnx("%s: no section name string table", filename); + fclose(iop); + return (-1); + } + + shdr = NEW(Elf64_Shdr, ehdr.e_shnum); + if (fseek(iop, ehdr.e_shoff, SEEK_SET) == -1) { + warn("%s", filename); + free(shdr); + fclose(iop); + return (-1); + } + if (fread(shdr, sizeof *shdr, ehdr.e_shnum, iop) != ehdr.e_shnum) { + warnx("%s: truncated section table", filename); + free(shdr); + fclose(iop); + return (-1); + } + + shstr = NEW(char, shdr[ehdr.e_shstrndx].sh_size); + if (fseek(iop, shdr[ehdr.e_shstrndx].sh_offset, SEEK_SET) == -1) { + warn("%s", filename); + free(shstr); + free(shdr); + fclose(iop); + return (-1); + } + if (fread(shstr, sizeof *shstr, shdr[ehdr.e_shstrndx].sh_size, iop) != + shdr[ehdr.e_shstrndx].sh_size) { + warnx("%s: truncated section name string table", filename); + free(shstr); + free(shdr); + fclose(iop); + return (-1); + } + + for (i = 1; i < ehdr.e_shnum; i++) { + const char *name = shstr + shdr[i].sh_name; + + if (strncmp(name, PREFIX, sizeof (PREFIX) - 1) == 0) + enter(name + sizeof (PREFIX) - 1, shdr[i].sh_size); + } + + free(shstr); + free(shdr); + fclose(iop); + return (0); +} + +/* + * Destructively merge all the sorted hash chains into a single sorted + * list, and return a pointer to its first element. + */ +static hashent * +merge(void) +{ + unsigned int numchains = HASHSIZE; + + while (numchains > 1) { /* More merging to do. */ + unsigned int lo = 0; + /* + * Merge chains pairwise from the outside in, halving the + * number of chains. + */ + while (numchains - lo >= 2) { + hashent **linkp = &hashtab[lo]; + hashent *l1 = hashtab[lo++]; + hashent *l2 = hashtab[--numchains]; + + while (l1 != NULL && l2 != NULL) { + if (strcmp(l1->name, l2->name) < 0) { + *linkp = l1; + linkp = &l1->next; + l1 = l1->next; + } else { + *linkp = l2; + linkp = &l2->next; + l2 = l2->next; + } + } + *linkp = l1==NULL ? l2 : l1; + } + } + + return (hashtab[0]); +} + +/* + * Determine the host byte order. + */ +static int +my_byte_order(void) +{ + static unsigned short s = 0xbbaa; + int byte0; + + byte0 = *(unsigned char *)&s; + if (byte0 == 0xaa) + return (ELFDATA2LSB); + else if (byte0 == 0xbb) + return (ELFDATA2MSB); + else + return (ELFDATANONE); +} + +/* + * Allocate a chunk of memory and return a pointer to it. Die if the + * malloc fails. + */ +static void * +xmalloc(size_t size) +{ + void *p; + + p = malloc(size); + if (p == NULL) + err(EXIT_FAILURE, "malloc"); + return (p); +} + +/* + * Duplicate a string and return a pointer to the copy. Die if there is + * not enough memory. + */ +static char * +xstrdup(const char *s) +{ + int size; + + size = strlen(s) + 1; + return (memcpy(xmalloc(size), s, size)); +} diff --git a/sys/alpha/alpha/in_cksum.c b/sys/alpha/alpha/in_cksum.c new file mode 100644 index 0000000..cbebc65 --- /dev/null +++ b/sys/alpha/alpha/in_cksum.c @@ -0,0 +1,216 @@ +/* $Id$ */ +/* $NetBSD: in_cksum.c,v 1.7 1997/09/02 13:18:15 thorpej Exp $ */ + +/* + * Copyright (c) 1988, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1996 + * Matt Thomas <matt@3am-software.com> + * + * 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. + * + * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/systm.h> +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <machine/in_cksum.h> + +/* + * Checksum routine for Internet Protocol family headers + * (Portable Alpha version). + * + * This routine is very heavily used in the network + * code and should be modified for each CPU to be as fast as possible. + */ + +#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) +#define REDUCE32 \ + { \ + q_util.q = sum; \ + sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + } +#define REDUCE16 \ + { \ + q_util.q = sum; \ + l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + sum = l_util.s[0] + l_util.s[1]; \ + ADDCARRY(sum); \ + } + +static const u_int32_t in_masks[] = { + /*0 bytes*/ /*1 byte*/ /*2 bytes*/ /*3 bytes*/ + 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */ + 0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */ + 0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000, /* offset 2 */ + 0x00000000, 0xFF000000, 0xFF000000, 0xFF000000, /* offset 3 */ +}; + +union l_util { + u_int16_t s[2]; + u_int32_t l; +}; +union q_util { + u_int16_t s[4]; + u_int32_t l[2]; + u_int64_t q; +}; + +u_int64_t in_cksumdata __P((caddr_t buf, int len)); + +u_int64_t +in_cksumdata(buf, len) + register caddr_t buf; + register int len; +{ + const u_int32_t *lw = (u_int32_t *) buf; + u_int64_t sum = 0; + u_int64_t prefilled; + int offset; + union q_util q_util; + + if ((3 & (long) lw) == 0 && len == 20) { + sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4]; + REDUCE32; + return sum; + } + + if ((offset = 3 & (long) lw) != 0) { + const u_int32_t *masks = in_masks + (offset << 2); + lw = (u_int32_t *) (((long) lw) - offset); + sum = *lw++ & masks[len >= 3 ? 3 : len]; + len -= 4 - offset; + if (len <= 0) { + REDUCE32; + return sum; + } + } +#if 0 + /* + * Force to cache line boundary. + */ + offset = 32 - (0x1f & (long) lw); + if (offset < 32 && len > offset) { + len -= offset; + if (4 & offset) { + sum += (u_int64_t) lw[0]; + lw += 1; + } + if (8 & offset) { + sum += (u_int64_t) lw[0] + lw[1]; + lw += 2; + } + if (16 & offset) { + sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3]; + lw += 4; + } + } +#endif + /* + * access prefilling to start load of next cache line. + * then add current cache line + * save result of prefilling for loop iteration. + */ + prefilled = lw[0]; + while ((len -= 32) >= 4) { + u_int64_t prefilling = lw[8]; + sum += prefilled + lw[1] + lw[2] + lw[3] + + lw[4] + lw[5] + lw[6] + lw[7]; + lw += 8; + prefilled = prefilling; + } + if (len >= 0) { + sum += prefilled + lw[1] + lw[2] + lw[3] + + lw[4] + lw[5] + lw[6] + lw[7]; + lw += 8; + } else { + len += 32; + } + while ((len -= 16) >= 0) { + sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3]; + lw += 4; + } + len += 16; + while ((len -= 4) >= 0) { + sum += (u_int64_t) *lw++; + } + len += 4; + if (len > 0) + sum += (u_int64_t) (in_masks[len] & *lw); + REDUCE32; + return sum; +} + +int +in_cksum(m, len) + register struct mbuf *m; + register int len; +{ + register u_int64_t sum = 0; + register int mlen = 0; + register int clen = 0; + register caddr_t addr; + union q_util q_util; + union l_util l_util; + + for (; m && len; m = m->m_next) { + if (m->m_len == 0) + continue; + mlen = m->m_len; + if (len < mlen) + mlen = len; + addr = mtod(m, caddr_t); + if ((clen ^ (long) addr) & 1) + sum += in_cksumdata(addr, mlen) << 8; + else + sum += in_cksumdata(addr, mlen); + + clen += mlen; + len -= mlen; + } + REDUCE16; + return (~sum & 0xffff); +} + +u_int in_cksum_hdr(ip) + const struct ip *ip; +{ + u_int64_t sum = in_cksumdata((caddr_t) ip, sizeof(struct ip)); + union q_util q_util; + union l_util l_util; + REDUCE16; + return (~sum & 0xffff); +} + diff --git a/sys/alpha/alpha/interrupt.c b/sys/alpha/alpha/interrupt.c new file mode 100644 index 0000000..c4945a1 --- /dev/null +++ b/sys/alpha/alpha/interrupt.c @@ -0,0 +1,264 @@ +/* $Id */ +/* $NetBSD: interrupt.c,v 1.23 1998/02/24 07:38:01 thorpej Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Authors: Keith Bostic, Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * Additional Copyright (c) 1997 by Matthew Jacob for NASA/Ames Research Center. + * Redistribute and modify at will, leaving only this additional copyright + * notice. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +/* __KERNEL_RCSID(0, "$NetBSD: interrupt.c,v 1.23 1998/02/24 07:38:01 thorpej Exp $");*/ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/vmmeter.h> + +#include <machine/reg.h> +#include <machine/frame.h> +#include <machine/cpuconf.h> + +#if 0 +#ifdef EVCNT_COUNTERS +#include <sys/device.h> +struct evcnt clock_intr_evcnt; /* event counter for clock intrs. */ +#else +#include <machine/intrcnt.h> +#endif +#endif + +volatile int mc_expected, mc_received; + +void +interrupt(a0, a1, a2, framep) + unsigned long a0, a1, a2; + struct trapframe *framep; +{ + + { + struct proc* p = curproc; + if (!p) p = &proc0; + if ((caddr_t) framep < (caddr_t) p->p_addr + 1024) + printf("possible stack overflow\n"); + } + + switch (a0) { + case ALPHA_INTR_XPROC: /* interprocessor interrupt */ + printf("interprocessor interrupt!\n"); + break; + + case ALPHA_INTR_CLOCK: /* clock interrupt */ + cnt.v_intr++; +#if 0 +#ifdef EVCNT_COUNTERS + clock_intr_evcnt.ev_count++; +#else + intrcnt[INTRCNT_CLOCK]++; +#endif +#endif + if (platform.clockintr) + (*platform.clockintr)(framep); + break; + + case ALPHA_INTR_ERROR: /* Machine Check or Correctable Error */ + a0 = alpha_pal_rdmces(); + if (platform.mcheck_handler) + (*platform.mcheck_handler)(a0, framep, a1, a2); + else + machine_check(a0, framep, a1, a2); + break; + + case ALPHA_INTR_DEVICE: /* I/O device interrupt */ + cnt.v_intr++; + if (platform.iointr) + (*platform.iointr)(framep, a1); + break; + + case ALPHA_INTR_PERF: /* interprocessor interrupt */ + printf("performance interrupt!\n"); + break; + + case ALPHA_INTR_PASSIVE: +#if 0 + printf("passive release interrupt vec 0x%lx (ignoring)\n", a1); +#endif + break; + + default: + panic("unexpected interrupt: type 0x%lx vec 0x%lx a2 0x%lx\n", + a0, a1, a2); + /* NOTREACHED */ + } +} + +void +set_iointr(niointr) + void (*niointr) __P((void *, unsigned long)); +{ + if (platform.iointr) + panic("set iointr twice"); + platform.iointr = niointr; +} + + +void +machine_check(mces, framep, vector, param) + unsigned long mces; + struct trapframe *framep; + unsigned long vector, param; +{ + const char *type; + + /* Make sure it's an error we know about. */ + if ((mces & (ALPHA_MCES_MIP|ALPHA_MCES_SCE|ALPHA_MCES_PCE)) == 0) { + type = "fatal machine check or error (unknown type)"; + goto fatal; + } + + /* Machine checks. */ + if (mces & ALPHA_MCES_MIP) { + /* If we weren't expecting it, then we punt. */ + if (!mc_expected) { + type = "unexpected machine check"; + goto fatal; + } + + mc_expected = 0; + mc_received = 1; + } + + /* System correctable errors. */ + if (mces & ALPHA_MCES_SCE) + printf("Warning: received system correctable error.\n"); + + /* Processor correctable errors. */ + if (mces & ALPHA_MCES_PCE) + printf("Warning: received processor correctable error.\n"); + + /* Clear pending machine checks and correctable errors */ + alpha_pal_wrmces(mces); + return; + +fatal: + /* Clear pending machine checks and correctable errors */ + alpha_pal_wrmces(mces); + + printf("\n"); + printf("%s:\n", type); + printf("\n"); + printf(" mces = 0x%lx\n", mces); + printf(" vector = 0x%lx\n", vector); + printf(" param = 0x%lx\n", param); + printf(" pc = 0x%lx\n", framep->tf_regs[FRAME_PC]); + printf(" ra = 0x%lx\n", framep->tf_regs[FRAME_RA]); + printf(" curproc = %p\n", curproc); + if (curproc != NULL) + printf(" pid = %d, comm = %s\n", curproc->p_pid, + curproc->p_comm); + printf("\n"); + panic("machine check"); +} + +int +badaddr(addr, size) + void *addr; + size_t size; +{ + return(badaddr_read(addr, size, NULL)); +} + +int +badaddr_read(addr, size, rptr) + void *addr; + size_t size; + void *rptr; +{ + long rcpt; + + /* Get rid of any stale machine checks that have been waiting. */ + alpha_pal_draina(); + + /* Tell the trap code to expect a machine check. */ + mc_received = 0; + mc_expected = 1; + + /* Read from the test address, and make sure the read happens. */ + alpha_mb(); + switch (size) { + case sizeof (u_int8_t): + rcpt = *(volatile u_int8_t *)addr; + break; + + case sizeof (u_int16_t): + rcpt = *(volatile u_int16_t *)addr; + break; + + case sizeof (u_int32_t): + rcpt = *(volatile u_int32_t *)addr; + break; + + case sizeof (u_int64_t): + rcpt = *(volatile u_int64_t *)addr; + break; + + default: + panic("badaddr: invalid size (%ld)\n", size); + } + alpha_mb(); + + /* Make sure we took the machine check, if we caused one. */ + alpha_pal_draina(); + + /* disallow further machine checks */ + mc_expected = 0; + + if (rptr) { + switch (size) { + case sizeof (u_int8_t): + *(volatile u_int8_t *)rptr = rcpt; + break; + + case sizeof (u_int16_t): + *(volatile u_int16_t *)rptr = rcpt; + break; + + case sizeof (u_int32_t): + *(volatile u_int32_t *)rptr = rcpt; + break; + + case sizeof (u_int64_t): + *(volatile u_int64_t *)rptr = rcpt; + break; + } + } + /* Return non-zero (i.e. true) if it's a bad address. */ + return (mc_received); +} diff --git a/sys/alpha/alpha/ipl_funcs.c b/sys/alpha/alpha/ipl_funcs.c new file mode 100644 index 0000000..61ebc4b --- /dev/null +++ b/sys/alpha/alpha/ipl_funcs.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/systm.h> +#include <machine/ipl.h> +#include <machine/cpu.h> +#include <net/netisr.h> + +unsigned int netisr; + +void +do_sir() +{ +} + +void (*netisrs[32]) __P((void)); + +u_int64_t ssir; + +void +spl0() +{ + /* XXX soft interrupts here */ + + alpha_pal_swpipl(ALPHA_PSL_IPL_0); +} diff --git a/sys/alpha/alpha/mem.c b/sys/alpha/alpha/mem.c new file mode 100644 index 0000000..baf0ae5 --- /dev/null +++ b/sys/alpha/alpha/mem.c @@ -0,0 +1,443 @@ +/*- + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990 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, and code derived from software contributed to + * Berkeley by William Jolitz. + * + * 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: mem.c 1.13 89/10/08$ + * from: @(#)mem.c 7.2 (Berkeley) 5/9/91 + * $Id: mem.c,v 1.50 1998/03/12 09:14:18 bde Exp $ + */ + +/* + * Memory special file + */ + +#include "opt_devfs.h" + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/buf.h> +#ifdef DEVFS +#include <sys/devfsext.h> +#endif /* DEVFS */ +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/uio.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/msgbuf.h> + +#include <machine/frame.h> +/* #include <machine/random.h>*/ +#include <machine/psl.h> +#ifdef PERFMON +#include <machine/perfmon.h> +#endif + +#include <vm/vm.h> +#include <vm/vm_prot.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> + +static caddr_t zeropage; + +static d_open_t mmopen; +static d_close_t mmclose; +static d_read_t mmrw; +static d_ioctl_t mmioctl; +static d_mmap_t memmmap; +static d_poll_t mmpoll; + +#define CDEV_MAJOR 2 +static struct cdevsw mem_cdevsw = + { mmopen, mmclose, mmrw, mmrw, /*2*/ + mmioctl, nullstop, nullreset, nodevtotty,/* memory */ + mmpoll, memmmap, NULL, "mem", NULL, -1 }; + +static caddr_t zbuf; + +#ifdef DEVFS +static void *mem_devfs_token; +static void *kmem_devfs_token; +static void *null_devfs_token; +static void *random_devfs_token; +static void *urandom_devfs_token; +static void *zero_devfs_token; +static void *io_devfs_token; +#ifdef PERFMON +static void *perfmon_devfs_token; +#endif + +static void memdevfs_init __P((void)); + +static void +memdevfs_init() +{ + mem_devfs_token = + devfs_add_devswf(&mem_cdevsw, 0, DV_CHR, + UID_ROOT, GID_KMEM, 0640, "mem"); + kmem_devfs_token = + devfs_add_devswf(&mem_cdevsw, 1, DV_CHR, + UID_ROOT, GID_KMEM, 0640, "kmem"); + null_devfs_token = + devfs_add_devswf(&mem_cdevsw, 2, DV_CHR, + UID_ROOT, GID_WHEEL, 0666, "null"); + random_devfs_token = + devfs_add_devswf(&mem_cdevsw, 3, DV_CHR, + UID_ROOT, GID_WHEEL, 0644, "random"); + urandom_devfs_token = + devfs_add_devswf(&mem_cdevsw, 4, DV_CHR, + UID_ROOT, GID_WHEEL, 0644, "urandom"); + zero_devfs_token = + devfs_add_devswf(&mem_cdevsw, 12, DV_CHR, + UID_ROOT, GID_WHEEL, 0666, "zero"); +#ifdef PERFMON + perfmon_devfs_token = + devfs_add_devswf(&mem_cdevsw, 32, DV_CHR, + UID_ROOT, GID_KMEM, 0640, "perfmon"); +#endif /* PERFMON */ +} +#endif /* DEVFS */ + +static int +mmclose(dev, flags, fmt, p) + dev_t dev; + int flags; + int fmt; + struct proc *p; +{ + switch (minor(dev)) { +#ifdef PERFMON + case 32: + return perfmon_close(dev, flags, fmt, p); +#endif + default: + break; + } + return(0); +} + +static int +mmopen(dev, flags, fmt, p) + dev_t dev; + int flags; + int fmt; + struct proc *p; +{ + int error; + + switch (minor(dev)) { + case 32: +#ifdef PERFMON + return perfmon_open(dev, flags, fmt, p); +#else + return ENODEV; +#endif + default: + break; + } + return(0); +} + +/*ARGSUSED*/ +int +mmrw(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + register vm_offset_t o, v; + register int c; + register struct iovec *iov; + int error = 0, rw; + + while (uio->uio_resid > 0 && !error) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("mmrw"); + continue; + } + switch (minor(dev)) { + +/* minor device 0 is physical memory */ + case 0: + v = uio->uio_offset; +kmemphys: + if (v >= ALPHA_K0SEG_TO_PHYS((vm_offset_t)msgbufp)) { + if (msgbufmapped == 0) { + printf("Message Buf not Mapped\n"); + error = EFAULT; + break; + } + } + + /* Allow reads only in RAM. */ + rw = (uio->uio_rw == UIO_READ) ? VM_PROT_READ : VM_PROT_WRITE; + if ((alpha_pa_access(v) & rw) != rw) { + error = EFAULT; + break; + } + + o = uio->uio_offset & PAGE_MASK; + c = min(uio->uio_resid, (int)(PAGE_SIZE - o)); + error = + uiomove((caddr_t)ALPHA_PHYS_TO_K0SEG(v), c, uio); + break; + +/* minor device 1 is kernel memory */ + case 1: + v = uio->uio_offset; + + if (v >= ALPHA_K0SEG_BASE && v <= ALPHA_K0SEG_END) { + v = ALPHA_K0SEG_TO_PHYS(v); + goto kmemphys; + } + + c = min(iov->iov_len, MAXPHYS); +#if defined(UVM) + if (!uvm_kernacc((caddr_t)v, c, + uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) + return (EFAULT); +#else + if (!kernacc((caddr_t)v, c, + uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) + return (EFAULT); +#endif + error = uiomove((caddr_t)v, c, uio); + break; + +/* minor device 2 is EOF/rathole */ + case 2: + if (uio->uio_rw == UIO_WRITE) + uio->uio_resid = 0; + return (0); + +/* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ + case 12: + if (uio->uio_rw == UIO_WRITE) { + uio->uio_resid = 0; + return (0); + } + /* + * On the first call, allocate and zero a page + * of memory for use with /dev/zero. + */ + if (zeropage == NULL) { + zeropage = (caddr_t) + malloc(PAGE_SIZE, M_TEMP, M_WAITOK); + bzero(zeropage, PAGE_SIZE); + } + c = min(iov->iov_len, PAGE_SIZE); + error = uiomove(zeropage, c, uio); + break; + + default: + return (ENXIO); + } + } + return (error); +} + +/*******************************************************\ +* allow user processes to MMAP some memory sections * +* instead of going through read/write * +\*******************************************************/ +static int +memmmap(dev_t dev, int offset, int prot) +{ + /* + * /dev/mem is the only one that makes sense through this + * interface. For /dev/kmem any physaddr we return here + * could be transient and hence incorrect or invalid at + * a later time. /dev/null just doesn't make any sense + * and /dev/zero is a hack that is handled via the default + * pager in mmap(). + */ + if (minor(dev) != 0) + return (-1); + + /* + * Allow access only in RAM. + */ + if ((prot & alpha_pa_access(atop((vm_offset_t)offset))) != prot) + return (-1); + return (alpha_btop(offset)); +} + +/* + * Allow userland to select which interrupts will be used in the muck + * gathering business. + */ +static int +mmioctl(dev, cmd, cmdarg, flags, p) + dev_t dev; + u_long cmd; + caddr_t cmdarg; + int flags; + struct proc *p; +{ + static u_int16_t interrupt_allowed = 0; + u_int16_t interrupt_mask; + int error; + + switch(minor(dev)) { + case 3: + case 4: + break; + +#ifdef PERFMON + case 32: + return perfmon_ioctl(dev, cmd, cmdarg, flags, p); +#endif + default: + return ENODEV; + } + + if (*(u_int16_t *)cmdarg >= 16) + return (EINVAL); + +#if 0 + /* Only root can do this */ + error = suser(p->p_ucred, &p->p_acflag); + if (error) { + return (error); + } + interrupt_mask = 1 << *(u_int16_t *)cmdarg; + + switch (cmd) { + + case MEM_SETIRQ: + if (!(interrupt_allowed & interrupt_mask)) { + disable_intr(); + interrupt_allowed |= interrupt_mask; + sec_intr_handler[*(u_int16_t *)cmdarg] = + intr_handler[*(u_int16_t *)cmdarg]; + intr_handler[*(u_int16_t *)cmdarg] = + add_interrupt_randomness; + sec_intr_unit[*(u_int16_t *)cmdarg] = + intr_unit[*(u_int16_t *)cmdarg]; + intr_unit[*(u_int16_t *)cmdarg] = + *(u_int16_t *)cmdarg; + enable_intr(); + } + else return (EPERM); + break; + + case MEM_CLEARIRQ: + if (interrupt_allowed & interrupt_mask) { + disable_intr(); + interrupt_allowed &= ~(interrupt_mask); + intr_handler[*(u_int16_t *)cmdarg] = + sec_intr_handler[*(u_int16_t *)cmdarg]; + intr_unit[*(u_int16_t *)cmdarg] = + sec_intr_unit[*(u_int16_t *)cmdarg]; + enable_intr(); + } + else return (EPERM); + break; + + case MEM_RETURNIRQ: + *(u_int16_t *)cmdarg = interrupt_allowed; + break; + + default: + return (ENOTTY); + } +#endif + return (0); +} + +int +mmpoll(dev, events, p) + dev_t dev; + int events; + struct proc *p; +{ + switch (minor(dev)) { + case 3: /* /dev/random */ + /* return random_poll(dev, events, p);*/ + case 4: /* /dev/urandom */ + default: + return seltrue(dev, events, p); + } +} + +/* + * Routine that identifies /dev/mem and /dev/kmem. + * + * A minimal stub routine can always return 0. + */ +int +iskmemdev(dev) + dev_t dev; +{ + + return ((major(dev) == mem_cdevsw.d_maj) + && (minor(dev) == 0 || minor(dev) == 1)); +} + +int +iszerodev(dev) + dev_t dev; +{ + return ((major(dev) == mem_cdevsw.d_maj) + && minor(dev) == 12); +} + + + +static int mem_devsw_installed; + +static void +mem_drvinit(void *unused) +{ + dev_t dev; + + if( ! mem_devsw_installed ) { + dev = makedev(CDEV_MAJOR, 0); + cdevsw_add(&dev,&mem_cdevsw, NULL); + mem_devsw_installed = 1; +#ifdef DEVFS + memdevfs_init(); +#endif + } +} + +SYSINIT(memdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mem_drvinit,NULL) + diff --git a/sys/alpha/alpha/pal.s b/sys/alpha/alpha/pal.s new file mode 100644 index 0000000..36ecdfb --- /dev/null +++ b/sys/alpha/alpha/pal.s @@ -0,0 +1,350 @@ +/* $NetBSD: pal.s,v 1.12 1998/02/27 03:44:53 thorpej Exp $ */ + +/* + * Copyright (c) 1994, 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * The various OSF PALcode routines. + * + * The following code is originally derived from pages: (I) 6-5 - (I) 6-7 + * and (III) 2-1 - (III) 2-25 of "Alpha Architecture Reference Manual" by + * Richard L. Sites. + * + * Updates taken from pages: (II-B) 2-1 - (II-B) 2-33 of "Alpha AXP + * Architecture Reference Manual, Second Edition" by Richard L. Sites + * and Richard T. Witek. + */ + +#include <machine/asm.h> + +__KERNEL_RCSID(1, "$NetBSD: pal.s,v 1.12 1998/02/27 03:44:53 thorpej Exp $"); + +inc2: .stabs __FILE__,132,0,0,inc2; .loc 1 __LINE__ +/* + * alpha_rpcc: read process cycle counter (XXX INSTRUCTION, NOT PALcode OP) + */ + .text +LEAF(alpha_rpcc,1) + rpcc v0 + RET + END(alpha_rpcc) + +/* + * alpha_mb: memory barrier (XXX INSTRUCTION, NOT PALcode OP) + */ + .text +LEAF(alpha_mb,0) + mb + RET + END(alpha_mb) + +/* + * alpha_wmb: write memory barrier (XXX INSTRUCTION, NOT PALcode OP) + */ + .text +LEAF(alpha_wmb,0) + /* wmb XXX */ + mb /* XXX */ + RET + END(alpha_wmb) + +/* + * alpha_amask: read architecture features (XXX INSTRUCTION, NOT PALcode OP) + * + * Arguments: + * a0 bitmask of features to test + * + * Returns: + * v0 bitmask - bit is _cleared_ if feature is supported + */ + .text +LEAF(alpha_amask,1) + amask a0, v0 + RET + END(alpha_amask) + +/* + * alpha_implver: read implementation version (XXX INSTRUCTION, NOT PALcode OP) + * + * Returns: + * v0 implementation version - see <machine/alpha_cpu.h> + */ + .text +LEAF(alpha_implver,0) +#if 0 + implver 0x1, v0 +#else + .long 0x47e03d80 /* XXX gas(1) does the Wrong Thing */ +#endif + RET + END(alpha_implver) + +/* + * alpha_pal_imb: I-Stream memory barrier. [UNPRIVILEGED] + * (Makes instruction stream coherent with data stream.) + */ + .text +LEAF(alpha_pal_imb,0) + call_pal PAL_imb + RET + END(alpha_pal_imb) + +/* + * alpha_pal_cflush: Cache flush [PRIVILEGED] + * + * Flush the entire physical page specified by the PFN specified in + * a0 from any data caches associated with the current processor. + * + * Arguments: + * a0 page frame number of page to flush + */ + .text +LEAF(alpha_pal_cflush,1) + call_pal PAL_cflush + RET + END(alpha_pal_cflush) + +/* + * alpha_pal_draina: Drain aborts. [PRIVILEGED] + */ + .text +LEAF(alpha_pal_draina,0) + call_pal PAL_draina + RET + END(alpha_pal_draina) + +/* + * alpha_pal_halt: Halt the processor. [PRIVILEGED] + */ + .text +LEAF(alpha_pal_halt,0) + call_pal PAL_halt + br zero,alpha_pal_halt /* Just in case */ + RET + END(alpha_pal_halt) + +/* + * alpha_pal_rdmces: Read MCES processor register. [PRIVILEGED] + * + * Return: + * v0 current MCES value + */ + .text +LEAF(alpha_pal_rdmces,1) + call_pal PAL_OSF1_rdmces + RET + END(alpha_pal_rdmces) + +/* + * alpha_pal_rdps: Read processor status. [PRIVILEGED] + * + * Return: + * v0 current PS value + */ + .text +LEAF(alpha_pal_rdps,0) + call_pal PAL_OSF1_rdps + RET + END(alpha_pal_rdps) + +/* + * alpha_pal_rdusp: Read user stack pointer. [PRIVILEGED] + * + * Return: + * v0 current user stack pointer + */ + .text +LEAF(alpha_pal_rdusp,0) + call_pal PAL_OSF1_rdusp + RET + END(alpha_pal_rdusp) + +/* + * alpha_pal_rdval: Read system value. [PRIVILEGED] + * + * Returns the sysvalue in v0, allowing access to a 64-bit + * per-processor value for use by the operating system. + * + * Return: + * v0 sysvalue + */ + .text +LEAF(alpha_pal_rdval,0) + call_pal PAL_OSF1_rdval + RET + END(alpha_pal_rdval) + +/* + * alpha_pal_swpipl: Swap Interrupt priority level. [PRIVILEGED] + * _alpha_pal_swpipl: Same, from profiling code. [PRIVILEGED] + * + * Arguments: + * a0 new IPL + * + * Return: + * v0 old IPL + */ + .text +LEAF(alpha_pal_swpipl,1) + call_pal PAL_OSF1_swpipl + RET + END(alpha_pal_swpipl) + +LEAF_NOPROFILE(_alpha_pal_swpipl,1) + call_pal PAL_OSF1_swpipl + RET + END(_alpha_pal_swpipl) + +/* + * alpha_pal_tbi: Translation buffer invalidate. [PRIVILEGED] + * + * Arguments: + * a0 operation selector + * a1 address to operate on (if necessary) + */ + .text +LEAF(alpha_pal_tbi,2) + call_pal PAL_OSF1_tbi + RET + END(alpha_pal_tbi) + +/* + * alpha_pal_whami: Who am I? [PRIVILEGED] + * + * Return: + * v0 processor number + */ + .text +LEAF(alpha_pal_whami,0) + call_pal PAL_OSF1_whami + RET + END(alpha_pal_whami) + +/* + * alpha_pal_wrent: Write system entry address. [PRIVILEGED] + * + * Arguments: + * a0 new vector + * a1 vector selector + */ + .text +LEAF(alpha_pal_wrent,2) + call_pal PAL_OSF1_wrent + RET + END(alpha_pal_wrent) + +/* + * alpha_pal_wrfen: Write floating-point enable. [PRIVILEGED] + * + * Arguments: + * a0 new enable value (val & 0x1 -> enable). + */ + .text +LEAF(alpha_pal_wrfen,1) + call_pal PAL_OSF1_wrfen + RET + END(alpha_pal_wrfen) + +/* + * alpha_pal_wripir: Write interprocessor interrupt request. [PRIVILEGED] + * + * Generate an interprocessor interrupt on the processor specified by + * processor number in a0. + * + * Arguments: + * a0 processor to interrupt + */ + .text +LEAF(alpha_pal_wripir,1) + call_pal PAL_ipir + RET + END(alpha_pal_wripir) + +/* + * alpha_pal_wrusp: Write user stack pointer. [PRIVILEGED] + * + * Arguments: + * a0 new user stack pointer + */ + .text +LEAF(alpha_pal_wrusp,1) + call_pal PAL_OSF1_wrusp + RET + END(alpha_pal_wrusp) + +/* + * alpha_pal_wrvptptr: Write virtual page table pointer. [PRIVILEGED] + * + * Arguments: + * a0 new virtual page table pointer + */ + .text +LEAF(alpha_pal_wrvptptr,1) + call_pal PAL_OSF1_wrvptptr + RET + END(alpha_pal_wrvptptr) + +/* + * alpha_pal_wrmces: Write MCES processor register. [PRIVILEGED] + * + * Arguments: + * a0 value to write to MCES + */ + .text +LEAF(alpha_pal_wrmces,1) + call_pal PAL_OSF1_wrmces + RET + END(alpha_pal_wrmces) + +/* + * alpha_pal_wrval: Write system value. [PRIVILEGED] + * + * Write the value passed in a0 to this processor's sysvalue. + * + * Arguments: + * a0 value to write to sysvalue + */ +LEAF(alpha_pal_wrval,1) + call_pal PAL_OSF1_wrval + RET + END(alpha_pal_wrval) + +/* + * alpha_pal_swpctx: Swap context. [PRIVILEGED] + * + * Switch to a new process context. + * + * Arguments: + * a0 physical address of hardware PCB describing context + * + * Returns: + * v0 physical address of hardware PCB describing previous context + */ +LEAF(alpha_pal_swpctx,1) + call_pal PAL_OSF1_swpctx + RET + END(alpha_pal_swpctx) diff --git a/sys/alpha/alpha/pmap.c b/sys/alpha/alpha/pmap.c new file mode 100644 index 0000000..54f8633 --- /dev/null +++ b/sys/alpha/alpha/pmap.c @@ -0,0 +1,3081 @@ +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * Copyright (c) 1994 John S. Dyson + * All rights reserved. + * Copyright (c) 1994 David Greenman + * All rights reserved. + * Copyright (c) 1998 Doug Rabson + * 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 and William Jolitz of UUNET Technologies Inc. + * + * 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: @(#)pmap.c 7.7 (Berkeley) 5/12/91 + * from: i386 Id: pmap.c,v 1.193 1998/04/19 15:22:48 bde Exp + * with some ideas from NetBSD's alpha pmap + * $Id$ + */ + +/* + * Manages physical address maps. + * + * In addition to hardware address maps, this + * module is called upon to provide software-use-only + * maps which may or may not be stored in the same + * form as hardware maps. These pseudo-maps are + * used to store intermediate results from copy + * operations to and from address spaces. + * + * Since the information managed by this module is + * also stored by the logical address mapping module, + * this module may throw away valid virtual-to-physical + * mappings at almost any time. However, invalidations + * of virtual-to-physical mappings must be done as + * requested. + * + * In order to cope with hardware architectures which + * make virtual-to-physical map invalidates expensive, + * this module may delay invalidate or reduced protection + * operations until such time as they are actually + * necessary. This module is given full information as + * to which processors are currently using which maps, + * and to when physical maps must be made correct. + */ + +/* + * Notes for alpha pmap. + * + * On alpha, pm_pdeobj will hold lev1, lev2 and lev3 page tables. + * Indices from 0 to NUSERLEV3MAPS-1 will map user lev3 page tables, + * indices from NUSERLEV3MAPS to NUSERLEV3MAPS+NUSERLEV2MAPS-1 will + * map user lev2 page tables and index NUSERLEV3MAPS+NUSERLEV2MAPS + * will map the lev1 page table. The lev1 table will self map at + * address VADDR(PTLEV1I,0,0). + * + * The vm_object kptobj holds the kernel page tables on i386 (62 or 63 + * of them, depending on whether the system is SMP). On alpha, kptobj + * will hold the lev3 and lev2 page tables for K1SEG. Indices 0 to + * NKLEV3MAPS-1 will map kernel lev3 page tables and indices + * NKLEV3MAPS to NKLEV3MAPS+NKLEV2MAPS will map lev2 page tables. (XXX + * should the kernel Lev1map be inserted into this object?). + * + * pvtmmap is not needed for alpha since K0SEG maps all of physical + * memory. CADDR1 and CADDR2 are not needed for the same reason. The + * only places outside pmap and machdep which use CADDR1 are xxdump + * routines which use them for dumping physical pages. + * + * + * alpha virtual memory map: + * + * + * Address Lev1 index + * + * --------------------------------- + * 0000000000000000 | | 0 + * | | + * | | + * | | + * | | + * --- --- + * User space (USEG) + * --- --- + * | | + * | | + * | | + * | | + * 000003ffffffffff | | 511=UMAXLEV1I + * --------------------------------- + * fffffc0000000000 | | 512=K0SEGLEV1I + * | Kernel code/data/bss | + * | | + * | | + * | | + * --- --- + * K0SEG + * --- --- + * | | + * | 1-1 physical/virtual | + * | | + * | | + * fffffdffffffffff | | + * --------------------------------- + * fffffe0000000000 | | 768=K1SEGLEV1I + * | Kernel dynamic data | + * | | + * | | + * | | + * --- --- + * K1SEG + * --- --- + * | | + * | mapped by ptes | + * | | + * | | + * fffffff7ffffffff | | + * --------------------------------- + * fffffffe00000000 | | 1023=PTLEV1I + * | PTmap (pte self map) | + * ffffffffffffffff | | + * --------------------------------- + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/msgbuf.h> +#include <sys/vmmeter.h> +#include <sys/mman.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_prot.h> +#include <sys/lock.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_object.h> +#include <vm/vm_extern.h> +#include <vm/vm_pageout.h> +#include <vm/vm_pager.h> +#include <vm/vm_zone.h> + +#include <sys/user.h> + +#include <machine/md_var.h> + +#ifndef PMAP_SHPGPERPROC +#define PMAP_SHPGPERPROC 200 +#endif + +#if defined(DIAGNOSTIC) +#define PMAP_DIAGNOSTIC +#endif + +#define MINPV 2048 + +#define PMAP_DIAGNOSTIC + +#if !defined(PMAP_DIAGNOSTIC) +#define PMAP_INLINE __inline +#else +#define PMAP_INLINE +#endif + +/* + * Some macros for manipulating virtual addresses + */ +#define ALPHA_L1SIZE (1L << ALPHA_L1SHIFT) +#define ALPHA_L2SIZE (1L << ALPHA_L2SHIFT) + +#define alpha_l1trunc(va) ((va) & (ALPHA_L1SIZE-1)) +#define alpha_l2trunc(va) ((va) & (ALPHA_L2SIZE-1)) + +/* + * Get PDEs and PTEs for user/kernel address space + */ +#define pmap_pte_w(pte) ((*(pte) & PG_W) != 0) +#define pmap_pte_managed(pte) ((*(pte) & PG_MANAGED) != 0) +#define pmap_pte_v(pte) ((*(pte) & PG_V) != 0) +#define pmap_pte_pa(pte) alpha_ptob(ALPHA_PTE_TO_PFN(*(pte))) +#define pmap_pte_prot(pte) (*(pte) & PG_PROT) + +#define pmap_pte_set_w(pte, v) ((v)?(*pte |= PG_W):(*pte &= ~PG_W)) +#define pmap_pte_set_prot(pte, v) ((*pte &= ~PG_PROT), (*pte |= (v))) + +/* + * Given a map and a machine independent protection code, + * convert to an alpha protection code. + */ +#define pte_prot(m, p) (protection_codes[m == pmap_kernel() ? 0 : 1][p]) +int protection_codes[2][8]; + +#define pa_index(pa) atop((pa) - vm_first_phys) +#define pa_to_pvh(pa) (&pv_table[pa_index(pa)]) + +/* + * Return non-zero if this pmap is currently active + */ +#define pmap_isactive(pmap) (pmap == kernel_pmap || \ + ALPHA_PTE_TO_PFN(pmap->pm_lev1[PTLEV1I]) == ALPHA_PTE_TO_PFN(PTlev1pte)) + +/* + * Extract level 1, 2 and 3 page table indices from a va + */ +#define PTMASK ((1 << ALPHA_PTSHIFT) - 1) + +#define pmap_lev1_index(va) (((va) >> ALPHA_L1SHIFT) & PTMASK) +#define pmap_lev2_index(va) (((va) >> ALPHA_L2SHIFT) & PTMASK) +#define pmap_lev3_index(va) (((va) >> ALPHA_L3SHIFT) & PTMASK) + +/* + * Given a physical address, construct a pte + */ +#define pmap_phys_to_pte(pa) ALPHA_PTE_FROM_PFN(alpha_btop(pa)) + +/* + * Given a page frame number, construct a k0seg va + */ +#define pmap_k0seg_to_pfn(va) alpha_btop(ALPHA_K0SEG_TO_PHYS(va)) + +/* + * Given a pte, construct a k0seg va + */ +#define pmap_k0seg_to_pte(va) ALPHA_PTE_FROM_PFN(pmap_k0seg_to_pfn(va)) + +/* + * Lev1map: + * + * Kernel level 1 page table. This maps all kernel level 2 + * page table pages, and is used as a template for all user + * pmap level 1 page tables. When a new user level 1 page + * table is allocated, all Lev1map PTEs for kernel addresses + * are copied to the new map. + * + * Lev2map: + * + * Initial set of kernel level 2 page table pages. These + * map the kernel level 3 page table pages. As kernel + * level 3 page table pages are added, more level 2 page + * table pages may be added to map them. These pages are + * never freed. + * + * Lev3map: + * + * Initial set of kernel level 3 page table pages. These + * map pages in K1SEG. More level 3 page table pages may + * be added at run-time if additional K1SEG address space + * is required. These pages are never freed. + * + * Lev2mapsize: + * + * Number of entries in the initial Lev2map. + * + * Lev3mapsize: + * + * Number of entries in the initial Lev3map. + * + * NOTE: When mappings are inserted into the kernel pmap, all + * level 2 and level 3 page table pages must already be allocated + * and mapped into the parent page table. + */ +pt_entry_t *Lev1map, *Lev2map, *Lev3map; +vm_size_t Lev2mapsize, Lev3mapsize; + +/* + * Statically allocated kernel pmap + */ +static struct pmap kernel_pmap_store; +pmap_t kernel_pmap; + +vm_offset_t avail_start; /* PA of first available physical page */ +vm_offset_t avail_end; /* PA of last available physical page */ +vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ +vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ +static boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */ +static vm_offset_t vm_first_phys; +static int pv_npg; + +static vm_object_t kptobj; + +static int nklev3, nklev2; +vm_offset_t kernel_vm_end; + +/* + * Data for the pv entry allocation mechanism + */ +static vm_zone_t pvzone; +static struct vm_zone pvzone_store; +static struct vm_object pvzone_obj; +static int pv_entry_count=0, pv_entry_max=0, pv_entry_high_water=0; +static int pmap_pagedaemon_waken = 0; +static struct pv_entry *pvinit; + +/* + * All those kernel PT submaps that BSD is so fond of + */ +pt_entry_t *CMAP1 = 0; +static pt_entry_t *CMAP2, *ptmmap; +static pv_table_t *pv_table; +caddr_t CADDR1; +static caddr_t CADDR2; + +static PMAP_INLINE void free_pv_entry __P((pv_entry_t pv)); +static pv_entry_t get_pv_entry __P((void)); +static void alpha_protection_init __P((void)); +static void pmap_changebit __P((vm_offset_t pa, int bit, boolean_t setem)); + +static PMAP_INLINE int pmap_is_managed __P((vm_offset_t pa)); +static void pmap_remove_all __P((vm_offset_t pa)); +static vm_page_t pmap_enter_quick __P((pmap_t pmap, vm_offset_t va, + vm_offset_t pa, vm_page_t mpte)); +static int pmap_remove_pte __P((pmap_t pmap, pt_entry_t* ptq, vm_offset_t sva)); +static void pmap_remove_page __P((struct pmap *pmap, vm_offset_t va)); +static int pmap_remove_entry __P((struct pmap *pmap, pv_table_t *pv, + vm_offset_t va)); +static boolean_t pmap_testbit __P((vm_offset_t pa, int bit)); +static void pmap_insert_entry __P((pmap_t pmap, vm_offset_t va, + vm_page_t mpte, vm_offset_t pa)); + +static vm_page_t pmap_allocpte __P((pmap_t pmap, vm_offset_t va)); + +static int pmap_release_free_page __P((pmap_t pmap, vm_page_t p)); +static vm_page_t _pmap_allocpte __P((pmap_t pmap, unsigned ptepindex)); +static vm_page_t pmap_page_lookup __P((vm_object_t object, vm_pindex_t pindex)); +static int pmap_unuse_pt __P((pmap_t, vm_offset_t, vm_page_t)); +static vm_offset_t pmap_kmem_choose(vm_offset_t addr) ; +void pmap_collect(void); + + +/* + * Routine: pmap_lev1pte + * Function: + * Extract the level 1 page table entry associated + * with the given map/virtual_address pair. + */ +static PMAP_INLINE pt_entry_t* +pmap_lev1pte(pmap_t pmap, vm_offset_t va) +{ + if (!pmap) + return 0; + return &pmap->pm_lev1[pmap_lev1_index(va)]; +} + +/* + * Routine: pmap_lev2pte + * Function: + * Extract the level 2 page table entry associated + * with the given map/virtual_address pair. + */ +static PMAP_INLINE pt_entry_t* +pmap_lev2pte(pmap_t pmap, vm_offset_t va) +{ + pt_entry_t* l1pte; + pt_entry_t* l2map; + + l1pte = pmap_lev1pte(pmap, va); + if (!pmap_pte_v(l1pte)) + return 0; + + l2map = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l1pte)); + return &l2map[pmap_lev2_index(va)]; +} + +/* + * Routine: pmap_lev3pte + * Function: + * Extract the level 3 page table entry associated + * with the given map/virtual_address pair. + */ +static PMAP_INLINE pt_entry_t* +pmap_lev3pte(pmap_t pmap, vm_offset_t va) +{ + pt_entry_t* l2pte; + pt_entry_t* l3map; + + l2pte = pmap_lev2pte(pmap, va); + if (!l2pte || !pmap_pte_v(l2pte)) + return 0; + + l3map = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l2pte)); + return &l3map[pmap_lev3_index(va)]; +} + +vm_offset_t +pmap_steal_memory(vm_size_t size) +{ + vm_size_t bank_size; + vm_offset_t pa, va; + + size = round_page(size); + + bank_size = phys_avail[1] - phys_avail[0]; + while (size > bank_size) { + int i; + for (i = 0; phys_avail[i+2]; i+= 2) { + phys_avail[i] = phys_avail[i+2]; + phys_avail[i+1] = phys_avail[i+3]; + } + phys_avail[i] = 0; + phys_avail[i+1] = 0; + if (!phys_avail[0]) + panic("pmap_steal_memory: out of memory"); + bank_size = phys_avail[1] - phys_avail[0]; + } + + pa = phys_avail[0]; + phys_avail[0] += size; + + va = ALPHA_PHYS_TO_K0SEG(pa); + bzero((caddr_t) va, size); + return va; +} + +extern pt_entry_t rom_pte; /* XXX */ +extern int prom_mapped; /* XXX */ + +/* + * Bootstrap the system enough to run with virtual memory. + */ +void +pmap_bootstrap(vm_offset_t ptaddr, u_int maxasn) +{ + pt_entry_t newpte; + pt_entry_t* pte; + vm_offset_t va; + int i; + + /* + * Allocate a level 1 map for the kernel. + */ + Lev1map = (pt_entry_t*) pmap_steal_memory(PAGE_SIZE); + + /* + * Allocate a level 2 map for the kernel + */ + Lev2map = (pt_entry_t*) pmap_steal_memory(PAGE_SIZE); + Lev2mapsize = PAGE_SIZE; + + /* + * Allocate some level 3 maps for the kernel + */ + Lev3map = (pt_entry_t*) pmap_steal_memory(PAGE_SIZE*NKPT); + Lev3mapsize = NKPT * PAGE_SIZE; + + /* Map all of the level 2 maps */ + for (i = 0; i < howmany(Lev2mapsize, PAGE_SIZE); i++) { + unsigned long pfn = + pmap_k0seg_to_pfn((vm_offset_t) Lev2map) + i; + newpte = ALPHA_PTE_FROM_PFN(pfn); + newpte |= PG_V | PG_KRE | PG_KWE | PG_W; + Lev1map[K1SEGLEV1I + i] = newpte; + } + + + /* Setup the mapping for the prom console */ + { + + if (pmap_uses_prom_console()) { + /* XXX save old pte so that we can remap prom if necessary */ + rom_pte = *(pt_entry_t *)ptaddr & ~PG_ASM; /* XXX */ + } + prom_mapped = 0; + + /* + * Actually, this code lies. The prom is still mapped, and will + * remain so until the context switch after alpha_init() returns. + * Printfs using the firmware before then will end up frobbing + * Lev1map unnecessarily, but that's OK. + */ + } + + /* Level 1 self mapping */ + newpte = pmap_k0seg_to_pte((vm_offset_t) Lev1map); + newpte |= PG_V | PG_KRE | PG_KWE; + Lev1map[PTLEV1I] = newpte; + + /* Map all of the level 3 maps */ + for (i = 0; i < howmany(Lev3mapsize, PAGE_SIZE); i++) { + unsigned long pfn = + pmap_k0seg_to_pfn((vm_offset_t) Lev3map) + i; + newpte = ALPHA_PTE_FROM_PFN(pfn); + newpte |= PG_V | PG_KRE | PG_KWE | PG_W; + Lev2map[i] = newpte; + } + + avail_start = phys_avail[0]; + for (i = 0; phys_avail[i+2]; i+= 2) ; + avail_end = phys_avail[i+1]; + + virtual_avail = VM_MIN_KERNEL_ADDRESS; + virtual_end = VPTBASE; + + /* + * Initialize protection array. + */ + alpha_protection_init(); + + /* + * The kernel's pmap is statically allocated so we don't have to use + * pmap_create, which is unlikely to work correctly at this part of + * the boot sequence (XXX and which no longer exists). + */ + kernel_pmap = &kernel_pmap_store; + kernel_pmap->pm_lev1 = Lev1map; + kernel_pmap->pm_count = 1; + TAILQ_INIT(&kernel_pmap->pm_pvlist); + nklev3 = NKPT; + nklev2 = 1; + + /* + * Reserve some special page table entries/VA space for temporary + * mapping of pages. + */ +#define SYSMAP(c, p, v, n) \ + v = (c)va; va += ((n)*PAGE_SIZE); p = pte; pte += (n); + + va = virtual_avail; + pte = pmap_lev3pte(kernel_pmap, va); + + /* + * CMAP1/CMAP2 are used for zeroing and copying pages. + */ + SYSMAP(caddr_t, CMAP1, CADDR1, 1) + SYSMAP(caddr_t, CMAP2, CADDR2, 1) + + virtual_avail = va; + + *CMAP1 = *CMAP2 = 0; + + /* + * Set up proc0's PCB such that the ptbr points to the right place + * and has the kernel pmap's (really unused) ASN. + */ + proc0.p_addr->u_pcb.pcb_hw.apcb_ptbr = + ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map) >> PAGE_SHIFT; + proc0.p_addr->u_pcb.pcb_hw.apcb_asn = 0; +} + +int +pmap_uses_prom_console() +{ +#if 0 + extern int cputype; + +#if defined(NEW_SCC_DRIVER) + return (cputype == ST_DEC_21000); +#else + return (cputype == ST_DEC_21000 + || cputype == ST_DEC_3000_300 + || cputype == ST_DEC_3000_500); +#endif /* NEW_SCC_DRIVER */ +#endif + + return 1; +} + +void +pmap_setdevram(unsigned long long basea, vm_offset_t sizea) +{ +} + +/* + * Initialize the pmap module. + * Called by vm_init, to initialize any structures that the pmap + * system needs to map virtual memory. + * pmap_init has been enhanced to support in a fairly consistant + * way, discontiguous physical memory. + */ +void +pmap_init(phys_start, phys_end) + vm_offset_t phys_start, phys_end; +{ + vm_offset_t addr; + vm_size_t s; + int i; + int initial_pvs; + + /* + * calculate the number of pv_entries needed + */ + vm_first_phys = phys_avail[0]; + for (i = 0; phys_avail[i + 1]; i += 2); + pv_npg = (phys_avail[(i - 2) + 1] - vm_first_phys) / PAGE_SIZE; + + /* + * Allocate memory for random pmap data structures. Includes the + * pv_head_table. + */ + s = (vm_size_t) (sizeof(pv_table_t) * pv_npg); + s = round_page(s); + + addr = (vm_offset_t) kmem_alloc(kernel_map, s); + pv_table = (pv_table_t *) addr; + for(i = 0; i < pv_npg; i++) { + vm_offset_t pa; + TAILQ_INIT(&pv_table[i].pv_list); + pv_table[i].pv_list_count = 0; + pa = vm_first_phys + i * PAGE_SIZE; + pv_table[i].pv_vm_page = PHYS_TO_VM_PAGE(pa); + } + + /* + * init the pv free list + */ + initial_pvs = pv_npg; + if (initial_pvs < MINPV) + initial_pvs = MINPV; + pvzone = &pvzone_store; + pvinit = (struct pv_entry *) kmem_alloc(kernel_map, + initial_pvs * sizeof (struct pv_entry)); + zbootinit(pvzone, "PV ENTRY", sizeof (struct pv_entry), pvinit, pv_npg); + /* + * object for kernel page table pages + */ + kptobj = vm_object_allocate(OBJT_DEFAULT, NKLEV3MAPS + NKLEV2MAPS); + + /* + * Now it is safe to enable pv_table recording. + */ + pmap_initialized = TRUE; +} + +/* + * Initialize the address space (zone) for the pv_entries. Set a + * high water mark so that the system can recover from excessive + * numbers of pv entries. + */ +void +pmap_init2() +{ + pv_entry_max = PMAP_SHPGPERPROC * maxproc + pv_npg; + pv_entry_high_water = 9 * (pv_entry_max / 10); + zinitna(pvzone, &pvzone_obj, NULL, 0, pv_entry_max, ZONE_INTERRUPT, 1); +} + +/* + * Used to map a range of physical addresses into kernel + * virtual address space. + * + * For now, VM is already on, we only need to map the + * specified memory. + */ +vm_offset_t +pmap_map(virt, start, end, prot) + vm_offset_t virt; + vm_offset_t start; + vm_offset_t end; + int prot; +{ + while (start < end) { + pmap_enter(kernel_pmap, virt, start, prot, FALSE); + virt += PAGE_SIZE; + start += PAGE_SIZE; + } + return (virt); +} + + +/*************************************************** + * Low level helper routines..... + ***************************************************/ + +/* + * this routine defines the region(s) of memory that should + * not be tested for the modified bit. + */ +static PMAP_INLINE int +pmap_track_modified( vm_offset_t va) { + if ((va < clean_sva) || (va >= clean_eva)) + return 1; + else + return 0; +} + +/* + * Routine: pmap_extract + * Function: + * Extract the physical page address associated + * with the given map/virtual_address pair. + */ +vm_offset_t +pmap_extract(pmap, va) + register pmap_t pmap; + vm_offset_t va; +{ + pt_entry_t* pte = pmap_lev3pte(pmap, va); + if (pte) + return alpha_ptob(ALPHA_PTE_TO_PFN(*pte)); + else + return 0; +} + +/* + * determine if a page is managed (memory vs. device) + */ +static PMAP_INLINE int +pmap_is_managed(pa) + vm_offset_t pa; +{ + int i; + + if (!pmap_initialized) + return 0; + + for (i = 0; phys_avail[i + 1]; i += 2) { + if (pa < phys_avail[i + 1] && pa >= phys_avail[i]) + return 1; + } + return 0; +} + + +/*************************************************** + * Low level mapping routines..... + ***************************************************/ + +/* + * Add a list of wired pages to the kva + * this routine is only used for temporary + * kernel mappings that do not need to have + * page modification or references recorded. + * Note that old mappings are simply written + * over. The page *must* be wired. + */ +void +pmap_qenter(vm_offset_t va, vm_page_t *m, int count) +{ + int i; + pt_entry_t *pte; + + for (i = 0; i < count; i++) { + vm_offset_t tva = va + i * PAGE_SIZE; + pt_entry_t npte = pmap_phys_to_pte(VM_PAGE_TO_PHYS(m[i])) + | PG_KRE | PG_KWE | PG_V; + pt_entry_t opte; + pte = vtopte(tva); + opte = *pte; + *pte = npte; + if (opte) + ALPHA_TBIS(tva); + } +} + +/* + * this routine jerks page mappings from the + * kernel -- it is meant only for temporary mappings. + */ +void +pmap_qremove(va, count) + vm_offset_t va; + int count; +{ + int i; + register pt_entry_t *pte; + + for (i = 0; i < count; i++) { + pte = vtopte(va); + *pte = 0; + ALPHA_TBIS(va); + va += PAGE_SIZE; + } +} + +/* + * add a wired page to the kva + * note that in order for the mapping to take effect -- you + * should do a invltlb after doing the pmap_kenter... + */ +PMAP_INLINE void +pmap_kenter(vm_offset_t va, vm_offset_t pa) +{ + pt_entry_t *pte; + pt_entry_t npte, opte; + + npte = pmap_phys_to_pte(pa) | PG_KRE | PG_KWE | PG_V; + pte = vtopte(va); + opte = *pte; + *pte = npte; + if (opte) + ALPHA_TBIS(va); +} + +/* + * remove a page from the kernel pagetables + */ +PMAP_INLINE void +pmap_kremove(vm_offset_t va) +{ + register pt_entry_t *pte; + + pte = vtopte(va); + *pte = 0; + ALPHA_TBIS(va); +} + +static vm_page_t +pmap_page_lookup(vm_object_t object, vm_pindex_t pindex) +{ + vm_page_t m; +retry: + m = vm_page_lookup(object, pindex); + if (m && vm_page_sleep(m, "pplookp", NULL)) + goto retry; + return m; +} + +/* + * Create the UPAGES for a new process. + * This routine directly affects the fork perf for a process. + */ +void +pmap_new_proc(struct proc *p) +{ + int i; + vm_object_t upobj; + vm_page_t m; + struct user *up; + pt_entry_t *ptek, oldpte; + + /* + * allocate object for the upages + */ + if ((upobj = p->p_upages_obj) == NULL) { + upobj = vm_object_allocate( OBJT_DEFAULT, UPAGES); + p->p_upages_obj = upobj; + } + + /* get a kernel virtual address for the UPAGES for this proc */ + if ((up = p->p_addr) == NULL) { + up = (struct user *) kmem_alloc_pageable(kernel_map, + UPAGES * PAGE_SIZE); +#if !defined(MAX_PERF) + if (up == NULL) + panic("pmap_new_proc: u_map allocation failed"); +#endif + p->p_addr = up; + } + + ptek = vtopte((vm_offset_t) up); + + for(i=0;i<UPAGES;i++) { + /* + * Get a kernel stack page + */ + m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); + + /* + * Wire the page + */ + m->wire_count++; + cnt.v_wire_count++; + + oldpte = *(ptek + i); + /* + * Enter the page into the kernel address space. + */ + *(ptek + i) = pmap_phys_to_pte(VM_PAGE_TO_PHYS(m)) | PG_KRE | PG_KWE | PG_V; + if (oldpte) + ALPHA_TBIS((vm_offset_t)up + i * PAGE_SIZE); + + PAGE_WAKEUP(m); + m->flags &= ~PG_ZERO; + m->flags |= PG_MAPPED | PG_WRITEABLE; + m->valid = VM_PAGE_BITS_ALL; + } +} + +/* + * Dispose the UPAGES for a process that has exited. + * This routine directly impacts the exit perf of a process. + */ +void +pmap_dispose_proc(p) + struct proc *p; +{ + int i; + vm_object_t upobj; + vm_page_t m; + pt_entry_t *ptek, oldpte; + + upobj = p->p_upages_obj; + + ptek = vtopte((vm_offset_t) p->p_addr); + for(i=0;i<UPAGES;i++) { + + if ((m = vm_page_lookup(upobj, i)) == NULL) + panic("pmap_dispose_proc: upage already missing???"); + + m->flags |= PG_BUSY; + + oldpte = *(ptek + i); + *(ptek + i) = 0; + ALPHA_TBIS((vm_offset_t)p->p_addr + i * PAGE_SIZE); + vm_page_unwire(m); + vm_page_free(m); + } +} + +/* + * Allow the UPAGES for a process to be prejudicially paged out. + */ +void +pmap_swapout_proc(p) + struct proc *p; +{ + int i; + vm_object_t upobj; + vm_page_t m; + + upobj = p->p_upages_obj; + /* + * let the upages be paged + */ + for(i=0;i<UPAGES;i++) { + if ((m = vm_page_lookup(upobj, i)) == NULL) + panic("pmap_swapout_proc: upage already missing???"); + m->dirty = VM_PAGE_BITS_ALL; + vm_page_unwire(m); + vm_page_deactivate(m); + pmap_kremove( (vm_offset_t) p->p_addr + PAGE_SIZE * i); + } +} + +/* + * Bring the UPAGES for a specified process back in. + */ +void +pmap_swapin_proc(p) + struct proc *p; +{ + int i,rv; + vm_object_t upobj; + vm_page_t m; + + upobj = p->p_upages_obj; + for(i=0;i<UPAGES;i++) { + + m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); + + pmap_kenter(((vm_offset_t) p->p_addr) + i * PAGE_SIZE, + VM_PAGE_TO_PHYS(m)); + + if (m->valid != VM_PAGE_BITS_ALL) { + rv = vm_pager_get_pages(upobj, &m, 1, 0); +#if !defined(MAX_PERF) + if (rv != VM_PAGER_OK) + panic("pmap_swapin_proc: cannot get upages for proc: %d\n", p->p_pid); +#endif + m = vm_page_lookup(upobj, i); + m->valid = VM_PAGE_BITS_ALL; + } + + vm_page_wire(m); + PAGE_WAKEUP(m); + m->flags |= PG_MAPPED | PG_WRITEABLE; + } +} + +/*************************************************** + * Page table page management routines..... + ***************************************************/ + +/* + * This routine unholds page table pages, and if the hold count + * drops to zero, then it decrements the wire count. + */ +static int +_pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m) +{ + int s; + + while (vm_page_sleep(m, "pmuwpt", NULL)); + + if (m->hold_count == 0) { + vm_offset_t pteva; + pt_entry_t* pte; + int level; + + /* + * unmap the page table page + */ + if (m->pindex >= NUSERLEV3MAPS) { + /* Level 2 page table */ + pte = pmap_lev1pte(pmap, va); + pteva = (vm_offset_t) PTlev2 + alpha_ptob(m->pindex - NUSERLEV3MAPS); + } else { + /* Level 3 page table */ + pte = pmap_lev2pte(pmap, va); + pteva = (vm_offset_t) PTmap + alpha_ptob(m->pindex); + } + + *pte = 0; + + if (m->pindex < NUSERLEV3MAPS) { + /* unhold the level 2 page table */ + vm_page_t lev2pg; + lev2pg = pmap_page_lookup(pmap->pm_pteobj, + NUSERLEV3MAPS + pmap_lev1_index(va)); + vm_page_unhold(lev2pg); + if (m->hold_count == 0) + _pmap_unwire_pte_hold(pmap, va, lev2pg); + } + + --pmap->pm_stats.resident_count; + if (ALPHA_PTE_TO_PFN(pmap->pm_lev1[PTLEV1I]) == ALPHA_PTE_TO_PFN(PTlev1pte)) { + /* + * Do a invltlb to make the invalidated mapping + * take effect immediately. + */ + ALPHA_TBIS(pteva); + } + + if (pmap->pm_ptphint == m) + pmap->pm_ptphint = NULL; + + /* + * If the page is finally unwired, simply free it. + */ + --m->wire_count; + if (m->wire_count == 0) { + + if (m->flags & PG_WANTED) { + m->flags &= ~PG_WANTED; + wakeup(m); + } + + m->flags |= PG_BUSY; + vm_page_free_zero(m); + --cnt.v_wire_count; + } + return 1; + } + return 0; +} + +static PMAP_INLINE int +pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m) +{ + vm_page_unhold(m); + if (m->hold_count == 0) + return _pmap_unwire_pte_hold(pmap, va, m); + else + return 0; +} + +/* + * After removing a page table entry, this routine is used to + * conditionally free the page, and manage the hold/wire counts. + */ +static int +pmap_unuse_pt(pmap_t pmap, vm_offset_t va, vm_page_t mpte) +{ + unsigned ptepindex; + if (va >= VM_MAXUSER_ADDRESS) + return 0; + + if (mpte == NULL) { + ptepindex = (va >> ALPHA_L2SHIFT); + if (pmap->pm_ptphint && + (pmap->pm_ptphint->pindex == ptepindex)) { + mpte = pmap->pm_ptphint; + } else { + mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); + pmap->pm_ptphint = mpte; + } + } + + return pmap_unwire_pte_hold(pmap, va, mpte); +} + +void +pmap_pinit0(pmap) + struct pmap *pmap; +{ + pmap->pm_lev1 = Lev1map; + pmap->pm_flags = 0; + pmap->pm_count = 1; + pmap->pm_ptphint = NULL; + TAILQ_INIT(&pmap->pm_pvlist); + bzero(&pmap->pm_stats, sizeof pmap->pm_stats); +} + +/* + * Initialize a preallocated and zeroed pmap structure, + * such as one in a vmspace structure. + */ +void +pmap_pinit(pmap) + register struct pmap *pmap; +{ + vm_page_t lev1pg; + + /* + * allocate object for the ptes + */ + if (pmap->pm_pteobj == NULL) + pmap->pm_pteobj = vm_object_allocate(OBJT_DEFAULT, NUSERLEV3MAPS + NUSERLEV2MAPS + 1); + + /* + * allocate the page directory page + */ +retry: + lev1pg = vm_page_grab(pmap->pm_pteobj, NUSERLEV3MAPS + NUSERLEV2MAPS, + VM_ALLOC_NORMAL | VM_ALLOC_RETRY); + + lev1pg->wire_count = 1; + ++cnt.v_wire_count; + + lev1pg->flags &= ~(PG_MAPPED | PG_BUSY); /* not mapped normally */ + lev1pg->valid = VM_PAGE_BITS_ALL; + + pmap->pm_lev1 = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(VM_PAGE_TO_PHYS(lev1pg)); + if ((lev1pg->flags & PG_ZERO) == 0) + bzero(pmap->pm_lev1, PAGE_SIZE); + + /* wire in kernel global address entries */ + /* XXX copies current process, does not fill in MPPTDI */ + bcopy(PTlev1 + K1SEGLEV1I, pmap->pm_lev1 + K1SEGLEV1I, nklev2 * PTESIZE); + + /* install self-referential address mapping entry */ + pmap->pm_lev1[PTLEV1I] = pmap_phys_to_pte(VM_PAGE_TO_PHYS(lev1pg)) + | PG_V | PG_KRE | PG_KWE; + + pmap->pm_flags = 0; + pmap->pm_count = 1; + pmap->pm_ptphint = NULL; + TAILQ_INIT(&pmap->pm_pvlist); + bzero(&pmap->pm_stats, sizeof pmap->pm_stats); +} + +static int +pmap_release_free_page(pmap_t pmap, vm_page_t p) +{ + int s; + pt_entry_t* pte; + pt_entry_t* l2map; + + if (p->pindex >= NUSERLEV3MAPS + NUSERLEV2MAPS) + /* level 1 page table */ + pte = &pmap->pm_lev1[PTLEV1I]; + else if (p->pindex >= NUSERLEV3MAPS) + /* level 2 page table */ + pte = &pmap->pm_lev1[p->pindex - NUSERLEV3MAPS]; + else { + /* level 3 page table */ + pte = &pmap->pm_lev1[p->pindex >> ALPHA_PTSHIFT]; + l2map = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(pte)); + pte = &l2map[p->pindex & ((1 << ALPHA_PTSHIFT) - 1)]; + } + + /* + * This code optimizes the case of freeing non-busy + * page-table pages. Those pages are zero now, and + * might as well be placed directly into the zero queue. + */ + if (vm_page_sleep(p, "pmaprl", NULL)) + return 0; + + p->flags |= PG_BUSY; + + /* + * Remove the page table page from the processes address space. + */ + *pte = 0; + pmap->pm_stats.resident_count--; + +#if !defined(MAX_PERF) + if (p->hold_count) { + panic("pmap_release: freeing held page table page"); + } +#endif + /* + * Level1 pages need to have the kernel + * stuff cleared, so they can go into the zero queue also. + */ + if (p->pindex == NUSERLEV3MAPS + NUSERLEV2MAPS) + bzero(pmap->pm_lev1 + K1SEGLEV1I, nklev2 * PTESIZE); + + if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex)) + pmap->pm_ptphint = NULL; + + vm_page_free_zero(p); + return 1; +} + +/* + * this routine is called if the page table page is not + * mapped correctly. + */ +static vm_page_t +_pmap_allocpte(pmap, ptepindex) + pmap_t pmap; + unsigned ptepindex; +{ + pt_entry_t* pte; + vm_offset_t pteva, ptepa; + vm_page_t m; + + /* + * Find or fabricate a new pagetable page + */ + m = vm_page_grab(pmap->pm_pteobj, ptepindex, + VM_ALLOC_ZERO | VM_ALLOC_RETRY); + + if (m->queue != PQ_NONE) { + int s = splvm(); + vm_page_unqueue(m); + splx(s); + } + + if (m->wire_count == 0) + cnt.v_wire_count++; + m->wire_count++; + + /* + * Increment the hold count for the page table page + * (denoting a new mapping.) + */ + m->hold_count++; + + /* + * Map the pagetable page into the process address space, if + * it isn't already there. + */ + + pmap->pm_stats.resident_count++; + + ptepa = VM_PAGE_TO_PHYS(m); + + if (ptepindex >= NUSERLEV3MAPS) { + pte = &pmap->pm_lev1[ptepindex - NUSERLEV3MAPS]; + } else { + int l1index = ptepindex >> ALPHA_PTSHIFT; + pt_entry_t* l1pte = &pmap->pm_lev1[l1index]; + pt_entry_t* l2map; + if (!pmap_pte_v(l1pte)) + _pmap_allocpte(pmap, NUSERLEV3MAPS + l1index); + l2map = (pt_entry_t*) ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l1pte)); + pte = &l2map[ptepindex & ((1 << ALPHA_PTSHIFT) - 1)]; + } + + *pte = pmap_phys_to_pte(ptepa) | PG_KRE | PG_KWE | PG_V; + + /* + * Set the page table hint + */ + pmap->pm_ptphint = m; + + if ((m->flags & PG_ZERO) == 0) + bzero((caddr_t) ALPHA_PHYS_TO_K0SEG(ptepa), PAGE_SIZE); + + m->valid = VM_PAGE_BITS_ALL; + m->flags &= ~(PG_ZERO | PG_BUSY); + m->flags |= PG_MAPPED; + + return m; +} + +static vm_page_t +pmap_allocpte(pmap_t pmap, vm_offset_t va) +{ + unsigned ptepindex; + pt_entry_t* lev2pte; + vm_offset_t ptepa; + vm_page_t m; + + /* + * Calculate pagetable page index + */ + ptepindex = va >> (PAGE_SHIFT + ALPHA_PTSHIFT); + + /* + * Get the level2 entry + */ + lev2pte = pmap_lev2pte(pmap, va); + + /* + * If the page table page is mapped, we just increment the + * hold count, and activate it. + */ + if (lev2pte && pmap_pte_v(lev2pte)) { + /* + * In order to get the page table page, try the + * hint first. + */ + if (pmap->pm_ptphint && + (pmap->pm_ptphint->pindex == ptepindex)) { + m = pmap->pm_ptphint; + } else { + m = pmap_page_lookup( pmap->pm_pteobj, ptepindex); + pmap->pm_ptphint = m; + } + m->hold_count++; + return m; + } + /* + * Here if the pte page isn't mapped, or if it has been deallocated. + */ + return _pmap_allocpte(pmap, ptepindex); +} + + +/*************************************************** +* Pmap allocation/deallocation routines. + ***************************************************/ + +/* + * Release any resources held by the given physical map. + * Called when a pmap initialized by pmap_pinit is being released. + * Should only be called if the map contains no valid mappings. + */ +void +pmap_release(pmap_t pmap) +{ + vm_page_t p,n,lev1pg; + vm_object_t object = pmap->pm_pteobj; + int curgeneration; + +#if defined(DIAGNOSTIC) + if (object->ref_count != 1) + panic("pmap_release: pteobj reference count != 1"); +#endif + + lev1pg = NULL; +retry: + curgeneration = object->generation; + for (p = TAILQ_FIRST(&object->memq); p != NULL; p = n) { + n = TAILQ_NEXT(p, listq); + if (p->pindex >= NUSERLEV3MAPS) { + continue; + } + while (1) { + if (!pmap_release_free_page(pmap, p) && + (object->generation != curgeneration)) + goto retry; + } + } + for (p = TAILQ_FIRST(&object->memq); p != NULL; p = n) { + n = TAILQ_NEXT(p, listq); + if (p->pindex < NUSERLEV3MAPS) { + /* can this happen? maybe panic */ + goto retry; + } + if (p->pindex >= NUSERLEV3MAPS + NUSERLEV2MAPS) { + lev1pg = p; + continue; + } + while (1) { + if (!pmap_release_free_page(pmap, p) && + (object->generation != curgeneration)) + goto retry; + } + } + + if (lev1pg && !pmap_release_free_page(pmap, lev1pg)) + goto retry; +} + +/* + * grow the number of kernel page table entries, if needed + */ +void +pmap_growkernel(vm_offset_t addr) +{ + /* XXX come back to this */ + struct proc *p; + struct pmap *pmap; + int s; + pt_entry_t* pte; + pt_entry_t newlev1, newlev2; + vm_offset_t pa; + vm_page_t nkpg; + + s = splhigh(); + + if (kernel_vm_end == 0) { + kernel_vm_end = VM_MIN_KERNEL_ADDRESS;; + + /* Count the level 2 page tables */ + nklev2 = 0; + nklev3 = 0; + while (pmap_pte_v(pmap_lev1pte(kernel_pmap, kernel_vm_end))) { + nklev2++; + nklev3 += (1L << ALPHA_PTSHIFT); + kernel_vm_end += ALPHA_L1SIZE; + } + + /* Count the level 3 page tables in the last level 2 page table */ + kernel_vm_end -= ALPHA_L1SIZE; + nklev3 -= (1 << ALPHA_PTSHIFT); + while (pmap_pte_v(pmap_lev2pte(kernel_pmap, kernel_vm_end))) { + nklev3++; + kernel_vm_end += ALPHA_L2SIZE; + } + } + + addr = (addr + ALPHA_L2SIZE) & ~(ALPHA_L2SIZE - 1); + while (kernel_vm_end < addr) { + /* + * If the level 1 pte is invalid, allocate a new level 2 page table + */ + pte = pmap_lev1pte(kernel_pmap, kernel_vm_end); + if (!pmap_pte_v(pte)) { + int pindex = NKLEV3MAPS + pmap_lev1_index(kernel_vm_end) - K1SEGLEV1I; + + nkpg = vm_page_alloc(kptobj, pindex, VM_ALLOC_SYSTEM); +#if !defined(MAX_PERF) + if (!nkpg) + panic("pmap_growkernel: no memory to grow kernel"); +#endif + nklev2++; + vm_page_wire(nkpg); + pa = VM_PAGE_TO_PHYS(nkpg); + pmap_zero_page(pa); + + newlev1 = pmap_phys_to_pte(pa) | PG_V | PG_KRE | PG_KWE; + + for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { + if (p->p_vmspace) { + pmap = &p->p_vmspace->vm_pmap; + *pmap_lev1pte(pmap, kernel_vm_end) = newlev1; + } + } + *pte = newlev1; + ALPHA_TBIA(); + } + + /* + * If the level 2 pte is invalid, allocate a new level 3 page table + */ + pte = pmap_lev2pte(kernel_pmap, kernel_vm_end); + if (pmap_pte_v(pte)) { + kernel_vm_end = (kernel_vm_end + ALPHA_L2SIZE) & ~(ALPHA_L2SIZE - 1); + continue; + } + + /* + * This index is bogus, but out of the way + */ + nkpg = vm_page_alloc(kptobj, nklev3, VM_ALLOC_SYSTEM); +#if !defined(MAX_PERF) + if (!nkpg) + panic("pmap_growkernel: no memory to grow kernel"); +#endif + + nklev3++; + + vm_page_wire(nkpg); + pa = VM_PAGE_TO_PHYS(nkpg); + pmap_zero_page(pa); + newlev2 = pmap_phys_to_pte(pa) | PG_V | PG_KRE | PG_KWE; + *pte = newlev2; + + kernel_vm_end = (kernel_vm_end + ALPHA_L2SIZE) & ~(ALPHA_L2SIZE - 1); + } + splx(s); +} + +/* + * Retire the given physical map from service. + * Should only be called if the map contains + * no valid mappings. + */ +void +pmap_destroy(pmap_t pmap) +{ + int count; + + if (pmap == NULL) + return; + + count = --pmap->pm_count; + if (count == 0) { + pmap_release(pmap); +#if !defined(MAX_PERF) + panic("destroying a pmap is not yet implemented"); +#endif + } +} + +/* + * Add a reference to the specified pmap. + */ +void +pmap_reference(pmap_t pmap) +{ + if (pmap != NULL) { + pmap->pm_count++; + } +} + +/*************************************************** +* page management routines. + ***************************************************/ + +/* + * free the pv_entry back to the free list + */ +static PMAP_INLINE void +free_pv_entry(pv_entry_t pv) +{ + pv_entry_count--; + zfreei(pvzone, pv); +} + +/* + * get a new pv_entry, allocating a block from the system + * when needed. + * the memory allocation is performed bypassing the malloc code + * because of the possibility of allocations at interrupt time. + */ +static pv_entry_t +get_pv_entry(void) +{ + pv_entry_count++; + if (pv_entry_high_water && + (pv_entry_count > pv_entry_high_water) && + (pmap_pagedaemon_waken == 0)) { + pmap_pagedaemon_waken = 1; + wakeup (&vm_pages_needed); + } + return zalloci(pvzone); +} + +/* + * This routine is very drastic, but can save the system + * in a pinch. + */ +void +pmap_collect() +{ + pv_table_t *ppv; + int i; + vm_offset_t pa; + vm_page_t m; + static int warningdone=0; + + if (pmap_pagedaemon_waken == 0) + return; + + if (warningdone < 5) { + printf("pmap_collect: collecting pv entries -- suggest increasing PMAP_SHPGPERPROC\n"); + warningdone++; + } + + for(i = 0; i < pv_npg; i++) { + if ((ppv = &pv_table[i]) == 0) + continue; + m = ppv->pv_vm_page; + if ((pa = VM_PAGE_TO_PHYS(m)) == 0) + continue; + if (m->wire_count || m->hold_count || m->busy || + (m->flags & PG_BUSY)) + continue; + pmap_remove_all(pa); + } + pmap_pagedaemon_waken = 0; +} + + +/* + * If it is the first entry on the list, it is actually + * in the header and we must copy the following entry up + * to the header. Otherwise we must search the list for + * the entry. In either case we free the now unused entry. + */ + +static int +pmap_remove_entry(pmap_t pmap, pv_table_t* ppv, vm_offset_t va) +{ + pv_entry_t pv; + int rtval; + int s; + + s = splvm(); + if (ppv->pv_list_count < pmap->pm_stats.resident_count) { + for (pv = TAILQ_FIRST(&ppv->pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + if (pmap == pv->pv_pmap && va == pv->pv_va) + break; + } + } else { + for (pv = TAILQ_FIRST(&pmap->pm_pvlist); + pv; + pv = TAILQ_NEXT(pv, pv_plist)) { + if (va == pv->pv_va) + break; + } + } + + rtval = 0; + if (pv) { + rtval = pmap_unuse_pt(pmap, va, pv->pv_ptem); + TAILQ_REMOVE(&ppv->pv_list, pv, pv_list); + ppv->pv_list_count--; + if (TAILQ_FIRST(&ppv->pv_list) == NULL) + ppv->pv_vm_page->flags &= ~(PG_MAPPED | PG_WRITEABLE); + + TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist); + free_pv_entry(pv); + } + + splx(s); + return rtval; +} + +/* + * Create a pv entry for page at pa for + * (pmap, va). + */ +static void +pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t mpte, vm_offset_t pa) +{ + + int s; + pv_entry_t pv; + pv_table_t *ppv; + + s = splvm(); + pv = get_pv_entry(); + pv->pv_va = va; + pv->pv_pmap = pmap; + pv->pv_ptem = mpte; + + TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist); + + ppv = pa_to_pvh(pa); + TAILQ_INSERT_TAIL(&ppv->pv_list, pv, pv_list); + ppv->pv_list_count++; + + splx(s); +} + +/* + * pmap_remove_pte: do the things to unmap a page in a process + */ +static int +pmap_remove_pte(pmap_t pmap, pt_entry_t* ptq, vm_offset_t va) +{ + pt_entry_t oldpte; + pv_table_t *ppv; + + oldpte = *ptq; + *ptq = 0; + if (oldpte & PG_W) + pmap->pm_stats.wired_count -= 1; + + pmap->pm_stats.resident_count -= 1; + if (oldpte & PG_MANAGED) { + ppv = pa_to_pvh(pmap_pte_pa(&oldpte)); + return pmap_remove_entry(pmap, ppv, va); + } else { + return pmap_unuse_pt(pmap, va, NULL); + } + + return 0; +} + +/* + * Remove a single page from a process address space + */ +static void +pmap_remove_page(pmap_t pmap, vm_offset_t va) +{ + register pt_entry_t *ptq; + + ptq = pmap_lev3pte(pmap, va); + + /* + * if there is no pte for this address, just skip it!!! + */ + if (!ptq || !pmap_pte_v(ptq)) + return; + + /* + * get a local va for mappings for this pmap. + */ + (void) pmap_remove_pte(pmap, ptq, va); + ALPHA_TBIS(va); + + return; +} + +/* + * Remove the given range of addresses from the specified map. + * + * It is assumed that the start and end are properly + * rounded to the page size. + */ +void +pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) +{ + vm_offset_t va; + + if (pmap == NULL) + return; + + if (pmap->pm_stats.resident_count == 0) + return; + + for (va = sva; va < eva; va += PAGE_SIZE) + pmap_remove_page(pmap, va); +} + +/* + * Routine: pmap_remove_all + * Function: + * Removes this physical page from + * all physical maps in which it resides. + * Reflects back modify bits to the pager. + * + * Notes: + * Original versions of this routine were very + * inefficient because they iteratively called + * pmap_remove (slow...) + */ + +static void +pmap_remove_all(vm_offset_t pa) +{ + register pv_entry_t pv; + pv_table_t *ppv; + pt_entry_t *pte, tpte; + int nmodify; + int update_needed; + int s; + + nmodify = 0; + update_needed = 0; +#if defined(PMAP_DIAGNOSTIC) + /* + * XXX this makes pmap_page_protect(NONE) illegal for non-managed + * pages! + */ + if (!pmap_is_managed(pa)) { + panic("pmap_page_protect: illegal for unmanaged page, va: 0x%lx", pa); + } +#endif + + s = splvm(); + ppv = pa_to_pvh(pa); + while ((pv = TAILQ_FIRST(&ppv->pv_list)) != NULL) { + pte = pmap_lev3pte(pv->pv_pmap, pv->pv_va); + + pv->pv_pmap->pm_stats.resident_count--; + + if (pmap_pte_pa(pte) != pa) + panic("pmap_remove_all: pv_table for %x is inconsistent", pa); + + tpte = *pte; + + *pte = 0; + if (tpte & PG_W) + pv->pv_pmap->pm_stats.wired_count--; + + if (!update_needed && + ((!curproc || (&curproc->p_vmspace->vm_pmap == pv->pv_pmap)) || + (pv->pv_pmap == kernel_pmap))) { + update_needed = 1; + } + + TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist); + TAILQ_REMOVE(&ppv->pv_list, pv, pv_list); + ppv->pv_list_count--; + pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem); + free_pv_entry(pv); + } + + ppv->pv_vm_page->flags &= ~(PG_MAPPED | PG_WRITEABLE); + + if (update_needed) + ALPHA_TBIA(); + + splx(s); + return; +} + +/* + * Set the physical protection on the + * specified range of this map as requested. + */ +void +pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) +{ + pt_entry_t* pte; + vm_offset_t pdnxt, ptpaddr; + int isactive; + int newprot; + + if (pmap == NULL) + return; + + if ((prot & VM_PROT_READ) == VM_PROT_NONE) { + pmap_remove(pmap, sva, eva); + return; + } + + if (prot & VM_PROT_WRITE) + return; + + newprot = pte_prot(pmap, prot); + isactive = pmap_isactive(pmap); + + if ((sva & PAGE_MASK) || (eva & PAGE_MASK)) + panic("pmap_protect: unaligned addresses"); + + while (sva < eva) { + pt_entry_t pbits; + + /* + * If level 1 pte is invalid, skip this segment + */ + pte = pmap_lev1pte(pmap, sva); + if (!pmap_pte_v(pte)) { + sva = alpha_l1trunc(sva) + ALPHA_L1SIZE; + continue; + } + + /* + * If level 2 pte is invalid, skip this segment + */ + pte = pmap_lev2pte(pmap, sva); + if (!pmap_pte_v(pte)) { + sva = alpha_l2trunc(sva) + ALPHA_L2SIZE; + continue; + } + + /* + * If level 3 pte is invalid, skip this page + */ + pte = pmap_lev3pte(pmap, sva); + if (!pmap_pte_v(pte)) { + sva += PAGE_SIZE; + continue; + } + + if (pmap_pte_prot(pte) != newprot) { + pmap_pte_set_prot(pte, newprot); + if (isactive) + ALPHA_TBIS(sva); + } + + sva += PAGE_SIZE; + } +} + +/* + * Insert the given physical page (p) at + * the specified virtual address (v) in the + * target physical map with the protection requested. + * + * If specified, the page will be wired down, meaning + * that the related pte can not be reclaimed. + * + * NB: This is the only routine which MAY NOT lazy-evaluate + * or lose information. That is, this routine must actually + * insert this page into the given map NOW. + */ +void +pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, + boolean_t wired) +{ + pt_entry_t *pte; + vm_offset_t opa; + pt_entry_t origpte, newpte; + vm_page_t mpte; + int managed; + + if (pmap == NULL) + return; + + va &= ~PAGE_MASK; +#ifdef PMAP_DIAGNOSTIC + if (va > VM_MAX_KERNEL_ADDRESS) + panic("pmap_enter: toobig"); +#endif + + mpte = NULL; + /* + * In the case that a page table page is not + * resident, we are creating it here. + */ + if (va < VM_MAXUSER_ADDRESS) { + mpte = pmap_allocpte(pmap, va); + } + + pte = pmap_lev3pte(pmap, va); + +#if !defined(MAX_PERF) + /* + * Page Directory table entry not valid, we need a new PT page + */ + if (pte == NULL) { + panic("pmap_enter: invalid kernel page tables pmap=%p, va=0x%lx\n", pmap, va); + } +#endif + + origpte = *pte; + pa &= ~PAGE_MASK; + managed = 0; + opa = pmap_pte_pa(pte); + + /* + * Mapping has not changed, must be protection or wiring change. + */ + if (origpte && (opa == pa)) { + /* + * Wiring change, just update stats. We don't worry about + * wiring PT pages as they remain resident as long as there + * are valid mappings in them. Hence, if a user page is wired, + * the PT page will be also. + */ + if (wired && ((origpte & PG_W) == 0)) + pmap->pm_stats.wired_count++; + else if (!wired && (origpte & PG_W)) + pmap->pm_stats.wired_count--; + + /* + * Remove extra pte reference + */ + if (mpte) + mpte->hold_count--; + + managed = origpte & PG_MANAGED; + goto validate; + } + /* + * Mapping has changed, invalidate old range and fall through to + * handle validating new mapping. + */ + if (opa) { + int err; + err = pmap_remove_pte(pmap, pte, va); +#if !defined(MAX_PERF) + if (err) + panic("pmap_enter: pte vanished, va: 0x%x", va); +#endif + } + + /* + * Enter on the PV list if part of our managed memory Note that we + * raise IPL while manipulating pv_table since pmap_enter can be + * called at interrupt time. + */ + if (pmap_is_managed(pa)) { + pmap_insert_entry(pmap, va, mpte, pa); + managed |= PG_MANAGED; + } + + /* + * Increment counters + */ + pmap->pm_stats.resident_count++; + if (wired) + pmap->pm_stats.wired_count++; + +validate: + /* + * Now validate mapping with desired protection/wiring. + */ + newpte = pmap_phys_to_pte(pa) | pte_prot(pmap, prot) | PG_V | managed; + + if (managed) { + pv_table_t* ppv; + + /* + * Set up referenced/modified emulation for the new mapping + */ + ppv = pa_to_pvh(pa); + if ((ppv->pv_flags & PV_TABLE_REF) == 0) + newpte |= PG_FOR | PG_FOW | PG_FOE; + else if ((ppv->pv_flags & PV_TABLE_MOD) == 0) + newpte |= PG_FOW; + } + + if (wired) + newpte |= PG_W; + + /* + * if the mapping or permission bits are different, we need + * to update the pte. + */ + if (origpte != newpte) { + *pte = newpte; + if (origpte) + ALPHA_TBIS(va); + } +} + +/* + * this code makes some *MAJOR* assumptions: + * 1. Current pmap & pmap exists. + * 2. Not wired. + * 3. Read access. + * 4. No page table pages. + * 5. Tlbflush is deferred to calling procedure. + * 6. Page IS managed. + * but is *MUCH* faster than pmap_enter... + */ + +static vm_page_t +pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_page_t mpte) +{ + register pt_entry_t *pte; + + + /* + * In the case that a page table page is not + * resident, we are creating it here. + */ + if (va < VM_MAXUSER_ADDRESS) { + unsigned ptepindex; + pt_entry_t* l2pte; + + /* + * Calculate lev2 page index + */ + ptepindex = va >> ALPHA_L2SHIFT; + if (mpte && (mpte->pindex == ptepindex)) { + mpte->hold_count++; + } else { +retry: + /* + * Get the level 2 entry + */ + l2pte = pmap_lev2pte(pmap, va); + + /* + * If the level 2 page table is mapped, we just increment + * the hold count, and activate it. + */ + if (l2pte) { + if (pmap->pm_ptphint && + (pmap->pm_ptphint->pindex == ptepindex)) { + mpte = pmap->pm_ptphint; + } else { + mpte = pmap_page_lookup( pmap->pm_pteobj, ptepindex); + pmap->pm_ptphint = mpte; + } + if (mpte == NULL) + goto retry; + mpte->hold_count++; + } else { + mpte = _pmap_allocpte(pmap, ptepindex); + } + } + } else { + mpte = NULL; + } + + /* + * This call to vtopte makes the assumption that we are + * entering the page into the current pmap. In order to support + * quick entry into any pmap, one would likely use pmap_pte_quick. + * But that isn't as quick as vtopte. + */ + pte = vtopte(va); + if (*pte) { + if (mpte) + pmap_unwire_pte_hold(pmap, va, mpte); + return 0; + } + + /* + * Enter on the PV list if part of our managed memory Note that we + * raise IPL while manipulating pv_table since pmap_enter can be + * called at interrupt time. + */ + pmap_insert_entry(pmap, va, mpte, pa); + + /* + * Increment counters + */ + pmap->pm_stats.resident_count++; + + /* + * Now validate mapping with RO protection + */ + *pte = pmap_phys_to_pte(pa) | PG_V | PG_KRE | PG_URE | PG_MANAGED; + + return mpte; +} + +#define MAX_INIT_PT (96) +/* + * pmap_object_init_pt preloads the ptes for a given object + * into the specified pmap. This eliminates the blast of soft + * faults on process startup and immediately after an mmap. + */ +void +pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, + vm_object_t object, vm_pindex_t pindex, + vm_size_t size, int limit) +{ + vm_offset_t tmpidx; + int psize; + vm_page_t p, mpte; + int objpgs; + + if (!pmap) + return; + + psize = alpha_btop(size); + + if ((object->type != OBJT_VNODE) || + (limit && (psize > MAX_INIT_PT) && + (object->resident_page_count > MAX_INIT_PT))) { + return; + } + + if (psize + pindex > object->size) + psize = object->size - pindex; + + mpte = NULL; + /* + * if we are processing a major portion of the object, then scan the + * entire thing. + */ + if (psize > (object->size >> 2)) { + objpgs = psize; + + for (p = TAILQ_FIRST(&object->memq); + ((objpgs > 0) && (p != NULL)); + p = TAILQ_NEXT(p, listq)) { + + tmpidx = p->pindex; + if (tmpidx < pindex) { + continue; + } + tmpidx -= pindex; + if (tmpidx >= psize) { + continue; + } + if (((p->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) && + (p->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) { + if ((p->queue - p->pc) == PQ_CACHE) + vm_page_deactivate(p); + p->flags |= PG_BUSY; + mpte = pmap_enter_quick(pmap, + addr + alpha_ptob(tmpidx), + VM_PAGE_TO_PHYS(p), mpte); + p->flags |= PG_MAPPED; + PAGE_WAKEUP(p); + } + objpgs -= 1; + } + } else { + /* + * else lookup the pages one-by-one. + */ + for (tmpidx = 0; tmpidx < psize; tmpidx += 1) { + p = vm_page_lookup(object, tmpidx + pindex); + if (p && + ((p->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) && + (p->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) { + if ((p->queue - p->pc) == PQ_CACHE) + vm_page_deactivate(p); + p->flags |= PG_BUSY; + mpte = pmap_enter_quick(pmap, + addr + alpha_ptob(tmpidx), + VM_PAGE_TO_PHYS(p), mpte); + p->flags |= PG_MAPPED; + PAGE_WAKEUP(p); + } + } + } + return; +} + +/* + * pmap_prefault provides a quick way of clustering + * pagefaults into a processes address space. It is a "cousin" + * of pmap_object_init_pt, except it runs at page fault time instead + * of mmap time. + */ +#define PFBAK 4 +#define PFFOR 4 +#define PAGEORDER_SIZE (PFBAK+PFFOR) + +static int pmap_prefault_pageorder[] = { + -PAGE_SIZE, PAGE_SIZE, + -2 * PAGE_SIZE, 2 * PAGE_SIZE, + -3 * PAGE_SIZE, 3 * PAGE_SIZE + -4 * PAGE_SIZE, 4 * PAGE_SIZE +}; + +void +pmap_prefault(pmap, addra, entry) + pmap_t pmap; + vm_offset_t addra; + vm_map_entry_t entry; +{ + int i; + vm_offset_t starta; + vm_offset_t addr; + vm_pindex_t pindex; + vm_page_t m, mpte; + vm_object_t object; + + if (!curproc || (pmap != &curproc->p_vmspace->vm_pmap)) + return; + + object = entry->object.vm_object; + + starta = addra - PFBAK * PAGE_SIZE; + if (starta < entry->start) { + starta = entry->start; + } else if (starta > addra) { + starta = 0; + } + + mpte = NULL; + for (i = 0; i < PAGEORDER_SIZE; i++) { + vm_object_t lobject; + pt_entry_t *pte; + + addr = addra + pmap_prefault_pageorder[i]; + if (addr > addra + (PFFOR * PAGE_SIZE)) + addr = 0; + + if (addr < starta || addr >= entry->end) + continue; + + if (!pmap_pte_v(pmap_lev1pte(pmap, addr)) + || !pmap_pte_v(pmap_lev2pte(pmap, addr))) + continue; + + pte = vtopte(addr); + if (*pte) + continue; + + pindex = ((addr - entry->start) + entry->offset) >> PAGE_SHIFT; + lobject = object; + for (m = vm_page_lookup(lobject, pindex); + (!m && (lobject->type == OBJT_DEFAULT) && (lobject->backing_object)); + lobject = lobject->backing_object) { + if (lobject->backing_object_offset & PAGE_MASK) + break; + pindex += (lobject->backing_object_offset >> PAGE_SHIFT); + m = vm_page_lookup(lobject->backing_object, pindex); + } + + /* + * give-up when a page is not in memory + */ + if (m == NULL) + break; + + if (((m->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) && + (m->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) { + + if ((m->queue - m->pc) == PQ_CACHE) { + vm_page_deactivate(m); + } + m->flags |= PG_BUSY; + mpte = pmap_enter_quick(pmap, addr, + VM_PAGE_TO_PHYS(m), mpte); + m->flags |= PG_MAPPED; + PAGE_WAKEUP(m); + } + } +} + +/* + * Routine: pmap_change_wiring + * Function: Change the wiring attribute for a map/virtual-address + * pair. + * In/out conditions: + * The mapping must already exist in the pmap. + */ +void +pmap_change_wiring(pmap, va, wired) + register pmap_t pmap; + vm_offset_t va; + boolean_t wired; +{ + pt_entry_t *pte; + + if (pmap == NULL) + return; + + pte = pmap_lev3pte(pmap, va); + + if (wired && !pmap_pte_w(pte)) + pmap->pm_stats.wired_count++; + else if (!wired && pmap_pte_w(pte)) + pmap->pm_stats.wired_count--; + + /* + * Wiring is not a hardware characteristic so there is no need to + * invalidate TLB. + */ + pmap_pte_set_w(pte, wired); +} + + + +/* + * Copy the range specified by src_addr/len + * from the source map to the range dst_addr/len + * in the destination map. + * + * This routine is only advisory and need not do anything. + */ + +void +pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len, + vm_offset_t src_addr) +{ +} + +/* + * Routine: pmap_kernel + * Function: + * Returns the physical map handle for the kernel. + */ +pmap_t +pmap_kernel() +{ + return (kernel_pmap); +} + +/* + * pmap_zero_page zeros the specified (machine independent) + * page by mapping the page into virtual memory and using + * bzero to clear its contents, one machine dependent page + * at a time. + */ +void +pmap_zero_page(vm_offset_t pa) +{ + vm_offset_t va = ALPHA_PHYS_TO_K0SEG(pa); + bzero((caddr_t) va, PAGE_SIZE); +} + +/* + * pmap_copy_page copies the specified (machine independent) + * page by mapping the page into virtual memory and using + * bcopy to copy the page, one machine dependent page at a + * time. + */ +void +pmap_copy_page(vm_offset_t src, vm_offset_t dst) +{ + src = ALPHA_PHYS_TO_K0SEG(src); + dst = ALPHA_PHYS_TO_K0SEG(dst); + bcopy((caddr_t) src, (caddr_t) dst, PAGE_SIZE); +} + + +/* + * Routine: pmap_pageable + * Function: + * Make the specified pages (by pmap, offset) + * pageable (or not) as requested. + * + * A page which is not pageable may not take + * a fault; therefore, its page table entry + * must remain valid for the duration. + * + * This routine is merely advisory; pmap_enter + * will specify that these pages are to be wired + * down (or not) as appropriate. + */ +void +pmap_pageable(pmap, sva, eva, pageable) + pmap_t pmap; + vm_offset_t sva, eva; + boolean_t pageable; +{ +} + +/* + * this routine returns true if a physical page resides + * in the given pmap. + */ +boolean_t +pmap_page_exists(pmap, pa) + pmap_t pmap; + vm_offset_t pa; +{ + register pv_entry_t pv; + pv_table_t *ppv; + int s; + + if (!pmap_is_managed(pa)) + return FALSE; + + s = splvm(); + + ppv = pa_to_pvh(pa); + /* + * Not found, check current mappings returning immediately if found. + */ + for (pv = TAILQ_FIRST(&ppv->pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + if (pv->pv_pmap == pmap) { + splx(s); + return TRUE; + } + } + splx(s); + return (FALSE); +} + +#define PMAP_REMOVE_PAGES_CURPROC_ONLY +/* + * Remove all pages from specified address space + * this aids process exit speeds. Also, this code + * is special cased for current process only, but + * can have the more generic (and slightly slower) + * mode enabled. This is much faster than pmap_remove + * in the case of running down an entire address space. + */ +void +pmap_remove_pages(pmap, sva, eva) + pmap_t pmap; + vm_offset_t sva, eva; +{ + pt_entry_t *pte, tpte; + pv_table_t *ppv; + pv_entry_t pv, npv; + int s; + +#ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY + if (!curproc || (pmap != &curproc->p_vmspace->vm_pmap)) { + printf("warning: pmap_remove_pages called with non-current pmap\n"); + return; + } +#endif + + s = splvm(); + for(pv = TAILQ_FIRST(&pmap->pm_pvlist); + pv; + pv = npv) { + + if (pv->pv_va >= eva || pv->pv_va < sva) { + npv = TAILQ_NEXT(pv, pv_plist); + continue; + } + +#ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY + pte = vtopte(pv->pv_va); +#else + pte = pmap_pte_quick(pv->pv_pmap, pv->pv_va); +#endif + if (!pmap_pte_v(pte)) + panic("pmap_remove_pages: page on pm_pvlist has no pte\n"); + tpte = *pte; + + +/* + * We cannot remove wired pages from a process' mapping at this time + */ + if (tpte & PG_W) { + npv = TAILQ_NEXT(pv, pv_plist); + continue; + } + *pte = 0; + + ppv = pa_to_pvh(pmap_pte_pa(&tpte)); + + pv->pv_pmap->pm_stats.resident_count--; + + npv = TAILQ_NEXT(pv, pv_plist); + TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist); + + ppv->pv_list_count--; + TAILQ_REMOVE(&ppv->pv_list, pv, pv_list); + if (TAILQ_FIRST(&ppv->pv_list) == NULL) { + ppv->pv_vm_page->flags &= ~(PG_MAPPED | PG_WRITEABLE); + } + + pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem); + free_pv_entry(pv); + } + splx(s); + ALPHA_TBIA(); +} + +/* + * pmap_testbit tests bits in pte's + * note that the testbit/changebit routines are inline, + * and a lot of things compile-time evaluate. + */ +static boolean_t +pmap_testbit(vm_offset_t pa, int bit) +{ + register pv_entry_t pv; + pv_table_t *ppv; + pt_entry_t *pte; + int s; + + if (!pmap_is_managed(pa)) + return FALSE; + + ppv = pa_to_pvh(pa); + if (TAILQ_FIRST(&ppv->pv_list) == NULL) + return FALSE; + + s = splvm(); + + for (pv = TAILQ_FIRST(&ppv->pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + +#if defined(PMAP_DIAGNOSTIC) + if (!pv->pv_pmap) { + printf("Null pmap (tb) at va: 0x%lx\n", pv->pv_va); + continue; + } +#endif + pte = pmap_lev3pte(pv->pv_pmap, pv->pv_va); + if (*pte & bit) { + splx(s); + return TRUE; + } + } + splx(s); + return (FALSE); +} + +/* + * this routine is used to modify bits in ptes + */ +static void +pmap_changebit(vm_offset_t pa, int bit, boolean_t setem) +{ + pv_entry_t pv; + pv_table_t *ppv; + pt_entry_t *pte; + int changed; + int s; + + if (!pmap_is_managed(pa)) + return; + + s = splvm(); + changed = 0; + ppv = pa_to_pvh(pa); + + /* + * Loop over all current mappings setting/clearing as appropos If + * setting RO do we need to clear the VAC? + */ + for (pv = TAILQ_FIRST(&ppv->pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + + /* + * don't write protect pager mappings + */ + if (!setem && bit == (PG_UWE|PG_KWE)) { + if (!pmap_track_modified(pv->pv_va)) + continue; + } + +#if defined(PMAP_DIAGNOSTIC) + if (!pv->pv_pmap) { + printf("Null pmap (cb) at va: 0x%lx\n", pv->pv_va); + continue; + } +#endif + + pte = pmap_lev3pte(pv->pv_pmap, pv->pv_va); + + if (setem) { + *pte |= bit; + changed = 1; + } else { + pt_entry_t pbits = *pte; + if (pbits & bit) { + changed = 1; + *pte = pbits & ~bit; + } + } + } + splx(s); + if (changed) + ALPHA_TBIA(); +} + +/* + * pmap_page_protect: + * + * Lower the permission for all mappings to a given page. + */ +void +pmap_page_protect(vm_offset_t phys, vm_prot_t prot) +{ + if ((prot & VM_PROT_WRITE) == 0) { + if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { + pmap_changebit(phys, PG_KWE|PG_UWE, FALSE); + } else { + pmap_remove_all(phys); + } + } +} + +vm_offset_t +pmap_phys_address(ppn) + int ppn; +{ + return (alpha_ptob(ppn)); +} + +/* + * pmap_ts_referenced: + * + * Return the count of reference bits for a page, clearing all of them. + * + */ +int +pmap_ts_referenced(vm_offset_t pa) +{ + pv_table_t *ppv; + int ret; + + if (!pmap_is_managed(pa)) + return FALSE; + + ppv = pa_to_pvh(pa); + + ret = (ppv->pv_flags & PV_TABLE_REF) != 0; + ppv->pv_flags &= ~PV_TABLE_REF; + + return ret; +} + +/* + * pmap_is_modified: + * + * Return whether or not the specified physical page was modified + * in any physical maps. + */ +boolean_t +pmap_is_modified(vm_offset_t pa) +{ + pv_table_t *ppv; + + if (!pmap_is_managed(pa)) + return FALSE; + + ppv = pa_to_pvh(pa); + + return (ppv->pv_flags & PV_TABLE_MOD) != 0; +} + +/* + * Clear the modify bits on the specified physical page. + */ +void +pmap_clear_modify(vm_offset_t pa) +{ + pv_table_t *ppv; + + if (!pmap_is_managed(pa)) + return; + + ppv = pa_to_pvh(pa); + + if (ppv->pv_flags & PV_TABLE_MOD) { + pmap_changebit(pa, PG_FOW, TRUE); + ppv->pv_flags &= ~PV_TABLE_MOD; + } +} + +/* + * pmap_clear_reference: + * + * Clear the reference bit on the specified physical page. + */ +void +pmap_clear_reference(vm_offset_t pa) +{ + pv_table_t *ppv; + + if (!pmap_is_managed(pa)) + return; + + ppv = pa_to_pvh(pa); + + if (ppv->pv_flags & PV_TABLE_REF) { + pmap_changebit(pa, PG_FOR|PG_FOE|PG_FOW, TRUE); + ppv->pv_flags &= ~PV_TABLE_REF; + } +} + +/* + * pmap_emulate_reference: + * + * Emulate reference and/or modified bit hits. + * From NetBSD + */ +void +pmap_emulate_reference(struct proc *p, vm_offset_t v, int user, int write) +{ + pt_entry_t faultoff, *pte; + vm_offset_t pa; + pv_table_t *ppv; + + /* + * Convert process and virtual address to physical address. + */ + if (v >= VM_MIN_KERNEL_ADDRESS) { + if (user) + panic("pmap_emulate_reference: user ref to kernel"); + pte = vtopte(v); + } else { +#ifdef DIAGNOSTIC + if (p == NULL) + panic("pmap_emulate_reference: bad proc"); + if (p->p_vmspace == NULL) + panic("pmap_emulate_reference: bad p_vmspace"); +#endif + pte = pmap_lev3pte(p->p_vmspace->vm_map.pmap, v); + } +#ifdef DEBUG /* These checks are more expensive */ + if (!pmap_pte_v(pte)) + panic("pmap_emulate_reference: invalid pte"); +#if 0 + /* + * Can't do these, because cpu_fork and cpu_swapin call + * pmap_emulate_reference(), and the bits aren't guaranteed, + * for them... + */ + if (write) { + if (!(*pte & (user ? PG_UWE : PG_UWE | PG_KWE))) + panic("pmap_emulate_reference: write but unwritable"); + if (!(*pte & PG_FOW)) + panic("pmap_emulate_reference: write but not FOW"); + } else { + if (!(*pte & (user ? PG_URE : PG_URE | PG_KRE))) + panic("pmap_emulate_reference: !write but unreadable"); + if (!(*pte & (PG_FOR | PG_FOE))) + panic("pmap_emulate_reference: !write but not FOR|FOE"); + } +#endif + /* Other diagnostics? */ +#endif + pa = pmap_pte_pa(pte); + +#ifdef DIAGNOSTIC + if ((*pte & PG_MANAGED) == 0) + panic("pmap_emulate_reference(%p, 0x%lx, %d, %d): pa 0x%lx not managed", p, v, user, write, pa); +#endif + + /* + * Twiddle the appropriate bits to reflect the reference + * and/or modification.. + * + * The rules: + * (1) always mark page as used, and + * (2) if it was a write fault, mark page as modified. + */ + ppv = pa_to_pvh(pa); + ppv->pv_flags = PV_TABLE_REF; + faultoff = PG_FOR | PG_FOE; + ppv->pv_vm_page->flags |= PG_REFERENCED; + if (write) { + ppv->pv_flags |= PV_TABLE_MOD; + ppv->pv_vm_page->dirty = VM_PAGE_BITS_ALL; + faultoff |= PG_FOW; + } + pmap_changebit(pa, faultoff, FALSE); + if ((*pte & faultoff) != 0) { +#if 0 + /* + * This is apparently normal. Why? -- cgd + * XXX because was being called on unmanaged pages? + */ + printf("warning: pmap_changebit didn't."); +#endif + *pte &= ~faultoff; + ALPHA_TBIS(v); + } +} + +/* + * Miscellaneous support routines follow + */ + +static void +alpha_protection_init() +{ + int prot, *kp, *up; + + kp = protection_codes[0]; + up = protection_codes[1]; + + for (prot = 0; prot < 8; prot++) { + switch (prot) { + case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE: + *kp++ = PG_ASM; + *up++ = 0; + break; + case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE: + case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE: + case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE: + *kp++ = PG_ASM | PG_KRE; + *up++ = PG_URE | PG_KRE; + break; + case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE: + *kp++ = PG_ASM | PG_KWE; + *up++ = PG_UWE | PG_KWE; + break; + case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE: + case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE: + case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: + *kp++ = PG_ASM | PG_KWE | PG_KRE; + *up++ = PG_UWE | PG_URE | PG_KWE | PG_KRE; + break; + } + } +} + +/* + * Map a set of physical memory pages into the kernel virtual + * address space. Return a pointer to where it is mapped. This + * routine is intended to be used for mapping device memory, + * NOT real memory. + */ +void * +pmap_mapdev(pa, size) + vm_offset_t pa; + vm_size_t size; +{ + vm_offset_t va, tmpva; + pt_entry_t *pte; + + size = roundup(size, PAGE_SIZE); + + va = kmem_alloc_pageable(kernel_map, size); +#if !defined(MAX_PERF) + if (!va) + panic("pmap_mapdev: Couldn't alloc kernel virtual memory"); +#endif + + pa = pa & ~PAGE_MASK; + for (tmpva = va; size > 0;) { + pte = vtopte(tmpva); + *pte = pmap_phys_to_pte(pa) | PG_KRE | PG_KWE | PG_V; + size -= PAGE_SIZE; + tmpva += PAGE_SIZE; + pa += PAGE_SIZE; + } + ALPHA_TBIA(); + + return ((void *) va); +} + +/* + * perform the pmap work for mincore + */ +int +pmap_mincore(pmap, addr) + pmap_t pmap; + vm_offset_t addr; +{ + + pt_entry_t *pte; + vm_page_t m; + int val = 0; + + pte = pmap_lev3pte(pmap, addr); + if (pte == 0) { + return 0; + } + + if (pmap_pte_v(pte)) { + pv_table_t *ppv; + vm_offset_t pa; + + val = MINCORE_INCORE; + if ((*pte & PG_MANAGED) == 0) + return val; + + pa = pmap_pte_pa(pte); + + ppv = pa_to_pvh(pa); + m = ppv->pv_vm_page; + + /* + * Modified by us + */ + if (ppv->pv_flags & PV_TABLE_MOD) + val |= MINCORE_MODIFIED|MINCORE_MODIFIED_OTHER; + /* + * Modified by someone + */ + else if (m->dirty || pmap_is_modified(pa)) + val |= MINCORE_MODIFIED_OTHER; + /* + * Referenced by us + */ + if (ppv->pv_flags & PV_TABLE_REF) + val |= MINCORE_REFERENCED|MINCORE_REFERENCED_OTHER; + + /* + * Referenced by someone + */ + else if ((m->flags & PG_REFERENCED) || pmap_ts_referenced(pa)) { + val |= MINCORE_REFERENCED_OTHER; + m->flags |= PG_REFERENCED; + } + } + return val; +} + +void +pmap_activate(struct proc *p) +{ + pmap_t pmap; + + pmap = &p->p_vmspace->vm_pmap; + p->p_addr->u_pcb.pcb_hw.apcb_ptbr = + ALPHA_K0SEG_TO_PHYS((vm_offset_t) pmap->pm_lev1) >> PAGE_SHIFT; + + if (p == curproc) { + alpha_pal_swpctx((u_long)p->p_md.md_pcbpaddr); + } else + /* XXX remove after implementing ASNs */ + ALPHA_TBIA(); + +} + +void +pmap_deactivate(struct proc *p) +{ +} + +vm_offset_t +pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size) { + + return addr; +} + +#if 0 +#if defined(PMAP_DEBUG) +pmap_pid_dump(int pid) { + pmap_t pmap; + struct proc *p; + int npte = 0; + int index; + for (p = allproc.lh_first; p != NULL; p = p->p_list.le_next) { + if (p->p_pid != pid) + continue; + + if (p->p_vmspace) { + int i,j; + index = 0; + pmap = &p->p_vmspace->vm_pmap; + for(i=0;i<1024;i++) { + pd_entry_t *pde; + pt_entry_t *pte; + unsigned base = i << PDRSHIFT; + + pde = &pmap->pm_pdir[i]; + if (pde && pmap_pde_v(pde)) { + for(j=0;j<1024;j++) { + unsigned va = base + (j << PAGE_SHIFT); + if (va >= (vm_offset_t) VM_MIN_KERNEL_ADDRESS) { + if (index) { + index = 0; + printf("\n"); + } + return npte; + } + pte = pmap_pte_quick( pmap, va); + if (pte && pmap_pte_v(pte)) { + vm_offset_t pa; + vm_page_t m; + pa = *(int *)pte; + m = PHYS_TO_VM_PAGE((pa & PG_FRAME)); + printf("va: 0x%x, pt: 0x%x, h: %d, w: %d, f: 0x%x", + va, pa, m->hold_count, m->wire_count, m->flags); + npte++; + index++; + if (index >= 2) { + index = 0; + printf("\n"); + } else { + printf(" "); + } + } + } + } + } + } + } + return npte; +} +#endif + +#if defined(DEBUG) + +static void pads __P((pmap_t pm)); +static void pmap_pvdump __P((vm_offset_t pa)); + +/* print address space of pmap*/ +static void +pads(pm) + pmap_t pm; +{ + int i, j; + vm_offset_t va; + pt_entry_t *ptep; + + if (pm == kernel_pmap) + return; + for (i = 0; i < 1024; i++) + if (pm->pm_pdir[i]) + for (j = 0; j < 1024; j++) { + va = (i << PDRSHIFT) + (j << PAGE_SHIFT); + if (pm == kernel_pmap && va < KERNBASE) + continue; + if (pm != kernel_pmap && va > UPT_MAX_ADDRESS) + continue; + ptep = pmap_pte_quick(pm, va); + if (pmap_pte_v(ptep)) + printf("%x:%x ", va, *(int *) ptep); + }; + +} + +static void +pmap_pvdump(pa) + vm_offset_t pa; +{ + pv_table_t *ppv; + register pv_entry_t pv; + + printf("pa %x", pa); + ppv = pa_to_pvh(pa); + for (pv = TAILQ_FIRST(&ppv->pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { +#ifdef used_to_be + printf(" -> pmap %x, va %x, flags %x", + pv->pv_pmap, pv->pv_va, pv->pv_flags); +#endif + printf(" -> pmap %x, va %x", + pv->pv_pmap, pv->pv_va); + pads(pv->pv_pmap); + } + printf(" "); +} +#endif +#endif diff --git a/sys/alpha/alpha/procfs_machdep.c b/sys/alpha/alpha/procfs_machdep.c new file mode 100644 index 0000000..11898d0 --- /dev/null +++ b/sys/alpha/alpha/procfs_machdep.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1993 Jan-Simon Pendry + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * 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. + * + * @(#)procfs_machdep.c 8.3 (Berkeley) 1/27/94 + * + * From: + * $Id: procfs_machdep.c,v 1.10 1997/07/20 08:37:22 bde Exp $ + */ + +/* + * Functions to be implemented here are: + * + * procfs_read_regs(proc, regs) + * Get the current user-visible register set from the process + * and copy it into the regs structure (<machine/reg.h>). + * The process is stopped at the time read_regs is called. + * + * procfs_write_regs(proc, regs) + * Update the current register set from the passed in regs + * structure. Take care to avoid clobbering special CPU + * registers or privileged bits in the PSL. + * Depending on the architecture this may have fix-up work to do, + * especially if the IAR or PCW are modified. + * The process is stopped at the time write_regs is called. + * + * procfs_read_fpregs, procfs_write_fpregs + * deal with the floating point register set, otherwise as above. + * + * procfs_sstep(proc) + * Arrange for the process to trap after executing a single instruction. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/ptrace.h> +#include <sys/vnode.h> +#include <machine/reg.h> +#include <machine/md_var.h> +#include <miscfs/procfs/procfs.h> + +#include <vm/vm.h> +#include <sys/lock.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> + +#include <sys/user.h> + +int +procfs_read_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + return (fill_regs(p, regs)); +} + +int +procfs_write_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + return (set_regs(p, regs)); +} + +/* + * Ptrace doesn't support fpregs at all, and there are no security holes + * or translations for fpregs, so we can just copy them. + */ + +int +procfs_read_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + + if (p == fpcurproc) { + alpha_pal_wrfen(1); + savefpstate(&p->p_addr->u_pcb.pcb_fp); + alpha_pal_wrfen(0); + } + + bcopy(&p->p_addr->u_pcb.pcb_fp, fpregs, sizeof *fpregs); + return (0); +} + +int +procfs_write_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + + if (p == fpcurproc) + fpcurproc = NULL; + + bcopy(fpregs, &p->p_addr->u_pcb.pcb_fp, sizeof *fpregs); + return (0); +} + +int +procfs_sstep(p) + struct proc *p; +{ + return (EINVAL); +} diff --git a/sys/alpha/alpha/prom.c b/sys/alpha/alpha/prom.c new file mode 100644 index 0000000..1069ac7 --- /dev/null +++ b/sys/alpha/alpha/prom.c @@ -0,0 +1,361 @@ +/* $NetBSD: prom.c,v 1.22 1998/02/27 04:03:00 thorpej Exp $ */ + +/* + * Copyright (c) 1992, 1994, 1995, 1996 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include "opt_simos.h" + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +/* __KERNEL_RCSID(0, "$NetBSD: prom.c,v 1.22 1998/02/27 04:03:00 thorpej Exp $"); */ + +#include <stddef.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_prot.h> +#include <vm/vm_map.h> +#include <sys/proc.h> +#include <sys/user.h> + +#include <machine/rpb.h> +#include <machine/prom.h> +#include <machine/vmparam.h> + +#include <machine/cons.h> + +/* XXX this is to fake out the console routines, while booting. */ +struct consdev promcons = { NULL, NULL, promcngetc, NULL, promcnputc, + NULL, NODEV, CN_NORMAL }; + +struct rpb *hwrpb; +int alpha_console; + +extern struct prom_vec prom_dispatch_v; + +int prom_mapped = 1; /* Is PROM still mapped? */ +pt_entry_t rom_pte, saved_pte[1]; /* XXX */ + +static pt_entry_t *rom_lev1map __P((void)); +extern struct pcb* curpcb; +extern pt_entry_t* Lev1map; + +static void prom_cache_sync __P((void)); + +static pt_entry_t * +rom_lev1map() +{ + struct alpha_pcb *apcb; + + /* + * We may be called before the first context switch + * after alpha_init(), in which case we just need + * to use the kernel Lev1map. + */ + if (curpcb == 0) + return (Lev1map); + + /* + * Find the level 1 map that we're currently running on. + */ + apcb = (struct alpha_pcb *)ALPHA_PHYS_TO_K0SEG((vm_offset_t) curpcb); + + return ((pt_entry_t *)ALPHA_PHYS_TO_K0SEG(alpha_ptob(apcb->apcb_ptbr))); +} + +void +init_prom_interface(rpb) + struct rpb *rpb; +{ + struct crb *c; + + c = (struct crb *)((char *)rpb + rpb->rpb_crb_off); + + prom_dispatch_v.routine_arg = c->crb_v_dispatch; + prom_dispatch_v.routine = c->crb_v_dispatch->entry_va; +} + +extern struct consdev* cn_tab; + +void +init_bootstrap_console() +{ + char buf[4]; + + init_prom_interface(hwrpb); + +#ifdef SIMOS + alpha_console = 0; +#else + prom_getenv(PROM_E_TTY_DEV, buf, 4); + alpha_console = buf[0] - '0'; +#endif + + /* XXX fake out the console routines, for now */ + cn_tab = &promcons; +} + +static int enter_prom __P((void)); +static void leave_prom __P((int)); +#ifdef _PMAP_MAY_USE_PROM_CONSOLE +static void prom_cache_sync __P((void)); +#endif + +static int +enter_prom() +{ + int s = splhigh(); + + pt_entry_t *lev1map; + + if (!prom_mapped) { +#ifdef SIMOS + /* + * SimOS console uses floating point. + */ + if (curproc != fpcurproc) { + alpha_pal_wrfen(1); + if (fpcurproc) + savefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); + fpcurproc = curproc; + restorefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); + } +#endif + if (!pmap_uses_prom_console()) + panic("enter_prom"); + lev1map = rom_lev1map(); /* XXX */ + saved_pte[0] = lev1map[0]; /* XXX */ + lev1map[0] = rom_pte; /* XXX */ + prom_cache_sync(); /* XXX */ + } + return s; +} + +static void +leave_prom __P((s)) + int s; +{ + + pt_entry_t *lev1map; + + if (!prom_mapped) { + if (!pmap_uses_prom_console()) + panic("leave_prom"); + lev1map = rom_lev1map(); /* XXX */ + lev1map[0] = saved_pte[0]; /* XXX */ + prom_cache_sync(); /* XXX */ + } + splx(s); +} + +static void +prom_cache_sync __P((void)) +{ + ALPHA_TBIA(); + alpha_pal_imb(); +} + +/* + * promcnputc: + * + * Remap char before passing off to prom. + * + * Prom only takes 32 bit addresses. Copy char somewhere prom can + * find it. This routine will stop working after pmap_rid_of_console + * is called in alpha_init. This is due to the hard coded address + * of the console area. + */ +void +promcnputc(dev, c) + dev_t dev; + int c; +{ + prom_return_t ret; + unsigned char *to = (unsigned char *)0x20000000; + int s; + + s = enter_prom(); /* splhigh() and map prom */ + *to = c; + + do { + ret.bits = prom_putstr(alpha_console, to, 1); + } while ((ret.u.retval & 1) == 0); + + leave_prom(s); /* unmap prom and splx(s) */ +} + +/* + * promcngetc: + * + * Wait for the prom to get a real char and pass it back. + */ +int +promcngetc(dev) + dev_t dev; +{ + prom_return_t ret; + int s; + + for (;;) { + s = enter_prom(); + ret.bits = prom_getc(alpha_console); + leave_prom(s); + if (ret.u.status == 0 || ret.u.status == 1) + return (ret.u.retval); + } +} + +/* + * promcnlookc: + * + * See if prom has a real char and pass it back. + */ +int +promcnlookc(dev, cp) + dev_t dev; + char *cp; +{ + prom_return_t ret; + int s; + + s = enter_prom(); + ret.bits = prom_getc(alpha_console); + leave_prom(s); + if (ret.u.status == 0 || ret.u.status == 1) { + *cp = ret.u.retval; + return 1; + } else + return 0; +} + +int +prom_getenv(id, buf, len) + int id, len; + char *buf; +{ + unsigned char *to = (unsigned char *)0x20000000; + prom_return_t ret; + int s; + + s = enter_prom(); + ret.bits = prom_getenv_disp(id, to, len); + bcopy(to, buf, len); + leave_prom(s); + + if (ret.u.status & 0x4) + ret.u.retval = 0; + buf[ret.u.retval] = '\0'; + + return (ret.bits); +} + +void +prom_halt(halt) + int halt; +{ + struct pcs *p; + + /* + * Turn off interrupts, for sanity. + */ + (void) splhigh(); + + /* + * Set "boot request" part of the CPU state depending on what + * we want to happen when we halt. + */ + p = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off + + (hwrpb->rpb_primary_cpu_id * hwrpb->rpb_pcs_size)); + p->pcs_flags &= ~(PCS_RC | PCS_HALT_REQ); + if (halt) + p->pcs_flags |= PCS_HALT_STAY_HALTED; + else + p->pcs_flags |= PCS_HALT_WARM_BOOT; + + /* + * Halt the machine. + */ + alpha_pal_halt(); +} + +u_int64_t +hwrpb_checksum() +{ + u_int64_t *p, sum; + int i; + + for (i = 0, p = (u_int64_t *)hwrpb, sum = 0; + i < (offsetof(struct rpb, rpb_checksum) / sizeof (u_int64_t)); + i++, p++) + sum += *p; + + return (sum); +} + +void +hwrpb_restart_setup() +{ + struct pcs *p; + + /* Clear bootstrap-in-progress flag since we're done bootstrapping */ + p = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off); + p->pcs_flags &= ~PCS_BIP; + + bcopy(&proc0.p_addr->u_pcb.pcb_hw, p->pcs_hwpcb, + sizeof proc0.p_addr->u_pcb.pcb_hw); + hwrpb->rpb_vptb = VPTBASE; + + /* when 'c'ontinuing from console halt, do a dump */ + hwrpb->rpb_rest_term = (u_int64_t)&XentRestart; + hwrpb->rpb_rest_term_val = 0x1; + +#if 0 + /* don't know what this is really used by, so don't mess with it. */ + hwrpb->rpb_restart = (u_int64_t)&XentRestart; + hwrpb->rpb_restart_val = 0x2; +#endif + + hwrpb->rpb_checksum = hwrpb_checksum(); + + p->pcs_flags |= (PCS_RC | PCS_CV); +} + +u_int64_t +console_restart(ra, ai, pv) + u_int64_t ra, ai, pv; +{ + struct pcs *p; + + /* Clear restart-capable flag, since we can no longer restart. */ + p = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off); + p->pcs_flags &= ~PCS_RC; + + panic("user requested console halt"); + + return (1); +} diff --git a/sys/alpha/alpha/prom_disp.s b/sys/alpha/alpha/prom_disp.s new file mode 100644 index 0000000..23bdbef --- /dev/null +++ b/sys/alpha/alpha/prom_disp.s @@ -0,0 +1,116 @@ +/* $NetBSD: prom_disp.s,v 1.8 1997/11/03 04:22:03 ross Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _LOCORE +#include <machine/asm.h> +#else +__KERNEL_RCSID(2, "$NetBSD: prom_disp.s,v 1.8 1997/11/03 04:22:03 ross Exp $"); +#endif + + .globl prom_dispatch_v + .comm prom_dispatch_v,16 + + .text + .align 4 + +inc3: .stabs __FILE__,132,0,0,inc3; .loc 1 __LINE__ +/* + * Dispatcher routine. Implements prom's calling machinery, saves our + * callee-saved registers as required by C. + */ +#define D_RA (7*8) +#define D_S0 (8*8) +#define D_S1 (9*8) +#define D_S2 (10*8) +#define D_S3 (11*8) +#define D_S4 (12*8) +#define D_S5 (13*8) +#define D_S6 (14*8) +#define DISPATCH_FRAME_SIZE (15*8) +#define DISPATCH_REGS IM_RA|IM_S0|IM_S1|IM_S2|IM_S3|IM_S4|IM_S5|IM_S6 + +NESTED(prom_dispatch, 5, DISPATCH_FRAME_SIZE, ra, DISPATCH_REGS, 0) + + ldgp gp, 0(pv) + + lda sp, -DISPATCH_FRAME_SIZE(sp) + stq ra, D_RA(sp) + stq s0, D_S0(sp) + stq s1, D_S1(sp) + stq s2, D_S2(sp) + stq s3, D_S3(sp) + stq s4, D_S4(sp) + stq s5, D_S5(sp) + stq s6, D_S6(sp) + + /* Lord have mercy because.. I would not. */ +#define STUPID_PROM_IS_32_BITS +#ifdef STUPID_PROM_IS_32_BITS + ldah s0, 0x2000(zero) /* hack for hack */ + lda s0, (0x2000-8)(s0) + + stq sp, 0(s0) + or s0, zero, sp +#endif /* STUPID_PROM_IS_32_BITS */ + + lda pv, prom_dispatch_v + ldq v0, 0(pv) /* routine */ + ldq pv, 8(pv) /* routine_arg */ + + jsr ra, (v0) + +#ifdef STUPID_PROM_IS_32_BITS + ldah s0, 0x2000(zero) /* hack for hack */ + lda s0, (0x2000-8)(s0) + + ldq sp, 0(s0) +#endif /* STUPID_PROM_IS_32_BITS */ + + ldq ra, D_RA(sp) + ldq s0, D_S0(sp) + ldq s1, D_S1(sp) + ldq s2, D_S2(sp) + ldq s3, D_S3(sp) + ldq s4, D_S4(sp) + ldq s5, D_S5(sp) + ldq s6, D_S6(sp) + lda sp, DISPATCH_FRAME_SIZE(sp) + RET +END(prom_dispatch) + +#undef D_RA +#undef D_S0 +#undef D_S1 +#undef D_S2 +#undef D_S3 +#undef D_S4 +#undef D_S5 +#undef D_S6 +#undef DISPATCH_FRAME_SIZE +#undef DISPATCH_REGS diff --git a/sys/alpha/alpha/promcons.c b/sys/alpha/alpha/promcons.c new file mode 100644 index 0000000..8be259a6 --- /dev/null +++ b/sys/alpha/alpha/promcons.c @@ -0,0 +1,249 @@ +/* $NetBSD: promcons.c,v 1.13 1998/03/21 22:52:59 mycroft Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: promcons.c,v 1.13 1998/03/21 22:52:59 mycroft Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/select.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/file.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/syslog.h> +#include <sys/types.h> +#include <sys/device.h> +#include <vm/vm.h> /* XXX for _PMAP_MAY_USE_PROM_CONSOLE */ + +#include <machine/conf.h> +#include <machine/prom.h> + +#ifdef _PMAP_MAY_USE_PROM_CONSOLE + +#define PROM_POLL_HZ 50 + +static struct tty *prom_tty[1]; +static int polltime; + +void promstart __P((struct tty *)); +void promtimeout __P((void *)); +int promparam __P((struct tty *, struct termios *)); + +int +promopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = minor(dev); + struct tty *tp; + int s; + int error = 0, setuptimeout = 0; + + if (!pmap_uses_prom_console() || unit >= 1) + return ENXIO; + + s = spltty(); + + if (!prom_tty[unit]) { + tp = prom_tty[unit] = ttymalloc(); + tty_attach(tp); + } else + tp = prom_tty[unit]; + + tp->t_oproc = promstart; + tp->t_param = promparam; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_CARR_ON; + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG|CLOCAL; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = 9600; + ttsetwater(tp); + + setuptimeout = 1; + } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) { + splx(s); + return EBUSY; + } + + splx(s); + + error = (*linesw[tp->t_line].l_open)(dev, tp); + if (error == 0 && setuptimeout) { + polltime = hz / PROM_POLL_HZ; + if (polltime < 1) + polltime = 1; + timeout(promtimeout, tp, polltime); + } + return error; +} + +int +promclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = minor(dev); + struct tty *tp = prom_tty[unit]; + + untimeout(promtimeout, tp); + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + return 0; +} + +int +promread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct tty *tp = prom_tty[minor(dev)]; + + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +promwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct tty *tp = prom_tty[minor(dev)]; + + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +int +promioctl(dev, cmd, data, flag, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + int unit = minor(dev); + struct tty *tp = prom_tty[unit]; + int error; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return error; + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return error; + + return ENOTTY; +} + +int +promparam(tp, t) + struct tty *tp; + struct termios *t; +{ + + return 0; +} + +void +promstart(tp) + struct tty *tp; +{ + int s; + + s = spltty(); + if (tp->t_state & (TS_TTSTOP | TS_BUSY)) + goto out; + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup((caddr_t)&tp->t_outq); + } + selwakeup(&tp->t_wsel); + } + tp->t_state |= TS_BUSY; + while (tp->t_outq.c_cc != 0) + promcnputc(tp->t_dev, getc(&tp->t_outq)); + tp->t_state &= ~TS_BUSY; +out: + splx(s); +} + +/* + * Stop output on a line. + */ +void +promstop(tp, flag) + struct tty *tp; +{ + int s; + + s = spltty(); + if (tp->t_state & TS_BUSY) + if ((tp->t_state & TS_TTSTOP) == 0) + tp->t_state |= TS_FLUSH; + splx(s); +} + +void +promtimeout(v) + void *v; +{ + struct tty *tp = v; + u_char c; + + while (promcnlookc(tp->t_dev, &c)) { + if (tp->t_state & TS_ISOPEN) + (*linesw[tp->t_line].l_rint)(c, tp); + } + timeout(promtimeout, tp, polltime); +} + +struct tty * +promtty(dev) + dev_t dev; +{ + + if (minor(dev) != 0) + panic("promtty: bogus"); + + return prom_tty[0]; +} + +#endif /* _PMAP_MAY_USE_PROM_CONSOLE */ diff --git a/sys/alpha/alpha/setdef0.c b/sys/alpha/alpha/setdef0.c new file mode 100644 index 0000000..e91857f --- /dev/null +++ b/sys/alpha/alpha/setdef0.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 1997 John D. Polstra + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id: setdef0.c,v 1.2 1997/05/21 23:21:30 jdp Exp $ + */ + +#ifdef __ELF__ + +#include <sys/param.h> +#include <sys/kernel.h> + +/* + * DEFINE_SET creates the section and label for a set, and emits the + * count word at the front of it. + */ +#define DEFINE_SET(set, count) \ + __asm__(".section .set." #set ",\"aw\""); \ + __asm__(".globl " #set); \ + __asm__(".type " #set ",@object"); \ + __asm__(".p2align 3"); \ + __asm__(#set ":"); \ + __asm__(".quad " #count); \ + __asm__(".previous") + +#include "setdefs.h" /* Contains a `DEFINE_SET' for each set */ + +#endif /* __ELF__ */ diff --git a/sys/alpha/alpha/setdef1.c b/sys/alpha/alpha/setdef1.c new file mode 100644 index 0000000..0b2bbaa --- /dev/null +++ b/sys/alpha/alpha/setdef1.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 1997 John D. Polstra + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id: setdef1.c,v 1.2 1997/05/21 23:21:30 jdp Exp $ + */ + +#ifdef __ELF__ + +/* + * DEFINE_SET emits the NULL terminator for a set. + */ +#define DEFINE_SET(set, count) \ + __asm__(".section .set." #set ",\"aw\""); \ + __asm__(".quad 0"); \ + __asm__(".previous") + +#include "setdefs.h" /* Contains a `DEFINE_SET' for each set */ + +#endif /* __ELF__ */ diff --git a/sys/alpha/alpha/support.s b/sys/alpha/alpha/support.s new file mode 100644 index 0000000..1bf8b45 --- /dev/null +++ b/sys/alpha/alpha/support.s @@ -0,0 +1,626 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <machine/asm.h> +#include <assym.s> + + .text + +/**************************************************************************/ + +/* + * fu{byte,word} : fetch a byte (word) from user memory + */ + + LEAF(suword, 1) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + stq a1, 0(a0) /* try the store */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + mov zero, v0 + RET + END(suword) + + LEAF(subyte, 1) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + zap a1, 0xfe, a1 /* mask off the byte to store */ + insbl a1, a0, a1 /* shift it to the right place */ + ldq_u t0, 0(a0) /* read the qword to store it in */ + mskbl t0, a0, t0 /* make a place for our byte */ + or a1, t0, a1 /* move it in */ + stq_u a1, 0(a0) /* and put the byte back */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + mov zero, v0 + RET + END(subyte) + + LEAF(fuword, 1) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + ldq v0, 0(a0) /* try the fetch */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + RET + END(fuword) + + LEAF(fubyte, 1) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + ldq_u v0, 0(a0) /* get the word containing our byte */ + extbl v0, a0, v0 /* extract the byte */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + mov zero, v0 + RET + END(fubyte) + + LEAF(suibyte, 2) + ldiq v0, -1 + RET + END(suibyte) + + LEAF(fusufault, 0) + ldq t0, curproc + ldq t0, P_ADDR(t0) + stq zero, U_PCB_ONFAULT(t0) + ldiq v0, -1 + RET + END(fusufault) + +LEAF(fswintrberr, 0) +XLEAF(fuswintr, 2) /* XXX what is a 'word'? */ +XLEAF(suswintr, 2) /* XXX what is a 'word'? */ + LDGP(pv) + ldiq v0, -1 + RET + END(fswintrberr) + +/**************************************************************************/ + +/* + * Copy a null-terminated string within the kernel's address space. + * If lenp is not NULL, store the number of chars copied in *lenp + * + * int copystr(char *from, char *to, size_t len, size_t *lenp); + */ +LEAF(copystr, 4) + LDGP(pv) + + mov a2, t0 /* t0 = i = len */ + beq a2, Lcopystr2 /* if (len == 0), bail out */ + +Lcopystr1: + ldq_u t1, 0(a0) /* t1 = *from */ + extbl t1, a0, t1 + ldq_u t3, 0(a1) /* set up t2 with quad around *to */ + insbl t1, a1, t2 + mskbl t3, a1, t3 + or t3, t2, t3 /* add *from to quad around *to */ + stq_u t3, 0(a1) /* write out that quad */ + + subl a2, 1, a2 /* len-- */ + beq t1, Lcopystr2 /* if (*from == 0), bail out */ + addq a1, 1, a1 /* to++ */ + addq a0, 1, a0 /* from++ */ + bne a2, Lcopystr1 /* if (len != 0) copy more */ + +Lcopystr2: + beq a3, Lcopystr3 /* if (lenp != NULL) */ + subl t0, a2, t0 /* *lenp = (i - len) */ + stq t0, 0(a3) +Lcopystr3: + beq t1, Lcopystr4 /* *from == '\0'; leave quietly */ + + ldiq v0, ENAMETOOLONG /* *from != '\0'; error. */ + RET + +Lcopystr4: + mov zero, v0 /* return 0. */ + RET + END(copystr) + +NESTED(copyinstr, 4, 16, ra, 0, 0) + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */ + cmpult a0, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(copystr) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + RET /* v0 left over from copystr */ + END(copyinstr) + +NESTED(copyoutstr, 4, 16, ra, 0, 0) + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */ + cmpult a1, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(copystr) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + RET /* v0 left over from copystr */ + END(copyoutstr) + +/* + * Alternative memory mover + */ + LEAF(memcpy,3) + mov a0,t0 + mov a1,a0 + mov t0,a1 + br bcopy + END(memcpy) + +/* + * Copy a bytes within the kernel's address space. + * + * In the kernel, bcopy() doesn't have to handle the overlapping + * case; that's that ovbcopy() is for. However, it doesn't hurt + * to do both in bcopy, and it does provide a measure of safety. + * + * void bcopy(char *from, char *to, size_t len); + * void ovbcopy(char *from, char *to, size_t len); + */ +LEAF(bcopy,3) +XLEAF(ovbcopy,3) + + /* Check for negative length */ + ble a2,bcopy_done + + /* Check for overlap */ + subq a1,a0,t5 + cmpult t5,a2,t5 + bne t5,bcopy_overlap + + /* a3 = end address */ + addq a0,a2,a3 + + /* Get the first word */ + ldq_u t2,0(a0) + + /* Do they have the same alignment? */ + xor a0,a1,t0 + and t0,7,t0 + and a1,7,t1 + bne t0,bcopy_different_alignment + + /* src & dst have same alignment */ + beq t1,bcopy_all_aligned + + ldq_u t3,0(a1) + addq a2,t1,a2 + mskqh t2,a0,t2 + mskql t3,a0,t3 + or t2,t3,t2 + + /* Dst is 8-byte aligned */ + +bcopy_all_aligned: + /* If less than 8 bytes,skip loop */ + subq a2,1,t0 + and a2,7,a2 + bic t0,7,t0 + beq t0,bcopy_samealign_lp_end + +bcopy_samealign_lp: + stq_u t2,0(a1) + addq a1,8,a1 + ldq_u t2,8(a0) + subq t0,8,t0 + addq a0,8,a0 + bne t0,bcopy_samealign_lp + +bcopy_samealign_lp_end: + /* If we're done, exit */ + bne a2,bcopy_small_left + stq_u t2,0(a1) + RET + +bcopy_small_left: + mskql t2,a2,t4 + ldq_u t3,0(a1) + mskqh t3,a2,t3 + or t4,t3,t4 + stq_u t4,0(a1) + RET + +bcopy_different_alignment: + /* + * this is the fun part + */ + addq a0,a2,a3 + cmpule a2,8,t0 + bne t0,bcopy_da_finish + + beq t1,bcopy_da_noentry + + /* Do the initial partial word */ + subq zero,a1,t0 + and t0,7,t0 + ldq_u t3,7(a0) + extql t2,a0,t2 + extqh t3,a0,t3 + or t2,t3,t5 + insql t5,a1,t5 + ldq_u t6,0(a1) + mskql t6,a1,t6 + or t5,t6,t5 + stq_u t5,0(a1) + addq a0,t0,a0 + addq a1,t0,a1 + subq a2,t0,a2 + ldq_u t2,0(a0) + +bcopy_da_noentry: + subq a2,1,t0 + bic t0,7,t0 + and a2,7,a2 + beq t0,bcopy_da_finish2 + +bcopy_da_lp: + ldq_u t3,7(a0) + addq a0,8,a0 + extql t2,a0,t4 + extqh t3,a0,t5 + subq t0,8,t0 + or t4,t5,t5 + stq t5,0(a1) + addq a1,8,a1 + beq t0,bcopy_da_finish1 + ldq_u t2,7(a0) + addq a0,8,a0 + extql t3,a0,t4 + extqh t2,a0,t5 + subq t0,8,t0 + or t4,t5,t5 + stq t5,0(a1) + addq a1,8,a1 + bne t0,bcopy_da_lp + +bcopy_da_finish2: + /* Do the last new word */ + mov t2,t3 + +bcopy_da_finish1: + /* Do the last partial word */ + ldq_u t2,-1(a3) + extql t3,a0,t3 + extqh t2,a0,t2 + or t2,t3,t2 + br zero,bcopy_samealign_lp_end + +bcopy_da_finish: + /* Do the last word in the next source word */ + ldq_u t3,-1(a3) + extql t2,a0,t2 + extqh t3,a0,t3 + or t2,t3,t2 + insqh t2,a1,t3 + insql t2,a1,t2 + lda t4,-1(zero) + mskql t4,a2,t5 + cmovne t5,t5,t4 + insqh t4,a1,t5 + insql t4,a1,t4 + addq a1,a2,a4 + ldq_u t6,0(a1) + ldq_u t7,-1(a4) + bic t6,t4,t6 + bic t7,t5,t7 + and t2,t4,t2 + and t3,t5,t3 + or t2,t6,t2 + or t3,t7,t3 + stq_u t3,-1(a4) + stq_u t2,0(a1) + RET + +bcopy_overlap: + /* + * Basically equivalent to previous case, only backwards. + * Not quite as highly optimized + */ + addq a0,a2,a3 + addq a1,a2,a4 + + /* less than 8 bytes - don't worry about overlap */ + cmpule a2,8,t0 + bne t0,bcopy_ov_short + + /* Possibly do a partial first word */ + and a4,7,t4 + beq t4,bcopy_ov_nostart2 + subq a3,t4,a3 + subq a4,t4,a4 + ldq_u t1,0(a3) + subq a2,t4,a2 + ldq_u t2,7(a3) + ldq t3,0(a4) + extql t1,a3,t1 + extqh t2,a3,t2 + or t1,t2,t1 + mskqh t3,t4,t3 + mskql t1,t4,t1 + or t1,t3,t1 + stq t1,0(a4) + +bcopy_ov_nostart2: + bic a2,7,t4 + and a2,7,a2 + beq t4,bcopy_ov_lp_end + +bcopy_ov_lp: + /* This could be more pipelined, but it doesn't seem worth it */ + ldq_u t0,-8(a3) + subq a4,8,a4 + ldq_u t1,-1(a3) + subq a3,8,a3 + extql t0,a3,t0 + extqh t1,a3,t1 + subq t4,8,t4 + or t0,t1,t0 + stq t0,0(a4) + bne t4,bcopy_ov_lp + +bcopy_ov_lp_end: + beq a2,bcopy_done + + ldq_u t0,0(a0) + ldq_u t1,7(a0) + ldq_u t2,0(a1) + extql t0,a0,t0 + extqh t1,a0,t1 + or t0,t1,t0 + insql t0,a1,t0 + mskql t2,a1,t2 + or t2,t0,t2 + stq_u t2,0(a1) + +bcopy_done: + RET + +bcopy_ov_short: + ldq_u t2,0(a0) + br zero,bcopy_da_finish + + END(bcopy) + +NESTED(copyin, 3, 16, ra, 0, 0) + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */ + cmpult a0, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(bcopy) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + mov zero, v0 /* return 0. */ + RET + END(copyin) + +NESTED(copyout, 3, 16, ra, 0, 0) + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */ + cmpult a1, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(bcopy) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + mov zero, v0 /* return 0. */ + RET + END(copyout) + +LEAF(copyerr, 0) + LDGP(pv) + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + ldiq v0, EFAULT /* return EFAULT. */ + RET +END(copyerr) + +/**************************************************************************/ + +/* + * Kernel setjmp and longjmp. Rather minimalist. + * + * longjmp(label_t *a) + * will generate a "return (1)" from the last call to + * setjmp(label_t *a) + * by restoring registers from the stack, + */ + + .set noreorder + +LEAF(setjmp, 1) + LDGP(pv) + + stq ra, (0 * 8)(a0) /* return address */ + stq s0, (1 * 8)(a0) /* callee-saved registers */ + stq s1, (2 * 8)(a0) + stq s2, (3 * 8)(a0) + stq s3, (4 * 8)(a0) + stq s4, (5 * 8)(a0) + stq s5, (6 * 8)(a0) + stq s6, (7 * 8)(a0) + stq sp, (8 * 8)(a0) + + ldiq t0, 0xbeeffedadeadbabe /* set magic number */ + stq t0, (9 * 8)(a0) + + mov zero, v0 /* return zero */ + RET +END(setjmp) + +LEAF(longjmp, 1) + LDGP(pv) + + ldiq t0, 0xbeeffedadeadbabe /* check magic number */ + ldq t1, (9 * 8)(a0) + cmpeq t0, t1, t0 + beq t0, longjmp_botch /* if bad, punt */ + + ldq ra, (0 * 8)(a0) /* return address */ + ldq s0, (1 * 8)(a0) /* callee-saved registers */ + ldq s1, (2 * 8)(a0) + ldq s2, (3 * 8)(a0) + ldq s3, (4 * 8)(a0) + ldq s4, (5 * 8)(a0) + ldq s5, (6 * 8)(a0) + ldq s6, (7 * 8)(a0) + ldq sp, (8 * 8)(a0) + + ldiq v0, 1 + RET + +longjmp_botch: + lda a0, longjmp_botchmsg + mov ra, a1 + CALL(panic) + call_pal PAL_bugchk + + .data +longjmp_botchmsg: + .asciz "longjmp botch from %p" + .text +END(longjmp) diff --git a/sys/alpha/alpha/swtch.s b/sys/alpha/alpha/swtch.s new file mode 100644 index 0000000..2953f1d --- /dev/null +++ b/sys/alpha/alpha/swtch.s @@ -0,0 +1,388 @@ +/* $Id$ */ +/* $NetBSD: locore.s,v 1.47 1998/03/22 07:26:32 thorpej Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <machine/asm.h> +#include "assym.s" + +/**************************************************************************/ + +/* + * Perform actions necessary to switch to a new context. The + * hwpcb should be in a0. + */ +#define SWITCH_CONTEXT \ + /* Make a note of the context we're running on. */ \ + stq a0, curpcb; \ + \ + /* Swap in the new context. */ \ + call_pal PAL_OSF1_swpctx + +/* + * savectx: save process context, i.e. callee-saved registers + * + * Note that savectx() only works for processes other than curproc, + * since cpu_switch will copy over the info saved here. (It _can_ + * sanely be used for curproc iff cpu_switch won't be called again, e.g. + * from if called from boot().) + * + * Arguments: + * a0 'struct user *' of the process that needs its context saved + * + * Return: + * v0 0. (note that for child processes, it seems + * like savectx() returns 1, because the return address + * in the PCB is set to the return address from savectx().) + */ + +LEAF(savectx, 1) + br pv, Lsavectx1 +Lsavectx1: LDGP(pv) + stq sp, U_PCB_HWPCB_KSP(a0) /* store sp */ + stq s0, U_PCB_CONTEXT+(0 * 8)(a0) /* store s0 - s6 */ + stq s1, U_PCB_CONTEXT+(1 * 8)(a0) + stq s2, U_PCB_CONTEXT+(2 * 8)(a0) + stq s3, U_PCB_CONTEXT+(3 * 8)(a0) + stq s4, U_PCB_CONTEXT+(4 * 8)(a0) + stq s5, U_PCB_CONTEXT+(5 * 8)(a0) + stq s6, U_PCB_CONTEXT+(6 * 8)(a0) + stq ra, U_PCB_CONTEXT+(7 * 8)(a0) /* store ra */ + call_pal PAL_OSF1_rdps /* NOTE: doesn't kill a0 */ + stq v0, U_PCB_CONTEXT+(8 * 8)(a0) /* store ps, for ipl */ + + mov zero, v0 + RET + END(savectx) + +/**************************************************************************/ + +IMPORT(whichqs, 4) +IMPORT(want_resched, 8) +IMPORT(Lev1map, 8) + +/* + * When no processes are on the runq, cpu_switch branches to idle + * to wait for something to come ready. + * Note: this is really a part of cpu_switch() but defined here for kernel + * profiling. + */ +LEAF(idle, 0) + br pv, Lidle1 +Lidle1: LDGP(pv) + stq zero, curproc /* curproc <- NULL for stats */ + mov zero, a0 /* enable all interrupts */ + call_pal PAL_OSF1_swpipl +Lidle2: + ldl t0, whichqs /* look for non-empty queue */ + beq t0, Lidle2 + ldiq a0, ALPHA_PSL_IPL_HIGH /* disable all interrupts */ + call_pal PAL_OSF1_swpipl + jmp zero, sw1 /* jump back into the fray */ + END(idle) + +/* + * cpu_switch() + * Find the highest priority process and resume it. + */ +LEAF(cpu_switch, 1) + LDGP(pv) + /* do an inline savectx(), to save old context */ + ldq a1, P_ADDR(a0) + /* NOTE: ksp is stored by the swpctx */ + stq s0, U_PCB_CONTEXT+(0 * 8)(a1) /* store s0 - s6 */ + stq s1, U_PCB_CONTEXT+(1 * 8)(a1) + stq s2, U_PCB_CONTEXT+(2 * 8)(a1) + stq s3, U_PCB_CONTEXT+(3 * 8)(a1) + stq s4, U_PCB_CONTEXT+(4 * 8)(a1) + stq s5, U_PCB_CONTEXT+(5 * 8)(a1) + stq s6, U_PCB_CONTEXT+(6 * 8)(a1) + stq ra, U_PCB_CONTEXT+(7 * 8)(a1) /* store ra */ + call_pal PAL_OSF1_rdps /* NOTE: doesn't kill a0 */ + stq v0, U_PCB_CONTEXT+(8 * 8)(a1) /* store ps, for ipl */ + + mov a0, s0 /* save old curproc */ + mov a1, s1 /* save old U-area */ + + ldl t0, whichqs /* look for non-empty queue */ + beq t0, idle /* and if none, go idle */ + + ldiq a0, ALPHA_PSL_IPL_HIGH /* disable all interrupts */ + call_pal PAL_OSF1_swpipl +sw1: + br pv, Lcs1 +Lcs1: LDGP(pv) + ldl t0, whichqs /* look for non-empty queue */ + beq t0, idle /* and if none, go idle */ + mov t0, t3 /* t3 = saved whichqs */ + mov zero, t2 /* t2 = lowest bit set */ + blbs t0, Lcs3 /* if low bit set, done! */ + +Lcs2: srl t0, 1, t0 /* try next bit */ + addq t2, 1, t2 + blbc t0, Lcs2 /* if clear, try again */ + +Lcs3: + /* + * Remove process from queue + */ + lda t1, qs /* get queues */ + sll t2, 4, t0 /* queue head is 16 bytes */ + addq t1, t0, t0 /* t0 = qp = &qs[firstbit] */ + + ldq t4, PH_LINK(t0) /* t4 = p = highest pri proc */ + ldq t5, P_FORW(t4) /* t5 = p->p_forw */ + bne t4, Lcs4 /* make sure p != NULL */ + PANIC("cpu_switch",Lcpu_switch_pmsg) /* nothing in queue! */ + +Lcs4: + stq t5, PH_LINK(t0) /* qp->ph_link = p->p_forw */ + stq t0, P_BACK(t5) /* p->p_forw->p_back = qp */ + stq zero, P_BACK(t4) /* firewall: p->p_back = NULL */ + cmpeq t0, t5, t0 /* see if queue is empty */ + beq t0, Lcs5 /* nope, it's not! */ + + ldiq t0, 1 /* compute bit in whichqs */ + sll t0, t2, t0 + xor t3, t0, t3 /* clear bit in whichqs */ + stl t3, whichqs + +Lcs5: + mov t4, s2 /* save new proc */ + ldq s3, P_MD_PCBPADDR(s2) /* save new pcbpaddr */ + + /* + * Check to see if we're switching to ourself. If we are, + * don't bother loading the new context. + * + * Note that even if we re-enter cpu_switch() from idle(), + * s0 will still contain the old curproc value because any + * users of that register between then and now must have + * saved it. Also note that switch_exit() ensures that + * s0 is clear before jumping here to find a new process. + */ + cmpeq s0, t4, t0 /* oldproc == newproc? */ + bne t0, Lcs7 /* Yes! Skip! */ + + /* + * Deactivate the old address space before activating the + * new one. We need to do this before activating the + * new process's address space in the event that new + * process is using the same vmspace as the old. If we + * do this after we activate, then we might end up + * incorrectly marking the pmap inactive! + * + * We don't deactivate if we came here from switch_exit + * (old pmap no longer exists; vmspace has been freed). + * oldproc will be NULL in this case. We have actually + * taken care of calling pmap_deactivate() in cpu_exit(), + * before the vmspace went away. + */ + beq s0, Lcs6 + + mov s0, a0 /* pmap_deactivate(oldproc) */ + CALL(pmap_deactivate) + +Lcs6: + /* + * Activate the new process's address space and perform + * the actual context swap. + */ + + mov s2, a0 /* pmap_activate(p) */ + CALL(pmap_activate) + + mov s3, a0 /* swap the context */ + SWITCH_CONTEXT + +Lcs7: + + /* + * Now that the switch is done, update curproc and other + * globals. We must do this even if switching to ourselves + * because we might have re-entered cpu_switch() from idle(), + * in which case curproc would be NULL. + */ + stq s2, curproc /* curproc = p */ + stq zero, want_resched /* we've rescheduled */ + + /* + * Now running on the new u struct. + * Restore registers and return. + */ + ldq t0, P_ADDR(s2) + + /* NOTE: ksp is restored by the swpctx */ + ldq s0, U_PCB_CONTEXT+(0 * 8)(t0) /* restore s0 - s6 */ + ldq s1, U_PCB_CONTEXT+(1 * 8)(t0) + ldq s2, U_PCB_CONTEXT+(2 * 8)(t0) + ldq s3, U_PCB_CONTEXT+(3 * 8)(t0) + ldq s4, U_PCB_CONTEXT+(4 * 8)(t0) + ldq s5, U_PCB_CONTEXT+(5 * 8)(t0) + ldq s6, U_PCB_CONTEXT+(6 * 8)(t0) + ldq ra, U_PCB_CONTEXT+(7 * 8)(t0) /* restore ra */ + ldq a0, U_PCB_CONTEXT+(8 * 8)(t0) /* restore ipl */ + and a0, ALPHA_PSL_IPL_MASK, a0 + call_pal PAL_OSF1_swpipl + + ldiq v0, 1 /* possible ret to savectx() */ + RET + END(cpu_switch) + + +/* + * switch_trampoline() + * + * Arrange for a function to be invoked neatly, after a cpu_switch(). + * + * Invokes the function specified by the s0 register with the return + * address specified by the s1 register and with one argument, a + * pointer to the executing process's proc structure. + */ +LEAF(switch_trampoline, 0) + mov s0, pv + mov s1, ra + mov s2, a0 + jmp zero, (pv) + END(switch_trampoline) + + +/**************************************************************************/ + +/* + * exception_return: return from trap, exception, or syscall + */ + +BSS(ssir, 8) +IMPORT(astpending, 8) + +LEAF(exception_return, 1) /* XXX should be NESTED */ + br pv, Ler1 +Ler1: LDGP(pv) + + ldq s1, (FRAME_PS * 8)(sp) /* get the saved PS */ + and s1, ALPHA_PSL_IPL_MASK, t0 /* look at the saved IPL */ + bne t0, Lrestoreregs /* != 0: can't do AST or SIR */ + + /* see if we can do an SIR */ + ldq t1, ssir /* SIR pending? */ + beq t1, Lchkast /* no, try an AST*/ + + /* We've got a SIR. */ + CALL(do_sir) /* do the SIR; lowers IPL */ + +Lchkast: + ldiq a0, ALPHA_PSL_IPL_0 /* drop IPL to zero*/ + call_pal PAL_OSF1_swpipl + + and s1, ALPHA_PSL_USERMODE, t0 /* are we returning to user? */ + beq t0, Lrestoreregs /* no: just return */ + + ldq t2, astpending /* AST pending? */ + beq t2, Lsetfpenable /* no: return & deal with FP */ + + /* We've got an AST. Handle it. */ + mov sp, a0 /* only arg is frame */ + CALL(ast) + +Lsetfpenable: + /* enable FPU based on whether the current proc is fpcurproc */ + ldq t0, curproc + ldq t1, fpcurproc + cmpeq t0, t1, t0 + mov zero, a0 + cmovne t0, 1, a0 + call_pal PAL_OSF1_wrfen + +Lrestoreregs: + /* restore the registers, and return */ + bsr ra, exception_restore_regs /* jmp/CALL trashes pv/t12 */ + ldq ra,(FRAME_RA*8)(sp) + .set noat + ldq at_reg,(FRAME_AT*8)(sp) + + lda sp,(FRAME_SW_SIZE*8)(sp) + call_pal PAL_OSF1_rti + .set at + END(exception_return) + +LEAF(exception_save_regs, 0) + stq v0,(FRAME_V0*8)(sp) + stq a3,(FRAME_A3*8)(sp) + stq a4,(FRAME_A4*8)(sp) + stq a5,(FRAME_A5*8)(sp) + stq s0,(FRAME_S0*8)(sp) + stq s1,(FRAME_S1*8)(sp) + stq s2,(FRAME_S2*8)(sp) + stq s3,(FRAME_S3*8)(sp) + stq s4,(FRAME_S4*8)(sp) + stq s5,(FRAME_S5*8)(sp) + stq s6,(FRAME_S6*8)(sp) + stq t0,(FRAME_T0*8)(sp) + stq t1,(FRAME_T1*8)(sp) + stq t2,(FRAME_T2*8)(sp) + stq t3,(FRAME_T3*8)(sp) + stq t4,(FRAME_T4*8)(sp) + stq t5,(FRAME_T5*8)(sp) + stq t6,(FRAME_T6*8)(sp) + stq t7,(FRAME_T7*8)(sp) + stq t8,(FRAME_T8*8)(sp) + stq t9,(FRAME_T9*8)(sp) + stq t10,(FRAME_T10*8)(sp) + stq t11,(FRAME_T11*8)(sp) + stq t12,(FRAME_T12*8)(sp) + RET + END(exception_save_regs) + +LEAF(exception_restore_regs, 0) + ldq v0,(FRAME_V0*8)(sp) + ldq a3,(FRAME_A3*8)(sp) + ldq a4,(FRAME_A4*8)(sp) + ldq a5,(FRAME_A5*8)(sp) + ldq s0,(FRAME_S0*8)(sp) + ldq s1,(FRAME_S1*8)(sp) + ldq s2,(FRAME_S2*8)(sp) + ldq s3,(FRAME_S3*8)(sp) + ldq s4,(FRAME_S4*8)(sp) + ldq s5,(FRAME_S5*8)(sp) + ldq s6,(FRAME_S6*8)(sp) + ldq t0,(FRAME_T0*8)(sp) + ldq t1,(FRAME_T1*8)(sp) + ldq t2,(FRAME_T2*8)(sp) + ldq t3,(FRAME_T3*8)(sp) + ldq t4,(FRAME_T4*8)(sp) + ldq t5,(FRAME_T5*8)(sp) + ldq t6,(FRAME_T6*8)(sp) + ldq t7,(FRAME_T7*8)(sp) + ldq t8,(FRAME_T8*8)(sp) + ldq t9,(FRAME_T9*8)(sp) + ldq t10,(FRAME_T10*8)(sp) + ldq t11,(FRAME_T11*8)(sp) + ldq t12,(FRAME_T12*8)(sp) + RET + END(exception_restore_regs) diff --git a/sys/alpha/alpha/symbols.raw b/sys/alpha/alpha/symbols.raw new file mode 100644 index 0000000..bf8881a --- /dev/null +++ b/sys/alpha/alpha/symbols.raw @@ -0,0 +1,81 @@ +# @(#)symbols.raw 7.6 (Berkeley) 5/8/91 +# +# $Id: symbols.raw,v 1.12 1998/03/30 09:48:20 phk Exp $ +# + + +#gdb + _IdlePTD + _PTD + _panicstr + _atdevbase +# _version +#dmesg + _msgbufp +# _msgbuf +#iostat + _dk_busy + _dk_time + _dk_xfer + _dk_wds + _tk_nin + _tk_nout + _dk_seek + _cp_time + _dk_wpms +# _io_info +#ps + _nswap + _maxslp + _ccpu + _fscale + _avail_start + _avail_end +#pstat +# _cons + _nswap + _swaplist +#vmstat + _cp_time +# _rate +# _total +# _sum +# _rectime +# _pgintime + _dk_xfer + _boottime +#w + _swapdev + _nswap + _averunnable + _boottime +#netstat + _mbstat + _ipstat + _tcb + _tcpstat + _udb + _udpstat +# _rawcb + _ifnet +# _rthost +# _rtnet + _icmpstat + _filehead + _nfiles +# _rthashsize +# _radix_node_head +#routed + _ifnet +#rwho + _boottime +#savecore + _dumpdev + _dumplo + _time_second + _version + _dumpsize + _panicstr + _dumpmag +#deprecated +# _avenrun diff --git a/sys/alpha/alpha/sys_machdep.c b/sys/alpha/alpha/sys_machdep.c new file mode 100644 index 0000000..e0c55dd --- /dev/null +++ b/sys/alpha/alpha/sys_machdep.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * 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: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 + * $Id: sys_machdep.c,v 1.34 1998/03/23 19:52:34 jlemon Exp $ + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> + +#include <vm/vm.h> +#include <sys/lock.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> + +#include <sys/user.h> + +#include <machine/cpu.h> + +#include <vm/vm_kern.h> /* for kernel_map */ + +#ifndef _SYS_SYSPROTO_H_ +struct sysarch_args { + int op; + char *parms; +}; +#endif + +int +sysarch(p, uap) + struct proc *p; + register struct sysarch_args *uap; +{ + int error = 0; + + switch(SCARG(uap,op)) { + default: + error = EINVAL; + break; + } + return (error); +} diff --git a/sys/alpha/alpha/trap.c b/sys/alpha/alpha/trap.c new file mode 100644 index 0000000..e68aef1 --- /dev/null +++ b/sys/alpha/alpha/trap.c @@ -0,0 +1,1010 @@ +/* $Id */ +/* $NetBSD: trap.c,v 1.31 1998/03/26 02:21:46 thorpej Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* #include "opt_fix_unaligned_vax_fp.h" */ +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/signalvar.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/lock.h> +#include <sys/vmmeter.h> +#include <sys/buf.h> +#include <sys/sysent.h> +#include <sys/syscall.h> +#include <sys/pioctl.h> +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_prot.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> +#include <vm/vm_param.h> +#include <sys/user.h> +#include <sys/ptrace.h> +#include <machine/clock.h> +#include <machine/md_var.h> +#include <machine/reg.h> +#include <machine/pal.h> + +#ifdef DDB +#include <ddb/ddb.h> +#endif + +struct proc *fpcurproc; /* current user of the FPU */ + +void userret __P((struct proc *, u_int64_t, u_quad_t)); + +unsigned long Sfloat_to_reg __P((unsigned int)); +unsigned int reg_to_Sfloat __P((unsigned long)); +unsigned long Tfloat_reg_cvt __P((unsigned long)); +#ifdef FIX_UNALIGNED_VAX_FP +unsigned long Ffloat_to_reg __P((unsigned int)); +unsigned int reg_to_Ffloat __P((unsigned long)); +unsigned long Gfloat_reg_cvt __P((unsigned long)); +#endif + +int unaligned_fixup __P((unsigned long, unsigned long, + unsigned long, struct proc *)); + +static void printtrap __P((const unsigned long, const unsigned long, + const unsigned long, const unsigned long, struct trapframe *, int, int)); +/* + * Define the code needed before returning to user mode, for + * trap and syscall. + */ +void +userret(p, pc, oticks) + register struct proc *p; + u_int64_t pc; + u_quad_t oticks; +{ + int sig, s; + + /* take pending signals */ + while ((sig = CURSIG(p)) != 0) + postsig(sig); + p->p_priority = p->p_usrpri; + if (want_resched) { + /* + * Since we are curproc, a clock interrupt could + * change our priority without changing run queues + * (the running process is not kept on a run queue). + * If this happened after we setrunqueue ourselves but + * before we switch()'ed, we might not be on the queue + * indicated by our priority. + */ + s = splstatclock(); + setrunqueue(p); + p->p_stats->p_ru.ru_nivcsw++; + mi_switch(); + splx(s); + while ((sig = CURSIG(p)) != 0) + postsig(sig); + } + + /* + * If profiling, charge recent system time to the trapped pc. + */ + if (p->p_flag & P_PROFIL) { + addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio); + } + + curpriority = p->p_priority; +} + +static void +printtrap(a0, a1, a2, entry, framep, isfatal, user) + const unsigned long a0, a1, a2, entry; + struct trapframe *framep; + int isfatal, user; +{ + char ubuf[64]; + const char *entryname; + + switch (entry) { + case ALPHA_KENTRY_INT: + entryname = "interrupt"; + break; + case ALPHA_KENTRY_ARITH: + entryname = "arithmetic trap"; + break; + case ALPHA_KENTRY_MM: + entryname = "memory management fault"; + break; + case ALPHA_KENTRY_IF: + entryname = "instruction fault"; + break; + case ALPHA_KENTRY_UNA: + entryname = "unaligned access fault"; + break; + case ALPHA_KENTRY_SYS: + entryname = "system call"; + break; + default: + sprintf(ubuf, "type %lx", entry); + entryname = (const char *) ubuf; + break; + } + + printf("\n"); + printf("%s %s trap:\n", isfatal? "fatal" : "handled", + user ? "user" : "kernel"); + printf("\n"); + printf(" trap entry = 0x%lx (%s)\n", entry, entryname); + printf(" a0 = 0x%lx\n", a0); + printf(" a1 = 0x%lx\n", a1); + printf(" a2 = 0x%lx\n", a2); + printf(" pc = 0x%lx\n", framep->tf_regs[FRAME_PC]); + printf(" ra = 0x%lx\n", framep->tf_regs[FRAME_RA]); + printf(" curproc = %p\n", curproc); + if (curproc != NULL) + printf(" pid = %d, comm = %s\n", curproc->p_pid, + curproc->p_comm); + printf("\n"); +} + +/* + * Trap is called from locore to handle most types of processor traps. + * System calls are broken out for efficiency and ASTs are broken out + * to make the code a bit cleaner and more representative of the + * Alpha architecture. + */ +/*ARGSUSED*/ +void +trap(a0, a1, a2, entry, framep) + const unsigned long a0, a1, a2, entry; + struct trapframe *framep; +{ + register struct proc *p; + register int i; + u_int64_t ucode; + u_quad_t sticks; + int user; + + cnt.v_trap++; + p = curproc; + ucode = 0; + user = (framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0; + if (user) { + sticks = p->p_sticks; + p->p_md.md_tf = framep; +#if 0 +/* This is to catch some wierd stuff on the UDB (mj) */ + if (framep->tf_regs[FRAME_PC] > 0 && + framep->tf_regs[FRAME_PC] < 0x120000000) { + printf("PC Out of Whack\n"); + printtrap(a0, a1, a2, entry, framep, 1, user); + } +#endif + } else { + sticks = 0; /* XXX bogus -Wuninitialized warning */ + } + + switch (entry) { + case ALPHA_KENTRY_UNA: + /* + * If user-land, do whatever fixups, printing, and + * signalling is appropriate (based on system-wide + * and per-process unaligned-access-handling flags). + */ + if (user) { + if ((i = unaligned_fixup(a0, a1, a2, p)) == 0) + goto out; + + ucode = a0; /* VA */ + break; + } + + /* + * Unaligned access from kernel mode is always an error, + * EVEN IF A COPY FAULT HANDLER IS SET! + * + * It's an error if a copy fault handler is set because + * the various routines which do user-initiated copies + * do so in a bcopy-like manner. In other words, the + * kernel never assumes that pointers provided by the + * user are properly aligned, and so if the kernel + * does cause an unaligned access it's a kernel bug. + */ + goto dopanic; + + case ALPHA_KENTRY_ARITH: + /* + * If user-land, just give a SIGFPE. Should do + * software completion and IEEE handling, if the + * user has requested that. + */ + if (user) { + i = SIGFPE; + ucode = a0; /* exception summary */ + break; + } + + /* Always fatal in kernel. Should never happen. */ + goto dopanic; + + case ALPHA_KENTRY_IF: + /* + * These are always fatal in kernel, and should never + * happen. + */ + if (!user) { +#ifdef DDB + /* + * ...unless, of course, DDB is configured; BUGCHK + * is used to invoke the kernel debugger, and we + * might have set a breakpoint. + */ + if (a0 == ALPHA_IF_CODE_BUGCHK || + a0 == ALPHA_IF_CODE_BPT) { + if (ddb_trap(a0, a1, a2, entry, framep)) + goto out; + } + + /* + * If we get here, DDB did _not_ handle the + * trap, and we need to PANIC! + */ +#endif + goto dopanic; + } + i = 0; + switch (a0) { + case ALPHA_IF_CODE_GENTRAP: + if (framep->tf_regs[FRAME_A0] == -2) { /* weird! */ + i = SIGFPE; + ucode = a0; /* exception summary */ + break; + } + /* FALLTHROUTH */ + case ALPHA_IF_CODE_BPT: + case ALPHA_IF_CODE_BUGCHK: + ucode = a0; /* trap type */ + i = SIGTRAP; + break; + + case ALPHA_IF_CODE_OPDEC: + ucode = a0; /* trap type */ + i = SIGILL; + break; + + case ALPHA_IF_CODE_FEN: + /* + * on exit from the kernel, if proc == fpcurproc, + * FP is enabled. + */ + if (fpcurproc == p) { + printf("trap: fp disabled for fpcurproc == %p", + p); + goto dopanic; + } + + alpha_pal_wrfen(1); + if (fpcurproc) + savefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); + fpcurproc = p; + restorefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); + alpha_pal_wrfen(0); + + p->p_md.md_flags |= MDP_FPUSED; + goto out; + + default: + printf("trap: unknown IF type 0x%lx\n", a0); + goto dopanic; + } + break; + + case ALPHA_KENTRY_MM: + switch (a1) { + case ALPHA_MMCSR_FOR: + case ALPHA_MMCSR_FOE: + pmap_emulate_reference(p, a0, user, 0); + goto out; + + case ALPHA_MMCSR_FOW: + pmap_emulate_reference(p, a0, user, 1); + goto out; + + case ALPHA_MMCSR_INVALTRANS: + case ALPHA_MMCSR_ACCESS: + { + register vm_offset_t va; + register struct vmspace *vm = NULL; + register vm_map_t map; + vm_prot_t ftype = 0; + int rv; + + /* + * If it was caused by fuswintr or suswintr, + * just punt. Note that we check the faulting + * address against the address accessed by + * [fs]uswintr, in case another fault happens + * when they are running. + */ + if (!user && + p != NULL && + p->p_addr->u_pcb.pcb_onfault == + (unsigned long)fswintrberr && + p->p_addr->u_pcb.pcb_accessaddr == a0) { + framep->tf_regs[FRAME_PC] = + p->p_addr->u_pcb.pcb_onfault; + p->p_addr->u_pcb.pcb_onfault = 0; + goto out; + } + + /* + * It is only a kernel address space fault iff: + * 1. !user and + * 2. pcb_onfault not set or + * 3. pcb_onfault set but kernel space data fault + * The last can occur during an exec() copyin where the + * argument space is lazy-allocated. + */ + if (!user && (a0 >= VM_MIN_KERNEL_ADDRESS || + p == NULL || p->p_addr->u_pcb.pcb_onfault == 0)) + map = kernel_map; + else { + vm = p->p_vmspace; + map = &vm->vm_map; + } + + switch (a2) { + case -1: /* instruction fetch fault */ + case 0: /* load instruction */ + ftype = VM_PROT_READ; + break; + case 1: /* store instruction */ + ftype = VM_PROT_WRITE; + break; +#ifdef DIAGNOSTIC + default: /* XXX gcc -Wuninitialized */ + goto dopanic; +#endif + } + + va = trunc_page((vm_offset_t)a0); + rv = vm_fault(map, va, ftype, FALSE); + /* + * If this was a stack access we keep track of the + * maximum accessed stack size. Also, if vm_fault + * gets a protection failure it is due to accessing + * the stack region outside the current limit and + * we need to reflect that as an access error. + */ + if (map != kernel_map && + (caddr_t)va >= vm->vm_maxsaddr) { + if (rv == KERN_SUCCESS) { + unsigned nss; + + nss = alpha_btop(round_page(USRSTACK - va)); + if (nss > vm->vm_ssize) + vm->vm_ssize = nss; + } else if (rv == KERN_PROTECTION_FAILURE) + rv = KERN_INVALID_ADDRESS; + } + if (rv == KERN_SUCCESS) { + goto out; + } + + if (!user) { + /* Check for copyin/copyout fault */ + if (p != NULL && + p->p_addr->u_pcb.pcb_onfault != 0) { + framep->tf_regs[FRAME_PC] = + p->p_addr->u_pcb.pcb_onfault; + p->p_addr->u_pcb.pcb_onfault = 0; + goto out; + } + goto dopanic; + } + ucode = a0; + i = SIGSEGV; +#ifdef DEBUG + printtrap(a0, a1, a2, entry, framep, 1, user); +#endif + break; + } + + default: + printf("trap: unknown MMCSR value 0x%lx\n", a1); + goto dopanic; + } + break; + + default: + goto dopanic; + } + +#ifdef DEBUG + printtrap(a0, a1, a2, entry, framep, 1, user); +#endif + trapsignal(p, i, ucode); +out: + if (user) + userret(p, framep->tf_regs[FRAME_PC], sticks); + return; + +dopanic: + printtrap(a0, a1, a2, entry, framep, 1, user); + + /* XXX dump registers */ + +#ifdef DDB + /* XXX + * Really would like to be able to indicate that the + * kernel should _not_ panic, here. However, two problems + * exist: + * + * (a) There is not currently a way for DDB to distinguish + * between "continue and panic" and "continue, and + * don't panic". + * + * (b) panic() will again invoke the debugger, so calling + * it here is silly. + * + * For now, we just do nothing. + */ +#endif + + panic("trap"); +} + +/* + * Process a system call. + * + * System calls are strange beasts. They are passed the syscall number + * in v0, and the arguments in the registers (as normal). They return + * an error flag in a3 (if a3 != 0 on return, the syscall had an error), + * and the return value (if any) in v0. + * + * The assembly stub takes care of moving the call number into a register + * we can get to, and moves all of the argument registers into their places + * in the trap frame. On return, it restores the callee-saved registers, + * a3, and v0 from the frame before returning to the user process. + */ +void +syscall(code, framep) + u_int64_t code; + struct trapframe *framep; +{ + struct sysent *callp; + struct proc *p; + int error = 0, numsys; + u_int64_t opc; + u_quad_t sticks; + u_int64_t args[10]; /* XXX */ + u_int hidden = 0, nargs; + +#if notdef /* can't happen, ever. */ + if ((framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) == 0) { + panic("syscall"); +#endif + cnt.v_syscall++; + p = curproc; + p->p_md.md_tf = framep; + opc = framep->tf_regs[FRAME_PC] - 4; + sticks = p->p_sticks; + + if (p->p_sysent->sv_prepsyscall) { + /* (*p->p_sysent->sv_prepsyscall)(framep, args, &code, ¶ms); */ + panic("prepsyscall"); + } else { + /* + * syscall() and __syscall() are handled the same on + * the alpha, as everything is 64-bit aligned, anyway. + */ + if (code == SYS_syscall || code == SYS___syscall) { + /* + * Code is first argument, followed by actual args. + */ + code = framep->tf_regs[FRAME_A0]; + hidden = 1; + } + } + + if (p->p_sysent->sv_mask) + code &= p->p_sysent->sv_mask; + + if (code >= p->p_sysent->sv_size) + callp = &p->p_sysent->sv_table[0]; + else + callp = &p->p_sysent->sv_table[code]; + + nargs = callp->sy_narg + hidden; + switch (nargs) { + default: + if (nargs > 10) /* XXX */ + panic("syscall: too many args (%d)", nargs); + error = copyin((caddr_t)(alpha_pal_rdusp()), &args[6], + (nargs - 6) * sizeof(u_int64_t)); + case 6: + args[5] = framep->tf_regs[FRAME_A5]; + case 5: + args[4] = framep->tf_regs[FRAME_A4]; + case 4: + args[3] = framep->tf_regs[FRAME_A3]; + case 3: + args[2] = framep->tf_regs[FRAME_A2]; + case 2: + args[1] = framep->tf_regs[FRAME_A1]; + case 1: + args[0] = framep->tf_regs[FRAME_A0]; + case 0: + break; + } +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, callp->sy_narg, args + hidden); +#endif + if (error == 0) { + p->p_retval[0] = 0; + p->p_retval[1] = 0; + + STOPEVENT(p, S_SCE, callp->sy_narg); + + error = (*callp->sy_call)(p, args + hidden); + } + + + switch (error) { + case 0: + framep->tf_regs[FRAME_V0] = p->p_retval[0]; + framep->tf_regs[FRAME_A4] = p->p_retval[1]; + framep->tf_regs[FRAME_A3] = 0; + break; + case ERESTART: + framep->tf_regs[FRAME_PC] = opc; + break; + case EJUSTRETURN: + break; + default: + if (p->p_sysent->sv_errsize) + if (error >= p->p_sysent->sv_errsize) + error = -1; /* XXX */ + else + error = p->p_sysent->sv_errtbl[error]; + framep->tf_regs[FRAME_V0] = error; + framep->tf_regs[FRAME_A3] = 1; + break; + } + + /* + * Reinitialize proc pointer `p' as it may be different + * if this is a child returning from fork syscall. + */ + p = curproc; + + userret(p, framep->tf_regs[FRAME_PC], sticks); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, code, error, rval[0]); +#endif + + /* + * This works because errno is findable through the + * register set. If we ever support an emulation where this + * is not the case, this code will need to be revisited. + */ + STOPEVENT(p, S_SCX, code); +} + +/* + * Process the tail end of a fork() for the child. + */ +void +child_return(p) + struct proc *p; +{ + + /* + * Return values in the frame set by cpu_fork(). + */ + + userret(p, p->p_md.md_tf->tf_regs[FRAME_PC], 0); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, SYS_fork, 0, 0); +#endif +} + +/* + * Process an asynchronous software trap. + * This is relatively easy. + */ +void +ast(framep) + struct trapframe *framep; +{ + register struct proc *p; + u_quad_t sticks; + + p = curproc; + sticks = p->p_sticks; + p->p_md.md_tf = framep; + + if ((framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) == 0) + panic("ast and not user"); + + cnt.v_soft++; + + astpending = 0; + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + addupc_task(p, p->p_stats->p_prof.pr_addr, + p->p_stats->p_prof.pr_ticks); + } + + userret(p, framep->tf_regs[FRAME_PC], sticks); +} + +/* + * Unaligned access handler. It's not clear that this can get much slower... + * + */ +const static int reg_to_framereg[32] = { + FRAME_V0, FRAME_T0, FRAME_T1, FRAME_T2, + FRAME_T3, FRAME_T4, FRAME_T5, FRAME_T6, + FRAME_T7, FRAME_S0, FRAME_S1, FRAME_S2, + FRAME_S3, FRAME_S4, FRAME_S5, FRAME_S6, + FRAME_A0, FRAME_A1, FRAME_A2, FRAME_A3, + FRAME_A4, FRAME_A5, FRAME_T8, FRAME_T9, + FRAME_T10, FRAME_T11, FRAME_RA, FRAME_T12, + FRAME_AT, FRAME_GP, FRAME_SP, -1, +}; + +#define irp(p, reg) \ + ((reg_to_framereg[(reg)] == -1) ? NULL : \ + &(p)->p_md.md_tf->tf_regs[reg_to_framereg[(reg)]]) + +#define frp(p, reg) \ + (&(p)->p_addr->u_pcb.pcb_fp.fpr_regs[(reg)]) + +#define dump_fp_regs() \ + if (p == fpcurproc) { \ + alpha_pal_wrfen(1); \ + savefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); \ + alpha_pal_wrfen(0); \ + fpcurproc = NULL; \ + } + +#define unaligned_load(storage, ptrf, mod) \ + if (copyin((caddr_t)va, &(storage), sizeof (storage)) == 0 && \ + (regptr = ptrf(p, reg)) != NULL) \ + signal = 0; \ + else \ + break; \ + *regptr = mod (storage); + +#define unaligned_store(storage, ptrf, mod) \ + if ((regptr = ptrf(p, reg)) == NULL) \ + break; \ + (storage) = mod (*regptr); \ + if (copyout(&(storage), (caddr_t)va, sizeof (storage)) == 0) \ + signal = 0; \ + else \ + break; + +#define unaligned_load_integer(storage) \ + unaligned_load(storage, irp, ) + +#define unaligned_store_integer(storage) \ + unaligned_store(storage, irp, ) + +#define unaligned_load_floating(storage, mod) \ + dump_fp_regs(); \ + unaligned_load(storage, frp, mod) + +#define unaligned_store_floating(storage, mod) \ + dump_fp_regs(); \ + unaligned_store(storage, frp, mod) + +unsigned long +Sfloat_to_reg(s) + unsigned int s; +{ + unsigned long sign, expn, frac; + unsigned long result; + + sign = (s & 0x80000000) >> 31; + expn = (s & 0x7f800000) >> 23; + frac = (s & 0x007fffff) >> 0; + + /* map exponent part, as appropriate. */ + if (expn == 0xff) + expn = 0x7ff; + else if ((expn & 0x80) != 0) + expn = (0x400 | (expn & ~0x80)); + else if ((expn & 0x80) == 0 && expn != 0) + expn = (0x380 | (expn & ~0x80)); + + result = (sign << 63) | (expn << 52) | (frac << 29); + return (result); +} + +unsigned int +reg_to_Sfloat(r) + unsigned long r; +{ + unsigned long sign, expn, frac; + unsigned int result; + + sign = (r & 0x8000000000000000) >> 63; + expn = (r & 0x7ff0000000000000) >> 52; + frac = (r & 0x000fffffe0000000) >> 29; + + /* map exponent part, as appropriate. */ + expn = (expn & 0x7f) | ((expn & 0x400) != 0 ? 0x80 : 0x00); + + result = (sign << 31) | (expn << 23) | (frac << 0); + return (result); +} + +/* + * Conversion of T floating datums to and from register format + * requires no bit reordering whatsoever. + */ +unsigned long +Tfloat_reg_cvt(input) + unsigned long input; +{ + + return (input); +} + +#ifdef FIX_UNALIGNED_VAX_FP +unsigned long +Ffloat_to_reg(f) + unsigned int f; +{ + unsigned long sign, expn, frlo, frhi; + unsigned long result; + + sign = (f & 0x00008000) >> 15; + expn = (f & 0x00007f80) >> 7; + frhi = (f & 0x0000007f) >> 0; + frlo = (f & 0xffff0000) >> 16; + + /* map exponent part, as appropriate. */ + if ((expn & 0x80) != 0) + expn = (0x400 | (expn & ~0x80)); + else if ((expn & 0x80) == 0 && expn != 0) + expn = (0x380 | (expn & ~0x80)); + + result = (sign << 63) | (expn << 52) | (frhi << 45) | (frlo << 29); + return (result); +} + +unsigned int +reg_to_Ffloat(r) + unsigned long r; +{ + unsigned long sign, expn, frhi, frlo; + unsigned int result; + + sign = (r & 0x8000000000000000) >> 63; + expn = (r & 0x7ff0000000000000) >> 52; + frhi = (r & 0x000fe00000000000) >> 45; + frlo = (r & 0x00001fffe0000000) >> 29; + + /* map exponent part, as appropriate. */ + expn = (expn & 0x7f) | ((expn & 0x400) != 0 ? 0x80 : 0x00); + + result = (sign << 15) | (expn << 7) | (frhi << 0) | (frlo << 16); + return (result); +} + +/* + * Conversion of G floating datums to and from register format is + * symmetrical. Just swap shorts in the quad... + */ +unsigned long +Gfloat_reg_cvt(input) + unsigned long input; +{ + unsigned long a, b, c, d; + unsigned long result; + + a = (input & 0x000000000000ffff) >> 0; + b = (input & 0x00000000ffff0000) >> 16; + c = (input & 0x0000ffff00000000) >> 32; + d = (input & 0xffff000000000000) >> 48; + + result = (a << 48) | (b << 32) | (c << 16) | (d << 0); + return (result); +} +#endif /* FIX_UNALIGNED_VAX_FP */ + +extern int alpha_unaligned_print, alpha_unaligned_fix; +extern int alpha_unaligned_sigbus; + +int +unaligned_fixup(va, opcode, reg, p) + unsigned long va, opcode, reg; + struct proc *p; +{ + int doprint, dofix, dosigbus; + int signal, size; + const char *type; + unsigned long *regptr, longdata; + int intdata; /* signed to get extension when storing */ + struct { + const char *type; /* opcode name */ + int size; /* size, 0 if fixup not supported */ + } tab[0x10] = { +#ifdef FIX_UNALIGNED_VAX_FP + { "ldf", 4 }, { "ldg", 8 }, +#else + { "ldf", 0 }, { "ldg", 0 }, +#endif + { "lds", 4 }, { "ldt", 8 }, +#ifdef FIX_UNALIGNED_VAX_FP + { "stf", 4 }, { "stg", 8 }, +#else + { "stf", 0 }, { "stg", 0 }, +#endif + { "sts", 4 }, { "stt", 8 }, + { "ldl", 4 }, { "ldq", 8 }, + { "ldl_l", 0 }, { "ldq_l", 0 }, /* can't fix */ + { "stl", 4 }, { "stq", 8 }, + { "stl_c", 0 }, { "stq_c", 0 }, /* can't fix */ + }; + + /* + * Figure out what actions to take. + * + * XXX In the future, this should have a per-process component + * as well. + */ + doprint = alpha_unaligned_print; + dofix = alpha_unaligned_fix; + dosigbus = alpha_unaligned_sigbus; + + /* + * Find out which opcode it is. Arrange to have the opcode + * printed if it's an unknown opcode. + */ + if (opcode >= 0x20 && opcode <= 0x2f) { + type = tab[opcode - 0x20].type; + size = tab[opcode - 0x20].size; + } else { + type = "0x%lx"; + size = 0; + } + + /* + * See if the user can access the memory in question. + * Even if it's an unknown opcode, SEGV if the access + * should have failed. + */ + if (!useracc((caddr_t)va, size ? size : 1, B_WRITE)) { + signal = SIGSEGV; + goto out; + } + + /* + * If we're supposed to be noisy, squawk now. + */ + if (doprint) { + uprintf( + "pid %d (%s): unaligned access: va=0x%lx pc=0x%lx ra=0x%lx op=", + p->p_pid, p->p_comm, va, p->p_md.md_tf->tf_regs[FRAME_PC], + p->p_md.md_tf->tf_regs[FRAME_RA]); + uprintf(type,opcode); + uprintf("\n"); + } + + /* + * If we should try to fix it and know how, give it a shot. + * + * We never allow bad data to be unknowingly used by the + * user process. That is, if we decide not to fix up an + * access we cause a SIGBUS rather than letting the user + * process go on without warning. + * + * If we're trying to do a fixup, we assume that things + * will be botched. If everything works out OK, + * unaligned_{load,store}_* clears the signal flag. + */ + signal = SIGBUS; + if (dofix && size != 0) { + switch (opcode) { +#ifdef FIX_UNALIGNED_VAX_FP + case 0x20: /* ldf */ + unaligned_load_floating(intdata, Ffloat_to_reg); + break; + + case 0x21: /* ldg */ + unaligned_load_floating(longdata, Gfloat_reg_cvt); + break; +#endif + + case 0x22: /* lds */ + unaligned_load_floating(intdata, Sfloat_to_reg); + break; + + case 0x23: /* ldt */ + unaligned_load_floating(longdata, Tfloat_reg_cvt); + break; + +#ifdef FIX_UNALIGNED_VAX_FP + case 0x24: /* stf */ + unaligned_store_floating(intdata, reg_to_Ffloat); + break; + + case 0x25: /* stg */ + unaligned_store_floating(longdata, Gfloat_reg_cvt); + break; +#endif + + case 0x26: /* sts */ + unaligned_store_floating(intdata, reg_to_Sfloat); + break; + + case 0x27: /* stt */ + unaligned_store_floating(longdata, Tfloat_reg_cvt); + break; + + case 0x28: /* ldl */ + unaligned_load_integer(intdata); + break; + + case 0x29: /* ldq */ + unaligned_load_integer(longdata); + break; + + case 0x2c: /* stl */ + unaligned_store_integer(intdata); + break; + + case 0x2d: /* stq */ + unaligned_store_integer(longdata); + break; + +#ifdef DIAGNOSTIC + default: + panic("unaligned_fixup: can't get here"); +#endif + } + } + + /* + * Force SIGBUS if requested. + */ + if (dosigbus) + signal = SIGBUS; + +out: + return (signal); +} diff --git a/sys/alpha/conf/GENERIC b/sys/alpha/conf/GENERIC new file mode 100644 index 0000000..55d674a --- /dev/null +++ b/sys/alpha/conf/GENERIC @@ -0,0 +1,74 @@ +# +# GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks +# +# For more information read the handbook part System Administration -> +# Configuring the FreeBSD Kernel -> The Configuration File. +# The handbook is available in /usr/share/doc/handbook or online as +# latest version from the FreeBSD World Wide Web server +# <URL:http://www.FreeBSD.ORG/> +# +# An exhaustive list of options and more detailed explanations of the +# device lines is present in the ./LINT configuration file. If you are +# in doubt as to the purpose or necessity of a line, check first in LINT. +# +# $Id: GENERIC,v 1.107 1998/02/16 23:57:03 msmith Exp $ + +machine "alpha" +cpu "EV5" +ident GENERIC +maxusers 10 + +options __FreeBSD__=3 #XXX hack city + +#options MATH_EMULATE #Support for x87 emulation +options INET #InterNETworking +options FFS #Berkeley Fast Filesystem +options NFS #Network Filesystem +options MSDOSFS #MSDOS Filesystem +options "CD9660" #ISO 9660 Filesystem +options "CD9660_ROOT" #CD-ROM usable as root device +options FFS_ROOT #FFS usable as root device [keep this!] +options NFS_ROOT #NFS usable as root device +options PROCFS #Process filesystem +options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=15 #Be pessimistic about Joe SCSI device +options UCONSOLE #Allow users to grab the console +options FAILSAFE #Be conservative + +config kernel root on sd0 + +controller scbus0 + +device sd0 + +device od0 #See LINT for possible `od' options. + +device st0 + +device cd0 #Only need one of these, the code dynamically grows + +# Order is important here due to intrusive probes, do *not* alphabetize +# this list of network interfaces until the probes have been fixed. +# Right now it appears that the ie0 must be probed before ep0. See +# revision 1.20 of this file. +#device de0 + +pseudo-device loop +pseudo-device ether +pseudo-device sl 1 +pseudo-device ppp 1 +pseudo-device tun 1 +pseudo-device pty 16 +pseudo-device gzip # Exec gzipped a.out's + +# KTRACE enables the system-call tracing facility ktrace(2). +# This adds 4 KB bloat to your kernel, and slightly increases +# the costs of each syscall. +options KTRACE #kernel tracing + +# This provides support for System V shared memory. +# +options SYSVSHM + +options DDB + diff --git a/sys/alpha/conf/Makefile.alpha b/sys/alpha/conf/Makefile.alpha new file mode 100644 index 0000000..ecc9daa --- /dev/null +++ b/sys/alpha/conf/Makefile.alpha @@ -0,0 +1,272 @@ +# Makefile.alpha -- with config changes. +# Copyright 1990 W. Jolitz +# from: @(#)Makefile.alpha 7.1 5/10/91 +# $Id: Makefile.alpha,v 1.109 1998/04/17 07:51:36 dima Exp $ +# +# Makefile for FreeBSD +# +# This makefile is constructed from a machine description: +# config machineid +# Most changes should be made in the machine description +# /sys/alpha/conf/``machineid'' +# after which you should do +# config machineid +# Generic makefile changes should be made in +# /sys/alpha/conf/Makefile.alpha +# after which config should be rerun for all machines. +# + +# Which version of config(8) is required. +%VERSREQ= 300003 + +BINFORMAT?= elf + +STD8X16FONT?= iso + +.if exists(./@/.) +S= ./@ +.else +S= ../.. +.endif +ALPHA= ${S}/alpha + +COPTFLAGS?=-O +INCLUDES= -nostdinc -I- -I. -I$S +# This hack is to allow kernel compiles to succeed on machines w/out srcdist +.if exists($S/../include) +INCLUDES+= -I$S/../include +.else +INCLUDES+= -I/usr/include +.endif +COPTS= ${INCLUDES} ${IDENT} -DKERNEL -include opt_global.h +CFLAGS= ${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS} -mno-fp-regs +LOAD_ADDRESS?= 0xfffffc0000230000 +DEFINED_PROF= ${PROF} +.if defined(PROF) +CFLAGS+= -malign-functions=4 +.if ${PROFLEVEL} >= 2 +IDENT+= -DGPROF4 -DGUPROF +PROF+= -mprofiler-epilogue +.endif +.endif + +NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $< +NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< +# XXX LOCORE means "don't declare C stuff" not "for locore.s". +NORMAL_S= ${CC} -c -x assembler-with-cpp -DLOCORE ${COPTS} $< +DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $< +DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< +DRIVER_S= ${CC} -c -x assembler-with-cpp -DLOCORE ${COPTS} $< +PROFILE_C= ${CC} -c ${CFLAGS} ${PARAM} $< + +# ${ALPHA}/alpha/setdef0.c and ${ALPHA}/alpha/setdef1.c are intentionally +# omitted from SYSTEM_CFILES. They depend on setdefs.h, a header which +# is generated from all of ${OBJS}. We don't want to have to compile +# everything just to do a make depend. +SYSTEM_CFILES= ioconf.c param.c vnode_if.c config.c +SYSTEM_SFILES= ${ALPHA}/alpha/locore.s +SYSTEM_DEP= Makefile symbols.exclude symbols.sort ${SYSTEM_OBJS} +.if ${CFLAGS:M-g} == "" +SYMORDER_EXCLUDE=-x symbols.exclude +.endif +SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ +.if ${BINFORMAT} == elf +SYSTEM_OBJS= locore.o setdef0.o vnode_if.o ${OBJS} ioconf.o param.o config.o \ + setdef1.o +SYSTEM_LD= @${LD} -Bstatic -N -Ttext ${LOAD_ADDRESS} -e locorestart -defsym _DYNAMIC=0 \ + -o $@ -X ${SYSTEM_OBJS} vers.o +SYSTEM_LD_TAIL= @size $@; chmod 755 $@ +.endif + +%BEFORE_DEPEND + +%OBJS + +%CFILES + +%SFILES + +%LOAD + +%CLEAN + +clean: + rm -f *.o *.s eddep errs genassym gensetdefs kernel linterrs \ + makelinks param.c setdefs.h symbols.exclude symbols.sort tags \ + vers.c vnode_if.c vnode_if.h ${CLEAN} + +#lint: /tmp param.c +# @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \ +# ${ALPHA}/alpha/Locore.c ${CFILES} ioconf.c param.c | \ +# grep -v 'struct/union .* never defined' | \ +# grep -v 'possible pointer alignment problem' + +symbols.exclude: Makefile + echo "gcc2_compiled." >symbols.exclude + echo "___gnu_compiled_c" >>symbols.exclude + +symbols.sort: ${ALPHA}/alpha/symbols.raw + grep -v '^#' ${ALPHA}/alpha/symbols.raw \ + | sed 's/^ //' | sort -u > symbols.sort + +locore.o: ${ALPHA}/alpha/locore.s assym.s + ${NORMAL_S} + +setdef0.o: ${ALPHA}/alpha/setdef0.c setdefs.h + ${NORMAL_C} + +setdef1.o: ${ALPHA}/alpha/setdef1.c setdefs.h + ${NORMAL_C} + +setdefs.h: gensetdefs ${OBJS} + @echo Generating kernel linker sets + @./gensetdefs ${OBJS} >setdefs.h + +gensetdefs: gensetdefs.o + ${CC} ${CFLAGS} gensetdefs.o -o $@ + +gensetdefs.o: ${ALPHA}/alpha/gensetdefs.c + ${CC} -c ${CFLAGS} ${ALPHA}/alpha/gensetdefs.c + +# everything potentially depends on the Makefile since everything potentially +# depends on the options. Some things are more dependent on the Makefile for +# historical reasons. +machdep.o: Makefile + +# the following is necessary because autoconf.o depends on #if GENERIC +autoconf.o: Makefile + +# XXX - may no longer be needed +locore.o: Makefile + +# depends on KDB (cons.o also depends on GENERIC) +trap.o cons.o: Makefile + +# this rule stops ./assym.s in .depend from causing problems +./assym.s: assym.s + +assym.s: genassym + ./genassym >assym.s + +# Some of the defines that genassym outputs may well depend on the +# value of kernel options. +genassym.o: ${ALPHA}/alpha/genassym.c Makefile opt_global.h + ${CC} -c ${CFLAGS} ${PARAM} -UKERNEL ${ALPHA}/alpha/genassym.c + +genassym: genassym.o + ${CC} ${CFLAGS} ${PARAM} genassym.o -o $@ + +SYSTEM_OBJS+= __divqu.o __divq.o __divlu.o __divl.o +SYSTEM_OBJS+= __remqu.o __remq.o __remlu.o __reml.o +CLEAN+= __divqu.S __divq.S __divlu.S __divl.S +CLEAN+= __remqu.S __remq.S __remlu.S __reml.S + +__divqu.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divqu')define(OP,\`div')define(S,\`false')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__divq.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divq')define(OP,\`div')define(S,\`true')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__divlu.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divlu')define(OP,\`div')define(S,\`false')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__divl.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divl')define(OP,\`div')define(S,\`true')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__remqu.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__remqu')define(OP,\`rem')define(S,\`false')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__remq.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__remq')define(OP,\`rem')define(S,\`true')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__remlu.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__remlu')define(OP,\`rem')define(S,\`false')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__reml.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__reml')define(OP,\`rem')define(S,\`true')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + + +${OBJS}: opt_global.h + +# XXX this assumes that the options for NORMAL_C* and DRIVER_C* are identical. +depend: assym.s param.c vnode_if.h ${BEFORE_DEPEND} + rm -f .newdep + mkdep -a -f .newdep ${COPTS} ${CFILES} ${SYSTEM_CFILES} + mkdep -a -f .newdep ${COPTS} ${PARAM} -UKERNEL ${ALPHA}/alpha/genassym.c + MKDEP_CPP="${CC} -E -x assembler-with-cpp" ; export MKDEP_CPP ; \ + mkdep -a -f .newdep -DLOCORE ${COPTS} ${SFILES} ${SYSTEM_SFILES} + rm -f .depend + mv -f .newdep .depend + +cleandepend: + rm -f .depend + +links: + egrep '#if' ${CFILES:Nswapkernel.c} | sed -f $S/conf/defines | \ + sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink + echo ${CFILES:Nswapkernel.c} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ + sort -u | comm -23 - dontlink | \ + sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks + sh makelinks && rm -f dontlink + +tags: + @echo "see $S/kern/Makefile for tags" + +install: + @if [ ! -f kernel ] ; then \ + echo "You must first build your kernel before trying to install." ; \ + exit 1 ; \ + fi +.if exists(${DESTDIR}/kernel) + chflags noschg ${DESTDIR}/kernel + mv ${DESTDIR}/kernel ${DESTDIR}/kernel.old +.endif + PATH=$${PATH}:/sbin:/usr/sbin; \ + if [ `sysctl -n kern.bootfile` = ${DESTDIR}/kernel ] ; then \ + sysctl -w kern.bootfile=${DESTDIR}/kernel.old ; \ + if [ -f /var/db/kvm_kernel.db ] ; then \ + mv -f /var/db/kvm_kernel.db /var/db/kvm_kernel.old.db ; \ + fi \ + fi + install -c -m 555 -o root -g wheel -fschg kernel ${DESTDIR}/ + +ioconf.o: ioconf.c $S/sys/param.h $S/sys/buf.h + ${CC} -c ${CFLAGS} ioconf.c + +param.c: $S/conf/param.c + -rm -f param.c + cp $S/conf/param.c . + +param.o: param.c Makefile + ${CC} -c ${CFLAGS} ${PARAM} param.c + +vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} + sh $S/conf/newvers.sh ${KERN_IDENT} ${IDENT} + ${CC} ${CFLAGS} -c vers.c + +vnode_if.c: $S/kern/vnode_if.sh $S/kern/vnode_if.src + sh $S/kern/vnode_if.sh $S/kern/vnode_if.src +vnode_if.h: $S/kern/vnode_if.sh $S/kern/vnode_if.src + sh $S/kern/vnode_if.sh $S/kern/vnode_if.src + +.include <bsd.kern.mk> + +%RULES + +# DO NOT DELETE THIS LINE -- make depend uses it diff --git a/sys/alpha/conf/NOTES b/sys/alpha/conf/NOTES new file mode 100644 index 0000000..55d674a --- /dev/null +++ b/sys/alpha/conf/NOTES @@ -0,0 +1,74 @@ +# +# GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks +# +# For more information read the handbook part System Administration -> +# Configuring the FreeBSD Kernel -> The Configuration File. +# The handbook is available in /usr/share/doc/handbook or online as +# latest version from the FreeBSD World Wide Web server +# <URL:http://www.FreeBSD.ORG/> +# +# An exhaustive list of options and more detailed explanations of the +# device lines is present in the ./LINT configuration file. If you are +# in doubt as to the purpose or necessity of a line, check first in LINT. +# +# $Id: GENERIC,v 1.107 1998/02/16 23:57:03 msmith Exp $ + +machine "alpha" +cpu "EV5" +ident GENERIC +maxusers 10 + +options __FreeBSD__=3 #XXX hack city + +#options MATH_EMULATE #Support for x87 emulation +options INET #InterNETworking +options FFS #Berkeley Fast Filesystem +options NFS #Network Filesystem +options MSDOSFS #MSDOS Filesystem +options "CD9660" #ISO 9660 Filesystem +options "CD9660_ROOT" #CD-ROM usable as root device +options FFS_ROOT #FFS usable as root device [keep this!] +options NFS_ROOT #NFS usable as root device +options PROCFS #Process filesystem +options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=15 #Be pessimistic about Joe SCSI device +options UCONSOLE #Allow users to grab the console +options FAILSAFE #Be conservative + +config kernel root on sd0 + +controller scbus0 + +device sd0 + +device od0 #See LINT for possible `od' options. + +device st0 + +device cd0 #Only need one of these, the code dynamically grows + +# Order is important here due to intrusive probes, do *not* alphabetize +# this list of network interfaces until the probes have been fixed. +# Right now it appears that the ie0 must be probed before ep0. See +# revision 1.20 of this file. +#device de0 + +pseudo-device loop +pseudo-device ether +pseudo-device sl 1 +pseudo-device ppp 1 +pseudo-device tun 1 +pseudo-device pty 16 +pseudo-device gzip # Exec gzipped a.out's + +# KTRACE enables the system-call tracing facility ktrace(2). +# This adds 4 KB bloat to your kernel, and slightly increases +# the costs of each syscall. +options KTRACE #kernel tracing + +# This provides support for System V shared memory. +# +options SYSVSHM + +options DDB + diff --git a/sys/alpha/conf/SIMOS b/sys/alpha/conf/SIMOS new file mode 100644 index 0000000..052dfad --- /dev/null +++ b/sys/alpha/conf/SIMOS @@ -0,0 +1,84 @@ +# +# GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks +# +# For more information read the handbook part System Administration -> +# Configuring the FreeBSD Kernel -> The Configuration File. +# The handbook is available in /usr/share/doc/handbook or online as +# latest version from the FreeBSD World Wide Web server +# <URL:http://www.FreeBSD.ORG/> +# +# An exhaustive list of options and more detailed explanations of the +# device lines is present in the ./LINT configuration file. If you are +# in doubt as to the purpose or necessity of a line, check first in LINT. +# +# $Id: GENERIC,v 1.107 1998/02/16 23:57:03 msmith Exp $ + +machine "alpha" +cpu "EV5" +ident GENERIC +maxusers 10 + +options __FreeBSD__=3 #XXX hack city + +options "DEC_KN8AE" +options SIMOS +#options MATH_EMULATE #Support for x87 emulation +options INET #InterNETworking +options FFS #Berkeley Fast Filesystem +options NFS #Network Filesystem +options MSDOSFS #MSDOS Filesystem +options "CD9660" #ISO 9660 Filesystem +options "CD9660_ROOT" #CD-ROM usable as root device +options FFS_ROOT #FFS usable as root device [keep this!] +options NFS_ROOT #NFS usable as root device +options PROCFS #Process filesystem +options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=15 #Be pessimistic about Joe SCSI device +options UCONSOLE #Allow users to grab the console +options FAILSAFE #Be conservative + +config kernel root on sd0 + +controller pci0 +controller tlsb0 +controller gbus0 +controller kft0 +controller dwlpx0 + +controller simos0 + +controller scbus0 + +device sd0 + +device od0 #See LINT for possible `od' options. + +device st0 + +device cd0 #Only need one of these, the code dynamically grows + +# Order is important here due to intrusive probes, do *not* alphabetize +# this list of network interfaces until the probes have been fixed. +# Right now it appears that the ie0 must be probed before ep0. See +# revision 1.20 of this file. +#device de0 + +pseudo-device loop +pseudo-device ether +pseudo-device sl 1 +pseudo-device ppp 1 +pseudo-device tun 1 +pseudo-device pty 16 +pseudo-device gzip # Exec gzipped a.out's + +# KTRACE enables the system-call tracing facility ktrace(2). +# This adds 4 KB bloat to your kernel, and slightly increases +# the costs of each syscall. +options KTRACE #kernel tracing + +# This provides support for System V shared memory. +# +options SYSVSHM + +options DDB + diff --git a/sys/alpha/conf/devices.alpha b/sys/alpha/conf/devices.alpha new file mode 100644 index 0000000..2727862 --- /dev/null +++ b/sys/alpha/conf/devices.alpha @@ -0,0 +1,18 @@ +# This file tells what major numbers the various possible swap devices have. +# +# $Id: devices.i386,v 1.13 1998/02/17 11:33:31 sos Exp $ +# +wd 0 +wfd 1 +fd 2 +wt 3 +sd 4 +st 5 +cd 6 +mcd 7 +vn 15 +scd 16 +pcd 17 +wcd 19 +od 20 +wst 24 diff --git a/sys/alpha/conf/files.alpha b/sys/alpha/conf/files.alpha new file mode 100644 index 0000000..04e5410 --- /dev/null +++ b/sys/alpha/conf/files.alpha @@ -0,0 +1,80 @@ +# This file tells config what files go into building a kernel, +# files marked standard are always included. +# +# $Id$ +# +# The long compile-with and dependency lines are required because of +# limitations in config: backslash-newline doesn't work in strings, and +# dependency lines other than the first are silently ignored. +# +# +font8x16.o optional std8x16font \ + compile-with "uudecode < /usr/share/syscons/fonts/${STD8X16FONT}-8x16.fnt && file2c 'unsigned char font_16[16*256] = {' '};' < ${STD8X16FONT}-8x16 > font8x16.c && ${CC} -c ${CFLAGS} font8x16.c" \ + no-implicit-rule before-depend \ + clean "${STD8X16FONT}-8x16 font8x16.c" + +# +alpha/alpha/autoconf.c standard device-driver +alpha/alpha/cpuconf.c standard +alpha/alpha/dec_kn8ae.c optional dec_kn8ae +alpha/alpha/mountroot.c optional slice +alpha/alpha/ipl_funcs.c standard +alpha/alpha/pal.s standard +alpha/alpha/cons.c standard +alpha/alpha/prom.c standard +alpha/alpha/prom_disp.s standard +alpha/alpha/db_disasm.c optional ddb +alpha/alpha/db_interface.c optional ddb +alpha/alpha/db_trace.c optional ddb +alpha/alpha/exception.s standard +alpha/alpha/in_cksum.c optional inet +# locore.s needs to be handled in Makefile to put it first. Otherwise it's +# now normal. +# alpha/alpha/locore.s standard +alpha/alpha/machdep.c standard +alpha/alpha/math_emulate.c optional math_emulate +alpha/alpha/mem.c standard +alpha/alpha/mp_machdep.c optional smp +alpha/alpha/perfmon.c optional perfmon profiling-routine +alpha/alpha/perfmon.c optional perfmon +alpha/alpha/pmap.c standard +alpha/alpha/procfs_machdep.c standard +alpha/alpha/simplelock.s optional smp +alpha/alpha/support.s standard +alpha/alpha/swtch.s standard +alpha/alpha/sys_machdep.c standard +alpha/alpha/trap.c standard +alpha/alpha/interrupt.c standard +alpha/alpha/userconfig.c optional userconfig +alpha/alpha/vm_machdep.c standard +alpha/alpha/clock.c standard +alpha/alpha/diskslice_machdep.c standard +alpha/tlsb/tlsb.c optional tlsb +alpha/tlsb/gbus.c optional gbus +alpha/tlsb/kftxx.c optional kft +alpha/tlsb/mcclock_tlsb.c optional gbus +alpha/tlsb/zs_tlsb.c optional gbus +alpha/tlsb/dwlpx.c optional dwlpx +dev/dec/mcclock.c optional gbus +alpha/pci/pcibus.c optional pci +kern/subr_bus.c standard +libkern/bcd.c standard +libkern/bcmp.c standard +libkern/ffs.c standard +libkern/inet_ntoa.c standard +libkern/index.c standard +libkern/mcount.c optional profiling-routine +libkern/qsort.c standard +libkern/random.c standard +libkern/scanc.c standard +libkern/skpc.c standard +libkern/strcat.c standard +libkern/strcmp.c standard +libkern/strcpy.c standard +libkern/strlen.c standard +libkern/strncmp.c standard +libkern/strncpy.c standard +libkern/alpha/htonl.S standard +libkern/alpha/htons.S standard +libkern/alpha/ntohl.S standard +libkern/alpha/ntohs.S standard diff --git a/sys/alpha/conf/majors.alpha b/sys/alpha/conf/majors.alpha new file mode 100644 index 0000000..a171d68c --- /dev/null +++ b/sys/alpha/conf/majors.alpha @@ -0,0 +1,141 @@ +$Id: majors.i386,v 1.37 1998/04/17 20:26:43 julian Exp $ + +Hopefully, this list will one day be obsoleted by DEVFS, but for now +this is the current allocation of device major numbers. + +For local use, you are encouraged to use the reserved numbers. + +If you intend the driver to be available, send email to the +hackers@freebsd.org mailing list to see about having a number +reserved for you. + +The most "complete" version of this will be the one in FreeBSD-current. +(see http://www.freebsd.org/ or from ftp://ftp.cdrom.com/pub/FreeBSD/) + +blkdev name comments +0 wd ST506 disk controller (with IDE extensions) +1 wfd ATAPI Floppy client of "ata" +2 fd floppy disk +3 wt QIC-02/36 tape +4 sd SCSI "disk" type +5 st SCSI "tape" type +6 cd SCSI "cdrom" type +7 mcd Mitsumi CDROM interface +8 lkm assigned to Loadable Kernel modules +9 lkm assigned to Loadable Kernel modules +10 lkm assigned to Loadable Kernel modules +11 lkm assigned to Loadable Kernel modules +12 lkm assigned to Loadable Kernel modules +13 lkm assigned to Loadable Kernel modules +14 ?? reserved for local use +15 vn vnode disk device +16 scd Sony CDROM interface +17 matcd Matsushita/Panasonic/Creative(SB) CDROM interface +18 ata "device independent" ATA/IDE driver +19 wcdb ATAPI CDROM client of "ata" +20 od SCSI "magneto-optical" disk +21 ccd concatenated disk +22 gd Geometry disk. +23 worm SCSI "worm type" +24 wstb ATAPI tape client of "ata" +25 vinum RAID fs +26 sw VM internal swap device +chrdev name comments +0 cn console +1 ctty /dev/tty +2 mm /dev/mem,kmem,etc +3 wd ST506 disk controller (with IDE extensions) +4 swap /dev/drum +5 pts pseudo tty "tty" half +6 ptc pseudo tty "master" half +7 log system log +8 bqu B004 transputer board +9 fd floppy disk +10 wt QIC-02/36 tape +11 spigot Video capture? +12 sc syscons/pcvt virtual consoles +13 sd SCSI "disk type" +14 st SCSI "tape type" +15 cd SCSI "CDROM type" +16 lpt PC parallel printer port +17 ch SCSI changer +18 su SCSI universal type +19 tw X-10 power interface +20 ?? reserved for local use +21 psm PS/2 Mouse +22 fd (/dev/stdin etc) +23 bpf Berkeley Packet Filter +24 pca PC speaker (/dev/pcaudio) +25 ?? was vat +26 spkr PC speaker (/dev/spkr) +27 mse Microsoft bus-mouse +28 sio 16450/16550 serial +29 mcd Mitsumi CDROM interface +30 snd sound driver system +31 uk SCSI "unknown device type" +32 lkmc Loadable Kernel Module Controller +33 lkm assigned to Loadable Kernel Modules +34 lkm assigned to Loadable Kernel Modules +35 lkm assigned to Loadable Kernel Modules +36 lkm assigned to Loadable Kernel Modules +37 lkm assigned to Loadable Kernel Modules +38 lkm assigned to Loadable Kernel Modules +39 apm Advanced Power Management +40 ctx Cortex +41 ?? was socksys +42 cx Cronyx +43 vn vnode "disk" device +44 gp GPIB +45 scd Sony CDROM interface +46 matcd Matsushita/Panasonic/Creative(SB) CDROM interface +47 gsc Genius Scanner +48 cy Cyclades +49 ssc SCSI super device +50 card pcmcia cards +51 joy joystick +52 tun IP tunnel device +53 snp tty snoop +54 OLDnic ISDN system +55 OLDisdn ISDN system +56 OLDity ISDN system +57 OLDitel ISDN system +58 dgb Digiboard +59 OLDispy ISDN system +60 OLDnnic ISDN system +61 pt SCSI "processor type" +62 worm SCSI "worm type" +63 rc Riscom/8 driver +64 ?? Talisman +65 sctarg SCSI target +66 labpc National Instruments LabPC +67 meteor Matrox Meteor video capture +68 si Specialix SI/XIO (peter@freebsd.org) +69 wcd ATAPI CDROM client of "ata" +70 od SCSI "magneto-optical disk type" +71 asc AmiScan driver +72 stl Stallion (cd1400 based) (gerg@stallion.oz.au) +73 ?? was qcam +74 ccd concatenated disk +75 stli Stallion (intelligent cdk based) (gerg@stallion.oz.au) +76 scc IBM Smart Capture Card (ohashi@mickey.ai.kyutech.ac.jp) +77 cyy Cyclades Ye/PCI serial card +78 pci PCI bus +79 ipl IP Filter +80 xdcp Assigned to Chris Ficklin <chris@serengeti.com> +81 rp RocketPort/Steve Gericke <steveg@comtrol.com> +82 ppi Generic Parallel I/O <Nicolas.Souchu@prism.uvsq.fr> +83 can CAN16-2 CAN-PC Interface +84 ttxt Unitext teletext decoder (arg@arg1.demon.co.uk) +85 vesa VESA support device (j_mini@efn.org) +86 alog Industrial Computer Source AIO8-P driver +87 wfd ATAPI floppy client of "ata" +88 dpt DPT RAID Controller <shimon@i-connect.net> +89 pps Pulse-Per-Second timing interface +90 wst ATAPI tape client of "ata" +91 vinum RAID fs +92 bktr Bt848 video capture driver (hasty@star-gate.com) +93 coda CODA filesystem. +94 loran Loran-C Receiver +95 gd Geometry disk +96 altq alternate queueing (including cbq, red, wfq) +97 zsc TurboLaser console uart diff --git a/sys/alpha/conf/options.alpha b/sys/alpha/conf/options.alpha new file mode 100644 index 0000000..666e7f7 --- /dev/null +++ b/sys/alpha/conf/options.alpha @@ -0,0 +1,18 @@ +# $Id$ + +EV5 opt_global.h +DEC_KN8AE opt_cpu.h + +ATAPI opt_atapi.h +ATAPI_STATIC opt_atapi.h + +CMD640 opt_wd.h + +SHOW_BUSYBUFS +PANIC_REBOOT_WAIT_TIME opt_panic.h + +AHC_TAGENABLE opt_aic7xxx.h +AHC_SCBPAGING_ENABLE opt_aic7xxx.h +AHC_ALLOW_MEMIO opt_aic7xxx.h +AHC_SHARE_SCBS opt_aic7xxx.h + diff --git a/sys/alpha/include/alpha_cpu.h b/sys/alpha/include/alpha_cpu.h index 267b120..9bd97f4 100644 --- a/sys/alpha/include/alpha_cpu.h +++ b/sys/alpha/include/alpha_cpu.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: alpha_cpu.h,v 1.1 1998/01/10 10:13:13 jb Exp $ */ /* From: NetBSD: alpha_cpu.h,v 1.15 1997/09/20 19:02:34 mjacob Exp */ /* @@ -183,8 +183,12 @@ struct alpha_logout_area { * NOTE THAT THESE DEFINITIONS MAY CHANGE IN FUTURE ALPHA CPUS! */ -#define ALPHA_PGSHIFT 13 +#define ALPHA_PGSHIFT 13 /* bits that index within page */ +#define ALPHA_PTSHIFT 10 /* bits that index within page tables */ #define ALPHA_PGBYTES (1 << ALPHA_PGSHIFT) +#define ALPHA_L3SHIFT ALPHA_PGSHIFT +#define ALPHA_L2SHIFT (ALPHA_L3SHIFT+ALPHA_PTSHIFT) +#define ALPHA_L1SHIFT (ALPHA_L2SHIFT+ALPHA_PTSHIFT) #define ALPHA_USEG_BASE 0 /* virtual */ #define ALPHA_USEG_END 0x000003ffffffffff @@ -218,8 +222,8 @@ struct alpha_logout_area { #define ALPHA_PTE_PFN 0xffffffff00000000 -#define ALPHA_PTE_TO_PFN(pte) ((pte) >> 32) -#define ALPHA_PTE_FROM_PFN(pfn) ((pfn) << 32) +#define ALPHA_PTE_TO_PFN(pte) ((u_long)(pte) >> 32) +#define ALPHA_PTE_FROM_PFN(pfn) ((u_long)(pfn) << 32) typedef unsigned long alpha_pt_entry_t; @@ -280,6 +284,7 @@ typedef unsigned long alpha_pt_entry_t; #define ALPHA_IMPLVER_EV5 1 /* EV5/EV56/PCA56 */ #define ALPHA_IMPLVER_EV6 2 /* EV6 */ + /* * Stubs for Alpha instructions normally inaccessible from C. */ @@ -307,6 +312,7 @@ unsigned long alpha_pal_rdmces __P((void)); unsigned long alpha_pal_rdps __P((void)); unsigned long alpha_pal_rdusp __P((void)); unsigned long alpha_pal_rdval __P((void)); +unsigned long alpha_pal_swpctx __P((unsigned long)); unsigned long alpha_pal_swpipl __P((unsigned long)); unsigned long _alpha_pal_swpipl __P((unsigned long)); /* for profiling */ void alpha_pal_tbi __P((unsigned long, vm_offset_t)); diff --git a/sys/alpha/include/asm.h b/sys/alpha/include/asm.h index e68927f..f5044df 100644 --- a/sys/alpha/include/asm.h +++ b/sys/alpha/include/asm.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: asm.h,v 1.1 1998/01/10 22:09:52 jb Exp $ */ /* From: NetBSD: asm.h,v 1.18 1997/11/03 04:22:06 ross Exp */ /* @@ -474,7 +474,7 @@ _name_ = _value_ _name_:; \ .mask _i_mask_|IM_EXC,0; \ .frame sp,MSS_SIZE,ra; -/* .livereg _i_mask_|IM_EXC,0 +/* .livereg _i_mask_|IM_EXC,0 */ /* should have been .proc _name_,1; \ .frame MSS_SIZE,$31,_i_mask_,0; \ @@ -617,7 +617,7 @@ label: ASCIZ msg; \ * Kernel RCS ID tag and copyright macros */ -#ifdef _KERNEL +#ifdef KERNEL #ifdef __ELF__ #define __KERNEL_SECTIONSTRING(_sec, _str) \ diff --git a/sys/alpha/include/bootinfo.h b/sys/alpha/include/bootinfo.h new file mode 100644 index 0000000..36b3943 --- /dev/null +++ b/sys/alpha/include/bootinfo.h @@ -0,0 +1,21 @@ +/* + * Kernel-internal structure used to hold important bits of boot + * information. NOT to be used by boot blocks. + * + * Note that not all of the fields from the bootinfo struct(s) + * passed by the boot blocks aren't here (because they're not currently + * used by the kernel!). Fields here which aren't supplied by the + * bootinfo structure passed by the boot blocks are supposed to be + * filled in at startup with sane contents. + */ +struct bootinfo_kernel { + u_long ssym; /* start of syms */ + u_long esym; /* end of syms */ + u_long hwrpb_phys; /* hwrpb physical address */ + u_long hwrpb_size; /* size of hwrpb data */ + char boot_flags[64]; /* boot flags */ + char booted_kernel[64]; /* name of booted kernel */ + char booted_dev[64]; /* name of booted device */ +}; + +extern struct bootinfo_kernel bootinfo; diff --git a/sys/alpha/include/bus.h b/sys/alpha/include/bus.h new file mode 100644 index 0000000..dfb7cde --- /dev/null +++ b/sys/alpha/include/bus.h @@ -0,0 +1,620 @@ +/* $NetBSD: bus.h,v 1.22 1998/05/13 21:21:16 thorpej Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _ALPHA_BUS_H_ +#define _ALPHA_BUS_H_ + +#ifndef __BUS_SPACE_COMPAT_OLDDEFS +#define __BUS_SPACE_COMPAT_OLDDEFS +#endif + +/* + * Addresses (in bus space). + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +/* + * Access methods for bus space. + */ +typedef struct alpha_bus_space *bus_space_tag_t; +typedef u_long bus_space_handle_t; + +struct alpha_bus_space { + /* cookie */ + void *abs_cookie; + + /* mapping/unmapping */ + int (*abs_map) __P((void *, bus_addr_t, bus_size_t, + int, bus_space_handle_t *)); + void (*abs_unmap) __P((void *, bus_space_handle_t, + bus_size_t)); + int (*abs_subregion) __P((void *, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *)); + + /* allocation/deallocation */ + int (*abs_alloc) __P((void *, bus_addr_t, bus_addr_t, + bus_size_t, bus_size_t, bus_size_t, int, + bus_addr_t *, bus_space_handle_t *)); + void (*abs_free) __P((void *, bus_space_handle_t, + bus_size_t)); + + /* barrier */ + void (*abs_barrier) __P((void *, bus_space_handle_t, + bus_size_t, bus_size_t, int)); + + /* read (single) */ + u_int8_t (*abs_r_1) __P((void *, bus_space_handle_t, + bus_size_t)); + u_int16_t (*abs_r_2) __P((void *, bus_space_handle_t, + bus_size_t)); + u_int32_t (*abs_r_4) __P((void *, bus_space_handle_t, + bus_size_t)); + u_int64_t (*abs_r_8) __P((void *, bus_space_handle_t, + bus_size_t)); + + /* read multiple */ + void (*abs_rm_1) __P((void *, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t)); + void (*abs_rm_2) __P((void *, bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t)); + void (*abs_rm_4) __P((void *, bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t)); + void (*abs_rm_8) __P((void *, bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t)); + + /* read region */ + void (*abs_rr_1) __P((void *, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t)); + void (*abs_rr_2) __P((void *, bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t)); + void (*abs_rr_4) __P((void *, bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t)); + void (*abs_rr_8) __P((void *, bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t)); + + /* write (single) */ + void (*abs_w_1) __P((void *, bus_space_handle_t, + bus_size_t, u_int8_t)); + void (*abs_w_2) __P((void *, bus_space_handle_t, + bus_size_t, u_int16_t)); + void (*abs_w_4) __P((void *, bus_space_handle_t, + bus_size_t, u_int32_t)); + void (*abs_w_8) __P((void *, bus_space_handle_t, + bus_size_t, u_int64_t)); + + /* write multiple */ + void (*abs_wm_1) __P((void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t)); + void (*abs_wm_2) __P((void *, bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t)); + void (*abs_wm_4) __P((void *, bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t)); + void (*abs_wm_8) __P((void *, bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t)); + + /* write region */ + void (*abs_wr_1) __P((void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t)); + void (*abs_wr_2) __P((void *, bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t)); + void (*abs_wr_4) __P((void *, bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t)); + void (*abs_wr_8) __P((void *, bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t)); + + /* set multiple */ + void (*abs_sm_1) __P((void *, bus_space_handle_t, + bus_size_t, u_int8_t, bus_size_t)); + void (*abs_sm_2) __P((void *, bus_space_handle_t, + bus_size_t, u_int16_t, bus_size_t)); + void (*abs_sm_4) __P((void *, bus_space_handle_t, + bus_size_t, u_int32_t, bus_size_t)); + void (*abs_sm_8) __P((void *, bus_space_handle_t, + bus_size_t, u_int64_t, bus_size_t)); + + /* set region */ + void (*abs_sr_1) __P((void *, bus_space_handle_t, + bus_size_t, u_int8_t, bus_size_t)); + void (*abs_sr_2) __P((void *, bus_space_handle_t, + bus_size_t, u_int16_t, bus_size_t)); + void (*abs_sr_4) __P((void *, bus_space_handle_t, + bus_size_t, u_int32_t, bus_size_t)); + void (*abs_sr_8) __P((void *, bus_space_handle_t, + bus_size_t, u_int64_t, bus_size_t)); + + /* copy */ + void (*abs_c_1) __P((void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t)); + void (*abs_c_2) __P((void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t)); + void (*abs_c_4) __P((void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t)); + void (*abs_c_8) __P((void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t)); +}; + + +/* + * Utility macros; INTERNAL USE ONLY. + */ +#define __abs_c(a,b) __CONCAT(a,b) +#define __abs_opname(op,size) __abs_c(__abs_c(__abs_c(abs_,op),_),size) + +#define __abs_rs(sz, t, h, o) \ + (*(t)->__abs_opname(r,sz))((t)->abs_cookie, h, o) +#define __abs_ws(sz, t, h, o, v) \ + (*(t)->__abs_opname(w,sz))((t)->abs_cookie, h, o, v) +#ifndef DEBUG +#define __abs_nonsingle(type, sz, t, h, o, a, c) \ + (*(t)->__abs_opname(type,sz))((t)->abs_cookie, h, o, a, c) +#else +#define __abs_nonsingle(type, sz, t, h, o, a, c) \ + do { \ + if (((unsigned long)a & (sz - 1)) != 0) \ + panic("bus non-single %d-byte unaligned (to %p) at %s:%d", \ + sz, a, __FILE__, __LINE__); \ + (*(t)->__abs_opname(type,sz))((t)->abs_cookie, h, o, a, c); \ + } while (0) +#endif +#define __abs_set(type, sz, t, h, o, v, c) \ + (*(t)->__abs_opname(type,sz))((t)->abs_cookie, h, o, v, c) +#define __abs_copy(sz, t, h1, o1, h2, o2, cnt) \ + (*(t)->__abs_opname(c,sz))((t)->abs_cookie, h1, o1, h2, o2, cnt) + + +/* + * Mapping and unmapping operations. + */ +#define bus_space_map(t, a, s, f, hp) \ + (*(t)->abs_map)((t)->abs_cookie, (a), (s), (f), (hp)) +#define bus_space_unmap(t, h, s) \ + (*(t)->abs_unmap)((t)->abs_cookie, (h), (s)) +#define bus_space_subregion(t, h, o, s, hp) \ + (*(t)->abs_subregion)((t)->abs_cookie, (h), (o), (s), (hp)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 + +/* + * Allocation and deallocation operations. + */ +#define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp) \ + (*(t)->abs_alloc)((t)->abs_cookie, (rs), (re), (s), (a), (b), \ + (f), (ap), (hp)) +#define bus_space_free(t, h, s) \ + (*(t)->abs_free)((t)->abs_cookie, (h), (s)) + + +/* + * Bus barrier operations. + */ +#define bus_space_barrier(t, h, o, l, f) \ + (*(t)->abs_barrier)((t)->abs_cookie, (h), (o), (l), (f)) + +#define BUS_SPACE_BARRIER_READ 0x01 +#define BUS_SPACE_BARRIER_WRITE 0x02 + +#ifdef __BUS_SPACE_COMPAT_OLDDEFS +/* compatibility definitions; deprecated */ +#define BUS_BARRIER_READ BUS_SPACE_BARRIER_READ +#define BUS_BARRIER_WRITE BUS_SPACE_BARRIER_WRITE +#endif + + +/* + * Bus read (single) operations. + */ +#define bus_space_read_1(t, h, o) __abs_rs(1,(t),(h),(o)) +#define bus_space_read_2(t, h, o) __abs_rs(2,(t),(h),(o)) +#define bus_space_read_4(t, h, o) __abs_rs(4,(t),(h),(o)) +#define bus_space_read_8(t, h, o) __abs_rs(8,(t),(h),(o)) + + +/* + * Bus read multiple operations. + */ +#define bus_space_read_multi_1(t, h, o, a, c) \ + __abs_nonsingle(rm,1,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_2(t, h, o, a, c) \ + __abs_nonsingle(rm,2,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_4(t, h, o, a, c) \ + __abs_nonsingle(rm,4,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_8(t, h, o, a, c) \ + __abs_nonsingle(rm,8,(t),(h),(o),(a),(c)) + + +/* + * Bus read region operations. + */ +#define bus_space_read_region_1(t, h, o, a, c) \ + __abs_nonsingle(rr,1,(t),(h),(o),(a),(c)) +#define bus_space_read_region_2(t, h, o, a, c) \ + __abs_nonsingle(rr,2,(t),(h),(o),(a),(c)) +#define bus_space_read_region_4(t, h, o, a, c) \ + __abs_nonsingle(rr,4,(t),(h),(o),(a),(c)) +#define bus_space_read_region_8(t, h, o, a, c) \ + __abs_nonsingle(rr,8,(t),(h),(o),(a),(c)) + + +/* + * Bus write (single) operations. + */ +#define bus_space_write_1(t, h, o, v) __abs_ws(1,(t),(h),(o),(v)) +#define bus_space_write_2(t, h, o, v) __abs_ws(2,(t),(h),(o),(v)) +#define bus_space_write_4(t, h, o, v) __abs_ws(4,(t),(h),(o),(v)) +#define bus_space_write_8(t, h, o, v) __abs_ws(8,(t),(h),(o),(v)) + + +/* + * Bus write multiple operations. + */ +#define bus_space_write_multi_1(t, h, o, a, c) \ + __abs_nonsingle(wm,1,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_2(t, h, o, a, c) \ + __abs_nonsingle(wm,2,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_4(t, h, o, a, c) \ + __abs_nonsingle(wm,4,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_8(t, h, o, a, c) \ + __abs_nonsingle(wm,8,(t),(h),(o),(a),(c)) + + +/* + * Bus write region operations. + */ +#define bus_space_write_region_1(t, h, o, a, c) \ + __abs_nonsingle(wr,1,(t),(h),(o),(a),(c)) +#define bus_space_write_region_2(t, h, o, a, c) \ + __abs_nonsingle(wr,2,(t),(h),(o),(a),(c)) +#define bus_space_write_region_4(t, h, o, a, c) \ + __abs_nonsingle(wr,4,(t),(h),(o),(a),(c)) +#define bus_space_write_region_8(t, h, o, a, c) \ + __abs_nonsingle(wr,8,(t),(h),(o),(a),(c)) + + +/* + * Set multiple operations. + */ +#define bus_space_set_multi_1(t, h, o, v, c) \ + __abs_set(sm,1,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_2(t, h, o, v, c) \ + __abs_set(sm,2,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_4(t, h, o, v, c) \ + __abs_set(sm,4,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_8(t, h, o, v, c) \ + __abs_set(sm,8,(t),(h),(o),(v),(c)) + + +/* + * Set region operations. + */ +#define bus_space_set_region_1(t, h, o, v, c) \ + __abs_set(sr,1,(t),(h),(o),(v),(c)) +#define bus_space_set_region_2(t, h, o, v, c) \ + __abs_set(sr,2,(t),(h),(o),(v),(c)) +#define bus_space_set_region_4(t, h, o, v, c) \ + __abs_set(sr,4,(t),(h),(o),(v),(c)) +#define bus_space_set_region_8(t, h, o, v, c) \ + __abs_set(sr,8,(t),(h),(o),(v),(c)) + + +/* + * Copy region operations. + */ +#define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \ + __abs_copy(1, (t), (h1), (o1), (h2), (o2), (c)) +#define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \ + __abs_copy(2, (t), (h1), (o1), (h2), (o2), (c)) +#define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \ + __abs_copy(4, (t), (h1), (o1), (h2), (o2), (c)) +#define bus_space_copy_region_8(t, h1, o1, h2, o2, c) \ + __abs_copy(8, (t), (h1), (o1), (h2), (o2), (c)) + +#ifdef __BUS_SPACE_COMPAT_OLDDEFS +/* compatibility definitions; deprecated */ +#define bus_space_copy_1(t, h1, o1, h2, o2, c) \ + bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c)) +#define bus_space_copy_2(t, h1, o1, h2, o2, c) \ + bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c)) +#define bus_space_copy_4(t, h1, o1, h2, o2, c) \ + bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c)) +#define bus_space_copy_8(t, h1, o1, h2, o2, c) \ + bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c)) +#endif + + +/* + * Bus DMA methods. + */ + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x04 /* hint: map memory DMA coherent */ +#define BUS_DMA_BUS1 0x10 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x20 +#define BUS_DMA_BUS3 0x40 +#define BUS_DMA_BUS4 0x80 + +/* + * Private flags stored in the DMA map. + */ +#define DMAMAP_HAS_SGMAP 0x80000000 /* sgva/len are valid */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct uio; +struct alpha_sgmap; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ +#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ +#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ +#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ + +/* + * alpha_bus_t + * + * Busses supported by NetBSD/alpha, used by internal + * utility functions. NOT TO BE USED BY MACHINE-INDEPENDENT + * CODE! + */ +typedef enum { + ALPHA_BUS_TURBOCHANNEL, + ALPHA_BUS_PCI, + ALPHA_BUS_EISA, + ALPHA_BUS_ISA, + ALPHA_BUS_TLSB, +} alpha_bus_t; + +typedef struct alpha_bus_dma_tag *bus_dma_tag_t; +typedef struct alpha_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct alpha_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ +}; +typedef struct alpha_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ +struct alpha_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + bus_addr_t _wbase; /* DMA window base */ + + /* + * The following two members are used to chain DMA windows + * together. If, during the course of a map load, the + * resulting physical memory address is too large to + * be addressed by the window, the next window will be + * attempted. These would be chained together like so: + * + * direct -> sgmap -> NULL + * or + * sgmap -> NULL + * or + * direct -> NULL + * + * If the window size is 0, it will not be checked (e.g. + * TurboChannel DMA). + */ + bus_size_t _wsize; + struct alpha_bus_dma_tag *_next_window; + + /* + * A chipset may have more than one SGMAP window, so SGMAP + * windows also get a pointer to their SGMAP state. + */ + struct alpha_sgmap *_sgmap; + + /* + * Internal-use only utility methods. NOT TO BE USED BY + * MACHINE-INDEPENDENT CODE! + */ + bus_dma_tag_t (*_get_tag) __P((bus_dma_tag_t, alpha_bus_t)); + + /* + * DMA mapping methods. + */ + int (*_dmamap_create) __P((bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *)); + void (*_dmamap_destroy) __P((bus_dma_tag_t, bus_dmamap_t)); + int (*_dmamap_load) __P((bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int)); + int (*_dmamap_load_mbuf) __P((bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int)); + int (*_dmamap_load_uio) __P((bus_dma_tag_t, bus_dmamap_t, + struct uio *, int)); + int (*_dmamap_load_raw) __P((bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int)); + void (*_dmamap_unload) __P((bus_dma_tag_t, bus_dmamap_t)); + void (*_dmamap_sync) __P((bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int)); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int)); + void (*_dmamem_free) __P((bus_dma_tag_t, + bus_dma_segment_t *, int)); + int (*_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int)); + void (*_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t)); + int (*_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *, + int, int, int, int)); +}; + +#define alphabus_dma_get_tag(t, b) \ + (*(t)->_get_tag)(t, b) + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, o, l, ops) \ + (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct alpha_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use my machine-independent code. + */ + vm_object_t _dm_obj; /* for allocating pages */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + /* + * This is used only for SGMAP-mapped DMA, but we keep it + * here to avoid pointless indirection. + */ + int _dm_pteidx; /* PTE index */ + int _dm_ptecnt; /* PTE count */ + u_long _dm_sgva; /* allocated sgva */ + bus_size_t _dm_sgvalen; /* svga length */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#ifdef _ALPHA_BUS_DMA_PRIVATE +int _bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t, + bus_size_t, int, bus_dmamap_t *)); +void _bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t)); + +int _bus_dmamap_load_direct __P((bus_dma_tag_t, bus_dmamap_t, + void *, bus_size_t, struct proc *, int)); +int _bus_dmamap_load_mbuf_direct __P((bus_dma_tag_t, + bus_dmamap_t, struct mbuf *, int)); +int _bus_dmamap_load_uio_direct __P((bus_dma_tag_t, + bus_dmamap_t, struct uio *, int)); +int _bus_dmamap_load_raw_direct __P((bus_dma_tag_t, + bus_dmamap_t, bus_dma_segment_t *, int, bus_size_t, int)); + +void _bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t)); +void _bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int)); + +int _bus_dmamem_alloc __P((bus_dma_tag_t tag, bus_dmamap_t, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags)); +void _bus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs)); +int _bus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags)); +void _bus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva, + size_t size)); +int _bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, int off, int prot, int flags)); +#endif /* _ALPHA_BUS_DMA_PRIVATE */ + +#endif /* _ALPHA_BUS_H_ */ diff --git a/sys/alpha/include/chipset.h b/sys/alpha/include/chipset.h new file mode 100644 index 0000000..aa6f606 --- /dev/null +++ b/sys/alpha/include/chipset.h @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#ifndef _MACHINE_CHIPSET_H_ +#define _MACHINE_CHIPSET_H_ + +typedef u_int8_t alpha_chipset_inb_t(u_int32_t port); +typedef u_int16_t alpha_chipset_inw_t(u_int32_t port); +typedef u_int32_t alpha_chipset_inl_t(u_int32_t port); +typedef void alpha_chipset_outb_t(u_int32_t port, u_int8_t data); +typedef void alpha_chipset_outw_t(u_int32_t port, u_int16_t data); +typedef void alpha_chipset_outl_t(u_int32_t port, u_int32_t data); + +typedef int alpha_chipset_maxdevs_t(u_int bus); +typedef u_int8_t alpha_chipset_cfgreadb_t(u_int, u_int, u_int, u_int); +typedef u_int16_t alpha_chipset_cfgreadw_t(u_int, u_int, u_int, u_int); +typedef u_int32_t alpha_chipset_cfgreadl_t(u_int, u_int, u_int, u_int); +typedef void alpha_chipset_cfgwriteb_t(u_int, u_int, u_int, u_int, + u_int8_t); +typedef void alpha_chipset_cfgwritew_t(u_int, u_int, u_int, u_int, + u_int16_t); +typedef void alpha_chipset_cfgwritel_t(u_int, u_int, u_int, u_int, + u_int32_t); + + +typedef struct alpha_chipset { + /* + * I/O port access + */ + alpha_chipset_inb_t* inb; + alpha_chipset_inw_t* inw; + alpha_chipset_inl_t* inl; + alpha_chipset_outb_t* outb; + alpha_chipset_outw_t* outw; + alpha_chipset_outl_t* outl; + + /* + * PCI configuration access + */ + alpha_chipset_maxdevs_t* maxdevs; + alpha_chipset_cfgreadb_t* cfgreadb; + alpha_chipset_cfgreadw_t* cfgreadw; + alpha_chipset_cfgreadl_t* cfgreadl; + alpha_chipset_cfgwriteb_t* cfgwriteb; + alpha_chipset_cfgwritew_t* cfgwritew; + alpha_chipset_cfgwritel_t* cfgwritel; +} alpha_chipset_t; + +extern alpha_chipset_t chipset; + +#endif /* !_MACHINE_CHIPSET_H_ */ diff --git a/sys/alpha/include/clock.h b/sys/alpha/include/clock.h new file mode 100644 index 0000000..95c160f --- /dev/null +++ b/sys/alpha/include/clock.h @@ -0,0 +1,22 @@ +/* + * Kernel interface to machine-dependent clock driver. + * Garrett Wollman, September 1994. + * This file is in the public domain. + * + * $Id: clock.h,v 1.34 1998/03/05 21:45:42 tegge Exp $ + */ + +#ifndef _MACHINE_CLOCK_H_ +#define _MACHINE_CLOCK_H_ + +#ifdef KERNEL + +extern int wall_cmos_clock; +extern int adjkerntz; + +void DELAY __P((int usec)); +int sysbeep __P((int pitch, int period)); + +#endif /* KERNEL */ + +#endif /* !_MACHINE_CLOCK_H_ */ diff --git a/sys/alpha/include/conf.h b/sys/alpha/include/conf.h new file mode 100644 index 0000000..ee6b603 --- /dev/null +++ b/sys/alpha/include/conf.h @@ -0,0 +1,11 @@ +#ifndef _MACHINE_CONF_H_ +#define _MACHINE_CONF_H_ + +#ifdef KERNEL +#ifndef ACTUALLY_LKM_NOT_KERNEL +#include "ioconf.h" +#endif + +#endif /* KERNEL */ + +#endif /* !_MACHINE_CONF_H_ */ diff --git a/sys/alpha/include/cons.h b/sys/alpha/include/cons.h new file mode 100644 index 0000000..df135cc --- /dev/null +++ b/sys/alpha/include/cons.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1991 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. 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: @(#)cons.h 7.2 (Berkeley) 5/9/91 + * $Id: cons.h,v 1.17 1997/07/01 00:54:37 bde Exp $ + */ + +#ifndef _MACHINE_CONS_H_ +#define _MACHINE_CONS_H_ + +struct consdev; +typedef void cn_probe_t __P((struct consdev *)); +typedef void cn_init_t __P((struct consdev *)); +typedef int cn_getc_t __P((dev_t)); +typedef int cn_checkc_t __P((dev_t)); +typedef void cn_putc_t __P((dev_t, int)); + +#ifdef KERNEL +/* + * XXX public functions in drivers should be declared in headers produced + * by `config', not here. + */ +cn_probe_t pccnprobe; +cn_init_t pccninit; +cn_getc_t pccngetc; +cn_checkc_t pccncheckc; +cn_putc_t pccnputc; + +cn_probe_t sccnprobe; +cn_init_t sccninit; +cn_getc_t sccngetc; +cn_checkc_t sccncheckc; +cn_putc_t sccnputc; + +cn_probe_t siocnprobe; +cn_init_t siocninit; +cn_getc_t siocngetc; +cn_checkc_t siocncheckc; +cn_putc_t siocnputc; +#endif /* KERNEL */ + +struct consdev { + cn_probe_t *cn_probe; + /* probe hardware and fill in consdev info */ + cn_init_t *cn_init; + /* turn on as console */ + cn_getc_t *cn_getc; + /* kernel getchar interface */ + cn_checkc_t *cn_checkc; + /* kernel "return char if available" interface */ + cn_putc_t *cn_putc; + /* kernel putchar interface */ + struct tty *cn_tp; /* tty structure for console device */ + dev_t cn_dev; /* major/minor of device */ + short cn_pri; /* pecking order; the higher the better */ +}; + +/* values for cn_pri - reflect our policy for console selection */ +#define CN_DEAD 0 /* device doesn't exist */ +#define CN_NORMAL 1 /* device exists but is nothing special */ +#define CN_INTERNAL 2 /* "internal" bit-mapped display */ +#define CN_REMOTE 3 /* serial interface with remote bit set */ + +#ifdef KERNEL +extern int cons_unavail; + +/* Other kernel entry points. */ +int cncheckc __P((void)); +int cngetc __P((void)); +void cninit __P((void)); +void cninit_finish __P((void)); +void cnputc __P((int)); + +#endif /* KERNEL */ + +#endif /* !_MACHINE_CONS_H_ */ diff --git a/sys/alpha/include/cpu.h b/sys/alpha/include/cpu.h index adf0eba..6b0c81f 100644 --- a/sys/alpha/include/cpu.h +++ b/sys/alpha/include/cpu.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: cpu.h,v 1.1 1998/01/10 10:13:14 jb Exp $ */ /* From: NetBSD: cpu.h,v 1.18 1997/09/23 23:17:49 mjacob Exp */ /* @@ -53,12 +53,6 @@ #include <machine/frame.h> /* - * definitions of cpu-dependent requirements - * referenced in generic code - */ -#define cpu_wait(p) /* nothing */ - -/* * Arguments to hardclock and gatherstats encapsulate the previous * machine state in an opaque clockframe. One the Alpha, we use * what we push on an interrupt (a trapframe). @@ -98,7 +92,7 @@ struct clockframe { #define aston() (astpending = 1) -#ifdef _KERNEL +#ifdef KERNEL u_int64_t astpending; /* need to trap before returning to user mode */ u_int64_t want_resched; /* resched() was called */ #endif @@ -125,7 +119,7 @@ u_int64_t want_resched; /* resched() was called */ { "booted_kernel", CTLTYPE_STRING }, \ } -#ifdef _KERNEL +#ifdef KERNEL struct pcb; struct proc; @@ -133,7 +127,6 @@ struct reg; struct rpb; struct trapframe; -extern int cold; extern struct proc *fpcurproc; extern struct rpb *hwrpb; extern volatile int mc_expected, mc_received; @@ -145,19 +138,19 @@ void XentMM __P((u_int64_t, u_int64_t, u_int64_t)); /* MAGIC */ void XentRestart __P((void)); /* MAGIC */ void XentSys __P((u_int64_t, u_int64_t, u_int64_t)); /* MAGIC */ void XentUna __P((u_int64_t, u_int64_t, u_int64_t)); /* MAGIC */ -void alpha_init __P((u_long, u_long, u_long, u_long)); +void alpha_init __P((u_long, u_long, u_long, u_long, u_long)); +int alpha_pa_access __P((u_long)); void ast __P((struct trapframe *)); int badaddr __P((void *, size_t)); int badaddr_read __P((void *, size_t, void *)); void child_return __P((struct proc *p)); -void configure __P((void)); u_int64_t console_restart __P((u_int64_t, u_int64_t, u_int64_t)); void do_sir __P((void)); void dumpconf __P((void)); void exception_return __P((void)); /* MAGIC */ void frametoreg __P((struct trapframe *, struct reg *)); long fswintrberr __P((void)); /* MAGIC */ -void init_prom_interface __P((void)); +void init_prom_interface __P((struct rpb*)); void interrupt __P((unsigned long, unsigned long, unsigned long, struct trapframe *)); void machine_check @@ -173,6 +166,7 @@ void switch_trampoline __P((void)); /* MAGIC */ void syscall __P((u_int64_t, struct trapframe *)); void trap __P((unsigned long, unsigned long, unsigned long, unsigned long, struct trapframe *)); +void cpu_set_fork_handler __P((struct proc *, void (*pc)(void *), void *)); #endif /* _KERNEL */ diff --git a/sys/alpha/include/cpuconf.h b/sys/alpha/include/cpuconf.h new file mode 100644 index 0000000..30ef4c7 --- /dev/null +++ b/sys/alpha/include/cpuconf.h @@ -0,0 +1,118 @@ +/* $NetBSD: cpuconf.h,v 1.7 1997/11/06 00:42:03 thorpej Exp $ */ +#ifndef _ALPHA_CPUCONF_H +#define _ALPHA_CPUCONF_H +/* + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * 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 Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * 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. + */ +/* + * Additional reworking by Matthew Jacob for NASA/Ames Research Center. + * Copyright (c) 1997 + */ +#ifdef KERNEL +/* + * Platform Specific Information and Function Hooks. + * + * The tags family and model information are strings describing the platform. + * + * The tag iobus describes the primary iobus for the platform- primarily + * to give a hint as to where to start configuring. The likely choices + * are one of tcasic, lca, apecs, cia, or tlsb. + * + */ +struct device; /* XXX */ + +extern struct platform { + /* + * Platform Information. + */ + const char *family; /* Family Name */ + const char *model; /* Model (variant) Name */ + const char *iobus; /* Primary iobus name */ + + /* + * Platform Specific Function Hooks + * cons_init - console initialization + * device_register - boot configuration aid + * iointr - I/O interrupt handler + * clockintr - Clock Interrupt Handler + * mcheck_handler - Platform Specific Machine Check Handler + */ + void (*cons_init) __P((void)); + void (*device_register) __P((struct device *, void *)); + void (*iointr) __P((void *, unsigned long)); + void (*clockintr) __P((void *)); + void (*mcheck_handler) __P((unsigned long, struct trapframe *, + unsigned long, unsigned long)); +} platform; + +/* + * Lookup table entry for Alpha system variations. + */ +struct alpha_variation_table { + u_int64_t avt_variation; /* variation, from HWRPB */ + const char *avt_model; /* model string */ +}; + +/* + * There is an array of functions to initialize the platform structure. + * + * It's responsible for filling in the family, model_name and iobus + * tags. It may optionally fill in the cons_init, device_register and + * mcheck_handler tags. + * + * The iointr tag is filled in by set_iointr (in interrupt.c). + * The clockintr tag is filled in by cpu_initclocks (in clock.c). + * + * nocpu is function to call when you can't figure what platform you're on. + * There's no return from this function. + */ + +struct cpuinit { + void (*init) __P((int)); + const char *option; +}; + +#define cpu_notsupp(st) { platform_not_supported, st } +#define cpu_init(fn, opt) { fn, opt } + +/* + * Misc. support routines. + */ +const char *alpha_dsr_sysname __P((void)); +const char *alpha_variation_name __P((u_int64_t variation, + const struct alpha_variation_table *avtp)); +const char *alpha_unknown_sysname __P((void)); + +extern struct cpuinit cpuinit[]; +extern int ncpuinit; +extern void platform_not_configured __P((int)); +extern void platform_not_supported __P((int)); + +#endif /* KERNEL */ +#endif /* !_ALPHA_CPUCONF_H */ diff --git a/sys/alpha/include/cpufunc.h b/sys/alpha/include/cpufunc.h new file mode 100644 index 0000000..6125ba3 --- /dev/null +++ b/sys/alpha/include/cpufunc.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +#ifdef KERNEL + +#include <sys/types.h> +#include <machine/chipset.h> + +#define inb(port) chipset.inb(port) +#define inw(port) chipset.inw(port) +#define inl(port) chipset.inl(port) +#define outb(port, data) chipset.outb(port, data) +#define outw(port, data) chipset.outw(port, data) +#define outl(port, data) chipset.outl(port, data) + +#endif /* KERNEL */ + +#endif /* !_MACHINE_CPUFUNC_H_ */ diff --git a/sys/alpha/include/db_machdep.h b/sys/alpha/include/db_machdep.h new file mode 100644 index 0000000..3aa84d3 --- /dev/null +++ b/sys/alpha/include/db_machdep.h @@ -0,0 +1,112 @@ +/* $NetBSD: db_machdep.h,v 1.6 1997/09/06 02:02:25 thorpej Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _ALPHA_DB_MACHDEP_H_ +#define _ALPHA_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include <sys/param.h> +#include <vm/vm.h> +#include <machine/frame.h> + +typedef vm_offset_t db_addr_t; /* address - unsigned */ +typedef long db_expr_t; /* expression - signed */ + +typedef struct trapframe db_regs_t; +db_regs_t ddb_regs; /* register state */ +#define DDB_REGS (&ddb_regs) + +#define PC_REGS(regs) ((db_addr_t)(regs)->tf_regs[FRAME_PC]) + +#define BKPT_INST 0x00000080 /* breakpoint instruction */ +#define BKPT_SIZE (4) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#if 0 +#define FIXUP_PC_AFTER_BREAK \ + (ddb_regs.tf_regs[FRAME_PC] -= BKPT_SIZE) +#endif + +#define SOFTWARE_SSTEP 1 /* no hardware support */ +#define IS_BREAKPOINT_TRAP(type, code) ((type) == ALPHA_KENTRY_IF && \ + (code) == ALPHA_IF_CODE_BPT) +#define IS_WATCHPOINT_TRAP(type, code) 0 + +/* + * Functions needed for software single-stepping. + */ + +boolean_t db_inst_trap_return __P((int inst)); +boolean_t db_inst_return __P((int inst)); +boolean_t db_inst_call __P((int inst)); +boolean_t db_inst_branch __P((int inst)); +boolean_t db_inst_load __P((int inst)); +boolean_t db_inst_store __P((int inst)); +boolean_t db_inst_unconditional_flow_transfer __P((int inst)); +db_addr_t db_branch_taken __P((int inst, db_addr_t pc, db_regs_t *regs)); + +#define inst_trap_return(ins) db_inst_trap_return(ins) +#define inst_return(ins) db_inst_return(ins) +#define inst_call(ins) db_inst_call(ins) +#define inst_branch(ins) db_inst_branch(ins) +#define inst_load(ins) db_inst_load(ins) +#define inst_store(ins) db_inst_store(ins) +#define inst_unconditional_flow_transfer(ins) \ + db_inst_unconditional_flow_transfer(ins) +#define branch_taken(ins, pc, regs) \ + db_branch_taken((ins), (pc), (regs)) + +/* No delay slots on Alpha. */ +#define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4))) + +u_long db_register_value __P((db_regs_t *, int)); +int ddb_trap __P((unsigned long, unsigned long, unsigned long, + unsigned long, struct trapframe *)); + +/* + * Pretty arbitrary + */ +#define DB_SMALL_VALUE_MAX 0x7fffffff +#define DB_SMALL_VALUE_MIN (-0x400001) + +/* + * We define some of our own commands. + */ +#define DB_MACHINE_COMMANDS + +/* + * We use Elf64 symbols in DDB. + */ +#define DB_ELF_SYMBOLS +#define DB_ELFSIZE 64 + +#endif /* _ALPHA_DB_MACHDEP_H_ */ diff --git a/sys/alpha/include/elf.h b/sys/alpha/include/elf.h index ce2da56..e49a729 100644 --- a/sys/alpha/include/elf.h +++ b/sys/alpha/include/elf.h @@ -23,17 +23,17 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elf.h,v 1.2 1997/08/30 18:59:48 peter Exp $ + * $Id: elf.h,v 1.1.1.1 1998/03/09 05:42:33 jb Exp $ */ #ifndef _MACHINE_ELF_H_ #define _MACHINE_ELF_H_ 1 /* - * ELF definitions for the i386 architecture. + * ELF definitions for the alpha architecture. */ -#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */ +#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */ /* * Auxiliary vector entries for passing information to the interpreter. @@ -43,13 +43,13 @@ */ typedef struct { /* Auxiliary vector entry on initial stack */ - int a_type; /* Entry type. */ + long a_type; /* Entry type. */ union { long a_val; /* Integer value. */ void *a_ptr; /* Address. */ void (*a_fcn)(void); /* Function pointer (not used). */ } a_un; -} Elf32_Auxinfo; +} Elf64_Auxinfo; /* Values for a_type. */ #define AT_NULL 0 /* Terminates the vector. */ @@ -89,24 +89,41 @@ typedef struct { /* Auxiliary vector entry on initial stack */ * Relocation types. */ -#define R_386_NONE 0 /* No relocation. */ -#define R_386_32 1 /* Add symbol value. */ -#define R_386_PC32 2 /* Add PC-relative symbol value. */ -#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ -#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ -#define R_386_COPY 5 /* Copy data from shared object. */ -#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ -#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ -#define R_386_RELATIVE 8 /* Add load address of shared object. */ -#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ -#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_OP_PUSH 12 /* OP stack push */ +#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ +#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ +#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ +#define R_ALPHA_GPVALUE 16 +#define R_ALPHA_GPRELHIGH 17 +#define R_ALPHA_GPRELLOW 18 +#define R_ALPHA_IMMED_GP_16 19 +#define R_ALPHA_IMMED_GP_HI32 20 +#define R_ALPHA_IMMED_SCN_HI32 21 +#define R_ALPHA_IMMED_BR_HI32 22 +#define R_ALPHA_IMMED_LO32 23 +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ -#define R_386_COUNT 11 /* Count of defined relocation types. */ +#define R_ALPHA_COUNT 28 /* Define "machine" characteristics */ -#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_CLASS ELFCLASS64 #define ELF_TARG_DATA ELFDATA2LSB -#define ELF_TARG_MACH EM_386 +#define ELF_TARG_MACH EM_ALPHA #define ELF_TARG_VER 1 #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/alpha/include/in_cksum.h b/sys/alpha/include/in_cksum.h new file mode 100644 index 0000000..7e1c0f0 --- /dev/null +++ b/sys/alpha/include/in_cksum.h @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * 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 tahoe: in_cksum.c 1.2 86/01/05 + * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 + * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp + * $Id: in_cksum.h,v 1.5 1997/08/16 19:14:55 wollman Exp $ + */ + +#ifndef _MACHINE_IN_CKSUM_H_ +#define _MACHINE_IN_CKSUM_H_ 1 + +#include <sys/cdefs.h> + +/* + * It it useful to have an Internet checksum routine which is inlineable + * and optimized specifically for the task of computing IP header checksums + * in the normal case (where there are no options and the header length is + * therefore always exactly five 32-bit words. + */ +#ifdef __GNUC__ + +static __inline void +in_cksum_update(struct ip *ip) +{ + int __tmpsum; + __tmpsum = (int)ntohs(ip->ip_sum) + 256; + ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16)); +} + +#else + +#define in_cksum_update(ip) \ + do { \ + int __tmpsum; \ + __tmpsum = (int)ntohs(ip->ip_sum) + 256; \ + ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16)); \ + } while(0) + +#endif + +typedef unsigned in_psum_t; +#ifdef KERNEL +u_int in_cksum_hdr(const struct ip *ip); +in_psum_t in_cksum_partial(in_psum_t psum, const u_short *w, int len); +int in_cksum_finalize(in_psum_t psum); +#endif /* KERNEL */ + +#endif /* _MACHINE_IN_CKSUM_H_ */ diff --git a/sys/alpha/include/ipl.h b/sys/alpha/include/ipl.h new file mode 100644 index 0000000..d4ed20e --- /dev/null +++ b/sys/alpha/include/ipl.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#ifndef _MACHINE_IPL_H_ +#define _MACHINE_IPL_H_ + +#include <machine/alpha_cpu.h> + +/* IPL-lowering/restoring macros */ +#define splx(s) \ + ((s) == ALPHA_PSL_IPL_0 ? spl0() : alpha_pal_swpipl(s)) +#define splsoft() alpha_pal_swpipl(ALPHA_PSL_IPL_SOFT) +#define splsoftclock() splsoft() +#define splsoftnet() splsoft() + +/* IPL-raising functions/macros */ +static __inline int _splraise __P((int)) __attribute__ ((unused)); +static __inline int +_splraise(s) + int s; +{ + int cur = alpha_pal_rdps() & ALPHA_PSL_IPL_MASK; + return (s > cur ? alpha_pal_swpipl(s) : cur); +} +#define splnet() _splraise(ALPHA_PSL_IPL_IO) +#define splbio() _splraise(ALPHA_PSL_IPL_IO) +#define splimp() _splraise(ALPHA_PSL_IPL_IO) +#define spltty() _splraise(ALPHA_PSL_IPL_IO) +#define splvm() _splraise(ALPHA_PSL_IPL_IO) +#define splclock() _splraise(ALPHA_PSL_IPL_CLOCK) +#define splstatclock() _splraise(ALPHA_PSL_IPL_CLOCK) +#define splhigh() _splraise(ALPHA_PSL_IPL_HIGH) + +/* + * simulated software interrupt register + */ +extern u_int64_t ssir; + +#define SIR_NET 0x1 +#define SIR_CLOCK 0x2 + +#define setsoftnet() ssir |= SIR_NET +#define setsoftclock() ssir |= SIR_CLOCK + +extern void spl0(void); + +/* XXX bogus */ +extern unsigned cpl; /* current priority level mask */ + +#endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/alpha/include/lock.h b/sys/alpha/include/lock.h index b5604e8..a00a1e3 100644 --- a/sys/alpha/include/lock.h +++ b/sys/alpha/include/lock.h @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: lock.h,v 1.5 1997/12/15 02:18:27 tegge Exp $ + * $Id: lock.h,v 1.1.1.1 1998/03/09 05:43:16 jb Exp $ */ @@ -38,5 +38,9 @@ struct simplelock { volatile int lock_data; }; +#define simple_lock_init(alp) +#define simple_lock(alp) +#define simple_lock_try(alp) 1 +#define simple_unlock(alp) #endif /* !_MACHINE_LOCK_H_ */ diff --git a/sys/alpha/include/md_var.h b/sys/alpha/include/md_var.h new file mode 100644 index 0000000..d70c1da --- /dev/null +++ b/sys/alpha/include/md_var.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#ifndef _MACHINE_MD_VAR_H_ +#define _MACHINE_MD_VAR_H_ + +/* + * Miscellaneous machine-dependent declarations. + */ + +extern char sigcode[]; +extern int szsigcode; +extern int Maxmem; +extern void (*netisrs[32]) __P((void)); + +void cpu_power_down __P((void)); +void cpu_halt __P((void)); +void cpu_reset __P((void)); +int is_physical_memory __P((vm_offset_t addr)); +void swi_vm __P((void)); +int vm_page_zero_idle __P((void)); +int fill_regs __P((struct proc *, struct reg *)); +int set_regs __P((struct proc *, struct reg *)); + +#endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/alpha/include/param.h b/sys/alpha/include/param.h index 92dbbc6..70101f0 100644 --- a/sys/alpha/include/param.h +++ b/sys/alpha/include/param.h @@ -1,4 +1,4 @@ -/* $Id: param.h,v 1.1 1998/01/10 10:13:15 jb Exp $ */ +/* $Id: param.h,v 1.2 1998/03/09 05:53:10 jb Exp $ */ /* From: NetBSD: param.h,v 1.20 1997/09/19 13:52:53 leo Exp */ /* @@ -70,25 +70,20 @@ #define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES) #define ALIGNED_POINTER(p,t) ((((u_long)(p)) & (sizeof(t)-1)) == 0) -#define NBPG (1 << ALPHA_PGSHIFT) /* bytes/page */ -#define PAGE_SIZE NBPG -#define PGOFSET (NBPG-1) /* byte off. into pg */ -#define PGSHIFT ALPHA_PGSHIFT /* LOG2(NBPG) */ -#define NPTEPG (1 << (PGSHIFT-PTESHIFT)) /* pte's/page */ - -#define SEGSHIFT (PGSHIFT + (PGSHIFT-PTESHIFT)) /* LOG2(NBSEG) */ -#define NBSEG (1 << SEGSHIFT) /* bytes/segment (8M) */ -#define SEGOFSET (NBSEG-1) /* byte off. into seg */ +#define PAGE_SIZE (1 << ALPHA_PGSHIFT) /* bytes/page */ +#define PAGE_SHIFT ALPHA_PGSHIFT +#define PAGE_MASK (PAGE_SIZE-1) +#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t))) #define KERNBASE 0xfffffc0000230000 /* start of kernel virtual */ #define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT) -#define DEV_BSIZE 512 #define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ -#define BLKDEV_IOSIZE 2048 -#ifndef MAXPHYS -#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */ -#endif +#define DEV_BSIZE (1<<DEV_BSHIFT) + +#define BLKDEV_IOSIZE 2048 +#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */ +#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */ #define CLSIZE 1 #define CLSIZELOG2 0 @@ -97,11 +92,11 @@ #define SSIZE 1 /* initial stack size/NBPG */ #define SINCR 1 /* increment of stack/NBPG */ -#define UPAGES 2 /* pages of u-area */ -#define USPACE (UPAGES * NBPG) /* total size of u-area */ +#define UPAGES 2 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ #ifndef MSGBUFSIZE -#define MSGBUFSIZE NBPG /* default message buffer size */ +#define MSGBUFSIZE PAGE_SIZE /* default message buffer size */ #endif /* @@ -134,12 +129,12 @@ #endif /* pages ("clicks") to disk blocks */ -#define ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT)) -#define dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT)) +#define ctod(x) ((x) << (PAGE_SHIFT - DEV_BSHIFT)) +#define dtoc(x) ((x) >> (PAGE_SHIFT - DEV_BSHIFT)) /* pages to bytes */ -#define ctob(x) ((x) << PGSHIFT) -#define btoc(x) (((x) + PGOFSET) >> PGSHIFT) +#define ctob(x) ((x) << PAGE_SHIFT) +#define btoc(x) (((x) + PAGE_MASK) >> PAGE_SHIFT) /* bytes to disk blocks */ #define btodb(x) ((x) >> DEV_BSHIFT) @@ -156,10 +151,14 @@ /* * Mach derived conversion macros */ -#define alpha_round_page(x) ((((unsigned long)(x)) + NBPG - 1) & ~(NBPG-1)) -#define alpha_trunc_page(x) ((unsigned long)(x) & ~(NBPG-1)) -#define alpha_btop(x) ((unsigned long)(x) >> PGSHIFT) -#define alpha_ptob(x) ((unsigned long)(x) << PGSHIFT) +#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) +#define trunc_page(x) ((unsigned long)(x) & ~(PAGE_MASK)) + +#define atop(x) ((unsigned long)(x) >> PAGE_SHIFT) +#define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT) + +#define alpha_btop(x) ((unsigned long)(x) >> PAGE_SHIFT) +#define alpha_ptob(x) ((unsigned long)(x) << PAGE_SHIFT) #include <machine/intr.h> diff --git a/sys/alpha/include/pmap.h b/sys/alpha/include/pmap.h index 9f013ac..a928678 100644 --- a/sys/alpha/include/pmap.h +++ b/sys/alpha/include/pmap.h @@ -1,14 +1,10 @@ -/* $Id$ */ -/* From: NetBSD: pmap.old.h,v 1.16 1998/01/09 19:13:09 thorpej Exp */ - -/* - * Copyright (c) 1987 Carnegie-Mellon University - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. +/* + * Copyright (c) 1991 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. + * Science Department and William Jolitz of UUNET Technologies Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,103 +34,198 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)pmap.h 8.1 (Berkeley) 6/10/93 + * Derived from hp300 version by Mike Hibler, this version by William + * Jolitz uses a recursive map [a pde points to the page directory] to + * map the page tables using the pagetables themselves. This is done to + * reduce the impact on kernel virtual memory for lots of sparse address + * space, and to reduce the cost of memory to each process. + * + * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 + * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 + * from: i386 pmap.h,v 1.54 1997/11/20 19:30:35 bde Exp + * $Id$ */ -#ifndef _PMAP_MACHINE_ -#define _PMAP_MACHINE_ +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ -#include <machine/pte.h> -#include <machine/lock.h> - -extern vm_offset_t vtophys(vm_offset_t); - -#define ALPHA_PAGE_SIZE NBPG -#define ALPHA_SEG_SIZE NBSEG +/* + * Define meanings for a few software bits in the pte + */ +#define PG_V ALPHA_PTE_VALID +#define PG_FOR ALPHA_PTE_FAULT_ON_READ +#define PG_FOW ALPHA_PTE_FAULT_ON_WRITE +#define PG_FOE ALPHA_PTE_FAULT_ON_EXECUTE +#define PG_ASM ALPHA_PTE_ASM +#define PG_GH ALPHA_PTE_GRANULARITY +#define PG_KRE ALPHA_PTE_KR +#define PG_URE ALPHA_PTE_UR +#define PG_KWE ALPHA_PTE_KW +#define PG_UWE ALPHA_PTE_UW +#define PG_PROT ALPHA_PTE_PROT +#define PG_SHIFT 32 + +#define PG_W 0x00010000 /* software wired */ +#define PG_MANAGED 0x00020000 /* software managed */ -#define alpha_trunc_seg(x) (((u_long)(x)) & ~(ALPHA_SEG_SIZE-1)) -#define alpha_round_seg(x) alpha_trunc_seg((u_long)(x) + ALPHA_SEG_SIZE-1) +/* + * Pte related macros + */ +#define VADDR(l1, l2, l3) (((l1) << ALPHA_L1SHIFT) \ + + ((l2) << ALPHA_L2SHIFT) \ + + ((l3) << ALPHA_L3SHIFT) -typedef struct simplelock simple_lock_data_t; +#ifndef NKPT +#define NKPT 9 /* initial number of kernel page tables */ +#endif +#define NKLEV2MAPS 255 /* max number of lev2 page tables */ +#define NKLEV3MAPS (NKLEV2MAPS << ALPHA_PTSHIFT) /* max number of lev3 page tables */ /* - * Pmap stuff + * The *PTDI values control the layout of virtual memory + * + * XXX This works for now, but I am not real happy with it, I'll fix it + * right after I fix locore.s and the magic 28K hole + * + * SMP_PRIVPAGES: The per-cpu address space is 0xff80000 -> 0xffbfffff */ -struct pmap { - pt_entry_t *pm_ptab; /* KVA of page table */ - pt_entry_t *pm_stab; /* KVA of segment table */ - pt_entry_t pm_stpte; /* PTE mapping STE */ - short pm_sref; /* segment table ref count */ - short pm_count; /* pmap reference count */ - simple_lock_data_t pm_lock; /* lock on pmap */ - struct pmap_statistics pm_stats; /* pmap statistics */ - long pm_ptpages; /* more stats: PT pages */ -}; +#define PTLEV1I (NPTEPG-1) /* Lev0 entry that points to Lev0 */ +#define K0SEGLEV1I (NPTEPG/2) +#define K1SEGLEV1I (K0SEGLEV1I+(NPTEPG/4)) -typedef struct pmap *pmap_t; +#define NUSERLEV2MAPS (NPTEPG/2) +#define NUSERLEV3MAPS (NUSERLEV2MAPS << ALPHA_PTSHIFT) + +#ifndef LOCORE -extern struct pmap kernel_pmap_store; +#include <sys/queue.h> -#define pmap_kernel() (&kernel_pmap_store) -#define active_pmap(pm) \ - ((pm) == pmap_kernel() \ - || curproc == NULL \ - || (pm) == curproc->p_vmspace->vm_map.pmap) -#define active_user_pmap(pm) \ - (curproc && \ - (pm) != pmap_kernel() && (pm) == curproc->p_vmspace->vm_map.pmap) +typedef alpha_pt_entry_t pt_entry_t; + +#define PTESIZE sizeof(pt_entry_t) /* for assembly files */ /* - * For each vm_page_t, there is a list of all currently valid virtual - * mappings of that page. An entry is a pv_entry_t, the list is pv_table. + * Address of current address space page table maps */ -typedef struct pv_entry { - struct pv_entry *pv_next; /* next pv_entry */ - struct pmap *pv_pmap; /* pmap where mapping lies */ - vm_offset_t pv_va; /* virtual address for mapping */ - pt_entry_t *pv_ptpte; /* non-zero if VA maps a PT page */ - struct pmap *pv_ptpmap; /* if pv_ptpte, pmap for PT page */ - int pv_flags; /* flags */ -} *pv_entry_t; +#ifdef KERNEL +extern pt_entry_t PTmap[]; /* lev3 page tables */ +extern pt_entry_t PTlev2[]; /* lev2 page tables */ +extern pt_entry_t PTlev1[]; /* lev1 page table */ +extern pt_entry_t PTlev1pte; /* pte that maps lev1 page table */ +#endif -#define PV_PTPAGE 0x01 /* header: entry maps a page table page */ +#ifdef KERNEL +/* + * virtual address to page table entry and + * to physical address. + * Note: this work recursively, thus vtopte of a pte will give + * the corresponding lev1 that in turn maps it. + */ +#define vtopte(va) (PTmap + (alpha_btop(va) \ + & ((1 << 3*ALPHA_PTSHIFT)-1))) -struct pv_page_info { - TAILQ_ENTRY(pv_page) pgi_list; - struct pv_entry *pgi_freelist; - int pgi_nfree; -}; +/* + * Routine: pmap_kextract + * Function: + * Extract the physical page address associated + * kernel virtual address. + */ +static __inline vm_offset_t +pmap_kextract(vm_offset_t va) +{ + vm_offset_t pa; + if (va >= ALPHA_K0SEG_BASE && va <= ALPHA_K0SEG_END) + pa = ALPHA_K0SEG_TO_PHYS(va); + else + pa = alpha_ptob(ALPHA_PTE_TO_PFN(*vtopte(va))) + | (va & PAGE_MASK); + return pa; +} + +#define vtophys(va) pmap_kextract(((vm_offset_t) (va))) + +#endif /* KERNEL */ + +/* + * Pmap stuff + */ +struct pv_entry; +typedef struct { + int pv_list_count; + struct vm_page *pv_vm_page; + int pv_flags; + TAILQ_HEAD(,pv_entry) pv_list; +} pv_table_t; -#define NPVPPG ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry)) +#define PV_TABLE_MOD 0x01 /* modified */ +#define PV_TABLE_REF 0x02 /* referenced */ -struct pv_page { - struct pv_page_info pvp_pgi; - struct pv_entry pvp_pv[NPVPPG]; +struct pmap { + pt_entry_t *pm_lev1; /* KVA of lev0map */ + vm_object_t pm_pteobj; /* Container for pte's */ + TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */ + int pm_count; /* reference count */ + int pm_flags; /* pmap flags */ + struct pmap_statistics pm_stats; /* pmap statistics */ + struct vm_page *pm_ptphint; /* pmap ptp hint */ }; -/* - * Physical page attributes. - */ -typedef int pmap_attr_t; -#define PMAP_ATTR_MOD 0x01 /* modified */ -#define PMAP_ATTR_REF 0x02 /* referenced */ +#define pmap_resident_count(pmap) (pmap)->pm_stats.resident_count -#ifdef _KERNEL -#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) -#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) +#define PM_FLAG_LOCKED 0x1 +#define PM_FLAG_WANTED 0x2 -extern pt_entry_t *Sysmap; -extern char *vmmap; /* map for mem, dumps, etc. */ +typedef struct pmap *pmap_t; -#if defined(MACHINE_NEW_NONCONTIG) -#define PMAP_STEAL_MEMORY /* enable pmap_steal_memory() */ +#ifdef KERNEL +extern pmap_t kernel_pmap; #endif -/* Machine-specific functions. */ -void pmap_bootstrap __P((vm_offset_t firstaddr, vm_offset_t ptaddr)); -void pmap_emulate_reference __P((struct proc *p, vm_offset_t v, - int user, int write)); -void pmap_unmap_prom __P((void)); -#endif /* _KERNEL */ +/* + * For each vm_page_t, there is a list of all currently valid virtual + * mappings of that page. An entry is a pv_entry_t, the list is pv_table. + */ +typedef struct pv_entry { + pmap_t pv_pmap; /* pmap where mapping lies */ + vm_offset_t pv_va; /* virtual address for mapping */ + TAILQ_ENTRY(pv_entry) pv_list; + TAILQ_ENTRY(pv_entry) pv_plist; + vm_page_t pv_ptem; /* VM page for pte */ +} *pv_entry_t; -#endif /* _PMAP_MACHINE_ */ +#define PV_ENTRY_NULL ((pv_entry_t) 0) + +#define PV_CI 0x01 /* all entries must be cache inhibited */ +#define PV_PTPAGE 0x02 /* entry maps a page table page */ + +#ifdef KERNEL + +extern caddr_t CADDR1; +extern pt_entry_t *CMAP1; +extern vm_offset_t avail_end; +extern vm_offset_t avail_start; +extern vm_offset_t clean_eva; +extern vm_offset_t clean_sva; +extern vm_offset_t phys_avail[]; +extern char *ptvmmap; /* poor name! */ +extern vm_offset_t virtual_avail; +extern vm_offset_t virtual_end; + +vm_offset_t pmap_steal_memory __P((vm_size_t)); +void pmap_bootstrap __P((vm_offset_t, u_int)); +void pmap_setdevram __P((unsigned long long basea, vm_offset_t sizea)); +int pmap_uses_prom_console __P((void)); +pmap_t pmap_kernel __P((void)); +void *pmap_mapdev __P((vm_offset_t, vm_size_t)); +unsigned *pmap_pte __P((pmap_t, vm_offset_t)) __pure2; +vm_page_t pmap_use_pt __P((pmap_t, vm_offset_t)); +void pmap_set_opt __P((unsigned *)); +void pmap_set_opt_bsp __P((void)); +void pmap_deactivate __P((struct proc *p)); +void pmap_emulate_reference __P((struct proc *p, vm_offset_t v, int user, int write)); + +#endif /* KERNEL */ + +#endif /* !LOCORE */ + +#endif /* !_MACHINE_PMAP_H_ */ diff --git a/sys/alpha/include/proc.h b/sys/alpha/include/proc.h index 1f433c5..6cb6d1b 100644 --- a/sys/alpha/include/proc.h +++ b/sys/alpha/include/proc.h @@ -1,4 +1,4 @@ -/* $Id$ +/* $Id: proc.h,v 1.1.1.1 1998/03/09 05:43:16 jb Exp $ */ /* From: NetBSD: proc.h,v 1.3 1997/04/06 08:47:36 cgd Exp */ /* diff --git a/sys/alpha/include/prom.h b/sys/alpha/include/prom.h new file mode 100644 index 0000000..84f5f9c --- /dev/null +++ b/sys/alpha/include/prom.h @@ -0,0 +1,104 @@ +/* $NetBSD: prom.h,v 1.7 1997/04/06 08:47:37 cgd Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Keith Bostic, Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef ASSEMBLER +struct prom_vec { + u_int64_t routine; + void *routine_arg; +}; + +/* The return value from a prom call. */ +typedef union { + struct { + u_int64_t + retval : 32, /* return value. */ + unit : 8, + mbz : 8, + error : 13, + status : 3; + } u; + u_int64_t bits; +} prom_return_t; + +#ifdef STANDALONE +int getchar __P((void)); +int prom_open __P((char *, int)); +void putchar __P((int)); +#endif + +void prom_halt __P((int)) __attribute__((__noreturn__)); +int prom_getenv __P((int, char *, int)); + +#endif + +/* Prom operation values. */ +#define PROM_R_CLOSE 0x11 +#define PROM_R_GETC 0x01 +#define PROM_R_GETENV 0x22 +#define PROM_R_OPEN 0x10 +#define PROM_R_PUTS 0x02 +#define PROM_R_READ 0x13 +#define PROM_R_WRITE 0x14 + +/* Environment variable values. */ +#define PROM_E_BOOTED_DEV 0x4 +#define PROM_E_BOOTED_FILE 0x6 +#define PROM_E_BOOTED_OSFLAGS 0x8 +#define PROM_E_TTY_DEV 0xf + +/* + * There have to be stub routines to do the copying that ensures that the + * PROM doesn't get called with an address larger than 32 bits. Calls that + * either don't need to copy anything, or don't need the copy because it's + * already being done elsewhere, are defined here. + */ +#define prom_close(chan) \ + prom_dispatch(PROM_R_CLOSE, chan, 0, 0, 0) +#define prom_read(chan, len, buf, blkno) \ + prom_dispatch(PROM_R_READ, chan, len, (u_int64_t)buf, blkno) +#define prom_write(chan, len, buf, blkno) \ + prom_dispatch(PROM_R_WRITE, chan, len, (u_int64_t)buf, blkno) +#define prom_putstr(chan, str, len) \ + prom_dispatch(PROM_R_PUTS, chan, (u_int64_t)str, len, 0) +#define prom_getc(chan) \ + prom_dispatch(PROM_R_GETC, chan, 0, 0, 0) +#define prom_getenv_disp(id, buf, len) \ + prom_dispatch(PROM_R_GETENV, id, (u_int64_t)buf, len, 0) + +#ifndef ASSEMBLER +#ifdef KERNEL +void promcnputc __P((dev_t, int)); +int promcngetc __P((dev_t)); +int promcnlookc __P((dev_t, char *)); + +u_int64_t prom_dispatch __P((u_int64_t, u_int64_t, u_int64_t, u_int64_t, + u_int64_t)); +void init_bootstrap_console __P((void)); +#endif /* _KERNEL */ +#endif /* ASSEMBLER */ diff --git a/sys/alpha/include/psl.h b/sys/alpha/include/psl.h new file mode 100644 index 0000000..b54c48e --- /dev/null +++ b/sys/alpha/include/psl.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +/* + * XXX don't need this. + */ + diff --git a/sys/alpha/include/pte.h b/sys/alpha/include/pte.h index da211ca..4981272 100644 --- a/sys/alpha/include/pte.h +++ b/sys/alpha/include/pte.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: pte.h,v 1.1.1.1 1998/03/09 05:43:16 jb Exp $ */ /* From: NetBSD: pte.h,v 1.10 1997/09/02 19:07:22 thorpej Exp */ /* @@ -91,7 +91,7 @@ typedef alpha_pt_entry_t pt_entry_t; #define vatopa(va) \ ((PG_PFNUM(*kvtopte(va)) << PGSHIFT) | ((vm_offset_t)(va) & PGOFSET)) -#define ALPHA_STSIZE ((u_long)NBPG) /* 8k */ +#define ALPHA_STSIZE ((u_long)PAGE_SIZE) /* 8k */ #define ALPHA_MAX_PTSIZE ((u_long)(NPTEPG * NBPG)) /* 8M */ #ifdef _KERNEL diff --git a/sys/alpha/include/ptrace.h b/sys/alpha/include/ptrace.h new file mode 100644 index 0000000..2b4a9cb --- /dev/null +++ b/sys/alpha/include/ptrace.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + * + * @(#)ptrace.h 8.1 (Berkeley) 6/11/93 + * $Id: ptrace.h,v 1.6 1998/05/19 00:00:12 tegge Exp $ + */ + +#ifndef _MACHINE_PTRACE_H_ +#define _MACHINE_PTRACE_H_ + +/* + * Machine dependent trace commands. + */ +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) + +#ifdef KERNEL +int ptrace_read_u_check __P((struct proc *p, vm_offset_t off, size_t len)); +#endif /* !KERNEL */ + +#endif + diff --git a/sys/alpha/include/reg.h b/sys/alpha/include/reg.h index d2d5ab9..3bbc69f 100644 --- a/sys/alpha/include/reg.h +++ b/sys/alpha/include/reg.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: reg.h,v 1.1.1.1 1998/03/09 05:43:16 jb Exp $ */ /* From: NetBSD: reg.h,v 1.3 1997/04/06 08:47:40 cgd Exp */ /* @@ -91,9 +91,10 @@ struct fpreg { u_int64_t fpr_cr; }; -#ifdef _KERNEL +#ifdef KERNEL void restorefpstate __P((struct fpreg *)); void savefpstate __P((struct fpreg *)); +void setregs __P((struct proc *, u_long, u_long)); #endif #endif /* _ALPHA_REG_H_ */ diff --git a/sys/alpha/include/rpb.h b/sys/alpha/include/rpb.h new file mode 100644 index 0000000..164127f --- /dev/null +++ b/sys/alpha/include/rpb.h @@ -0,0 +1,393 @@ +/* $NetBSD: rpb.h,v 1.20 1998/04/15 00:47:33 mjacob Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Keith Bostic, Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * From DEC 3000 300/400/500/600/700/800/900 System Programmer's Manual, + * EK-D3SYS-PM.B01. + */ + +/* + * HWRPB (Hardware Restart Parameter Block). + */ +#define HWRPB_ADDR 0x10000000 /* virtual address, at boot */ + +#ifndef ASSEMBLER +struct rpb { + u_int64_t rpb_phys; /* 0: HWRPB phys. address. */ + char rpb_magic[8]; /* 8: "HWRPB" (in ASCII) */ + u_int64_t rpb_version; /* 10 */ + u_int64_t rpb_size; /* 18: HWRPB size in bytes */ + u_int64_t rpb_primary_cpu_id; /* 20 */ + u_int64_t rpb_page_size; /* 28: (8192) */ + u_int64_t rpb_phys_addr_size; /* 30: (34) */ + u_int64_t rpb_max_asn; /* 38: (16) */ + char rpb_ssn[16]; /* 40: only first 10 valid */ + +#define ST_ADU 1 /* Alpha Demo. Unit (?) */ +#define ST_DEC_4000 2 /* "Cobra" (?) */ +#define ST_DEC_7000 3 /* "Ruby" (?) */ +#define ST_DEC_3000_500 4 /* "Flamingo" family (TC) */ +#define ST_DEC_2000_300 6 /* "Jensen" (EISA/ISA) */ +#define ST_DEC_3000_300 7 /* "Pelican" (TC) */ +#define ST_AVALON_A12 8 /* XXX Avalon Multicomputer */ +#define ST_DEC_2100_A500 9 /* "Sable" (?) */ +#define ST_DEC_APXVME_64 10 /* "AXPvme" (VME?) */ +#define ST_DEC_AXPPCI_33 11 /* "NoName" (PCI/ISA) */ +#define ST_DEC_21000 12 /* "TurboLaser" (PCI/EISA) */ +#define ST_DEC_2100_A50 13 /* "Avanti" (PCI/ISA) */ +#define ST_DEC_MUSTANG 14 /* "Mustang" (?) */ +#define ST_DEC_KN20AA 15 /* kn20aa (PCI/EISA) */ +#define ST_DEC_1000 17 /* "Mikasa" (PCI/ISA?) */ +#define ST_EB66 19 /* EB66 (PCI/ISA?) */ +#define ST_EB64P 20 /* EB64+ (PCI/ISA?) */ +#define ST_ALPHABOOK1 21 /* Alphabook (?) */ +#define ST_DEC_4100 22 /* "Rawhide" (PCI/EISA) */ +#define ST_DEC_EV45_PBP 23 /* "Lego" (?) */ +#define ST_DEC_2100A_A500 24 /* "Lynx" (?) */ +#define ST_EB164 26 /* EB164 (PCI/ISA) */ +#define ST_DEC_1000A 27 /* "Noritake" (?) */ +#define ST_DEC_ALPHAVME_224 28 /* "Cortex" (?) */ +#define ST_DEC_EV56_PBP 32 /* "Takara" (?) */ +#define ST_DEC_ALPHAVME_320 33 /* "Yukon" (VME?) */ + + u_int64_t rpb_type; /* 50: */ + +#define SV_MPCAP 0x00000001 /* multiprocessor capable */ + +#define SV_CONSOLE 0x0000001e /* console hardware mask */ +#define SV_CONSOLE_DETACHED 0x00000002 +#define SV_CONSOLE_EMBEDDED 0x00000004 + +#define SV_POWERFAIL 0x000000e0 /* powerfail mask */ +#define SV_PF_UNITED 0x00000020 +#define SV_PF_SEPARATE 0x00000040 +#define SV_PF_BBACKUP 0x00000060 +#define SV_PF_ACTION 0x00000100 /* powerfail restart */ + +#define SV_GRAPHICS 0x00000200 /* graphic engine present */ + +#define SV_ST_MASK 0x0000fc00 /* system type mask */ +#define SV_ST_RESERVED 0x00000000 /* RESERVED */ + +/* + * System types for the DEC 3000/500 (Flamingo) Family + */ +#define SV_ST_SANDPIPER 0x00000400 /* Sandpiper; 3000/400 */ +#define SV_ST_FLAMINGO 0x00000800 /* Flamingo; 3000/500 */ +#define SV_ST_HOTPINK 0x00000c00 /* "Hot Pink"; 3000/500X */ +#define SV_ST_FLAMINGOPLUS 0x00001000 /* Flamingo+; 3000/800 */ +#define SV_ST_ULTRA 0x00001400 /* "Ultra", aka Flamingo+ */ +#define SV_ST_SANDPLUS 0x00001800 /* Sandpiper+; 3000/600 */ +#define SV_ST_SANDPIPER45 0x00001c00 /* Sandpiper45; 3000/700 */ +#define SV_ST_FLAMINGO45 0x00002000 /* Flamingo45; 3000/900 */ + +/* + * System types for ??? + */ +#define SV_ST_SABLE 0x00000400 /* Sable (???) */ + +/* + * System types for the DEC 3000/300 (Pelican) Family + */ +#define SV_ST_PELICAN 0x00000000 /* Pelican; 3000/300 */ +#define SV_ST_PELICA 0x00000400 /* Pelica; 3000/300L */ +#define SV_ST_PELICANPLUS 0x00000800 /* Pelican+; 3000/300X */ +#define SV_ST_PELICAPLUS 0x00000c00 /* Pelica+; 3000/300LX */ + +/* + * System types for the AlphaStation Family + */ +#define SV_ST_AVANTI 0x00000000 /* Avanti; 400 4/233 */ +#define SV_ST_MUSTANG2_4_166 0x00000800 /* Mustang II; 200 4/166 */ +#define SV_ST_MUSTANG2_4_233 0x00001000 /* Mustang II; 200 4/233 */ +#define SV_ST_AVANTI_XXX 0x00001400 /* also Avanti; 400 4/233 */ +#define SV_ST_AVANTI_4_266 0x00002000 +#define SV_ST_MUSTANG2_4_100 0x00002400 /* Mustang II; 200 4/100 */ +#define SV_ST_AVANTI_4_233 0x0000a800 /* AlphaStation 255/233 */ + + u_int64_t rpb_variation; /* 58 */ + + char rpb_revision[8]; /* 60; only first 4 valid */ + u_int64_t rpb_intr_freq; /* 68; scaled by 4096 */ + u_int64_t rpb_cc_freq; /* 70: cycle cntr frequency */ + vm_offset_t rpb_vptb; /* 78: */ + u_int64_t rpb_reserved_arch; /* 80: */ + vm_offset_t rpb_tbhint_off; /* 88: */ + u_int64_t rpb_pcs_cnt; /* 90: */ + u_int64_t rpb_pcs_size; /* 98; pcs size in bytes */ + vm_offset_t rpb_pcs_off; /* A0: offset to pcs info */ + u_int64_t rpb_ctb_cnt; /* A8: console terminal */ + u_int64_t rpb_ctb_size; /* B0: ctb size in bytes */ + vm_offset_t rpb_ctb_off; /* B8: offset to ctb */ + vm_offset_t rpb_crb_off; /* C0: offset to crb */ + vm_offset_t rpb_memdat_off; /* C8: memory data offset */ + vm_offset_t rpb_condat_off; /* D0: config data offset */ + vm_offset_t rpb_fru_off; /* D8: FRU table offset */ + u_int64_t rpb_save_term; /* E0: terminal save */ + u_int64_t rpb_save_term_val; /* E8: */ + u_int64_t rpb_rest_term; /* F0: terminal restore */ + u_int64_t rpb_rest_term_val; /* F8: */ + u_int64_t rpb_restart; /* 100: restart */ + u_int64_t rpb_restart_val; /* 108: */ + u_int64_t rpb_reserve_os; /* 110: */ + u_int64_t rpb_reserve_hw; /* 118: */ + u_int64_t rpb_checksum; /* 120: HWRPB checksum */ + u_int64_t rpb_rxrdy; /* 128: receive ready */ + u_int64_t rpb_txrdy; /* 130: transmit ready */ + vm_offset_t rpb_dsrdb_off; /* 138: HWRPB + DSRDB offset */ + u_int64_t rpb_tbhint[8]; /* 149: TB hint block */ +}; + +/* + * PCS: Per-CPU information. + */ +struct pcs { + u_int8_t pcs_hwpcb[128]; /* 0: PAL dependent */ + +#define PCS_BIP 0x000001 /* boot in progress */ +#define PCS_RC 0x000002 /* restart possible */ +#define PCS_PA 0x000004 /* processor available */ +#define PCS_PP 0x000008 /* processor present */ +#define PCS_OH 0x000010 /* user halted */ +#define PCS_CV 0x000020 /* context valid */ +#define PCS_PV 0x000040 /* PALcode valid */ +#define PCS_PMV 0x000080 /* PALcode memory valid */ +#define PCS_PL 0x000100 /* PALcode loaded */ + +#define PCS_HALT_REQ 0xff0000 /* halt request mask */ +#define PCS_HALT_DEFAULT 0x000000 +#define PCS_HALT_SAVE_EXIT 0x010000 +#define PCS_HALT_COLD_BOOT 0x020000 +#define PCS_HALT_WARM_BOOT 0x030000 +#define PCS_HALT_STAY_HALTED 0x040000 +#define PCS_mbz 0xffffffffff000000 /* 24:63 -- must be zero */ + u_int64_t pcs_flags; /* 80: */ + + u_int64_t pcs_pal_memsize; /* 88: PAL memory size */ + u_int64_t pcs_pal_scrsize; /* 90: PAL scratch size */ + vm_offset_t pcs_pal_memaddr; /* 98: PAL memory addr */ + vm_offset_t pcs_pal_scraddr; /* A0: PAL scratch addr */ + struct { + u_int64_t + minorrev : 8, /* alphabetic char 'a' - 'z' */ + majorrev : 8, /* alphabetic char 'a' - 'z' */ +#define PAL_TYPE_STANDARD 0 +#define PAL_TYPE_VMS 1 +#define PAL_TYPE_OSF1 2 + pal_type : 8, /* PALcode type: + * 0 == standard + * 1 == OpenVMS + * 2 == OSF/1 + * 3-127 DIGITAL reserv. + * 128-255 non-DIGITAL reserv. + */ + sbz1 : 8, + compatibility : 16, /* Compatibility revision */ + proc_cnt : 16; /* Processor count */ + } pcs_pal_rev; /* A8: */ +#define pcs_minorrev pcs_pal_rev.minorrev +#define pcs_majorrev pcs_pal_rev.majorrev +#define pcs_pal_type pcs_pal_rev.pal_type +#define pcs_compatibility pcs_pal_rev.compatibility +#define pcs_proc_cnt pcs_pal_rev.proc_cnt + + u_int64_t pcs_proc_type; /* B0: processor type */ + +#define PCS_PROC_MAJOR 0x00000000ffffffff +#define PCS_PROC_MAJORSHIFT 0 + +#define PCS_PROC_EV3 1 /* EV3 */ +#define PCS_PROC_EV4 2 /* EV4: 21064 */ +#define PCS_PROC_SIMULATION 3 /* Simulation */ +#define PCS_PROC_LCA4 4 /* LCA4: 2106[68] */ +#define PCS_PROC_EV5 5 /* EV5: 21164 */ +#define PCS_PROC_EV45 6 /* EV45: 21064A */ +#define PCS_PROC_EV56 7 /* EV56: 21164A */ +#define PCS_PROC_EV6 8 /* EV6: 21264 */ +#define PCS_PROC_PCA56 9 /* PCA256: 21164PC */ + +#define PCS_PROC_MINOR 0xffffffff00000000 +#define PCS_PROC_MINORSHIFT 32 + + /* Minor number interpretation is processor specific. See cpu.c. */ + + u_int64_t pcs_proc_var; /* B8: processor variation. */ + +#define PCS_VAR_VAXFP 0x0000000000000001 /* VAX FP support */ +#define PCS_VAR_IEEEFP 0x0000000000000002 /* IEEE FP support */ +#define PCS_VAR_PE 0x0000000000000004 /* Primary Eligible */ +#define PCS_VAR_RESERVED 0xfffffffffffffff8 /* Reserved */ + + char pcs_proc_revision[8]; /* C0: only first 4 valid */ + char pcs_proc_sn[16]; /* C8: only first 10 valid */ + vm_offset_t pcs_machcheck; /* D8: mach chk phys addr. */ + u_int64_t pcs_machcheck_len; /* E0: length in bytes */ + vm_offset_t pcs_halt_pcbb; /* E8: phys addr of halt PCB */ + vm_offset_t pcs_halt_pc; /* F0: halt PC */ + u_int64_t pcs_halt_ps; /* F8: halt PS */ + u_int64_t pcs_halt_r25; /* 100: halt argument list */ + u_int64_t pcs_halt_r26; /* 108: halt return addr list */ + u_int64_t pcs_halt_r27; /* 110: halt procedure value */ + +#define PCS_HALT_RESERVED 0 +#define PCS_HALT_POWERUP 1 +#define PCS_HALT_CONSOLE_HALT 2 +#define PCS_HALT_CONSOLE_CRASH 3 +#define PCS_HALT_KERNEL_MODE 4 +#define PCS_HALT_KERNEL_STACK_INVALID 5 +#define PCS_HALT_DOUBLE_ERROR_ABORT 6 +#define PCS_HALT_SCBB 7 +#define PCS_HALT_PTBR 8 /* 9-FF: reserved */ + u_int64_t pcs_halt_reason; /* 118: */ + + u_int64_t pcs_reserved_soft; /* 120: preserved software */ + u_int64_t pcs_buffer[21]; /* 128: console buffers */ + +#define PALvar_reserved 0 +#define PALvar_OpenVMS 1 +#define PALvar_OSF1 2 + u_int64_t pcs_palrevisions[16]; /* 1D0: PALcode revisions */ + + u_int64_t pcs_reserved_arch[6]; /* 250: reserved arch */ +}; + +/* + * CTB: Console Terminal Block + */ +struct ctb { + u_int64_t ctb_type; /* 0: always 4 */ + u_int64_t ctb_unit; /* 8: */ + u_int64_t ctb_reserved; /* 16: */ + u_int64_t ctb_len; /* 24: bytes of info */ + u_int64_t ctb_ipl; /* 32: console ipl level */ + vm_offset_t ctb_tintr_vec; /* 40: transmit vec (0x800) */ + vm_offset_t ctb_rintr_vec; /* 48: receive vec (0x800) */ + +#define CTB_GRAPHICS 3 /* graphics device */ +#define CTB_NETWORK 0xC0 /* network device */ +#define CTB_PRINTERPORT 2 /* printer port on the SCC */ + u_int64_t ctb_term_type; /* 56: terminal type */ + + u_int64_t ctb_keybd_type; /* 64: keyboard nationality */ + vm_offset_t ctb_keybd_trans; /* 72: trans. table addr */ + vm_offset_t ctb_keybd_map; /* 80: map table addr */ + u_int64_t ctb_keybd_state; /* 88: keyboard flags */ + u_int64_t ctb_keybd_last; /* 96: last key entered */ + vm_offset_t ctb_font_us; /* 104: US font table addr */ + vm_offset_t ctb_font_mcs; /* 112: MCS font table addr */ + u_int64_t ctb_font_width; /* 120: font width, height */ + u_int64_t ctb_font_height; /* 128: in pixels */ + u_int64_t ctb_mon_width; /* 136: monitor width, height */ + u_int64_t ctb_mon_height; /* 144: in pixels */ + u_int64_t ctb_dpi; /* 152: monitor dots per inch */ + u_int64_t ctb_planes; /* 160: # of planes */ + u_int64_t ctb_cur_width; /* 168: cursor width, height */ + u_int64_t ctb_cur_height; /* 176: in pixels */ + u_int64_t ctb_head_cnt; /* 184: # of heads */ + u_int64_t ctb_opwindow; /* 192: opwindow on screen */ + vm_offset_t ctb_head_offset; /* 200: offset to head info */ + vm_offset_t ctb_putchar; /* 208: output char to TURBO */ + u_int64_t ctb_io_state; /* 216: I/O flags */ + u_int64_t ctb_listen_state; /* 224: listener flags */ + vm_offset_t ctb_xaddr; /* 232: extended info addr */ + u_int64_t ctb_turboslot; /* 248: TURBOchannel slot # */ + u_int64_t ctb_server_off; /* 256: offset to server info */ + u_int64_t ctb_line_off; /* 264: line parameter offset */ + u_int8_t ctb_csd; /* 272: console specific data */ +}; + +/* + * CRD: Console Routine Descriptor + */ +struct crd { + int64_t descriptor; + u_int64_t entry_va; +}; + +/* + * CRB: Console Routine Block + */ +struct crb { + struct crd *crb_v_dispatch; /* 0: virtual dispatch addr */ + vm_offset_t crb_p_dispatch; /* 8: phys dispatch addr */ + struct crd *crb_v_fixup; /* 10: virtual fixup addr */ + vm_offset_t crb_p_fixup; /* 18: phys fixup addr */ + u_int64_t crb_map_cnt; /* 20: phys/virt map entries */ + u_int64_t crb_page_cnt; /* 28: pages to be mapped */ +}; + +/* + * MDDT: Memory Data Descriptor Table + */ +struct mddt { + int64_t mddt_cksum; /* 0: 7-N checksum */ + vm_offset_t mddt_physaddr; /* 8: bank config addr + * IMPLEMENTATION SPECIFIC + */ + u_int64_t mddt_cluster_cnt; /* 10: memory cluster count */ + struct mddt_cluster { + vm_offset_t mddt_pfn; /* 0: starting PFN */ + u_int64_t mddt_pg_cnt; /* 8: 8KB page count */ + u_int64_t mddt_pg_test; /* 10: tested page count */ + vm_offset_t mddt_v_bitaddr; /* 18: bitmap virt addr */ + vm_offset_t mddt_p_bitaddr; /* 20: bitmap phys addr */ + int64_t mddt_bit_cksum; /* 28: bitmap checksum */ + +#define MDDT_NONVOLATILE 0x10 /* cluster is non-volatile */ +#define MDDT_PALCODE 0x01 /* console and PAL only */ +#define MDDT_SYSTEM 0x00 /* system software only */ +#define MDDT_mbz 0xfffffffffffffffc /* 2:63 -- must be zero */ + int64_t mddt_usage; /* 30: bitmap permissions */ + } mddt_clusters[1]; /* variable length array */ +}; + +/* + * DSR: Dynamic System Recognition. We're interested in the sysname + * offset. The data pointed to by sysname is: + * + * [8 bytes: length of system name][N bytes: system name string] + * + * The system name string is NUL-terminated. + */ +struct dsrdb { + int64_t dsr_smm; /* 0: SMM number */ + u_int64_t dsr_lurt_off; /* 8: LURT table offset */ + u_int64_t dsr_sysname_off; /* 16: offset to sysname */ +}; + +/* + * The DSR appeared in version 5 of the HWRPB. + */ +#define HWRPB_DSRDB_MINVERS 5 + +#ifdef _KERNEL +int cputype; +#endif + +#endif /* ASSEMBLER */ diff --git a/sys/alpha/include/vmparam.h b/sys/alpha/include/vmparam.h index bc543fd..612fe8e 100644 --- a/sys/alpha/include/vmparam.h +++ b/sys/alpha/include/vmparam.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: vmparam.h,v 1.1.1.1 1998/03/09 05:43:16 jb Exp $ */ /* From: NetBSD: vmparam.h,v 1.6 1997/09/23 23:23:23 mjacob Exp */ #ifndef _ALPHA_VMPARAM_H #define _ALPHA_VMPARAM_H @@ -74,6 +74,9 @@ #ifndef MAXSSIZ #define MAXSSIZ (1<<25) /* max stack size (32M) */ #endif +#ifndef SGROWSIZ +#define SGROWSIZ (128UL*1024) /* amount to grow stack */ +#endif /* * PTEs for mapping user space into the kernel for phyio operations. @@ -131,23 +134,30 @@ /* user/kernel map constants */ #define VM_MIN_ADDRESS ((vm_offset_t)ALPHA_USEG_BASE) /* 0 */ -#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x0000000200000000) /* 8G XXX */ +#define VM_MAXUSER_ADDRESS ((vm_offset_t)(ALPHA_USEG_END + 1L)) #define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS #define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)ALPHA_K1SEG_BASE) #define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)ALPHA_K1SEG_END) /* virtual sizes (bytes) for various kernel submaps */ -#ifndef _KERNEL -#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES) -#define VM_KMEM_SIZE (NKMEMCLUSTERS*CLBYTES) -#define VM_PHYS_SIZE (USRIOSIZE*CLBYTES) -#else -extern u_int32_t vm_mbuf_size, vm_kmem_size, vm_phys_size; -#define VM_MBUF_SIZE vm_mbuf_size -#define VM_KMEM_SIZE vm_kmem_size -#define VM_PHYS_SIZE vm_phys_size +#ifndef VM_KMEM_SIZE +#define VM_KMEM_SIZE (12 * 1024 * 1024) +#endif + +/* + * How many physical pages per KVA page allocated. + * min(max(VM_KMEM_SIZE, Physical memory/VM_KMEM_SIZE_SCALE), VM_KMEM_SIZE_MAX) + * is the total KVA space allocated for kmem_map. + */ +#ifndef VM_KMEM_SIZE_SCALE +#define VM_KMEM_SIZE_SCALE (4) /* XXX 8192 byte pages */ +#endif + +/* initial pagein size of beginning of executable file */ +#ifndef VM_INITIAL_PAGEIN +#define VM_INITIAL_PAGEIN 16 #endif /* some Alpha-specific constants */ -#define VPTBASE ((vm_offset_t)0xfffffffc00000000) /* Virt. pg table */ +#define VPTBASE ((vm_offset_t)0xfffffffe00000000) /* Virt. pg table */ #endif /* !_ALPHA_VMPARAM_H */ diff --git a/sys/alpha/pci/pcibus.c b/sys/alpha/pci/pcibus.c new file mode 100644 index 0000000..6e488a8 --- /dev/null +++ b/sys/alpha/pci/pcibus.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1997, Stefan Esser <se@freebsd.org> + * All rights reserved. + * + * 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 unmodified, 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. + * + * $Id: pcibus.c,v 1.41 1997/12/20 09:04:25 se Exp $ + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus_private.h> + +#include <pci/pcivar.h> +#include <machine/chipset.h> + +static int cfgmech; +static int devmax; + +#ifdef notyet + +/* return max number of devices on the bus */ +int +pci_maxdevs(pcicfgregs *cfg) +{ + return chipset.maxdevs(cfg->bus); +} + +#endif + +/* read configuration space register */ + +int +pci_cfgread(pcicfgregs *cfg, int reg, int bytes) +{ + switch (bytes) { + case 1: + return chipset.cfgreadb(cfg->bus, cfg->slot, cfg->func, reg); + case 2: + return chipset.cfgreadw(cfg->bus, cfg->slot, cfg->func, reg); + case 4: + return chipset.cfgreadl(cfg->bus, cfg->slot, cfg->func, reg); + } + return ~0; +} + + +/* write configuration space register */ + +void +pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes) +{ + switch (bytes) { + case 1: + return chipset.cfgwriteb(cfg->bus, cfg->slot, cfg->func, reg, data); + case 2: + return chipset.cfgwritew(cfg->bus, cfg->slot, cfg->func, reg, data); + case 4: + return chipset.cfgwritel(cfg->bus, cfg->slot, cfg->func, reg, data); + } +} + +int +pci_cfgopen(void) +{ + return 1; +} diff --git a/sys/alpha/pci/pcibus.h b/sys/alpha/pci/pcibus.h new file mode 100644 index 0000000..eb56cec --- /dev/null +++ b/sys/alpha/pci/pcibus.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +typedef int alpha_pci_maxdevs_t(pcicfgregs*); +typedef int alpha_pci_cfgread_t(pcicfgregs*, int, int); +typedef void alpha_pci_cfgwrite_t(pcicfgregs*, int, int, int); + +struct alpha_pci_ops { + alpha_pci_maxdevs_t* maxdevs; + alpha_pci_cfgread_t* cfgread; + alpha_pci_cfgwrite_t* cfgwrite; +}; + +struct alpha_pci_softc { + struct alpha_pci_ops* ops; +}; diff --git a/sys/alpha/tlsb/dwlpx.c b/sys/alpha/tlsb/dwlpx.c new file mode 100644 index 0000000..e9f2aa5 --- /dev/null +++ b/sys/alpha/tlsb/dwlpx.c @@ -0,0 +1,291 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#include "opt_simos.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> + +#include <alpha/tlsb/dwlpxreg.h> + +#include <alpha/tlsb/tlsbreg.h> +#include <alpha/tlsb/tlsbvar.h> + +#include <alpha/tlsb/kftxxvar.h> + +#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa) +#define DWLPX_BASE(n, h) ((((u_long)(n) - 4) << 36) \ + | ((u_long)(h) << 34) \ + | (1L << 39)) + +static devclass_t dwlpx_devclass; +static device_t dwlpx0; /* XXX only one for now */ + +struct dwlpx_softc { + vm_offset_t dmem_base; /* dense memory */ + vm_offset_t smem_base; /* sparse memory */ + vm_offset_t io_base; /* sparse i/o */ + vm_offset_t cfg_base; /* sparse pci config */ +}; + +#define DWLPX_SOFTC(dev) (struct dwlpx_softc*) device_get_softc(dev) + +#define SPARSE_READ(o) (*(u_int32_t*) (o)) +#define SPARSE_WRITE(o, d) (*(u_int32_t*) (o) = (d)) + +#define SPARSE_BYTE_OFFSET(o) (((o) << 5) | ((o) & 3)) +#define SPARSE_WORD_OFFSET(o) (((o) << 5) | ((o) & 2) | 0x8) +#define SPARSE_LONG_OFFSET(o) (((o) << 5) | 0x18) + +#define SPARSE_BYTE_EXTRACT(o, d) ((d) >> (8*((o) & 3))) +#define SPARSE_WORD_EXTRACT(o, d) ((d) >> (8*((o) & 2))) + +#define SPARSE_BYTE_INSERT(o, d) ((d) << (8*((o) & 3))) +#define SPARSE_WORD_INSERT(o, d) ((d) << (8*((o) & 2))) + +#define SPARSE_READ_BYTE(base, o) \ + SPARSE_BYTE_EXTRACT(o, SPARSE_READ(base + SPARSE_BYTE_OFFSET(o))) + +#define SPARSE_READ_WORD(base, o) \ + SPARSE_WORD_EXTRACT(o, SPARSE_READ(base + SPARSE_WORD_OFFSET(o))) + +#define SPARSE_READ_LONG(base, o) \ + SPARSE_READ(base + SPARSE_LONG_OFFSET(o)) + +#define SPARSE_WRITE_BYTE(base, o, d) \ + SPARSE_WRITE(base + SPARSE_BYTE_OFFSET(o), SPARSE_BYTE_INSERT(o, d)) + +#define SPARSE_WRITE_WORD(base, o, d) \ + SPARSE_WRITE(base + SPARSE_WORD_OFFSET(o), SPARSE_WORD_INSERT(o, d)) + +#define SPARSE_WRITE_LONG(base, o, d) \ + SPARSE_WRITE(base + SPARSE_LONG_OFFSET(o), d) + +static alpha_chipset_inb_t dwlpx_inb; +static alpha_chipset_inw_t dwlpx_inw; +static alpha_chipset_inl_t dwlpx_inl; +static alpha_chipset_outb_t dwlpx_outb; +static alpha_chipset_outw_t dwlpx_outw; +static alpha_chipset_outl_t dwlpx_outl; +static alpha_chipset_maxdevs_t dwlpx_maxdevs; +static alpha_chipset_cfgreadb_t dwlpx_cfgreadb; +static alpha_chipset_cfgreadw_t dwlpx_cfgreadw; +static alpha_chipset_cfgreadl_t dwlpx_cfgreadl; +static alpha_chipset_cfgwriteb_t dwlpx_cfgwriteb; +static alpha_chipset_cfgwritew_t dwlpx_cfgwritew; +static alpha_chipset_cfgwritel_t dwlpx_cfgwritel; + +static alpha_chipset_t dwlpx_chipset = { + dwlpx_inb, + dwlpx_inw, + dwlpx_inl, + dwlpx_outb, + dwlpx_outw, + dwlpx_outl, + dwlpx_maxdevs, + dwlpx_cfgreadb, + dwlpx_cfgreadw, + dwlpx_cfgreadl, + dwlpx_cfgwriteb, + dwlpx_cfgwritew, + dwlpx_cfgwritel, +}; + +/* + * For supporting multiple busses, we will encode the dwlpx unit number into + * the port address as Linux does. + */ + +static u_int8_t +dwlpx_inb(u_int32_t port) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + return SPARSE_READ_BYTE(sc->io_base, port); +} + +static u_int16_t +dwlpx_inw(u_int32_t port) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + return SPARSE_READ_WORD(sc->io_base, port); +} + +static u_int32_t +dwlpx_inl(u_int32_t port) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + return SPARSE_READ_LONG(sc->io_base, port); +} + +static void +dwlpx_outb(u_int32_t port, u_int8_t data) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + SPARSE_WRITE_BYTE(sc->io_base, port, data); +} + +static void +dwlpx_outw(u_int32_t port, u_int16_t data) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + SPARSE_WRITE_WORD(sc->io_base, port, data); +} + +static void +dwlpx_outl(u_int32_t port, u_int32_t data) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + SPARSE_WRITE_LONG(sc->io_base, port, data); +} + +static int +dwlpx_maxdevs(u_int b) +{ + return 12; /* XXX */ +} + +/* XXX only support bus 0 */ + +#define DWLPX_CFGOFF(b, s, f, r) \ + (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) + +static u_int8_t +dwlpx_cfgreadb(u_int b, u_int s, u_int f, u_int r) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + vm_offset_t off = DWLPX_CFGOFF(b, s, f, r); + if (badaddr((caddr_t)(sc->cfg_base + off), 1)) return ~0; + return SPARSE_READ_BYTE(sc->cfg_base, off); +} + +static u_int16_t +dwlpx_cfgreadw(u_int b, u_int s, u_int f, u_int r) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + vm_offset_t off = DWLPX_CFGOFF(b, s, f, r); + if (badaddr((caddr_t)(sc->cfg_base + off), 2)) return ~0; + return SPARSE_READ_WORD(sc->cfg_base, off); +} + +static u_int32_t +dwlpx_cfgreadl(u_int b, u_int s, u_int f, u_int r) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + vm_offset_t off = DWLPX_CFGOFF(b, s, f, r); + if (badaddr((caddr_t)(sc->cfg_base + off), 4)) return ~0; + return SPARSE_READ_LONG(sc->cfg_base, off); +} + +static void +dwlpx_cfgwriteb(u_int b, u_int s, u_int f, u_int r, u_int8_t data) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + vm_offset_t off = DWLPX_CFGOFF(b, s, f, r); + if (badaddr((caddr_t)(sc->cfg_base + off), 1)) return; + SPARSE_WRITE_BYTE(sc->cfg_base, off, data); +} + +static void +dwlpx_cfgwritew(u_int b, u_int s, u_int f, u_int r, u_int16_t data) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + vm_offset_t off = DWLPX_CFGOFF(b, s, f, r); + if (badaddr((caddr_t)(sc->cfg_base + off), 2)) return; + SPARSE_WRITE_WORD(sc->cfg_base, off, data); +} + +static void +dwlpx_cfgwritel(u_int b, u_int s, u_int f, u_int r, u_int32_t data) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dwlpx0); + vm_offset_t off = DWLPX_CFGOFF(b, s, f, r); + if (badaddr((caddr_t)(sc->cfg_base + off), 4)) return; + SPARSE_WRITE_LONG(sc->cfg_base, off, data); +} + +static driver_probe_t dwlpx_probe; +static driver_attach_t dwlpx_attach; +static driver_intr_t dwlpx_intr; + +static driver_t dwlpx_driver = { + "dwlpx", + dwlpx_probe, + dwlpx_attach, + NULL, + NULL, + DRIVER_TYPE_MISC, + sizeof(struct dwlpx_softc), + NULL, +}; + + +static int +dwlpx_probe(bus_t bus, device_t dev) +{ + if (dwlpx0) + return ENXIO; + device_set_desc(dev, "DWLPA or DWLPB PCI adapter"); + return 0; +} + +static int +dwlpx_attach(bus_t bus, device_t dev) +{ + struct dwlpx_softc* sc = DWLPX_SOFTC(dev); + vm_offset_t regs; + dwlpx0 = dev; + + chipset = dwlpx_chipset; + + regs = KV(DWLPX_BASE(kft_get_node(dev), kft_get_hosenum(dev))); + sc->dmem_base = regs + (0L << 32); + sc->smem_base = regs + (1L << 32); + sc->io_base = regs + (2L << 32); + sc->cfg_base = regs + (3L << 32); + + *(u_int32_t*) (regs + PCIA_CTL(0)) = 1; /* Type1 config cycles */ + + bus_map_intr(bus, dev, dwlpx_intr, 0); + + return 0; +} + +static void +dwlpx_intr(void* arg) +{ +#ifdef SIMOS + extern void simos_intr(int); + simos_intr(0); +#endif +} + +DRIVER_MODULE(dwlpx, kft, dwlpx_driver, dwlpx_devclass, 0, 0); + diff --git a/sys/alpha/tlsb/dwlpxreg.h b/sys/alpha/tlsb/dwlpxreg.h new file mode 100644 index 0000000..cafadc4 --- /dev/null +++ b/sys/alpha/tlsb/dwlpxreg.h @@ -0,0 +1,237 @@ +/* $NetBSD: dwlpxreg.h,v 1.9 1998/03/21 22:02:42 mjacob Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Taken from combinations of: + * + * ``DWLPA and DWLPB PCI Adapter Technical Manual, + * Order Number: EK-DWLPX-TM.A01'' + * + * and + * + * ``AlphaServer 8200/8400 System Technical Manual, + * Order Number EK-T8030-TM. A01'' + */ + +#define REGVAL(r) (*(volatile int32_t *)ALPHA_PHYS_TO_K0SEG(r)) + +/* + * There are (potentially) 4 I/O hoses, and there are three + * (electrically distinct) PCI busses per DWLPX (which appear + * as one logical PCI bus). + * + * A CPU to PCI Address Mapping looks (roughly) like this: + * + * 39 38........36 35.34 33.....32 31....................5 4.........3 2...0 + * -------------------------------------------------------------------------- + * |1| I/O NodeID |Hose#|PCI Space|Byte Aligned I/O <26:0>|Byte Length|0 0 0| + * -------------------------------------------------------------------------- + * + * I/O Node is the TLSB Node ID minus 4. Don't ask. + */ + +#define NHPC 3 + +/* + * Address Space Cookies + * + * (lacking I/O Node ID and Hose Numbers) + */ + +#define DWLPX_PCI_DENSE 0x000000000LL +#define DWLPX_PCI_SPARSE 0x100000000LL +#define DWLPX_PCI_IOSPACE 0x200000000LL +#define DWLPX_PCI_CONF 0x300000000LL + +/* + * PCIA Interface Adapter Register Addresses (Offsets from Node Address) + * + * + * Addresses are for Hose #0, PCI bus #0. Macros below will offset + * per bus. I/O Hose and TLSB Node I/D offsets must be added separately. + */ + +#define _PCIA_CTL 0x380000000LL /* PCI 0 Bus Control */ +#define _PCIA_MRETRY 0x380000080LL /* PCI 0 Master Retry Limit */ +#define _PCIA_GPR 0x380000100LL /* PCI 0 General Purpose */ +#define _PCIA_ERR 0x380000180LL /* PCI 0 Error Summary */ +#define _PCIA_FADR 0x380000200LL /* PCI 0 Failing Address */ +#define _PCIA_IMASK 0x380000280LL /* PCI 0 Interrupt Mask */ +#define _PCIA_DIAG 0x380000300LL /* PCI 0 Diagnostic */ +#define _PCIA_IPEND 0x380000380LL /* PCI 0 Interrupt Pending */ +#define _PCIA_IPROG 0x380000400LL /* PCI 0 Interrupt in Progress */ +#define _PCIA_WMASK_A 0x380000480LL /* PCI 0 Window Mask A */ +#define _PCIA_WBASE_A 0x380000500LL /* PCI 0 Window Base A */ +#define _PCIA_TBASE_A 0x380000580LL /* PCI 0 Window Translated Base A */ +#define _PCIA_WMASK_B 0x380000600LL /* PCI 0 Window Mask B */ +#define _PCIA_WBASE_B 0x380000680LL /* PCI 0 Window Base B */ +#define _PCIA_TBASE_B 0x380000700LL /* PCI 0 Window Translated Base B */ +#define _PCIA_WMASK_C 0x380000780LL /* PCI 0 Window Mask C */ +#define _PCIA_WBASE_C 0x380000800LL /* PCI 0 Window Base C */ +#define _PCIA_TBASE_C 0x380000880LL /* PCI 0 Window Translated Base C */ +#define _PCIA_ERRVEC 0x380000900LL /* PCI 0 Error Interrupt Vector */ +#define _PCIA_DEVVEC 0x380001000LL /* PCI 0 Device Interrupt Vector */ + + +#define PCIA_CTL(hpc) (_PCIA_CTL + (0x200000 * (hpc))) +#define PCIA_MRETRY(hpc) (_PCIA_MRETRY + (0x200000 * (hpc))) +#define PCIA_GPR(hpc) (_PCIA_GPR + (0x200000 * (hpc))) +#define PCIA_ERR(hpc) (_PCIA_ERR + (0x200000 * (hpc))) +#define PCIA_FADR(hpc) (_PCIA_FADR + (0x200000 * (hpc))) +#define PCIA_IMASK(hpc) (_PCIA_IMASK + (0x200000 * (hpc))) +#define PCIA_DIAG(hpc) (_PCIA_DIAG + (0x200000 * (hpc))) +#define PCIA_IPEND(hpc) (_PCIA_IPEND + (0x200000 * (hpc))) +#define PCIA_IPROG(hpc) (_PCIA_IPROG + (0x200000 * (hpc))) +#define PCIA_WMASK_A(hpc) (_PCIA_WMASK_A + (0x200000 * (hpc))) +#define PCIA_WBASE_A(hpc) (_PCIA_WBASE_A + (0x200000 * (hpc))) +#define PCIA_TBASE_A(hpc) (_PCIA_TBASE_A + (0x200000 * (hpc))) +#define PCIA_WMASK_B(hpc) (_PCIA_WMASK_B + (0x200000 * (hpc))) +#define PCIA_WBASE_B(hpc) (_PCIA_WBASE_B + (0x200000 * (hpc))) +#define PCIA_TBASE_B(hpc) (_PCIA_TBASE_B + (0x200000 * (hpc))) +#define PCIA_WMASK_C(hpc) (_PCIA_WMASK_C + (0x200000 * (hpc))) +#define PCIA_WBASE_C(hpc) (_PCIA_WBASE_C + (0x200000 * (hpc))) +#define PCIA_TBASE_C(hpc) (_PCIA_TBASE_C + (0x200000 * (hpc))) +#define PCIA_ERRVEC(hpc) (_PCIA_ERRVEC + (0x200000 * (hpc))) + +#define PCIA_DEVVEC(hpc, subslot, ipin) \ + (_PCIA_DEVVEC + (0x200000 * (hpc)) + ((subslot) * 0x200) + ((ipin-1) * 0x80)) + +#define PCIA_SCYCLE 0x380002000LL /* PCI Special Cycle */ +#define PCIA_IACK 0x380002080LL /* PCI Interrupt Acknowledge */ + +#define PCIA_PRESENT 0x380800000LL /* PCI Slot Present */ +#define PCIA_TBIT 0x380A00000LL /* PCI TBIT */ +#define PCIA_MCTL 0x380C00000LL /* PCI Module Control */ +#define PCIA_IBR 0x380E00000LL /* PCI Information Base Repair */ + +/* + * Bits in PCIA_CTL register + */ +#define PCIA_CTL_SG32K (0<<25) /* 32K SGMAP entries */ +#define PCIA_CTL_SG64K (1<<25) /* 64K SGMAP entries */ +#define PCIA_CTL_SG128K (3<<25) /* 128K SGMAP entries */ +#define PCIA_CTL_SG0K (2<<25) /* disable SGMAP in HPC */ +#define PCIA_CTL_4UP (0<<23) /* 4 Up Hose buffers */ +#define PCIA_CTL_1UP (1<<23) /* 1 "" */ +#define PCIA_CTL_2UP (2<<23) /* 2 "" */ +#define PCIA_CTL_3UP (3<<23) /* 3 "" (normal) */ +#define PCIA_CTL_RMM4X (1<<22) /* Read Multiple 2X -> 4X */ +#define PCIA_CTL_RMMENA (1<<21) /* Read Multiple Enable */ +#define PCIA_CTL_RMMARB (1<<20) /* RMM Multiple Arb */ +#define PCIA_CTL_HAEDIS (1<<19) /* Hardware Address Ext. Disable */ +#define PCIA_CTL_MHAE(x) ((x&0x1f)<<14) /* Memory Hardware Address Extension */ +#define PCIA_CTL_IHAE(x) ((x&0x1f)<<9) /* I/O Hardware Address Extension */ +#define PCIA_CTL_CUTENA (1<<8) /* PCI Cut Through */ +#define PCIA_CTL_CUT(x) ((x&0x7)<<4) /* PCI Cut Through Size */ +#define PCIA_CTL_PRESET (1<<3) /* PCI Reset */ +#define PCIA_CTL_DTHROT (1<<2) /* DMA downthrottle */ +#define PCIA_CTL_T1CYC (1<<0) /* Type 1 Configuration Cycle */ + +/* + * Bits in PCIA_ERR. All are "Write 1 to clear". + */ +#define PCIA_ERR_SERR_L (1<<18) /* PCI device asserted SERR_L */ +#define PCIA_ERR_ILAT (1<<17) /* Incremental Latency Exceeded */ +#define PCIA_ERR_SGPRTY (1<<16) /* CPU access of SG RAM Parity Error */ +#define PCIA_ERR_ILLCSR (1<<15) /* Illegal CSR Address Error */ +#define PCIA_ERR_PCINXM (1<<14) /* Nonexistent PCI Address Error */ +#define PCIA_ERR_DSCERR (1<<13) /* PCI Target Disconnect Error */ +#define PCIA_ERR_ABRT (1<<12) /* PCI Target Abort Error */ +#define PCIA_ERR_WPRTY (1<<11) /* PCI Write Parity Error */ +#define PCIA_ERR_DPERR (1<<10) /* PCI Data Parity Error */ +#define PCIA_ERR_APERR (1<<9) /* PCI Address Parity Error */ +#define PCIA_ERR_DFLT (1<<8) /* SG Map RAM Invalid Entry Error */ +#define PCIA_ERR_DPRTY (1<<7) /* DMA access of SG RAM Parity Error */ +#define PCIA_ERR_DRPERR (1<<6) /* DMA Read Return Parity Error */ +#define PCIA_ERR_MABRT (1<<5) /* PCI Master Abort Error */ +#define PCIA_ERR_CPRTY (1<<4) /* CSR Parity Error */ +#define PCIA_ERR_COVR (1<<3) /* CSR Overrun Error */ +#define PCIA_ERR_MBPERR (1<<2) /* Mailbox Parity Error */ +#define PCIA_ERR_MBILI (1<<1) /* Mailbox Illegal Length Error */ +#define PCIA_ERR_ERROR (1<<0) /* Summary Error */ +#define PCIA_ERR_ALLERR ((1<<19) - 1) + +/* + * Bits in PCIA_PRESENT. + */ +#define PCIA_PRESENT_REVSHIFT 25 /* shift by this to get revision */ +#define PCIA_PRESENT_REVMASK 0xf +#define PCIA_PRESENT_STDIO 0x01000000 /* STD I/O bridge present */ +#define PCIA_PRESENT_SLOTSHIFT(hpc, slot) \ + (((hpc) << 3) + ((slot) << 1)) +#define PCIA_PRESENT_SLOT_MASK 0x3 +#define PCIA_PRESENT_SLOT_NONE 0x0 +#define PCIA_PRESENT_SLOT_25W 0x1 +#define PCIA_PRESENT_SLOT_15W 0x2 +#define PCIA_PRESENT_SLOW_7W 0x3 + +/* + * Location of the DWLPx SGMAP page table SRAM. + */ +#define PCIA_SGMAP_PT 0x381000000UL + +/* + * Values for PCIA_WMASK_x + */ +#define PCIA_WMASK_MASK 0xffff0000 /* mask of valid bits */ +#define PCIA_WMASK_64K 0x00000000 +#define PCIA_WMASK_128K 0x00010000 +#define PCIA_WMASK_256K 0x00030000 +#define PCIA_WMASK_512K 0x00070000 +#define PCIA_WMASK_1M 0x000f0000 +#define PCIA_WMASK_2M 0x001f0000 +#define PCIA_WMASK_4M 0x003f0000 +#define PCIA_WMASK_8M 0x007f0000 +#define PCIA_WMASK_16M 0x00ff0000 +#define PCIA_WMASK_32M 0x01ff0000 +#define PCIA_WMASK_64M 0x03ff0000 +#define PCIA_WMASK_128M 0x07ff0000 +#define PCIA_WMASK_256M 0x0fff0000 +#define PCIA_WMASK_512M 0x1fff0000 +#define PCIA_WMASK_1G 0x3fff0000 +#define PCIA_WMASK_2G 0x7fff0000 +#define PCIA_WMASK_4G 0xffff0000 + +/* + * Values for PCIA_WBASE_x + */ +#define PCIA_WBASE_MASK 0xffff0000 /* mask of valid bits in address */ +#define PCIA_WBASE_W_EN 0x00000002 /* window enable */ +#define PCIA_WBASE_SG_EN 0x00000001 /* SGMAP enable */ + +/* + * Values for PCIA_TBASE_x + * + * NOTE: Translated Base is only used on direct-mapped DMA on the DWLPx!! + */ +#define PCIA_TBASE_MASK 0x00fffffe +#define PCIA_TBASE_SHIFT 15 diff --git a/sys/alpha/tlsb/gbus.c b/sys/alpha/tlsb/gbus.c new file mode 100644 index 0000000..5235284 --- /dev/null +++ b/sys/alpha/tlsb/gbus.c @@ -0,0 +1,155 @@ +/* $Id */ +/* $NetBSD: gbus.c,v 1.8 1998/05/13 22:13:35 thorpej Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Autoconfiguration and support routines for the Gbus: the internal + * bus on AlphaServer CPU modules. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> + +#include <machine/rpb.h> +#include <machine/pte.h> + +#include <alpha/tlsb/gbusreg.h> +#include <alpha/tlsb/gbusvar.h> + +#include <alpha/tlsb/tlsbreg.h> +#include <alpha/tlsb/tlsbvar.h> + +extern int cputype; + +#define KV(_addr) ((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr))) + +/* + * The structure used to attach devices to the Gbus. + */ +struct gbus_device { + const char* gd_name; + int gd_offset; +}; + +#define DEVTOGBUS(dev) ((struct gbus_device*) device_get_ivars(dev)) + +struct gbus_device gbus_children[] = { + { "zsc", GBUS_DUART0_OFFSET }, +/* { "zsc", GBUS_DUART1_OFFSET },*/ + { "mcclock", GBUS_CLOCK_OFFSET }, + { NULL, 0 }, +}; + +static devclass_t gbus_devclass; + +/* + * Bus handlers. + */ +static bus_print_device_t gbus_print_device; +static bus_read_ivar_t gbus_read_ivar; + +static bus_ops_t gbus_bus_ops = { + gbus_print_device, + gbus_read_ivar, + null_write_ivar, + null_map_intr, +}; + +static void +gbus_print_device(bus_t bus, device_t dev) +{ + struct gbus_device* gdev = DEVTOGBUS(dev); + device_t gbusdev = bus_get_device(bus); + + printf(" at %s%d offset 0x%lx", + device_get_name(gbusdev), device_get_unit(gbusdev), + gdev->gd_offset); +} + +static int +gbus_read_ivar(bus_t bus, device_t dev, + int index, u_long* result) +{ + struct gbus_device* gdev = DEVTOGBUS(dev); + + switch (index) { + case GBUS_IVAR_OFFSET: + *result = gdev->gd_offset; + break; + } + return ENOENT; +} + +static driver_probe_t gbus_bus_probe; + +static driver_t gbus_bus_driver = { + "gbus", + gbus_bus_probe, + bus_generic_attach, + bus_generic_detach, + bus_generic_shutdown, + DRIVER_TYPE_MISC, + sizeof(struct bus), + NULL, +}; + +/* + * At 'probe' time, we add all the devices which we know about to the + * bus. The generic attach routine will probe and attach them if they + * are alive. + */ +static int +gbus_bus_probe(bus_t parent, device_t dev) +{ + bus_t bus = device_get_softc(dev); + struct gbus_device *gdev; + + /* + * Make sure we're looking for a Gbus. + * Right now, only Gbus could be a + * child of a TLSB CPU Node. + */ + if (!TLDEV_ISCPU(tlsb_get_dtype(dev))) + return ENXIO; + + bus_init(bus, dev, &gbus_bus_ops); + + for (gdev = gbus_children; gdev->gd_name; gdev++) + bus_add_device(bus, gdev->gd_name, -1, gdev); + + return 0; +} + +DRIVER_MODULE(gbus, tlsb, gbus_bus_driver, gbus_devclass, 0, 0); diff --git a/sys/alpha/tlsb/gbusreg.h b/sys/alpha/tlsb/gbusreg.h new file mode 100644 index 0000000..4e75854 --- /dev/null +++ b/sys/alpha/tlsb/gbusreg.h @@ -0,0 +1,46 @@ +/* $NetBSD: gbusreg.h,v 1.1 1998/05/13 02:50:29 thorpej Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Register definitions for the Gbus found on TurboLaser CPU modules. + */ + +#define GBUS_DUART0_OFFSET 0x10000000 /* duart 0 */ +#define GBUS_DUART1_OFFSET 0x11000000 /* duart 1 */ +#define GBUS_CLOCK_OFFSET 0x20000000 /* clock */ diff --git a/sys/alpha/tlsb/gbusvar.h b/sys/alpha/tlsb/gbusvar.h new file mode 100644 index 0000000..1652619 --- /dev/null +++ b/sys/alpha/tlsb/gbusvar.h @@ -0,0 +1,64 @@ +/* $NetBSD: gbusvar.h,v 1.1 1998/05/13 02:50:29 thorpej Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Autoconfiguration definitions for the Gbus found on TurboLaser CPU modules. + */ + +/* #include <machine/bus.h> */ + +enum gbus_device_ivars { + GBUS_IVAR_OFFSET /* offset from Gbus base */ +}; + +/* + * Simplified accessors for gbus devices + */ + +#define GBUS_ACCESSOR(A, B, T) \ + \ +static __inline T gbus_get_ ## A(device_t dev) \ +{ \ + u_long v; \ + bus_read_ivar(device_get_parent(dev), dev, GBUS_IVAR_ ## B, &v); \ + return (T) v; \ +} + +GBUS_ACCESSOR(offset, OFFSET, u_int32_t) + diff --git a/sys/alpha/tlsb/kftxx.c b/sys/alpha/tlsb/kftxx.c new file mode 100644 index 0000000..9f41b62 --- /dev/null +++ b/sys/alpha/tlsb/kftxx.c @@ -0,0 +1,192 @@ +/* $Id$ */ +/* $NetBSD: kftxx.c,v 1.9 1998/05/14 00:01:32 thorpej Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * KFTIA and KFTHA Bus Adapter Node for I/O hoses + * found on AlphaServer 8200 and 8400 systems. + * + * i.e., handler for all TLSB I/O nodes. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> + +#include <machine/rpb.h> + +#include <alpha/tlsb/tlsbreg.h> +#include <alpha/tlsb/tlsbvar.h> +#include <alpha/tlsb/kftxxreg.h> +#include <alpha/tlsb/kftxxvar.h> + +struct kft_softc { + struct bus sc_bus; /* bus common */ + int sc_node; /* TLSB node */ + u_int16_t sc_dtype; /* device type */ +}; + +/* + * Instance variables for kft devices. + */ +struct kft_device { + char * kd_name; /* name */ + int kd_node; /* node number */ + u_int16_t kd_dtype; /* device type */ + u_int16_t kd_hosenum; /* hose number */ +}; + +#define KV(_addr) ((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr))) + +static devclass_t kft_devclass; + +/* + * Bus handlers. + */ +static bus_print_device_t kft_print_device; +static bus_read_ivar_t kft_read_ivar; + +static bus_ops_t kft_bus_ops = { + kft_print_device, + kft_read_ivar, + null_write_ivar, + null_map_intr, +}; + +static void +kft_print_device(bus_t bus, device_t dev) +{ + struct kft_device *kd = (struct kft_device*) device_get_ivars(dev); + device_t busdev = bus_get_device(bus); + + printf(" at %s%d hose %d", + device_get_name(busdev), device_get_unit(busdev), + kd->kd_hosenum); +} + +static int +kft_read_ivar(bus_t bus, device_t dev, + int index, u_long* result) +{ + struct kft_device *kd = (struct kft_device*) device_get_ivars(dev); + + switch (index) { + case KFT_IVAR_NAME: + *result = (u_long) kd->kd_name; + return 0; + + case KFT_IVAR_NODE: + *result = (u_long) kd->kd_node; + return 0; + + case KFT_IVAR_DTYPE: + *result = (u_long) kd->kd_dtype; + return 0; + + case KFT_IVAR_HOSENUM: + *result = (u_long) kd->kd_hosenum; + return 0; + + default: + return ENOENT; + } +} + +static driver_probe_t kft_bus_probe; + +static driver_t kft_bus_driver = { + "kft", + kft_bus_probe, + bus_generic_attach, + bus_generic_detach, + bus_generic_shutdown, + DRIVER_TYPE_MISC, + sizeof(struct kft_softc), + NULL, +}; + +static int +kft_bus_probe(bus_t parent, device_t dev) +{ + struct kft_softc *sc = (struct kft_softc *) device_get_softc(dev); + struct kft_device* kd; + int hoseno; + + if (!TLDEV_ISIOPORT(tlsb_get_dtype(dev))) + return ENXIO; + + bus_init(&sc->sc_bus, dev, &kft_bus_ops); + + sc->sc_node = tlsb_get_node(dev); + sc->sc_dtype = tlsb_get_dtype(dev); + + for (hoseno = 0; hoseno < MAXHOSE; hoseno++) { + u_int32_t value = + TLSB_GET_NODEREG(sc->sc_node, KFT_IDPNSEX(hoseno)); + if (value & 0x0E000000) { + printf("%s%d: Hose %d IDPNSE has %x\n", + device_get_name(dev), device_get_unit(dev), + hoseno, value); + continue; + } + if ((value & 0x1) != 0x0) { + printf("%s%d: Hose %d has a Bad Cable (0x%x)\n", + device_get_name(dev), device_get_unit(dev), + hoseno, value); + continue; + } + if ((value & 0x6) != 0x6) { + if (value) + printf("%s%d: Hose %d is missing PWROK (0x%x)\n", + device_get_name(dev), device_get_unit(dev), + hoseno, value); + continue; + } + + kd = (struct kft_device*) malloc(sizeof(struct kft_device), + M_DEVBUF, M_NOWAIT); + if (!kd) continue; + + kd->kd_name = "dwlpx"; + kd->kd_node = sc->sc_node; + kd->kd_dtype = sc->sc_dtype; + kd->kd_hosenum = hoseno; + bus_add_device(&sc->sc_bus, kd->kd_name, -1, kd); + } + + return 0; +} + +DRIVER_MODULE(kft, tlsb, kft_bus_driver, kft_devclass, 0, 0); diff --git a/sys/alpha/tlsb/kftxxreg.h b/sys/alpha/tlsb/kftxxreg.h new file mode 100644 index 0000000..0f45fdd --- /dev/null +++ b/sys/alpha/tlsb/kftxxreg.h @@ -0,0 +1,74 @@ +/* $NetBSD: kftxxreg.h,v 1.4 1997/06/04 01:47:15 cgd Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Registers and values specific to KFTIA or KFTHA nodes. + */ + +/* + * Taken from combinations of: + * + * ``DWLPA and DWLPB PCI Adapter Technical Manual, + * Order Number: EK-DWLPX-TM.A01'' + * + * and + * + * ``AlphaServer 8200/8400 System Technical Manual, + * Order Number EK-T8030-TM. A01'' + */ + +#define REGVAL(r) (*(volatile int32_t *)ALPHA_PHYS_TO_K0SEG(r)) + +/* + * There are (potentially) 4 I/O hoses per I/O node. + * + * A CPU to Hose Address Mapping looks (roughly) like this: + * + * 39 38........36 35.34 33.................0 + * ------------------------------------------- + * |1|TLSB NodeID |Hose#|Hose Module Specific| + * ------------------------------------------- + * + */ + +#define HOSE_SIZE 0x400000000L + +#define MAXHOSE 4 +/* + * Hose Specific I/O registers (offsets from base of I/O Board) + */ + +#define KFT_IDPNSEX(hose) ((hose)? (0x2040 + (0x100 * (hose))) : 0x2A40) + +#define KFT_ICCNSE 0x2040 +#define KFT_ICCWTR 0x2100 +#define KFT_IDPMSR 0x2B80 diff --git a/sys/alpha/tlsb/kftxxvar.h b/sys/alpha/tlsb/kftxxvar.h new file mode 100644 index 0000000..d0b3f40 --- /dev/null +++ b/sys/alpha/tlsb/kftxxvar.h @@ -0,0 +1,59 @@ +/* $NetBSD: kftxxvar.h,v 1.3 1997/04/06 20:08:38 cgd Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Instance vars for children of a KFTIA or KFTHA node. + */ +enum kft_dev_ivars { + KFT_IVAR_NAME, + KFT_IVAR_NODE, + KFT_IVAR_DTYPE, + KFT_IVAR_HOSENUM +}; + +/* + * Simplified accessors for kft devices + */ + +#define KFT_ACCESSOR(A, B, T) \ + \ +static __inline T kft_get_ ## A(device_t dev) \ +{ \ + u_long v; \ + bus_read_ivar(device_get_parent(dev), dev, KFT_IVAR_ ## B, &v); \ + return (T) v; \ +} + +KFT_ACCESSOR(name, NAME, const char*) +KFT_ACCESSOR(node, NODE, int) +KFT_ACCESSOR(dtype, DTYPE, u_int16_t) +KFT_ACCESSOR(hosenum, HOSENUM, u_int16_t) diff --git a/sys/alpha/tlsb/mcclock_tlsb.c b/sys/alpha/tlsb/mcclock_tlsb.c new file mode 100644 index 0000000..15974fc --- /dev/null +++ b/sys/alpha/tlsb/mcclock_tlsb.c @@ -0,0 +1,126 @@ +/* $Id$ */ +/* $NetBSD: mcclock_tlsb.c,v 1.8 1998/05/13 02:50:29 thorpej Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> + +#include <dev/dec/clockvar.h> +#include <dev/dec/mcclockvar.h> + +#include <alpha/tlsb/gbusvar.h> + +#include <alpha/tlsb/tlsbreg.h> /* XXX */ + +#include <dev/dec/mc146818reg.h> + +#define KV(_addr) ((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr))) +/* + * Registers are 64 bytes apart (and 1 byte wide) + */ +#define REGSHIFT 6 + +struct mcclock_tlsb_softc { + struct mcclock_softc sc_mcclock; + unsigned long regbase; +}; + +static int mcclock_tlsb_probe(bus_t, device_t); +static int mcclock_tlsb_attach(bus_t, device_t); + +static devclass_t mcclock_devclass; + +driver_t mcclock_tlsb_driver = { + "mcclock", + mcclock_tlsb_probe, + mcclock_tlsb_attach, + NULL, + NULL, + DRIVER_TYPE_MISC, + sizeof(struct mcclock_tlsb_softc), + NULL, +}; + +static void mcclock_tlsb_write __P((struct mcclock_softc *, u_int, u_int)); +static u_int mcclock_tlsb_read __P((struct mcclock_softc *, u_int)); + +const struct mcclock_busfns mcclock_tlsb_busfns = { + mcclock_tlsb_write, mcclock_tlsb_read, +}; + +int +mcclock_tlsb_probe(bus_t bus, device_t dev) +{ + device_set_desc(dev, "MC146818A real time clock"); + return 0; +} + +int +mcclock_tlsb_attach(bus_t bus, device_t dev) +{ + struct mcclock_tlsb_softc *sc = device_get_softc(dev); + + /* XXX Should be bus.h'd, so we can accomodate the kn7aa. */ + + sc->sc_mcclock.sc_dev = dev; + sc->regbase = TLSB_GBUS_BASE + gbus_get_offset(dev); + + mcclock_attach(&sc->sc_mcclock, &mcclock_tlsb_busfns); + return 0; +} + +static void +mcclock_tlsb_write(mcsc, reg, val) + struct mcclock_softc *mcsc; + u_int reg, val; +{ + struct mcclock_tlsb_softc *sc = (struct mcclock_tlsb_softc *)mcsc; + unsigned char *ptr = (unsigned char *) + KV(sc->regbase + (reg << REGSHIFT)); + *ptr = val; +} + +static u_int +mcclock_tlsb_read(mcsc, reg) + struct mcclock_softc *mcsc; + u_int reg; +{ + struct mcclock_tlsb_softc *sc = (struct mcclock_tlsb_softc *)mcsc; + unsigned char *ptr = (unsigned char *) + KV(sc->regbase + (reg << REGSHIFT)); + return *ptr; +} + +DRIVER_MODULE(mcclock_tlsb, gbus, mcclock_tlsb_driver, mcclock_devclass, 0, 0); diff --git a/sys/alpha/tlsb/tlsb.c b/sys/alpha/tlsb/tlsb.c new file mode 100644 index 0000000..7b778ac --- /dev/null +++ b/sys/alpha/tlsb/tlsb.c @@ -0,0 +1,329 @@ +/* $Id */ +/* $NetBSD: tlsb.c,v 1.10 1998/05/14 00:01:32 thorpej Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * Based in part upon a prototype version by Jason Thorpe + * Copyright (c) 1996 by Jason Thorpe. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Autoconfiguration and support routines for the TurboLaser System Bus + * found on AlphaServer 8200 and 8400 systems. + */ + +#include "opt_simos.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/malloc.h> + +#include <machine/rpb.h> +#include <machine/cpuconf.h> + +#include <alpha/tlsb/tlsbreg.h> +#include <alpha/tlsb/tlsbvar.h> + +/* #include "locators.h" */ + +extern int cputype; + +#define KV(_addr) ((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr))) + +/* + * The structure used to attach devices to the TurboLaser. + */ +struct tlsb_device { + int td_node; /* node number */ + u_int16_t td_dtype; /* device type */ + u_int8_t td_swrev; /* software revision */ + u_int8_t td_hwrev; /* hardware revision */ +}; +#define DEVTOTLSB(dev) ((struct tlsb_device*) device_get_ivars(dev)) + +struct intr_mapping { + STAILQ_ENTRY(intr_mapping) queue; + driver_intr_t* intr; + void* arg; +}; + +struct tlsb_softc { + struct bus bus; + STAILQ_HEAD(, intr_mapping) intr_handlers; +}; + +static char *tlsb_node_type_str(u_int32_t); +static void tlsb_intr(void* frame, u_long vector); + +/* There can be only one. */ +static int tlsb_found; +static struct tlsb_softc* tlsb0_softc; + +/* + * Bus handlers. + */ +static bus_print_device_t tlsb_print_device; +static bus_read_ivar_t tlsb_read_ivar; +static bus_map_intr_t tlsb_map_intr; + +static bus_ops_t tlsb_bus_ops = { + tlsb_print_device, + tlsb_read_ivar, + null_write_ivar, + tlsb_map_intr, +}; + +static void +tlsb_print_device(bus_t bus, device_t dev) +{ + device_t busdev = bus_get_device(bus); + struct tlsb_device* tdev = DEVTOTLSB(dev); + + printf(" at %s%d node %d", + device_get_name(busdev), + device_get_unit(busdev), + tdev->td_node); +} + +static int +tlsb_read_ivar(bus_t bus, device_t dev, + int index, u_long* result) +{ + struct tlsb_device* tdev = DEVTOTLSB(dev); + + switch (index) { + case TLSB_IVAR_NODE: + *result = tdev->td_node; + break; + + case TLSB_IVAR_DTYPE: + *result = tdev->td_dtype; + break; + + case TLSB_IVAR_SWREV: + *result = tdev->td_swrev; + break; + + case TLSB_IVAR_HWREV: + *result = tdev->td_hwrev; + break; + } + return ENOENT; +} + +static int +tlsb_map_intr(bus_t bus, device_t dev, driver_intr_t *intr, void *arg) +{ + struct tlsb_softc* sc = (struct tlsb_softc*) bus; + struct intr_mapping* i; + i = malloc(sizeof(struct intr_mapping), M_DEVBUF, M_NOWAIT); + if (!i) + return ENOMEM; + i->intr = intr; + i->arg = arg; + STAILQ_INSERT_TAIL(&sc->intr_handlers, i, queue); + + return 0; +} + +static driver_probe_t tlsb_bus_probe; +static devclass_t tlsb_devclass; + +static driver_t tlsb_bus_driver = { + "tlsb", + tlsb_bus_probe, + bus_generic_attach, + bus_generic_detach, + bus_generic_shutdown, + DRIVER_TYPE_MISC, + sizeof(struct tlsb_softc), + NULL, +}; + +/* + * At 'probe' time, we add all the devices which we know about to the + * bus. The generic attach routine will probe and attach them if they + * are alive. + */ +static int +tlsb_bus_probe(bus_t parent, device_t dev) +{ + struct tlsb_softc* sc = device_get_softc(dev); + struct tlsb_device *tdev; + u_int32_t tldev; + u_int8_t vid; + int node; + device_t subdev; + + device_set_desc(dev, "TurboLaser bus"); + bus_init(&sc->bus, dev, &tlsb_bus_ops); + STAILQ_INIT(&sc->intr_handlers); + tlsb0_softc = sc; + + set_iointr(tlsb_intr); + + printf("Probing for devices on the TurboLaser bus:\n"); + + tlsb_found = 1; + + /* + * Attempt to find all devices on the bus, including + * CPUs, memory modules, and I/O modules. + */ + + /* + * Sigh. I would like to just start off nicely, + * but I need to treat I/O modules differently- + * The highest priority I/O node has to be in + * node #8, and I want to find it *first*, since + * it will have the primary disks (most likely) + * on it. + */ + /* + * XXX dfr: I don't see why I need to do this + */ + for (node = 0; node <= TLSB_NODE_MAX; ++node) { + /* + * Check for invalid address. This may not really + * be necessary, but what the heck... + */ + if (badaddr(TLSB_NODE_REG_ADDR(node, TLDEV), sizeof(u_int32_t))) + continue; + tldev = TLSB_GET_NODEREG(node, TLDEV); +#ifdef SIMOS + if (node != 0 && node != 8) + continue; +#endif + if (tldev == 0) { + /* Nothing at this node. */ + continue; + } +#if 0 + if (TLDEV_ISIOPORT(tldev)) + continue; /* not interested right now */ +#endif + + tdev = (struct tlsb_device*) + malloc(sizeof(struct tlsb_device), + M_DEVBUF, M_NOWAIT); + + if (!tdev) + continue; + + tdev->td_node = node; +#ifdef SIMOS + if (node == 0) + tdev->td_dtype = TLDEV_DTYPE_SCPU4; + else if (node == 8) + tdev->td_dtype = TLDEV_DTYPE_KFTIA; +#else + tdev->td_dtype = TLDEV_DTYPE(tldev); +#endif + tdev->td_swrev = TLDEV_SWREV(tldev); + tdev->td_hwrev = TLDEV_HWREV(tldev); + + subdev = bus_add_device(&sc->bus, NULL, -1, tdev); + device_set_desc(subdev, tlsb_node_type_str(tdev->td_dtype)); + + /* + * Deal with hooking CPU instances to TurboLaser nodes. + */ + if (TLDEV_ISCPU(tldev)) { + printf("%s%d node %d: %s", + device_get_name(dev), device_get_unit(dev), + node, tlsb_node_type_str(tldev)); + + /* + * Hook in the first CPU unit. + */ + vid = (TLSB_GET_NODEREG(node, TLVID) & + TLVID_VIDA_MASK) >> TLVID_VIDA_SHIFT; + printf(", VID %d\n", vid); + TLSB_PUT_NODEREG(node, TLCPUMASK, (1<<vid)); + } + } + + return 0; +} + +static void +tlsb_intr(void* frame, u_long vector) +{ + struct tlsb_softc* sc = tlsb0_softc; + struct intr_mapping* i; + + /* + * XXX for SimOS, broadcast the interrupt. A real implementation + * will decode the vector to extract node and host etc. + */ + for (i = STAILQ_FIRST(&sc->intr_handlers); + i; i = STAILQ_NEXT(i, queue)) + i->intr(i->arg); +} + +DRIVER_MODULE(tlsb, root, tlsb_bus_driver, tlsb_devclass, 0, 0); + +static char * +tlsb_node_type_str(u_int32_t dtype) +{ + static char tlsb_line[64]; + + switch (dtype & TLDEV_DTYPE_MASK) { + case TLDEV_DTYPE_KFTHA: + return ("KFTHA I/O interface"); + + case TLDEV_DTYPE_KFTIA: + return ("KFTIA I/O interface"); + + case TLDEV_DTYPE_MS7CC: + return ("MS7CC Memory Module"); + + case TLDEV_DTYPE_SCPU4: + return ("Single CPU, 4MB cache"); + + case TLDEV_DTYPE_SCPU16: + return ("Single CPU, 16MB cache"); + + case TLDEV_DTYPE_DCPU4: + return ("Dual CPU, 4MB cache"); + + case TLDEV_DTYPE_DCPU16: + return ("Dual CPU, 16MB cache"); + + default: + bzero(tlsb_line, sizeof(tlsb_line)); + sprintf(tlsb_line, "unknown, dtype 0x%x", dtype); + return (tlsb_line); + } + /* NOTREACHED */ +} diff --git a/sys/alpha/tlsb/tlsbmem.c b/sys/alpha/tlsb/tlsbmem.c new file mode 100644 index 0000000..c46306c --- /dev/null +++ b/sys/alpha/tlsb/tlsbmem.c @@ -0,0 +1,91 @@ +/* $NetBSD: tlsbmem.c,v 1.6 1998/01/12 10:21:25 thorpej Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Dummy Node for TLSB Memory Modules found on + * AlphaServer 8200 and 8400 systems. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: tlsbmem.c,v 1.6 1998/01/12 10:21:25 thorpej Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/malloc.h> + +#include <machine/autoconf.h> +#include <machine/rpb.h> +#include <machine/pte.h> + +#include <alpha/tlsb/tlsbreg.h> +#include <alpha/tlsb/tlsbvar.h> + +struct tlsbmem_softc { + struct device sc_dv; + int sc_node; /* TLSB node */ + u_int16_t sc_dtype; /* device type */ +}; + +static int tlsbmemmatch __P((struct device *, struct cfdata *, void *)); +static void tlsbmemattach __P((struct device *, struct device *, void *)); +struct cfattach tlsbmem_ca = { + sizeof (struct tlsbmem_softc), tlsbmemmatch, tlsbmemattach +}; + +static int +tlsbmemmatch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct tlsb_dev_attach_args *ta = aux; + if (TLDEV_ISMEM(ta->ta_dtype)) + return (1); + return (0); +} + +static void +tlsbmemattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct tlsb_dev_attach_args *ta = aux; + struct tlsbmem_softc *sc = (struct tlsbmem_softc *)self; + + sc->sc_node = ta->ta_node; + sc->sc_dtype = ta->ta_dtype; + + printf("\n"); +} diff --git a/sys/alpha/tlsb/tlsbreg.h b/sys/alpha/tlsb/tlsbreg.h new file mode 100644 index 0000000..37b58de --- /dev/null +++ b/sys/alpha/tlsb/tlsbreg.h @@ -0,0 +1,318 @@ +/* $NetBSD: tlsbreg.h,v 1.3 1997/04/06 20:08:40 cgd Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * Based in part upon a prototype version by Jason Thorpe + * Copyright (c) 1996 by Jason Thorpe. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Definitions for the TurboLaser System Bus found on + * AlphaServer 8200/8400 systems. + */ + +/* + * There are 9 TurboLaser nodes, 0 though 8. Their uses are defined as + * follows: + * + * Node Module + * ---- ------ + * 0 CPU, Memory + * 1 CPU, Memory + * 2 CPU, Memory + * 3 CPU, Memory + * 4 CPU, Memory, I/O + * 5 CPU, Memory, I/O + * 6 CPU, Memory, I/O + * 7 CPU, Memory, I/O + * 8 I/O + * + * A node occurs every 0x00400000 bytes. + * + * Note, the AlphaServer 8200 only has nodes 4 though 8. + */ + +#define TLSB_NODE_BASE 0x000000ff88000000 /* Dense */ +#define TLSB_NODE_SIZE 0x00400000 +#define TLSB_NODE_MAX 8 + +/* Translate a node number to an address. */ +#define TLSB_NODE_ADDR(_node) \ + (long)(TLSB_NODE_BASE + ((_node) * TLSB_NODE_SIZE)) + +#define TLSB_NODE_REG_ADDR(_node, _reg) \ + KV((long)TLSB_NODE_ADDR((_node)) + (_reg)) + +/* Access the specified register on the specified node. */ +#define TLSB_GET_NODEREG(_node, _reg) \ + *(volatile u_int32_t *)(TLSB_NODE_REG_ADDR((_node), (_reg))) +#define TLSB_PUT_NODEREG(_node, _reg, _val) \ + *(volatile u_int32_t *)(TLSB_NODE_REG_ADDR((_node), (_reg))) = (_val) + +/* + * Some registers are shared by all TurboLaser nodes, and appear in + * the TurboLaser Broadcast space. + */ +#define TLSB_BCAST_BASE 0x000000ff8e000000 /* Dense */ + +#define TLSB_BCAST_REG_ADDR(_reg) KV((long)(TLSB_BCASE_BASE + (_reg))) + +/* Access the specified register in the broadcast space. */ +#define TLSB_GET_BCASTREG(_reg) \ + *(volatile u_int32_t *)(TLSB_BCAST_REG_ADDR + (_reg)) +#define TLSB_PUT_BCASTREG(_reg, _val) \ + *(volatile u_int32_t *)(TLSB_BCAST_REG_ADDR + (_reg)) = (_val) + +/* + * Location of the Gbus, the per-CPU bus containing the clock and + * console hardware. + */ +#define TLSB_GBUS_BASE 0x000000ff90000000 /* Dense */ + +/* + * Note that not every module type supports each TurboLaser register. + * The following defines the keys used to denote module support for + * a given register: + * + * C Supported by CPU module + * M Supported by Memory module + * I Supported by I/O module + */ + +/* + * Per-node TurboLaser System Bus registers, offsets from the + * base of the node. + */ +#define TLDEV 0x0000 /* CMI: Device Register */ +#define TLBER 0x0040 /* CMI: Bus Error Register */ +#define TLCNR 0x0080 /* CMI: Congfiguration Register */ +#define TLVID 0x00c0 /* CM: Virtual ID Register */ +#define TLMMR0 0x0200 /* CM: Memory Mapping Register 0 */ +#define TLMMR1 0x0240 /* CM: Memory Mapping Register 1 */ +#define TLMMR2 0x0280 /* CM: Memory Mapping Register 2 */ +#define TLMMR3 0x02c0 /* CM: Memory Mapping Register 3 */ +#define TLMMR4 0x0300 /* CM: Memory Mapping Register 4 */ +#define TLMMR5 0x0340 /* CM: Memory Mapping Register 5 */ +#define TLMMR6 0x0380 /* CM: Memory Mapping Register 6 */ +#define TLMMR7 0x03c0 /* CM: Memory Mapping Register 7 */ +#define TLFADR0 0x0600 /* MI: Failing Address Register 0 */ +#define TLFADR1 0x0640 /* MI: Failing Address Register 1 */ +#define TLESR0 0x0680 /* CMI: Error Syndrome Register 0 */ +#define TLESR1 0x06c0 /* CMI: Error Syndrome Register 1 */ +#define TLESR2 0x0700 /* CMI: Error Syndrome Register 2 */ +#define TLESR3 0x0740 /* CMI: Error Syndrome Register 3 */ +#define TLILID0 0x0a00 /* I: Int. Level 0 IDENT Register */ +#define TLILID1 0x0a40 /* I: Int. Level 1 IDENT Register */ +#define TLILID2 0x0a80 /* I: Int. Level 2 IDENT Register */ +#define TLILID3 0x0ac0 /* I: Int. Level 3 IDENT Register */ +#define TLCPUMASK 0x0b00 /* I: CPU Interrupt Mask Register */ +#define TLMBPTR 0x0c00 /* I: Mailbox Pointer Register */ +#define TLEPAERR 0x1500 /* C: ADG error register */ + +/* + * Registers shared between TurboLaser nodes, offsets from the + * TurboLaser Broadcast Base. + */ +#define TLPRIVATE 0x0000 /* CMI: private "global" space */ +#define TLIPINTR 0x0040 /* C: Interprocessor Int. Register */ +#define TLIOINTR4 0x0100 /* C: I/O Interrupt Register 4 */ +#define TLIOINTR5 0x0140 /* C: I/O Interrupt Register 5 */ +#define TLIOINTR6 0x0180 /* C: I/O Interrupt Register 6 */ +#define TLIOINTR7 0x01c0 /* C: I/O Interrupt Register 7 */ +#define TLIOINTR8 0x0200 /* C: I/O Interrupt Register 8 */ +#define TLWSDQR4 0x0400 /* C: Win Spc Dcr Que Ctr Reg 4 */ +#define TLWSDQR5 0x0440 /* C: Win Spc Dcr Que Ctr Reg 5 */ +#define TLWSDQR6 0x0480 /* C: Win Spc Dcr Que Ctr Reg 6 */ +#define TLWSDQR7 0x04c0 /* C: Win Spc Dcr Que Ctr Reg 7 */ +#define TLWSDQR8 0x0500 /* C: Win Spc Dcr Que Ctr Reg 8 */ +#define TLRMDQRX 0x0600 /* C: Mem Chan Dcr Que Ctr Reg X */ +#define TLRMDQR8 0x0640 /* C: Mem Chan Dcr Que Ctr Reg 8 */ +#define TLRDRD 0x0800 /* C: CSR Read Data Rtn Data Reg */ +#define TLRDRE 0x0840 /* C: CSR Read Data Rtn Error Reg */ +#define TLMCR 0x1880 /* M: Memory Control Register */ + +/* + * TLDEV - Device Register + * + * Access: R/W + * + * Notes: + * Register is loaded during initialization with information + * that identifies a node. A zero value indicates a non-initialized + * (slot empty) node. + * + * Bits 0-15 contain the hardware device type, bits 16-23 + * the board's software revision, and bits 24-31 the board's + * hardware revision. + * + * The device type portion is laid out as follows: + * + * Bit 15: identifies a CPU + * Bit 14: identifies a memory board + * Bit 13: identifies an I/O board + * Bits 0-7: specify the ID of a node type + */ +#define TLDEV_DTYPE_MASK 0x0000ffff +#define TLDEV_DTYPE_KFTHA 0x2000 /* KFTHA board, I/O */ +#define TLDEV_DTYPE_KFTIA 0x2020 /* KFTIA board, I/O */ +#define TLDEV_DTYPE_MS7CC 0x5000 /* Memory board */ +#define TLDEV_DTYPE_SCPU4 0x8011 /* 1 CPU, 4mb cache */ +#define TLDEV_DTYPE_SCPU16 0x8012 /* 1 CPU, 16mb cache */ +#define TLDEV_DTYPE_DCPU4 0x8014 /* 2 CPU, 4mb cache */ +#define TLDEV_DTYPE_DCPU16 0x8015 /* 2 CPU, 16mb cache */ + +#define TLDEV_DTYPE(_val) ((_val) & TLDEV_DTYPE_MASK) +# define TLDEV_ISCPU(_val) (TLDEV_DTYPE(_val) & 0x8000) +# define TLDEV_ISMEM(_val) (TLDEV_DTYPE(_val) & 0x4000) +# define TLDEV_ISIOPORT(_val) (TLDEV_DTYPE(_val) & 0x2000) +#define TLDEV_SWREV(_val) (((_val) >> 16) & 0xff) +#define TLDEV_HWREV(_val) (((_val) >> 24) & 0xff) + +/* + * TLBER - Bus Error Register + * + * Access: R/W + * + * Notes: + * This register contains information about TLSB errors detected by + * nodes on the TLSB. The register will become locked when: + * + * * Any error occurs and the "lock on first error" + * bit of the Configuration Register is set. + * + * * Any bit other than 20-23 (DS0-DS3) becomes set. + * + * and will remain locked until either: + * + * * All bits in the TLBER are cleared. + * + * * The "lock on first error" bit is cleared. + * + * TLBER locking is intended for diagnosic purposes only, and + * not for general use. + */ +#define TLBER_ATCE 0x00000001 /* Addr Transmit Ck Error */ +#define TLBER_APE 0x00000002 /* Addr Parity Error */ +#define TLBER_BAE 0x00000004 /* Bank Avail Violation Error */ +#define TLBER_LKTO 0x00000008 /* Bank Lock Timeout */ +#define TLBER_NAE 0x00000010 /* No Ack Error */ +#define TLBER_RTCE 0x00000020 /* Read Transmit Ck Error */ +#define TLBER_ACKTCE 0x00000040 /* Ack Transmit Ck Error */ +#define TLBER_MMRE 0x00000080 /* Mem Mapping Register Error */ +#define TLBER_FNAE 0x00000100 /* Fatal No Ack Error */ +#define TLBER_REQDE 0x00000200 /* Request Deassertion Error */ +#define TLBER_ATDE 0x00000400 /* Addredd Transmitter During Error */ +#define TLBER_UDE 0x00010000 /* Uncorrectable Data Error */ +#define TLBER_CWDE 0x00020000 /* Correctable Write Data Error */ +#define TLBER_CRDE 0x00040000 /* Correctable Read Data Error */ +#define TLBER_CRDE2 0x00080000 /* ...ditto... */ +#define TLBER_DS0 0x00100000 /* Data Synd 0 */ +#define TLBER_DS1 0x00200000 /* Data Synd 1 */ +#define TLBER_DS2 0x00400000 /* Data Synd 2 */ +#define TLBER_DS3 0x00800000 /* Data Synd 3 */ +#define TLBER_DTDE 0x01000000 /* Data Transmitter During Error */ +#define TLBER_FDTCE 0x02000000 /* Fatal Data Transmit Ck Error */ +#define TLBER_UACKE 0x04000000 /* Unexpected Ack Error */ +#define TLBER_ABTCE 0x08000000 /* Addr Bus Transmit Error */ +#define TLBER_DCTCE 0x10000000 /* Data Control Transmit Ck Error */ +#define TLBER_SEQE 0x20000000 /* Sequence Error */ +#define TLBER_DSE 0x40000000 /* Data Status Error */ +#define TLBER_DTO 0x80000000 /* Data Timeout Error */ + +/* + * TLCNR - Configuration Register + * + * Access: R/W + */ +#define TLCNR_CWDD 0x00000001 /* Corr Write Data Err INTR Dis */ +#define TLCNR_CRDD 0x00000002 /* Corr Read Data Err INTR Dis */ +#define TLCNR_LKTOD 0x00000004 /* Bank Lock Timeout Disable */ +#define TLCNR_DTOD 0x00000008 /* Data Timeout Disable */ +#define TLCNR_STF_A 0x00001000 /* Self-Test Fail A */ +#define TLCNR_STF_B 0x00002000 /* Self-Test Fail B */ +#define TLCNR_HALT_A 0x00100000 /* Halt A */ +#define TLCNR_HALT_B 0x00200000 /* Halt B */ +#define TLCNR_RSTSTAT 0x10000000 /* Reset Status */ +#define TLCNR_NRST 0x40000000 /* Node Reset */ +#define TLCNR_LOFE 0x80000000 /* Lock On First Error */ + +#define TLCNR_NODE_MASK 0x000000f0 /* Node ID mask */ +#define TLCNR_NODE_SHIFT 4 + +#define TLCNR_VCNT_MASK 0x00000f00 /* VCNT mask */ +#define TLCNR_VCNT_SHIFT 8 + +/* + * TLVID - Virtual ID Register + * + * Access: R/W + * + * Notes: + * Virtual units can be CPUs or Memory boards. The units are + * are addressed using virtual IDs. These virtual IDs are assigned + * by writing to the TLVID register. The upper 24 bits of this + * register are reserved and must be written as `0'. + */ +#define TLVID_VIDA_MASK 0x0000000f /* Virtual ID for unit 0 */ +#define TLVID_VIDA_SHIFT 0 + +#define TLVID_VIDB_MASK 0x000000f0 /* Virtual ID for unit 1 */ +#define TLVID_VIDB_SHIFT 4 + +/* + * TLMMRn - Memory Mapping Registers + * + * Access: W + * + * Notes: + * Contains mapping information for doing a bank-decode. + */ +#define TLMMR_INTMASK 0x00000003 /* Valid bits in Interleave */ +#define TLMMR_ADRMASK 0x000000f0 /* Valid bits in Address */ +#define TLMMR_SBANK 0x00000800 /* Single-bank indicator */ +#define TLMMR_VALID 0x80000000 /* Indicated mapping is valid */ + +#define TLMMR_INTLV_MASK 0x00000700 /* Mask for interleave value */ +#define TLMMR_INTLV_SHIFT 8 + +#define TLMMR_ADDRESS_MASK 0x03fff000 /* Mask for address value */ +#define TLMMR_ADDRESS_SHIFT 12 + +/* + * TLFADRn - Failing Address Registers + * + * Access: R/W + * + * Notes: + * These registers contain status information for a failed address. + * Not all nodes preserve this information. The validation bits + * indicate the validity of a given field. + */ + diff --git a/sys/alpha/tlsb/tlsbvar.h b/sys/alpha/tlsb/tlsbvar.h new file mode 100644 index 0000000..bfb24ed --- /dev/null +++ b/sys/alpha/tlsb/tlsbvar.h @@ -0,0 +1,75 @@ +/* $Id$ */ +/* $NetBSD: tlsbvar.h,v 1.5 1998/05/13 23:23:23 thorpej Exp $ */ + +/* + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center. + * All rights reserved. + * + * Based in part upon a prototype version by Jason Thorpe + * Copyright (c) 1996 by Jason Thorpe. + * + * 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 immediately at the beginning of the file, without modification, + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Definitions for the TurboLaser System Bus found on + * AlphaServer 8200/8400 systems. + */ + +enum tlsb_device_instvars { + TLSB_IVAR_NODE, + TLSB_IVAR_DTYPE, + TLSB_IVAR_SWREV, + TLSB_IVAR_HWREV +}; + +/* + * Simplified accessors for turbolaser devices + */ + +#define TLSB_ACCESSOR(A, B, T) \ + \ +static __inline T tlsb_get_ ## A(device_t dev) \ +{ \ + u_long v; \ + bus_read_ivar(device_get_parent(dev), dev, TLSB_IVAR_ ## B, &v); \ + return v; \ +} + +TLSB_ACCESSOR(node, NODE, int) +TLSB_ACCESSOR(dtype, DTYPE, u_int16_t) +TLSB_ACCESSOR(hwrev, HWREV, u_int8_t) +TLSB_ACCESSOR(swrev, SWREV, u_int8_t) + +/* + * Bus-dependent structure for CPUs. This is dynamically allocated + * for each CPU on the TurboLaser, and glued into the cpu_softc + * as sc_busdep (when there is a cpu_softc to do this to). + */ +struct tlsb_cpu_busdep { + u_int8_t tcpu_vid; /* virtual ID of CPU */ + int tcpu_node; /* TurboLaser node */ +}; diff --git a/sys/alpha/tlsb/zs_tlsb.c b/sys/alpha/tlsb/zs_tlsb.c new file mode 100644 index 0000000..8532ed3 --- /dev/null +++ b/sys/alpha/tlsb/zs_tlsb.c @@ -0,0 +1,473 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ +/* + * This driver is a hopeless hack to get the SimOS console working. A real + * driver would use the zs driver source from NetBSD. + */ + +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/ucred.h> +#include <machine/cons.h> +#include <machine/clock.h> + +#include <alpha/tlsb/gbusvar.h> +#include <alpha/tlsb/tlsbreg.h> /* XXX */ +#include <alpha/tlsb/zsreg.h> + +#define KV(_addr) ((caddr_t)ALPHA_PHYS_TO_K0SEG((_addr))) + +static int zsc_get_channel(device_t dev); +static caddr_t zsc_get_base(device_t dev); + +struct zs_softc { + struct tty tty; + int channel; + caddr_t base; +}; +#define ZS_SOFTC(unit) \ + ((struct zs_softc*)devclass_get_softc(zs_devclass, (unit))) + +static d_open_t zsopen; +static d_close_t zsclose; +static d_read_t zsread; +static d_write_t zswrite; +static d_ioctl_t zsioctl; +static d_stop_t zsstop; +static d_devtotty_t zsdevtotty; + +#define CDEV_MAJOR 97 +static struct cdevsw zs_cdevsw = { + zsopen, zsclose, zsread, zswrite, + zsioctl, zsstop, noreset, zsdevtotty, + ttpoll, nommap, NULL, "zs", + NULL, -1, +}; + +static void zsstart __P((struct tty *)); +static int zsparam __P((struct tty *, struct termios *)); + +/* + * Helpers for console support. + */ + +static int zs_cngetc __P((dev_t)); +static void zs_cnputc __P((dev_t, int)); +static void zs_cnpollc __P((dev_t, int)); + +struct consdev zs_cons = { + NULL, NULL, zs_cngetc, NULL, zs_cnputc, + NULL, makedev(CDEV_MAJOR, 0), CN_NORMAL, +}; + +static caddr_t zs_console_addr; +static int zs_console; + +static int zs_probe(bus_t, device_t); +static int zs_attach(bus_t, device_t); + +static devclass_t zs_devclass; +static devclass_t zsc_devclass; + +driver_t zs_driver = { + "zs", + zs_probe, + zs_attach, + NULL, + NULL, + DRIVER_TYPE_MISC, + sizeof(struct zs_softc), + NULL, +}; + +static int +zs_probe(bus_t bus, device_t dev) +{ + return 0; +} + +static int +zs_attach(bus_t bus, device_t dev) +{ + struct zs_softc *sc = device_get_softc(dev); + + sc->channel = zsc_get_channel(dev); + sc->base = zsc_get_base(dev); + + return 0; +} + +static int +zs_get_status(caddr_t base) +{ + return (*(u_int32_t*) (base + ZSC_STATUS)) & 0xff; +} + +static void +zs_put_status(caddr_t base, int v) +{ + *(u_int32_t*) (base + ZSC_STATUS) = v; + alpha_mb(); +} + +static int +zs_get_rr3(caddr_t base) +{ + zs_put_status(base, 3); + return zs_get_status(base); +} + +static int +zs_get_data(caddr_t base) +{ + return (*(u_int32_t*) (base + ZSC_DATA)) & 0xff; +} + +static void +zs_put_data(caddr_t base, int v) +{ + *(u_int32_t*) (base + ZSC_DATA) = v; + alpha_mb(); +} + +static int +zs_getc(caddr_t base) +{ + while (!(zs_get_status(base) & 1)) + DELAY(5); + return zs_get_data(base); +} + +static void +zs_putc(caddr_t base, int c) +{ + while (!(zs_get_status(base) & 4)) + DELAY(5); + zs_put_data(base, c); +} + +extern struct consdev* cn_tab; + +int +zs_cnattach(vm_offset_t base, vm_offset_t offset) +{ + zs_console_addr = (caddr_t) ALPHA_PHYS_TO_K0SEG(base + offset); + zs_console = 1; + + cn_tab = &zs_cons; + return 0; +} + +static int +zs_cngetc(dev_t dev) +{ + int s = spltty(); + int c = zs_getc(zs_console_addr); + splx(s); + return c; +} + +static void +zs_cnputc(dev_t dev, int c) +{ + int s = spltty(); + zs_putc(zs_console_addr, c); + splx(s); +} + +static void +zs_cnpollc(dev_t dev, int onoff) +{ +} + + +static int +zsopen(dev_t dev, int flag, int mode, struct proc *p) +{ + struct zs_softc* sc = ZS_SOFTC(minor(dev)); + struct tty *tp; + int s; + int error = 0; + + if (!sc) + return ENXIO; + + s = spltty(); + + tp = &sc->tty; + + tp->t_oproc = zsstart; + tp->t_param = zsparam; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_CARR_ON; + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG|CLOCAL; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = 9600; + ttsetwater(tp); + } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) { + splx(s); + return EBUSY; + } + + splx(s); + + error = (*linesw[tp->t_line].l_open)(dev, tp); + + return error; +} + +static int +zsclose(dev_t dev, int flag, int mode, struct proc *p) +{ + struct tty *tp = &ZS_SOFTC(minor(dev))->tty; + + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + return 0; +} + +static int +zsread(dev_t dev, struct uio *uio, int flag) +{ + struct tty *tp = &ZS_SOFTC(minor(dev))->tty; + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +static int +zswrite(dev_t dev, struct uio *uio, int flag) +{ + struct tty *tp = &ZS_SOFTC(minor(dev))->tty; + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +static int +zsioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct tty *tp = &ZS_SOFTC(minor(dev))->tty; + int error; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error != ENOIOCTL) + return error; + error = ttioctl(tp, cmd, data, flag); + if (error != ENOIOCTL) + return error; + + return ENOTTY; +} + +static int +zsparam(struct tty *tp, struct termios *t) +{ + + return 0; +} + +static void +zsstart(struct tty *tp) +{ + struct zs_softc* sc = (struct zs_softc*) tp; + int s; + + s = spltty(); + + if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { + ttwwakeup(tp); + splx(s); + return; + } + + tp->t_state |= TS_BUSY; + while (tp->t_outq.c_cc != 0) + zs_putc(sc->base, getc(&tp->t_outq)); + tp->t_state &= ~TS_BUSY; + + ttwwakeup(tp); + splx(s); +} + +/* + * Stop output on a line. + */ +static void +zsstop(struct tty *tp, int flag) +{ + int s; + + s = spltty(); + if (tp->t_state & TS_BUSY) + if ((tp->t_state & TS_TTSTOP) == 0) + tp->t_state |= TS_FLUSH; + splx(s); +} + +static struct tty * +zsdevtotty(dev_t dev) +{ + struct zs_softc* sc = ZS_SOFTC(minor(dev)); + if (!sc) + return (NULL); + return (&sc->tty); +} + +CDEV_DRIVER_MODULE(zs, zsc, zs_driver, zs_devclass, + CDEV_MAJOR, zs_cdevsw, 0, 0); + +/* + * The zsc bus holds two zs devices, one for channel A, one for channel B. + */ + +struct zsc_softc { + struct bus bus; + caddr_t base; + struct zs_softc* sc_a; + struct zs_softc* sc_b; +}; + +static driver_probe_t zsc_tlsb_probe; +static driver_attach_t zsc_tlsb_attach; +static driver_intr_t zsc_tlsb_intr; +static bus_print_device_t zsc_tlsb_print_device; + +driver_t zsc_tlsb_driver = { + "zsc", + zsc_tlsb_probe, + zsc_tlsb_attach, + NULL, + NULL, + DRIVER_TYPE_MISC, + sizeof(struct zsc_softc), + NULL, +}; + + +static bus_ops_t zsc_tlsb_ops = { + zsc_tlsb_print_device, + null_read_ivar, + null_write_ivar, + null_map_intr, +}; + +static int +zsc_get_channel(device_t dev) +{ + return (long) device_get_ivars(dev); +} + +static caddr_t +zsc_get_base(device_t dev) +{ + device_t busdev = bus_get_device(device_get_parent(dev)); + struct zsc_softc* sc = device_get_softc(busdev); + return sc->base; +} + +static void +zsc_tlsb_print_device(bus_t bus, device_t dev) +{ + device_t busdev = bus_get_device(bus); + + printf(" at %s%d channel %c", + device_get_name(busdev), device_get_unit(busdev), + 'A' + (device_get_unit(dev) & 1)); +} + +static int +zsc_tlsb_probe(bus_t parent, device_t dev) +{ + struct zsc_softc* sc = device_get_softc(dev); + + device_set_desc(dev, "Z8530 uart"); + + bus_init(&sc->bus, dev, &zsc_tlsb_ops); + + sc->base = (caddr_t) ALPHA_PHYS_TO_K0SEG(TLSB_GBUS_BASE + + gbus_get_offset(dev)); + + /* + * Add channel A for now. + */ + bus_add_device(&sc->bus, "zs", -1, (void*) 0); + + return 0; +} + +static int +zsc_tlsb_attach(bus_t parent, device_t dev) +{ + struct zsc_softc* sc = device_get_softc(dev); + + bus_generic_attach(parent, dev); + + /* XXX */ + sc->sc_a = ZS_SOFTC(0); + + bus_map_intr(parent, dev, zsc_tlsb_intr, sc); + + return 0; +} + + +static void +zsc_tlsb_intr(void* arg) +{ + struct zsc_softc* sc = arg; + caddr_t base = sc->base; + + /* XXX only allow for zs0 at zsc0 */ + int rr3 = zs_get_rr3(base); + if (rr3 & 0x20) { + struct tty* tp = &sc->sc_a->tty; + int c; + + while (zs_get_status(base) & 1) { + c = zs_get_data(base); +#ifdef DDB + if (c == CTRL('\\')) + Debugger("manual escape to debugger"); +#endif + if (tp->t_state & TS_ISOPEN) + (*linesw[tp->t_line].l_rint)(c, tp); + DELAY(5); + } + } +} + +DRIVER_MODULE(zsc_tlsb, gbus, zsc_tlsb_driver, zsc_devclass, 0, 0); diff --git a/sys/alpha/tlsb/zsreg.h b/sys/alpha/tlsb/zsreg.h new file mode 100644 index 0000000..68e567d --- /dev/null +++ b/sys/alpha/tlsb/zsreg.h @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#define ZSC_STATUS 0x80 +#define ZSC_DATA 0xc0 diff --git a/sys/conf/Makefile.alpha b/sys/conf/Makefile.alpha new file mode 100644 index 0000000..ecc9daa --- /dev/null +++ b/sys/conf/Makefile.alpha @@ -0,0 +1,272 @@ +# Makefile.alpha -- with config changes. +# Copyright 1990 W. Jolitz +# from: @(#)Makefile.alpha 7.1 5/10/91 +# $Id: Makefile.alpha,v 1.109 1998/04/17 07:51:36 dima Exp $ +# +# Makefile for FreeBSD +# +# This makefile is constructed from a machine description: +# config machineid +# Most changes should be made in the machine description +# /sys/alpha/conf/``machineid'' +# after which you should do +# config machineid +# Generic makefile changes should be made in +# /sys/alpha/conf/Makefile.alpha +# after which config should be rerun for all machines. +# + +# Which version of config(8) is required. +%VERSREQ= 300003 + +BINFORMAT?= elf + +STD8X16FONT?= iso + +.if exists(./@/.) +S= ./@ +.else +S= ../.. +.endif +ALPHA= ${S}/alpha + +COPTFLAGS?=-O +INCLUDES= -nostdinc -I- -I. -I$S +# This hack is to allow kernel compiles to succeed on machines w/out srcdist +.if exists($S/../include) +INCLUDES+= -I$S/../include +.else +INCLUDES+= -I/usr/include +.endif +COPTS= ${INCLUDES} ${IDENT} -DKERNEL -include opt_global.h +CFLAGS= ${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS} -mno-fp-regs +LOAD_ADDRESS?= 0xfffffc0000230000 +DEFINED_PROF= ${PROF} +.if defined(PROF) +CFLAGS+= -malign-functions=4 +.if ${PROFLEVEL} >= 2 +IDENT+= -DGPROF4 -DGUPROF +PROF+= -mprofiler-epilogue +.endif +.endif + +NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $< +NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< +# XXX LOCORE means "don't declare C stuff" not "for locore.s". +NORMAL_S= ${CC} -c -x assembler-with-cpp -DLOCORE ${COPTS} $< +DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $< +DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< +DRIVER_S= ${CC} -c -x assembler-with-cpp -DLOCORE ${COPTS} $< +PROFILE_C= ${CC} -c ${CFLAGS} ${PARAM} $< + +# ${ALPHA}/alpha/setdef0.c and ${ALPHA}/alpha/setdef1.c are intentionally +# omitted from SYSTEM_CFILES. They depend on setdefs.h, a header which +# is generated from all of ${OBJS}. We don't want to have to compile +# everything just to do a make depend. +SYSTEM_CFILES= ioconf.c param.c vnode_if.c config.c +SYSTEM_SFILES= ${ALPHA}/alpha/locore.s +SYSTEM_DEP= Makefile symbols.exclude symbols.sort ${SYSTEM_OBJS} +.if ${CFLAGS:M-g} == "" +SYMORDER_EXCLUDE=-x symbols.exclude +.endif +SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ +.if ${BINFORMAT} == elf +SYSTEM_OBJS= locore.o setdef0.o vnode_if.o ${OBJS} ioconf.o param.o config.o \ + setdef1.o +SYSTEM_LD= @${LD} -Bstatic -N -Ttext ${LOAD_ADDRESS} -e locorestart -defsym _DYNAMIC=0 \ + -o $@ -X ${SYSTEM_OBJS} vers.o +SYSTEM_LD_TAIL= @size $@; chmod 755 $@ +.endif + +%BEFORE_DEPEND + +%OBJS + +%CFILES + +%SFILES + +%LOAD + +%CLEAN + +clean: + rm -f *.o *.s eddep errs genassym gensetdefs kernel linterrs \ + makelinks param.c setdefs.h symbols.exclude symbols.sort tags \ + vers.c vnode_if.c vnode_if.h ${CLEAN} + +#lint: /tmp param.c +# @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \ +# ${ALPHA}/alpha/Locore.c ${CFILES} ioconf.c param.c | \ +# grep -v 'struct/union .* never defined' | \ +# grep -v 'possible pointer alignment problem' + +symbols.exclude: Makefile + echo "gcc2_compiled." >symbols.exclude + echo "___gnu_compiled_c" >>symbols.exclude + +symbols.sort: ${ALPHA}/alpha/symbols.raw + grep -v '^#' ${ALPHA}/alpha/symbols.raw \ + | sed 's/^ //' | sort -u > symbols.sort + +locore.o: ${ALPHA}/alpha/locore.s assym.s + ${NORMAL_S} + +setdef0.o: ${ALPHA}/alpha/setdef0.c setdefs.h + ${NORMAL_C} + +setdef1.o: ${ALPHA}/alpha/setdef1.c setdefs.h + ${NORMAL_C} + +setdefs.h: gensetdefs ${OBJS} + @echo Generating kernel linker sets + @./gensetdefs ${OBJS} >setdefs.h + +gensetdefs: gensetdefs.o + ${CC} ${CFLAGS} gensetdefs.o -o $@ + +gensetdefs.o: ${ALPHA}/alpha/gensetdefs.c + ${CC} -c ${CFLAGS} ${ALPHA}/alpha/gensetdefs.c + +# everything potentially depends on the Makefile since everything potentially +# depends on the options. Some things are more dependent on the Makefile for +# historical reasons. +machdep.o: Makefile + +# the following is necessary because autoconf.o depends on #if GENERIC +autoconf.o: Makefile + +# XXX - may no longer be needed +locore.o: Makefile + +# depends on KDB (cons.o also depends on GENERIC) +trap.o cons.o: Makefile + +# this rule stops ./assym.s in .depend from causing problems +./assym.s: assym.s + +assym.s: genassym + ./genassym >assym.s + +# Some of the defines that genassym outputs may well depend on the +# value of kernel options. +genassym.o: ${ALPHA}/alpha/genassym.c Makefile opt_global.h + ${CC} -c ${CFLAGS} ${PARAM} -UKERNEL ${ALPHA}/alpha/genassym.c + +genassym: genassym.o + ${CC} ${CFLAGS} ${PARAM} genassym.o -o $@ + +SYSTEM_OBJS+= __divqu.o __divq.o __divlu.o __divl.o +SYSTEM_OBJS+= __remqu.o __remq.o __remlu.o __reml.o +CLEAN+= __divqu.S __divq.S __divlu.S __divl.S +CLEAN+= __remqu.S __remq.S __remlu.S __reml.S + +__divqu.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divqu')define(OP,\`div')define(S,\`false')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__divq.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divq')define(OP,\`div')define(S,\`true')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__divlu.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divlu')define(OP,\`div')define(S,\`false')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__divl.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divl')define(OP,\`div')define(S,\`true')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__remqu.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__remqu')define(OP,\`rem')define(S,\`false')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__remq.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__remq')define(OP,\`rem')define(S,\`true')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__remlu.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__remlu')define(OP,\`rem')define(S,\`false')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + +__reml.S: ${S}/alpha/alpha/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__reml')define(OP,\`rem')define(S,\`true')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | m4 > ${.TARGET} + + +${OBJS}: opt_global.h + +# XXX this assumes that the options for NORMAL_C* and DRIVER_C* are identical. +depend: assym.s param.c vnode_if.h ${BEFORE_DEPEND} + rm -f .newdep + mkdep -a -f .newdep ${COPTS} ${CFILES} ${SYSTEM_CFILES} + mkdep -a -f .newdep ${COPTS} ${PARAM} -UKERNEL ${ALPHA}/alpha/genassym.c + MKDEP_CPP="${CC} -E -x assembler-with-cpp" ; export MKDEP_CPP ; \ + mkdep -a -f .newdep -DLOCORE ${COPTS} ${SFILES} ${SYSTEM_SFILES} + rm -f .depend + mv -f .newdep .depend + +cleandepend: + rm -f .depend + +links: + egrep '#if' ${CFILES:Nswapkernel.c} | sed -f $S/conf/defines | \ + sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink + echo ${CFILES:Nswapkernel.c} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ + sort -u | comm -23 - dontlink | \ + sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks + sh makelinks && rm -f dontlink + +tags: + @echo "see $S/kern/Makefile for tags" + +install: + @if [ ! -f kernel ] ; then \ + echo "You must first build your kernel before trying to install." ; \ + exit 1 ; \ + fi +.if exists(${DESTDIR}/kernel) + chflags noschg ${DESTDIR}/kernel + mv ${DESTDIR}/kernel ${DESTDIR}/kernel.old +.endif + PATH=$${PATH}:/sbin:/usr/sbin; \ + if [ `sysctl -n kern.bootfile` = ${DESTDIR}/kernel ] ; then \ + sysctl -w kern.bootfile=${DESTDIR}/kernel.old ; \ + if [ -f /var/db/kvm_kernel.db ] ; then \ + mv -f /var/db/kvm_kernel.db /var/db/kvm_kernel.old.db ; \ + fi \ + fi + install -c -m 555 -o root -g wheel -fschg kernel ${DESTDIR}/ + +ioconf.o: ioconf.c $S/sys/param.h $S/sys/buf.h + ${CC} -c ${CFLAGS} ioconf.c + +param.c: $S/conf/param.c + -rm -f param.c + cp $S/conf/param.c . + +param.o: param.c Makefile + ${CC} -c ${CFLAGS} ${PARAM} param.c + +vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} + sh $S/conf/newvers.sh ${KERN_IDENT} ${IDENT} + ${CC} ${CFLAGS} -c vers.c + +vnode_if.c: $S/kern/vnode_if.sh $S/kern/vnode_if.src + sh $S/kern/vnode_if.sh $S/kern/vnode_if.src +vnode_if.h: $S/kern/vnode_if.sh $S/kern/vnode_if.src + sh $S/kern/vnode_if.sh $S/kern/vnode_if.src + +.include <bsd.kern.mk> + +%RULES + +# DO NOT DELETE THIS LINE -- make depend uses it diff --git a/sys/conf/files b/sys/conf/files index 74e8553..bc9694b 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,6 +1,6 @@ aicasm optional ahc device-driver \ dependency "$S/dev/aic7xxx/*.[chyl]" \ - compile-with "make -f $S/dev/aic7xxx/Makefile MAKESRCPATH=$S/dev/aic7xxx" \ + compile-with "${MAKE} -f $S/dev/aic7xxx/Makefile MAKESRCPATH=$S/dev/aic7xxx" \ no-obj no-implicit-rule \ clean "aicasm" # @@ -86,7 +86,7 @@ kern/inflate.c optional gzip kern/init_main.c standard kern/init_sysent.c standard kern/init_sysvec.c standard -kern/kern_intr.c standard +#kern/kern_intr.c standard kern/kern_module.c standard kern/kern_linker.c standard kern/link_aout.c standard @@ -403,6 +403,7 @@ pci/pci_compat.c optional pci pci/pcisupport.c optional pci pci/tek390.c optional amd device-driver pci/wdc_p.c optional wdc device-driver +pci/simos.c optional simos device-driver pci/xrpu.c optional xrpu device-driver posix4/posix4_mib.c standard posix4/p1003_1b.c standard diff --git a/sys/conf/files.alpha b/sys/conf/files.alpha new file mode 100644 index 0000000..04e5410 --- /dev/null +++ b/sys/conf/files.alpha @@ -0,0 +1,80 @@ +# This file tells config what files go into building a kernel, +# files marked standard are always included. +# +# $Id$ +# +# The long compile-with and dependency lines are required because of +# limitations in config: backslash-newline doesn't work in strings, and +# dependency lines other than the first are silently ignored. +# +# +font8x16.o optional std8x16font \ + compile-with "uudecode < /usr/share/syscons/fonts/${STD8X16FONT}-8x16.fnt && file2c 'unsigned char font_16[16*256] = {' '};' < ${STD8X16FONT}-8x16 > font8x16.c && ${CC} -c ${CFLAGS} font8x16.c" \ + no-implicit-rule before-depend \ + clean "${STD8X16FONT}-8x16 font8x16.c" + +# +alpha/alpha/autoconf.c standard device-driver +alpha/alpha/cpuconf.c standard +alpha/alpha/dec_kn8ae.c optional dec_kn8ae +alpha/alpha/mountroot.c optional slice +alpha/alpha/ipl_funcs.c standard +alpha/alpha/pal.s standard +alpha/alpha/cons.c standard +alpha/alpha/prom.c standard +alpha/alpha/prom_disp.s standard +alpha/alpha/db_disasm.c optional ddb +alpha/alpha/db_interface.c optional ddb +alpha/alpha/db_trace.c optional ddb +alpha/alpha/exception.s standard +alpha/alpha/in_cksum.c optional inet +# locore.s needs to be handled in Makefile to put it first. Otherwise it's +# now normal. +# alpha/alpha/locore.s standard +alpha/alpha/machdep.c standard +alpha/alpha/math_emulate.c optional math_emulate +alpha/alpha/mem.c standard +alpha/alpha/mp_machdep.c optional smp +alpha/alpha/perfmon.c optional perfmon profiling-routine +alpha/alpha/perfmon.c optional perfmon +alpha/alpha/pmap.c standard +alpha/alpha/procfs_machdep.c standard +alpha/alpha/simplelock.s optional smp +alpha/alpha/support.s standard +alpha/alpha/swtch.s standard +alpha/alpha/sys_machdep.c standard +alpha/alpha/trap.c standard +alpha/alpha/interrupt.c standard +alpha/alpha/userconfig.c optional userconfig +alpha/alpha/vm_machdep.c standard +alpha/alpha/clock.c standard +alpha/alpha/diskslice_machdep.c standard +alpha/tlsb/tlsb.c optional tlsb +alpha/tlsb/gbus.c optional gbus +alpha/tlsb/kftxx.c optional kft +alpha/tlsb/mcclock_tlsb.c optional gbus +alpha/tlsb/zs_tlsb.c optional gbus +alpha/tlsb/dwlpx.c optional dwlpx +dev/dec/mcclock.c optional gbus +alpha/pci/pcibus.c optional pci +kern/subr_bus.c standard +libkern/bcd.c standard +libkern/bcmp.c standard +libkern/ffs.c standard +libkern/inet_ntoa.c standard +libkern/index.c standard +libkern/mcount.c optional profiling-routine +libkern/qsort.c standard +libkern/random.c standard +libkern/scanc.c standard +libkern/skpc.c standard +libkern/strcat.c standard +libkern/strcmp.c standard +libkern/strcpy.c standard +libkern/strlen.c standard +libkern/strncmp.c standard +libkern/strncpy.c standard +libkern/alpha/htonl.S standard +libkern/alpha/htons.S standard +libkern/alpha/ntohl.S standard +libkern/alpha/ntohs.S standard diff --git a/sys/conf/options.alpha b/sys/conf/options.alpha new file mode 100644 index 0000000..666e7f7 --- /dev/null +++ b/sys/conf/options.alpha @@ -0,0 +1,18 @@ +# $Id$ + +EV5 opt_global.h +DEC_KN8AE opt_cpu.h + +ATAPI opt_atapi.h +ATAPI_STATIC opt_atapi.h + +CMD640 opt_wd.h + +SHOW_BUSYBUFS +PANIC_REBOOT_WAIT_TIME opt_panic.h + +AHC_TAGENABLE opt_aic7xxx.h +AHC_SCBPAGING_ENABLE opt_aic7xxx.h +AHC_ALLOW_MEMIO opt_aic7xxx.h +AHC_SHARE_SCBS opt_aic7xxx.h + diff --git a/sys/ddb/db_examine.c b/sys/ddb/db_examine.c index a848ac7..0853891 100644 --- a/sys/ddb/db_examine.c +++ b/sys/ddb/db_examine.c @@ -23,7 +23,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: db_examine.c,v 1.18 1998/06/07 17:09:37 dfr Exp $ + * $Id: db_examine.c,v 1.19 1998/06/08 08:43:19 dfr Exp $ */ /* @@ -257,7 +257,7 @@ db_search_cmd(dummy1, dummy2, dummy3, dummy4) int size; db_expr_t value; db_expr_t mask; - unsigned int count; + db_expr_t count; t = db_read_token(); if (t == tSLASH) { diff --git a/sys/ddb/db_print.c b/sys/ddb/db_print.c index 114cf00..7840496 100644 --- a/sys/ddb/db_print.c +++ b/sys/ddb/db_print.c @@ -23,7 +23,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: db_print.c,v 1.18 1998/06/07 17:09:37 dfr Exp $ + * $Id: db_print.c,v 1.19 1998/06/08 02:15:37 bde Exp $ */ /* @@ -53,7 +53,7 @@ db_show_regs(dummy1, dummy2, dummy3, dummy4) for (regp = db_regs; regp < db_eregs; regp++) { db_read_variable(regp, &value); - db_printf("%-12s%#10n", regp->name, value); + db_printf("%-12s%#10ln", regp->name, value); db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset); if (name != 0 && offset <= db_maxoff && offset != value) { db_printf("\t%s", name); diff --git a/sys/ddb/db_sym.c b/sys/ddb/db_sym.c index 40f3651..5caf478 100644 --- a/sys/ddb/db_sym.c +++ b/sys/ddb/db_sym.c @@ -23,7 +23,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: db_sym.c,v 1.20 1997/06/30 23:54:49 bde Exp $ + * $Id: db_sym.c,v 1.21 1998/06/07 17:09:38 dfr Exp $ */ /* @@ -300,11 +300,11 @@ db_printsym(off, strategy) if (name == 0) value = off; if (value >= DB_SMALL_VALUE_MIN && value <= DB_SMALL_VALUE_MAX) { - db_printf("%+#n", off); + db_printf("%+#ln", off); return; } if (name == 0 || d >= db_maxoff) { - db_printf("%#n", off); + db_printf("%#ln", off); return; } db_printf("%s", name); diff --git a/sys/dev/dec/clockvar.h b/sys/dev/dec/clockvar.h new file mode 100644 index 0000000..920d162 --- /dev/null +++ b/sys/dev/dec/clockvar.h @@ -0,0 +1,62 @@ +/* $NetBSD: clockvar.h,v 1.4 1997/06/22 08:02:18 jonathan Exp $ */ + +/* + * Copyright (c) 1994, 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Definitions for cpu-independent clock handling for the alpha and pmax. + */ + +/* + * clocktime structure: + * + * structure passed to TOY clocks when setting them. broken out this + * way, so that the time_t -> field conversion can be shared. + */ +struct clocktime { + int year; /* year - 1900 */ + int mon; /* month (1 - 12) */ + int day; /* day (1 - 31) */ + int hour; /* hour (0 - 23) */ + int min; /* minute (0 - 59) */ + int sec; /* second (0 - 59) */ + int dow; /* day of week (0 - 6; 0 = Sunday) */ +}; + +/* + * clockfns structure: + * + * function switch used by chip-independent clock code, to access + * chip-dependent routines. + */ +struct clockfns { + void (*cf_init) __P((struct device *)); + void (*cf_get) __P((struct device *, time_t, struct clocktime *)); + void (*cf_set) __P((struct device *, struct clocktime *)); +}; + +void clockattach __P((device_t, const struct clockfns *)); diff --git a/sys/dev/dec/mc146818reg.h b/sys/dev/dec/mc146818reg.h new file mode 100644 index 0000000..95c3ccf --- /dev/null +++ b/sys/dev/dec/mc146818reg.h @@ -0,0 +1,194 @@ +/* $NetBSD: mc146818reg.h,v 1.2 1997/03/12 06:53:42 cgd Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Definitions for the Motorola MC146818A Real Time Clock. + * They also apply for the (compatible) Dallas Semicontuctor DS1287A RTC. + * + * Though there are undoubtedly other (better) sources, this material was + * culled from the DEC "KN121 System Module Programmer's Reference + * Information." + * + * The MC146818A has 16 registers. The first 10 contain time-of-year + * and alarm data. The rest contain various control and status bits. + * + * To read or write the registers, one writes the register number to + * the RTC's control port, then either reads from or writes the new + * data to the RTC's data port. Since the locations of these ports + * and the method used to access them can be machine-dependent, the + * low-level details of reading and writing the RTC's registers are + * handled by machine-specific functions. + * + * The time-of-year and alarm data can be expressed in either binary + * or BCD, and they are selected by a bit in register B. + * + * The "hour" time-of-year and alarm fields can either be expressed in + * AM/PM format, or in 24-hour format. If AM/PM format is chosen, the + * hour fields can have the values: 1-12 and 81-92 (the latter being + * PM). If the 24-hour format is chosen, they can have the values + * 0-24. The hour format is selectable by a bit in register B. + * (XXX IS AM/PM MODE DESCRIPTION CORRECT?) + * + * It is assumed the if systems are going to use BCD (rather than + * binary) mode, or AM/PM hour format, they'll do the appropriate + * conversions in machine-dependent code. Also, if the clock is + * switched between BCD and binary mode, or between AM/PM mode and + * 24-hour mode, the time-of-day and alarm registers are NOT + * automatically reset; they must be reprogrammed with correct values. + */ + +/* + * The registers, and the bits within each register. + */ + +#define MC_SEC 0x0 /* Time of year: seconds (0-59) */ +#define MC_ASEC 0x1 /* Alarm: seconds */ +#define MC_MIN 0x2 /* Time of year: minutes (0-59) */ +#define MC_AMIN 0x3 /* Alarm: minutes */ +#define MC_HOUR 0x4 /* Time of year: hour (see above) */ +#define MC_AHOUR 0x5 /* Alarm: hour */ +#define MC_DOW 0x6 /* Time of year: day of week (1-7) */ +#define MC_DOM 0x7 /* Time of year: day of month (1-31) */ +#define MC_MONTH 0x8 /* Time of year: month (1-12) */ +#define MC_YEAR 0x9 /* Time of year: year in century (0-99) */ + +#define MC_REGA 0xa /* Control register A */ + +#define MC_REGA_RSMASK 0x0f /* Interrupt rate select mask (see below) */ +#define MC_REGA_DVMASK 0x70 /* Divisor select mask (see below) */ +#define MC_REGA_UIP 0x80 /* Update in progress; read only. */ + +#define MC_REGB 0xb /* Control register B */ + +#define MC_REGB_DSE 0x01 /* Daylight Savings Enable */ +#define MC_REGB_24HR 0x02 /* 24-hour mode (AM/PM mode when clear) */ +#define MC_REGB_BINARY 0x04 /* Binary mode (BCD mode when clear) */ +#define MC_REGB_SQWE 0x08 /* Square Wave Enable */ +#define MC_REGB_UIE 0x10 /* Update End interrupt enable */ +#define MC_REGB_AIE 0x20 /* Alarm interrupt enable */ +#define MC_REGB_PIE 0x40 /* Periodic interrupt enable */ +#define MC_REGB_SET 0x80 /* Allow time to be set; stops updates */ + +#define MC_REGC 0xc /* Control register C */ + +/* MC_REGC_UNUSED 0x0f UNUSED */ +#define MC_REGC_UF 0x10 /* Update End interrupt flag */ +#define MC_REGC_AF 0x20 /* Alarm interrupt flag */ +#define MC_REGC_PF 0x40 /* Periodic interrupt flag */ +#define MC_REGC_IRQF 0x80 /* Interrupt request pending flag */ + +#define MC_REGD 0xd /* Control register D */ + +/* MC_REGD_UNUSED 0x7f UNUSED */ +#define MC_REGD_VRT 0x80 /* Valid RAM and Time bit */ + + +#define MC_NREGS 0xe /* 14 registers; CMOS follows */ +#define MC_NTODREGS 0xa /* 10 of those regs are for TOD and alarm */ + +#define MC_NVRAM_START 0xe /* start of NVRAM: offset 14 */ +#define MC_NVRAM_SIZE 50 /* 50 bytes of NVRAM */ + +/* + * Periodic Interrupt Rate Select constants (Control register A) + */ +#define MC_RATE_NONE 0x0 /* No periodic interrupt */ +#define MC_RATE_1 0x1 /* 256 Hz if MC_BASE_32_KHz, else 32768 Hz */ +#define MC_RATE_2 0x2 /* 128 Hz if MC_BASE_32_KHz, else 16384 Hz */ +#define MC_RATE_8192_Hz 0x3 /* 122.070 us period */ +#define MC_RATE_4096_Hz 0x4 /* 244.141 us period */ +#define MC_RATE_2048_Hz 0x5 /* 488.281 us period */ +#define MC_RATE_1024_Hz 0x6 /* 976.562 us period */ +#define MC_RATE_512_Hz 0x7 /* 1.953125 ms period */ +#define MC_RATE_256_Hz 0x8 /* 3.90625 ms period */ +#define MC_RATE_128_Hz 0x9 /* 7.8125 ms period */ +#define MC_RATE_64_Hz 0xa /* 15.625 ms period */ +#define MC_RATE_32_Hz 0xb /* 31.25 ms period */ +#define MC_RATE_16_Hz 0xc /* 62.5 ms period */ +#define MC_RATE_8_Hz 0xd /* 125 ms period */ +#define MC_RATE_4_Hz 0xe /* 250 ms period */ +#define MC_RATE_2_Hz 0xf /* 500 ms period */ + +/* + * Time base (divisor select) constants (Control register A) + */ +#define MC_BASE_4_MHz 0x00 /* 4MHz crystal */ +#define MC_BASE_1_MHz 0x10 /* 1MHz crystal */ +#define MC_BASE_32_KHz 0x20 /* 32KHz crystal */ +#define MC_BASE_NONE 0x60 /* actually, both of these reset */ +#define MC_BASE_RESET 0x70 + + +/* + * RTC register/NVRAM read and write functions -- machine-dependent. + * Appropriately manipulate RTC registers to get/put data values. + */ +u_int mc146818_read __P((void *sc, u_int reg)); +void mc146818_write __P((void *sc, u_int reg, u_int datum)); + +/* + * A collection of TOD/Alarm registers. + */ +typedef u_int mc_todregs[MC_NTODREGS]; + +/* + * Get all of the TOD/Alarm registers + * Must be called at splhigh(), and with the RTC properly set up. + */ +#define MC146818_GETTOD(sc, regs) \ + do { \ + int i; \ + \ + /* update in progress; spin loop */ \ + while (mc146818_read(sc, MC_REGA) & MC_REGA_UIP) \ + ; \ + \ + /* read all of the tod/alarm regs */ \ + for (i = 0; i < MC_NTODREGS; i++) \ + (*regs)[i] = mc146818_read(sc, i); \ + } while (0); + +/* + * Set all of the TOD/Alarm registers + * Must be called at splhigh(), and with the RTC properly set up. + */ +#define MC146818_PUTTOD(sc, regs) \ + do { \ + int i; \ + \ + /* stop updates while setting */ \ + mc146818_write(sc, MC_REGB, \ + mc146818_read(sc, MC_REGB) | MC_REGB_SET); \ + \ + /* write all of the tod/alarm regs */ \ + for (i = 0; i < MC_NTODREGS; i++) \ + mc146818_write(sc, i, (*regs)[i]); \ + \ + /* reenable updates */ \ + mc146818_write(sc, MC_REGB, \ + mc146818_read(sc, MC_REGB) & ~MC_REGB_SET); \ + } while (0); diff --git a/sys/dev/dec/mcclock.c b/sys/dev/dec/mcclock.c new file mode 100644 index 0000000..76e3805 --- /dev/null +++ b/sys/dev/dec/mcclock.c @@ -0,0 +1,141 @@ +/* $Id$ */ +/* $NetBSD: mcclock.c,v 1.11 1998/04/19 07:50:25 jonathan Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <dev/dec/clockvar.h> +#include <dev/dec/mcclockvar.h> +#include <dev/dec/mc146818reg.h> + +/* + * XXX rate is machine-dependent. + */ +#ifdef __alpha__ +#define MC_DEFAULTRATE MC_RATE_1024_Hz +#endif +#ifdef __pmax__ +#define MC_DEFAULTRATE MC_RATE_256_Hz +#endif + + +void mcclock_init __P((struct device *)); +void mcclock_get __P((struct device *, time_t, struct clocktime *)); +void mcclock_set __P((struct device *, struct clocktime *)); + +const struct clockfns mcclock_clockfns = { + mcclock_init, mcclock_get, mcclock_set, +}; + +#define mc146818_write(dev, reg, datum) \ + (*(dev)->sc_busfns->mc_bf_write)(dev, reg, datum) +#define mc146818_read(dev, reg) \ + (*(dev)->sc_busfns->mc_bf_read)(dev, reg) + +void +mcclock_attach(sc, busfns) + struct mcclock_softc *sc; + const struct mcclock_busfns *busfns; +{ + sc->sc_busfns = busfns; + + /* Turn interrupts off, just in case. */ + mc146818_write(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR); + + clockattach(sc->sc_dev, &mcclock_clockfns); +} + +void +mcclock_init(dev) + device_t dev; +{ + struct mcclock_softc *sc = device_get_softc(dev); + + mc146818_write(sc, MC_REGA, MC_BASE_32_KHz | MC_DEFAULTRATE); + mc146818_write(sc, MC_REGB, + MC_REGB_PIE | MC_REGB_SQWE | MC_REGB_BINARY | MC_REGB_24HR); +} + +/* + * Get the time of day, based on the clock's value and/or the base value. + */ +void +mcclock_get(dev, base, ct) + struct device *dev; + time_t base; + struct clocktime *ct; +{ + struct mcclock_softc *sc = device_get_softc(dev); + mc_todregs regs; + int s; + + s = splclock(); + MC146818_GETTOD(sc, ®s) + splx(s); + + ct->sec = regs[MC_SEC]; + ct->min = regs[MC_MIN]; + ct->hour = regs[MC_HOUR]; + ct->dow = regs[MC_DOW]; + ct->day = regs[MC_DOM]; + ct->mon = regs[MC_MONTH]; + ct->year = regs[MC_YEAR]; +} + +/* + * Reset the TODR based on the time value. + */ +void +mcclock_set(dev, ct) + struct device *dev; + struct clocktime *ct; +{ + struct mcclock_softc *sc = device_get_softc(dev); + mc_todregs regs; + int s; + + s = splclock(); + MC146818_GETTOD(sc, ®s); + splx(s); + + regs[MC_SEC] = ct->sec; + regs[MC_MIN] = ct->min; + regs[MC_HOUR] = ct->hour; + regs[MC_DOW] = ct->dow; + regs[MC_DOM] = ct->day; + regs[MC_MONTH] = ct->mon; + regs[MC_YEAR] = ct->year; + + s = splclock(); + MC146818_PUTTOD(sc, ®s); + splx(s); +} diff --git a/sys/dev/dec/mcclockvar.h b/sys/dev/dec/mcclockvar.h new file mode 100644 index 0000000..d2c0ac8 --- /dev/null +++ b/sys/dev/dec/mcclockvar.h @@ -0,0 +1,41 @@ +/* $NetBSD: mcclockvar.h,v 1.4 1997/06/22 08:02:19 jonathan Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +struct mcclock_softc { + device_t sc_dev; + const struct mcclock_busfns *sc_busfns; +}; + +struct mcclock_busfns { + void (*mc_bf_write) __P((struct mcclock_softc *, u_int, u_int)); + u_int (*mc_bf_read) __P((struct mcclock_softc *, u_int)); +}; + +void mcclock_attach __P((struct mcclock_softc *, + const struct mcclock_busfns *)); diff --git a/sys/dev/mc146818/mc146818reg.h b/sys/dev/mc146818/mc146818reg.h new file mode 100644 index 0000000..95c3ccf --- /dev/null +++ b/sys/dev/mc146818/mc146818reg.h @@ -0,0 +1,194 @@ +/* $NetBSD: mc146818reg.h,v 1.2 1997/03/12 06:53:42 cgd Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Definitions for the Motorola MC146818A Real Time Clock. + * They also apply for the (compatible) Dallas Semicontuctor DS1287A RTC. + * + * Though there are undoubtedly other (better) sources, this material was + * culled from the DEC "KN121 System Module Programmer's Reference + * Information." + * + * The MC146818A has 16 registers. The first 10 contain time-of-year + * and alarm data. The rest contain various control and status bits. + * + * To read or write the registers, one writes the register number to + * the RTC's control port, then either reads from or writes the new + * data to the RTC's data port. Since the locations of these ports + * and the method used to access them can be machine-dependent, the + * low-level details of reading and writing the RTC's registers are + * handled by machine-specific functions. + * + * The time-of-year and alarm data can be expressed in either binary + * or BCD, and they are selected by a bit in register B. + * + * The "hour" time-of-year and alarm fields can either be expressed in + * AM/PM format, or in 24-hour format. If AM/PM format is chosen, the + * hour fields can have the values: 1-12 and 81-92 (the latter being + * PM). If the 24-hour format is chosen, they can have the values + * 0-24. The hour format is selectable by a bit in register B. + * (XXX IS AM/PM MODE DESCRIPTION CORRECT?) + * + * It is assumed the if systems are going to use BCD (rather than + * binary) mode, or AM/PM hour format, they'll do the appropriate + * conversions in machine-dependent code. Also, if the clock is + * switched between BCD and binary mode, or between AM/PM mode and + * 24-hour mode, the time-of-day and alarm registers are NOT + * automatically reset; they must be reprogrammed with correct values. + */ + +/* + * The registers, and the bits within each register. + */ + +#define MC_SEC 0x0 /* Time of year: seconds (0-59) */ +#define MC_ASEC 0x1 /* Alarm: seconds */ +#define MC_MIN 0x2 /* Time of year: minutes (0-59) */ +#define MC_AMIN 0x3 /* Alarm: minutes */ +#define MC_HOUR 0x4 /* Time of year: hour (see above) */ +#define MC_AHOUR 0x5 /* Alarm: hour */ +#define MC_DOW 0x6 /* Time of year: day of week (1-7) */ +#define MC_DOM 0x7 /* Time of year: day of month (1-31) */ +#define MC_MONTH 0x8 /* Time of year: month (1-12) */ +#define MC_YEAR 0x9 /* Time of year: year in century (0-99) */ + +#define MC_REGA 0xa /* Control register A */ + +#define MC_REGA_RSMASK 0x0f /* Interrupt rate select mask (see below) */ +#define MC_REGA_DVMASK 0x70 /* Divisor select mask (see below) */ +#define MC_REGA_UIP 0x80 /* Update in progress; read only. */ + +#define MC_REGB 0xb /* Control register B */ + +#define MC_REGB_DSE 0x01 /* Daylight Savings Enable */ +#define MC_REGB_24HR 0x02 /* 24-hour mode (AM/PM mode when clear) */ +#define MC_REGB_BINARY 0x04 /* Binary mode (BCD mode when clear) */ +#define MC_REGB_SQWE 0x08 /* Square Wave Enable */ +#define MC_REGB_UIE 0x10 /* Update End interrupt enable */ +#define MC_REGB_AIE 0x20 /* Alarm interrupt enable */ +#define MC_REGB_PIE 0x40 /* Periodic interrupt enable */ +#define MC_REGB_SET 0x80 /* Allow time to be set; stops updates */ + +#define MC_REGC 0xc /* Control register C */ + +/* MC_REGC_UNUSED 0x0f UNUSED */ +#define MC_REGC_UF 0x10 /* Update End interrupt flag */ +#define MC_REGC_AF 0x20 /* Alarm interrupt flag */ +#define MC_REGC_PF 0x40 /* Periodic interrupt flag */ +#define MC_REGC_IRQF 0x80 /* Interrupt request pending flag */ + +#define MC_REGD 0xd /* Control register D */ + +/* MC_REGD_UNUSED 0x7f UNUSED */ +#define MC_REGD_VRT 0x80 /* Valid RAM and Time bit */ + + +#define MC_NREGS 0xe /* 14 registers; CMOS follows */ +#define MC_NTODREGS 0xa /* 10 of those regs are for TOD and alarm */ + +#define MC_NVRAM_START 0xe /* start of NVRAM: offset 14 */ +#define MC_NVRAM_SIZE 50 /* 50 bytes of NVRAM */ + +/* + * Periodic Interrupt Rate Select constants (Control register A) + */ +#define MC_RATE_NONE 0x0 /* No periodic interrupt */ +#define MC_RATE_1 0x1 /* 256 Hz if MC_BASE_32_KHz, else 32768 Hz */ +#define MC_RATE_2 0x2 /* 128 Hz if MC_BASE_32_KHz, else 16384 Hz */ +#define MC_RATE_8192_Hz 0x3 /* 122.070 us period */ +#define MC_RATE_4096_Hz 0x4 /* 244.141 us period */ +#define MC_RATE_2048_Hz 0x5 /* 488.281 us period */ +#define MC_RATE_1024_Hz 0x6 /* 976.562 us period */ +#define MC_RATE_512_Hz 0x7 /* 1.953125 ms period */ +#define MC_RATE_256_Hz 0x8 /* 3.90625 ms period */ +#define MC_RATE_128_Hz 0x9 /* 7.8125 ms period */ +#define MC_RATE_64_Hz 0xa /* 15.625 ms period */ +#define MC_RATE_32_Hz 0xb /* 31.25 ms period */ +#define MC_RATE_16_Hz 0xc /* 62.5 ms period */ +#define MC_RATE_8_Hz 0xd /* 125 ms period */ +#define MC_RATE_4_Hz 0xe /* 250 ms period */ +#define MC_RATE_2_Hz 0xf /* 500 ms period */ + +/* + * Time base (divisor select) constants (Control register A) + */ +#define MC_BASE_4_MHz 0x00 /* 4MHz crystal */ +#define MC_BASE_1_MHz 0x10 /* 1MHz crystal */ +#define MC_BASE_32_KHz 0x20 /* 32KHz crystal */ +#define MC_BASE_NONE 0x60 /* actually, both of these reset */ +#define MC_BASE_RESET 0x70 + + +/* + * RTC register/NVRAM read and write functions -- machine-dependent. + * Appropriately manipulate RTC registers to get/put data values. + */ +u_int mc146818_read __P((void *sc, u_int reg)); +void mc146818_write __P((void *sc, u_int reg, u_int datum)); + +/* + * A collection of TOD/Alarm registers. + */ +typedef u_int mc_todregs[MC_NTODREGS]; + +/* + * Get all of the TOD/Alarm registers + * Must be called at splhigh(), and with the RTC properly set up. + */ +#define MC146818_GETTOD(sc, regs) \ + do { \ + int i; \ + \ + /* update in progress; spin loop */ \ + while (mc146818_read(sc, MC_REGA) & MC_REGA_UIP) \ + ; \ + \ + /* read all of the tod/alarm regs */ \ + for (i = 0; i < MC_NTODREGS; i++) \ + (*regs)[i] = mc146818_read(sc, i); \ + } while (0); + +/* + * Set all of the TOD/Alarm registers + * Must be called at splhigh(), and with the RTC properly set up. + */ +#define MC146818_PUTTOD(sc, regs) \ + do { \ + int i; \ + \ + /* stop updates while setting */ \ + mc146818_write(sc, MC_REGB, \ + mc146818_read(sc, MC_REGB) | MC_REGB_SET); \ + \ + /* write all of the tod/alarm regs */ \ + for (i = 0; i < MC_NTODREGS; i++) \ + mc146818_write(sc, i, (*regs)[i]); \ + \ + /* reenable updates */ \ + mc146818_write(sc, MC_REGB, \ + mc146818_read(sc, MC_REGB) & ~MC_REGB_SET); \ + } while (0); diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c new file mode 100644 index 0000000..883666d --- /dev/null +++ b/sys/kern/subr_bus.c @@ -0,0 +1,854 @@ +/*- + * Copyright (c) 1997 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus_private.h> +#include <sys/systm.h> + +device_t +bus_get_device(bus_t bus) +{ + return bus->dev; +} + +void +bus_print_device(bus_t bus, device_t dev) +{ + printf("%s%d", device_get_name(dev), device_get_unit(dev)); + if (device_is_alive(dev)) { + if (device_get_desc(dev)) + printf(": <%s>", device_get_desc(dev)); + bus->ops->print_device(bus, dev); + } else + printf(" not found"); + printf("\n"); +} + +int +bus_read_ivar(bus_t bus, device_t dev, + int index, u_long *result) +{ + return bus->ops->read_ivar(bus, dev, index, result); +} + +int +bus_write_ivar(bus_t bus, device_t dev, + int index, u_long value) +{ + return bus->ops->write_ivar(bus, dev, index, value); +} + +int +bus_map_intr(bus_t bus, device_t dev, driver_intr_t *intr, void *arg) +{ + return bus->ops->map_intr(bus, dev, intr, arg); +} + +static devclass_list_t devclasses; + +static void +devclass_init(void) +{ + TAILQ_INIT(&devclasses); +} + +static devclass_t +devclass_find_internal(const char *classname, int create) +{ + devclass_t dc; + + for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link)) + if (!strcmp(dc->name, classname)) + return dc; + + if (create) { + dc = malloc(sizeof(struct devclass) + strlen(classname) + 1, + M_DEVBUF, M_NOWAIT); + if (!dc) + return NULL; + dc->name = (char*) (dc + 1); + strcpy(dc->name, classname); + dc->devices = NULL; + dc->maxunit = 0; + dc->nextunit = 0; + TAILQ_INIT(&dc->drivers); + TAILQ_INSERT_TAIL(&devclasses, dc, link); + } + + return dc; +} + +devclass_t +devclass_find(const char *classname) +{ + return devclass_find_internal(classname, FALSE); +} + +int +devclass_add_driver(devclass_t dc, driver_t *driver) +{ + /* + * Make sure the devclass which the driver is implementing exists. + */ + devclass_find_internal(driver->name, TRUE); + + TAILQ_INSERT_TAIL(&dc->drivers, driver, link); + + return 0; +} + +int +devclass_delete_driver(devclass_t dc, driver_t *driver) +{ + bus_t bus; + device_t dev; + int i; + int error; + + /* + * Disassociate from any devices. We iterate through all the + * devices attached to any bus in this class. + */ + for (i = 0; i < dc->maxunit; i++) { + if (dc->devices[i]) { + bus = dc->devices[i]->softc; + for (dev = TAILQ_FIRST(&bus->devices); dev; + dev = TAILQ_NEXT(dev, link)) + if (dev->driver == driver) { + if (error = device_detach(dev)) + return error; + device_set_driver(dev, NULL); + } + } + } + + TAILQ_REMOVE(&dc->drivers, driver, link); + return 0; +} + +driver_t * +devclass_find_driver(devclass_t dc, const char *classname) +{ + driver_t *driver; + + for (driver = TAILQ_FIRST(&dc->drivers); driver; + driver = TAILQ_NEXT(driver, link)) + if (!strcmp(driver->name, classname)) + return driver; + + return NULL; +} + +const char * +devclass_get_name(devclass_t dc) +{ + return dc->name; +} + +device_t +devclass_get_device(devclass_t dc, int unit) +{ + if (unit < 0 || unit >= dc->maxunit) + return NULL; + return dc->devices[unit]; +} + +void * +devclass_get_softc(devclass_t dc, int unit) +{ + device_t dev; + + if (unit < 0 || unit >= dc->maxunit) + return NULL; + dev = dc->devices[unit]; + if (!dev || dev->state < DS_ATTACHED) + return NULL; + return dev->softc; +} + +int +devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp) +{ + int i; + int count; + device_t dev; + device_t *list; + + count = 0; + for (i = 0; i < dc->maxunit; i++) + if (dc->devices[i]) + count++; + + list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT); + if (!list) + return ENOMEM; + + count = 0; + for (i = 0; i < dc->maxunit; i++) + if (dc->devices[i]) { + list[count] = dc->devices[i]; + count++; + } + + *devlistp = list; + *devcountp = count; + + return 0; +} + +int +devclass_get_maxunit(devclass_t dc) +{ + return dc->maxunit; +} + +static int +devclass_alloc_unit(devclass_t dc, int *unitp) +{ + int unit = *unitp; + + /* + * If we have been given a wired unit number, check for existing + * device. + */ + if (unit != -1) { + device_t dev; + dev = devclass_get_device(dc, unit); + if (dev) { + printf("devclass_alloc_unit: %s%d already exists, using next available unit number\n", dc->name, unit); + unit = -1; + } + } + + if (unit == -1) { + unit = dc->nextunit; + dc->nextunit++; + } else if (dc->nextunit <= unit) + dc->nextunit = unit + 1; + + if (unit >= dc->maxunit) { + device_t *newlist; + int newsize; + + newsize = (dc->maxunit ? 2 * dc->maxunit + : MINALLOCSIZE / sizeof(device_t)); + newlist = malloc(sizeof(device_t) * newsize, M_DEVBUF, M_NOWAIT); + if (!newlist) + return ENOMEM; + bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit); + bzero(newlist + dc->maxunit, + sizeof(device_t) * (newsize - dc->maxunit)); + if (dc->devices) + free(dc->devices, M_DEVBUF); + dc->devices = newlist; + dc->maxunit = newsize; + } + + *unitp = unit; + return 0; +} + +static int +devclass_add_device(devclass_t dc, device_t dev) +{ + int error; + + if (error = devclass_alloc_unit(dc, &dev->unit)) + return error; + dc->devices[dev->unit] = dev; + dev->devclass = dc; + return 0; +} + +static int +devclass_delete_device(devclass_t dc, device_t dev) +{ + if (dev->devclass != dc + || dc->devices[dev->unit] != dev) + panic("devclass_delete_device: inconsistent device class"); + dc->devices[dev->unit] = NULL; + if (dev->flags & DF_WILDCARD) + dev->unit = -1; + dev->devclass = NULL; + while (dc->nextunit > 0 && dc->devices[dc->nextunit - 1] == NULL) + dc->nextunit--; + return 0; +} + +static device_t +make_device(bus_t bus, const char *name, + int unit, void *ivars) +{ + driver_t *driver; + device_t dev; + devclass_t dc; + int error; + + if (name) { + dc = devclass_find_internal(name, TRUE); + if (!dc) { + printf("make_device: can't find device class %s\n", name); + return NULL; + } + + if (error = devclass_alloc_unit(dc, &unit)) + return NULL; + } else + dc = NULL; + + dev = malloc(sizeof(struct device), M_DEVBUF, M_NOWAIT); + if (!dev) + return 0; + + dev->parent = bus; + dev->driver = NULL; + dev->devclass = dc; + dev->unit = unit; + dev->desc = NULL; + dev->busy = 0; + dev->flags = DF_ENABLED; + if (unit == -1) + dev->flags |= DF_WILDCARD; + if (name) + dev->flags |= DF_FIXEDCLASS; + dev->ivars = ivars; + dev->softc = NULL; + + if (dc) + dc->devices[unit] = dev; + + dev->state = DS_NOTPRESENT; + + return dev; +} + +void +bus_init(bus_t bus, device_t dev, bus_ops_t *ops) +{ + bus->ops = ops; + bus->dev = dev; + TAILQ_INIT(&bus->devices); +} + +device_t +bus_add_device(bus_t bus, const char *name, int unit, void *ivars) +{ + device_t dev; + + dev = make_device(bus, name, unit, ivars); + + TAILQ_INSERT_TAIL(&bus->devices, dev, link); + + return dev; +} + +device_t +bus_add_device_after(bus_t bus, device_t place, const char *name, + int unit, void *ivars) +{ + device_t dev; + + dev = make_device(bus, name, unit, ivars); + + if (place) { + TAILQ_INSERT_AFTER(&bus->devices, place, dev, link); + } else { + TAILQ_INSERT_HEAD(&bus->devices, dev, link); + } + + return dev; +} + +int +bus_delete_device(bus_t bus, device_t dev) +{ + int error; + + if (error = device_detach(dev)) + return error; + if (dev->devclass) + devclass_delete_device(dev->devclass, dev); + TAILQ_REMOVE(&bus->devices, dev, link); + free(dev, M_DEVBUF); + + return 0; +} + +/* + * Find only devices attached to this bus. + */ +device_t +bus_find_device(bus_t bus, const char *classname, int unit) +{ + devclass_t dc; + device_t dev; + + dc = devclass_find(classname); + if (!dc) + return NULL; + + dev = devclass_get_device(dc, unit); + if (dev && dev->parent == bus) + return dev; + return NULL; +} + +static driver_t * +first_matching_driver(devclass_t dc, device_t dev) +{ + if (dev->devclass) + return devclass_find_driver(dc, dev->devclass->name); + else + return TAILQ_FIRST(&dc->drivers); +} + +static driver_t * +next_matching_driver(devclass_t dc, device_t dev, driver_t *last) +{ + if (dev->devclass) { + driver_t *driver; + for (driver = TAILQ_NEXT(last, link); driver; + driver = TAILQ_NEXT(driver, link)) + if (!strcmp(dev->devclass->name, driver->name)) + return driver; + return NULL; + } else + return TAILQ_NEXT(last, link); +} + +static int +bus_probe_device(bus_t bus, device_t dev) +{ + devclass_t dc; + driver_t *driver; + void *softc; + + dc = bus->dev->devclass; + if (dc == NULL) + panic("bus_probe_device: bus' device has no devclass"); + + if (dev->state == DS_ALIVE) + return 0; + + for (driver = first_matching_driver(dc, dev); + driver; + driver = next_matching_driver(dc, dev, driver)) { + device_set_driver(dev, driver); + if (driver->probe(bus, dev) == 0) { + if (!dev->devclass) + device_set_devclass(dev, driver->name); + dev->state = DS_ALIVE; + return 0; + } + } + + return ENXIO; +} + +int +bus_generic_attach(bus_t parent, device_t busdev) +{ + bus_t bus = busdev->softc; + device_t dev; + int error; + + for (dev = TAILQ_FIRST(&bus->devices); + dev; dev = TAILQ_NEXT(dev, link)) + device_probe_and_attach(dev); + + return 0; +} + +int +bus_generic_detach(bus_t parent, device_t busdev) +{ + bus_t bus = busdev->softc; + device_t dev; + int error; + + if (busdev->state != DS_ATTACHED) + return EBUSY; + + for (dev = TAILQ_FIRST(&bus->devices); + dev; dev = TAILQ_NEXT(dev, link)) + device_detach(dev); + + return 0; +} + +int +bus_generic_shutdown(bus_t parent, device_t busdev) +{ + bus_t bus = busdev->softc; + device_t dev; + + for (dev = TAILQ_FIRST(&bus->devices); + dev; dev = TAILQ_NEXT(dev, link)) + device_shutdown(dev); + + return 0; +} + +bus_t +device_get_parent(device_t dev) +{ + return dev->parent; +} + +driver_t * +device_get_driver(device_t dev) +{ + return dev->driver; +} + +devclass_t +device_get_devclass(device_t dev) +{ + return dev->devclass; +} + +const char * +device_get_name(device_t dev) +{ + if (dev->devclass) + return devclass_get_name(dev->devclass); + return NULL; +} + +int +device_get_unit(device_t dev) +{ + return dev->unit; +} + +const char * +device_get_desc(device_t dev) +{ + return dev->desc; +} + +void +device_set_desc(device_t dev, const char* desc) +{ + dev->desc = desc; +} + +void * +device_get_softc(device_t dev) +{ + return dev->softc; +} + +void * +device_get_ivars(device_t dev) +{ + return dev->ivars; +} + +device_state_t +device_get_state(device_t dev) +{ + return dev->state; +} + +void +device_enable(device_t dev) +{ + dev->flags |= DF_ENABLED; +} + +void +device_disable(device_t dev) +{ + dev->flags &= ~DF_ENABLED; +} + +void +device_busy(device_t dev) +{ + if (dev->state < DS_ATTACHED) + panic("device_busy: called for unattached device"); + if (dev->busy == 0 && dev->parent) + device_busy(dev->parent->dev); + dev->busy++; + dev->state = DS_BUSY; +} + +void +device_unbusy(device_t dev) +{ + if (dev->state != DS_BUSY) + panic("device_unbusy: called for non-busy device"); + dev->busy--; + if (dev->busy == 0) { + if (dev->parent->dev) + device_unbusy(dev->parent->dev); + dev->state = DS_ATTACHED; + } +} + +int +device_is_enabled(device_t dev) +{ + return (dev->flags & DF_ENABLED) != 0; +} + +int +device_is_alive(device_t dev) +{ + return dev->state >= DS_ALIVE; +} + +int +device_set_devclass(device_t dev, const char *classname) +{ + devclass_t dc; + + if (dev->devclass) { + printf("device_set_devclass: device class already set\n"); + return EINVAL; + } + + dc = devclass_find_internal(classname, TRUE); + if (!dc) + return ENOMEM; + + return devclass_add_device(dc, dev); +} + +int +device_set_driver(device_t dev, driver_t *driver) +{ + if (dev->state >= DS_ATTACHED) + return EBUSY; + + if (dev->driver == driver) + return 0; + + if (dev->softc) { + free(dev->softc, M_DEVBUF); + dev->softc = NULL; + } + dev->driver = driver; + if (driver) { + dev->softc = malloc(driver->softc, M_DEVBUF, M_NOWAIT); + bzero(dev->softc, driver->softc); + } + return 0; +} + +int +device_probe_and_attach(device_t dev) +{ + bus_t bus = dev->parent; + int error; + + if (dev->state >= DS_ALIVE) + return 0; + + if (dev->flags & DF_ENABLED) { + bus_probe_device(bus, dev); + bus_print_device(bus, dev); + if (dev->state == DS_ALIVE) { + error = dev->driver->attach(bus, dev); + if (!error) + dev->state = DS_ATTACHED; + else { + printf("device_probe_and_attach: %s%n attach returned %d\n", + dev->driver->name, dev->unit, error); + device_set_driver(dev, NULL); + dev->state = DS_NOTPRESENT; + } + } + } else + printf("%s%d: disabled, not probed.\n", + dev->devclass->name, dev->unit); + + return 0; +} + +int +device_detach(device_t dev) +{ + int error; + + if (dev->state == DS_BUSY) + return EBUSY; + if (dev->state != DS_ATTACHED) + return 0; + + if (dev->driver->detach) { + if (error = dev->driver->detach(dev->parent, dev)) + return error; + } else + return EBUSY; + + if (!(dev->flags & DF_FIXEDCLASS)) + devclass_delete_device(dev->devclass, dev); + + dev->state = DS_NOTPRESENT; + device_set_driver(dev, NULL); + + return 0; +} + +int +device_shutdown(device_t dev) +{ + if (dev->state < DS_ATTACHED) + return 0; + if (dev->driver->shutdown) + return dev->driver->shutdown(dev->parent, dev); + else + return 0; +} + +void +null_print_device(bus_t bus, device_t dev) +{ +} + +int +null_read_ivar(bus_t bus, device_t dev, int index, u_long* result) +{ + return ENOENT; +} + +int +null_write_ivar(bus_t bus, device_t dev, int index, u_long value) +{ + return ENOENT; +} + +int +null_map_intr(bus_t bus, device_t dev, driver_intr_t *intr, void *arg) +{ + /* Propagate up the bus hierarchy until someone handles it. */ + if (bus->dev) + return bus_map_intr(bus->dev->parent, bus->dev, intr, arg); + else + return EINVAL; +} + +bus_ops_t null_bus_ops = { + null_print_device, + null_read_ivar, + null_write_ivar, + null_map_intr, +}; + +static void +root_bus_print_device(bus_t bus, device_t dev) +{ +} + +static int root_bus_map_intr(bus_t bus, device_t dev, + driver_intr_t *intr, void *arg) +{ + return EINVAL; +} + +static bus_ops_t root_bus_ops = { + root_bus_print_device, + null_read_ivar, + null_write_ivar, + root_bus_map_intr, +}; + +static struct bus the_root_bus; +bus_t root_bus = &the_root_bus; +device_t root_device; +devclass_t root_devclass; + +static int +root_bus_module_handler(module_t mod, modeventtype_t what, void* arg) +{ + switch (what) { + case MOD_LOAD: + devclass_init(); + root_device = make_device(NULL, "root", 0, NULL); + root_device->state = DS_ATTACHED; + bus_init(root_bus, root_device, &root_bus_ops); + root_devclass = devclass_find("root"); + return 0; + } + + return 0; +} + +static moduledata_t root_bus_mod = { + "rootbus", + root_bus_module_handler, + 0 +}; +DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); + +void +root_bus_configure() +{ + device_t dev; + int error; + + for (dev = TAILQ_FIRST(&root_bus->devices); dev; + dev = TAILQ_NEXT(dev, link)) { + device_probe_and_attach(dev); + } +} + +int +driver_module_handler(module_t mod, modeventtype_t what, void* arg) +{ + struct driver_module_data* data = (struct driver_module_data*) arg; + devclass_t bus_devclass = devclass_find_internal(data->busname, TRUE); + int error; + + switch (what) { + case MOD_LOAD: + if (error = devclass_add_driver(bus_devclass, + data->driver)) + return error; + *data->devclass = + devclass_find_internal(data->driver->name, TRUE); + break; + + case MOD_UNLOAD: + if (error = devclass_delete_driver(bus_devclass, + data->driver)) + return error; + break; + } + + if (data->chainevh) + return data->chainevh(mod, what, data->chainarg); + else + return 0; +} diff --git a/sys/libkern/alpha/byte_swap_2.S b/sys/libkern/alpha/byte_swap_2.S new file mode 100644 index 0000000..fab3c58 --- /dev/null +++ b/sys/libkern/alpha/byte_swap_2.S @@ -0,0 +1,47 @@ +/* $NetBSD: byte_swap_2.S,v 1.2 1996/10/17 03:08:08 cgd Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <machine/asm.h> + +#ifndef NAME +#define NAME byte_swap_2 +#endif + +/* + * Byte-swap a 2-byte quantity. (Convert 0x0123 to 0x2301.) + * + * Argument is an unsigned 2-byte integer (u_int16_t). + */ +LEAF(NAME, 1) /* a0 contains 0x0123 */ + extbl a0, 0, t0 /* t0 = 0x 23 */ + extbl a0, 1, t1 /* t1 = 0x 01 */ + sll t0, 8, t0 /* t1 = 0x23 */ + or t0, t1, v0 /* v0 = 0x2301 */ + RET +END(NAME) diff --git a/sys/libkern/alpha/byte_swap_4.S b/sys/libkern/alpha/byte_swap_4.S new file mode 100644 index 0000000..8dbb83c --- /dev/null +++ b/sys/libkern/alpha/byte_swap_4.S @@ -0,0 +1,53 @@ +/* $NetBSD: byte_swap_4.S,v 1.2 1996/10/17 03:08:09 cgd Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <machine/asm.h> + +#ifndef NAME +#define NAME byte_swap_4 +#endif + +/* + * Byte-swap a 4-byte quantity. (Convert 0x01234567 to 0x67452301.) + * + * Argument is an unsigned 4-byte integer (u_int32_t). + */ +LEAF(NAME, 1) /* a0 contains 0x01234567 */ + extbl a0, 0, t0 /* t0 = 0x 67 */ + extbl a0, 1, t1 /* t1 = 0x 45 */ + extbl a0, 2, t2 /* t2 = 0x 23 */ + extbl a0, 3, t3 /* t3 = 0x 01 */ + sll t0, 24, t0 /* t0 = 0x67 */ + sll t1, 16, t1 /* t1 = 0x 45 */ + sll t2, 8, t2 /* t2 = 0x 23 */ + or t3, t0, v0 /* v0 = 0x67 01 */ + or t1, t2, t1 /* t1 = 0x 4523 */ + or t1, v0, v0 /* v0 = 0x67452301 */ + RET +END(NAME) diff --git a/sys/libkern/alpha/htonl.S b/sys/libkern/alpha/htonl.S new file mode 100644 index 0000000..7fab6f9 --- /dev/null +++ b/sys/libkern/alpha/htonl.S @@ -0,0 +1,32 @@ +/* $NetBSD: htonl.S,v 1.1 1996/04/17 22:36:52 cgd Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#define NAME htonl + +#include <libkern/alpha/byte_swap_4.S> diff --git a/sys/libkern/alpha/htons.S b/sys/libkern/alpha/htons.S new file mode 100644 index 0000000..392578c --- /dev/null +++ b/sys/libkern/alpha/htons.S @@ -0,0 +1,32 @@ +/* $NetBSD: htons.S,v 1.1 1996/04/17 22:36:54 cgd Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#define NAME htons + +#include <libkern/alpha/byte_swap_2.S> diff --git a/sys/libkern/alpha/ntohl.S b/sys/libkern/alpha/ntohl.S new file mode 100644 index 0000000..370848a --- /dev/null +++ b/sys/libkern/alpha/ntohl.S @@ -0,0 +1,32 @@ +/* $NetBSD: ntohl.S,v 1.1 1996/04/17 22:36:57 cgd Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#define NAME ntohl + +#include <libkern/alpha/byte_swap_4.S> diff --git a/sys/libkern/alpha/ntohs.S b/sys/libkern/alpha/ntohs.S new file mode 100644 index 0000000..80be3f8 --- /dev/null +++ b/sys/libkern/alpha/ntohs.S @@ -0,0 +1,32 @@ +/* $NetBSD: ntohs.S,v 1.1 1996/04/17 22:37:02 cgd Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#define NAME ntohs + +#include <libkern/alpha/byte_swap_2.S> diff --git a/sys/pci/simos.c b/sys/pci/simos.c new file mode 100644 index 0000000..4e84edd --- /dev/null +++ b/sys/pci/simos.c @@ -0,0 +1,312 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/proc.h> + +#include <scsi/scsiconf.h> +#include <scsi/scsi_debug.h> + +#include <machine/clock.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <sys/kernel.h> + +#include <pci/simos.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <machine/alpha_cpu.h> + +#define MAX_SIZE (64*1024) + +struct simos_softc { + int sc_unit; + struct scsi_link sc_link; + SimOS_SCSI* sc_regs; + int sc_busy; + struct scsi_xfer* sc_head; + struct scsi_xfer* sc_tail; +}; + +struct simos_softc* simosp[10]; + +static u_long simos_unit; + +static char *simos_probe __P((pcici_t tag, pcidi_t type)); +static void simos_attach __P((pcici_t config_d, int unit)); + +struct pci_device simos_driver = { + "simos", + simos_probe, + simos_attach, + &simos_unit, + NULL +}; +DATA_SET (pcidevice_set, simos_driver); + +static int32_t simos_start(struct scsi_xfer * xp); +static void simos_min_phys (struct buf *bp); +static u_int32_t simos_info(int unit); + +static struct scsi_adapter simos_switch = +{ + simos_start, + simos_min_phys, + 0, + 0, + simos_info, + "simos" +}; + +static struct scsi_device simos_dev = +{ + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ + "simos", +}; + +static char * +simos_probe(pcici_t tag, pcidi_t type) +{ + switch (type) { + case 0x1291|(0x1291<<16): + return "SimOS SCSI"; + default: + return NULL; + } + +} + +static void +simos_attach(pcici_t config_id, int unit) +{ + struct simos_softc* sc; + struct scsibus_data* scbus; + + sc = malloc(sizeof(struct simos_softc), M_DEVBUF, M_WAITOK); + simosp[unit] = sc; + bzero(sc, sizeof *sc); + + sc->sc_unit = unit; + sc->sc_regs = (SimOS_SCSI*) SIMOS_SCSI_ADDR; + sc->sc_busy = 0; + sc->sc_head = 0; + sc->sc_tail = 0; + + sc->sc_link.adapter_unit = unit; + sc->sc_link.adapter_softc = sc; + sc->sc_link.adapter_targ = SIMOS_SCSI_MAXTARG-1; + sc->sc_link.fordriver = 0; + sc->sc_link.adapter = &simos_switch; + sc->sc_link.device = &simos_dev; + sc->sc_link.flags = 0; + + scbus = scsi_alloc_bus(); + scbus->adapter_link = &sc->sc_link; + scbus->maxtarg = 1; + scbus->maxlun = 0; + scsi_attachdevs(scbus); + scbus = 0; +} + +static void +simos_enqueue(struct simos_softc* sc, struct scsi_xfer* xp) +{ + if (sc->sc_tail) { + sc->sc_tail->next = xp; + } else { + sc->sc_head = sc->sc_tail = xp; + } + xp->next = 0; +} + +static void +simos_start_transfer(struct simos_softc* sc) +{ + struct scsi_xfer* xp = sc->sc_head; + u_int8_t* p; + int i, count, target; + vm_offset_t va; + vm_size_t size; + + if (sc->sc_busy || !xp) + return; + + sc->sc_busy = TRUE; + + target = xp->sc_link->target; + + /* + * Copy the command into SimOS' buffer + */ + p = (u_int8_t*) xp->cmd; + count = xp->cmdlen; + for (i = 0; i < count; i++) + sc->sc_regs->cmd[i] = *p++; + sc->sc_regs->length = count; + sc->sc_regs->target = target; + sc->sc_regs->lun = xp->sc_link->lun; + + /* + * Setup the segment descriptors. + */ + va = (vm_offset_t) xp->data; + size = xp->datalen; + i = 0; + while (size > 0) { + vm_size_t len = PAGE_SIZE - (va & PAGE_MASK); + if (len > size) + len = size; + sc->sc_regs->sgMap[i].pAddr = vtophys(va); + sc->sc_regs->sgMap[i].len = len; + size -= len; + va += len; + i++; + } + sc->sc_regs->sgLen = i; + + /* + * Start the i/o. + */ + alpha_wmb(); + sc->sc_regs->startIO = 1; + alpha_wmb(); +} + +static void +simos_done(struct simos_softc* sc) +{ + struct scsi_xfer* xp; + int done; + + if (!sc->sc_busy) + return; + + xp = sc->sc_head; + + /* + * Spurious interrupt caused by my bogus interrupt broadcasting. + */ + if (!sc->sc_regs->done[xp->sc_link->target]) + return; + + sc->sc_head = xp->next; + if (!sc->sc_head) + sc->sc_tail = 0; + + sc->sc_busy = FALSE; + + done = sc->sc_regs->done[xp->sc_link->target]; + if (done >> 16) { + /* Error detected */ + xp->error = XS_TIMEOUT; + } + xp->flags |= ITSDONE; + + sc->sc_regs->done[xp->sc_link->target] = 1; + alpha_wmb(); + + if (!(xp->flags & SCSI_NOMASK)) + scsi_done(xp); + + if (sc->sc_head) + simos_start_transfer(sc); +} + +static int32_t +simos_start(struct scsi_xfer * xp) +{ + struct simos_softc* sc; + int flags = xp->flags; + int retval = 0; + int s; + + sc = xp->sc_link->adapter_softc; + + /* + * Reset (chortle) the adapter. + */ + if (flags & SCSI_RESET) + return COMPLETE; + + /* + * Simos doesn't understand some commands + */ + if (xp->cmd->opcode == START_STOP || xp->cmd->opcode == PREVENT_ALLOW) + return COMPLETE; + + s = splbio(); + + simos_enqueue(sc, xp); + simos_start_transfer(sc); + + if (flags & SCSI_NOMASK) { + /* + * Poll for result + */ + while (!sc->sc_regs->done[xp->sc_link->target]) + ; + + simos_done(sc); + retval = COMPLETE; + } else + retval = SUCCESSFULLY_QUEUED; + + splx(s); + + return retval; +} + +static void +simos_min_phys (struct buf *bp) +{ + if ((unsigned long)bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE; +} + +static u_int32_t +simos_info(int unit) +{ + return 1; +} + +void +simos_intr(int unit) +{ + /* XXX bogus */ + struct simos_softc* sc = simosp[unit]; + + simos_done(sc); +} diff --git a/sys/pci/simos.h b/sys/pci/simos.h new file mode 100644 index 0000000..4609354 --- /dev/null +++ b/sys/pci/simos.h @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +/* + * Copyright (C) 1998 by the Board of Trustees + * of Leland Stanford Junior University. + * Copyright (C) 1998 Digital Equipment Corporation + * + * This file is part of the SimOS distribution. + * See LICENSE file for terms of the license. + * + */ + + + + +#ifndef _SIMOS_SCSI_H +#define _SIMOS_SCSI_H + +#define SIMOS_SCSI_ADDR 0xfffffcc500000000 +#define SIMOS_SCSI_ADDR_32 0xffffffffa5000000 +#define SIMOS_SCSI_MAXDMA_LEN 128 +#define SIMOS_SCSI_MAXTARG 16 +#define SIMOS_SCSI_MAXLUN 16 + +#define SIMOS_SCSI_REGS ((struct SimOS_SCSI *)SIMOS_SCSI_ADDR) +#define SIMOS_SCSI_REGS_32 ((struct SimOS_SCSI *)SIMOS_SCSI_ADDR_32) + +typedef unsigned long SCSIReg; + + +typedef struct SimOS_SCSI { + SCSIReg startIO; /* write-only */ + SCSIReg done[SIMOS_SCSI_MAXTARG]; /* read-write (write=ack) */ + + SCSIReg target; /* data fields */ + SCSIReg lun; + SCSIReg cmd[12]; + SCSIReg length; + SCSIReg sgLen; + struct { + SCSIReg pAddr; + SCSIReg len; + } sgMap[SIMOS_SCSI_MAXDMA_LEN]; + + +} SimOS_SCSI; + +#endif diff --git a/sys/powerpc/include/bootinfo.h b/sys/powerpc/include/bootinfo.h new file mode 100644 index 0000000..36b3943 --- /dev/null +++ b/sys/powerpc/include/bootinfo.h @@ -0,0 +1,21 @@ +/* + * Kernel-internal structure used to hold important bits of boot + * information. NOT to be used by boot blocks. + * + * Note that not all of the fields from the bootinfo struct(s) + * passed by the boot blocks aren't here (because they're not currently + * used by the kernel!). Fields here which aren't supplied by the + * bootinfo structure passed by the boot blocks are supposed to be + * filled in at startup with sane contents. + */ +struct bootinfo_kernel { + u_long ssym; /* start of syms */ + u_long esym; /* end of syms */ + u_long hwrpb_phys; /* hwrpb physical address */ + u_long hwrpb_size; /* size of hwrpb data */ + char boot_flags[64]; /* boot flags */ + char booted_kernel[64]; /* name of booted kernel */ + char booted_dev[64]; /* name of booted device */ +}; + +extern struct bootinfo_kernel bootinfo; diff --git a/sys/powerpc/include/clock.h b/sys/powerpc/include/clock.h new file mode 100644 index 0000000..95c160f --- /dev/null +++ b/sys/powerpc/include/clock.h @@ -0,0 +1,22 @@ +/* + * Kernel interface to machine-dependent clock driver. + * Garrett Wollman, September 1994. + * This file is in the public domain. + * + * $Id: clock.h,v 1.34 1998/03/05 21:45:42 tegge Exp $ + */ + +#ifndef _MACHINE_CLOCK_H_ +#define _MACHINE_CLOCK_H_ + +#ifdef KERNEL + +extern int wall_cmos_clock; +extern int adjkerntz; + +void DELAY __P((int usec)); +int sysbeep __P((int pitch, int period)); + +#endif /* KERNEL */ + +#endif /* !_MACHINE_CLOCK_H_ */ diff --git a/sys/powerpc/include/md_var.h b/sys/powerpc/include/md_var.h new file mode 100644 index 0000000..d70c1da --- /dev/null +++ b/sys/powerpc/include/md_var.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#ifndef _MACHINE_MD_VAR_H_ +#define _MACHINE_MD_VAR_H_ + +/* + * Miscellaneous machine-dependent declarations. + */ + +extern char sigcode[]; +extern int szsigcode; +extern int Maxmem; +extern void (*netisrs[32]) __P((void)); + +void cpu_power_down __P((void)); +void cpu_halt __P((void)); +void cpu_reset __P((void)); +int is_physical_memory __P((vm_offset_t addr)); +void swi_vm __P((void)); +int vm_page_zero_idle __P((void)); +int fill_regs __P((struct proc *, struct reg *)); +int set_regs __P((struct proc *, struct reg *)); + +#endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c new file mode 100644 index 0000000..520bd41 --- /dev/null +++ b/sys/powerpc/powerpc/genassym.c @@ -0,0 +1,212 @@ +/*- + * Copyright (c) 1982, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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: @(#)genassym.c 5.11 (Berkeley) 5/10/91 + * $Id: genassym.c,v 1.54 1998/04/06 18:59:14 peter Exp $ + */ + +#include <sys/param.h> +#include <sys/buf.h> +#include <sys/errno.h> +#include <sys/proc.h> +#include <sys/mount.h> +#include <sys/socket.h> +#include <sys/resource.h> +#include <sys/resourcevar.h> +#include <machine/frame.h> +#include <sys/vmmeter.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#define KERNEL /* XXX avoid user headers */ +#include <sys/user.h> +#undef KERNEL +#include <net/if.h> +#include <netinet/in.h> +#include <nfs/nfsv2.h> +#include <nfs/rpcv2.h> +#include <nfs/nfs.h> +#include <nfs/nfsdiskless.h> + +int main __P((void)); +int printf __P((const char *, ...)); + +#define P(name, val) \ + printf(val > 999 ? "#define\t%s 0x%lx\n" : "#define\t%s %ld\n", name, val) + +/* XXX Danger Will Robinson */ +struct prochd { + struct proc *ph_link; /* Linked list of running processes. */ + struct proc *ph_rlink; +}; + +#define OFF(name, type, elem) P(#name, (long)&((type*)0)->elem) +#define CONST2(name, val) P(#name, val) +#define CONST1(name) P(#name, name) + +int +main() +{ + OFF(P_FORW, struct proc, p_procq.tqe_next); + OFF(P_BACK, struct proc, p_procq.tqe_prev); + OFF(P_VMSPACE, struct proc, p_vmspace); + OFF(P_ADDR, struct proc, p_addr); + OFF(P_PRI, struct proc, p_priority); + OFF(P_RTPRIO_TYPE, struct proc, p_rtprio.type); + OFF(P_RTPRIO_PRIO, struct proc, p_rtprio.prio); + OFF(P_STAT, struct proc, p_stat); + OFF(P_WCHAN, struct proc, p_wchan); + OFF(P_FLAG, struct proc, p_flag); + OFF(P_PID, struct proc, p_pid); + OFF(P_RUNTIME, struct proc, p_runtime); + OFF(P_MD_PCBPADDR, struct proc, p_md.md_pcbpaddr); + + OFF(PH_LINK, struct prochd, ph_link); + OFF(PH_RLINK, struct prochd, ph_rlink); + + CONST1(SSLEEP); + CONST1(SRUN); + + OFF(VM_PMAP, struct vmspace, vm_pmap); + OFF(V_TRAP, struct vmmeter, v_trap); + OFF(V_SYSCALL, struct vmmeter, v_trap); + OFF(V_INTR, struct vmmeter, v_trap); + + CONST1(UPAGES); + CONST1(PAGE_SIZE); + CONST1(PAGE_SHIFT); + CONST1(PAGE_MASK); + CONST1(USRSTACK); + CONST1(VM_MAXUSER_ADDRESS); + CONST1(KERNBASE); + CONST1(PTLEV1I); + CONST1(PTESIZE); + + OFF(U_PCB_ONFAULT, struct user, u_pcb.pcb_onfault); + OFF(U_PCB_HWPCB_KSP, struct user, u_pcb.pcb_hw.apcb_ksp); + OFF(U_PCB_CONTEXT, struct user, u_pcb.pcb_context); + OFF(U_PROFSCALE, struct user, u_stats.p_prof.pr_scale); + + OFF(PR_BASE, struct uprof, pr_base); + OFF(PR_SIZE, struct uprof, pr_size); + OFF(PR_OFF, struct uprof, pr_off); + OFF(PR_SCALE, struct uprof, pr_scale); + + OFF(RU_MINFLT, struct rusage, ru_minflt); + + OFF(PCB_HW, struct pcb, pcb_hw); + OFF(PCB_CONTEXT, struct pcb, pcb_context); + OFF(PCB_FP, struct pcb, pcb_fp); + OFF(PCB_ONFAULT, struct pcb, pcb_onfault); + OFF(PCB_ACCESSADDR, struct pcb, pcb_accessaddr); + + OFF(FPREG_FPR_REGS, struct fpreg, fpr_regs); + OFF(FPREG_FPR_CR, struct fpreg, fpr_cr); + + CONST1(B_READ); + CONST1(ENOENT); + CONST1(EFAULT); + CONST1(ENAMETOOLONG); + CONST1(MAXPATHLEN); + + /* Register offsets, for stack frames. */ + CONST1(FRAME_V0), + CONST1(FRAME_T0), + CONST1(FRAME_T1), + CONST1(FRAME_T2), + CONST1(FRAME_T3), + CONST1(FRAME_T4), + CONST1(FRAME_T5), + CONST1(FRAME_T6), + CONST1(FRAME_T7), + CONST1(FRAME_S0), + CONST1(FRAME_S1), + CONST1(FRAME_S2), + CONST1(FRAME_S3), + CONST1(FRAME_S4), + CONST1(FRAME_S5), + CONST1(FRAME_S6), + CONST1(FRAME_A3), + CONST1(FRAME_A4), + CONST1(FRAME_A5), + CONST1(FRAME_T8), + CONST1(FRAME_T9), + CONST1(FRAME_T10), + CONST1(FRAME_T11), + CONST1(FRAME_RA), + CONST1(FRAME_T12), + CONST1(FRAME_AT), + CONST1(FRAME_SP), + + CONST1(FRAME_SW_SIZE), + + CONST1(FRAME_PS), + CONST1(FRAME_PC), + CONST1(FRAME_GP), + CONST1(FRAME_A0), + CONST1(FRAME_A1), + CONST1(FRAME_A2), + + CONST1(FRAME_SIZE), + + /* bits of the PS register */ + CONST1(ALPHA_PSL_USERMODE); + CONST1(ALPHA_PSL_IPL_MASK); + CONST1(ALPHA_PSL_IPL_0); + CONST1(ALPHA_PSL_IPL_SOFT); + CONST1(ALPHA_PSL_IPL_HIGH); + + /* pte bits */ + CONST1(ALPHA_L1SHIFT); + CONST1(ALPHA_L2SHIFT); + CONST1(ALPHA_L3SHIFT); + CONST1(ALPHA_K1SEG_BASE); + CONST1(ALPHA_PTE_VALID); + CONST1(ALPHA_PTE_ASM); + CONST1(ALPHA_PTE_KR); + CONST1(ALPHA_PTE_KW); + + /* Kernel entries */ + CONST1(ALPHA_KENTRY_ARITH); + CONST1(ALPHA_KENTRY_MM); + + CONST1(ALPHA_KENTRY_IF); + CONST1(ALPHA_KENTRY_UNA); + + CONST1(VPTBASE); + + return (0); +} diff --git a/sys/powerpc/powerpc/procfs_machdep.c b/sys/powerpc/powerpc/procfs_machdep.c new file mode 100644 index 0000000..11898d0 --- /dev/null +++ b/sys/powerpc/powerpc/procfs_machdep.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1993 Jan-Simon Pendry + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * 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. + * + * @(#)procfs_machdep.c 8.3 (Berkeley) 1/27/94 + * + * From: + * $Id: procfs_machdep.c,v 1.10 1997/07/20 08:37:22 bde Exp $ + */ + +/* + * Functions to be implemented here are: + * + * procfs_read_regs(proc, regs) + * Get the current user-visible register set from the process + * and copy it into the regs structure (<machine/reg.h>). + * The process is stopped at the time read_regs is called. + * + * procfs_write_regs(proc, regs) + * Update the current register set from the passed in regs + * structure. Take care to avoid clobbering special CPU + * registers or privileged bits in the PSL. + * Depending on the architecture this may have fix-up work to do, + * especially if the IAR or PCW are modified. + * The process is stopped at the time write_regs is called. + * + * procfs_read_fpregs, procfs_write_fpregs + * deal with the floating point register set, otherwise as above. + * + * procfs_sstep(proc) + * Arrange for the process to trap after executing a single instruction. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/ptrace.h> +#include <sys/vnode.h> +#include <machine/reg.h> +#include <machine/md_var.h> +#include <miscfs/procfs/procfs.h> + +#include <vm/vm.h> +#include <sys/lock.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> + +#include <sys/user.h> + +int +procfs_read_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + return (fill_regs(p, regs)); +} + +int +procfs_write_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + return (set_regs(p, regs)); +} + +/* + * Ptrace doesn't support fpregs at all, and there are no security holes + * or translations for fpregs, so we can just copy them. + */ + +int +procfs_read_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + + if (p == fpcurproc) { + alpha_pal_wrfen(1); + savefpstate(&p->p_addr->u_pcb.pcb_fp); + alpha_pal_wrfen(0); + } + + bcopy(&p->p_addr->u_pcb.pcb_fp, fpregs, sizeof *fpregs); + return (0); +} + +int +procfs_write_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + + if (p == fpcurproc) + fpcurproc = NULL; + + bcopy(fpregs, &p->p_addr->u_pcb.pcb_fp, sizeof *fpregs); + return (0); +} + +int +procfs_sstep(p) + struct proc *p; +{ + return (EINVAL); +} diff --git a/sys/sys/bus.h b/sys/sys/bus.h new file mode 100644 index 0000000..54ca3d1 --- /dev/null +++ b/sys/sys/bus.h @@ -0,0 +1,229 @@ +/*- + * Copyright (c) 1997 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#ifndef _SYS_BUS_H_ +#define _SYS_BUS_H_ + +#ifdef KERNEL + +/* + * Forward declarations + */ +typedef struct bus *bus_t; +typedef struct device *device_t; +typedef struct driver driver_t; +typedef struct devclass *devclass_t; + +typedef int driver_probe_t(bus_t bus, device_t dev); +typedef int driver_attach_t(bus_t bus, device_t dev); +typedef int driver_detach_t(bus_t bus, device_t dev); +typedef int driver_shutdown_t(bus_t bus, device_t dev); +typedef void driver_intr_t(void*); + +typedef enum driver_type { + DRIVER_TYPE_TTY, + DRIVER_TYPE_BIO, + DRIVER_TYPE_NET, + DRIVER_TYPE_MISC, + MAX_DRIVER_TYPE +} driver_type_t; + +struct driver { + const char *name; + driver_probe_t *probe; + driver_attach_t *attach; + driver_detach_t *detach; + driver_shutdown_t *shutdown; + driver_type_t type; + size_t softc; /* size of device softc struct */ + TAILQ_ENTRY(driver) link; /* list of devices on bus */ + void *buspriv; /* private data for the owning bus */ +}; + +typedef enum device_state device_state_t; +enum device_state { + DS_NOTPRESENT, /* not probed or probe failed */ + DS_ALIVE, /* probe succeeded */ + DS_ATTACHED, /* attach method called */ + DS_BUSY /* device is open */ +}; + +/* + * Busses - containers of devices. + */ +typedef void bus_print_device_t(bus_t bus, device_t dev); +typedef int bus_read_ivar_t(bus_t bus, device_t dev, + int index, u_long *result); +typedef int bus_write_ivar_t(bus_t bus, device_t dev, + int index, u_long value); +typedef int bus_map_intr_t(bus_t bus, device_t dev, + driver_intr_t *intr, void *arg); + +typedef struct bus_ops { + bus_print_device_t *print_device; + bus_read_ivar_t *read_ivar; + bus_write_ivar_t *write_ivar; + bus_map_intr_t *map_intr; +} bus_ops_t; + +typedef TAILQ_HEAD(device_list, device) device_list_t; + +struct bus { + bus_ops_t *ops; + device_t dev; /* device instance in parent bus */ + device_list_t devices; +}; + +/* + * Bus priorities. This determines the order in which busses are probed. + */ +#define BUS_PRIORITY_HIGH 1 +#define BUS_PRIORITY_MEDIUM 2 +#define BUS_PRIORITY_LOW 3 + +/* + * The root bus, to which all top-level busses are attached. + */ +extern bus_t root_bus; +extern devclass_t root_devclass; +void root_bus_configure(void); + +/* + * Access functions for bus. + */ +device_t bus_get_device(bus_t bus); +void bus_print_device(bus_t bus, device_t dev); +int bus_read_ivar(bus_t bus, device_t dev, + int index, u_long *result); +int bus_write_ivar(bus_t bus, device_t dev, + int index, u_long value); +int bus_map_intr(bus_t bus, device_t dev, driver_intr_t *intr, void *arg); +device_t bus_add_device(bus_t bus, const char *name, + int unit, void *ivars); +device_t bus_add_device_after(bus_t bus, device_t place, const char *name, + int unit, void *ivars); +int bus_delete_device(bus_t bus, device_t dev); +device_t bus_find_device(bus_t bus, const char *classname, int unit); + +/* + * Useful functions for implementing busses. + */ +void bus_init(bus_t bus, device_t dev, bus_ops_t *ops); +driver_attach_t bus_generic_attach; +driver_detach_t bus_generic_detach; +driver_shutdown_t bus_generic_shutdown; +bus_print_device_t null_print_device; +bus_read_ivar_t null_read_ivar; +bus_write_ivar_t null_write_ivar; +bus_map_intr_t null_map_intr; +extern bus_ops_t null_bus_ops; + +/* + * Access functions for device. + */ +bus_t device_get_parent(device_t dev); +driver_t *device_get_driver(device_t dev); +devclass_t device_get_devclass(device_t dev); +int device_set_devclass(device_t dev, const char *classname); +int device_set_driver(device_t dev, driver_t *driver); +void device_set_desc(device_t dev, const char* desc); +const char* device_get_desc(device_t dev); +const char* device_get_name(device_t dev); +int device_get_unit(device_t dev); +void *device_get_softc(device_t dev); +void *device_get_ivars(device_t dev); +device_state_t device_get_state(device_t dev); +void device_enable(device_t dev); +void device_disable(device_t dev); +void device_busy(device_t dev); +void device_unbusy(device_t dev); +int device_is_enabled(device_t dev); +int device_is_alive(device_t dev); /* did probe succeed? */ +int device_probe_and_attach(device_t dev); +int device_detach(device_t dev); +int device_shutdown(device_t dev); + +/* + * Access functions for devclass. + */ +devclass_t devclass_find(const char *classname); +int devclass_add_driver(devclass_t dc, driver_t *driver); +int devclass_delete_driver(devclass_t dc, driver_t *driver); +driver_t *devclass_find_driver(devclass_t dc, const char *classname); +const char *devclass_get_name(devclass_t dc); +device_t devclass_get_device(devclass_t dc, int unit); +void *devclass_get_softc(devclass_t dc, int unit); +int devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp); +int devclass_get_maxunit(devclass_t dc); + +#ifdef _SYS_MODULE_H_ + +/* + * Module support for automatically adding drivers to busses. + */ +struct driver_module_data { + modeventhand_t chainevh; + void* chainarg; + const char* busname; + driver_t* driver; + devclass_t* devclass; +}; + +int driver_module_handler __P((module_t, modeventtype_t, void*)); + +#define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \ + \ +static struct driver_module_data name##_driver_mod = { \ + evh, arg, \ + #busname, \ + &driver, \ + &devclass, \ +}; \ + \ +static moduledata_t name##_mod = { \ + #name, \ + driver_module_handler, \ + &name##_driver_mod \ +}; \ +DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE) + +#define CDEV_DRIVER_MODULE(name, busname, driver, devclass, \ + major, devsw, evh, arg) \ + \ +static struct cdevsw_module_data name##_cdevsw_mod = { \ + evh, arg, makedev(major, 0), &devsw \ +}; \ + \ +DRIVER_MODULE(name, busname, driver, devclass, \ + cdevsw_module_handler, &name##_cdevsw_mod) + +#endif + +#endif /* KERNEL */ + +#endif /* !_SYS_BUS_H_ */ diff --git a/sys/sys/bus_private.h b/sys/sys/bus_private.h new file mode 100644 index 0000000..5a9fba9 --- /dev/null +++ b/sys/sys/bus_private.h @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 1997 Doug Rabson + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id$ + */ + +#ifndef _SYS_BUS_PRIVATE_H_ +#define _SYS_BUS_PRIVATE_H_ + +#include <sys/bus.h> + +/* + * Forward declarations + */ +typedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t; +typedef TAILQ_HEAD(driver_list, driver) driver_list_t; + +struct devclass { + TAILQ_ENTRY(devclass) link; + driver_list_t drivers; /* bus devclasses store drivers for bus */ + char *name; + device_t *devices; /* array of devices indexed by unit */ + int maxunit; /* size of devices array */ + int nextunit; /* next unused unit number */ +}; + +/* + * Implementation of device. + */ +struct device { + TAILQ_ENTRY(device) link; /* list of devices on a bus */ + bus_t parent; + driver_t *driver; + devclass_t devclass; /* device class which we are in */ + int unit; + const char* desc; /* driver specific description */ + int busy; /* count of calls to device_busy() */ + device_state_t state; + int flags; +#define DF_ENABLED 1 /* device should be probed/attached */ +#define DF_FIXEDCLASS 2 /* devclass specified at create time */ +#define DF_WILDCARD 4 /* unit was originally wildcard */ + void *ivars; + void *softc; +}; + + + +#endif /* !_SYS_BUS_PRIVATE_H_ */ diff --git a/sys/sys/elf64.h b/sys/sys/elf64.h new file mode 100644 index 0000000..a17f082 --- /dev/null +++ b/sys/sys/elf64.h @@ -0,0 +1,312 @@ +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * 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 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 AUTHOR 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. + * + * $Id: elf64.h,v 1.2 1997/08/30 18:58:31 peter Exp $ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef u_int64_t Elf64_Addr; +typedef u_int16_t Elf64_Half; +typedef u_int64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef u_int32_t Elf64_Word; +typedef u_int64_t Elf64_Size; + +/* + * ELF header. + */ + +#define EI_NIDENT 16 /* Size of e_ident array. */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* Indexes into the e_ident array. */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_PAD 7 /* Start of padding (per SVR4 ABI). */ +#define EI_BRAND 8 /* Start of architecture identification. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M64 1 /* AT&T WE64100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_486 6 /* Intel i486. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */ + +/* Extensions */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_SPARC64 11 /* SPARC v9 64-bit unoffical */ +#define EM_PARISC 15 /* HPPA */ +#define EM_PPC 20 /* PowerPC */ +#define EM_ALPHA 0x9026 /* Alpha */ + + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Size sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Word sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Size sh_addralign; /* Alignment in bytes. */ + Elf64_Size sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends*/ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relation section without addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Size p_filesz; /* Size of contents in file. */ + Elf64_Size p_memsz; /* Size of contents in memory. */ + Elf64_Size p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ + +#define PT_COUNT 7 /* Number of defined p_type values. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Size d_tag; /* Entry type. */ + union { + Elf64_Size d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of Elf64_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of Elf64_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each Elf64_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. */ +#define DT_REL 17 /* Address of Elf64_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of Elf64_Rel relocations. */ +#define DT_RELENT 19 /* Size of each Elf64_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ + +#define DT_COUNT 24 /* Number of defined d_tag values. */ + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Size r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Size r_info; /* Relocation type and symbol index. */ + Elf64_Off r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 8) +#define ELF64_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Size st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Symbol Binding - ELF64_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific symbol bindings */ + +/* Symbol type - ELF64_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific symbol types */ + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +#endif /* !_SYS_ELF64_H_ */ diff --git a/sys/sys/module.h b/sys/sys/module.h index fe54185..7553a77 100644 --- a/sys/sys/module.h +++ b/sys/sys/module.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: module.h,v 1.1 1997/05/07 16:05:45 dfr Exp $ + * $Id: module.h,v 1.2 1997/10/24 05:29:07 jmg Exp $ */ #ifndef _SYS_MODULE_H_ @@ -52,7 +52,8 @@ typedef struct moduledata { } moduledata_t; #define DECLARE_MODULE(name, data, sub, order) \ -SYSINIT(name##module, sub, order, module_register_init, &data) +SYSINIT(name##module, sub, order, module_register_init, &data) \ +struct __hack void module_register_init(void *data); int module_register(const char *name, modeventhand_t callback, void *arg); |