diff options
Diffstat (limited to 'sys/arch')
230 files changed, 12255 insertions, 5237 deletions
diff --git a/sys/arch/alpha/Makefile b/sys/arch/alpha/Makefile index 116bfe45f14..7724b7b9656 100644 --- a/sys/arch/alpha/Makefile +++ b/sys/arch/alpha/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.2 1996/07/29 22:57:03 niklas Exp $ +# $OpenBSD: Makefile,v 1.3 1996/10/30 22:37:51 niklas Exp $ # $NetBSD: Makefile,v 1.3 1995/02/27 16:36:07 cgd Exp $ # Makefile for alpha tags file and boot blocks diff --git a/sys/arch/alpha/README b/sys/arch/alpha/README index c0d5b25262d..eeb22268302 100644 --- a/sys/arch/alpha/README +++ b/sys/arch/alpha/README @@ -1,16 +1,19 @@ -$OpenBSD: README,v 1.4 1996/07/29 22:57:06 niklas Exp $ -$NetBSD: README,v 1.8.4.1 1996/06/13 20:49:01 cgd Exp $ +$OpenBSD: README,v 1.5 1996/10/30 22:37:53 niklas Exp $ +$NetBSD: README,v 1.10 1996/07/09 22:08:28 cgd Exp $ -Obtaining NetBSD/Alpha sources and binaries: +[ Don't trust this file yet, it contains a lot of inaccuracies. When it's + ready, this notice will be removed. -NH ] - NetBSD/Alpha's sources, with the exceptions of the GNU - toolchain and X11 code, are integrated into NetBSD-current, +Obtaining OpenBSD/Alpha sources and binaries: + + OpenBSD/Alpha's sources, with the exceptions of the GNU + toolchain and X11 code, are integrated into OpenBSD-current, and are available from: - ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-current/ + ftp://ftp.openbsd.org/pub/OpenBSD/ - The latest NetBSD/Alpha binary snapshot, and source snapshots + The latest OpenBSD/Alpha binary snapshot, and source snapshots for the toolchain and X11 code, can be found at: - ftp://ftp.netbsd.org/pub/NetBSD/arch/alpha + ftp://ftp.openbsd.org/pub/OpenBSD/arch/alpha Binary snapshots include two different set of system binaries: (1) an rz25 disk image, for first-time installation @@ -25,24 +28,24 @@ Obtaining NetBSD/Alpha sources and binaries: Binary snapshots include a kernel image which is the same as the one on the rz25 disk image. - The sources provided seperately from the normal NetBSD-current + The sources provided seperately from the normal OpenBSD-current distribution are: (1) complete compiler toolchain sources (2) diffs against the XFree86 3.1.2 distribution to - make X work with NetBSD/Alpha. (Note that + make X work with OpenBSD/Alpha. (Note that at this time, the diffs are against 3.1.2, i.e. not against 3.1.2D, etc.) - If you are using or are interested in the NetBSD/Alpha port, I - suggest that you subscribe to the NetBSD "port-alpha" mailing list - by sending an email message to majordomo@netbsd.org with no + If you are using or are interested in the OpenBSD/Alpha port, I + suggest that you subscribe to the OpenBSD "port-alpha" mailing list + by sending an email message to majordomo@openbsd.org with no subject and with a body of "subscribe port-alpha" (without the quotes). For help on using majordomo, send it mail with an empty - subject and body. In general, questions about NetBSD/Alpha + subject and body. In general, questions about OpenBSD/Alpha are best asked on that mailing list (rather than by sending me mail directly). -Installing the NetBSD/Alpha distribution: +Installing the OpenBSD/Alpha distribution: [ Note that these instructions are minimal; it's assumed that if you're going to be installing this, you're knowledgeable about @@ -51,7 +54,7 @@ Installing the NetBSD/Alpha distribution: good enough to get you running, get in touch with me and I'll try to help you. ] - To install the NetBSD/Alpha distribution, you'll need a disk at + To install the OpenBSD/Alpha distribution, you'll need a disk at least the size of an RZ25 -- about 406Mb. Once you've gotten the binary distribution, gunzip it and dd it to the raw disk. The binary distribution includes a disklabel and boot block, so you don't need @@ -60,7 +63,7 @@ Installing the NetBSD/Alpha distribution: Berkeley Fast File System format, so that you can mount, read, and write them under Digital UNIX. - If your are using one of the supported systems that includes a + If you are using one of the supported systems that includes a PCI bus, and have either a PCI VGA frame buffer of any type or a ZLXp-E1 frame buffer, you may use it as console. (If you are using your frame buffer as the console, you should use the @@ -68,8 +71,8 @@ Installing the NetBSD/Alpha distribution: Alpha or have a different kind of frame buffer, you have to use a serial console.) - Boot the Alpha with the NetBSD disk, supplying the boot flag "-s". - It should print something like "NetBSD/Alpha Boot program", load + Boot the Alpha with the OpenBSD disk, supplying the boot flag "-s". + It should print something like "OpenBSD/Alpha Boot program", load the kernel, print a copyright, and print various startup messages. After a short while, you should be asked for the name of a shell @@ -109,12 +112,16 @@ Installing the NetBSD/Alpha distribution: Once those files are created, you should be able to boot the system multi-user. To do so, halt the system and boot again from the - NetBSD disk, this time supplying the boot flag "-a". + OpenBSD disk, this time supplying the boot flag "-a". If you used a disk other than an RZ25, you may want to edit the disk's disklabel, and create one or more partitions after the existing partitions to use the extra space. -Chris Demetriou -cgd@cs.cmu.edu +This document was derived from the NetBSD version originally written by +Chris Demetriou <cgd@cs.cmu.edu>, + +Niklas Hallqvist +niklas@openbsd.org + diff --git a/sys/arch/alpha/STATUS b/sys/arch/alpha/STATUS index b0d70786deb..62539c2ea7d 100644 --- a/sys/arch/alpha/STATUS +++ b/sys/arch/alpha/STATUS @@ -1,17 +1,16 @@ -$OpenBSD: STATUS,v 1.4 1996/07/29 22:57:07 niklas Exp $ -$NetBSD: STATUS,v 1.3.4.1 1996/06/13 20:49:04 cgd Exp $ +$OpenBSD: STATUS,v 1.5 1996/10/30 22:37:54 niklas Exp $ +$NetBSD: STATUS,v 1.5 1996/09/06 04:01:37 cgd Exp $ -NetBSD/Alpha's Status +OpenBSD/Alpha's Status If you find an inaccuracy in this file, can clarify it in any place, -etc., please send mail to me (cgd@cs.cmu.edu). +etc., please send mail to me (niklas@appli.se). Supported hardware: - DEC 3000/[456789]00 (I've only tested it on the 400 and - 600, but the rest should "just work) using the following - peripherals: + DEC 3000/[456789]00 (I've not tested them, but they should + "just work") using the following peripherals: Supported hardware: Built-in serial ports @@ -58,12 +57,11 @@ Supported hardware: DEC ZLXp-E2 and ZLXp-E3 PCI video boards. Other PCI boards. - AlphaStation 600 systems, with the same supported hardware - list as the AlphaStation {200,250,255,400} systems. (NOTE - THAT THAT MEANS THE AlphaStation 600's BUILT-IN SCSI + AlphaStation 500 and 600 systems, with the same supported + hardware list as the AlphaStation {200,250,255,400} systems. + (NOTE THAT THAT MEANS THE AlphaStation 600's BUILT-IN SCSI CONTROLLERS DO NOT WORK. You'll need to get a 53c810 board, - or run diskless.) AlphaStation 500 systems may work, but - have not been tested. + or run diskless.) AXPpci systems (including Multia), with the same supported hardware list as the AlphaStation {200,250,255,400} systems. @@ -75,16 +73,9 @@ At this time none of the following systems are supported: in disguise). Multiprocessor Alpha systems -I was hoping to get a DECpc AXP port working "for free" based on -the PCI work, but the DECpc AXP is a very different (and, in my -opinion, very alien) piece of hardware. If somebody wants to make -NetBSD/Alpha run on the DECpc AXP system, get in touch and I'll do -what I can to help you get started. - - Console frame buffers & keyboard are supported only with the frame buffers and keyboards mentioned as supported above. On other systems -(including all TurboChannel-based machines), NetBSD/Alpha _must_ be used +(including all TurboChannel-based machines), OpenBSD/Alpha _must_ be used with a serial console. To configure various Alpha systems to use a serial console, do the following depending on the model: @@ -108,10 +99,13 @@ See the file src/sys/arch/alpha/README to find out how to get the latest sources and binaries. Please see the file src/sys/arch/alpha/TODO.users for a list of things -that users can do to help NetBSD/Alpha improve. If you're interested +that users can do to help OpenBSD/Alpha improve. If you're interested in doing any of them, or porting to new hardware, get in touch and I'll do what I can to help. -Chris Demetriou -cgd@cs.cmu.edu +This document was derived from the NetBSD version originally written by +Chris Demetriou <cgd@cs.cmu.edu>. + +Niklas Hallqvist +niklas@openbsd.org diff --git a/sys/arch/alpha/TODO.users b/sys/arch/alpha/TODO.users index 7991cb7ae27..f9e29249e0b 100644 --- a/sys/arch/alpha/TODO.users +++ b/sys/arch/alpha/TODO.users @@ -1,10 +1,10 @@ -$OpenBSD: TODO.users,v 1.4 1996/07/29 22:57:08 niklas Exp $ -$NetBSD: TODO.users,v 1.3.4.1 1996/06/13 20:49:07 cgd Exp $ +$OpenBSD: TODO.users,v 1.5 1996/10/30 22:37:55 niklas Exp $ +$NetBSD: TODO.users,v 1.5 1996/10/01 21:24:37 cgd Exp $ -The NetBSD/Alpha "User" To-Do List +The OpenBSD/Alpha "User" To-Do List -The following are things that I'd like to see "users" of NetBSD/Alpha +The following are things that I'd like to see "users" of OpenBSD/Alpha do. It's unlikely that I'll get around to them in any reasonable time frame, and I think they should get done. @@ -16,24 +16,23 @@ tell me about it, so that I can keep people from duplicating work. Once you've done something on this list, send me context diffs. -Chris Demetriou -cgd@cs.cmu.edu +This document is derived from the NetBSD version originally written by +Chris Demetriou <cgd@cs.cmu.edu>. + +Niklas Hallqvist +niklas@openbsd.org -- Test programs; find and fix bugs. In particular: (1) make sure accounting works - (2) last i checked, 'file' core dumped - (3) /usr/games + (2) /usr/games Test TurboChannel option slot support. Write TurboChannel option board drivers. Test PMAD-A (TC le) driver. -Get the GNU tools to generate a.out binaries for the alpha. Once that -is done, make the rest of the NetBSD a.out-manipulation tools (e.g. nm) -work. +Make DDB work. + +Add isadma support. -Make DDB work. (For completeness, may require a.out kernel binaries -and/or some ecoff symbol handling code to be written; the former is -strongly preferred.) +Add floppy support (requires isadma). -Track down any bugs caused by compiling the kernel with -O. (At least -some of these may be code generation bugs.) +Add WSS (audio) support (requires isadma).
\ No newline at end of file diff --git a/sys/arch/alpha/alpha/autoconf.c b/sys/arch/alpha/alpha/autoconf.c index 3f0bbe7b631..7231ee3d031 100644 --- a/sys/arch/alpha/alpha/autoconf.c +++ b/sys/arch/alpha/alpha/autoconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: autoconf.c,v 1.3 1996/07/29 22:57:12 niklas Exp $ */ -/* $NetBSD: autoconf.c,v 1.3.4.3 1996/06/14 20:42:41 cgd Exp $ */ +/* $OpenBSD: autoconf.c,v 1.4 1996/10/30 22:37:57 niklas Exp $ */ +/* $NetBSD: autoconf.c,v 1.14 1996/10/13 02:59:23 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -54,8 +54,11 @@ #include <sys/device.h> #include <machine/autoconf.h> +#include <machine/rpb.h> #include <machine/prom.h> +#include <dev/cons.h> + extern char root_device[17]; /* XXX */ struct device *booted_device; @@ -65,8 +68,11 @@ char boot_dev[128]; void parse_prom_bootdev __P((void)); int atoi __P((char *)); +void setroot __P((void)); +void swapconf __P((void)); -struct device *parsedisk __P((char *str, int len, int defpart, dev_t *devp)); +static struct device *parsedisk __P((char *str, int len, int defpart, + dev_t *devp)); static struct device *getdisk __P((char *str, int len, int defpart, dev_t *devp)); static int findblkmajor __P((struct device *dv)); @@ -100,6 +106,7 @@ configure() /* * Configure swap space and related parameters. */ +void swapconf() { struct swdevt *swp; @@ -126,12 +133,17 @@ struct nam2blk { } nam2blk[] = { { "st", 2 }, { "cd", 3 }, + { "rd", 6 }, { "sd", 8 }, #if 0 { "fd", XXX }, #endif }; +#ifdef RAMDISK_HOOKS +static struct device fakerdrootdev = { DV_DISK, {}, NULL, 0, "rd0", NULL }; +#endif + static int findblkmajor(dv) struct device *dv; @@ -168,6 +180,9 @@ getdisk(str, len, defpart, devp) if ((dv = parsedisk(str, len, defpart, devp)) == NULL) { printf("use one of:"); +#ifdef RAMDISK_HOOKS + printf(" %s[a-h]", fakerdrootdev.dv_xname); +#endif for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) { if (dv->dv_class == DV_DISK) @@ -177,12 +192,12 @@ getdisk(str, len, defpart, devp) printf(" %s", dv->dv_xname); #endif } - printf("\n"); + printf(" halt\n"); } return (dv); } -struct device * +static struct device * parsedisk(str, len, defpart, devp) char *str; int len, defpart; @@ -194,6 +209,10 @@ parsedisk(str, len, defpart, devp) if (len == 0) return (NULL); + + if (len == 4 && !strcmp(str, "halt")) + boot(RB_HALT /* , NULL */); + cp = str + len - 1; c = *cp; if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) { @@ -202,9 +221,18 @@ parsedisk(str, len, defpart, devp) } else part = defpart; +#ifdef RAMDISK_HOOKS + if (strcmp(str, fakerdrootdev.dv_xname) == 0) { + dv = &fakerdrootdev; + goto gotdisk; + } +#endif for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) { if (dv->dv_class == DV_DISK && strcmp(str, dv->dv_xname) == 0) { +#ifdef RAMDISK_HOOKS +gotdisk: +#endif majdev = findblkmajor(dv); if (majdev < 0) panic("parsedisk"); @@ -233,6 +261,7 @@ parsedisk(str, len, defpart, devp) * (ie. DV_DISK or DV_IFNET) because of how (*mountroot) is written. * That should be fixed. */ +void setroot() { struct swdevt *swp; @@ -252,8 +281,13 @@ setroot() extern int ffs_mountroot __P((void *)); #endif +#ifdef RAMDISK_HOOKS + bootdv = &fakerdrootdev; + bootpartition = 0; +#else bootdv = booted_device; bootpartition = booted_partition; +#endif /* * If 'swap generic' and we couldn't determine root device, @@ -265,19 +299,18 @@ setroot() if (boothowto & RB_ASKNAME) { for (;;) { printf("root device"); - if (bootdv != NULL) - printf(" (default %s%c)", - bootdv->dv_xname, - bootdv->dv_class == DV_DISK - ? bootpartition + 'a' : ' '); + if (bootdv != NULL) { + printf(" (default %s", bootdv->dv_xname); + if (bootdv->dv_class == DV_DISK) + printf("%c", bootpartition + 'a'); + printf(")"); + } printf(": "); len = getstr(buf, sizeof(buf)); if (len == 0 && bootdv != NULL) { strcpy(buf, bootdv->dv_xname); len = strlen(buf); } - if (len == 4 && !strcmp(buf, "halt")) - boot(RB_HALT); if (len > 0 && buf[len - 1] == '*') { buf[--len] = '\0'; dv = getdisk(buf, len, 1, &nrootdev); @@ -304,8 +337,10 @@ setroot() } for (;;) { printf("swap device"); - printf(" (default %s%c)", rootdv->dv_xname, - rootdv->dv_class == DV_DISK?'b':' '); + printf(" (default %s", rootdv->dv_xname); + if (rootdv->dv_class == DV_DISK) + printf("b"); + printf(")"); printf(": "); len = getstr(buf, sizeof(buf)); if (len == 0) { @@ -326,8 +361,6 @@ setroot() swapdv = rootdv; break; } - if (len == 4 && !strcmp(buf, "halt")) - boot(RB_HALT); dv = getdisk(buf, len, 1, &nswapdev); if (dv) { if (dv->dv_class == DV_IFNET) @@ -368,7 +401,7 @@ gotswap: swdevt[1].sw_dev = NODEV; } else { /* - * `root DEV swap DEV': honour rootdev/swdevt. + * `root DEV swap DEV': honor rootdev/swdevt. * rootdev/swdevt/mountroot already properly set. */ @@ -545,7 +578,6 @@ atoi(s) char *s; { int n, neg; - char c; n = 0; neg = 0; diff --git a/sys/arch/alpha/alpha/clock.c b/sys/arch/alpha/alpha/clock.c index 82a455b716c..3b69e90b6b2 100644 --- a/sys/arch/alpha/alpha/clock.c +++ b/sys/arch/alpha/alpha/clock.c @@ -1,5 +1,5 @@ -/* $OpenBSD: clock.c,v 1.5 1996/07/29 22:57:13 niklas Exp $ */ -/* $NetBSD: clock.c,v 1.10 1996/04/23 15:26:06 cgd Exp $ */ +/* $OpenBSD: clock.c,v 1.6 1996/10/30 22:37:58 niklas Exp $ */ +/* $NetBSD: clock.c,v 1.13 1996/10/13 02:59:25 christos Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -49,6 +49,7 @@ #include <sys/device.h> #include <machine/rpb.h> +#include <machine/autoconf.h> #include <alpha/alpha/clockvar.h> @@ -105,8 +106,6 @@ void cpu_initclocks() { extern int tickadj; - struct clock_softc *csc; - int fractick; if (clockfns == NULL) panic("cpu_initclocks: no clock attached"); @@ -160,8 +159,8 @@ inittodr(base) { register int days, yr; struct clocktime ct; - long deltat; - int badbase, s; + time_t deltat; + int badbase; if (base < 5*SECYR) { printf("WARNING: preposterous time in file system"); @@ -227,7 +226,6 @@ resettodr() { register int t, t2; struct clocktime ct; - int s; if (!clockinitted) return; @@ -238,6 +236,7 @@ resettodr() /* compute the year */ ct.year = 69; + t = t2; /* XXX ? */ while (t2 >= 0) { /* whittle off years */ t = t2; ct.year++; diff --git a/sys/arch/alpha/alpha/clockvar.h b/sys/arch/alpha/alpha/clockvar.h index 05c0d6ad797..bdf66e16909 100644 --- a/sys/arch/alpha/alpha/clockvar.h +++ b/sys/arch/alpha/alpha/clockvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: clockvar.h,v 1.3 1996/07/29 22:57:15 niklas Exp $ */ +/* $OpenBSD: clockvar.h,v 1.4 1996/10/30 22:37:59 niklas Exp $ */ /* $NetBSD: clockvar.h,v 1.2 1996/04/17 22:01:21 cgd Exp $ */ /* diff --git a/sys/arch/alpha/alpha/conf.c b/sys/arch/alpha/alpha/conf.c index 84ce29f2af1..6cb3cb311a0 100644 --- a/sys/arch/alpha/alpha/conf.c +++ b/sys/arch/alpha/alpha/conf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: conf.c,v 1.7 1996/10/19 13:26:03 mickey Exp $ */ -/* $NetBSD: conf.c,v 1.11 1996/04/12 02:07:23 cgd Exp $ */ +/* $OpenBSD: conf.c,v 1.8 1996/10/30 22:38:00 niklas Exp $ */ +/* $NetBSD: conf.c,v 1.16 1996/10/18 21:26:57 cgd Exp $ */ /*- * Copyright (c) 1991 The Regents of the University of California. @@ -44,14 +44,6 @@ #include <sys/conf.h> #include <sys/vnode.h> -int ttselect __P((dev_t, int, struct proc *)); - -#ifndef LKM -#define lkmenodev enodev -#else -int lkmenodev(); -#endif - bdev_decl(sw); #include "st.h" bdev_decl(st); @@ -63,6 +55,8 @@ bdev_decl(sd); bdev_decl(vnd); #include "ccd.h" bdev_decl(ccd); +#include "rd.h" +bdev_decl(rd); struct bdevsw bdevsw[] = { @@ -72,7 +66,7 @@ struct bdevsw bdevsw[] = bdev_disk_init(NCD,cd), /* 3: SCSI CD-ROM */ bdev_notdef(), /* 4 */ bdev_notdef(), /* 5 */ - bdev_notdef(), /* 6 */ + bdev_disk_init(NRD,rd), /* 6: ram disk driver */ bdev_disk_init(NCCD,ccd), /* 7: concatenated disk driver */ bdev_disk_init(NSD,sd), /* 8: SCSI disk */ bdev_disk_init(NVND,vnd), /* 9: vnode disk driver */ @@ -89,7 +83,7 @@ int nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]); #define cdev_wscons_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ - dev_init(c,n,tty), ttselect, dev_init(c,n,mmap), D_TTY } + dev_init(c,n,tty), ttselect /* ttpoll */, dev_init(c,n,mmap), D_TTY } /* open, close, write, ioctl */ #define cdev_lpt_init(c,n) { \ @@ -126,12 +120,6 @@ cdev_decl(cd); cdev_decl(ch); #include "scc.h" cdev_decl(scc); -#ifdef LKM -#define NLKM 1 -#else -#define NLKM 0 -#endif -cdev_decl(lkm); #include "audio.h" cdev_decl(audio); #include "wscons.h" @@ -142,6 +130,9 @@ cdev_decl(kbd); cdev_decl(ms); #include "lpt.h" cdev_decl(lpt); +cdev_decl(rd); +#include "ss.h" +cdev_decl(ss); #include "uk.h" cdev_decl(uk); @@ -178,12 +169,13 @@ struct cdevsw cdevsw[] = cdev_wscons_init(NWSCONS,wscons), /* 25: workstation console */ cdev_tty_init(NCOM,com), /* 26: ns16550 UART */ cdev_disk_init(NCCD,ccd), /* 27: concatenated disk driver */ - cdev_notdef(), /* 28 */ + cdev_disk_init(NRD,rd), /* 28: ram disk driver */ cdev_mouse_init(NWSCONS,kbd), /* 29: /dev/kbd XXX */ cdev_mouse_init(NWSCONS,ms), /* 30: /dev/mouse XXX */ cdev_lpt_init(NLPT,lpt), /* 31: parallel printer */ - cdev_uk_init(NUK,uk), /* 32: unknown SCSI */ - cdev_random_init(1,random), /* 33: random data source */ + cdev_scanner_init(NSS,ss), /* 32: SCSI scanner */ + cdev_uk_init(NUK,uk), /* 33: SCSI unknown */ + cdev_random_init(1,random), /* 34: random data source */ }; int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]); @@ -203,6 +195,7 @@ dev_t swapdev = makedev(1, 0); /* * Returns true if dev is /dev/mem or /dev/kmem. */ +int iskmemdev(dev) dev_t dev; { @@ -213,6 +206,7 @@ iskmemdev(dev) /* * Returns true if dev is /dev/zero. */ +int iszerodev(dev) dev_t dev; { @@ -231,12 +225,12 @@ static int chrtoblktbl[] = { /* 5 */ NODEV, /* 6 */ NODEV, /* 7 */ NODEV, - /* 8 */ 8, - /* 9 */ 9, + /* 8 */ 8, /* sd */ + /* 9 */ 9, /* vnd */ /* 10 */ NODEV, /* 11 */ NODEV, - /* 12 */ NODEV, - /* 13 */ 3, + /* 12 */ 2, /* st */ + /* 13 */ 3, /* cd */ /* 14 */ NODEV, /* 15 */ NODEV, /* 16 */ NODEV, @@ -250,16 +244,20 @@ static int chrtoblktbl[] = { /* 24 */ NODEV, /* 25 */ NODEV, /* 26 */ NODEV, - /* 27 */ 7, - /* 28 */ NODEV, + /* 27 */ 7, /* ccd */ + /* 28 */ 6, /* rd */ /* 29 */ NODEV, /* 30 */ NODEV, /* 31 */ NODEV, + /* 32 */ NODEV, + /* 33 */ NODEV, + /* 34 */ NODEV, }; /* * Convert a character device number to a block device number. */ +dev_t chrtoblk(dev) dev_t dev; { diff --git a/sys/arch/alpha/alpha/cpu.c b/sys/arch/alpha/alpha/cpu.c index 4e79e5ca346..ccace66662d 100644 --- a/sys/arch/alpha/alpha/cpu.c +++ b/sys/arch/alpha/alpha/cpu.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cpu.c,v 1.4 1996/07/29 22:57:18 niklas Exp $ */ -/* $NetBSD: cpu.c,v 1.9 1996/04/29 16:36:19 cgd Exp $ */ +/* $OpenBSD: cpu.c,v 1.5 1996/10/30 22:38:01 niklas Exp $ */ +/* $NetBSD: cpu.c,v 1.12 1996/10/13 02:59:26 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -29,14 +29,15 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/device.h> #include <machine/autoconf.h> #include <machine/rpb.h> /* Definition of the driver for autoconfig. */ -static int cpumatch(struct device *, void *, void *); -static void cpuattach(struct device *, struct device *, void *); +int cpumatch __P((struct device *, void *, void *)); +void cpuattach __P((struct device *, struct device *, void *)); struct cfattach cpu_ca = { sizeof(struct device), cpumatch, cpuattach @@ -46,15 +47,12 @@ struct cfdriver cpu_cd = { NULL, "cpu", DV_DULL }; -static int cpuprint __P((void *, char *pnp)); - -static int +int cpumatch(parent, cfdata, aux) struct device *parent; void *cfdata; void *aux; { - struct cfdata *cf = cfdata; struct confargs *ca = aux; /* make sure that we're looking for a CPU. */ @@ -64,7 +62,7 @@ cpumatch(parent, cfdata, aux) return (1); } -static void +void cpuattach(parent, dev, aux) struct device *parent; struct device *dev; @@ -88,7 +86,7 @@ cpuattach(parent, dev, aux) int ndc21064_cpu_minor = sizeof(dc21064_cpu_minor) / sizeof(dc21064_cpu_minor[0]); u_int32_t major, minor; - int needcomma, needrev, i; + int needcomma; p = (struct pcs*)((char *)hwrpb + hwrpb->rpb_pcs_off + (dev->dv_unit * hwrpb->rpb_pcs_size)); @@ -160,15 +158,3 @@ cpuattach(parent, dev, aux) * and more compact if done the 'normal' way. */ } - -static int -cpuprint(aux, pnp) - void *aux; - char *pnp; -{ - register struct confargs *ca = aux; - - if (pnp) - printf("%s at %s", ca->ca_name, pnp); - return (UNCONF); -} diff --git a/sys/arch/alpha/alpha/dec_2100_a50.c b/sys/arch/alpha/alpha/dec_2100_a50.c index 9d61c61deff..27fc4f3a196 100644 --- a/sys/arch/alpha/alpha/dec_2100_a50.c +++ b/sys/arch/alpha/alpha/dec_2100_a50.c @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_2100_a50.c,v 1.4 1996/07/29 22:57:20 niklas Exp $ */ -/* $NetBSD: dec_2100_a50.c,v 1.6.4.2 1996/06/14 20:42:23 cgd Exp $ */ +/* $OpenBSD: dec_2100_a50.c,v 1.5 1996/10/30 22:38:01 niklas Exp $ */ +/* $NetBSD: dec_2100_a50.c,v 1.14 1996/10/13 02:59:28 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/device.h> #include <sys/termios.h> #include <dev/cons.h> @@ -99,9 +100,7 @@ dec_2100_a50_consinit() /* serial console ... */ /* XXX */ { - extern bus_chipset_tag_t comconsbc; /* set */ - extern bus_io_handle_t comcomsioh; /* set */ - extern int comconsaddr, comconsinit; /* set */ + extern int comconsinit; /* set */ extern int comdefaultrate; extern int comcngetc __P((dev_t)); extern void comcnputc __P((dev_t, int)); @@ -148,7 +147,7 @@ dec_2100_a50_device_register(dev, aux) struct device *dev; void *aux; { - static int found; + static int found, initted, scsiboot, netboot; static struct device *pcidev, *scsidev; struct bootdev_data *b = bootdev_data; struct device *parent = dev->dv_parent; @@ -158,6 +157,15 @@ dec_2100_a50_device_register(dev, aux) if (found) return; + if (!initted) { + scsiboot = (strcmp(b->protocol, "SCSI") == 0); + netboot = (strcmp(b->protocol, "BOOTP") == 0); +#if 0 + printf("scsiboot = %d, netboot = %d\n", scsiboot, netboot); +#endif + initted =1; + } + if (pcidev == NULL) { if (strcmp(cd->cd_name, "pci")) return; @@ -175,7 +183,7 @@ dec_2100_a50_device_register(dev, aux) } } - if (scsidev == NULL) { + if (scsiboot && (scsidev == NULL)) { if (parent != pcidev) return; else { @@ -194,9 +202,10 @@ dec_2100_a50_device_register(dev, aux) } } - if (!strcmp(cd->cd_name, "sd") || - !strcmp(cd->cd_name, "st") || - !strcmp(cd->cd_name, "cd")) { + if (scsiboot && + (!strcmp(cd->cd_name, "sd") || + !strcmp(cd->cd_name, "st") || + !strcmp(cd->cd_name, "cd"))) { struct scsibus_attach_args *sa = aux; if (parent->dv_parent != scsidev) @@ -228,4 +237,24 @@ dec_2100_a50_device_register(dev, aux) #endif found = 1; } + + if (netboot) { + if (parent != pcidev) + return; + else { + struct pci_attach_args *pa = aux; + + if (b->slot != pa->pa_device) + return; + + /* XXX function? */ + + booted_device = dev; +#if 0 + printf("\nbooted_device = %s\n", booted_device->dv_xname); +#endif + found = 1; + return; + } + } } diff --git a/sys/arch/alpha/alpha/dec_2100_a50.h b/sys/arch/alpha/alpha/dec_2100_a50.h index 6574866c1e8..69ffc6a1e30 100644 --- a/sys/arch/alpha/alpha/dec_2100_a50.h +++ b/sys/arch/alpha/alpha/dec_2100_a50.h @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_2100_a50.h,v 1.3 1996/07/29 22:57:21 niklas Exp $ */ -/* $NetBSD: dec_2100_a50.h,v 1.2.6.2 1996/06/13 18:35:10 cgd Exp $ */ +/* $OpenBSD: dec_2100_a50.h,v 1.4 1996/10/30 22:38:02 niklas Exp $ */ +/* $NetBSD: dec_2100_a50.h,v 1.6 1996/06/13 18:31:49 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/alpha/dec_3000_300.c b/sys/arch/alpha/alpha/dec_3000_300.c index 73729f5e812..0947428fb98 100644 --- a/sys/arch/alpha/alpha/dec_3000_300.c +++ b/sys/arch/alpha/alpha/dec_3000_300.c @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_3000_300.c,v 1.3 1996/07/29 22:57:23 niklas Exp $ */ -/* $NetBSD: dec_3000_300.c,v 1.2.6.2 1996/06/13 18:35:12 cgd Exp $ */ +/* $OpenBSD: dec_3000_300.c,v 1.4 1996/10/30 22:38:03 niklas Exp $ */ +/* $NetBSD: dec_3000_300.c,v 1.9 1996/10/13 02:59:30 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -42,6 +42,10 @@ #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> +char *dec_3000_300_modelname __P((void)); +void dec_3000_300_consinit __P((void)); +void dec_3000_300_device_register __P((struct device *, void *)); + char * dec_3000_300_modelname() { @@ -69,7 +73,6 @@ dec_3000_300_modelname() void dec_3000_300_consinit() { - } void @@ -77,7 +80,7 @@ dec_3000_300_device_register(dev, aux) struct device *dev; void *aux; { - static int found; + static int found, initted, scsiboot, netboot; static struct device *scsidev; struct bootdev_data *b = bootdev_data; struct device *parent = dev->dv_parent; @@ -87,7 +90,16 @@ dec_3000_300_device_register(dev, aux) if (found) return; - if (strcmp(cd->cd_name, "esp") == 0) { + if (!initted) { + scsiboot = (strcmp(b->protocol, "SCSI") == 0); + netboot = (strcmp(b->protocol, "BOOTP") == 0); +#if 0 + printf("scsiboot = %d, netboot = %d\n", scsiboot, netboot); +#endif + initted =1; + } + + if (scsiboot && (strcmp(cd->cd_name, "esp") == 0)) { if (b->slot == 4 && strcmp(parent->dv_cfdata->cf_driver->cd_name, "tcds") == 0) { @@ -100,9 +112,12 @@ dec_3000_300_device_register(dev, aux) #endif } } - } else if (strcmp(cd->cd_name, "sd") == 0 || - strcmp(cd->cd_name, "st") == 0 || - strcmp(cd->cd_name, "cd") == 0) { + } + + if (scsiboot && + (strcmp(cd->cd_name, "sd") == 0 || + strcmp(cd->cd_name, "st") == 0 || + strcmp(cd->cd_name, "cd") == 0)) { struct scsibus_attach_args *sa = aux; if (scsidev == NULL) @@ -137,4 +152,26 @@ dec_3000_300_device_register(dev, aux) #endif found = 1; } + + if (netboot) { + if (b->slot == 5 && strcmp(cd->cd_name, "le") == 0 && + strcmp(parent->dv_cfdata->cf_driver->cd_name, "ioasic") + == 0) { + /* + * no need to check ioasic_attach_args, since only + * one le on ioasic. + */ + + booted_device = dev; +#if 0 + printf("\nbooted_device = %s\n", booted_device->dv_xname); +#endif + found = 1; + return; + } + + /* + * XXX GENERIC SUPPORT FOR TC NETWORK BOARDS + */ + } } diff --git a/sys/arch/alpha/alpha/dec_3000_300.h b/sys/arch/alpha/alpha/dec_3000_300.h index b1d7e3e90bb..c7d9c27b7c7 100644 --- a/sys/arch/alpha/alpha/dec_3000_300.h +++ b/sys/arch/alpha/alpha/dec_3000_300.h @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_3000_300.h,v 1.3 1996/07/29 22:57:24 niklas Exp $ */ -/* $NetBSD: dec_3000_300.h,v 1.2.6.2 1996/06/13 18:35:13 cgd Exp $ */ +/* $OpenBSD: dec_3000_300.h,v 1.4 1996/10/30 22:38:04 niklas Exp $ */ +/* $NetBSD: dec_3000_300.h,v 1.6 1996/06/13 18:32:00 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/alpha/dec_3000_500.c b/sys/arch/alpha/alpha/dec_3000_500.c index ace50cef152..c1c08d08fd5 100644 --- a/sys/arch/alpha/alpha/dec_3000_500.c +++ b/sys/arch/alpha/alpha/dec_3000_500.c @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_3000_500.c,v 1.3 1996/07/29 22:57:26 niklas Exp $ */ -/* $NetBSD: dec_3000_500.c,v 1.1.6.2 1996/06/13 18:35:15 cgd Exp $ */ +/* $OpenBSD: dec_3000_500.c,v 1.4 1996/10/30 22:38:05 niklas Exp $ */ +/* $NetBSD: dec_3000_500.c,v 1.8 1996/10/13 02:59:31 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -42,6 +42,10 @@ #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> +char *dec_3000_500_modelname __P((void)); +void dec_3000_500_consinit __P((void)); +void dec_3000_500_device_register __P((struct device *, void *)); + char * dec_3000_500_modelname() { @@ -87,7 +91,6 @@ systype_flamingo: void dec_3000_500_consinit() { - } void @@ -95,7 +98,7 @@ dec_3000_500_device_register(dev, aux) struct device *dev; void *aux; { - static int found; + static int found, initted, scsiboot, netboot; static struct device *scsidev; struct bootdev_data *b = bootdev_data; struct device *parent = dev->dv_parent; @@ -105,7 +108,16 @@ dec_3000_500_device_register(dev, aux) if (found) return; - if (strcmp(cd->cd_name, "esp") == 0) { + if (!initted) { + scsiboot = (strcmp(b->protocol, "SCSI") == 0); + netboot = (strcmp(b->protocol, "BOOTP") == 0); +#if 0 + printf("scsiboot = %d, netboot = %d\n", scsiboot, netboot); +#endif + initted =1; + } + + if (scsiboot && (strcmp(cd->cd_name, "esp") == 0)) { if (b->slot == 6 && strcmp(parent->dv_cfdata->cf_driver->cd_name, "tcds") == 0) { @@ -118,9 +130,12 @@ dec_3000_500_device_register(dev, aux) #endif } } - } else if (strcmp(cd->cd_name, "sd") == 0 || - strcmp(cd->cd_name, "st") == 0 || - strcmp(cd->cd_name, "cd") == 0) { + } + + if (scsiboot && + (strcmp(cd->cd_name, "sd") == 0 || + strcmp(cd->cd_name, "st") == 0 || + strcmp(cd->cd_name, "cd") == 0)) { struct scsibus_attach_args *sa = aux; if (scsidev == NULL) @@ -155,4 +170,26 @@ dec_3000_500_device_register(dev, aux) #endif found = 1; } + + if (netboot) { + if (b->slot == 7 && strcmp(cd->cd_name, "le") == 0 && + strcmp(parent->dv_cfdata->cf_driver->cd_name, "ioasic") + == 0) { + /* + * no need to check ioasic_attach_args, since only + * one le on ioasic. + */ + + booted_device = dev; +#if 0 + printf("\nbooted_device = %s\n", booted_device->dv_xname); +#endif + found = 1; + return; + } + + /* + * XXX GENERIC SUPPORT FOR TC NETWORK BOARDS + */ + } } diff --git a/sys/arch/alpha/alpha/dec_3000_500.h b/sys/arch/alpha/alpha/dec_3000_500.h index 1dd53322834..c4e68b30b97 100644 --- a/sys/arch/alpha/alpha/dec_3000_500.h +++ b/sys/arch/alpha/alpha/dec_3000_500.h @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_3000_500.h,v 1.3 1996/07/29 22:57:27 niklas Exp $ */ -/* $NetBSD: dec_3000_500.h,v 1.2.6.2 1996/06/13 18:35:17 cgd Exp $ */ +/* $OpenBSD: dec_3000_500.h,v 1.4 1996/10/30 22:38:05 niklas Exp $ */ +/* $NetBSD: dec_3000_500.h,v 1.6 1996/06/13 18:32:04 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/alpha/dec_axppci_33.c b/sys/arch/alpha/alpha/dec_axppci_33.c index 74e4ab96a60..43ce14c25cb 100644 --- a/sys/arch/alpha/alpha/dec_axppci_33.c +++ b/sys/arch/alpha/alpha/dec_axppci_33.c @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_axppci_33.c,v 1.3 1996/07/29 22:57:29 niklas Exp $ */ -/* $NetBSD: dec_axppci_33.c,v 1.4.4.2 1996/06/14 20:42:24 cgd Exp $ */ +/* $OpenBSD: dec_axppci_33.c,v 1.4 1996/10/30 22:38:06 niklas Exp $ */ +/* $NetBSD: dec_axppci_33.c,v 1.12 1996/10/13 02:59:32 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/device.h> #include <sys/termios.h> #include <dev/cons.h> @@ -82,9 +83,7 @@ dec_axppci_33_consinit() /* serial console ... */ /* XXX */ { - extern bus_chipset_tag_t comconsbc; /* set */ - extern bus_io_handle_t comcomsioh; /* set */ - extern int comconsaddr, comconsinit; /* set */ + extern int comconsinit; /* set */ extern int comdefaultrate; extern int comcngetc __P((dev_t)); extern void comcnputc __P((dev_t, int)); @@ -131,7 +130,7 @@ dec_axppci_33_device_register(dev, aux) struct device *dev; void *aux; { - static int found; + static int found, initted, scsiboot, netboot; static struct device *pcidev, *scsidev; struct bootdev_data *b = bootdev_data; struct device *parent = dev->dv_parent; @@ -141,6 +140,15 @@ dec_axppci_33_device_register(dev, aux) if (found) return; + if (!initted) { + scsiboot = (strcmp(b->protocol, "SCSI") == 0); + netboot = (strcmp(b->protocol, "BOOTP") == 0); +#if 0 + printf("scsiboot = %d, netboot = %d\n", scsiboot, netboot); +#endif + initted =1; + } + if (pcidev == NULL) { if (strcmp(cd->cd_name, "pci")) return; @@ -158,7 +166,7 @@ dec_axppci_33_device_register(dev, aux) } } - if (scsidev == NULL) { + if (scsiboot && (scsidev == NULL)) { if (parent != pcidev) return; else { @@ -177,9 +185,10 @@ dec_axppci_33_device_register(dev, aux) } } - if (!strcmp(cd->cd_name, "sd") || - !strcmp(cd->cd_name, "st") || - !strcmp(cd->cd_name, "cd")) { + if (scsiboot && + (!strcmp(cd->cd_name, "sd") || + !strcmp(cd->cd_name, "st") || + !strcmp(cd->cd_name, "cd"))) { struct scsibus_attach_args *sa = aux; if (parent->dv_parent != scsidev) @@ -211,4 +220,24 @@ dec_axppci_33_device_register(dev, aux) #endif found = 1; } + + if (netboot) { + if (parent != pcidev) + return; + else { + struct pci_attach_args *pa = aux; + + if (b->slot != pa->pa_device) + return; + + /* XXX function? */ + + booted_device = dev; +#if 0 + printf("\nbooted_device = %s\n", booted_device->dv_xname); +#endif + found = 1; + return; + } + } } diff --git a/sys/arch/alpha/alpha/dec_axppci_33.h b/sys/arch/alpha/alpha/dec_axppci_33.h index 105e9317e18..dbf4ffd4df2 100644 --- a/sys/arch/alpha/alpha/dec_axppci_33.h +++ b/sys/arch/alpha/alpha/dec_axppci_33.h @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_axppci_33.h,v 1.3 1996/07/29 22:57:30 niklas Exp $ */ -/* $NetBSD: dec_axppci_33.h,v 1.1.4.2 1996/06/13 18:35:18 cgd Exp $ */ +/* $OpenBSD: dec_axppci_33.h,v 1.4 1996/10/30 22:38:07 niklas Exp $ */ +/* $NetBSD: dec_axppci_33.h,v 1.5 1996/06/13 18:32:05 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/alpha/dec_kn20aa.c b/sys/arch/alpha/alpha/dec_kn20aa.c index 1b599144710..1639883b04f 100644 --- a/sys/arch/alpha/alpha/dec_kn20aa.c +++ b/sys/arch/alpha/alpha/dec_kn20aa.c @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_kn20aa.c,v 1.3 1996/07/29 22:57:32 niklas Exp $ */ -/* $NetBSD: dec_kn20aa.c,v 1.4.4.2 1996/06/14 20:42:25 cgd Exp $ */ +/* $OpenBSD: dec_kn20aa.c,v 1.4 1996/10/30 22:38:08 niklas Exp $ */ +/* $NetBSD: dec_kn20aa.c,v 1.12 1996/10/13 02:59:33 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/device.h> #include <sys/termios.h> #include <dev/cons.h> @@ -82,9 +83,7 @@ dec_kn20aa_consinit() /* serial console ... */ /* XXX */ { - extern bus_chipset_tag_t comconsbc; /* set */ - extern bus_io_handle_t comcomsioh; /* set */ - extern int comconsaddr, comconsinit; /* set */ + extern int comconsinit; /* set */ extern int comdefaultrate; extern int comcngetc __P((dev_t)); extern void comcnputc __P((dev_t, int)); @@ -131,7 +130,7 @@ dec_kn20aa_device_register(dev, aux) struct device *dev; void *aux; { - static int found; + static int found, initted, scsiboot, netboot; static struct device *pcidev, *scsidev; struct bootdev_data *b = bootdev_data; struct device *parent = dev->dv_parent; @@ -141,6 +140,15 @@ dec_kn20aa_device_register(dev, aux) if (found) return; + if (!initted) { + scsiboot = (strcmp(b->protocol, "SCSI") == 0); + netboot = (strcmp(b->protocol, "BOOTP") == 0); +#if 0 + printf("scsiboot = %d, netboot = %d\n", scsiboot, netboot); +#endif + initted =1; + } + if (pcidev == NULL) { if (strcmp(cd->cd_name, "pci")) return; @@ -158,7 +166,7 @@ dec_kn20aa_device_register(dev, aux) } } - if (scsidev == NULL) { + if (scsiboot && (scsidev == NULL)) { if (parent != pcidev) return; else { @@ -177,9 +185,10 @@ dec_kn20aa_device_register(dev, aux) } } - if (!strcmp(cd->cd_name, "sd") || - !strcmp(cd->cd_name, "st") || - !strcmp(cd->cd_name, "cd")) { + if (scsiboot && + (!strcmp(cd->cd_name, "sd") || + !strcmp(cd->cd_name, "st") || + !strcmp(cd->cd_name, "cd"))) { struct scsibus_attach_args *sa = aux; if (parent->dv_parent != scsidev) @@ -211,4 +220,24 @@ dec_kn20aa_device_register(dev, aux) #endif found = 1; } + + if (netboot) { + if (parent != pcidev) + return; + else { + struct pci_attach_args *pa = aux; + + if (b->slot != pa->pa_device) + return; + + /* XXX function? */ + + booted_device = dev; +#if 0 + printf("\nbooted_device = %s\n", booted_device->dv_xname); +#endif + found = 1; + return; + } + } } diff --git a/sys/arch/alpha/alpha/dec_kn20aa.h b/sys/arch/alpha/alpha/dec_kn20aa.h index c8be73911b1..ae165766657 100644 --- a/sys/arch/alpha/alpha/dec_kn20aa.h +++ b/sys/arch/alpha/alpha/dec_kn20aa.h @@ -1,5 +1,5 @@ -/* $OpenBSD: dec_kn20aa.h,v 1.3 1996/07/29 22:57:33 niklas Exp $ */ -/* $NetBSD: dec_kn20aa.h,v 1.1.4.2 1996/06/13 18:35:19 cgd Exp $ */ +/* $OpenBSD: dec_kn20aa.h,v 1.4 1996/10/30 22:38:09 niklas Exp $ */ +/* $NetBSD: dec_kn20aa.h,v 1.5 1996/06/13 18:32:07 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/alpha/disksubr.c b/sys/arch/alpha/alpha/disksubr.c index 78b90a4fa83..769c5a5fd0f 100644 --- a/sys/arch/alpha/alpha/disksubr.c +++ b/sys/arch/alpha/alpha/disksubr.c @@ -1,5 +1,5 @@ -/* $OpenBSD: disksubr.c,v 1.4 1996/07/29 22:57:35 niklas Exp $ */ -/* $NetBSD: disksubr.c,v 1.6 1996/04/29 16:34:50 cgd Exp $ */ +/* $OpenBSD: disksubr.c,v 1.5 1996/10/30 22:38:10 niklas Exp $ */ +/* $NetBSD: disksubr.c,v 1.8 1996/10/13 02:59:35 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -77,7 +77,7 @@ dk_establish(dk, dev) char * readdisklabel(dev, strat, lp, clp) dev_t dev; - void (*strat)(); + void (*strat) __P ((struct buf *)); struct disklabel *lp; struct cpu_disklabel *clp; { @@ -113,7 +113,7 @@ readdisklabel(dev, strat, lp, clp) dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET); if (dlp->d_magic == DISKMAGIC) { if (dkcksum(dlp)) { - msg = "NetBSD disk label corrupted"; + msg = "OpenBSD disk label corrupted"; goto done; } *lp = *dlp; @@ -190,13 +190,13 @@ setdisklabel(olp, nlp, openmask, clp) int writedisklabel(dev, strat, lp, clp) dev_t dev; - void (*strat)(); + void (*strat) __P((struct buf *)); register struct disklabel *lp; struct cpu_disklabel *clp; { struct buf *bp; struct disklabel *dlp; - int error = 0, cyl, i; + int error = 0; bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; @@ -205,7 +205,7 @@ writedisklabel(dev, strat, lp, clp) bp->b_bcount = lp->d_secsize; bp->b_flags = B_READ; /* get current label */ (*strat)(bp); - if (error = biowait(bp)) + if ((error = biowait(bp)) != 0) goto done; dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET); diff --git a/sys/arch/alpha/alpha/genassym.c b/sys/arch/alpha/alpha/genassym.c index cdac4f4b5a2..cfe3ddabf00 100644 --- a/sys/arch/alpha/alpha/genassym.c +++ b/sys/arch/alpha/alpha/genassym.c @@ -1,5 +1,5 @@ -/* $OpenBSD: genassym.c,v 1.4 1996/07/29 22:57:36 niklas Exp $ */ -/* $NetBSD: genassym.c,v 1.4 1996/05/17 18:29:41 cgd Exp $ */ +/* $OpenBSD: genassym.c,v 1.5 1996/10/30 22:38:10 niklas Exp $ */ +/* $NetBSD: genassym.c,v 1.9 1996/08/20 23:00:24 cgd Exp $ */ /* * Copyright (c) 1982, 1990, 1993 @@ -50,7 +50,6 @@ #include <machine/reg.h> #include <machine/frame.h> #include <machine/rpb.h> -#include <machine/trap.h> #include <stddef.h> #include <stdio.h> @@ -83,8 +82,6 @@ main(argc, argv) def("VM_MAX_ADDRESS", VM_MAX_ADDRESS); /* Register offsets, for stack frames. */ - def("FRAMESIZE", sizeof(struct trapframe)); - def("FRAME_NSAVEREGS", FRAME_NSAVEREGS); def("FRAME_V0", FRAME_V0); def("FRAME_T0", FRAME_T0); def("FRAME_T1", FRAME_T1); @@ -112,25 +109,30 @@ main(argc, argv) def("FRAME_T12", FRAME_T12); def("FRAME_AT", FRAME_AT); def("FRAME_SP", FRAME_SP); - off("TF_PS", struct trapframe, tf_ps); - off("TF_PC", struct trapframe, tf_ps); - off("TF_A0", struct trapframe, tf_a0); - off("TF_A1", struct trapframe, tf_a1); - off("TF_A2", struct trapframe, tf_a2); + + def("FRAME_SW_SIZE", FRAME_SW_SIZE); + + def("FRAME_PS", FRAME_PS); + def("FRAME_PC", FRAME_PC); + def("FRAME_GP", FRAME_GP); + def("FRAME_A0", FRAME_A0); + def("FRAME_A1", FRAME_A1); + def("FRAME_A2", FRAME_A2); + + def("FRAME_SIZE", FRAME_SIZE); /* bits of the PS register */ - def("PSL_U", PSL_U); - def("PSL_IPL", PSL_IPL); - def("PSL_IPL_0", PSL_IPL_0); - def("PSL_IPL_SOFT", PSL_IPL_SOFT); - def("PSL_IPL_HIGH", PSL_IPL_HIGH); + def("ALPHA_PSL_USERMODE", ALPHA_PSL_USERMODE); + def("ALPHA_PSL_IPL_MASK", ALPHA_PSL_IPL_MASK); + def("ALPHA_PSL_IPL_0", ALPHA_PSL_IPL_0); + def("ALPHA_PSL_IPL_SOFT", ALPHA_PSL_IPL_SOFT); + def("ALPHA_PSL_IPL_HIGH", ALPHA_PSL_IPL_HIGH); /* pte bits */ - def("PG_V", PG_V); - def("PG_ASM", PG_ASM); - def("PG_KRE", PG_KRE); - def("PG_KWE", PG_KWE); - def("PG_SHIFT", PG_SHIFT); + def("ALPHA_PTE_VALID", ALPHA_PTE_VALID); + def("ALPHA_PTE_ASM", ALPHA_PTE_ASM); + def("ALPHA_PTE_KR", ALPHA_PTE_KR); + def("ALPHA_PTE_KW", ALPHA_PTE_KW); /* Important offsets into the proc struct & associated constants */ off("P_FORW", struct proc, p_forw); @@ -142,16 +144,22 @@ main(argc, argv) off("PH_LINK", struct prochd, ph_link); off("PH_RLINK", struct prochd, ph_rlink); +#ifndef NEW_PMAP /* offsets needed by cpu_switch(), et al., to switch mappings. */ off("VM_PMAP_STPTE", struct vmspace, vm_pmap.pm_stpte); def("USTP_OFFSET", kvtol1pte(VM_MIN_ADDRESS) * sizeof(pt_entry_t)); +#else /* NEW_PMAP */ + off("VM_PMAP", struct vmspace, vm_pmap); +#endif /* NEW_PMAP */ /* Important offsets into the user struct & associated constants */ def("UPAGES", UPAGES); off("U_PCB", struct user, u_pcb); - off("U_PCB_KSP", struct user, u_pcb.pcb_ksp); - off("U_PCB_CONTEXT", struct user, u_pcb.pcb_context[0]); - off("U_PCB_ONFAULT", struct user, u_pcb.pcb_onfault); + off("PCB_HWPCB", struct pcb, pcb_hw); + off("PCB_HWPCB_KSP", struct pcb, pcb_hw.apcb_ksp); + off("PCB_CONTEXT", struct pcb, pcb_context[0]); + off("PCB_ONFAULT", struct pcb, pcb_onfault); + off("PCB_ACCESSADDR", struct pcb, pcb_accessaddr); /* Offsets into struct fpstate, for save, restore */ off("FPREG_FPR_REGS", struct fpreg, fpr_regs[0]); @@ -161,12 +169,11 @@ main(argc, argv) def("HWRPB_ADDR", HWRPB_ADDR); /* Restart parameter block */ def("VPTBASE", VPTBASE); /* Virtual Page Table base */ - /* Trap types and qualifiers */ - def("T_ASTFLT", T_ASTFLT); - def("T_UNAFLT", T_UNAFLT); - def("T_ARITHFLT", T_ARITHFLT); - def("T_IFLT", T_IFLT); /* qualifier */ - def("T_MMFLT", T_MMFLT); /* qualifier */ + /* Kernel entries */ + def("ALPHA_KENTRY_ARITH", ALPHA_KENTRY_ARITH); + def("ALPHA_KENTRY_MM", ALPHA_KENTRY_MM); + def("ALPHA_KENTRY_IF", ALPHA_KENTRY_IF); + def("ALPHA_KENTRY_UNA", ALPHA_KENTRY_UNA); /* errno values */ def("ENAMETOOLONG", ENAMETOOLONG); diff --git a/sys/arch/alpha/alpha/in_cksum.c b/sys/arch/alpha/alpha/in_cksum.c index 816d7f06139..5b303da7f00 100644 --- a/sys/arch/alpha/alpha/in_cksum.c +++ b/sys/arch/alpha/alpha/in_cksum.c @@ -1,5 +1,5 @@ -/* $OpenBSD: in_cksum.c,v 1.2 1996/07/29 22:57:37 niklas Exp $ */ -/* $NetBSD: in_cksum.c,v 1.2.4.1 1996/05/30 23:12:50 cgd Exp $ */ +/* $OpenBSD: in_cksum.c,v 1.3 1996/10/30 22:38:11 niklas Exp $ */ +/* $NetBSD: in_cksum.c,v 1.3 1996/05/30 23:08:36 cgd Exp $ */ /* * Copyright (c) 1988, 1992, 1993 @@ -43,6 +43,8 @@ #include <sys/systm.h> #include <netinet/in.h> +u_int64_t in_cksumdata __P((caddr_t, int)); + /* * Checksum routine for Internet Protocol family headers * (Portable Alpha version). @@ -93,7 +95,6 @@ in_cksumdata(buf, len) u_int64_t prefilled; int offset; union q_util q_util; - union l_util l_util; if ((3 & (long) lw) == 0 && len == 20) { sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4]; diff --git a/sys/arch/alpha/alpha/interrupt.c b/sys/arch/alpha/alpha/interrupt.c index 8520d5b4b66..8c112198e24 100644 --- a/sys/arch/alpha/alpha/interrupt.c +++ b/sys/arch/alpha/alpha/interrupt.c @@ -1,5 +1,5 @@ -/* $OpenBSD: interrupt.c,v 1.4 1996/07/29 22:57:39 niklas Exp $ */ -/* $NetBSD: interrupt.c,v 1.5 1996/04/23 13:54:32 cgd Exp $ */ +/* $OpenBSD: interrupt.c,v 1.5 1996/10/30 22:38:12 niklas Exp $ */ +/* $NetBSD: interrupt.c,v 1.12 1996/10/13 19:57:49 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -35,6 +35,7 @@ #include <machine/autoconf.h> #include <machine/reg.h> +#include <machine/frame.h> #ifdef EVCNT_COUNTERS #include <sys/device.h> @@ -49,47 +50,55 @@ struct logout { /* Unspecified. */ }; -void machine_check __P((struct trapframe *, struct logout *, - u_int64_t)); -static void nullintr __P((void *, int)); +void interrupt __P((u_long, u_long, u_long, struct trapframe *)); +void machine_check __P((struct trapframe *, u_long, u_long)); +void real_clockintr __P((void *, u_long)); +void nullintr __P((void *, u_long)); -static void (*iointr) __P((void *, int)) = nullintr; -static void (*clockintr) __P((void *, int)) = nullintr; -static int mc_expected, mc_received; +static void (*iointr) __P((void *, u_long)) = nullintr; +static void (*clockintr) __P((void *, u_long)) = nullintr; +static volatile int mc_expected, mc_received; #ifdef EVCNT_COUNTERS struct evcnt clock_intr_evcnt; /* event counter for clock intrs. */ #endif void -interrupt(framep, type, vec, logoutp) +interrupt(a0, a1, a2, framep) + u_long a0, a1, a2; struct trapframe *framep; - u_int64_t type, vec; - struct logout *logoutp; { - if (type == 1) /* clock interrupt */ - (*clockintr)(framep, vec); - else if (type == 3) /* I/O device interrupt */ - (*iointr)(framep, vec); - else if (type == 2) - machine_check(framep, logoutp, vec); - else - panic("unexpected interrupt: type %ld, vec %ld\n", - (long)type, (long)vec); + if (a0 == 1) { /* clock interrupt */ + cnt.v_intr++; + (*clockintr)(framep, a1); + } else if (a0 == 3) { /* I/O device interrupt */ + cnt.v_intr++; + (*iointr)(framep, a1); + } else if (a0 == 2) /* machine check or correctable error */ + machine_check(framep, a1, a2); + else { + /* + * Not expected or handled: + * 0 Interprocessor interrupt + * 4 Performance counter + */ + panic("unexpected interrupt: type 0x%lx, vec 0x%lx\n", + a0, a1); + } } -static void +void nullintr(framep, vec) void *framep; - int vec; + u_long vec; { } -static void +void real_clockintr(framep, vec) void *framep; - int vec; + u_long vec; { #ifdef EVCNT_COUNTERS @@ -112,7 +121,7 @@ set_clockintr() void set_iointr(niointr) - void (*niointr) __P((void *, int)); + void (*niointr) __P((void *, u_long)); { if (iointr != nullintr) @@ -122,59 +131,91 @@ set_iointr(niointr) } void -machine_check(framep, logoutp, vec) +machine_check(framep, vector, param) struct trapframe *framep; - struct logout *logoutp; - u_int64_t vec; + u_long vector, param; { + u_long mces; + const char *type; - if (!mc_expected) - panic("machine check: vec 0x%lx, pc = 0x%lx, ra = 0x%lx", - vec, framep->tf_pc, framep->tf_regs[FRAME_RA]); + mces = alpha_pal_rdmces(); + + /* If not a machine check, we have no clue ho we got here. */ + if ((mces & ALPHA_MCES_MIP) == 0) { + type = "fatal machine check or error (unknown type)"; + goto fatal; + } + + /* If we weren't expecting it, then we punt. */ + if (!mc_expected) { + type = "unexpected machine check"; + goto fatal; + } mc_expected = 0; mc_received = 1; - logoutp->q1 &= ~LOGOUT_RETRY; /* XXX: Necessary? */ - pal_mtpr_mces(0x19); /* XXX: VMS PAL! */ + /* Clear pending machine checks and correctable errors */ + alpha_pal_wrmces(mces); + return; + +fatal: + 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; - u_int64_t size; + size_t size; { - int rv; - volatile long rcpt; + 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. */ - wbflush(); + alpha_mb(); switch (size) { case sizeof (u_int8_t): - rcpt = *(u_int8_t *)addr; + rcpt = *(volatile u_int8_t *)addr; break; case sizeof (u_int16_t): - rcpt = *(u_int16_t *)addr; + rcpt = *(volatile u_int16_t *)addr; break; case sizeof (u_int32_t): - rcpt = *(u_int32_t *)addr; + rcpt = *(volatile u_int32_t *)addr; break; case sizeof (u_int64_t): - rcpt = *(u_int64_t *)addr; + rcpt = *(volatile u_int64_t *)addr; break; default: panic("badaddr: invalid size (%ld)\n", size); } - wbflush(); - pal_draina(); + alpha_mb(); + + /* Make sure we took the machine check, if we caused one. */ + alpha_pal_draina(); /* disallow further machine checks */ mc_expected = 0; diff --git a/sys/arch/alpha/alpha/locore.s b/sys/arch/alpha/alpha/locore.s index 9790d7b74c3..0589b15c26e 100644 --- a/sys/arch/alpha/alpha/locore.s +++ b/sys/arch/alpha/alpha/locore.s @@ -1,5 +1,5 @@ -/* $OpenBSD: locore.s,v 1.4 1996/07/29 22:57:41 niklas Exp $ */ -/* $NetBSD: locore.s,v 1.13.4.1 1996/06/13 18:06:59 cgd Exp $ */ +/* $OpenBSD: locore.s,v 1.5 1996/10/30 22:38:13 niklas Exp $ */ +/* $NetBSD: locore.s,v 1.26 1996/10/17 02:50:38 cgd Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -62,29 +62,28 @@ bootstack: * All arguments are passed to alpha_init(). */ NESTED_NOPROFILE(__start,1,0,ra,0,0) - br pv,1f -1: SETGP(pv) + br pv,Lstart1 +Lstart1: LDGP(pv) - /* Save a0, used by pal_wrkgp. */ - or a0,zero,s0 + /* Switch to the boot stack. */ + lda sp,bootstack /* Load KGP with current GP. */ + or a0,zero,s0 /* save pfn */ or gp,zero,a0 - CALL(pal_wrkgp) - - /* Switch to the boot stack. */ - lda sp,bootstack + call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */ + or s0,zero,a0 /* restore pfn */ /* - * Call alpha_init() to do pre-main initialization. Restore - * a0, and pass alpha_init the arguments we were called with. + * Call alpha_init() to do pre-main initialization. + * alpha_init() gets the arguments we were called with, + * which are already in a0 and a1. */ - or s0,zero,a0 CALL(alpha_init) /* Set up the virtual page table pointer. */ - CONST(VPTBASE, a0) - CALL(pal_wrvptptr) + ldiq a0, VPTBASE + call_pal PAL_OSF1_wrvptptr /* clobbers a0, t0, t8-t11 */ /* * Switch to proc0's PCB, which is at U_PCB off of proc0paddr. @@ -92,32 +91,23 @@ NESTED_NOPROFILE(__start,1,0,ra,0,0) lda t0,proc0 /* get phys addr of pcb */ ldq a0,P_MD_PCBPADDR(t0) call_pal PAL_OSF1_swpctx - CONST(-1, a0) + ldiq a0, -2 call_pal PAL_OSF1_tbi /* - * put a fake RA (0 XXX) on the stack, to panic if anything - * ever tries to return off the end of the stack - */ - lda sp,-8(sp) - stq zero,0(sp) - - /* * Construct a fake trap frame, so execve() can work normally. * Note that setregs() is responsible for setting its contents * to 'reasonable' values. */ - lda sp,-(FRAMESIZE)(sp) /* space for struct trapframe */ - + lda sp,-(FRAME_SIZE * 8)(sp) /* space for struct trapframe */ mov sp, a0 /* main()'s arg is frame ptr */ CALL(main) /* go to main()! */ /* - * Call REI, to restore the faked up trap frame and return - * to proc 1 == init! + * Call exception_return, to simulate return from (fake) + * exception to user-land, running process 1, init! */ - mov zero, a0 - JMP(rei) /* "And that's all she wrote." */ + jmp zero, exception_return /* "And that's all she wrote." */ END(__start) /**************************************************************************/ @@ -166,29 +156,27 @@ NESTED(sigcode,0,0,ra,0,0) jsr ra, (t12) /* call the signal handler (t12==pv) */ ldq a0, 0(sp) /* get the sigcontext pointer */ lda sp, 16(sp) - CONST(SYS_sigreturn, v0) /* and call sigreturn() with it. */ - call_pal PAL_OSF1_callsys + CALLSYS_NOERROR(sigreturn) /* and call sigreturn() with it. */ mov v0, a0 /* if that failed, get error code */ - CONST(SYS_exit, v0) /* and call exit() with it. */ - call_pal PAL_OSF1_callsys + CALLSYS_NOERROR(exit) /* and call exit() with it. */ XNESTED(esigcode,0) END(sigcode) /**************************************************************************/ /* - * rei: pseudo-emulation of VAX REI. + * exception_return: return from trap, exception, or syscall */ BSS(ssir, 8) IMPORT(astpending, 8) -LEAF(rei, 1) /* XXX should be NESTED */ - br pv, 1f -1: SETGP(pv) +LEAF(exception_return, 1) /* XXX should be NESTED */ + br pv, Ler1 +Ler1: LDGP(pv) - ldq s1, TF_PS(sp) /* get the saved PS */ - and s1, PSL_IPL, t0 /* look at the saved IPL */ + 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 */ @@ -196,26 +184,23 @@ LEAF(rei, 1) /* XXX should be NESTED */ beq t1, Lchkast /* no, try an AST*/ /* We've got a SIR. */ - CONST(PSL_IPL_SOFT, a0) /* yes, lower IPL to soft */ + ldiq a0, ALPHA_PSL_IPL_SOFT /* yes, lower IPL to soft */ call_pal PAL_OSF1_swpipl CALL(do_sir) /* do the SIR */ Lchkast: - CONST(PSL_IPL_0, a0) /* drop IPL to zero*/ + ldiq a0, ALPHA_PSL_IPL_0 /* drop IPL to zero*/ call_pal PAL_OSF1_swpipl - and s1, PSL_U, t0 /* are we returning to user? */ + 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. call trap to handle it */ - CONST(T_ASTFLT, a0) /* type = T_ASTFLT */ - mov zero, a1 /* code = 0 */ - mov zero, a2 /* v = 0 */ - mov sp, a3 /* frame */ - CALL(trap) + /* 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 */ @@ -227,12 +212,57 @@ Lsetfpenable: call_pal PAL_OSF1_wrfen Lrestoreregs: - /* restore the USP and the registers, and return */ - ldq a0,(FRAME_SP*8)(sp) - call_pal PAL_OSF1_wrusp - + /* 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) @@ -241,27 +271,15 @@ Lrestoreregs: ldq t5,(FRAME_T5*8)(sp) ldq t6,(FRAME_T6*8)(sp) ldq t7,(FRAME_T7*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 a3,(FRAME_A3*8)(sp) - ldq a4,(FRAME_A4*8)(sp) - ldq a5,(FRAME_A5*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 ra,(FRAME_RA*8)(sp) ldq t12,(FRAME_T12*8)(sp) - ldq at_reg,(FRAME_AT*8)(sp) - - lda sp,(FRAME_NSAVEREGS*8)(sp) - call_pal PAL_OSF1_rti - END(rei) +#ifndef __OpenBSD__ + RET +#endif + END(exception_restore_regs) /**************************************************************************/ @@ -272,51 +290,18 @@ Lrestoreregs: LEAF(XentArith, 2) /* XXX should be NESTED */ .set noat - lda sp,-(FRAME_NSAVEREGS*8)(sp) - stq v0,(FRAME_V0*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 s0,(FRAME_S0*8)(sp) - stq s1,(FRAME_S1*8)(sp) - stq s2,(FRAME_S2*8)(sp) - mov a0,s0 - stq s3,(FRAME_S3*8)(sp) - stq s4,(FRAME_S4*8)(sp) - stq s5,(FRAME_S5*8)(sp) - stq s6,(FRAME_S6*8)(sp) - mov a1,s1 - stq a3,(FRAME_A3*8)(sp) - stq a4,(FRAME_A4*8)(sp) - stq a5,(FRAME_A5*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 ra,(FRAME_RA*8)(sp) - stq t12,(FRAME_T12*8)(sp) + lda sp,-(FRAME_SW_SIZE*8)(sp) stq at_reg,(FRAME_AT*8)(sp) - - call_pal PAL_OSF1_rdusp - stq v0,(FRAME_SP*8)(sp) - .set at + stq ra,(FRAME_RA*8)(sp) + bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */ - br pv, 1f -1: SETGP(pv) - - CONST(T_ARITHFLT, a0) /* type = T_ARITHFLT */ - mov s0, a1 /* code = "summary" */ - mov s1, a2 /* v = "reguster mask" */ - mov sp, a3 /* frame */ + /* a0, a1, & a2 already set up */ + ldiq a3, ALPHA_KENTRY_ARITH + mov sp, a4 CALL(trap) - JMP(rei) + jmp zero, exception_return END(XentArith) /**************************************************************************/ @@ -328,50 +313,18 @@ LEAF(XentArith, 2) /* XXX should be NESTED */ LEAF(XentIF, 1) /* XXX should be NESTED */ .set noat - lda sp,-(FRAME_NSAVEREGS*8)(sp) - stq v0,(FRAME_V0*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 s0,(FRAME_S0*8)(sp) - stq s1,(FRAME_S1*8)(sp) - stq s2,(FRAME_S2*8)(sp) - mov a0,s0 - 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 a3,(FRAME_A3*8)(sp) - stq a4,(FRAME_A4*8)(sp) - stq a5,(FRAME_A5*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 ra,(FRAME_RA*8)(sp) - stq t12,(FRAME_T12*8)(sp) + lda sp,-(FRAME_SW_SIZE*8)(sp) stq at_reg,(FRAME_AT*8)(sp) - - call_pal PAL_OSF1_rdusp - stq v0,(FRAME_SP*8)(sp) - .set at + stq ra,(FRAME_RA*8)(sp) + bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */ - br pv, 1f -1: SETGP(pv) - - or s0, T_IFLT, a0 /* type = T_IFLT|type*/ - mov s0, a1 /* code = type */ - ldq a2, TF_PC(sp) /* v = frame's pc */ - mov sp, a3 /* frame */ + /* a0, a1, & a2 already set up */ + ldiq a3, ALPHA_KENTRY_IF + mov sp, a4 CALL(trap) - JMP(rei) + jmp zero, exception_return END(XentIF) /**************************************************************************/ @@ -383,52 +336,17 @@ LEAF(XentIF, 1) /* XXX should be NESTED */ LEAF(XentInt, 2) /* XXX should be NESTED */ .set noat - lda sp,-(FRAME_NSAVEREGS*8)(sp) - stq v0,(FRAME_V0*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 s0,(FRAME_S0*8)(sp) - stq s1,(FRAME_S1*8)(sp) - stq s2,(FRAME_S2*8)(sp) - mov a0,s0 - stq s3,(FRAME_S3*8)(sp) - stq s4,(FRAME_S4*8)(sp) - stq s5,(FRAME_S5*8)(sp) - stq s6,(FRAME_S6*8)(sp) - mov a1,s1 - stq a3,(FRAME_A3*8)(sp) - stq a4,(FRAME_A4*8)(sp) - stq a5,(FRAME_A5*8)(sp) - stq t8,(FRAME_T8*8)(sp) - mov a2,s2 - stq t9,(FRAME_T9*8)(sp) - stq t10,(FRAME_T10*8)(sp) - stq t11,(FRAME_T11*8)(sp) - stq ra,(FRAME_RA*8)(sp) - stq t12,(FRAME_T12*8)(sp) + lda sp,-(FRAME_SW_SIZE*8)(sp) stq at_reg,(FRAME_AT*8)(sp) - - call_pal PAL_OSF1_rdusp - stq v0,(FRAME_SP*8)(sp) - .set at + stq ra,(FRAME_RA*8)(sp) + bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */ - br pv, 1f -1: SETGP(pv) - - mov s2,a3 - mov s1,a2 - mov s0,a1 - mov sp,a0 + /* a0, a1, & a2 already set up */ + mov sp, a3 CALL(interrupt) - JMP(rei) + jmp zero, exception_return END(XentInt) /**************************************************************************/ @@ -440,52 +358,18 @@ LEAF(XentInt, 2) /* XXX should be NESTED */ LEAF(XentMM, 3) /* XXX should be NESTED */ .set noat - lda sp,-(FRAME_NSAVEREGS*8)(sp) - stq v0,(FRAME_V0*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 s0,(FRAME_S0*8)(sp) - stq s1,(FRAME_S1*8)(sp) - stq s2,(FRAME_S2*8)(sp) - mov a0,s0 - stq s3,(FRAME_S3*8)(sp) - stq s4,(FRAME_S4*8)(sp) - stq s5,(FRAME_S5*8)(sp) - stq s6,(FRAME_S6*8)(sp) - mov a1,s1 - stq a3,(FRAME_A3*8)(sp) - stq a4,(FRAME_A4*8)(sp) - stq a5,(FRAME_A5*8)(sp) - stq t8,(FRAME_T8*8)(sp) - mov a2,s2 - stq t9,(FRAME_T9*8)(sp) - stq t10,(FRAME_T10*8)(sp) - stq t11,(FRAME_T11*8)(sp) - stq ra,(FRAME_RA*8)(sp) - stq t12,(FRAME_T12*8)(sp) + lda sp,-(FRAME_SW_SIZE*8)(sp) stq at_reg,(FRAME_AT*8)(sp) - - call_pal PAL_OSF1_rdusp - stq v0,(FRAME_SP*8)(sp) - .set at + stq ra,(FRAME_RA*8)(sp) + bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */ - br pv, 1f -1: SETGP(pv) - - or s1, T_MMFLT, a0 /* type = T_MMFLT|MMCSR */ - mov s2, a1 /* code = "cause" */ - mov s0, a2 /* v = VA */ - mov sp, a3 /* frame */ + /* a0, a1, & a2 already set up */ + ldiq a3, ALPHA_KENTRY_MM + mov sp, a4 CALL(trap) - JMP(rei) + jmp zero, exception_return END(XentMM) /**************************************************************************/ @@ -496,8 +380,7 @@ LEAF(XentMM, 3) /* XXX should be NESTED */ */ LEAF(XentSys, 0) /* XXX should be NESTED */ - .set noat - lda sp,-(FRAME_NSAVEREGS*8)(sp) + lda sp,-(FRAME_SW_SIZE*8)(sp) stq v0,(FRAME_V0*8)(sp) /* in case we need to restart */ stq s0,(FRAME_S0*8)(sp) stq s1,(FRAME_S1*8)(sp) @@ -506,30 +389,20 @@ LEAF(XentSys, 0) /* XXX should be NESTED */ stq s4,(FRAME_S4*8)(sp) stq s5,(FRAME_S5*8)(sp) stq s6,(FRAME_S6*8)(sp) - stq a0,TF_A0(sp) - stq a1,TF_A1(sp) - stq a2,TF_A2(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) - /* save syscall number, which was passed in v0. */ - mov v0,s0 - - call_pal PAL_OSF1_rdusp - stq v0,(FRAME_SP*8)(sp) - - .set at - - br pv, 1f -1: SETGP(pv) - - mov s0,a0 + /* syscall number, passed in v0, is first arg, frame pointer second */ + mov v0,a0 mov sp,a1 CALL(syscall) - JMP(rei) + jmp zero, exception_return END(XentSys) /**************************************************************************/ @@ -541,52 +414,18 @@ LEAF(XentSys, 0) /* XXX should be NESTED */ LEAF(XentUna, 3) /* XXX should be NESTED */ .set noat - lda sp,-(FRAME_NSAVEREGS*8)(sp) - stq v0,(FRAME_V0*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 s0,(FRAME_S0*8)(sp) - stq s1,(FRAME_S1*8)(sp) - stq s2,(FRAME_S2*8)(sp) - mov a0,s0 - stq s3,(FRAME_S3*8)(sp) - stq s4,(FRAME_S4*8)(sp) - stq s5,(FRAME_S5*8)(sp) - stq s6,(FRAME_S6*8)(sp) - mov a1,s1 - stq a3,(FRAME_A3*8)(sp) - stq a4,(FRAME_A4*8)(sp) - stq a5,(FRAME_A5*8)(sp) - stq t8,(FRAME_T8*8)(sp) - mov a2,s2 - stq t9,(FRAME_T9*8)(sp) - stq t10,(FRAME_T10*8)(sp) - stq t11,(FRAME_T11*8)(sp) - stq ra,(FRAME_RA*8)(sp) - stq t12,(FRAME_T12*8)(sp) + lda sp,-(FRAME_SW_SIZE*8)(sp) stq at_reg,(FRAME_AT*8)(sp) - - call_pal PAL_OSF1_rdusp - stq v0,(FRAME_SP*8)(sp) - .set at + stq ra,(FRAME_RA*8)(sp) + bsr ra, exception_save_regs /* jmp/CALL trashes pv/t12 */ - br pv, 1f -1: SETGP(pv) - - CONST(T_UNAFLT, a0) /* type = T_UNAFLT */ - mov zero, a1 /* code = 0 */ - mov zero, a2 /* v = 0 */ - mov sp, a3 /* frame */ + /* a0, a1, & a2 already set up */ + ldiq a3, ALPHA_KENTRY_UNA + mov sp, a4 CALL(trap) - JMP(rei) + jmp zero, exception_return END(XentUna) /**************************************************************************/ @@ -599,7 +438,7 @@ LEAF(XentUna, 3) /* XXX should be NESTED */ */ LEAF(savefpstate, 1) - SETGP(pv) + LDGP(pv) /* save all of the FP registers */ lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */ stt $f0, (0 * 8)(t1) /* save first register, using hw name */ @@ -630,7 +469,9 @@ LEAF(savefpstate, 1) stt $f25, (25 * 8)(t1) stt $f26, (26 * 8)(t1) stt $f27, (27 * 8)(t1) + .set noat stt $f28, (28 * 8)(t1) + .set at stt $f29, (29 * 8)(t1) stt $f30, (30 * 8)(t1) @@ -638,7 +479,7 @@ LEAF(savefpstate, 1) * Then save the FPCR; note that the necessary 'trapb's are taken * care of on kernel entry and exit. */ - MF_FPCR(ft0) + mf_fpcr ft0 stt ft0, FPREG_FPR_CR(a0) /* store to FPCR save area */ RET @@ -654,13 +495,13 @@ LEAF(savefpstate, 1) */ LEAF(restorefpstate, 1) - SETGP(pv) + LDGP(pv) /* * Restore the FPCR; note that the necessary 'trapb's are taken care of * on kernel entry and exit. */ ldt ft0, FPREG_FPR_CR(a0) /* load from FPCR save area */ - MT_FPCR(ft0) + mt_fpcr ft0 /* Restore all of the FP registers. */ lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */ @@ -710,7 +551,7 @@ LEAF(restorefpstate, 1) * from if called from boot().) * * Arguments: - * a0 'struct user *' of the process that needs its context saved + * a0 'struct pcb *' of the process that needs its context saved * * Return: * v0 0. (note that for child processes, it seems @@ -719,19 +560,19 @@ LEAF(restorefpstate, 1) */ LEAF(savectx, 1) - br pv, 1f -1: SETGP(pv) - stq sp, U_PCB_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 */ + br pv, Lsavectx1 +Lsavectx1: LDGP(pv) + stq sp, PCB_HWPCB_KSP(a0) /* store sp */ + stq s0, PCB_CONTEXT+(0 * 8)(a0) /* store s0 - s6 */ + stq s1, PCB_CONTEXT+(1 * 8)(a0) + stq s2, PCB_CONTEXT+(2 * 8)(a0) + stq s3, PCB_CONTEXT+(3 * 8)(a0) + stq s4, PCB_CONTEXT+(4 * 8)(a0) + stq s5, PCB_CONTEXT+(5 * 8)(a0) + stq s6, PCB_CONTEXT+(6 * 8)(a0) + stq ra, 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 */ + stq v0, PCB_CONTEXT+(8 * 8)(a0) /* store ps, for ipl */ mov zero, v0 RET @@ -752,17 +593,17 @@ IMPORT(Lev1map, 8) * profiling. */ LEAF(idle, 0) - br pv, 1f -1: SETGP(pv) + br pv, Lidle1 +Lidle1: LDGP(pv) stq zero, curproc /* curproc <- NULL for stats */ mov zero, a0 /* enable all interrupts */ call_pal PAL_OSF1_swpipl -2: +Lidle2: ldl t0, whichqs /* look for non-empty queue */ - beq t0, 2b - CONST(PSL_IPL_HIGH, a0) /* disable all interrupts */ + beq t0, Lidle2 + ldiq a0, ALPHA_PSL_IPL_HIGH /* disable all interrupts */ call_pal PAL_OSF1_swpipl - JMP(sw1) /* jump back into the fray */ + jmp zero, sw1 /* jump back into the fray */ END(idle) /* @@ -771,41 +612,44 @@ LEAF(idle, 0) * XXX should optimiize, and not do the switch if switching to curproc */ LEAF(cpu_switch, 0) - SETGP(pv) + LDGP(pv) /* do an inline savectx(), to save old context */ ldq a0, curproc - ldq a0, P_ADDR(a0) + ldq a1, P_ADDR(a0) /* NOTE: ksp is stored by the swpctx */ - 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 */ + stq s0, U_PCB+PCB_CONTEXT+(0 * 8)(a1) /* store s0 - s6 */ + stq s1, U_PCB+PCB_CONTEXT+(1 * 8)(a1) + stq s2, U_PCB+PCB_CONTEXT+(2 * 8)(a1) + stq s3, U_PCB+PCB_CONTEXT+(3 * 8)(a1) + stq s4, U_PCB+PCB_CONTEXT+(4 * 8)(a1) + stq s5, U_PCB+PCB_CONTEXT+(5 * 8)(a1) + stq s6, U_PCB+PCB_CONTEXT+(6 * 8)(a1) + stq ra, U_PCB+PCB_CONTEXT+(7 * 8)(a1) /* store ra */ call_pal PAL_OSF1_rdps /* NOTE: doesn't kill a0 */ - stq v0, U_PCB_CONTEXT+(8 * 8)(a0) /* store ps, for ipl */ + stq v0, U_PCB+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 */ - CONST(PSL_IPL_HIGH, a0) /* disable all interrupts */ + ldiq a0, ALPHA_PSL_IPL_HIGH /* disable all interrupts */ call_pal PAL_OSF1_swpipl sw1: - br pv, 1f -1: SETGP(pv) + 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, 3f /* if low bit set, done! */ + blbs t0, Lcs3 /* if low bit set, done! */ -2: srl t0, 1, t0 /* try next bit */ +Lcs2: srl t0, 1, t0 /* try next bit */ addq t2, 1, t2 - blbc t0, 2b /* if clear, try again */ + blbc t0, Lcs2 /* if clear, try again */ -3: +Lcs3: /* * Remove process from queue */ @@ -815,22 +659,22 @@ sw1: ldq t4, PH_LINK(t0) /* t4 = p = highest pri proc */ ldq t5, P_FORW(t4) /* t5 = p->p_forw */ - bne t4, 4f /* make sure p != NULL */ - PANIC("cpu_switch") /* nothing in queue! */ + bne t4, Lcs4 /* make sure p != NULL */ + PANIC("cpu_switch",Lcpu_switch_pmsg) /* nothing in queue! */ -4: +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, 5f /* nope, it's not! */ + beq t0, Lcs5 /* nope, it's not! */ - CONST(1, t0) /* compute bit in whichqs */ + ldiq t0, 1 /* compute bit in whichqs */ sll t0, t2, t0 xor t3, t0, t3 /* clear bit in whichqs */ stl t3, whichqs -5: +Lcs5: /* * Switch to the new context */ @@ -842,6 +686,7 @@ sw1: ldq t5, P_MD_PCBPADDR(t4) /* t5 = p->p_md.md_pcbpaddr */ stq t5, curpcb /* and store it in curpcb */ +#ifndef NEW_PMAP /* * Do the context swap, and invalidate old TLB entries (XXX). * XXX should do the ASN thing, and therefore not have to invalidate. @@ -852,7 +697,7 @@ sw1: stq t2, USTP_OFFSET(t3) mov t5, a0 /* swap the context */ call_pal PAL_OSF1_swpctx - CONST(-1, a0) /* & invalidate old TLB ents */ + ldiq a0, -1 /* & invalidate old TLB ents */ call_pal PAL_OSF1_tbi /* @@ -861,25 +706,54 @@ sw1: */ ldq t0, curproc ldq t0, P_ADDR(t0) +#else /* NEW_PMAP */ + mov t4, s2 /* save new curproc */ + mov t5, s3 /* save new pcbpaddr */ + ldq s4, P_ADDR(t4) /* load/save new U-AREA */ + + ldq a0, P_VMSPACE(s2) /* p->p_vmspace */ + lda a1, U_PCB+PCB_HWPCB(s4) /* &hardware PCB */ + mov zero, a2 + lda a0, VM_PMAP(a0) /* &p->p_vmspace->vm_pmap */ + CALL(pmap_activate) + + mov s3, a0 /* swap the context */ + call_pal PAL_OSF1_swpctx + ldiq a0, -2 /* & invalidate old TLB ents */ + call_pal PAL_OSF1_tbi + + ldq a0, P_VMSPACE(s0) + lda a1, U_PCB+PCB_HWPCB(s1) + mov zero, a2 + lda a0, VM_PMAP(a0) + CALL(pmap_deactivate) + + /* + * Now running on the new u struct. + * Restore registers and return. + */ + mov s4, t0 +#endif /* NEW_PMAP */ /* 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, PSL_IPL, a0 + ldq s0, U_PCB+PCB_CONTEXT+(0 * 8)(t0) /* restore s0 - s6 */ + ldq s1, U_PCB+PCB_CONTEXT+(1 * 8)(t0) + ldq s2, U_PCB+PCB_CONTEXT+(2 * 8)(t0) + ldq s3, U_PCB+PCB_CONTEXT+(3 * 8)(t0) + ldq s4, U_PCB+PCB_CONTEXT+(4 * 8)(t0) + ldq s5, U_PCB+PCB_CONTEXT+(5 * 8)(t0) + ldq s6, U_PCB+PCB_CONTEXT+(6 * 8)(t0) + ldq ra, U_PCB+PCB_CONTEXT+(7 * 8)(t0) /* restore ra */ + ldq a0, U_PCB+PCB_CONTEXT+(8 * 8)(t0) /* restore ipl */ + and a0, ALPHA_PSL_IPL_MASK, a0 call_pal PAL_OSF1_swpipl - CONST(1, v0) /* possible ret to savectx() */ + ldiq v0, 1 /* possible ret to savectx() */ RET END(cpu_switch) + /* - * proc_trampoline() + * switch_trampoline() * * Arrange for a function to be invoked neatly, after a cpu_switch(). * @@ -887,12 +761,12 @@ sw1: * address specified by the s1 register and with one argument, a * pointer to the executing process's proc structure. */ -LEAF(proc_trampoline, 0) +LEAF(switch_trampoline, 0) mov s0, pv mov s1, ra ldq a0, curproc jmp zero, (pv) - END(proc_trampoline) + END(switch_trampoline) /* * switch_exit(struct proc *p) @@ -901,28 +775,37 @@ LEAF(proc_trampoline, 0) * to switch into a few process. MUST BE CALLED AT SPLHIGH. */ LEAF(switch_exit, 1) - SETGP(pv) + LDGP(pv) /* save the exiting proc pointer */ - mov a0, s0 + mov a0, s2 /* Switch to proc0. */ lda t4, proc0 /* t4 = &proc0 */ ldq t5, P_MD_PCBPADDR(t4) /* t5 = p->p_md.md_pcbpaddr */ stq t5, curpcb /* and store it in curpcb */ +#ifndef NEW_PMAP + mov t4, s0 + ldq s1, P_ADDR(t4) +#endif + /* * Do the context swap, and invalidate old TLB entries (XXX). * XXX should do the ASN thing, and therefore not have to invalidate. */ +#ifndef NEW_PMAP ldq t2, P_VMSPACE(t4) /* t2 = p->p_vmspace */ ldq t2, VM_PMAP_STPTE(t2) /* = p_vmspace.vm_pmap.pm_ste */ ldq t3, Lev1map /* and store pte into Lev1map */ stq t2, USTP_OFFSET(t3) +#endif /* NEW_PMAP */ mov t5, a0 /* swap the context */ call_pal PAL_OSF1_swpctx - CONST(-1, a0) /* & invalidate old TLB ents */ +#ifndef NEW_PMAP + ldiq a0, -1 /* & invalidate old TLB ents */ call_pal PAL_OSF1_tbi +#endif /* NEW_PMAP */ /* * Now running as proc0, except for the value of 'curproc' and @@ -931,12 +814,15 @@ LEAF(switch_exit, 1) /* blow away the old user struct */ ldq a0, kernel_map - ldq a1, P_ADDR(s0) - CONST(UPAGES*NBPG, a2) + ldq a1, P_ADDR(s2) + ldiq a2, (UPAGES * NBPG) CALL(kmem_free) /* and jump into the middle of cpu_switch. */ - JMP(sw1) +#ifdef NEW_PMAP + /* XXX XXX LOSE */ +#endif + jmp zero, sw1 END(switch_exit) /**************************************************************************/ @@ -948,12 +834,12 @@ LEAF(switch_exit, 1) * int copystr(char *from, char *to, size_t len, size_t *lenp); */ LEAF(copystr, 4) - SETGP(pv) + LDGP(pv) mov a2, t0 /* t0 = i = len */ - beq a2, 2f /* if (len == 0), bail out */ + beq a2, Lcopystr2 /* if (len == 0), bail out */ -1: +Lcopystr1: ldq_u t1, 0(a0) /* t1 = *from */ extbl t1, a0, t1 ldq_u t3, 0(a1) /* set up t2 with quad around *to */ @@ -963,44 +849,44 @@ LEAF(copystr, 4) stq_u t3, 0(a1) /* write out that quad */ subl a2, 1, a2 /* len-- */ - beq t1, 2f /* if (*from == 0), bail out */ + beq t1, Lcopystr2 /* if (*from == 0), bail out */ addq a1, 1, a1 /* to++ */ addq a0, 1, a0 /* from++ */ - bne a2, 1b /* if (len != 0) copy more */ + bne a2, Lcopystr1 /* if (len != 0) copy more */ -2: - beq a3, 3f /* if (lenp != NULL) */ +Lcopystr2: + beq a3, Lcopystr3 /* if (lenp != NULL) */ subl t0, a2, t0 /* *lenp = (i - len) */ stq t0, 0(a3) -3: - beq t1, 4f /* *from == '\0'; leave quietly */ +Lcopystr3: + beq t1, Lcopystr4 /* *from == '\0'; leave quietly */ - CONST(ENAMETOOLONG, v0) /* *from != '\0'; error. */ + ldiq v0, ENAMETOOLONG /* *from != '\0'; error. */ RET -4: +Lcopystr4: mov zero, v0 /* return 0. */ RET END(copystr) NESTED(copyinstr, 4, 16, ra, 0, 0) - SETGP(pv) + LDGP(pv) lda sp, -16(sp) /* set up stack frame */ stq ra, (16-8)(sp) /* save ra */ - CONST(VM_MAX_ADDRESS, t0) /* make sure that src addr */ + ldiq t0, VM_MAX_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) + stq v0, U_PCB+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) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ @@ -1008,23 +894,23 @@ NESTED(copyinstr, 4, 16, ra, 0, 0) END(copyinstr) NESTED(copyoutstr, 4, 16, ra, 0, 0) - SETGP(pv) + LDGP(pv) lda sp, -16(sp) /* set up stack frame */ stq ra, (16-8)(sp) /* save ra */ - CONST(VM_MAX_ADDRESS, t0) /* make sure that dest addr */ + ldiq t0, VM_MAX_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) + stq v0, U_PCB+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) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ @@ -1266,23 +1152,23 @@ bcopy_ov_short: END(bcopy) NESTED(copyin, 3, 16, ra, 0, 0) - SETGP(pv) + LDGP(pv) lda sp, -16(sp) /* set up stack frame */ stq ra, (16-8)(sp) /* save ra */ - CONST(VM_MAX_ADDRESS, t0) /* make sure that src addr */ + ldiq t0, VM_MAX_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) + stq v0, U_PCB+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) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ @@ -1291,23 +1177,23 @@ NESTED(copyin, 3, 16, ra, 0, 0) END(copyin) NESTED(copyout, 3, 16, ra, 0, 0) - SETGP(pv) + LDGP(pv) lda sp, -16(sp) /* set up stack frame */ stq ra, (16-8)(sp) /* save ra */ - CONST(VM_MAX_ADDRESS, t0) /* make sure that dest addr */ + ldiq t0, VM_MAX_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) + stq v0, U_PCB+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) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ @@ -1316,10 +1202,10 @@ NESTED(copyout, 3, 16, ra, 0, 0) END(copyout) LEAF(copyerr, 0) - SETGP(pv) + LDGP(pv) ldq ra, (16-8)(sp) /* restore ra. */ lda sp, 16(sp) /* kill stack frame. */ - CONST(EFAULT, v0) /* return EFAULT. */ + ldiq v0, EFAULT /* return EFAULT. */ RET END(copyerr) @@ -1334,85 +1220,85 @@ END(copyerr) #ifdef notdef LEAF(fuword, 1) XLEAF(fuiword, 1) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswberr /* if it's not, error out. */ lda t0, fswberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) .set at ldq v0, 0(a0) zap v0, 0xf0, v0 .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at RET END(fuword) LEAF(fusword, 1) XLEAF(fuisword, 1) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswberr /* if it's not, error out. */ lda t0, fswberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) .set at /* XXX FETCH IT */ .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at RET END(fusword) LEAF(fubyte, 1) XLEAF(fuibyte, 1) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswberr /* if it's not, error out. */ lda t0, fswberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) .set at /* XXX FETCH IT */ .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at RET END(fubyte) #endif /* notdef */ LEAF(suword, 2) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswberr /* if it's not, error out. */ lda t0, fswberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) .set at stq a1, 0(a0) /* do the wtore. */ .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at mov zero, v0 RET @@ -1420,21 +1306,21 @@ LEAF(suword, 2) #ifdef notdef LEAF(suiword, 2) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswberr /* if it's not, error out. */ lda t0, fswberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) .set at /* XXX STORE IT */ .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at call_pal PAL_OSF1_imb /* sync instruction stream */ mov zero, v0 @@ -1442,42 +1328,42 @@ LEAF(suiword, 2) END(suiword) LEAF(susword, 2) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswberr /* if it's not, error out. */ lda t0, fswberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) .set at /* XXX STORE IT */ .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at mov zero, v0 RET END(susword) LEAF(suisword, 2) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswberr /* if it's not, error out. */ lda t0, fswberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) .set at /* XXX STORE IT */ .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at call_pal PAL_OSF1_imb /* sync instruction stream */ mov zero, v0 @@ -1486,15 +1372,15 @@ LEAF(suisword, 2) #endif /* notdef */ LEAF(subyte, 2) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswberr /* if it's not, error out. */ lda t0, fswberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) .set at zap a1, 0xfe, a1 /* kill arg's high bytes */ insbl a1, a0, a1 /* move it to the right byte */ @@ -1505,22 +1391,22 @@ LEAF(subyte, 2) .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at mov zero, v0 RET END(subyte) LEAF(suibyte, 2) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswberr /* if it's not, error out. */ lda t0, fswberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) .set at zap a1, 0xfe, a1 /* kill arg's high bytes */ insbl a1, a0, a1 /* move it to the right byte */ @@ -1531,7 +1417,7 @@ LEAF(suibyte, 2) .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at call_pal PAL_OSF1_imb /* sync instruction stream */ mov zero, v0 @@ -1539,8 +1425,8 @@ LEAF(suibyte, 2) END(suibyte) LEAF(fswberr, 0) - SETGP(pv) - CONST(-1, v0) + LDGP(pv) + ldiq v0, -1 RET END(fswberr) @@ -1554,41 +1440,43 @@ LEAF(fswberr, 0) */ LEAF(fuswintr, 2) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswintrberr /* if it's not, error out. */ lda t0, fswintrberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) + stq a0, U_PCB+PCB_ACCESSADDR(at_reg) .set at /* XXX FETCH IT */ .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at RET END(fuswintr) LEAF(suswintr, 2) - SETGP(pv) - CONST(VM_MAX_ADDRESS, t0) /* make sure that addr */ + LDGP(pv) + ldiq t0, VM_MAX_ADDRESS /* make sure that addr */ cmpult a0, t0, t1 /* is in user space. */ beq t1, fswintrberr /* if it's not, error out. */ lda t0, fswintrberr .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq t0, U_PCB_ONFAULT(at_reg) + stq t0, U_PCB+PCB_ONFAULT(at_reg) + stq a0, U_PCB+PCB_ACCESSADDR(at_reg) .set at /* XXX STORE IT */ .set noat ldq at_reg, curproc ldq at_reg, P_ADDR(at_reg) - stq zero, U_PCB_ONFAULT(at_reg) + stq zero, U_PCB+PCB_ONFAULT(at_reg) .set at mov zero, v0 RET @@ -1598,8 +1486,8 @@ LEAF(suswintr, 2) LEAF(fswintrberr, 0) XLEAF(fuswintr, 2) /* XXX what is a 'word'? */ XLEAF(suswintr, 2) /* XXX what is a 'word'? */ - SETGP(pv) - CONST(-1, v0) + LDGP(pv) + ldiq v0, -1 RET END(fswberr) @@ -1625,10 +1513,67 @@ EXPORT(eintrcnt) /**************************************************************************/ - .text -LEAF(rpcc,1) - rpcc v0 +/* + * Object: + * swpctxt EXPORTED function + * + * Change HW process context + * + * Arguments: + * pcb PHYSICAL struct pcb_hw * + * old_ksp VIRTUAL long * + * + * If old_ksp is non-zero it saves the current KSP in it. + * Execute the PAL call. + */ +LEAF(swpctxt,2) + beq a1,Lswpctxt1 + stq sp,0(a1) +Lswpctxt1: call_pal PAL_OSF1_swpctx RET - END(pal_mtpr_mces) + END(swpctxt) -/**************************************************************************/ +/* + * 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/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c index 2c04c966fb4..075966bd54d 100644 --- a/sys/arch/alpha/alpha/machdep.c +++ b/sys/arch/alpha/alpha/machdep.c @@ -1,5 +1,5 @@ -/* $OpenBSD: machdep.c,v 1.10 1996/07/29 22:57:43 niklas Exp $ */ -/* $NetBSD: machdep.c,v 1.19.4.5 1996/06/15 03:56:33 cgd Exp $ */ +/* $OpenBSD: machdep.c,v 1.11 1996/10/30 22:38:14 niklas Exp $ */ +/* $NetBSD: machdep.c,v 1.49 1996/10/18 20:35:23 cgd Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -52,6 +52,9 @@ #include <sys/exec.h> #include <sys/exec_ecoff.h> #include <sys/sysctl.h> +#include <sys/core.h> +#include <sys/kcore.h> +#include <machine/kcore.h> #ifdef SYSVMSG #include <sys/msg.h> #endif @@ -65,10 +68,12 @@ #include <sys/mount.h> #include <sys/syscallargs.h> +#include <vm/pmap.h> #include <vm/vm_kern.h> #include <dev/cons.h> +#include <machine/autoconf.h> #include <machine/cpu.h> #include <machine/reg.h> #include <machine/rpb.h> @@ -94,13 +99,37 @@ #endif #include <net/netisr.h> -#include "ether.h" +#include <net/if.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/if_ether.h> +#include <netinet/ip_var.h> +#endif +#ifdef NS +#include <netns/ns_var.h> +#endif +#ifdef ISO +#include <netiso/iso.h> +#include <netiso/clnp.h> +#endif +#include "ppp.h" +#if NPPP > 0 +#include <net/ppp_defs.h> +#include <net/if_ppp.h> +#endif #include "le_ioasic.h" /* for le_iomem creation */ vm_map_t buffer_map; void dumpsys __P((void)); +int cpu_dumpsize __P((void)); +int cpu_dump __P((void)); +void printregs __P((struct reg *)); +void regdump __P((struct trapframe *framep)); +void netintr __P((void)); +void do_sir __P((void)); /* * Declare these as initialized data so we can patch them. @@ -120,7 +149,7 @@ int msgbufmapped = 0; /* set when safe to use msgbuf */ int maxmem; /* max memory per process */ int totalphysmem; /* total amount of physical memory in system */ -int physmem; /* physical memory used by NetBSD + some rsvd */ +int physmem; /* physical memory used by OpenBSD + some rsvd */ int firstusablepage; /* first usable memory page */ int lastusablepage; /* last usable memory page */ int resvmem; /* amount of memory reserved for PROM */ @@ -169,7 +198,8 @@ u_int64_t cycles_per_usec; caddr_t le_iomem; /* XXX iomem for LANCE DMA */ /* Interrupt vectors (in locore) */ -extern int XentInt(), XentArith(), XentMM(), XentIF(), XentUna(), XentSys(); +extern int XentInt __P((void)), XentArith __P((void)), XentMM __P((void)), + XentIF __P((void)), XentUna __P((void)), XentSys __P((void)); /* number of cpus in the box. really! */ int ncpus; @@ -183,7 +213,13 @@ char *cpu_iobus; char boot_flags[64]; /* for cpu_sysctl() */ -char root_device[17]; +char root_device[17]; +int alpha_unaligned_print = 1; /* warn about unaligned accesses */ +int alpha_unaligned_fix = 1; /* fix up unaligned accesses */ +int alpha_unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */ + +void identifycpu __P((void)); +int alpha_init __P((u_long, u_long)); int alpha_init(pfn, ptb) @@ -201,15 +237,16 @@ alpha_init(pfn, ptb) * Make sure the instruction and data streams are consistent. */ (void)splhigh(); - pal_wrfen(0); - TBIA(); - IMB(); + alpha_pal_wrfen(0); + ALPHA_TBIA(); + alpha_pal_imb(); /* * get address of the restart block, while we the bootstrap * mapping is still around. */ - hwrpb = (struct rpb *) phystok0seg(*(struct rpb **)HWRPB_ADDR); + hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG( + (vm_offset_t)(*(struct rpb **)HWRPB_ADDR)); /* * Remember how many cycles there are per microsecond, @@ -226,12 +263,18 @@ alpha_init(pfn, ptb) /* * Point interrupt/exception vectors to our own. */ - pal_wrent(XentInt, 0); - pal_wrent(XentArith, 1); - pal_wrent(XentMM, 2); - pal_wrent(XentIF, 3); - pal_wrent(XentUna, 4); - pal_wrent(XentSys, 5); + alpha_pal_wrent(XentInt, ALPHA_KENTRY_INT); + alpha_pal_wrent(XentArith, ALPHA_KENTRY_ARITH); + alpha_pal_wrent(XentMM, ALPHA_KENTRY_MM); + alpha_pal_wrent(XentIF, ALPHA_KENTRY_IF); + alpha_pal_wrent(XentUna, ALPHA_KENTRY_UNA); + alpha_pal_wrent(XentSys, ALPHA_KENTRY_SYS); + + /* + * Disable System and Processor Correctable Error reporting. + * Clear pending machine checks and error reports, etc. + */ + alpha_pal_wrmces(alpha_pal_rdmces() | ALPHA_MCES_DSC | ALPHA_MCES_DPC); /* * Find out how much memory is available, by looking at @@ -253,13 +296,13 @@ alpha_init(pfn, ptb) #define cnt mddtp->mddt_cluster_cnt #define usage(n) mddtp->mddt_clusters[(n)].mddt_usage if (cnt != 2 && cnt != 3) { - printf("WARNING: weird number (%d) of mem clusters\n", cnt); + printf("WARNING: weird number (%ld) of mem clusters\n", cnt); mddtweird = 1; } else if (usage(0) != MDDT_PALCODE || usage(1) != MDDT_SYSTEM || (cnt == 3 && usage(2) != MDDT_PALCODE)) { mddtweird = 1; - printf("WARNING: %d mem clusters, but weird config\n", cnt); + printf("WARNING: %ld mem clusters, but weird config\n", cnt); } for (i = 0; i < cnt; i++) { @@ -455,7 +498,8 @@ alpha_init(pfn, ptb) if (cputype == ST_DEC_3000_500 || cputype == ST_DEC_3000_300) { /* XXX possibly others? */ lastusablepage -= btoc(128 * 1024); - le_iomem = (caddr_t)phystok0seg(ctob(lastusablepage + 1)); + le_iomem = + (caddr_t)ALPHA_PHYS_TO_K0SEG(ctob(lastusablepage + 1)); } #endif /* NLE_IOASIC */ @@ -463,7 +507,8 @@ alpha_init(pfn, ptb) * Initialize error message buffer (at end of core). */ lastusablepage -= btoc(sizeof (struct msgbuf)); - msgbufp = (struct msgbuf *)phystok0seg(ctob(lastusablepage + 1)); + msgbufp = + (struct msgbuf *)ALPHA_PHYS_TO_K0SEG(ctob(lastusablepage + 1)); msgbufmapped = 1; /* @@ -530,22 +575,31 @@ alpha_init(pfn, ptb) * Initialize the virtual memory system, and set the * page table base register in proc 0's PCB. */ - pmap_bootstrap((vm_offset_t)v, phystok0seg(ptb << PGSHIFT)); +#ifndef NEW_PMAP + pmap_bootstrap((vm_offset_t)v, ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT)); +#else + pmap_bootstrap((vm_offset_t)v, ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT), + hwrpb->rpb_max_asn); +#endif /* * Initialize the rest of proc 0's PCB, and cache its physical * address. */ proc0.p_md.md_pcbpaddr = - (struct pcb *)k0segtophys(&proc0paddr->u_pcb); + (struct pcb *)ALPHA_K0SEG_TO_PHYS((vm_offset_t)&proc0paddr->u_pcb); /* * Set the kernel sp, reserving space for an (empty) trapframe, * and make proc0's trapframe pointer point to it for sanity. */ - proc0paddr->u_pcb.pcb_ksp = + proc0paddr->u_pcb.pcb_hw.apcb_ksp = (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe); - proc0.p_md.md_tf = (struct trapframe *)proc0paddr->u_pcb.pcb_ksp; + proc0.p_md.md_tf = (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp; + +#ifdef NEW_PMAP + pmap_activate(kernel_pmap, &proc0paddr->u_pcb.pcb_hw, 0); +#endif /* * Look at arguments passed to us and compute boothowto. @@ -571,9 +625,21 @@ alpha_init(pfn, ptb) boothowto &= ~RB_SINGLE; break; - case 'n': /* askname */ - case 'N': - boothowto |= RB_ASKNAME; + case 'c': /* enter user kernel configuration */ + case 'C': + boothowto |= RB_CONFIG; + break; + +#ifdef DEBUG + case 'd': /* crash dump immediately after autoconfig */ + case 'D': + boothowto |= RB_DUMP; + break; +#endif + + case 'h': /* always halt, never reboot */ + case 'H': + boothowto |= RB_HALT; break; #if 0 @@ -582,6 +648,11 @@ alpha_init(pfn, ptb) boothowto |= RB_MINIROOT; break; #endif + + case 'n': /* askname */ + case 'N': + boothowto |= RB_ASKNAME; + break; } } @@ -613,11 +684,10 @@ void cpu_startup() { register unsigned i; - register caddr_t v; int base, residual; vm_offset_t minaddr, maxaddr; vm_size_t size; -#ifdef DEBUG +#if defined(DEBUG) extern int pmapdebug; int opmapdebug = pmapdebug; @@ -629,7 +699,7 @@ cpu_startup() */ printf(version); identifycpu(); - printf("real mem = %d (%d reserved for PROM, %d used by NetBSD)\n", + printf("real mem = %d (%d reserved for PROM, %d used by OpenBSD)\n", ctob(totalphysmem), ctob(resvmem), ctob(physmem)); if (unusedmem) printf("WARNING: unused memory = %d bytes\n", ctob(unusedmem)); @@ -697,7 +767,7 @@ cpu_startup() callout[i-1].c_next = &callout[i]; callout[i-1].c_next = NULL; -#ifdef DEBUG +#if defined(DEBUG) pmapdebug = opmapdebug; #endif printf("avail mem = %ld\n", (long)ptoa(cnt.v_free_count)); @@ -720,17 +790,24 @@ cpu_startup() #endif } configure(); + + /* + * Note that bootstrapping is finished, and set the HWRPB up + * to do restarts. + */ + hwrbp_restart_setup(); } +void identifycpu() { /* * print out CPU identification information. */ - printf("%s, %dMHz\n", cpu_model, + printf("%s, %ldMHz\n", cpu_model, hwrpb->rpb_cc_freq / 1000000); /* XXX true for 21164? */ - printf("%d byte page size, %d processor%s.\n", + printf("%ld byte page size, %d processor%s.\n", hwrpb->rpb_page_size, ncpus, ncpus == 1 ? "" : "s"); #if 0 /* this isn't defined for any systems that we run on? */ @@ -747,8 +824,9 @@ int waittime = -1; struct pcb dumppcb; void -boot(howto) +boot(howto /* , bootstr */) int howto; + /* char *bootstr; */ { extern int cold; @@ -758,8 +836,18 @@ boot(howto) goto haltsys; } + /* If "always halt" was specified as a boot flag, obey. */ + if ((boothowto & RB_HALT) != 0) + howto |= RB_HALT; + boothowto = howto; if ((howto & RB_NOSYNC) == 0 && waittime < 0) { + extern struct proc proc0; + + /* protect against curproc->p_stats.foo refs in sync XXX */ + if (curproc == NULL) + curproc = &proc0; + waittime = 0; vfs_shutdown(); /* @@ -773,10 +861,12 @@ boot(howto) splhigh(); /* If rebooting and a dump is requested do it. */ - if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) { - savectx(&dumppcb, 0); +#if 0 + if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) +#else + if (howto & RB_DUMP) +#endif dumpsys(); - } haltsys: @@ -803,6 +893,55 @@ int dumpsize = 0; /* pages */ long dumplo = 0; /* blocks */ /* + * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. + */ +int +cpu_dumpsize() +{ + int size; + + size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); + if (roundup(size, dbtob(1)) != dbtob(1)) + return -1; + + return (1); +} + +/* + * cpu_dump: dump machine-dependent kernel core dump headers. + */ +int +cpu_dump() +{ + int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); + long buf[dbtob(1) / sizeof (long)]; + kcore_seg_t *segp; + cpu_kcore_hdr_t *cpuhdrp; + + dump = bdevsw[major(dumpdev)].d_dump; + + segp = (kcore_seg_t *)buf; + cpuhdrp = + (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)]; + + /* + * Generate a segment header. + */ + CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); + segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); + + /* + * Add the machine-dependent header info + */ + cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map); + cpuhdrp->page_size = PAGE_SIZE; + cpuhdrp->core_seg.start = ctob(firstusablepage); + cpuhdrp->core_seg.size = ctob(physmem); + + return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1))); +} + +/* * This is called by configure to set dumplo and dumpsize. * Dumps always skip the first CLBYTES of disk space * in case there might be a disk label stored there. @@ -812,55 +951,114 @@ long dumplo = 0; /* blocks */ void dumpconf() { - int nblks; /* size of dump area */ + int nblks, dumpblks; /* size of dump area */ int maj; if (dumpdev == NODEV) - return; + goto bad; maj = major(dumpdev); if (maj < 0 || maj >= nblkdev) panic("dumpconf: bad dumpdev=0x%x", dumpdev); if (bdevsw[maj].d_psize == NULL) - return; + goto bad; nblks = (*bdevsw[maj].d_psize)(dumpdev); if (nblks <= ctod(1)) - return; + goto bad; - /* XXX XXX XXX STARTING MEMORY LOCATION */ - dumpsize = physmem; + dumpblks = cpu_dumpsize(); + if (dumpblks < 0) + goto bad; + dumpblks += ctod(physmem); - /* Always skip the first CLBYTES, in case there is a label there. */ - if (dumplo < ctod(1)) - dumplo = ctod(1); + /* If dump won't fit (incl. room for possible label), punt. */ + if (dumpblks > (nblks - ctod(1))) + goto bad; - /* Put dump at end of partition, and make it fit. */ - if (dumpsize > dtoc(nblks - dumplo)) - dumpsize = dtoc(nblks - dumplo); - if (dumplo < nblks - ctod(dumpsize)) - dumplo = nblks - ctod(dumpsize); + /* Put dump at end of partition */ + dumplo = nblks - dumpblks; + + /* dumpsize is in page units, and doesn't include headers. */ + dumpsize = physmem; + return; + +bad: + dumpsize = 0; + return; } /* - * Doadump comes here after turning off memory management and - * getting on the dump stack, either when called above, or by - * the auto-restart code. + * Dump the kernel's image to the swap partition. */ +#define BYTES_PER_DUMP NBPG + void dumpsys() { + unsigned bytes, i, n; + int maddr, psize; + daddr_t blkno; + int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); + int error; - msgbufmapped = 0; + /* Save registers. */ + savectx(&dumppcb); + + msgbufmapped = 0; /* don't record dump msgs in msgbuf */ if (dumpdev == NODEV) return; - if (dumpsize == 0) { + + /* + * For dumps during autoconfiguration, + * if dump device has already configured... + */ + if (dumpsize == 0) dumpconf(); - if (dumpsize == 0) - return; + if (dumplo <= 0) { + printf("\ndump to dev %x not possible\n", dumpdev); + return; } - printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); + printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo); + psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); printf("dump "); - switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { + if (psize == -1) { + printf("area unavailable\n"); + return; + } + + /* XXX should purge all outstanding keystrokes. */ + + if ((error = cpu_dump()) != 0) + goto err; + + bytes = ctob(physmem); + maddr = ctob(firstusablepage); + blkno = dumplo + cpu_dumpsize(); + dump = bdevsw[major(dumpdev)].d_dump; + error = 0; + for (i = 0; i < bytes; i += n) { + + /* Print out how many MBs we to go. */ + n = bytes - i; + if (n && (n % (1024*1024)) == 0) + printf("%d ", n / (1024 * 1024)); + + /* Limit size for next transfer. */ + if (n > BYTES_PER_DUMP) + n = BYTES_PER_DUMP; + + error = (*dump)(dumpdev, blkno, + (caddr_t)ALPHA_PHYS_TO_K0SEG(maddr), n); + if (error) + break; + maddr += n; + blkno += btodb(n); /* XXX? */ + + /* XXX should look for keystrokes, to cancel. */ + } + +err: + switch (error) { case ENXIO: printf("device bad\n"); @@ -882,9 +1080,13 @@ dumpsys() printf("aborted from console\n"); break; - default: + case 0: printf("succeeded\n"); break; + + default: + printf("error %d\n", error); + break; } printf("\n\n"); delay(1000); @@ -912,9 +1114,9 @@ frametoreg(framep, regp) regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4]; regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5]; regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6]; - regp->r_regs[R_A0] = framep->tf_a0; - regp->r_regs[R_A1] = framep->tf_a1; - regp->r_regs[R_A2] = framep->tf_a2; + regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0]; + regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1]; + regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2]; regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3]; regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4]; regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5]; @@ -925,8 +1127,8 @@ frametoreg(framep, regp) regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA]; regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12]; regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT]; - regp->r_regs[R_GP] = framep->tf_gp; - regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; + regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP]; + /* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */ regp->r_regs[R_ZERO] = 0; } @@ -952,9 +1154,9 @@ regtoframe(regp, framep) framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4]; framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5]; framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6]; - framep->tf_a0 = regp->r_regs[R_A0]; - framep->tf_a1 = regp->r_regs[R_A1]; - framep->tf_a2 = regp->r_regs[R_A2]; + framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0]; + framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1]; + framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2]; framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3]; framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4]; framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5]; @@ -965,8 +1167,8 @@ regtoframe(regp, framep) framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA]; framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12]; framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT]; - framep->tf_gp = regp->r_regs[R_GP]; - framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; + framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP]; + /* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */ /* ??? = regp->r_regs[R_ZERO]; */ } @@ -988,6 +1190,8 @@ regdump(framep) struct reg reg; frametoreg(framep, ®); + reg.r_regs[R_SP] = alpha_pal_rdusp(); + printf("REGISTERS:\n"); printregs(®); } @@ -1033,13 +1237,12 @@ sendsig(catcher, sig, mask, code) psp->ps_sigstk.ss_size - rndfsize); psp->ps_sigstk.ss_flags |= SS_ONSTACK; } else - scp = (struct sigcontext *)(frame->tf_regs[FRAME_SP] - - rndfsize); + scp = (struct sigcontext *)(alpha_pal_rdusp() - rndfsize); if ((u_long)scp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) (void)grow(p, (u_long)scp); #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) - printf("sendsig(%d): sig %d ssp %lx usp %lx\n", p->p_pid, + printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, sig, &oonstack, scp); #endif if (useracc((caddr_t)scp, fsize, B_WRITE) == 0) { @@ -1066,18 +1269,19 @@ sendsig(catcher, sig, mask, code) */ ksc.sc_onstack = oonstack; ksc.sc_mask = mask; - ksc.sc_pc = frame->tf_pc; - ksc.sc_ps = frame->tf_ps; + ksc.sc_pc = frame->tf_regs[FRAME_PC]; + ksc.sc_ps = frame->tf_regs[FRAME_PS]; /* copy the registers. */ frametoreg(frame, (struct reg *)ksc.sc_regs); ksc.sc_regs[R_ZERO] = 0xACEDBADE; /* magic number */ + ksc.sc_regs[R_SP] = alpha_pal_rdusp(); /* save the floating-point state, if necessary, then copy it. */ if (p == fpcurproc) { - pal_wrfen(1); + alpha_pal_wrfen(1); savefpstate(&p->p_addr->u_pcb.pcb_fp); - pal_wrfen(0); + alpha_pal_wrfen(0); fpcurproc = NULL; } ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED; @@ -1100,24 +1304,25 @@ sendsig(catcher, sig, mask, code) (void) copyout((caddr_t)&ksc, (caddr_t)scp, fsize); #ifdef DEBUG if (sigdebug & SDB_FOLLOW) - printf("sendsig(%d): sig %d scp %lx code %lx\n", p->p_pid, sig, + printf("sendsig(%d): sig %d scp %p code %lx\n", p->p_pid, sig, scp, code); #endif /* * Set up the registers to return to sigcode. */ - frame->tf_pc = (u_int64_t)PS_STRINGS - (esigcode - sigcode); - frame->tf_regs[FRAME_SP] = (u_int64_t)scp; - frame->tf_a0 = sig; - frame->tf_a1 = code; - frame->tf_a2 = (u_int64_t)scp; + frame->tf_regs[FRAME_PC] = + (u_int64_t)PS_STRINGS - (esigcode - sigcode); + frame->tf_regs[FRAME_A0] = sig; + frame->tf_regs[FRAME_A1] = code; + frame->tf_regs[FRAME_A2] = (u_int64_t)scp; frame->tf_regs[FRAME_T12] = (u_int64_t)catcher; /* t12 is pv */ + alpha_pal_wrusp((unsigned long)scp); #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid, - frame->tf_pc, frame->tf_regs[FRAME_A3]); + frame->tf_regs[FRAME_PC], frame->tf_regs[FRAME_A3]); if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); @@ -1150,7 +1355,7 @@ sys_sigreturn(p, v, retval) scp = SCARG(uap, sigcntxp); #ifdef DEBUG if (sigdebug & SDB_FOLLOW) - printf("sigreturn: pid %d, scp %lx\n", p->p_pid, scp); + printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); #endif if (ALIGN(scp) != (u_int64_t)scp) @@ -1175,10 +1380,12 @@ sys_sigreturn(p, v, retval) p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; p->p_sigmask = ksc.sc_mask &~ sigcantmask; - p->p_md.md_tf->tf_pc = ksc.sc_pc; - p->p_md.md_tf->tf_ps = (ksc.sc_ps | PSL_USERSET) & ~PSL_USERCLR; + p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc; + p->p_md.md_tf->tf_regs[FRAME_PS] = + (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR; regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf); + alpha_pal_wrusp(ksc.sc_regs[R_SP]); /* XXX ksc.sc_ownedfp ? */ if (p == fpcurproc) @@ -1197,6 +1404,7 @@ sys_sigreturn(p, v, retval) /* * machine dependent system variables. */ +int cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) int *name; u_int namelen; @@ -1224,6 +1432,18 @@ cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) case CPU_ROOT_DEVICE: return (sysctl_rdstring(oldp, oldlenp, newp, root_device)); + case CPU_UNALIGNED_PRINT: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &alpha_unaligned_print)); + + case CPU_UNALIGNED_FIX: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &alpha_unaligned_fix)); + + case CPU_UNALIGNED_SIGBUS: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &alpha_unaligned_sigbus)); + default: return (EOPNOTSUPP); } @@ -1245,27 +1465,31 @@ setregs(p, pack, stack, retval) extern struct proc *fpcurproc; #ifdef DEBUG - for (i = 0; i < FRAME_NSAVEREGS; i++) + /* + * Crash and dump, if the user requested it. + */ + if (boothowto & RB_DUMP) + panic("crash requested by boot flags"); +#endif + +#ifdef DEBUG + for (i = 0; i < FRAME_SIZE; i++) tfp->tf_regs[i] = 0xbabefacedeadbeef; - tfp->tf_gp = 0xbabefacedeadbeef; - tfp->tf_a0 = 0xbabefacedeadbeef; - tfp->tf_a1 = 0xbabefacedeadbeef; - tfp->tf_a2 = 0xbabefacedeadbeef; #else - bzero(tfp->tf_regs, FRAME_NSAVEREGS * sizeof tfp->tf_regs[0]); - tfp->tf_gp = 0; - tfp->tf_a0 = 0; - tfp->tf_a1 = 0; - tfp->tf_a2 = 0; + bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]); #endif bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp); #define FP_RN 2 /* XXX */ p->p_addr->u_pcb.pcb_fp.fpr_cr = (long)FP_RN << 58; - tfp->tf_regs[FRAME_SP] = stack; /* restored to usp in trap return */ - tfp->tf_ps = PSL_USERSET; - tfp->tf_pc = pack->ep_entry & ~3; + alpha_pal_wrusp(stack); + tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET; + tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3; + + tfp->tf_regs[FRAME_A0] = stack; + /* a1 and a2 already zeroed */ + tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC]; /* a.k.a. PV */ - p->p_md.md_flags & ~MDP_FPUSED; + p->p_md.md_flags &= ~MDP_FPUSED; if (fpcurproc == p) fpcurproc = NULL; @@ -1275,42 +1499,40 @@ setregs(p, pack, stack, retval) void netintr() { + int n, s; + + s = splhigh(); + n = netisr; + netisr = 0; + splx(s); + +#define DONETISR(bit, fn) \ + do { \ + if (n & (1 << (bit))) \ + fn; \ + } while (0) + #ifdef INET -#if NETHER > 0 - if (netisr & (1 << NETISR_ARP)) { - netisr &= ~(1 << NETISR_ARP); - arpintr(); - } -#endif - if (netisr & (1 << NETISR_IP)) { - netisr &= ~(1 << NETISR_IP); - ipintr(); - } + DONETISR(NETISR_ARP, arpintr()); + DONETISR(NETISR_IP, ipintr()); #endif #ifdef NS - if (netisr & (1 << NETISR_NS)) { - netisr &= ~(1 << NETISR_NS); - nsintr(); - } + DONETISR(NETISR_NS, nsintr()); #endif #ifdef ISO - if (netisr & (1 << NETISR_ISO)) { - netisr &= ~(1 << NETISR_ISO); - clnlintr(); - } + DONETISR(NETISR_ISO, clnlintr()); #endif #ifdef CCITT - if (netisr & (1 << NETISR_CCITT)) { - netisr &= ~(1 << NETISR_CCITT); - ccittintr(); - } + DONETISR(NETISR_CCITT, ccittintr()); #endif -#ifdef PPP - if (netisr & (1 << NETISR_PPP)) { - netisr &= ~(1 << NETISR_PPP); - pppintr(); - } +#ifdef NATM + DONETISR(NETISR_NATM, natmintr()); +#endif +#if NPPP > 1 + DONETISR(NETISR_PPP, pppintr()); #endif + +#undef DONETISR } void @@ -1338,7 +1560,7 @@ spl0() do_sir(); } - return (pal_swpipl(PSL_IPL_0)); + return (alpha_pal_swpipl(ALPHA_PSL_IPL_0)); } /* @@ -1431,9 +1653,9 @@ microtime(tvp) /* * Wait "n" microseconds. */ -int +void delay(n) - int n; + unsigned long n; { long N = cycles_per_usec * (n); @@ -1452,7 +1674,7 @@ cpu_exec_ecoff_setregs(p, epp, stack, retval) struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; setregs(p, epp, stack, retval); - p->p_md.md_tf->tf_gp = execp->a.gp_value; + p->p_md.md_tf->tf_regs[FRAME_GP] = execp->a.gp_value; } /* @@ -1480,7 +1702,7 @@ cpu_exec_ecoff_hook(p, epp) break; #endif - case ECOFF_MAGIC_NETBSD_ALPHA: + case ECOFF_MAGIC_NATIVE_ALPHA: epp->ep_emul = &emul_native; break; @@ -1490,24 +1712,3 @@ cpu_exec_ecoff_hook(p, epp) return 0; } #endif - -vm_offset_t -vtophys(vaddr) - vm_offset_t vaddr; -{ - vm_offset_t paddr; - - if (vaddr < K0SEG_BEGIN) { - printf("vtophys: invalid vaddr 0x%lx", vaddr); - paddr = vaddr; - } else if (vaddr < K0SEG_END) - paddr = k0segtophys(vaddr); - else - paddr = vatopa(vaddr); - -#if 0 - printf("vtophys(0x%lx) -> %lx\n", vaddr, paddr); -#endif - - return (paddr); -} diff --git a/sys/arch/alpha/alpha/mainbus.c b/sys/arch/alpha/alpha/mainbus.c index 13aff1bbbad..e610c2b7f49 100644 --- a/sys/arch/alpha/alpha/mainbus.c +++ b/sys/arch/alpha/alpha/mainbus.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mainbus.c,v 1.5 1996/07/29 22:57:45 niklas Exp $ */ -/* $NetBSD: mainbus.c,v 1.9 1996/04/12 06:07:35 cgd Exp $ */ +/* $OpenBSD: mainbus.c,v 1.6 1996/10/30 22:38:15 niklas Exp $ */ +/* $NetBSD: mainbus.c,v 1.12 1996/10/13 02:59:40 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -44,7 +44,7 @@ struct mainbus_softc { /* Definition of the mainbus driver. */ static int mbmatch __P((struct device *, void *, void *)); static void mbattach __P((struct device *, struct device *, void *)); -static int mbprint __P((void *, char *)); +static int mbprint __P((void *, /* const */ char *)); struct cfattach mainbus_ca = { sizeof(struct mainbus_softc), mbmatch, mbattach @@ -87,9 +87,8 @@ mbattach(parent, self, aux) { struct mainbus_softc *sc = (struct mainbus_softc *)self; struct confargs nca; - struct pcs *pcsp; int i, cpuattachcnt; - extern int cputype, ncpus; + extern int ncpus; extern char *cpu_iobus; printf("\n"); @@ -136,7 +135,7 @@ mbattach(parent, self, aux) static int mbprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { struct confargs *ca = aux; diff --git a/sys/arch/alpha/alpha/mcclock.c b/sys/arch/alpha/alpha/mcclock.c index 6bec1b29f85..6c4b457f586 100644 --- a/sys/arch/alpha/alpha/mcclock.c +++ b/sys/arch/alpha/alpha/mcclock.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mcclock.c,v 1.2 1996/07/29 22:57:47 niklas Exp $ */ -/* $NetBSD: mcclock.c,v 1.2 1996/04/17 22:22:32 cgd Exp $ */ +/* $OpenBSD: mcclock.c,v 1.3 1996/10/30 22:38:16 niklas Exp $ */ +/* $NetBSD: mcclock.c,v 1.4 1996/10/13 02:59:41 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/alpha/mcclockvar.h b/sys/arch/alpha/alpha/mcclockvar.h index 73cd23ed7ce..f1064251092 100644 --- a/sys/arch/alpha/alpha/mcclockvar.h +++ b/sys/arch/alpha/alpha/mcclockvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mcclockvar.h,v 1.2 1996/07/29 22:57:48 niklas Exp $ */ +/* $OpenBSD: mcclockvar.h,v 1.3 1996/10/30 22:38:17 niklas Exp $ */ /* $NetBSD: mcclockvar.h,v 1.2 1996/04/17 22:22:38 cgd Exp $ */ /* diff --git a/sys/arch/alpha/alpha/mem.c b/sys/arch/alpha/alpha/mem.c index 747e36b50aa..46e0a555cd4 100644 --- a/sys/arch/alpha/alpha/mem.c +++ b/sys/arch/alpha/alpha/mem.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mem.c,v 1.4 1996/07/29 22:57:49 niklas Exp $ */ -/* $NetBSD: mem.c,v 1.6 1996/04/12 02:06:21 cgd Exp $ */ +/* $OpenBSD: mem.c,v 1.5 1996/10/30 22:38:17 niklas Exp $ */ +/* $NetBSD: mem.c,v 1.9 1996/08/20 23:00:25 cgd Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -59,11 +59,17 @@ caddr_t zeropage; extern int firstusablepage, lastusablepage; +int mmopen __P((dev_t, int, int, struct proc *)); +int mmclose __P((dev_t, int, int, struct proc *)); +int mmrw __P((dev_t, struct uio *, int)); +int mmmmap __P((dev_t, vm_offset_t, int)); + /*ARGSUSED*/ int -mmopen(dev, flag, mode) +mmopen(dev, flag, mode, p) dev_t dev; int flag, mode; + struct proc *p; { return (0); @@ -71,15 +77,17 @@ mmopen(dev, flag, mode) /*ARGSUSED*/ int -mmclose(dev, flag, mode) +mmclose(dev, flag, mode, p) dev_t dev; int flag, mode; + struct proc *p; { return (0); } /*ARGSUSED*/ +int mmrw(dev, uio, flags) dev_t dev; struct uio *uio; @@ -113,15 +121,16 @@ kmemphys: #endif o = uio->uio_offset & PGOFSET; c = min(uio->uio_resid, (int)(NBPG - o)); - error = uiomove((caddr_t)phystok0seg(v), c, uio); + error = + uiomove((caddr_t)ALPHA_PHYS_TO_K0SEG(v), c, uio); continue; /* minor device 1 is kernel memory */ case 1: v = uio->uio_offset; - if (v >= K0SEG_BEGIN && v < K0SEG_END) { - v = k0segtophys(v); + if (v >= ALPHA_K0SEG_BASE && v <= ALPHA_K0SEG_END) { + v = ALPHA_K0SEG_TO_PHYS(v); goto kmemphys; } @@ -152,7 +161,7 @@ kmemphys: * is a global zeroed page, the null segment table. */ if (zeropage == NULL) { -#if CLBYTES == NBPG +#if (CLBYTES == NBPG) && !defined(NEW_PMAP) extern caddr_t Segtabzero; zeropage = Segtabzero; #else diff --git a/sys/arch/alpha/alpha/pal.s b/sys/arch/alpha/alpha/pal.s index 1dc00e428d9..4be046c27af 100644 --- a/sys/arch/alpha/alpha/pal.s +++ b/sys/arch/alpha/alpha/pal.s @@ -1,5 +1,5 @@ -/* $OpenBSD: pal.s,v 1.3 1996/07/29 22:57:51 niklas Exp $ */ -/* $NetBSD: pal.s,v 1.2 1995/11/23 02:34:23 cgd Exp $ */ +/* $OpenBSD: pal.s,v 1.4 1996/10/30 22:38:18 niklas Exp $ */ +/* $NetBSD: pal.s,v 1.5 1996/07/14 04:21:53 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -37,166 +37,89 @@ */ /* - * pal_bpt: Breakpoint trap [UNPRIVILEGED] + * alpha_rpcc: read process cycle counter (XXX INSTRUCTION, NOT PALcode OP) */ - .text -LEAF(pal_bpt,0) - call_pal PAL_bpt - RET - END(pal_bpt) - -/* - * pal_bugchk: Bugcheck trap [UNPRIVILEGED] - */ - .text -LEAF(pal_bugchk,0) - call_pal PAL_bugchk - RET - END(pal_bugchk) + .text +LEAF(alpha_rpcc,1) + rpcc v0 + RET + END(alpha_rpcc) -#ifdef ILLEGAL /* ILLEGAL FROM KERNEL MODE */ /* - * pal_callsys: System call [UNPRIVILEGED] + * alpha_mb: memory barrier (XXX INSTRUCTION, NOT PALcode OP) */ .text -LEAF(pal_callsys,0) - call_pal PAL_OSF1_callsys +LEAF(alpha_mb,0) + mb RET - END(pal_callsys) -#endif /* ILLEGAL */ + END(alpha_mb) /* - * pal_gentrap: Generate trap [UNPRIVILEGED] + * alpha_wmb: write memory barrier (XXX INSTRUCTION, NOT PALcode OP) */ .text -LEAF(pal_gentrap,0) - call_pal PAL_gentrap +LEAF(alpha_wmb,0) + /* wmb XXX */ + mb /* XXX */ RET - END(pal_gentrap) + END(alpha_wmb) /* - * pal_imb: I-Stream memory barrier. [UNPRIVILEGED] + * alpha_pal_imb: I-Stream memory barrier. [UNPRIVILEGED] * (Makes instruction stream coherent with data stream.) */ .text -LEAF(pal_imb,0) +LEAF(alpha_pal_imb,0) call_pal PAL_imb RET - END(pal_imb) - -/* - * pal_rdunique: Read process unique value. [UNPRIVILEGED] - * - * Return: - * v0 current process unique value - */ - .text -LEAF(pal_rdunique,0) - call_pal PAL_rdunique - RET - END(pal_rdunique) - -/* - * pal_wrunique: Write process unique value. [UNPRIVILEGED] - * Arguments: - * a0 new process unique value - */ - .text -LEAF(pal_wrunique,1) - call_pal PAL_wrunique - RET - END(pal_wrunique) + END(alpha_pal_imb) /* - * pal_draina: Drain aborts. [PRIVILEGED] + * alpha_pal_draina: Drain aborts. [PRIVILEGED] */ .text -LEAF(pal_draina,0) +LEAF(alpha_pal_draina,0) call_pal PAL_draina RET - END(pal_draina) + END(alpha_pal_draina) /* - * pal_halt: Halt the processor. [PRIVILEGED] + * alpha_pal_halt: Halt the processor. [PRIVILEGED] */ .text -LEAF(pal_halt,0) +LEAF(alpha_pal_halt,0) call_pal PAL_halt - br zero,pal_halt /* Just in case */ + br zero,alpha_pal_halt /* Just in case */ RET - END(pal_halt) + END(alpha_pal_halt) /* - * pal_rdps: Read processor status. [PRIVILEGED] + * alpha_pal_rdmces: Read MCES processor register. [PRIVILEGED] * * Return: - * v0 current processor status + * v0 current MCES value */ .text -LEAF(pal_rdps,0) - call_pal PAL_OSF1_rdps +LEAF(alpha_pal_rdmces,1) + call_pal PAL_OSF1_rdmces RET - END(pal_rdps) + END(alpha_pal_rdmces) /* - * pal_rdusp: Read user stack pointer. [PRIVILEGED] + * alpha_pal_rdusp: Read user stack pointer. [PRIVILEGED] * * Return: * v0 current user stack pointer */ .text -LEAF(pal_rdusp,0) +LEAF(alpha_pal_rdusp,0) call_pal PAL_OSF1_rdusp RET - END(pal_rdusp) - -/* - * pal_rdval: Read system value. [PRIVILEGED] - * - * Return: - * v0 current system value - */ - .text -LEAF(pal_rdval,0) - call_pal PAL_OSF1_rdval - RET - END(pal_rdval) - -/* - * pal_retsys: Return from system call. [PRIVILEGED] - */ - .text -LEAF(pal_retsys,0) - call_pal PAL_OSF1_retsys - RET - END(pal_retsys) - -/* - * pal_rti: Return from trap, fault, or interrupt. [PRIVILEGED] - */ - .text -LEAF(pal_rti,0) - call_pal PAL_OSF1_rti - RET - END(pal_rti) - -/* - * pal_swpctx: Swap process context. [PRIVILEGED] - * - * Arguments: - * a0 new PCB - * - * Return: - * v0 old PCB - */ - .text -LEAF(pal_swpctx,1) - call_pal PAL_OSF1_swpctx - RET - END(pal_swpctx) + END(alpha_pal_rdusp) /* - * pal_swpipl: Swap Interrupt priority level. [PRIVILEGED] + * alpha_pal_swpipl: Swap Interrupt priority level. [PRIVILEGED] + * _alpha_pal_swpipl: Same, from profiling code. [PRIVILEGED] * * Arguments: * a0 new IPL @@ -205,122 +128,98 @@ LEAF(pal_swpctx,1) * v0 old IPL */ .text -LEAF(pal_swpipl,1) +LEAF(alpha_pal_swpipl,1) call_pal PAL_OSF1_swpipl RET - END(pal_swpipl) + END(alpha_pal_swpipl) -LEAF_NOPROFILE(profile_swpipl,1) +LEAF_NOPROFILE(_alpha_pal_swpipl,1) call_pal PAL_OSF1_swpipl RET - END(profile_swpipl) + END(_alpha_pal_swpipl) /* - * pal_tbi: Translation buffer invalidate. [PRIVILEGED] + * alpha_pal_tbi: Translation buffer invalidate. [PRIVILEGED] * * Arguments: * a0 operation selector * a1 address to operate on (if necessary) */ .text -LEAF(pal_tbi,2) +LEAF(alpha_pal_tbi,2) call_pal PAL_OSF1_tbi RET - END(pal_tbi) + END(alpha_pal_tbi) /* - * pal_whami: Who am I? [PRIVILEGED] + * alpha_pal_whami: Who am I? [PRIVILEGED] * * Return: * v0 processor number */ .text -LEAF(pal_whami,0) +LEAF(alpha_pal_whami,0) call_pal PAL_OSF1_whami RET - END(pal_whami) + END(alpha_pal_whami) /* - * pal_wrent: Write system entry address. [PRIVILEGED] + * alpha_pal_wrent: Write system entry address. [PRIVILEGED] * * Arguments: * a0 new vector * a1 vector selector */ .text -LEAF(pal_wrent,2) +LEAF(alpha_pal_wrent,2) call_pal PAL_OSF1_wrent RET - END(pal_wrent) + END(alpha_pal_wrent) /* - * pal_wrfen: Write floating-point enable. [PRIVILEGED] + * alpha_pal_wrfen: Write floating-point enable. [PRIVILEGED] * * Arguments: * a0 new enable value (val & 0x1 -> enable). */ .text -LEAF(pal_wrfen,1) +LEAF(alpha_pal_wrfen,1) call_pal PAL_OSF1_wrfen RET - END(pal_wrfen) - -/* - * pal_wrkgp: Write kernel global pointer. [PRIVILEGED] - * - * Arguments: - * a0 new kernel global pointer - */ - .text -LEAF(pal_wrkgp,1) - call_pal PAL_OSF1_wrkgp - RET - END(pal_wrkgp) + END(alpha_pal_wrfen) /* - * pal_wrusp: Write user stack pointer. [PRIVILEGED] + * alpha_pal_wrusp: Write user stack pointer. [PRIVILEGED] * * Arguments: * a0 new user stack pointer */ .text -LEAF(pal_wrusp,1) +LEAF(alpha_pal_wrusp,1) call_pal PAL_OSF1_wrusp RET - END(pal_wrusp) - -/* - * pal_wrval: Write system value. [PRIVILEGED] - * - * Arguments: - * a0 new system value - */ - .text -LEAF(pal_wrval,1) - call_pal PAL_OSF1_wrval - RET - END(pal_wrval) + END(alpha_pal_wrusp) /* - * pal_wrvptptr: Write virtual page table pointer. [PRIVILEGED] + * alpha_pal_wrvptptr: Write virtual page table pointer. [PRIVILEGED] * * Arguments: * a0 new virtual page table pointer */ .text -LEAF(pal_wrvptptr,1) +LEAF(alpha_pal_wrvptptr,1) call_pal PAL_OSF1_wrvptptr RET - END(pal_wrvptptr) + END(alpha_pal_wrvptptr) /* - * pal_mtpr_mces: Write MCES processor register. [PRIVILEGED, VMS, XXX!] + * alpha_pal_wrmces: Write MCES processor register. [PRIVILEGED] * * Arguments: * a0 value to write to MCES */ .text -LEAF(pal_mtpr_mces,1) - call_pal PAL_VMS_mtpr_mces +LEAF(alpha_pal_wrmces,1) + call_pal PAL_OSF1_wrmces RET - END(pal_mtpr_mces) + END(alpha_pal_wrmces) diff --git a/sys/arch/alpha/alpha/pmap.c b/sys/arch/alpha/alpha/pmap.c index dfd75311e7e..2357e853826 100644 --- a/sys/arch/alpha/alpha/pmap.c +++ b/sys/arch/alpha/alpha/pmap.c @@ -1,79 +1,51 @@ -/* $OpenBSD: pmap.c,v 1.4 1996/07/29 22:57:53 niklas Exp $ */ -/* $NetBSD: pmap.c,v 1.8 1996/04/12 02:09:24 cgd Exp $ */ +/* $OpenBSD: pmap.c,v 1.5 1996/10/30 22:38:20 niklas Exp $ */ +/* $NetBSD: pmap.c,v 1.17 1996/10/13 02:59:42 christos Exp $ */ -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. 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. - * - * @(#)pmap.c 8.6 (Berkeley) 5/27/94 +/* + * Copyright (c) 1992, 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. */ -#ifdef XXX /* - * HP9000/300 series physical map management code. - * - * Supports: - * 68020 with HP MMU models 320, 350 - * 68020 with 68551 MMU models 318, 319, 330 (all untested) - * 68030 with on-chip MMU models 340, 360, 370, 345, 375, 400 - * 68040 with on-chip MMU models 380, 425, 433 + * File: pmap.c * - * Notes: - * Don't even pay lip service to multiprocessor support. + * Author list + * vax: Avadis Tevanian, Jr., Michael Wayne Young + * i386: Lance Berc, Mike Kupfer, Bob Baron, David Golub, Richard Draves + * alpha: Alessandro Forin + * {Net,Open}BSD/Alpha: Chris Demetriou * - * We assume TLB entries don't have process tags (except for the - * supervisor/user distinction) so we only invalidate TLB entries - * when changing mappings for the current (or kernel) pmap. This is - * technically not true for the 68551 but we flush the TLB on every - * context switch, so it effectively winds up that way. + * Physical Map management code for DEC Alpha * - * Bitwise and/or operations are significantly faster than bitfield - * references so we use them when accessing STE/PTEs in the pmap_pte_* - * macros. Note also that the two are not always equivalent; e.g.: - * (*(int *)pte & PG_PROT) [4] != pte->pg_prot [1] - * and a couple of routines that deal with protection and wiring take - * some shortcuts that assume the and/or definitions. + * Manages physical address maps. * - * This implementation will only work for PAGE_SIZE == NBPG - * (i.e. 4096 bytes). + * 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 */ -#endif /* - * 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 @@ -110,359 +82,782 @@ #include <vm/vm.h> #include <vm/vm_kern.h> #include <vm/vm_page.h> +#include <vm/vm_pageout.h> #include <machine/cpu.h> +#include <machine/alpha_cpu.h> + + +#define VM_OBJECT_NULL NULL +#define VM_PAGE_NULL NULL +#define BYTE_SIZE NBBY +#define page_size PAGE_SIZE +#define ALPHA_PTE_GLOBAL ALPHA_PTE_ASM +#define MACRO_BEGIN do { +#define MACRO_END } while (0) +#define K2SEG_BASE ALPHA_K1SEG_BASE +#define integer_t long +#define spl_t int +#define vm_page_fictitious_addr 0 +#define aligned_block_copy(src, dest, size) bcopy((void *)src, (void *)dest, size) +#define db_printf printf +#define tbia ALPHA_TBIA +#define alphacache_Iflush alpha_pal_imb +#define cpu_number() 0 +#define check_simple_locks() +#define K0SEG_TO_PHYS ALPHA_K0SEG_TO_PHYS +#define ISA_K0SEG(v) (v >= ALPHA_K0SEG_BASE && v <= ALPHA_K0SEG_END) +#ifndef assert +#define assert(x) +#endif + +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 mem_size; /* memory size in bytes */ +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) */ -#ifdef PMAPSTATS -struct { - int collectscans; - int collectpages; - int kpttotal; - int kptinuse; - int kptmaxuse; -} kpt_stats; -struct { - int kernel; /* entering kernel mapping */ - int user; /* entering user mapping */ - int ptpneeded; /* needed to allocate a PT page */ - int nochange; /* no change at all */ - int pwchange; /* no mapping change, just wiring or protection */ - int wchange; /* no mapping change, just wiring */ - int pchange; /* no mapping change, just protection */ - int mchange; /* was mapped but mapping to different page */ - int managed; /* a managed page */ - int firstpv; /* first mapping for this PA */ - int secondpv; /* second mapping for this PA */ - int ci; /* cache inhibited */ - int unmanaged; /* not a managed page */ - int flushes; /* cache flushes */ -} enter_stats; -struct { - int calls; - int removes; - int pvfirst; - int pvsearch; - int ptinvalid; - int uflushes; - int sflushes; -} remove_stats; -struct { - int calls; - int changed; - int alreadyro; - int alreadyrw; -} protect_stats; -struct chgstats { - int setcalls; - int sethits; - int setmiss; - int clrcalls; - int clrhits; - int clrmiss; -} changebit_stats[16]; -#endif +/* XXX */ +struct pv_entry *pmap_alloc_pv __P((void)); +void pmap_free_pv __P((struct pv_entry *pv)); +vm_page_t vm_page_grab __P((void)); + +vm_offset_t pmap_resident_extract __P((pmap_t, vm_offset_t)); + +/* For external use... */ +vm_offset_t kvtophys(vm_offset_t virt) +{ + + return pmap_resident_extract(kernel_pmap, virt); +} + +/* ..but for internal use... */ +#define phystokv(a) ALPHA_PHYS_TO_K0SEG(a) +#define kvtophys(p) ALPHA_K0SEG_TO_PHYS((vm_offset_t)p) + + +/* + * Private data structures. + */ +/* + * Map from MI protection codes to MD codes. + * Assume that there are three MI protection codes, all using low bits. + */ +pt_entry_t user_protection_codes[8]; +pt_entry_t kernel_protection_codes[8]; + +alpha_protection_init() +{ + register pt_entry_t *kp, *up, prot; + + kp = kernel_protection_codes; + up = user_protection_codes; + for (prot = 0; prot < 8; prot++) { + switch (prot) { + case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE: + *kp++ = 0; + *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++ = ALPHA_PTE_KR; + *up++ = ALPHA_PTE_UR|ALPHA_PTE_KR; + break; + case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE: + *kp++ = ALPHA_PTE_KW; + *up++ = ALPHA_PTE_UW|ALPHA_PTE_KW; + 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++ = ALPHA_PTE_KW|ALPHA_PTE_KR; + *up++ = ALPHA_PTE_UW|ALPHA_PTE_UR|ALPHA_PTE_KW|ALPHA_PTE_KR; + break; + } + } +} + +/* + * Given a map and a machine independent protection code, + * convert to a alpha protection code. + */ + +#define alpha_protection(map, prot) \ + (((map) == kernel_pmap) ? kernel_protection_codes[prot] : \ + user_protection_codes[prot]) + +/* Build the typical kernel pte */ +#define pte_ktemplate(t,pa,pr) \ +MACRO_BEGIN \ + (t) = pa_to_pte(pa) | ALPHA_PTE_VALID | ALPHA_PTE_GLOBAL | \ + (alpha_protection(kernel_pmap,pr)); \ +MACRO_END + +/* build the typical pte */ +#define pte_template(m,t,pa,pr) \ +MACRO_BEGIN \ + (t) = pa_to_pte(pa) | ALPHA_PTE_VALID | \ + (alpha_protection(m,pr)); \ +MACRO_END + +/* + * 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 the pv_table. + */ + +typedef struct pv_entry { + struct pv_entry *next; /* next pv_entry */ + pmap_t pmap; /* pmap where mapping lies */ + vm_offset_t va; /* virtual address for mapping */ +} *pv_entry_t; + +#define PV_ENTRY_NULL ((pv_entry_t) 0) + +pv_entry_t pv_head_table; /* array of entries, one per page */ + +/* + * pv_list entries are kept on a list that can only be accessed + * with the pmap system locked (at SPLVM, not in the cpus_active set). + * The list is refilled from the pv_list_zone if it becomes empty. + */ +pv_entry_t pv_free_list; /* free list at SPLVM */ +decl_simple_lock_data(, pv_free_list_lock) + +#define PV_ALLOC(pv_e) { \ + simple_lock(&pv_free_list_lock); \ + if ((pv_e = pv_free_list) != 0) { \ + pv_free_list = pv_e->next; \ + } \ + simple_unlock(&pv_free_list_lock); \ +} + +#define PV_FREE(pv_e) { \ + simple_lock(&pv_free_list_lock); \ + pv_e->next = pv_free_list; \ + pv_free_list = pv_e; \ + simple_unlock(&pv_free_list_lock); \ +} -#ifdef DEBUG -#define PDB_FOLLOW 0x0001 -#define PDB_INIT 0x0002 -#define PDB_ENTER 0x0004 -#define PDB_REMOVE 0x0008 -#define PDB_CREATE 0x0010 -#define PDB_PTPAGE 0x0020 -#define PDB_CACHE 0x0040 -#define PDB_BITS 0x0080 -#define PDB_COLLECT 0x0100 -#define PDB_PROTECT 0x0200 -#define PDB_SEGTAB 0x0400 -#define PDB_MULTIMAP 0x0800 -#define PDB_BOOTSTRAP 0x1000 -#define PDB_PARANOIA 0x2000 -#define PDB_WIRING 0x4000 -#define PDB_PVDUMP 0x8000 - -int debugmap = 0; -int pmapdebug = PDB_PARANOIA; -extern vm_offset_t pager_sva, pager_eva; +#if 0 +zone_t pv_list_zone; /* zone of pv_entry structures */ #endif /* - * Get STEs and PTEs for user/kernel address space + * Each entry in the pv_head_table is locked by a bit in the + * pv_lock_table. The lock bits are accessed by the physical + * address of the page they lock. */ -#define pmap_ste(m, v) (&((m)->pm_stab[vatoste((vm_offset_t)(v))])) -#define pmap_ste_v(m, v) (*pmap_ste(m, v) & PG_V) -#define pmap_pte(m, v) \ - (&((m)->pm_ptab[NPTEPG * vatoste((vm_offset_t)(v)) + \ - vatopte((vm_offset_t)(v))])) -#define pmap_pte_pa(pte) (PG_PFNUM(*(pte)) << PGSHIFT) -#define pmap_pte_prot(pte) (*(pte) & PG_PROT) -#define pmap_pte_w(pte) (*(pte) & PG_WIRED) -#define pmap_pte_v(pte) (*(pte) & PG_V) +char *pv_lock_table; /* pointer to array of bits */ +#define pv_lock_table_size(n) (((n)+BYTE_SIZE-1)/BYTE_SIZE) + +/* + * First and last physical addresses that we maintain any information + * for. Initialized to zero so that pmap operations done before + * pmap_init won't touch any non-existent structures. + */ +vm_offset_t vm_first_phys = (vm_offset_t) 0; +vm_offset_t vm_last_phys = (vm_offset_t) 0; +boolean_t pmap_initialized = FALSE;/* Has pmap_init completed? */ -#define pmap_pte_set_w(pte, v) \ - if (v) *(u_long *)(pte) |= PG_WIRED; else *(u_long *)(pte) &= ~PG_WIRED -#define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte)) +/* + * Index into pv_head table, its lock bits, and the modify/reference + * bits starting at vm_first_phys. + */ -#define pmap_pte_set_prot(pte, np) { *(pte) &= ~PG_PROT ; *(pte) |= (np); } -#define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte)) - +#define pa_index(pa) (atop(pa - vm_first_phys)) + +#define pai_to_pvh(pai) (&pv_head_table[pai]) +#define lock_pvh_pai(pai) (bit_lock(pai, pv_lock_table)) +#define unlock_pvh_pai(pai) (bit_unlock(pai, pv_lock_table)) /* - * Given a map and a machine independent protection code, - * convert to an hp300 protection code. + * Array of physical page attributes for managed pages. + * One byte per physical page. */ -#define pte_prot(m, p) (protection_codes[m == pmap_kernel() ? 0 : 1][p]) -int protection_codes[2][8]; +char *pmap_phys_attributes; /* - * Kernel page table page management. + * Physical page attributes. Copy bits from PTE. + */ +#define PHYS_MODIFIED (ALPHA_PTE_MOD>>16) /* page modified */ +#define PHYS_REFERENCED (ALPHA_PTE_REF>>16) /* page referenced */ + +#define pte_get_attributes(p) ((*p & (ALPHA_PTE_MOD|ALPHA_PTE_REF)) >> 16) + +/* + * Amount of virtual memory mapped by one + * page-directory entry. + */ +#define PDE_MAPPED_SIZE (pdetova(1)) +#define PDE2_MAPPED_SIZE (pde2tova(1)) +#define PDE3_MAPPED_SIZE (pde3tova(1)) + +/* + * We allocate page table pages directly from the VM system + * through this object. It maps physical memory. + */ +vm_object_t pmap_object = VM_OBJECT_NULL; + +/* + * Locking and TLB invalidation + */ + +/* + * Locking Protocols: + * + * There are two structures in the pmap module that need locking: + * the pmaps themselves, and the per-page pv_lists (which are locked + * by locking the pv_lock_table entry that corresponds to the pv_head + * for the list in question.) Most routines want to lock a pmap and + * then do operations in it that require pv_list locking -- however + * pmap_remove_all and pmap_copy_on_write operate on a physical page + * basis and want to do the locking in the reverse order, i.e. lock + * a pv_list and then go through all the pmaps referenced by that list. + * To protect against deadlock between these two cases, the pmap_lock + * is used. There are three different locking protocols as a result: + * + * 1. pmap operations only (pmap_extract, pmap_access, ...) Lock only + * the pmap. + * + * 2. pmap-based operations (pmap_enter, pmap_remove, ...) Get a read + * lock on the pmap_lock (shared read), then lock the pmap + * and finally the pv_lists as needed [i.e. pmap lock before + * pv_list lock.] + * + * 3. pv_list-based operations (pmap_remove_all, pmap_copy_on_write, ...) + * Get a write lock on the pmap_lock (exclusive write); this + * also guaranteees exclusive access to the pv_lists. Lock the + * pmaps as needed. + * + * At no time may any routine hold more than one pmap lock or more than + * one pv_list lock. Because interrupt level routines can allocate + * mbufs and cause pmap_enter's, the pmap_lock and the lock on the + * kernel_pmap can only be held at splvm. + */ + +#if NCPUS > 1 +/* + * We raise the interrupt level to splvm, to block interprocessor + * interrupts during pmap operations. We must take the CPU out of + * the cpus_active set while interrupts are blocked. + */ +#define SPLVM(spl) { \ + spl = splvm(); \ + i_bit_clear(cpu_number(), &cpus_active); \ +} + +#define SPLX(spl) { \ + i_bit_set(cpu_number(), &cpus_active); \ + splx(spl); \ +} + +/* + * Lock on pmap system + */ +lock_data_t pmap_system_lock; + +volatile boolean_t cpu_update_needed[NCPUS]; + +#define PMAP_READ_LOCK(pmap, spl) { \ + SPLVM(spl); \ + lock_read(&pmap_system_lock); \ + simple_lock(&(pmap)->lock); \ +} + +#define PMAP_WRITE_LOCK(spl) { \ + SPLVM(spl); \ + lock_write(&pmap_system_lock); \ +} + +#define PMAP_READ_UNLOCK(pmap, spl) { \ + simple_unlock(&(pmap)->lock); \ + lock_read_done(&pmap_system_lock); \ + SPLX(spl); \ +} + +#define PMAP_WRITE_UNLOCK(spl) { \ + lock_write_done(&pmap_system_lock); \ + SPLX(spl); \ +} + +#define PMAP_WRITE_TO_READ_LOCK(pmap) { \ + simple_lock(&(pmap)->lock); \ + lock_write_to_read(&pmap_system_lock); \ +} + +#define LOCK_PVH(index) (lock_pvh_pai(index)) + +#define UNLOCK_PVH(index) (unlock_pvh_pai(index)) + +#define PMAP_UPDATE_TLBS(pmap, s, e) \ +{ \ + cpu_set cpu_mask = 1 << cpu_number(); \ + cpu_set users; \ + \ + /* Since the pmap is locked, other updates are locked */ \ + /* out, and any pmap_activate has finished. */ \ + \ + /* find other cpus using the pmap */ \ + users = (pmap)->cpus_using & ~cpu_mask; \ + if (users) { \ + /* signal them, and wait for them to finish */ \ + /* using the pmap */ \ + signal_cpus(users, (pmap), (s), (e)); \ + while ((pmap)->cpus_using & cpus_active & ~cpu_mask) \ + continue; \ + } \ + \ + /* invalidate our own TLB if pmap is in use */ \ + if ((pmap)->cpus_using & cpu_mask) { \ + INVALIDATE_TLB((s), (e)); \ + } \ +} + +#else NCPUS > 1 + +#define SPLVM(spl) +#define SPLX(spl) + +#define PMAP_READ_LOCK(pmap, spl) SPLVM(spl) +#define PMAP_WRITE_LOCK(spl) SPLVM(spl) +#define PMAP_READ_UNLOCK(pmap, spl) SPLX(spl) +#define PMAP_WRITE_UNLOCK(spl) SPLX(spl) +#define PMAP_WRITE_TO_READ_LOCK(pmap) + +#define LOCK_PVH(index) +#define UNLOCK_PVH(index) + +#if 0 /*fix bug later */ +#define PMAP_UPDATE_TLBS(pmap, s, e) { \ + /* invalidate our own TLB if pmap is in use */ \ + if ((pmap)->cpus_using) { \ + INVALIDATE_TLB((s), (e)); \ + } \ +} +#else +#define PMAP_UPDATE_TLBS(pmap, s, e) { \ + INVALIDATE_TLB((s), (e)); \ +} +#endif + +#endif /* NCPUS > 1 */ + +#if 0 +#define INVALIDATE_TLB(s, e) { \ + register vm_offset_t v = s, ve = e; \ + while (v < ve) { \ + tbis(v); v += ALPHA_PGBYTES; \ + } \ +} +#else +#define INVALIDATE_TLB(s, e) { \ + tbia(); \ +} +#endif + + +#if NCPUS > 1 + +void pmap_update_interrupt(); + +/* + * Structures to keep track of pending TLB invalidations */ -struct kpt_page { - struct kpt_page *kpt_next; /* link on either used or free list */ - vm_offset_t kpt_va; /* always valid kernel VA */ - vm_offset_t kpt_pa; /* PA of this page (for speed) */ -}; -struct kpt_page *kpt_free_list, *kpt_used_list; -struct kpt_page *kpt_pages; + +#define UPDATE_LIST_SIZE 4 + +struct pmap_update_item { + pmap_t pmap; /* pmap to invalidate */ + vm_offset_t start; /* start address to invalidate */ + vm_offset_t end; /* end address to invalidate */ +} ; + +typedef struct pmap_update_item *pmap_update_item_t; /* - * The Alpha's level-1 page table. + * List of pmap updates. If the list overflows, + * the last entry is changed to invalidate all. */ -pt_entry_t *Lev1map; +struct pmap_update_list { + decl_simple_lock_data(, lock) + int count; + struct pmap_update_item item[UPDATE_LIST_SIZE]; +} ; +typedef struct pmap_update_list *pmap_update_list_t; + +struct pmap_update_list cpu_update_list[NCPUS]; + +#endif /* NCPUS > 1 */ /* - * Kernel segment/page table and page table map. - * The page table map gives us a level of indirection we need to dynamically - * expand the page table. It is essentially a copy of the segment table - * with PTEs instead of STEs. All are initialized in locore at boot time. - * Segtabzero is an empty segment table which all processes share til they - * reference something. + * Other useful macros. */ -pt_entry_t *Sysptmap; -pt_entry_t *Sysmap; -vm_size_t Sysptmapsize, Sysmapsize; -pt_entry_t *Segtabzero, Segtabzeropte; +#define current_pmap() (vm_map_pmap(current_thread()->task->map)) +#define pmap_in_use(pmap, cpu) (((pmap)->cpus_using & (1 << (cpu))) != 0) struct pmap kernel_pmap_store; -vm_map_t st_map, pt_map; +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_size_t mem_size; /* memory size in bytes */ -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) */ -vm_offset_t vm_first_phys; /* PA of first managed page */ -vm_offset_t vm_last_phys; /* PA just past last managed page */ -boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */ -char *pmap_attributes; /* reference and modify bits */ +struct zone *pmap_zone; /* zone of pmap structures */ + +int pmap_debug = 0; /* flag for debugging prints */ +int ptes_per_vm_page; /* number of hardware ptes needed + to map one VM page. */ +unsigned int inuse_ptepages_count = 0; /* debugging */ +extern char end; /* - * Internal routines + * Page directory for kernel. */ -void alpha_protection_init __P((void)); -void pmap_remove_mapping __P((pmap_t, vm_offset_t, pt_entry_t *, int)); -void pmap_changebit __P((vm_offset_t, u_long, boolean_t)); -void pmap_enter_ptpage __P((pmap_t, vm_offset_t)); -#ifdef DEBUG -void pmap_pvdump __P((vm_offset_t)); -void pmap_check_wiring __P((char *, vm_offset_t)); +pt_entry_t *root_kpdes; + +void pmap_remove_range(); /* forward */ +#if NCPUS > 1 +void signal_cpus(); /* forward */ +#endif /* NCPUS > 1 */ + +int pmap_max_asn; +void pmap_expand __P((pmap_t, vm_offset_t)); + +/* XXX */ +#define PDB_BOOTSTRAP 0x00000001 +#define PDB_BOOTSTRAP_ALLOC 0x00000002 +#define PDB_UNMAP_PROM 0x00000004 +#define PDB_ACTIVATE 0x00000008 +#define PDB_DEACTIVATE 0x00000010 +#define PDB_TLBPID_INIT 0x00000020 +#define PDB_TLBPID_ASSIGN 0x00000040 +#define PDB_TLBPID_DESTROY 0x00000080 +#define PDB_ENTER 0x00000100 +#define PDB_CREATE 0x00000200 +#define PDB_PINIT 0x00000400 +#define PDB_EXPAND 0x00000800 +#define PDB_EXTRACT 0x00001000 +#define PDB_PTE 0x00002000 +#define PDB_RELEASE 0x00004000 +#define PDB_DESTROY 0x00008000 +#define PDB_COPY_PAGE 0x00010000 +#define PDB_ZERO_PAGE 0x00020000 + +#define PDB_ANOMALOUS 0x20000000 +#define PDB_FOLLOW 0x40000000 +#define PDB_VERBOSE 0x80000000 + +int pmapdebug = PDB_ANOMALOUS |-1 /* -1 */; + +#if defined(DEBUG) || 1 +#define DOPDB(x) ((pmapdebug & (x)) != 0) +#else +#define DOPDB(x) 0 #endif +#define DOVPDB(x) (DOPDB(x) && DOPDB(PDB_VERBOSE)) + +/* + * Given an offset and a map, compute the address of the + * pte. If the address is invalid with respect to the map + * then PT_ENTRY_NULL is returned (and the map may need to grow). + * + * This is only used internally. + */ +#define pmap_pde(pmap, addr) (&(pmap)->dirbase[pdenum(addr)]) + +pt_entry_t *pmap_pte(pmap, addr) + register pmap_t pmap; + register vm_offset_t addr; +{ + register pt_entry_t *ptp, *ptep; + register pt_entry_t pte; + + if (DOPDB(PDB_FOLLOW|PDB_PTE)) + printf("pmap_pte(%p, 0x%lx)\n", pmap, addr); + + if (pmap->dirbase == 0) { + if (DOVPDB(PDB_FOLLOW|PDB_PTE)) + printf("pmap_pte: dirbase == 0\n"); + ptep = PT_ENTRY_NULL; + goto out; + } + + /* seg1 */ + pte = *pmap_pde(pmap,addr); + if ((pte & ALPHA_PTE_VALID) == 0) { + if (DOVPDB(PDB_FOLLOW|PDB_PTE)) + printf("pmap_pte: l1 not valid\n"); + ptep = PT_ENTRY_NULL; + goto out; + } + + /* seg2 */ + ptp = (pt_entry_t *)ptetokv(pte); + pte = ptp[pte2num(addr)]; + if ((pte & ALPHA_PTE_VALID) == 0) { + if (DOVPDB(PDB_FOLLOW|PDB_PTE)) + printf("pmap_pte: l2 not valid\n"); + ptep = PT_ENTRY_NULL; + goto out; + } + + /* seg3 */ + ptp = (pt_entry_t *)ptetokv(pte); + ptep = &ptp[pte3num(addr)]; + +out: + if (DOPDB(PDB_FOLLOW|PDB_PTE)) + printf("pmap_pte: returns %p\n", ptep); + return (ptep); +} -#define PAGE_IS_MANAGED(pa) ((pa) >= vm_first_phys && (pa) < vm_last_phys) +#define DEBUG_PTE_PAGE 1 -/* pmap_remove_mapping flags */ -#define PRM_TFLUSH 1 -#define PRM_CFLUSH 2 +extern vm_offset_t virtual_avail, virtual_end; +extern vm_offset_t avail_start, avail_end; /* - * pmap_bootstrap: - * Bootstrap the system to run with virtual memory. - * firstaddr is the first unused kseg0 address (not page aligned). + * Bootstrap the system enough to run with virtual memory. + * Map the kernel's code and data, and allocate the system page table. + * Called with mapping OFF. Page_size must already be set. + * + * Parameters: + * avail_start PA of first available physical page + * avail_end PA of last available physical page + * virtual_avail VA of first available page + * virtual_end VA of last available page + * */ +vm_size_t pmap_kernel_vm = 5; /* each one 8 meg worth */ + +unsigned int +pmap_free_pages() +{ + return atop(avail_end - avail_start); +} + void -pmap_bootstrap(firstaddr, ptaddr) - vm_offset_t firstaddr; - vm_offset_t ptaddr; +pmap_bootstrap(firstaddr, ptaddr, maxasn) + vm_offset_t firstaddr, ptaddr; + int maxasn; { - register int i; + vm_offset_t pa; + pt_entry_t template; + pt_entry_t *pde, *pte; vm_offset_t start; - pt_entry_t pte; - extern int firstusablepage, lastusablepage; + extern int firstusablepage, lastusablepage; + int i; + long npages; -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_BOOTSTRAP)) - printf("pmap_bootstrap(0x%lx, 0x%lx)\n", firstaddr, ptaddr); -#endif + if (DOPDB(PDB_FOLLOW|PDB_BOOTSTRAP)) + printf("pmap_bootstrap(0x%lx, 0x%lx, %d)\n", firstaddr, ptaddr, + maxasn); /* must be page aligned */ start = firstaddr = alpha_round_page(firstaddr); -#define valloc(name, type, num) \ - (name) = (type *)firstaddr; \ +#define valloc(name, type, num) \ + (name) = (type *)firstaddr; \ firstaddr = ALIGN((vm_offset_t)((name)+(num))) +#define vallocsz(name, cast, size) \ + (name) = (cast)firstaddr; \ + firstaddr = ALIGN(firstaddr + size) /* - * Allocate an empty prototype segment map for processes. - * This will be used until processes get their own. + * Initialize protection array. */ - valloc(Segtabzero, pt_entry_t, NPTEPG); - Segtabzeropte = (k0segtophys(Segtabzero) >> PGSHIFT) << PG_SHIFT; - Segtabzeropte |= PG_V | PG_KRE | PG_KWE | PG_WIRED; + alpha_protection_init(); /* - * Figure out how many PTE's are necessary to map the kernel. - * The '512' comes from PAGER_MAP_SIZE in vm_pager_init(). - * This should be kept in sync. - * We also reserve space for kmem_alloc_pageable() for vm_fork(). + * Set ptes_per_vm_page for general use. */ - Sysmapsize = (VM_KMEM_SIZE + VM_MBUF_SIZE + VM_PHYS_SIZE + - nbuf * MAXBSIZE + 16 * NCARGS) / NBPG + 512 + 256; - Sysmapsize += maxproc * (btoc(ALPHA_STSIZE) + btoc(ALPHA_MAX_PTSIZE)); - -#ifdef SYSVSHM - Sysmapsize += shminfo.shmall; -#endif - Sysmapsize = roundup(Sysmapsize, NPTEPG); + ptes_per_vm_page = page_size / ALPHA_PGBYTES; /* - * Allocate a level 1 PTE table for the kernel. - * This is always one page long. - * IF THIS IS NOT A MULTIPLE OF NBPG, ALL WILL GO TO HELL. + * 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. */ - valloc(Lev1map, pt_entry_t, NPTEPG); + + kernel_pmap = &kernel_pmap_store; + +#if NCPUS > 1 + lock_init(&pmap_system_lock, FALSE); /* NOT a sleep lock */ +#endif /* NCPUS > 1 */ + + simple_lock_init(&kernel_pmap->lock); + + kernel_pmap->ref_count = 1; /* - * Allocate a level 2 PTE table for the kernel. - * These must map all of the level3 PTEs. - * IF THIS IS NOT A MULTIPLE OF NBPG, ALL WILL GO TO HELL. + * Allocate the kernel page directory, and put its + * virtual address in root_kpdes. + * + * No other physical memory has been allocated. */ - Sysptmapsize = roundup(howmany(Sysmapsize, NPTEPG), NPTEPG); - valloc(Sysptmap, pt_entry_t, Sysptmapsize); - pmap_kernel()->pm_stab = Sysptmap; + + vallocsz(root_kpdes, pt_entry_t *, PAGE_SIZE); + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: root_kpdes = %p\n", root_kpdes); + kernel_pmap->dirbase = root_kpdes; + kernel_pmap->dirpfn = alpha_btop(kvtophys((vm_offset_t)root_kpdes)); + + /* First, copy mappings for things below VM_MIN_KERNEL_ADDRESS */ + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: setting up root_kpdes (copy 0x%lx)\n", + pdenum(VM_MIN_KERNEL_ADDRESS) * sizeof root_kpdes[0]); + bzero(root_kpdes, PAGE_SIZE); + bcopy((caddr_t)ptaddr, root_kpdes, + pdenum(VM_MIN_KERNEL_ADDRESS) * sizeof root_kpdes[0]); /* - * Allocate a level 3 PTE table for the kernel. - * Contains Sysmapsize PTEs. + * Set up the virtual page table. */ - valloc(Sysmap, pt_entry_t, Sysmapsize); - pmap_kernel()->pm_ptab = Sysmap; + pte_ktemplate(template, kvtophys(root_kpdes), + VM_PROT_READ | VM_PROT_WRITE); + template &= ~ALPHA_PTE_GLOBAL; + root_kpdes[pdenum(VPTBASE)] = template; + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: VPT PTE 0x%lx at 0x%lx)\n", + root_kpdes[pdenum(VPTBASE)], &root_kpdes[pdenum(VPTBASE)]); +#if 0 /* - * Allocate memory for page attributes. - * allocates a few more entries than we need, but that's safe. + * Rid of console's default mappings */ - valloc(pmap_attributes, char, 1 + lastusablepage - firstusablepage); + for (pde = pmap_pde(kernel_pmap,0); + pde < pmap_pde(kernel_pmap,VM_MIN_KERNEL_ADDRESS);) + *pde++ = 0; +#endif /* - * Allocate memory for pv_table. - * This will allocate more entries than we really need. - * We could do this in pmap_init when we know the actual - * phys_start and phys_end but its better to use kseg0 addresses - * rather than kernel virtual addresses mapped through the TLB. + * Allocate the seg2 kernel page table entries from the front + * of available physical memory. Take enough to cover all of + * the K2SEG range. But of course one page is enough for 8Gb, + * and more in future chips ... */ - i = 1 + lastusablepage - alpha_btop(k0segtophys(firstaddr)); - valloc(pv_table, struct pv_entry, i); +#define enough_kseg2() (PAGE_SIZE) + + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: allocating kvseg segment pages\n"); + vallocsz(pte, pt_entry_t *, enough_kseg2()); /* virtual */ + pa = kvtophys(pte); /* physical */ + bzero(pte, enough_kseg2()); + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: kvseg segment pages at %p\n", pte); + +#undef enough_kseg2 /* - * Clear allocated memory. + * Make a note of it in the seg1 table */ - firstaddr = alpha_round_page(firstaddr); - bzero((caddr_t)start, firstaddr - start); + + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: inserting segment pages into root\n"); + tbia(); + pte_ktemplate(template,pa,VM_PROT_READ|VM_PROT_WRITE); + pde = pmap_pde(kernel_pmap,K2SEG_BASE); + i = ptes_per_vm_page; + do { + *pde++ = template; + pte_increment_pa(template); + i--; + } while (i > 0); /* - * Set up level 1 page table + * The kernel runs unmapped and cached (k0seg), + * only dynamic data are mapped in k1seg. + * ==> No need to map it. */ - /* First, copy mappings for things below VM_MIN_KERNEL_ADDRESS */ - bcopy((caddr_t)ptaddr, Lev1map, - kvtol1pte(VM_MIN_KERNEL_ADDRESS) * sizeof Lev1map[0]); - - /* Second, map all of the level 2 pte pages */ - for (i = 0; i < howmany(Sysptmapsize, NPTEPG); i++) { - pte = (k0segtophys(Sysptmap + (i*PAGE_SIZE)) >> PGSHIFT) - << PG_SHIFT; - pte |= PG_V | PG_ASM | PG_KRE | PG_KWE | PG_WIRED; - Lev1map[kvtol1pte(VM_MIN_KERNEL_ADDRESS + - (i*PAGE_SIZE*NPTEPG*NPTEPG))] = pte; - } - - /* Finally, map the virtual page table */ - pte = (k0segtophys(Lev1map) >> PGSHIFT) << PG_SHIFT; - pte |= PG_V | PG_KRE | PG_KWE; /* NOTE NO ASM */ - Lev1map[kvtol1pte(VPTBASE)] = pte; - /* - * Set up level 2 page table. + * But don't we need some seg2 pagetables to start with ? */ - /* Map all of the level 3 pte pages */ - for (i = 0; i < howmany(Sysmapsize, NPTEPG); i++) { - pte = (k0segtophys(((caddr_t)Sysmap)+(i*PAGE_SIZE)) >> PGSHIFT) - << PG_SHIFT; - pte |= PG_V | PG_ASM | PG_KRE | PG_KWE | PG_WIRED; - Sysptmap[vatoste(VM_MIN_KERNEL_ADDRESS+ - (i*PAGE_SIZE*NPTEPG))] = pte; + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: allocating kvseg page table pages\n"); + pde = &pte[pte2num(K2SEG_BASE)]; + for (i = pmap_kernel_vm; i > 0; i--) { + register int j; + + vallocsz(pte, pt_entry_t *, PAGE_SIZE); /* virtual */ + pa = kvtophys(pte); /* physical */ + pte_ktemplate(template,pa,VM_PROT_READ|VM_PROT_WRITE); + bzero(pte, PAGE_SIZE); + j = ptes_per_vm_page; + do { + *pde++ = template; + pte_increment_pa(template); + } while (--j > 0); } /* - * Set up level three page table (Sysmap) + * Fix up managed physical memory information. */ - /* Nothing to do; it's already zero'd */ - - avail_start = k0segtophys(firstaddr); -#if 1 + avail_start = ALPHA_K0SEG_TO_PHYS(firstaddr); avail_end = alpha_ptob(lastusablepage + 1); mem_size = avail_end - avail_start; -#else - /* XXX why not lastusablepage + 1, & not include NBPG in mem_size? */ - avail_end = alpha_ptob(lastusablepage); - mem_size = NBPG + avail_end - avail_start; -#endif -#if 0 - printf("avail_start = 0x%lx\n", avail_start); - printf("avail_end = 0x%lx\n", avail_end); - printf("mem_size = 0x%lx\n", mem_size); -#endif + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: avail: 0x%lx -> 0x%lx (0x%lx)\n", + avail_start, avail_end, mem_size); + + /* + * Allocate memory for the pv_head_table and its + * lock bits, and the reference/modify byte array. + */ + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: allocating page management data\n"); + + npages = ((BYTE_SIZE * mem_size) / + (BYTE_SIZE * (PAGE_SIZE + sizeof (struct pv_entry) + 1) + 1)); + + valloc(pv_head_table, struct pv_entry, npages); + bzero(pv_head_table, sizeof (struct pv_entry) * npages); - virtual_avail = VM_MIN_KERNEL_ADDRESS; - virtual_end = VM_MIN_KERNEL_ADDRESS + Sysmapsize * NBPG; + valloc(pv_lock_table, char, pv_lock_table_size(npages)); + bzero(pv_lock_table, pv_lock_table_size(npages)); - simple_lock_init(&pmap_kernel()->pm_lock); - pmap_kernel()->pm_count = 1; + valloc(pmap_phys_attributes, char, npages); + bzero(pmap_phys_attributes, sizeof (char) * npages); + + avail_start = alpha_round_page(ALPHA_K0SEG_TO_PHYS(firstaddr)); + if (npages > pmap_free_pages()) + panic("pmap_bootstrap"); + mem_size = avail_end - avail_start; + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: avail: 0x%lx -> 0x%lx (0x%lx)\n", + avail_start, avail_end, mem_size); /* - * Set up curproc's (i.e. proc 0's) PCB such that the ptbr - * points to the right place. + * Assert kernel limits (because of pmap_expand). */ - curproc->p_addr->u_pcb.pcb_ptbr = k0segtophys(Lev1map) >> PGSHIFT; -} -/* - * Unmap the PROM mappings. PROM mappings are kept around - * by pmap_bootstrap, so we can still use the prom's printf. - * Basically, blow away all mappings in the level one PTE - * table below VM_MIN_KERNEL_ADDRESS. The Virtual Page Table - * Is at the end of virtual space, so it's safe. - */ -void -pmap_unmap_prom() -{ - int i; - extern int prom_mapped; - extern pt_entry_t *rom_ptep, rom_pte; + virtual_avail = alpha_round_page(K2SEG_BASE); + virtual_end = trunc_page(K2SEG_BASE + pde2tova(pmap_kernel_vm)); + if (DOVPDB(PDB_BOOTSTRAP)) { + printf("pmap_bootstrap: virtual_avail = %p\n", virtual_avail); + printf("pmap_bootstrap: virtual_end = %p\n", virtual_end); + } -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_BOOTSTRAP)) - printf("pmap_unmap_prom\n"); -#endif + /* + * The distinguished tlbpid value of 0 is reserved for + * the kernel pmap. Initialize the tlbpid allocator, + * who knows about this. + */ + kernel_pmap->pid = 0; + pmap_tlbpid_init(maxasn); - /* XXX save old pte so that we can remap prom if necessary */ - rom_ptep = &Lev1map[0]; /* XXX */ - rom_pte = *rom_ptep & ~PG_ASM; /* XXX */ + if (DOVPDB(PDB_BOOTSTRAP)) + printf("pmap_bootstrap: leaving\n"); +} - /* Mark all mappings before VM_MIN_KERNEL_ADDRESS as invalid. */ - bzero(Lev1map, kvtol1pte(VM_MIN_KERNEL_ADDRESS) * sizeof Lev1map[0]); - prom_mapped = 0; - TBIA(); +pmap_rid_of_console() +{ + pt_entry_t *pde; + /* + * Rid of console's default mappings + */ + for (pde = pmap_pde(kernel_pmap,0L); + pde < pmap_pde(kernel_pmap,VM_MIN_KERNEL_ADDRESS);) + *pde++ = 0; } /* @@ -470,13 +865,14 @@ pmap_unmap_prom() * memory allocation until the virtual memory system has been bootstrapped. * After that point, either kmem_alloc or malloc should be used. This * function works by stealing pages from the (to be) managed page pool, - * stealing virtual address space, then implicitly mapping the pages - * (by using their k0seg addresses) and zeroing them. + * implicitly mapping them (by using their k0seg addresses), + * and zeroing them. * * It should be used from pmap_bootstrap till vm_page_startup, afterwards * it cannot be used, and will generate a panic if tried. Note that this * memory will never be freed, and in essence it is wired down. */ + void * pmap_bootstrap_alloc(size) int size; @@ -484,22 +880,58 @@ pmap_bootstrap_alloc(size) vm_offset_t val; extern boolean_t vm_page_startup_initialized; -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_BOOTSTRAP)) + if (DOPDB(PDB_FOLLOW|PDB_BOOTSTRAP_ALLOC)) printf("pmap_bootstrap_alloc(%lx)\n", size); -#endif if (vm_page_startup_initialized) panic("pmap_bootstrap_alloc: called after startup initialized"); - val = phystok0seg(avail_start); - size = round_page(size); + val = ALPHA_PHYS_TO_K0SEG(avail_start); + size = alpha_round_page(size); avail_start += size; + if (avail_start > avail_end) /* sanity */ + panic("pmap_bootstrap_alloc"); bzero((caddr_t)val, size); + + if (DOVPDB(PDB_BOOTSTRAP_ALLOC)) + printf("pmap_bootstrap_alloc: returns %p\n", val); return ((void *)val); } /* + * Unmap the PROM mappings. PROM mappings are kept around + * by pmap_bootstrap, so we can still use the prom's printf. + * Basically, blow away all mappings in the level one PTE + * table below VM_MIN_KERNEL_ADDRESS. The Virtual Page Table + * Is at the end of virtual space, so it's safe. + */ +void +pmap_unmap_prom() +{ + int i; + extern int prom_mapped; + extern pt_entry_t *rom_ptep, rom_pte; + + if (DOPDB(PDB_FOLLOW|PDB_UNMAP_PROM)) + printf("pmap_unmap_prom\n"); + + /* XXX save old pte so that we can remap prom if necessary */ + rom_ptep = &root_kpdes[0]; /* XXX */ + rom_pte = *rom_ptep & ~ALPHA_PTE_ASM; /* XXX */ + + if (DOVPDB(PDB_UNMAP_PROM)) + printf("pmap_unmap_prom: zero 0x%lx, rom_pte was 0x%lx\n", + pdenum(VM_MIN_KERNEL_ADDRESS) * sizeof root_kpdes[0], + rom_pte); + /* Mark all mappings before VM_MIN_KERNEL_ADDRESS as invalid. */ + bzero(root_kpdes, pdenum(VM_MIN_KERNEL_ADDRESS) * sizeof root_kpdes[0]); + prom_mapped = 0; + ALPHA_TBIA(); + if (DOVPDB(PDB_UNMAP_PROM)) + printf("pmap_unmap_prom: leaving\n"); +} + +/* * Initialize the pmap module. * Called by vm_init, to initialize any structures that the pmap * system needs to map virtual memory. @@ -508,65 +940,121 @@ void pmap_init(phys_start, phys_end) vm_offset_t phys_start, phys_end; { - vm_offset_t addr, addr2; - vm_size_t s; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_init(%x, %x)\n", phys_start, phys_end); -#endif - - /* initialize protection array */ - alpha_protection_init(); + vm_size_t s; + int i; /* - * Allocate the segment table map + * Create the zone of physical maps, + * and of the physical-to-virtual entries. */ - s = maxproc * ALPHA_STSIZE; - st_map = kmem_suballoc(kernel_map, &addr, &addr2, s, TRUE); +#if 0 + s = (vm_size_t) sizeof(struct pmap); + pmap_zone = zinit(s, 400*s, 4096, FALSE, "pmap"); /* XXX */ + s = (vm_size_t) sizeof(struct pv_entry); + pv_list_zone = zinit(s, 10000*s, 4096, FALSE, "pv_list"); /* XXX */ +#endif +#if NCPUS > 1 /* - * Allocate the page table map + * Set up the pmap request lists */ - s = maxproc * ALPHA_MAX_PTSIZE; /* XXX limit it */ - pt_map = kmem_suballoc(kernel_map, &addr, &addr2, s, TRUE); - + for (i = 0; i < NCPUS; i++) { + pmap_update_list_t up = &cpu_update_list[i]; + + simple_lock_init(&up->lock); + up->count = 0; + } + + alpha_set_scb_entry( SCB_INTERPROC, pmap_update_interrupt); + +#endif /* NCPUS > 1 */ + /* - * Now it is safe to enable pv_table recording. + * Only now, when all of the data structures are allocated, + * can we set vm_first_phys and vm_last_phys. If we set them + * too soon, the kmem_alloc_wired above will try to use these + * data structures and blow up. */ + vm_first_phys = phys_start; vm_last_phys = phys_end; -#if 0 - printf("vm_first_phys = 0x%lx\n", vm_first_phys); - printf("vm_last_phys = 0x%lx\n", vm_last_phys); -#endif pmap_initialized = TRUE; } +#define pmap_valid_page(x) ((avail_start <= x) && (x < avail_end)) +#define valid_page(x) (pmap_initialized && pmap_valid_page(x)) + /* - * Used to map a range of physical addresses into kernel - * virtual address space. + * Routine: pmap_page_table_page_alloc + * + * Allocates a new physical page to be used as a page-table page. * - * For now, VM is already on, we only need to map the - * specified memory. + * Must be called with the pmap system and the pmap unlocked, + * since these must be unlocked to use vm_page_grab. */ vm_offset_t -pmap_map(virt, start, end, prot) - vm_offset_t virt; - vm_offset_t start; - vm_offset_t end; - int prot; +pmap_page_table_page_alloc() { -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_map(%lx, %lx, %lx, %lx)\n", virt, start, end, prot); -#endif - while (start < end) { - pmap_enter(pmap_kernel(), virt, start, prot, FALSE); - virt += PAGE_SIZE; - start += PAGE_SIZE; - } - return(virt); + register vm_page_t m; + register vm_offset_t pa; + + check_simple_locks(); + + /* + * We cannot allocate the pmap_object in pmap_init, + * because it is called before the zone package is up. + * Allocate it now if it is missing. + */ + if (pmap_object == VM_OBJECT_NULL) + pmap_object = vm_object_allocate(mem_size); + + /* + * Allocate a VM page + */ + while ((m = vm_page_grab()) == VM_PAGE_NULL) + vm_page_wait(); + + /* + * Map the page to its physical address so that it + * can be found later. + */ + pa = m->phys_addr; + vm_object_lock(pmap_object); + vm_page_insert(m, pmap_object, pa); + vm_page_lock_queues(); + vm_page_wire(m); + inuse_ptepages_count++; + vm_page_unlock_queues(); + vm_object_unlock(pmap_object); + + /* + * Zero the page. + */ + bzero((void *)phystokv(pa), PAGE_SIZE); + + return pa; +} + +/* + * Deallocate a page-table page. + * The page-table page must have all mappings removed, + * and be removed from its page directory. + */ +void +pmap_page_table_page_dealloc(pa) + vm_offset_t pa; +{ + vm_page_t m; + + vm_object_lock(pmap_object); + m = vm_page_lookup(pmap_object, pa); + if (m == VM_PAGE_NULL) + panic("pmap_page_table_page_dealloc: page %#X not in object", pa); + vm_page_lock_queues(); + vm_page_free(m); + inuse_ptepages_count--; + vm_page_unlock_queues(); + vm_object_unlock(pmap_object); } /* @@ -583,55 +1071,91 @@ pmap_map(virt, start, end, prot) */ pmap_t pmap_create(size) - vm_size_t size; + vm_size_t size; { - register pmap_t pmap; + register pmap_t p; + + if (DOPDB(PDB_FOLLOW|PDB_CREATE)) + printf("pmap_create(%d)\n", size); -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) - printf("pmap_create(%lx)\n", size); -#endif /* - * Software use map does not need a pmap + * A software use-only map doesn't even need a map. */ - if (size) - return(NULL); + + if (size != 0) { + p = PMAP_NULL; + goto out; + } /* XXX: is it ok to wait here? */ - pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK); -#ifdef notifwewait - if (pmap == NULL) + p = (pmap_t) malloc(sizeof *p, M_VMPMAP, M_WAITOK); + if (p == NULL) panic("pmap_create: cannot allocate a pmap"); -#endif - bzero(pmap, sizeof(*pmap)); - pmap_pinit(pmap); - return (pmap); + + bzero(p, sizeof (*p)); + pmap_pinit(p); + +out: + if (DOVPDB(PDB_FOLLOW|PDB_CREATE)) + printf("pmap_create: returning %p\n", p); + return (p); } -/* - * Initialize a preallocated and zeroed pmap structure, - * such as one in a vmspace structure. - */ void -pmap_pinit(pmap) - register struct pmap *pmap; +pmap_pinit(p) + struct pmap *p; { + register pmap_statistics_t stats; + extern struct vmspace vmspace0; + + if (DOPDB(PDB_FOLLOW|PDB_PINIT)) + printf("pmap_init(%p)\n", p); + +#if 0 + /* XXX cgd WHY NOT pmap_page_table_page_alloc()? */ + p->dirbase = (void *)kmem_alloc(kernel_map, ALPHA_PGBYTES); +#else + p->dirbase = (void *)phystokv(pmap_page_table_page_alloc()); +#endif + if (p->dirbase == NULL) + panic("pmap_create"); + p->dirpfn = alpha_btop(pmap_resident_extract(kernel_pmap, + (vm_offset_t)p->dirbase)); + + if (DOVPDB(PDB_FOLLOW|PDB_PINIT)) + printf("pmap_init(%p): dirbase = %p, dirpfn = 0x%x\n", p, + p->dirbase, p->dirpfn); + aligned_block_copy(root_kpdes, p->dirbase, ALPHA_PGBYTES); + p->ref_count = 1; + p->pid = -1; + if (DOVPDB(PDB_FOLLOW|PDB_PINIT)) + printf("pmap_init(%p): first pde = 0x%lx\n", p->dirbase[0]); + + { + pt_entry_t template; + + pte_ktemplate(template, kvtophys(p->dirbase), + VM_PROT_READ | VM_PROT_WRITE); + template &= ~ALPHA_PTE_GLOBAL; + p->dirbase[pdenum(VPTBASE)] = template; + } +printf("PMAP_PINIT: FIRST ENT = 0x%lx\n", p->dirbase[0]); + + simple_lock_init(&p->lock); + p->cpus_using = 0; + p->hacking = 0; -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) - printf("pmap_pinit(%lx)\n", pmap); -#endif /* - * No need to allocate page table space yet but we do need a - * valid segment table. Initially, we point everyone at the - * "null" segment table. On the first pmap_enter, a real - * segment table will be allocated. + * Initialize statistics. */ - pmap->pm_stab = Segtabzero; - pmap->pm_stpte = Segtabzeropte; - pmap->pm_stchanged = TRUE; - pmap->pm_count = 1; - simple_lock_init(&pmap->pm_lock); + + stats = &p->stats; + stats->resident_count = 0; + stats->wired_count = 0; + +out: + if (DOVPDB(PDB_FOLLOW|PDB_PINIT)) + printf("pmap_init: leaving\n", p); } /* @@ -639,270 +1163,550 @@ pmap_pinit(pmap) * Should only be called if the map contains * no valid mappings. */ -void -pmap_destroy(pmap) - register pmap_t pmap; + +void pmap_destroy(p) + register pmap_t p; { - int count; + register int c; + register spl_t s; -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_destroy(%lx)\n", pmap); -#endif - if (pmap == NULL) - return; + if (DOPDB(PDB_FOLLOW|PDB_DESTROY)) + printf("pmap_destroy(%p)\n", p); + + if (p == PMAP_NULL) + goto out; - simple_lock(&pmap->pm_lock); - count = --pmap->pm_count; - simple_unlock(&pmap->pm_lock); - if (count == 0) { - pmap_release(pmap); - free((caddr_t)pmap, M_VMPMAP); + SPLVM(s); + simple_lock(&p->lock); + c = --p->ref_count; + simple_unlock(&p->lock); + SPLX(s); + + if (c == 0) { + pmap_release(p); + free(p, M_VMPMAP); } +out: + if (DOVPDB(PDB_FOLLOW|PDB_DESTROY)) + printf("pmap_destroy: leaving\n"); } -/* - * 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) - register struct pmap *pmap; +pmap_release(p) + pmap_t p; { + register pt_entry_t *pdep, *ptep, *eptep; + register vm_offset_t pa; -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_release(%lx)\n", pmap); -#endif -#ifdef notdef /* DIAGNOSTIC */ - /* count would be 0 from pmap_destroy... */ - simple_lock(&pmap->pm_lock); - if (pmap->pm_count != 1) - panic("pmap_release count"); + if (DOPDB(PDB_FOLLOW|PDB_RELEASE)) + printf("pmap_release(%p)\n", p); + + if (p->dirbase == NULL) { + if (DOPDB(PDB_FOLLOW|PDB_ANOMALOUS|PDB_RELEASE)) + printf("pmap_release: already reclaimed\n"); + /* resources already reclaimed */ + goto out; + } + + /* + * Free the memory maps, then the + * pmap structure. + */ + for (pdep = p->dirbase; + pdep < pmap_pde(p,VM_MIN_KERNEL_ADDRESS); + pdep += ptes_per_vm_page) { + if (*pdep & ALPHA_PTE_VALID) { + pa = pte_to_pa(*pdep); + + ptep = (pt_entry_t *)phystokv(pa); + eptep = ptep + NPTES; + for (; ptep < eptep; ptep += ptes_per_vm_page ) { + if (*ptep & ALPHA_PTE_VALID) + pmap_page_table_page_dealloc(pte_to_pa(*ptep)); + } + pmap_page_table_page_dealloc(pa); + } + } + pmap_tlbpid_destroy(p->pid, FALSE); + +#if 0 + kmem_free(kernel_map, (vm_offset_t)p->dirbase, ALPHA_PGBYTES); +#else + pmap_page_table_page_dealloc(kvtophys(p->dirbase)); #endif - if (pmap->pm_ptab) - kmem_free_wakeup(pt_map, (vm_offset_t)pmap->pm_ptab, - ALPHA_MAX_PTSIZE); - if (pmap->pm_stab != Segtabzero) - kmem_free_wakeup(st_map, (vm_offset_t)pmap->pm_stab, - ALPHA_STSIZE); + p->dirbase = NULL; + +out: + if (DOVPDB(PDB_FOLLOW|PDB_RELEASE)) + printf("pmap_release: leaving\n"); } /* * Add a reference to the specified pmap. */ -void -pmap_reference(pmap) - pmap_t pmap; + +void pmap_reference(p) + register pmap_t p; { -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_reference(%lx)\n", pmap); -#endif - if (pmap != NULL) { - simple_lock(&pmap->pm_lock); - pmap->pm_count++; - simple_unlock(&pmap->pm_lock); + spl_t s; + if (p != PMAP_NULL) { + SPLVM(s); + simple_lock(&p->lock); + p->ref_count++; + simple_unlock(&p->lock); + SPLX(s); } } /* - * Remove the given range of addresses from the specified map. + * Remove a range of hardware page-table entries. + * The entries given are the first (inclusive) + * and last (exclusive) entries for the VM pages. + * The virtual address is the va for the first pte. * - * It is assumed that the start and end are properly - * rounded to the page size. + * The pmap must be locked. + * If the pmap is not the kernel pmap, the range must lie + * entirely within one pte-page. This is NOT checked. + * Assumes that the pte-page exists. */ -void -pmap_remove(pmap, sva, eva) - register pmap_t pmap; - register vm_offset_t sva, eva; + +/* static */ +void pmap_remove_range(pmap, va, spte, epte) + pmap_t pmap; + vm_offset_t va; + pt_entry_t *spte; + pt_entry_t *epte; { - register vm_offset_t nssva; - register pt_entry_t *pte; - boolean_t firstpage, needcflush; - int flags; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) - printf("pmap_remove(%lx, %lx, %lx)\n", pmap, sva, eva); -#endif + register pt_entry_t *cpte; + int num_removed, num_unwired; + int pai; + vm_offset_t pa; - if (pmap == NULL) - return; + num_removed = 0; + num_unwired = 0; + + for (cpte = spte; cpte < epte; + cpte += ptes_per_vm_page, va += PAGE_SIZE) { + + if (*cpte == 0) + continue; + pa = pte_to_pa(*cpte); + + num_removed++; + if (*cpte & ALPHA_PTE_WIRED) + num_unwired++; + + if (!valid_page(pa)) { -#ifdef PMAPSTATS - remove_stats.calls++; -#endif - firstpage = TRUE; - needcflush = FALSE; - flags = active_pmap(pmap) ? PRM_TFLUSH : 0; - while (sva < eva) { - nssva = alpha_trunc_seg(sva) + ALPHA_SEG_SIZE; - if (nssva == 0 || nssva > eva) - nssva = eva; /* - * If VA belongs to an unallocated segment, - * skip to the next segment boundary. + * Outside range of managed physical memory. + * Just remove the mappings. */ - if (!pmap_ste_v(pmap, sva)) { - sva = nssva; - continue; + register int i = ptes_per_vm_page; + register pt_entry_t *lpte = cpte; + do { + *lpte = 0; + lpte++; + } while (--i > 0); + continue; + } + + pai = pa_index(pa); + LOCK_PVH(pai); + + /* + * Get the modify and reference bits. + */ + { + register int i; + register pt_entry_t *lpte; + + i = ptes_per_vm_page; + lpte = cpte; + do { + pmap_phys_attributes[pai] |= pte_get_attributes(lpte); + *lpte = 0; + lpte++; + } while (--i > 0); + } + + /* + * Remove the mapping from the pvlist for + * this physical page. + */ + { + register pv_entry_t pv_h, prev, cur; + + pv_h = pai_to_pvh(pai); + if (pv_h->pmap == PMAP_NULL) { + panic("pmap_remove: null pv_list!"); } - /* - * Invalidate every valid mapping within this segment. - */ - pte = pmap_pte(pmap, sva); - while (sva < nssva) { - if (pmap_pte_v(pte)) { - pmap_remove_mapping(pmap, sva, pte, flags); - firstpage = FALSE; + if (pv_h->va == va && pv_h->pmap == pmap) { + /* + * Header is the pv_entry. Copy the next one + * to header and free the next one (we cannot + * free the header) + */ + cur = pv_h->next; + if (cur != PV_ENTRY_NULL) { + *pv_h = *cur; + PV_FREE(cur); + } + else { + pv_h->pmap = PMAP_NULL; + } + } + else { + cur = pv_h; + do { + prev = cur; + if ((cur = prev->next) == PV_ENTRY_NULL) { + panic("pmap-remove: mapping not in pv_list!"); } - pte++; - sva += PAGE_SIZE; + } while (cur->va != va || cur->pmap != pmap); + prev->next = cur->next; + PV_FREE(cur); } + UNLOCK_PVH(pai); + } } + /* - * Didn't do anything, no need for cache flushes + * Update the counts */ - if (firstpage) - return; + pmap->stats.resident_count -= num_removed; + pmap->stats.wired_count -= num_unwired; } /* - * pmap_page_protect: - * - * Lower the permission for all mappings to a given page. + * One level up, iterate an operation on the + * virtual range va..eva, mapped by the 1st + * level pte spte. */ + +/* static */ +void pmap_iterate_lev2(pmap, s, e, spte, operation) + pmap_t pmap; + vm_offset_t s, e; + pt_entry_t *spte; + void (*operation)(); +{ + vm_offset_t l; + pt_entry_t *epte; + pt_entry_t *cpte; + +if (pmap_debug > 1) db_printf("iterate2(%x,%x,%x)", s, e, spte); + while (s < e) { + /* at most 1 << 23 virtuals per iteration */ + l = roundup(s+1,PDE2_MAPPED_SIZE); + if (l > e) + l = e; + if (*spte & ALPHA_PTE_VALID) { + register int n; + cpte = (pt_entry_t *) ptetokv(*spte); + n = pte3num(l); + if (n == 0) n = SEG_MASK + 1;/* l == next segment up */ + epte = &cpte[n]; + cpte = &cpte[pte3num(s)]; + assert(epte >= cpte); +if (pmap_debug > 1) db_printf(" [%x %x, %x %x]", s, l, cpte, epte); + operation(pmap, s, cpte, epte); + } + s = l; + spte++; + } +if (pmap_debug > 1) db_printf("\n"); +} + void -pmap_page_protect(pa, prot) - vm_offset_t pa; - vm_prot_t prot; +pmap_make_readonly(pmap, va, spte, epte) + pmap_t pmap; + vm_offset_t va; + pt_entry_t *spte; + pt_entry_t *epte; { - register pv_entry_t pv; - int s; + while (spte < epte) { + if (*spte & ALPHA_PTE_VALID) + *spte &= ~ALPHA_PTE_WRITE; + spte++; + } +} -#ifdef DEBUG - if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) || - prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE)) - printf("pmap_page_protect(%lx, %lx)\n", pa, prot); -#endif - if (!PAGE_IS_MANAGED(pa)) +/* + * Remove the given range of addresses + * from the specified map. + * + * It is assumed that the start and end are properly + * rounded to the hardware page size. + */ +vm_offset_t pmap_suspect_vs, pmap_suspect_ve; + + +void pmap_remove(map, s, e) + pmap_t map; + vm_offset_t s, e; +{ + spl_t spl; + register pt_entry_t *pde; + register pt_entry_t *spte; + vm_offset_t l; + + if (map == PMAP_NULL) return; +if (pmap_debug || ((s > pmap_suspect_vs) && (s < pmap_suspect_ve))) +db_printf("[%d]pmap_remove(%x,%x,%x)\n", cpu_number(), map, s, e); + PMAP_READ_LOCK(map, spl); + + /* + * Invalidate the translation buffer first + */ + PMAP_UPDATE_TLBS(map, s, e); + + pde = pmap_pde(map, s); + while (s < e) { + /* at most (1 << 33) virtuals per iteration */ + l = roundup(s+1, PDE_MAPPED_SIZE); + if (l > e) + l = e; + if (*pde & ALPHA_PTE_VALID) { + spte = (pt_entry_t *)ptetokv(*pde); + spte = &spte[pte2num(s)]; + pmap_iterate_lev2(map, s, l, spte, pmap_remove_range); + } + s = l; + pde++; + } + + PMAP_READ_UNLOCK(map, spl); +} + +/* + * Routine: pmap_page_protect + * + * Function: + * Lower the permission for all mappings to a given + * page. + */ +vm_offset_t pmap_suspect_phys; + +void pmap_page_protect(phys, prot) + vm_offset_t phys; + vm_prot_t prot; +{ + pv_entry_t pv_h, prev; + register pv_entry_t pv_e; + register pt_entry_t *pte; + int pai; + register pmap_t pmap; + spl_t spl; + boolean_t remove; + +if (pmap_debug || (phys == pmap_suspect_phys)) db_printf("pmap_page_protect(%x,%x)\n", phys, prot); + + assert(phys != vm_page_fictitious_addr); + if (!valid_page(phys)) { + /* + * Not a managed page. + */ + return; + } + + /* + * Determine the new protection. + */ switch (prot) { - case VM_PROT_READ|VM_PROT_WRITE: - case VM_PROT_ALL: - return; - /* copy_on_write */ - case VM_PROT_READ: - case VM_PROT_READ|VM_PROT_EXECUTE: -/* XXX */ pmap_changebit(pa, PG_KWE | PG_UWE, FALSE); - return; - /* remove_all */ - default: + case VM_PROT_READ: + case VM_PROT_READ|VM_PROT_EXECUTE: + remove = FALSE; + break; + case VM_PROT_ALL: + return; /* nothing to do */ + default: + remove = TRUE; break; } - pv = pa_to_pvh(pa); - s = splimp(); - while (pv->pv_pmap != NULL) { - register pt_entry_t *pte; - - pte = pmap_pte(pv->pv_pmap, pv->pv_va); -#ifdef DEBUG - if (!pmap_ste_v(pv->pv_pmap, pv->pv_va) || - pmap_pte_pa(pte) != pa) - panic("pmap_page_protect: bad mapping"); -#endif - if (!pmap_pte_w(pte)) - pmap_remove_mapping(pv->pv_pmap, pv->pv_va, - pte, PRM_TFLUSH|PRM_CFLUSH); + + /* + * Lock the pmap system first, since we will be changing + * several pmaps. + */ + + PMAP_WRITE_LOCK(spl); + + pai = pa_index(phys); + pv_h = pai_to_pvh(pai); + + /* + * Walk down PV list, changing or removing all mappings. + * We do not have to lock the pv_list because we have + * the entire pmap system locked. + */ + if (pv_h->pmap != PMAP_NULL) { + + prev = pv_e = pv_h; + do { + pmap = pv_e->pmap; + /* + * Lock the pmap to block pmap_extract and similar routines. + */ + simple_lock(&pmap->lock); + + { + register vm_offset_t va; + + va = pv_e->va; + pte = pmap_pte(pmap, va); + + /* + * Consistency checks. + */ + /* assert(*pte & ALPHA_PTE_VALID); XXX */ + /* assert(pte_to_phys(*pte) == phys); */ + + /* + * Invalidate TLBs for all CPUs using this mapping. + */ + PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE); + } + + /* + * Remove the mapping if new protection is NONE + * or if write-protecting a kernel mapping. + */ + if (remove || pmap == kernel_pmap) { + /* + * Remove the mapping, collecting any modify bits. + */ + if (*pte & ALPHA_PTE_WIRED) + panic("pmap_remove_all removing a wired page"); + + { + register int i = ptes_per_vm_page; + + do { + pmap_phys_attributes[pai] |= pte_get_attributes(pte); + *pte++ = 0; + } while (--i > 0); + } + + pmap->stats.resident_count--; + + /* + * Remove the pv_entry. + */ + if (pv_e == pv_h) { + /* + * Fix up head later. + */ + pv_h->pmap = PMAP_NULL; + } + else { + /* + * Delete this entry. + */ + prev->next = pv_e->next; + PV_FREE(pv_e); + } + } else { - pv = pv->pv_next; -#ifdef DEBUG - if (pmapdebug & PDB_PARANOIA) - printf("%s wired mapping for %lx not removed\n", - "pmap_page_protect:", pa); -#endif + /* + * Write-protect. + */ + register int i = ptes_per_vm_page; + + do { + *pte &= ~ALPHA_PTE_WRITE; + pte++; + } while (--i > 0); + + /* + * Advance prev. + */ + prev = pv_e; } + + simple_unlock(&pmap->lock); + + } while ((pv_e = prev->next) != PV_ENTRY_NULL); + + /* + * If pv_head mapping was removed, fix it up. + */ + if (pv_h->pmap == PMAP_NULL) { + pv_e = pv_h->next; + if (pv_e != PV_ENTRY_NULL) { + *pv_h = *pv_e; + PV_FREE(pv_e); + } + } } - splx(s); + + PMAP_WRITE_UNLOCK(spl); } /* * Set the physical protection on the * specified range of this map as requested. + * Will not increase permissions. */ -void -pmap_protect(pmap, sva, eva, prot) - register pmap_t pmap; - register vm_offset_t sva, eva; - vm_prot_t prot; +void pmap_protect(map, s, e, prot) + pmap_t map; + vm_offset_t s, e; + vm_prot_t prot; { - register vm_offset_t nssva; - register pt_entry_t *pte, bits; - boolean_t firstpage, needtflush; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) - printf("pmap_protect(%lx, %lx, %lx, %lx)\n", pmap, sva, eva, prot); -#endif + register pt_entry_t *pde; + register pt_entry_t *spte, *epte; + vm_offset_t l; + spl_t spl; - if (pmap == NULL) + if (map == PMAP_NULL) return; -#ifdef PMAPSTATS - protect_stats.calls++; -#endif - if ((prot & VM_PROT_READ) == VM_PROT_NONE) { - pmap_remove(pmap, sva, eva); +if (pmap_debug || ((s > pmap_suspect_vs) && (s < pmap_suspect_ve))) +db_printf("[%d]pmap_protect(%x,%x,%x,%x)\n", cpu_number(), map, s, e, prot); + /* + * Determine the new protection. + */ + switch (prot) { + case VM_PROT_READ|VM_PROT_EXECUTE: + alphacache_Iflush(); + case VM_PROT_READ: + break; + case VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE: + alphacache_Iflush(); + case VM_PROT_READ|VM_PROT_WRITE: + return; /* nothing to do */ + default: + pmap_remove(map, s, e); return; } - if (prot & VM_PROT_WRITE) - return; - bits = pte_prot(pmap, prot); - needtflush = active_pmap(pmap); - firstpage = TRUE; - while (sva < eva) { - nssva = alpha_trunc_seg(sva) + ALPHA_SEG_SIZE; - if (nssva == 0 || nssva > eva) - nssva = eva; - /* - * If VA belongs to an unallocated segment, - * skip to the next segment boundary. - */ - if (!pmap_ste_v(pmap, sva)) { - sva = nssva; - continue; - } - /* - * Change protection on mapping if it is valid and doesn't - * already have the correct protection. - */ - pte = pmap_pte(pmap, sva); - while (sva < nssva) { - if (pmap_pte_v(pte) && pmap_pte_prot_chg(pte, bits)) { - pmap_pte_set_prot(pte, bits); - if (needtflush) - TBIS((caddr_t)sva); -#ifdef PMAPSTATS - protect_stats.changed++; -#endif - firstpage = FALSE; - } -#ifdef PMAPSTATS - else if (pmap_pte_v(pte)) { - if (isro) - protect_stats.alreadyro++; - else - protect_stats.alreadyrw++; - } -#endif - pte++; - sva += PAGE_SIZE; - } + SPLVM(spl); + simple_lock(&map->lock); + + /* + * Invalidate the translation buffer first + */ + PMAP_UPDATE_TLBS(map, s, e); + + pde = pmap_pde(map, s); + while (s < e) { + /* at most (1 << 33) virtuals per iteration */ + l = roundup(s+1, PDE_MAPPED_SIZE); + if (l > e) + l = e; + if (*pde & ALPHA_PTE_VALID) { + spte = (pt_entry_t *)ptetokv(*pde); + spte = &spte[pte2num(s)]; + pmap_iterate_lev2(map, s, l, spte, pmap_make_readonly); + } + s = l; + pde++; } + + simple_unlock(&map->lock); + SPLX(spl); } /* @@ -918,222 +1722,225 @@ pmap_protect(pmap, sva, eva, prot) * insert this page into the given map NOW. */ void -pmap_enter(pmap, va, pa, prot, wired) - register pmap_t pmap; - vm_offset_t va; - register vm_offset_t pa; - vm_prot_t prot; - boolean_t wired; +pmap_enter(pmap, v, pa, prot, wired) + register pmap_t pmap; + vm_offset_t v; + register vm_offset_t pa; + vm_prot_t prot; + boolean_t wired; { - register pt_entry_t *pte; - register pt_entry_t npte; - vm_offset_t opa; - boolean_t checkpv = TRUE; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_ENTER)) - printf("pmap_enter(%lx, %lx, %lx, %lx, %lx)\n", - pmap, va, pa, prot, wired); -#endif - if (pmap == NULL) - return; + register pt_entry_t *pte; + register pv_entry_t pv_h; + register int i, pai; + pv_entry_t pv_e; + pt_entry_t template; + spl_t spl; + vm_offset_t old_pa; + + if (DOPDB(PDB_FOLLOW|PDB_ENTER)) + printf("pmap_enter(%p, 0x%lx, 0x%lx, 0x%x, %d)\n", + pmap, v, pa, prot, wired); + + assert(pa != vm_page_fictitious_addr); +if (pmap_debug || ((v > pmap_suspect_vs) && (v < pmap_suspect_ve))) +db_printf("[%d]pmap_enter(%x(%d), %x, %x, %x, %x)\n", cpu_number(), pmap, pmap->pid, v, pa, prot, wired); + if (pmap == PMAP_NULL) + goto out; + assert(!pmap_max_asn || pmap->pid >= 0); -#ifdef PMAPSTATS - if (pmap == pmap_kernel()) - enter_stats.kernel++; - else - enter_stats.user++; -#endif /* - * For user mapping, allocate kernel VM resources if necessary. + * Must allocate a new pvlist entry while we're unlocked; + * zalloc may cause pageout (which will lock the pmap system). + * If we determine we need a pvlist entry, we will unlock + * and allocate one. Then we will retry, throwing away + * the allocated entry later (if we no longer need it). */ - if (pmap->pm_ptab == NULL) - pmap->pm_ptab = (pt_entry_t *) - kmem_alloc_wait(pt_map, ALPHA_MAX_PTSIZE); - /* - * Segment table entry not valid, we need a new PT page - */ - if (!pmap_ste_v(pmap, va)) - pmap_enter_ptpage(pmap, va); - - pa = alpha_trunc_page(pa); - pte = pmap_pte(pmap, va); - opa = pmap_pte_pa(pte); -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) - printf("enter: pte %lx, *pte %lx\n", pte, *pte); -#endif + pv_e = PV_ENTRY_NULL; +Retry: + PMAP_READ_LOCK(pmap, spl); /* - * Mapping has not changed, must be protection or wiring change. + * Expand pmap to include this pte. Assume that + * pmap is always expanded to include enough hardware + * pages to map one VM page. */ - if (opa == pa) { -#ifdef PMAPSTATS - enter_stats.pwchange++; -#endif - /* - * 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 (pmap_pte_w_chg(pte, wired ? PG_WIRED : 0)) { -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) - printf("enter: wiring change -> %lx\n", wired); -#endif - if (wired) - pmap->pm_stats.wired_count++; - else - pmap->pm_stats.wired_count--; -#ifdef PMAPSTATS - if (pmap_pte_prot(pte) == pte_prot(pmap, prot)) - enter_stats.wchange++; -#endif - } -#ifdef PMAPSTATS - else if (pmap_pte_prot(pte) != pte_prot(pmap, prot)) - enter_stats.pchange++; - else - enter_stats.nochange++; -#endif + + while ((pte = pmap_pte(pmap, v)) == PT_ENTRY_NULL) { /* - * Retain cache inhibition status + * Must unlock to expand the pmap. */ - checkpv = FALSE; - goto validate; + PMAP_READ_UNLOCK(pmap, spl); + + pmap_expand(pmap, v); + + PMAP_READ_LOCK(pmap, spl); } /* - * Mapping has changed, invalidate old range and fall through to - * handle validating new mapping. + * Special case if the physical page is already mapped + * at this address. */ - if (opa) { -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) - printf("enter: removing old mapping %lx\n", va); -#endif - pmap_remove_mapping(pmap, va, pte, PRM_TFLUSH|PRM_CFLUSH); -#ifdef PMAPSTATS - enter_stats.mchange++; -#endif + old_pa = pte_to_pa(*pte); + if (*pte && old_pa == pa) { + /* + * May be changing its wired attribute or protection + */ + + if (DOVPDB(PDB_FOLLOW|PDB_ENTER)) + printf("pmap_enter: same PA already mapped there (0x%lx)\n", + *pte); + + if (wired && !(*pte & ALPHA_PTE_WIRED)) + pmap->stats.wired_count++; + else if (!wired && (*pte & ALPHA_PTE_WIRED)) + pmap->stats.wired_count--; + + pte_template(pmap,template,pa,prot); + if (pmap == kernel_pmap) + template |= ALPHA_PTE_GLOBAL; + if (wired) + template |= ALPHA_PTE_WIRED; + PMAP_UPDATE_TLBS(pmap, v, v + PAGE_SIZE); + i = ptes_per_vm_page; + do { + template |= (*pte & ALPHA_PTE_MOD); + *pte = template; + pte++; + pte_increment_pa(template); + } while (--i > 0); } + else { - /* - * If this is a new user mapping, increment the wiring count - * on this PT page. PT pages are wired down as long as there - * is a valid mapping in the page. - */ - if (pmap != pmap_kernel()) - (void) vm_map_pageable(pt_map, trunc_page(pte), - round_page(pte+1), FALSE); + /* + * Remove old mapping from the PV list if necessary. + */ + if (*pte) { + if (DOVPDB(PDB_FOLLOW|PDB_ENTER)) + printf("pmap_enter: removing old PTE (0x%lx)\n", *pte); - /* - * 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 (PAGE_IS_MANAGED(pa)) { - register pv_entry_t pv, npv; - int s; + /* + * Invalidate the translation buffer, + * then remove the mapping. + */ + PMAP_UPDATE_TLBS(pmap, v, v + PAGE_SIZE); -#ifdef PMAPSTATS - enter_stats.managed++; -#endif - pv = pa_to_pvh(pa); - s = splimp(); -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) - printf("enter: pv at %lx: %lx/%lx/%lx\n", - pv, pv->pv_va, pv->pv_pmap, pv->pv_next); -#endif /* - * No entries yet, use header as the first entry + * Don't free the pte page if removing last + * mapping - we will immediately replace it. */ - if (pv->pv_pmap == NULL) { -#ifdef PMAPSTATS - enter_stats.firstpv++; -#endif - pv->pv_va = va; - pv->pv_pmap = pmap; - pv->pv_next = NULL; - pv->pv_ptpte = NULL; - pv->pv_ptpmap = NULL; - pv->pv_flags = 0; - } + pmap_remove_range(pmap, v, pte, + pte + ptes_per_vm_page); + } + + if (valid_page(pa)) { + if (DOVPDB(PDB_FOLLOW|PDB_ENTER)) + printf("pmap_enter: valid page\n"); + /* - * There is at least one other VA mapping this page. - * Place this entry after the header. + * Enter the mapping in the PV list for this + * physical page. */ + + pai = pa_index(pa); + LOCK_PVH(pai); + pv_h = pai_to_pvh(pai); + + if (pv_h->pmap == PMAP_NULL) { + /* + * No mappings yet + */ + if (DOVPDB(PDB_FOLLOW|PDB_ENTER)) + printf("pmap_enter: first mapping\n"); + pv_h->va = v; + pv_h->pmap = pmap; + pv_h->next = PV_ENTRY_NULL; + if (prot & VM_PROT_EXECUTE) + alphacache_Iflush(); + } else { -#ifdef DEBUG - for (npv = pv; npv; npv = npv->pv_next) - if (pmap == npv->pv_pmap && va == npv->pv_va) - panic("pmap_enter: already in pv_tab"); -#endif - npv = (pv_entry_t) - malloc(sizeof *npv, M_VMPVENT, M_NOWAIT); - npv->pv_va = va; - npv->pv_pmap = pmap; - npv->pv_next = pv->pv_next; - npv->pv_ptpte = NULL; - npv->pv_ptpmap = NULL; - npv->pv_flags = 0; - pv->pv_next = npv; -#ifdef PMAPSTATS - if (!npv->pv_next) - enter_stats.secondpv++; + if (DOVPDB(PDB_FOLLOW|PDB_ENTER)) + printf("pmap_enter: second+ mapping\n"); + +#if DEBUG + { + /* check that this mapping is not already there */ + pv_entry_t e = pv_h; + while (e != PV_ENTRY_NULL) { + if (e->pmap == pmap && e->va == v) + panic("pmap_enter: already in pv_list"); + e = e->next; + } + } +#endif /* DEBUG */ + + /* + * Add new pv_entry after header. + */ + if (pv_e == PV_ENTRY_NULL) { + pv_e = pmap_alloc_pv(); +#if 0 + PV_ALLOC(pv_e); + if (pv_e == PV_ENTRY_NULL) { + UNLOCK_PVH(pai); + PMAP_READ_UNLOCK(pmap, spl); + + /* + * Refill from zone. + */ + pv_e = (pv_entry_t) zalloc(pv_list_zone); + goto Retry; + } #endif + } + pv_e->va = v; + pv_e->pmap = pmap; + pv_e->next = pv_h->next; + pv_h->next = pv_e; + /* + * Remember that we used the pvlist entry. + */ + pv_e = PV_ENTRY_NULL; } - splx(s); - } - /* - * Assumption: if it is not part of our managed memory - * then it must be device memory which may be volitile. - */ - else if (pmap_initialized) { - checkpv = FALSE; -#ifdef PMAPSTATS - enter_stats.unmanaged++; -#endif + UNLOCK_PVH(pai); + } + + /* + * And count the mapping. + */ + + pmap->stats.resident_count++; + if (wired) + pmap->stats.wired_count++; + + /* + * Build a template to speed up entering - + * only the pfn changes. + */ + pte_template(pmap,template,pa,prot); + if (pmap == kernel_pmap) + template |= ALPHA_PTE_GLOBAL; + if (wired) + template |= ALPHA_PTE_WIRED; + i = ptes_per_vm_page; + do { + if (DOVPDB(PDB_FOLLOW|PDB_ENTER)) + printf("pmap_enter: entering PTE 0x%lx at %p\n", + template, pte); + *pte = template; + pte++; + pte_increment_pa(template); + } while (--i > 0); + ALPHA_TBIA(); } - /* - * Increment counters - */ - pmap->pm_stats.resident_count++; - if (wired) - pmap->pm_stats.wired_count++; - -validate: - /* - * Build the new PTE. - */ - npte = ((pa >> PGSHIFT) << PG_SHIFT) | pte_prot(pmap, prot) | PG_V; - if (PAGE_IS_MANAGED(pa)) { - if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_REF) == 0) - npte |= PG_FOR | PG_FOW | PG_FOE; - else if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_MOD) == 0) - npte |= PG_FOW; + if (pv_e != PV_ENTRY_NULL) { + PV_FREE(pv_e); } - if (wired) - npte |= PG_WIRED; -#ifdef DEBUG - if (pmapdebug & PDB_ENTER) - printf("enter: new pte value %lx\n", npte); -#endif - /* - * Remember if this was a wiring-only change. - * If so, we need not flush the TLB and caches. - */ - wired = ((*pte ^ npte) == PG_WIRED); - *pte = npte; - if (!wired && active_pmap(pmap)) - TBIS((caddr_t)va); -#ifdef DEBUG - if ((pmapdebug & PDB_WIRING) && pmap != pmap_kernel()) - pmap_check_wiring("enter", trunc_page(pmap_pte(pmap, va))); -#endif + + PMAP_READ_UNLOCK(pmap, spl); +out: + if (DOVPDB(PDB_FOLLOW|PDB_ENTER)) + printf("pmap_enter: done\n"); } /* @@ -1143,54 +1950,47 @@ validate: * 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; +void pmap_change_wiring(map, v, wired) + register pmap_t map; + vm_offset_t v; boolean_t wired; { - register pt_entry_t *pte; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_change_wiring(%lx, %lx, %lx)\n", pmap, va, wired); -#endif - if (pmap == NULL) - return; + register pt_entry_t *pte; + register int i; + spl_t spl; - pte = pmap_pte(pmap, va); -#ifdef DEBUG - /* - * Page table page is not allocated. - * Should this ever happen? Ignore it for now, - * we don't want to force allocation of unnecessary PTE pages. - */ - if (!pmap_ste_v(pmap, va)) { - if (pmapdebug & PDB_PARANOIA) - printf("pmap_change_wiring: invalid STE for %lx\n", va); - return; - } +if (pmap_debug) db_printf("pmap_change_wiring(%x,%x,%x)\n", map, v, wired); /* - * Page not valid. Should this ever happen? - * Just continue and change wiring anyway. + * We must grab the pmap system lock because we may + * change a pte_page queue. */ - if (!pmap_pte_v(pte)) { - if (pmapdebug & PDB_PARANOIA) - printf("pmap_change_wiring: invalid PTE for %lx\n", va); + PMAP_READ_LOCK(map, spl); + + if ((pte = pmap_pte(map, v)) == PT_ENTRY_NULL) + panic("pmap_change_wiring: pte missing"); + + if (wired && !(*pte & ALPHA_PTE_WIRED)) { + /* + * wiring down mapping + */ + map->stats.wired_count++; + i = ptes_per_vm_page; + do { + *pte++ |= ALPHA_PTE_WIRED; + } while (--i > 0); } -#endif - /* - * If wiring actually changed (always?) set the wire bit and - * update the wire count. Note that wiring is not a hardware - * characteristic so there is no need to invalidate the TLB. - */ - if (pmap_pte_w_chg(pte, wired ? PG_WIRED : 0)) { - pmap_pte_set_w(pte, wired); - if (wired) - pmap->pm_stats.wired_count++; - else - pmap->pm_stats.wired_count--; + else if (!wired && (*pte & ALPHA_PTE_WIRED)) { + /* + * unwiring mapping + */ + map->stats.wired_count--; + i = ptes_per_vm_page; + do { + *pte &= ~ALPHA_PTE_WIRED; + } while (--i > 0); } + + PMAP_READ_UNLOCK(map, spl); } /* @@ -1203,36 +2003,207 @@ pmap_change_wiring(pmap, va, wired) vm_offset_t pmap_extract(pmap, va) register pmap_t pmap; - vm_offset_t va; + vm_offset_t va; { - pt_entry_t pte; - register vm_offset_t pa; + register pt_entry_t *pte; + register vm_offset_t pa; + spl_t spl; -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_extract(%lx, %lx) -> ", pmap, va); -#endif - pa = 0; - if (pmap && pmap_ste_v(pmap, va)) { - pte = *pmap_pte(pmap, va); - if (pte & PG_V) - pa = ctob(PG_PFNUM(pte)) | (va & PGOFSET); + if (DOPDB(PDB_FOLLOW|PDB_EXTRACT)) + printf("pmap_extract(%p, 0x%lx)\n", pmap, va); + + /* + * Special translation for kernel addresses in + * K0 space (directly mapped to physical addresses). + */ + if (ISA_K0SEG(va)) { + pa = K0SEG_TO_PHYS(va); + if (DOPDB(PDB_FOLLOW|PDB_EXTRACT)) + printf("pmap_extract: returns 0x%lx\n", pa); + goto out; } -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("%lx\n", pa); -#endif + SPLVM(spl); + simple_lock(&pmap->lock); + if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL) + pa = (vm_offset_t) 0; + else if (!(*pte & ALPHA_PTE_VALID)) + pa = (vm_offset_t) 0; + else + pa = pte_to_pa(*pte) + (va & ALPHA_OFFMASK); + simple_unlock(&pmap->lock); + + /* + * Beware: this puts back this thread in the cpus_active set + */ + SPLX(spl); + +out: + if (DOPDB(PDB_FOLLOW|PDB_EXTRACT)) + printf("pmap_extract: returns 0x%lx\n", pa); + return(pa); +} + +vm_offset_t +pmap_resident_extract(pmap, va) + register pmap_t pmap; + vm_offset_t va; +{ + register pt_entry_t *pte; + register vm_offset_t pa; + + /* + * Special translation for kernel addresses in + * K0 space (directly mapped to physical addresses). + */ + if (ISA_K0SEG(va)) { + pa = K0SEG_TO_PHYS(va); + goto out; + } + + if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL) + pa = (vm_offset_t) 0; + else if (!(*pte & ALPHA_PTE_VALID)) + pa = (vm_offset_t) 0; + else + pa = pte_to_pa(*pte) + (va & ALPHA_OFFMASK); + +out: return(pa); } /* + * Routine: pmap_expand + * + * Expands a pmap to be able to map the specified virtual address. + * + * Must be called with the pmap system and the pmap unlocked, + * since these must be unlocked to use vm_page_grab. + * Thus it must be called in a loop that checks whether the map + * has been expanded enough. + */ +void +pmap_expand(map, v) + register pmap_t map; + register vm_offset_t v; +{ + pt_entry_t template; + pt_entry_t *pdp; + register vm_page_t m; + register vm_offset_t pa; + register int i; + spl_t spl; + + if (DOPDB(PDB_FOLLOW|PDB_EXPAND)) + printf("pmap_expand(%p, 0x%lx)\n", map, v); + + /* Would have to go through all maps to add this page */ + if (map == kernel_pmap) + panic("pmap_expand"); + + /* + * Allocate a VM page for the level 2 page table entries, + * if not already there. + */ + pdp = pmap_pde(map,v); + if ((*pdp & ALPHA_PTE_VALID) == 0) { + pt_entry_t *pte; + + if (DOVPDB(PDB_FOLLOW|PDB_EXPAND)) + printf("pmap_expand: needs pde\n"); + + pa = pmap_page_table_page_alloc(); + + /* + * Re-lock the pmap and check that another thread has + * not already allocated the page-table page. If it + * has, discard the new page-table page (and try + * again to make sure). + */ + PMAP_READ_LOCK(map, spl); + + if (*pdp & ALPHA_PTE_VALID) { + /* + * Oops... + */ + PMAP_READ_UNLOCK(map, spl); + pmap_page_table_page_dealloc(pa); + return; + } + + /* + * Map the page. + */ + i = ptes_per_vm_page; + pte = pdp; + pte_ktemplate(template,pa,VM_PROT_READ|VM_PROT_WRITE); + if (map != kernel_pmap) + template &= ~ALPHA_PTE_ASM; + do { + *pte = template; + if (DOVPDB(PDB_FOLLOW|PDB_EXPAND)) + printf("pmap_expand: inserted l1 pte (0x%lx) at %p\n", + template, pte); + pte++; + pte_increment_pa(template); + } while (--i > 0); + PMAP_READ_UNLOCK(map, spl); + } + + /* + * Allocate a level 3 page table. + */ + + pa = pmap_page_table_page_alloc(); + + /* + * Re-lock the pmap and check that another thread has + * not already allocated the page-table page. If it + * has, we are done. + */ + PMAP_READ_LOCK(map, spl); + + if (pmap_pte(map, v) != PT_ENTRY_NULL) { + PMAP_READ_UNLOCK(map, spl); + pmap_page_table_page_dealloc(pa); + return; + } + + /* + * Set the page directory entry for this page table. + * If we have allocated more than one hardware page, + * set several page directory entries. + */ + i = ptes_per_vm_page; + pdp = (pt_entry_t *)ptetokv(*pdp); + pdp = &pdp[pte2num(v)]; + pte_ktemplate(template,pa,VM_PROT_READ|VM_PROT_WRITE); + if (map != kernel_pmap) + template &= ~ALPHA_PTE_ASM; + do { + *pdp = template; + if (DOVPDB(PDB_FOLLOW|PDB_EXPAND)) + printf("pmap_expand: inserted l2 pte (0x%lx) at %p\n", + template, pdp); + pdp++; + pte_increment_pa(template); + } while (--i > 0); + PMAP_READ_UNLOCK(map, spl); + +out: + if (DOVPDB(PDB_FOLLOW|PDB_EXPAND)) + printf("pmap_expand: leaving\n"); + return; +} + +/* * 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. */ +#if 0 void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) pmap_t dst_pmap; pmap_t src_pmap; @@ -1240,29 +2211,11 @@ void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) vm_size_t len; vm_offset_t src_addr; { -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_copy(%lx, %lx, %lx, %lx, %lx)\n", - dst_pmap, src_pmap, dst_addr, len, src_addr); -#endif +#ifdef lint + dst_pmap++; src_pmap++; dst_addr++; len++; src_addr++; +#endif /* lint */ } - -/* - * Require that all active physical maps contain no - * incorrect entries NOW. [This update includes - * forcing updates of any address map caching.] - * - * Generally used to insure that a thread about - * to run will see a semantically correct world. - */ -void pmap_update() -{ -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_update()\n"); #endif - TBIA(); -} /* * Routine: pmap_collect @@ -1275,176 +2228,216 @@ void pmap_update() * Usage: * Called by the pageout daemon when pages are scarce. */ -void -pmap_collect(pmap) - pmap_t pmap; +void pmap_collect(p) + pmap_t p; { - register vm_offset_t pa; - register pv_entry_t pv; - register pt_entry_t *pte; - vm_offset_t kpa; - int s; - -#ifdef DEBUG - pt_entry_t *ste; - int opmapdebug; -#endif - if (pmap != pmap_kernel()) +#if notyet + + register pt_entry_t *pdp, *ptp; + pt_entry_t *eptp; + vm_offset_t pa; + spl_t spl; + int wired; + + if (p == PMAP_NULL) return; -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_collect(%lx)\n", pmap); -#endif -#ifdef PMAPSTATS - kpt_stats.collectscans++; -#endif - s = splimp(); - for (pa = vm_first_phys; pa < vm_last_phys; pa += PAGE_SIZE) { - register struct kpt_page *kpt, **pkpt; + if (p == kernel_pmap) + return; - /* - * Locate physical pages which are being used as kernel - * page table pages. - */ - pv = pa_to_pvh(pa); - if (pv->pv_pmap != pmap_kernel() || !(pv->pv_flags & PV_PTPAGE)) - continue; - do { - if (pv->pv_ptpte && pv->pv_ptpmap == pmap_kernel()) - break; - } while (pv = pv->pv_next); - if (pv == NULL) - continue; -#ifdef DEBUG - if (pv->pv_va < (vm_offset_t)Sysmap || - pv->pv_va >= (vm_offset_t)Sysmap + ALPHA_MAX_PTSIZE) - printf("collect: kernel PT VA out of range\n"); - else - goto ok; - pmap_pvdump(pa); - continue; -ok: -#endif - pte = (pt_entry_t *)(pv->pv_va + ALPHA_PAGE_SIZE); - while (--pte >= (pt_entry_t *)pv->pv_va && *pte == PG_NV) - ; - if (pte >= (pt_entry_t *)pv->pv_va) - continue; - -#ifdef DEBUG - if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) { - printf("collect: freeing KPT page at %lx (ste %lx@%lx)\n", - pv->pv_va, *pv->pv_ptpte, pv->pv_ptpte); - opmapdebug = pmapdebug; - pmapdebug |= PDB_PTPAGE; - } + /* + * Garbage collect map. + */ + PMAP_READ_LOCK(p, spl); + PMAP_UPDATE_TLBS(p, VM_MIN_ADDRESS, VM_MAX_ADDRESS); + pmap_tlbpid_destroy(p->pid, FALSE); + + for (pdp = p->dirbase; + pdp < pmap_pde(p,VM_MIN_KERNEL_ADDRESS); + pdp += ptes_per_vm_page) + { + if (*pdp & ALPHA_PTE_VALID) { + + pa = pte_to_pa(*pdp); + ptp = (pt_entry_t *)phystokv(pa); + eptp = ptp + NPTES*ptes_per_vm_page; - ste = pv->pv_ptpte; -#endif - /* - * If all entries were invalid we can remove the page. - * We call pmap_remove_entry to take care of invalidating - * ST and Sysptmap entries. - */ - kpa = pmap_extract(pmap, pv->pv_va); - pmap_remove_mapping(pmap, pv->pv_va, PT_ENTRY_NULL, - PRM_TFLUSH|PRM_CFLUSH); /* - * Use the physical address to locate the original - * (kmem_alloc assigned) address for the page and put - * that page back on the free list. + * If the pte page has any wired mappings, we cannot + * free it. */ - for (pkpt = &kpt_used_list, kpt = *pkpt; - kpt != (struct kpt_page *)0; - pkpt = &kpt->kpt_next, kpt = *pkpt) - if (kpt->kpt_pa == kpa) - break; -#ifdef DEBUG - if (kpt == (struct kpt_page *)0) - panic("pmap_collect: lost a KPT page"); - if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) - printf("collect: %lx (%lx) to free list\n", - kpt->kpt_va, kpa); -#endif - *pkpt = kpt->kpt_next; - kpt->kpt_next = kpt_free_list; - kpt_free_list = kpt; -#ifdef PMAPSTATS - kpt_stats.kptinuse--; - kpt_stats.collectpages++; + wired = 0; + { + register pt_entry_t *ptep; + for (ptep = ptp; ptep < eptp; ptep++) { + if (*ptep & ALPHA_PTE_WIRED) { + wired = 1; + break; + } + } + } + if (!wired) { + /* + * Remove the virtual addresses mapped by this pte page. + */ +..... pmap_remove_range_2(p, + pdetova(pdp - p->dirbase), + ptp, + eptp); + + /* + * Invalidate the page directory pointer. + */ + { + register int i = ptes_per_vm_page; + register pt_entry_t *pdep = pdp; + do { + *pdep++ = 0; + } while (--i > 0); + } + + PMAP_READ_UNLOCK(p, spl); + + /* + * And free the pte page itself. + */ + { + register vm_page_t m; + + vm_object_lock(pmap_object); + m = vm_page_lookup(pmap_object, pa); + if (m == VM_PAGE_NULL) + panic("pmap_collect: pte page not in object"); + vm_page_lock_queues(); + vm_page_free(m); + inuse_ptepages_count--; + vm_page_unlock_queues(); + vm_object_unlock(pmap_object); + } + + PMAP_READ_LOCK(p, spl); + } + } + } + PMAP_READ_UNLOCK(p, spl); + return; #endif -#ifdef DEBUG - if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) - pmapdebug = opmapdebug; - - if (*ste) - printf("collect: kernel STE at %lx still valid (%lx)\n", - ste, *ste); - ste = &Sysptmap[(pt_entry_t *)ste-pmap_ste(pmap_kernel(), 0)]; - if (*ste) - printf("collect: kernel PTmap at %lx still valid (%lx)\n", - ste, *ste); +} + +/* + * Routine: pmap_activate + * Function: + * Binds the given physical map to the given + * processor, and returns a hardware map description. + */ +void +pmap_activate(pmap, hwpcb, cpu) + register pmap_t pmap; + struct alpha_pcb *hwpcb; + int cpu; +{ + + if (DOPDB(PDB_FOLLOW|PDB_ACTIVATE)) + printf("pmap_activate(%p, %p, %d)\n", pmap, hwpcb, cpu); + +#if 0 + PMAP_ACTIVATE(my_pmap, th, my_cpu); +#else + if (DOVPDB(PDB_ACTIVATE)) + printf("pmap_activate: old pid = %d\n", pmap->pid); + if (pmap->pid < 0) pmap_tlbpid_assign(pmap); + hwpcb->apcb_asn = pmap->pid; + hwpcb->apcb_ptbr = pmap->dirpfn; + if (pmap != kernel_pmap) + pmap->cpus_using = TRUE; + if (DOVPDB(PDB_ACTIVATE)) + printf("pmap_activate: new pid = %d, new ptbr = 0x%lx\n", + pmap->pid, pmap->dirpfn); #endif - } - splx(s); } +/* + * Routine: pmap_deactivate + * Function: + * Indicates that the given physical map is no longer + * in use on the specified processor. (This is a macro + * in pmap.h) + */ void -pmap_activate(pmap) - register pmap_t pmap; +pmap_deactivate(pmap, hwpcb, cpu) + register pmap_t pmap; + struct alpha_pcb *hwpcb; + int cpu; { - int iscurproc; + if (DOPDB(PDB_FOLLOW|PDB_DEACTIVATE)) + printf("pmap_deactivate(%p, %p, %d)\n", pmap, hwpcb, cpu); -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_SEGTAB)) - printf("pmap_activate(%lx)\n", pmap); +#if 0 + PMAP_DEACTIVATE(pmap, th, which_cpu); +#else + if (DOVPDB(PDB_DEACTIVATE)) + printf("pmap_deactivate: pid = %d, ptbr = 0x%lx\n", + pmap->pid, pmap->dirpfn); + pmap->cpus_using = FALSE; #endif +} - iscurproc = curproc != NULL && pmap == curproc->p_vmspace->vm_map.pmap; - PMAP_ACTIVATE(pmap, iscurproc); +/* + * Routine: pmap_kernel + * Function: + * Returns the physical map handle for the kernel. + */ +#if 0 +pmap_t pmap_kernel() +{ + return (kernel_pmap); } +#endif /* - * 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. + * pmap_zero_page zeros the specified (machine independent) page. + * See machine/phys.c or machine/phys.s for implementation. */ +#if 1 void pmap_zero_page(phys) - vm_offset_t phys; + register vm_offset_t phys; { - caddr_t p; -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_zero_page(%lx)\n", phys); -#endif - p = (caddr_t)phystok0seg(phys); - bzero(p, PAGE_SIZE); + if (DOPDB(PDB_FOLLOW|PDB_ZERO_PAGE)) + printf("pmap_zero_page(0x%lx)\n", phys); + + assert(phys != vm_page_fictitious_addr); + + bzero((void *)phystokv(phys), PAGE_SIZE); + + if (DOVPDB(PDB_FOLLOW|PDB_ZERO_PAGE)) + printf("pmap_zero_page: leaving\n"); } +#endif /* - * 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. + * pmap_copy_page copies the specified (machine independent) page. + * See machine/phys.c or machine/phys.s for implementation. */ +#if 1 /* fornow */ void pmap_copy_page(src, dst) - vm_offset_t src, dst; + vm_offset_t src, dst; { - caddr_t s, d; -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_copy_page(%lx, %lx)\n", src, dst); -#endif - s = (caddr_t)phystok0seg(src); - d = (caddr_t)phystok0seg(dst); - bcopy(s, d, PAGE_SIZE); + if (DOPDB(PDB_FOLLOW|PDB_COPY_PAGE)) + printf("pmap_copy_page(0x%lx, 0x%lx)\n", src, dst); + + assert(src != vm_page_fictitious_addr); + assert(dst != vm_page_fictitious_addr); + + aligned_block_copy(phystokv(src), phystokv(dst), PAGE_SIZE); + + if (DOVPDB(PDB_FOLLOW|PDB_COPY_PAGE)) + printf("pmap_copy_page: leaving\n"); } +#endif /* * Routine: pmap_pageable @@ -1461,130 +2454,247 @@ pmap_copy_page(src, dst) * down (or not) as appropriate. */ void -pmap_pageable(pmap, sva, eva, pageable) +pmap_pageable(pmap, start, end, pageable) pmap_t pmap; - vm_offset_t sva, eva; + vm_offset_t start; + vm_offset_t end; boolean_t pageable; { -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_pageable(%lx, %lx, %lx, %lx)\n", - pmap, sva, eva, pageable); +#ifdef lint + pmap++; start++; end++; pageable++; #endif +} + +/* + * Clear specified attribute bits. + */ +void +phys_attribute_clear(phys, bits) + vm_offset_t phys; + int bits; +{ + pv_entry_t pv_h; + register pv_entry_t pv_e; + register pt_entry_t *pte; + int pai; + register pmap_t pmap; + spl_t spl; + + assert(phys != vm_page_fictitious_addr); + if (!valid_page(phys)) { + /* + * Not a managed page. + */ + return; + } + + /* + * Lock the pmap system first, since we will be changing + * several pmaps. + */ + + PMAP_WRITE_LOCK(spl); + + pai = pa_index(phys); + pv_h = pai_to_pvh(pai); + /* - * If we are making a PT page pageable then all valid - * mappings must be gone from that page. Hence it should - * be all zeros and there is no need to clean it. - * Assumptions: - * - we are called with only one page at a time - * - PT pages have only one pv_table entry + * Walk down PV list, clearing all modify or reference bits. + * We do not have to lock the pv_list because we have + * the entire pmap system locked. */ - if (pmap == pmap_kernel() && pageable && sva + PAGE_SIZE == eva) { - register pv_entry_t pv; - register vm_offset_t pa; - -#ifdef DEBUG - if ((pmapdebug & (PDB_FOLLOW|PDB_PTPAGE)) == PDB_PTPAGE) - printf("pmap_pageable(%lx, %lx, %lx, %lx)\n", - pmap, sva, eva, pageable); + if (pv_h->pmap != PMAP_NULL) { + /* + * There are some mappings. + */ + for (pv_e = pv_h; pv_e != PV_ENTRY_NULL; pv_e = pv_e->next) { + + pmap = pv_e->pmap; + /* + * Lock the pmap to block pmap_extract and similar routines. + */ + simple_lock(&pmap->lock); + + { + register vm_offset_t va; + + va = pv_e->va; + pte = pmap_pte(pmap, va); + +#if 0 + /* + * Consistency checks. + */ + assert(*pte & ALPHA_PTE_VALID); + /* assert(pte_to_phys(*pte) == phys); */ #endif - if (!pmap_ste_v(pmap, sva)) - return; - pa = pmap_pte_pa(pmap_pte(pmap, sva)); - if (!PAGE_IS_MANAGED(pa)) - return; - pv = pa_to_pvh(pa); - if (pv->pv_ptpte == NULL) - return; -#ifdef DEBUG - if (pv->pv_va != sva || pv->pv_next) { - printf("pmap_pageable: bad PT page va %lx next %lx\n", - pv->pv_va, pv->pv_next); - return; + + /* + * Invalidate TLBs for all CPUs using this mapping. + */ + PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE); } -#endif + /* - * Mark it unmodified to avoid pageout + * Clear modify or reference bits. */ - pmap_clear_modify(pa); -#ifdef DEBUG - if ((PHYS_TO_VM_PAGE(pa)->flags & PG_CLEAN) == 0) { - printf("pa %lx: flags=%lx: not clean\n", - pa, PHYS_TO_VM_PAGE(pa)->flags); - PHYS_TO_VM_PAGE(pa)->flags |= PG_CLEAN; + { + register int i = ptes_per_vm_page; + do { + *pte &= ~bits; + } while (--i > 0); } - if (pmapdebug & PDB_PTPAGE) - printf("pmap_pageable: PT page %lx(%lx) unmodified\n", - sva, *pmap_pte(pmap, sva)); - if (pmapdebug & PDB_WIRING) - pmap_check_wiring("pageable", sva); -#endif + simple_unlock(&pmap->lock); + } } + + pmap_phys_attributes[pai] &= ~ (bits >> 16); + + PMAP_WRITE_UNLOCK(spl); } /* - * Clear the modify bits on the specified physical page. + * Check specified attribute bits. */ +boolean_t +phys_attribute_test(phys, bits) + vm_offset_t phys; + int bits; +{ + pv_entry_t pv_h; + register pv_entry_t pv_e; + register pt_entry_t *pte; + int pai; + register pmap_t pmap; + spl_t spl; + + assert(phys != vm_page_fictitious_addr); + if (!valid_page(phys)) { + /* + * Not a managed page. + */ + return (FALSE); + } + + /* + * Lock the pmap system first, since we will be checking + * several pmaps. + */ + + PMAP_WRITE_LOCK(spl); + + pai = pa_index(phys); + pv_h = pai_to_pvh(pai); + + if (pmap_phys_attributes[pai] & (bits >> 16)) { + PMAP_WRITE_UNLOCK(spl); + return (TRUE); + } + + /* + * Walk down PV list, checking all mappings. + * We do not have to lock the pv_list because we have + * the entire pmap system locked. + */ + if (pv_h->pmap != PMAP_NULL) { + /* + * There are some mappings. + */ + for (pv_e = pv_h; pv_e != PV_ENTRY_NULL; pv_e = pv_e->next) { + + pmap = pv_e->pmap; + /* + * Lock the pmap to block pmap_extract and similar routines. + */ + simple_lock(&pmap->lock); + + { + register vm_offset_t va; + + va = pv_e->va; + pte = pmap_pte(pmap, va); + +#if 0 + /* + * Consistency checks. + */ + assert(*pte & ALPHA_PTE_VALID); + /* assert(pte_to_phys(*pte) == phys); */ +#endif + } + /* + * Check modify or reference bits. + */ + { + register int i = ptes_per_vm_page; + + do { + if (*pte & bits) { + simple_unlock(&pmap->lock); + PMAP_WRITE_UNLOCK(spl); + return (TRUE); + } + } while (--i > 0); + } + simple_unlock(&pmap->lock); + } + } + PMAP_WRITE_UNLOCK(spl); + return (FALSE); +} + +/* + * Set specified attribute bits. <ugly> + */ void -pmap_clear_modify(pa) - vm_offset_t pa; +phys_attribute_set(phys, bits) + vm_offset_t phys; + int bits; { -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_clear_modify(%lx)\n", pa); -#endif - if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */ - return; - if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_MOD) != 0) { - pmap_changebit(pa, PG_FOW, TRUE); - pmap_attributes[pa_index(pa)] &= ~PMAP_ATTR_MOD; + int pai; + spl_t spl; + + assert(phys != vm_page_fictitious_addr); + if (!valid_page(phys)) { + /* + * Not a managed page. + */ + return; } + + /* + * Lock the pmap system. + */ + + PMAP_WRITE_LOCK(spl); + + pai = pa_index(phys); + pmap_phys_attributes[pai] |= (bits >> 16); + + PMAP_WRITE_UNLOCK(spl); } /* - * pmap_clear_reference: - * - * Clear the reference bit on the specified physical page. + * Clear the modify bits on the specified physical page. */ -void pmap_clear_reference(pa) - vm_offset_t pa; +void pmap_clear_modify(phys) + register vm_offset_t phys; { -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_clear_reference(%lx)\n", pa); -#endif - if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */ - return; - if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_REF) != 0) { - pmap_changebit(pa, PG_FOR | PG_FOW | PG_FOE, TRUE); - pmap_attributes[pa_index(pa)] &= ~PMAP_ATTR_REF; - } +if (pmap_debug) db_printf("pmap_clear_mod(%x)\n", phys); + phys_attribute_clear(phys, ALPHA_PTE_MOD); } /* - * pmap_is_referenced: - * - * Return whether or not the specified physical page is referenced - * by any physical maps. + * Set the modify bits on the specified physical page. */ -boolean_t -pmap_is_referenced(pa) - vm_offset_t pa; +void pmap_set_modify(phys) + register vm_offset_t phys; { - boolean_t rv; - - if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */ - return 0; - rv = (pmap_attributes[pa_index(pa)] & PMAP_ATTR_REF) != 0; -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) { - printf("pmap_is_referenced(%lx) -> %c\n", pa, "FT"[rv]); - } -#endif - return rv; +if (pmap_debug) db_printf("pmap_set_mod(%x)\n", phys); + phys_attribute_set(phys, ALPHA_PTE_MOD); } /* @@ -1594,524 +2704,496 @@ pmap_is_referenced(pa) * by any physical maps. */ -boolean_t -pmap_is_modified(pa) - vm_offset_t pa; +boolean_t pmap_is_modified(phys) + register vm_offset_t phys; { - boolean_t rv; - - if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */ - return 0; - rv = (pmap_attributes[pa_index(pa)] & PMAP_ATTR_MOD) != 0; -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) { - printf("pmap_is_modified(%lx) -> %c\n", pa, "FT"[rv]); - } -#endif - return rv; +if (pmap_debug) db_printf("pmap_is_mod(%x)\n", phys); + return (phys_attribute_test(phys, ALPHA_PTE_MOD)); } -vm_offset_t -pmap_phys_address(ppn) - int ppn; +/* + * pmap_clear_reference: + * + * Clear the reference bit on the specified physical page. + */ + +void pmap_clear_reference(phys) + vm_offset_t phys; { - return(alpha_ptob(ppn)); +if (pmap_debug) db_printf("pmap_clear_ref(%x)\n", phys); + phys_attribute_clear(phys, ALPHA_PTE_REF); } /* - * Miscellaneous support routines follow + * pmap_is_referenced: + * + * Return whether or not the specified physical page is referenced + * by any physical maps. */ +boolean_t pmap_is_referenced(phys) + vm_offset_t phys; +{ +if (pmap_debug) db_printf("pmap_is_ref(%x)\n", phys); + return (phys_attribute_test(phys, ALPHA_PTE_REF)); +} + +#if NCPUS > 1 +/* +* TLB Coherence Code (TLB "shootdown" code) +* +* Threads that belong to the same task share the same address space and +* hence share a pmap. However, they may run on distinct cpus and thus +* have distinct TLBs that cache page table entries. In order to guarantee +* the TLBs are consistent, whenever a pmap is changed, all threads that +* are active in that pmap must have their TLB updated. To keep track of +* this information, the set of cpus that are currently using a pmap is +* maintained within each pmap structure (cpus_using). Pmap_activate() and +* pmap_deactivate add and remove, respectively, a cpu from this set. +* Since the TLBs are not addressable over the bus, each processor must +* flush its own TLB; a processor that needs to invalidate another TLB +* needs to interrupt the processor that owns that TLB to signal the +* update. +* +* Whenever a pmap is updated, the lock on that pmap is locked, and all +* cpus using the pmap are signaled to invalidate. All threads that need +* to activate a pmap must wait for the lock to clear to await any updates +* in progress before using the pmap. They must ACQUIRE the lock to add +* their cpu to the cpus_using set. An implicit assumption made +* throughout the TLB code is that all kernel code that runs at or higher +* than splvm blocks out update interrupts, and that such code does not +* touch pageable pages. +* +* A shootdown interrupt serves another function besides signaling a +* processor to invalidate. The interrupt routine (pmap_update_interrupt) +* waits for the both the pmap lock (and the kernel pmap lock) to clear, +* preventing user code from making implicit pmap updates while the +* sending processor is performing its update. (This could happen via a +* user data write reference that turns on the modify bit in the page +* table). It must wait for any kernel updates that may have started +* concurrently with a user pmap update because the IPC code +* changes mappings. +* Spinning on the VALUES of the locks is sufficient (rather than +* having to acquire the locks) because any updates that occur subsequent +* to finding the lock unlocked will be signaled via another interrupt. +* (This assumes the interrupt is cleared before the low level interrupt code +* calls pmap_update_interrupt()). +* +* The signaling processor must wait for any implicit updates in progress +* to terminate before continuing with its update. Thus it must wait for an +* acknowledgement of the interrupt from each processor for which such +* references could be made. For maintaining this information, a set +* cpus_active is used. A cpu is in this set if and only if it can +* use a pmap. When pmap_update_interrupt() is entered, a cpu is removed from +* this set; when all such cpus are removed, it is safe to update. +* +* Before attempting to acquire the update lock on a pmap, a cpu (A) must +* be at least at the priority of the interprocessor interrupt +* (splip<=splvm). Otherwise, A could grab a lock and be interrupted by a +* kernel update; it would spin forever in pmap_update_interrupt() trying +* to acquire the user pmap lock it had already acquired. Furthermore A +* must remove itself from cpus_active. Otherwise, another cpu holding +* the lock (B) could be in the process of sending an update signal to A, +* and thus be waiting for A to remove itself from cpus_active. If A is +* spinning on the lock at priority this will never happen and a deadlock +* will result. +*/ + /* - * Initialize Alpha protection code array. + * Signal another CPU that it must flush its TLB */ -/* static */ -void -alpha_protection_init() +void signal_cpus(use_list, pmap, start, end) + cpu_set use_list; + pmap_t pmap; + vm_offset_t start, end; { - int prot, *kp, *up; + register int which_cpu, j; + register pmap_update_list_t update_list_p; - kp = protection_codes[0]; - up = protection_codes[1]; + while ((which_cpu = ffs(use_list)) != 0) { + which_cpu -= 1; /* convert to 0 origin */ - 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; - } + update_list_p = &cpu_update_list[which_cpu]; + simple_lock(&update_list_p->lock); + + j = update_list_p->count; + if (j >= UPDATE_LIST_SIZE) { + /* + * list overflowed. Change last item to + * indicate overflow. + */ + update_list_p->item[UPDATE_LIST_SIZE-1].pmap = kernel_pmap; + update_list_p->item[UPDATE_LIST_SIZE-1].start = VM_MIN_ADDRESS; + update_list_p->item[UPDATE_LIST_SIZE-1].end = VM_MAX_KERNEL_ADDRESS; + } + else { + update_list_p->item[j].pmap = pmap; + update_list_p->item[j].start = start; + update_list_p->item[j].end = end; + update_list_p->count = j+1; + } + cpu_update_needed[which_cpu] = TRUE; + simple_unlock(&update_list_p->lock); + + if ((cpus_idle & (1 << which_cpu)) == 0) + interrupt_processor(which_cpu); + use_list &= ~(1 << which_cpu); } } -/* - * Invalidate a single page denoted by pmap/va. - * If (pte != NULL), it is the already computed PTE for the page. - * If (flags & PRM_TFLUSH), we must invalidate any TLB information. - * If (flags & PRM_CFLUSH), we must flush/invalidate any cache information. - */ -/* static */ -void -pmap_remove_mapping(pmap, va, pte, flags) - register pmap_t pmap; - register vm_offset_t va; - register pt_entry_t *pte; - int flags; +void process_pmap_updates(my_pmap) + register pmap_t my_pmap; +{ + register int my_cpu = cpu_number(); + register pmap_update_list_t update_list_p; + register int j; + register pmap_t pmap; + + update_list_p = &cpu_update_list[my_cpu]; + simple_lock(&update_list_p->lock); + + for (j = 0; j < update_list_p->count; j++) { + pmap = update_list_p->item[j].pmap; + if (pmap == my_pmap || + pmap == kernel_pmap) { + + INVALIDATE_TLB(update_list_p->item[j].start, + update_list_p->item[j].end); + } + } + update_list_p->count = 0; + cpu_update_needed[my_cpu] = FALSE; + simple_unlock(&update_list_p->lock); +} + +#if MACH_KDB + +static boolean_t db_interp_int[NCPUS]; +int db_inside_pmap_update[NCPUS]; +int suicide_cpu; + +cpu_interrupt_to_db(i) + int i; { - register vm_offset_t pa; - register pv_entry_t pv, npv; - pmap_t ptpmap; - pt_entry_t *ste; - int s; -#ifdef DEBUG - pt_entry_t opte; - - if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) - printf("pmap_remove_mapping(%lx, %lx, %lx, %lx)\n", - pmap, va, pte, flags); + db_interp_int[i] = TRUE; + interrupt_processor(i); +} #endif - /* - * PTE not provided, compute it from pmap and va. - */ - if (pte == PT_ENTRY_NULL) { - pte = pmap_pte(pmap, va); - if (*pte == PG_NV) - return; +/* + * Interrupt routine for TBIA requested from other processor. + */ +void pmap_update_interrupt() +{ + register int my_cpu; + register pmap_t my_pmap; + spl_t s; + + my_cpu = cpu_number(); + + db_inside_pmap_update[my_cpu]++; +#if MACH_KDB + if (db_interp_int[my_cpu]) { + db_interp_int[my_cpu] = FALSE; + remote_db_enter(); + /* In case another processor modified text */ + alphacache_Iflush(); +if (cpu_number() == suicide_cpu) halt(); + goto out; /* uhmmm, maybe should do updates just in case */ } - pa = pmap_pte_pa(pte); -#ifdef DEBUG - opte = *pte; -#endif -#ifdef PMAPSTATS - remove_stats.removes++; #endif /* - * Update statistics + * Exit now if we're idle. We'll pick up the update request + * when we go active, and we must not put ourselves back in + * the active set because we'll never process the interrupt + * while we're idle (thus hanging the system). */ - if (pmap_pte_w(pte)) - pmap->pm_stats.wired_count--; - pmap->pm_stats.resident_count--; + if (cpus_idle & (1 << my_cpu)) + goto out; - /* - * Invalidate the PTE after saving the reference modify info. - */ -#ifdef DEBUG - if (pmapdebug & PDB_REMOVE) - printf("remove: invalidating pte at %lx\n", pte); -#endif - *pte = PG_NV; - if ((flags & PRM_TFLUSH) && active_pmap(pmap)) - TBIS((caddr_t)va); - /* - * For user mappings decrement the wiring count on - * the PT page. We do this after the PTE has been - * invalidated because vm_map_pageable winds up in - * pmap_pageable which clears the modify bit for the - * PT page. - */ - if (pmap != pmap_kernel()) { - (void) vm_map_pageable(pt_map, trunc_page(pte), - round_page(pte+1), TRUE); -#ifdef DEBUG - if (pmapdebug & PDB_WIRING) - pmap_check_wiring("remove", trunc_page(pte)); -#endif - } - /* - * If this isn't a managed page, we are all done. - */ - if (!PAGE_IS_MANAGED(pa)) - return; - /* - * Otherwise remove it from the PV table - * (raise IPL since we may be called at interrupt time). - */ - pv = pa_to_pvh(pa); - ste = NULL; - s = splimp(); - /* - * 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. - */ - if (pmap == pv->pv_pmap && va == pv->pv_va) { - ste = pv->pv_ptpte; - ptpmap = pv->pv_ptpmap; - npv = pv->pv_next; - if (npv) { - npv->pv_flags = pv->pv_flags; - *pv = *npv; - free((caddr_t)npv, M_VMPVENT); - } else - pv->pv_pmap = NULL; -#ifdef PMAPSTATS - remove_stats.pvfirst++; -#endif - } else { - for (npv = pv->pv_next; npv; npv = npv->pv_next) { -#ifdef PMAPSTATS - remove_stats.pvsearch++; -#endif - if (pmap == npv->pv_pmap && va == npv->pv_va) - break; - pv = npv; - } -#ifdef DEBUG - if (npv == NULL) - panic("pmap_remove: PA not in pv_tab"); -#endif - ste = npv->pv_ptpte; - ptpmap = npv->pv_ptpmap; - pv->pv_next = npv->pv_next; - free((caddr_t)npv, M_VMPVENT); - pv = pa_to_pvh(pa); + if (current_thread() == THREAD_NULL) + my_pmap = kernel_pmap; + else { + my_pmap = current_pmap(); + if (!pmap_in_use(my_pmap, my_cpu)) + my_pmap = kernel_pmap; } + /* - * If this was a PT page we must also remove the - * mapping from the associated segment table. + * Raise spl to splvm (above splip) to block out pmap_extract + * from IO code (which would put this cpu back in the active + * set). */ - if (ste) { -#ifdef PMAPSTATS - remove_stats.ptinvalid++; -#endif -#ifdef DEBUG - if (pmapdebug & (PDB_REMOVE|PDB_PTPAGE)) - printf("remove: ste was %lx@%lx pte was %lx@%lx\n", - *ste, ste, opte, pmap_pte(pmap, va)); -#endif - *ste = PG_NV; - /* - * If it was a user PT page, we decrement the - * reference count on the segment table as well, - * freeing it if it is now empty. - */ - if (ptpmap != pmap_kernel()) { -#ifdef DEBUG - if (pmapdebug & (PDB_REMOVE|PDB_SEGTAB)) - printf("remove: stab %lx, refcnt %d\n", - ptpmap->pm_stab, ptpmap->pm_sref - 1); - if ((pmapdebug & PDB_PARANOIA) && - ptpmap->pm_stab != (pt_entry_t *)trunc_page(ste)) - panic("remove: bogus ste"); -#endif - if (--(ptpmap->pm_sref) == 0) { -#ifdef DEBUG - if (pmapdebug&(PDB_REMOVE|PDB_SEGTAB)) - printf("remove: free stab %lx\n", - ptpmap->pm_stab); -#endif - kmem_free_wakeup(st_map, - (vm_offset_t)ptpmap->pm_stab, - ALPHA_STSIZE); - ptpmap->pm_stab = Segtabzero; - ptpmap->pm_stpte = Segtabzeropte; - ptpmap->pm_stchanged = TRUE; - /* - * XXX may have changed segment table - * pointer for current process so - * update now to reload hardware. - * (curproc may be NULL if exiting.) - */ - if (curproc != NULL && - ptpmap == curproc->p_vmspace->vm_map.pmap) - PMAP_ACTIVATE(ptpmap, 1); - } -#ifdef DEBUG - else if (ptpmap->pm_sref < 0) - panic("remove: sref < 0"); -#endif - } -#if 0 - /* - * XXX this should be unnecessary as we have been - * flushing individual mappings as we go. - */ - if (ptpmap == pmap_kernel()) - TBIAS(); - else - TBIAU(); -#endif - pv->pv_flags &= ~PV_PTPAGE; - ptpmap->pm_ptpages--; - } + s = splvm(); + + do { + + /* + * Indicate that we're not using either user or kernel + * pmap. + */ + i_bit_clear(my_cpu, &cpus_active); + + /* + * Wait for any pmap updates in progress, on either user + * or kernel pmap. + */ + while (*(volatile int *)&my_pmap->lock.lock_data || + *(volatile int *)&kernel_pmap->lock.lock_data) + continue; + + process_pmap_updates(my_pmap); + + i_bit_set(my_cpu, &cpus_active); + + } while (cpu_update_needed[my_cpu]); + splx(s); +out: + db_inside_pmap_update[my_cpu]--; +} +#else NCPUS > 1 +/* + * Dummy routine to satisfy external reference. + */ +void pmap_update_interrupt() +{ + /* should never be called. */ } +#endif /* NCPUS > 1 */ -/* static */ void -pmap_changebit(pa, bit, setem) - register vm_offset_t pa; - u_long bit; - boolean_t setem; +set_ptbr(pmap_t map, pcb_t pcb, boolean_t switchit) { - register pv_entry_t pv; - register pt_entry_t *pte, npte; - vm_offset_t va; - int s; - boolean_t firstpage = TRUE; -#ifdef PMAPSTATS - struct chgstats *chgp; -#endif + /* optimize later */ + vm_offset_t pa; -#ifdef DEBUG - if (pmapdebug & PDB_BITS) - printf("pmap_changebit(%lx, %lx, %s)\n", - pa, bit, setem ? "set" : "clear"); + pa = pmap_resident_extract(kernel_pmap, (vm_offset_t)map->dirbase); +printf("set_ptbr (switch = %d): dirbase = 0x%lx, pa = 0x%lx\n", switchit, map->dirbase, pa); + if (pa == 0) + panic("set_ptbr"); +#if 0 + pcb->mss.hw_pcb.ptbr = alpha_btop(pa); + if (switchit) { + pcb->mss.hw_pcb.asn = map->pid; + swpctxt(kvtophys((vm_offset_t) pcb), &(pcb)->mss.hw_pcb.ksp); + } +#else + pcb->pcb_hw.apcb_ptbr = alpha_btop(pa); + if (switchit) { + pcb->pcb_hw.apcb_asn = map->pid; + swpctxt(kvtophys((vm_offset_t) pcb), &(pcb)->pcb_hw.apcb_ksp); + } #endif - if (!PAGE_IS_MANAGED(pa)) - return; +} -#ifdef PMAPSTATS - chgp = &changebit_stats[(bit>>2)-1]; - if (setem) - chgp->setcalls++; - else - chgp->clrcalls++; -#endif - pv = pa_to_pvh(pa); - s = splimp(); - /* - * Loop over all current mappings setting/clearing as appropos - * If setting RO do we need to clear the VAC? - */ - if (pv->pv_pmap != NULL) { -#ifdef DEBUG - int toflush = 0; -#endif - for (; pv; pv = pv->pv_next) { -#ifdef DEBUG - toflush |= (pv->pv_pmap == pmap_kernel()) ? 2 : 1; +/*************************************************************************** + * + * TLBPID Management + * + * This is basically a unique number generator, with the twist + * that numbers are in a given range (dynamically defined). + * All things considered, I did it right in the MIPS case. + */ + +#if 0 +/* above */ +int pmap_max_asn; #endif - va = pv->pv_va; - /* - * XXX don't write protect pager mappings - */ -/* XXX */ if (bit == (PG_UWE | PG_KWE)) { - extern vm_offset_t pager_sva, pager_eva; +decl_simple_lock_data(static, tlbpid_lock) +static struct pmap **pids_in_use; +static int pmap_next_pid; - if (va >= pager_sva && va < pager_eva) - continue; - } +pmap_tlbpid_init(maxasn) + int maxasn; +{ + simple_lock_init(&tlbpid_lock); - pte = pmap_pte(pv->pv_pmap, va); - if (setem) - npte = *pte | bit; - else - npte = *pte & ~bit; - if (*pte != npte) { - *pte = npte; - if (active_pmap(pv->pv_pmap)) - TBIS((caddr_t)va); -#ifdef PMAPSTATS - if (setem) - chgp->sethits++; - else - chgp->clrhits++; -#endif - } -#ifdef PMAPSTATS - else { - if (setem) - chgp->setmiss++; - else - chgp->clrmiss++; + if (DOVPDB(PDB_FOLLOW|PDB_TLBPID_INIT)) + printf("pmap_tlbpid_init: maxasn = %d\n", maxasn); + + pmap_max_asn = maxasn; + if (maxasn == 0) { + /* ASNs not implemented... Is this the right way to check? */ + return; + } + + pids_in_use = (struct pmap **) + pmap_bootstrap_alloc((maxasn + 1) * sizeof(struct pmap *)); + bzero(pids_in_use, (maxasn + 1) * sizeof(struct pmap *)); + + pmap_next_pid = 1; +} + +/* + * Axioms: + * - pmap_next_pid always points to a free one, unless the table is full; + * in that case it points to a likely candidate for recycling. + * - pmap.pid prevents from making duplicates: if -1 there is no + * pid for it, otherwise there is one and only one entry at that index. + * + * pmap_tlbpid_assign provides a tlbpid for the given pmap, creating + * a new one if necessary + * pmap_tlbpid_destroy returns a tlbpid to the pool of available ones + */ + +pmap_tlbpid_assign(map) + struct pmap *map; +{ + register int pid, next_pid; + + if (DOVPDB(PDB_FOLLOW|PDB_TLBPID_ASSIGN)) + printf("pmap_tlbpid_assign: pmap %p had %d\n", map, map->pid); + + if (pmap_max_asn && map->pid < 0) { + + simple_lock(&tlbpid_lock); + + next_pid = pmap_next_pid; + if (pids_in_use[next_pid]) { + /* are we _really_ sure it's full ? */ + for (pid = 1; pid < pmap_max_asn; pid++) + if (pids_in_use[pid] == PMAP_NULL) { + /* aha! */ + next_pid = pid; + goto got_a_free_one; + } + /* Table full */ + while (pids_in_use[next_pid]->cpus_using) { + if (++next_pid == pmap_max_asn) + next_pid = 1; } -#endif + pmap_tlbpid_destroy(next_pid, TRUE); } +got_a_free_one: + pids_in_use[next_pid] = map; + map->pid = next_pid; + if (++next_pid == pmap_max_asn) + next_pid = 1; + pmap_next_pid = next_pid; + + simple_unlock(&tlbpid_lock); } - splx(s); + if (DOVPDB(PDB_FOLLOW|PDB_TLBPID_ASSIGN)) + printf("pmap_tlbpid_assign: pmap %p got %d\n", map, map->pid); } -/* static */ -void -pmap_enter_ptpage(pmap, va) - register pmap_t pmap; - register vm_offset_t va; +pmap_tlbpid_destroy(pid, locked) + int pid; + boolean_t locked; { - register vm_offset_t ptpa; - register pv_entry_t pv; - pt_entry_t *ste; - int s; - -#ifdef DEBUG - if (pmapdebug & (PDB_FOLLOW|PDB_ENTER|PDB_PTPAGE)) - printf("pmap_enter_ptpage: pmap %lx, va %lx\n", pmap, va); -#endif -#ifdef PMAPSTATS - enter_stats.ptpneeded++; -#endif - /* - * Allocate a segment table if necessary. Note that it is allocated - * from a private map and not pt_map. This keeps user page tables - * aligned on segment boundaries in the kernel address space. - * The segment table is wired down. It will be freed whenever the - * reference count drops to zero. - */ - if (pmap->pm_stab == Segtabzero) { - pmap->pm_stab = (pt_entry_t *) - kmem_alloc(st_map, ALPHA_STSIZE); - pmap->pm_stpte = *kvtopte(pmap->pm_stab); - pmap->pm_stchanged = TRUE; - /* - * XXX may have changed segment table pointer for current - * process so update now to reload hardware. - */ - if (pmap == curproc->p_vmspace->vm_map.pmap) - PMAP_ACTIVATE(pmap, 1); -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB)) - printf("enter: pmap %lx stab %lx(%lx)\n", - pmap, pmap->pm_stab, pmap->pm_stpte); -#endif - } + struct pmap *map; - ste = pmap_ste(pmap, va); - va = trunc_page((vm_offset_t)pmap_pte(pmap, va)); + if (DOVPDB(PDB_FOLLOW|PDB_TLBPID_DESTROY)) + printf("pmap_tlbpid_destroy(%d, %d)\n", pid, locked); - /* - * In the kernel we allocate a page from the kernel PT page - * free list and map it into the kernel page table map (via - * pmap_enter). - */ - if (pmap == pmap_kernel()) { - register struct kpt_page *kpt; + if (pid < 0) /* no longer in use */ + return; + + assert(pmap_max_asn); + + if (!locked) simple_lock(&tlbpid_lock); - s = splimp(); - if ((kpt = kpt_free_list) == (struct kpt_page *)0) { - /* - * No PT pages available. - * Try once to free up unused ones. - */ -#ifdef DEBUG - if (pmapdebug & PDB_COLLECT) - printf("enter: no KPT pages, collecting...\n"); -#endif - pmap_collect(pmap_kernel()); - if ((kpt = kpt_free_list) == (struct kpt_page *)0) - panic("pmap_enter_ptpage: can't get KPT page"); - } -#ifdef PMAPSTATS - if (++kpt_stats.kptinuse > kpt_stats.kptmaxuse) - kpt_stats.kptmaxuse = kpt_stats.kptinuse; -#endif - kpt_free_list = kpt->kpt_next; - kpt->kpt_next = kpt_used_list; - kpt_used_list = kpt; - ptpa = kpt->kpt_pa; - bzero((caddr_t)kpt->kpt_va, ALPHA_PAGE_SIZE); - pmap_enter(pmap, va, ptpa, VM_PROT_DEFAULT, TRUE); -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) { - int ix = pmap_ste(pmap, va) - pmap_ste(pmap, 0); - - printf("enter: add &Sysptmap[%d]: %lx (KPT page %lx)\n", - ix, Sysptmap[ix], kpt->kpt_va); - } -#endif - splx(s); - } /* - * For user processes we just simulate a fault on that location - * letting the VM system allocate a zero-filled page. + * Make the pid available, and the map unassigned. */ - else { - /* - * Count the segment table reference now so that we won't - * lose the segment table when low on memory. - */ - pmap->pm_sref++; -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) - printf("enter: about to fault UPT pg at %lx\n", va); -#endif - s = vm_fault(pt_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE); - if (s != KERN_SUCCESS) { - printf("vm_fault(pt_map, %lx, RW, 0) -> %d\n", va, s); - panic("pmap_enter: vm_fault failed"); + map = pids_in_use[pid]; + assert(map != NULL); + pids_in_use[pid] = PMAP_NULL; + map->pid = -1; + + if (!locked) simple_unlock(&tlbpid_lock); +} + +#if 1 /* DEBUG */ + +print_pv_list() +{ + pv_entry_t p; + vm_offset_t phys; + + db_printf("phys pages %x < p < %x\n", vm_first_phys, vm_last_phys); + for (phys = vm_first_phys; phys < vm_last_phys; phys += PAGE_SIZE) { + p = pai_to_pvh(pa_index(phys)); + if (p->pmap != PMAP_NULL) { + db_printf("%x: %x %x\n", phys, p->pmap, p->va); + while (p = p->next) + db_printf("\t\t%x %x\n", p->pmap, p->va); } - ptpa = pmap_extract(pmap_kernel(), va); - /* - * Mark the page clean now to avoid its pageout (and - * hence creation of a pager) between now and when it - * is wired; i.e. while it is on a paging queue. - */ - PHYS_TO_VM_PAGE(ptpa)->flags |= PG_CLEAN; -#ifdef DEBUG - PHYS_TO_VM_PAGE(ptpa)->flags |= PG_PTPAGE; -#endif - } - /* - * Locate the PV entry in the kernel for this PT page and - * record the STE address. This is so that we can invalidate - * the STE when we remove the mapping for the page. - */ - pv = pa_to_pvh(ptpa); - s = splimp(); - if (pv) { - pv->pv_flags |= PV_PTPAGE; - do { - if (pv->pv_pmap == pmap_kernel() && pv->pv_va == va) - break; - } while (pv = pv->pv_next); } -#ifdef DEBUG - if (pv == NULL) - panic("pmap_enter_ptpage: PT page not entered"); -#endif - pv->pv_ptpte = ste; - pv->pv_ptpmap = pmap; -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) - printf("enter: new PT page at PA %lx, ste at %lx\n", ptpa, ste); -#endif +} - /* - * Map the new PT page into the segment table. - * Reference count on the user segment tables incremented above - * to prevent race conditions. Note that we don't use vm_map_pageable - * to keep the count like we do for PT pages, this is mostly because - * it would be difficult to identify ST pages in pmap_pageable to - * release them. We also avoid the overhead of vm_map_pageable. - */ - *ste = ((ptpa >> PGSHIFT) << PG_SHIFT) | PG_KRE | PG_KWE | PG_V | - (pmap == pmap_kernel() ? PG_ASM : 0); - if (pmap != pmap_kernel()) { -#ifdef DEBUG - if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB)) - printf("enter: stab %lx refcnt %d\n", - pmap->pm_stab, pmap->pm_sref); #endif - } -#if 0 - /* - * Flush stale TLB info. - */ - if (pmap == pmap_kernel()) - TBIAS(); - else - TBIAU(); -#endif - pmap->pm_ptpages++; - splx(s); + +vm_offset_t +pmap_phys_address(ppn) + int ppn; +{ + return(alpha_ptob(ppn)); +} + +void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) + pmap_t dst_pmap; + pmap_t src_pmap; + vm_offset_t dst_addr; + vm_size_t len; + vm_offset_t src_addr; +{ +} + +void pmap_update() +{ +} + +vm_page_t +vm_page_grab() +{ + register vm_page_t mem; + int spl; + + spl = splimp(); /* XXX */ + simple_lock(&vm_page_queue_free_lock); + if (vm_page_queue_free.tqh_first == NULL) { + simple_unlock(&vm_page_queue_free_lock); + splx(spl); + return (NULL); + } + + mem = vm_page_queue_free.tqh_first; + TAILQ_REMOVE(&vm_page_queue_free, mem, pageq); + + cnt.v_free_count--; + simple_unlock(&vm_page_queue_free_lock); + splx(spl); + + mem->flags = PG_BUSY | PG_CLEAN | PG_FAKE; + mem->wire_count = 0; + + /* + * Decide if we should poke the pageout daemon. + * We do this if the free count is less than the low + * water mark, or if the free count is less than the high + * water mark (but above the low water mark) and the inactive + * count is less than its target. + * + * We don't have the counts locked ... if they change a little, + * it doesn't really matter. + */ + + if (cnt.v_free_count < cnt.v_free_min || + (cnt.v_free_count < cnt.v_free_target && + cnt.v_inactive_count < cnt.v_inactive_target)) + thread_wakeup((void *)&vm_pages_needed); + return (mem); +} + +int +vm_page_wait() +{ + + assert_wait(&cnt.v_free_count, 0); + thread_block(); } /* @@ -2119,146 +3201,120 @@ pmap_enter_ptpage(pmap, va) */ void pmap_emulate_reference(p, v, user, write) - struct proc *p; - vm_offset_t v; - int user; - int write; + struct proc *p; + vm_offset_t v; + int user; + int write; { - pt_entry_t faultoff, *pte; - vm_offset_t pa; - char attr; - -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("pmap_emulate_reference: 0x%lx, 0x%lx, %d, %d\n", - p, v, user, write); -#endif + /* XXX */ +} - /* - * 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 = kvtopte(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_pte(&p->p_vmspace->vm_pmap, v); - } -#ifdef DEBUG - if (pmapdebug & PDB_FOLLOW) { - printf("\tpte = 0x%lx, ", pte); - printf("*pte = 0x%lx\n", *pte); - } -#endif -#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"); +struct pv_page; + +struct pv_page_info { + TAILQ_ENTRY(pv_page) pgi_list; + struct pv_entry *pgi_freelist; + int pgi_nfree; +}; + +#define NPVPPG ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry)) + +struct pv_page { + struct pv_page_info pvp_pgi; + struct pv_entry pvp_pv[NPVPPG]; +}; + +TAILQ_HEAD(pv_page_list, pv_page) pv_page_freelist; +int pv_nfree; + +#define pv_next next + +struct pv_entry * +pmap_alloc_pv() +{ + struct pv_page *pvp; + struct pv_entry *pv; + int i; + + if (pv_nfree == 0) { + pvp = (struct pv_page *)kmem_alloc(kernel_map, NBPG); + if (pvp == 0) + panic("pmap_alloc_pv: kmem_alloc() failed"); + pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[1]; + for (i = NPVPPG - 2; i; i--, pv++) + pv->pv_next = pv + 1; + pv->pv_next = 0; + pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG - 1; + TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + pv = &pvp->pvp_pv[0]; } 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 DEBUG - if (pmapdebug & PDB_FOLLOW) - printf("\tpa = 0x%lx\n", pa); -#endif + --pv_nfree; + pvp = pv_page_freelist.tqh_first; + if (--pvp->pvp_pgi.pgi_nfree == 0) { + TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + } + pv = pvp->pvp_pgi.pgi_freelist; #ifdef DIAGNOSTIC - if (!PAGE_IS_MANAGED(pa)) - printf("WARNING: pmap_emulate_reference(0x%lx, 0x%lx, %d, %d): pa 0x%lx not managed\n", 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. - */ - attr = PMAP_ATTR_REF; - faultoff = PG_FOR | PG_FOE; - if (write) { - attr |= PMAP_ATTR_MOD; - faultoff |= PG_FOW; - } - pmap_attributes[pa_index(pa)] |= attr; - 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."); + if (pv == 0) + panic("pmap_alloc_pv: pgi_nfree inconsistent"); #endif - *pte &= ~faultoff; - TBIS((caddr_t)v); + pvp->pvp_pgi.pgi_freelist = pv->pv_next; } + return pv; } -#ifdef DEBUG -/* static */ void -pmap_pvdump(pa) - vm_offset_t pa; +pmap_free_pv(pv) + struct pv_entry *pv; { - register pv_entry_t pv; + register struct pv_page *pvp; + register int i; - printf("pa %lx", pa); - for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next) - printf(" -> pmap %lx, va %lx, stpte %lx, ptpmap %lx, flags %lx", - pv->pv_pmap, pv->pv_va, pv->pv_ptpte, pv->pv_ptpmap, - pv->pv_flags); - printf("\n"); + pvp = (struct pv_page *) trunc_page(pv); + switch (++pvp->pvp_pgi.pgi_nfree) { + case 1: + TAILQ_INSERT_TAIL(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + default: + pv->pv_next = pvp->pvp_pgi.pgi_freelist; + pvp->pvp_pgi.pgi_freelist = pv; + ++pv_nfree; + break; + case NPVPPG: + pv_nfree -= NPVPPG - 1; + TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + kmem_free(kernel_map, (vm_offset_t)pvp, NBPG); + break; + } } -/* static */ -void -pmap_check_wiring(str, va) - char *str; - vm_offset_t va; +#if 0 +sanity(pmap, addr) + register pmap_t pmap; + register vm_offset_t addr; { - vm_map_entry_t entry; - pt_entry_t *pte; - register int count; + register pt_entry_t *ptp; + register pt_entry_t pte; + + printf("checking dirbase...\n"); + assert(pmap->dirbase != 0); + printf("checking dirpfn...\n"); + assert(pmap->dirpfn == curproc->p_addr->u_pcb.pcb_hw.apcb_ptbr); + printf("checking pid...\n"); + assert(pmap->pid == curproc->p_addr->u_pcb.pcb_hw.apcb_asn); - va = trunc_page(va); - if (!pmap_ste_v(pmap_kernel(), va) || - !pmap_pte_v(pmap_pte(pmap_kernel(), va))) - return; + + /* seg1 */ + pte = *pmap_pde(pmap,addr); + if ((pte & ALPHA_PTE_VALID) == 0) + return(PT_ENTRY_NULL); + /* seg2 */ + ptp = (pt_entry_t *)ptetokv(pte); + pte = ptp[pte2num(addr)]; + if ((pte & ALPHA_PTE_VALID) == 0) + return(PT_ENTRY_NULL); + /* seg3 */ + ptp = (pt_entry_t *)ptetokv(pte); + return(&ptp[pte3num(addr)]); - if (!vm_map_lookup_entry(pt_map, va, &entry)) { - printf("wired_check: entry for %lx not found\n", va); - return; - } - count = 0; - for (pte = (pt_entry_t *)va; pte < (pt_entry_t *)(va+PAGE_SIZE); pte++) - if (*pte) - count++; - if (entry->wired_count != count) - printf("*%s*: %lx: w%d/a%d\n", - str, va, entry->wired_count, count); } #endif diff --git a/sys/arch/alpha/alpha/pmap.old.c b/sys/arch/alpha/alpha/pmap.old.c new file mode 100644 index 00000000000..28335634806 --- /dev/null +++ b/sys/arch/alpha/alpha/pmap.old.c @@ -0,0 +1,2283 @@ +/* $OpenBSD: pmap.old.c,v 1.1 1996/10/30 22:38:22 niklas Exp $ */ +/* $NetBSD: pmap.old.c,v 1.13 1996/10/13 02:59:44 christos Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + * + * @(#)pmap.c 8.6 (Berkeley) 5/27/94 + */ + +#ifdef XXX +/* + * HP9000/300 series physical map management code. + * + * Supports: + * 68020 with HP MMU models 320, 350 + * 68020 with 68551 MMU models 318, 319, 330 (all untested) + * 68030 with on-chip MMU models 340, 360, 370, 345, 375, 400 + * 68040 with on-chip MMU models 380, 425, 433 + * + * Notes: + * Don't even pay lip service to multiprocessor support. + * + * We assume TLB entries don't have process tags (except for the + * supervisor/user distinction) so we only invalidate TLB entries + * when changing mappings for the current (or kernel) pmap. This is + * technically not true for the 68551 but we flush the TLB on every + * context switch, so it effectively winds up that way. + * + * Bitwise and/or operations are significantly faster than bitfield + * references so we use them when accessing STE/PTEs in the pmap_pte_* + * macros. Note also that the two are not always equivalent; e.g.: + * (*(int *)pte & PG_PROT) [4] != pte->pg_prot [1] + * and a couple of routines that deal with protection and wiring take + * some shortcuts that assume the and/or definitions. + * + * This implementation will only work for PAGE_SIZE == NBPG + * (i.e. 4096 bytes). + */ +#endif + +/* + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/user.h> +#include <sys/buf.h> +#ifdef SYSVSHM +#include <sys/shm.h> +#endif + +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> + +#include <machine/cpu.h> + +#ifdef PMAPSTATS +struct { + int collectscans; + int collectpages; + int kpttotal; + int kptinuse; + int kptmaxuse; +} kpt_stats; +struct { + int kernel; /* entering kernel mapping */ + int user; /* entering user mapping */ + int ptpneeded; /* needed to allocate a PT page */ + int nochange; /* no change at all */ + int pwchange; /* no mapping change, just wiring or protection */ + int wchange; /* no mapping change, just wiring */ + int pchange; /* no mapping change, just protection */ + int mchange; /* was mapped but mapping to different page */ + int managed; /* a managed page */ + int firstpv; /* first mapping for this PA */ + int secondpv; /* second mapping for this PA */ + int ci; /* cache inhibited */ + int unmanaged; /* not a managed page */ + int flushes; /* cache flushes */ +} enter_stats; +struct { + int calls; + int removes; + int pvfirst; + int pvsearch; + int ptinvalid; + int uflushes; + int sflushes; +} remove_stats; +struct { + int calls; + int changed; + int alreadyro; + int alreadyrw; +} protect_stats; +struct chgstats { + int setcalls; + int sethits; + int setmiss; + int clrcalls; + int clrhits; + int clrmiss; +} changebit_stats[16]; +#endif + +#ifdef DEBUG +#define PDB_FOLLOW 0x0001 +#define PDB_INIT 0x0002 +#define PDB_ENTER 0x0004 +#define PDB_REMOVE 0x0008 +#define PDB_CREATE 0x0010 +#define PDB_PTPAGE 0x0020 +#define PDB_CACHE 0x0040 +#define PDB_BITS 0x0080 +#define PDB_COLLECT 0x0100 +#define PDB_PROTECT 0x0200 +#define PDB_SEGTAB 0x0400 +#define PDB_MULTIMAP 0x0800 +#define PDB_BOOTSTRAP 0x1000 +#define PDB_PARANOIA 0x2000 +#define PDB_WIRING 0x4000 +#define PDB_PVDUMP 0x8000 + +int debugmap = 0; +int pmapdebug = PDB_PARANOIA; +extern vm_offset_t pager_sva, pager_eva; +#endif + +/* + * Get STEs and PTEs for user/kernel address space + */ +#define pmap_ste(m, v) (&((m)->pm_stab[vatoste((vm_offset_t)(v))])) +#define pmap_ste_v(m, v) (*pmap_ste(m, v) & PG_V) + +#define pmap_pte(m, v) \ + (&((m)->pm_ptab[NPTEPG * vatoste((vm_offset_t)(v)) + \ + vatopte((vm_offset_t)(v))])) +#define pmap_pte_pa(pte) (PG_PFNUM(*(pte)) << PGSHIFT) +#define pmap_pte_prot(pte) (*(pte) & PG_PROT) +#define pmap_pte_w(pte) (*(pte) & PG_WIRED) +#define pmap_pte_v(pte) (*(pte) & PG_V) + +#define pmap_pte_set_w(pte, v) \ + if (v) *(u_long *)(pte) |= PG_WIRED; else *(u_long *)(pte) &= ~PG_WIRED +#define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte)) + +#define pmap_pte_set_prot(pte, np) { *(pte) &= ~PG_PROT ; *(pte) |= (np); } +#define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte)) + + +/* + * Given a map and a machine independent protection code, + * convert to an hp300 protection code. + */ +#define pte_prot(m, p) (protection_codes[m == pmap_kernel() ? 0 : 1][p]) +int protection_codes[2][8]; + +/* + * Kernel page table page management. + */ +struct kpt_page { + struct kpt_page *kpt_next; /* link on either used or free list */ + vm_offset_t kpt_va; /* always valid kernel VA */ + vm_offset_t kpt_pa; /* PA of this page (for speed) */ +}; +struct kpt_page *kpt_free_list, *kpt_used_list; +struct kpt_page *kpt_pages; + +/* + * The Alpha's level-1 page table. + */ +pt_entry_t *Lev1map; + +/* + * Kernel segment/page table and page table map. + * The page table map gives us a level of indirection we need to dynamically + * expand the page table. It is essentially a copy of the segment table + * with PTEs instead of STEs. All are initialized in locore at boot time. + * Segtabzero is an empty segment table which all processes share til they + * reference something. + */ +pt_entry_t *Sysptmap; +pt_entry_t *Sysmap; +vm_size_t Sysptmapsize, Sysmapsize; +pt_entry_t *Segtabzero, Segtabzeropte; + +struct pmap kernel_pmap_store; +vm_map_t st_map, pt_map; + +vm_offset_t avail_start; /* PA of first available physical page */ +vm_offset_t avail_end; /* PA of last available physical page */ +vm_size_t mem_size; /* memory size in bytes */ +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) */ +vm_offset_t vm_first_phys; /* PA of first managed page */ +vm_offset_t vm_last_phys; /* PA just past last managed page */ +boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */ +char *pmap_attributes; /* reference and modify bits */ + +/* + * Internal routines + */ +void alpha_protection_init __P((void)); +void pmap_remove_mapping __P((pmap_t, vm_offset_t, pt_entry_t *, int)); +void pmap_changebit __P((vm_offset_t, u_long, boolean_t)); +void pmap_enter_ptpage __P((pmap_t, vm_offset_t)); +#ifdef DEBUG +void pmap_pvdump __P((vm_offset_t)); +void pmap_check_wiring __P((char *, vm_offset_t)); +#endif + +#define PAGE_IS_MANAGED(pa) ((pa) >= vm_first_phys && (pa) < vm_last_phys) + +/* pmap_remove_mapping flags */ +#define PRM_TFLUSH 1 +#define PRM_CFLUSH 2 + +/* + * pmap_bootstrap: + * Bootstrap the system to run with virtual memory. + * firstaddr is the first unused kseg0 address (not page aligned). + */ +void +pmap_bootstrap(firstaddr, ptaddr) + vm_offset_t firstaddr; + vm_offset_t ptaddr; +{ + register int i; + vm_offset_t start; + pt_entry_t pte; + extern int firstusablepage, lastusablepage; + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_BOOTSTRAP)) + printf("pmap_bootstrap(0x%lx, 0x%lx)\n", firstaddr, ptaddr); +#endif + + /* must be page aligned */ + start = firstaddr = alpha_round_page(firstaddr); + +#define valloc(name, type, num) \ + (name) = (type *)firstaddr; \ + firstaddr = ALIGN((vm_offset_t)((name)+(num))) + + /* + * Allocate an empty prototype segment map for processes. + * This will be used until processes get their own. + */ + valloc(Segtabzero, pt_entry_t, NPTEPG); + Segtabzeropte = (ALPHA_K0SEG_TO_PHYS((vm_offset_t)Segtabzero) >> PGSHIFT) << PG_SHIFT; + Segtabzeropte |= PG_V | PG_KRE | PG_KWE | PG_WIRED; + + /* + * Figure out how many PTE's are necessary to map the kernel. + * The '512' comes from PAGER_MAP_SIZE in vm_pager_init(). + * This should be kept in sync. + * We also reserve space for kmem_alloc_pageable() for vm_fork(). + */ + Sysmapsize = (VM_KMEM_SIZE + VM_MBUF_SIZE + VM_PHYS_SIZE + + nbuf * MAXBSIZE + 16 * NCARGS) / NBPG + 512 + 256; + Sysmapsize += maxproc * (btoc(ALPHA_STSIZE) + btoc(ALPHA_MAX_PTSIZE)); + +#ifdef SYSVSHM + Sysmapsize += shminfo.shmall; +#endif + Sysmapsize = roundup(Sysmapsize, NPTEPG); + + /* + * Allocate a level 1 PTE table for the kernel. + * This is always one page long. + * IF THIS IS NOT A MULTIPLE OF NBPG, ALL WILL GO TO HELL. + */ + valloc(Lev1map, pt_entry_t, NPTEPG); + + /* + * Allocate a level 2 PTE table for the kernel. + * These must map all of the level3 PTEs. + * IF THIS IS NOT A MULTIPLE OF NBPG, ALL WILL GO TO HELL. + */ + Sysptmapsize = roundup(howmany(Sysmapsize, NPTEPG), NPTEPG); + valloc(Sysptmap, pt_entry_t, Sysptmapsize); + pmap_kernel()->pm_stab = Sysptmap; + + /* + * Allocate a level 3 PTE table for the kernel. + * Contains Sysmapsize PTEs. + */ + valloc(Sysmap, pt_entry_t, Sysmapsize); + pmap_kernel()->pm_ptab = Sysmap; + + /* + * Allocate memory for page attributes. + * allocates a few more entries than we need, but that's safe. + */ + valloc(pmap_attributes, char, 1 + lastusablepage - firstusablepage); + + /* + * Allocate memory for pv_table. + * This will allocate more entries than we really need. + * We could do this in pmap_init when we know the actual + * phys_start and phys_end but its better to use kseg0 addresses + * rather than kernel virtual addresses mapped through the TLB. + */ + i = 1 + lastusablepage - alpha_btop(ALPHA_K0SEG_TO_PHYS(firstaddr)); + valloc(pv_table, struct pv_entry, i); + + /* + * Clear allocated memory. + */ + firstaddr = alpha_round_page(firstaddr); + bzero((caddr_t)start, firstaddr - start); + + /* + * Set up level 1 page table + */ + + /* First, copy mappings for things below VM_MIN_KERNEL_ADDRESS */ + bcopy((caddr_t)ptaddr, Lev1map, + kvtol1pte(VM_MIN_KERNEL_ADDRESS) * sizeof Lev1map[0]); + + /* Second, map all of the level 2 pte pages */ + for (i = 0; i < howmany(Sysptmapsize, NPTEPG); i++) { + pte = (ALPHA_K0SEG_TO_PHYS(((vm_offset_t)Sysptmap) + (i*PAGE_SIZE)) >> PGSHIFT) + << PG_SHIFT; + pte |= PG_V | PG_ASM | PG_KRE | PG_KWE | PG_WIRED; + Lev1map[kvtol1pte(VM_MIN_KERNEL_ADDRESS + + (i*PAGE_SIZE*NPTEPG*NPTEPG))] = pte; + } + + /* Finally, map the virtual page table */ + pte = (ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map) >> PGSHIFT) << PG_SHIFT; + pte |= PG_V | PG_KRE | PG_KWE; /* NOTE NO ASM */ + Lev1map[kvtol1pte(VPTBASE)] = pte; + + /* + * Set up level 2 page table. + */ + /* Map all of the level 3 pte pages */ + for (i = 0; i < howmany(Sysmapsize, NPTEPG); i++) { + pte = (ALPHA_K0SEG_TO_PHYS(((vm_offset_t)Sysmap)+(i*PAGE_SIZE)) >> PGSHIFT) + << PG_SHIFT; + pte |= PG_V | PG_ASM | PG_KRE | PG_KWE | PG_WIRED; + Sysptmap[vatoste(VM_MIN_KERNEL_ADDRESS+ + (i*PAGE_SIZE*NPTEPG))] = pte; + } + + /* + * Set up level three page table (Sysmap) + */ + /* Nothing to do; it's already zero'd */ + + avail_start = ALPHA_K0SEG_TO_PHYS(firstaddr); +#if 1 + avail_end = alpha_ptob(lastusablepage + 1); + mem_size = avail_end - avail_start; +#else + /* XXX why not lastusablepage + 1, & not include NBPG in mem_size? */ + avail_end = alpha_ptob(lastusablepage); + mem_size = NBPG + avail_end - avail_start; +#endif +#if 0 + printf("avail_start = 0x%lx\n", avail_start); + printf("avail_end = 0x%lx\n", avail_end); + printf("mem_size = 0x%lx\n", mem_size); +#endif + + virtual_avail = VM_MIN_KERNEL_ADDRESS; + virtual_end = VM_MIN_KERNEL_ADDRESS + Sysmapsize * NBPG; + + simple_lock_init(&pmap_kernel()->pm_lock); + pmap_kernel()->pm_count = 1; + + /* + * Set up curproc's (i.e. proc 0's) PCB such that the ptbr + * points to the right place. + */ + curproc->p_addr->u_pcb.pcb_hw.apcb_ptbr = ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map) >> PGSHIFT; +} + +/* + * Unmap the PROM mappings. PROM mappings are kept around + * by pmap_bootstrap, so we can still use the prom's printf. + * Basically, blow away all mappings in the level one PTE + * table below VM_MIN_KERNEL_ADDRESS. The Virtual Page Table + * Is at the end of virtual space, so it's safe. + */ +void +pmap_unmap_prom() +{ + extern int prom_mapped; + extern pt_entry_t *rom_ptep, rom_pte; + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_BOOTSTRAP)) + printf("pmap_unmap_prom\n"); +#endif + + /* XXX save old pte so that we can remap prom if necessary */ + rom_ptep = &Lev1map[0]; /* XXX */ + rom_pte = *rom_ptep & ~PG_ASM; /* XXX */ + + /* Mark all mappings before VM_MIN_KERNEL_ADDRESS as invalid. */ + bzero(Lev1map, kvtol1pte(VM_MIN_KERNEL_ADDRESS) * sizeof Lev1map[0]); + prom_mapped = 0; + ALPHA_TBIA(); +} + +/* + * Bootstrap memory allocator. This function allows for early dynamic + * memory allocation until the virtual memory system has been bootstrapped. + * After that point, either kmem_alloc or malloc should be used. This + * function works by stealing pages from the (to be) managed page pool, + * stealing virtual address space, then implicitly mapping the pages + * (by using their k0seg addresses) and zeroing them. + * + * It should be used from pmap_bootstrap till vm_page_startup, afterwards + * it cannot be used, and will generate a panic if tried. Note that this + * memory will never be freed, and in essence it is wired down. + */ +void * +pmap_bootstrap_alloc(size) + int size; +{ + vm_offset_t val; + extern boolean_t vm_page_startup_initialized; + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_BOOTSTRAP)) + printf("pmap_bootstrap_alloc(%lx)\n", size); +#endif + if (vm_page_startup_initialized) + panic("pmap_bootstrap_alloc: called after startup initialized"); + + val = ALPHA_PHYS_TO_K0SEG(avail_start); + size = round_page(size); + avail_start += size; + + bzero((caddr_t)val, size); + return ((void *)val); +} + +/* + * Initialize the pmap module. + * Called by vm_init, to initialize any structures that the pmap + * system needs to map virtual memory. + */ +void +pmap_init(phys_start, phys_end) + vm_offset_t phys_start, phys_end; +{ + vm_offset_t addr, addr2; + vm_size_t s; + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_init(%x, %x)\n", phys_start, phys_end); +#endif + + /* initialize protection array */ + alpha_protection_init(); + + /* + * Allocate the segment table map + */ + s = maxproc * ALPHA_STSIZE; + st_map = kmem_suballoc(kernel_map, &addr, &addr2, s, TRUE); + + /* + * Allocate the page table map + */ + s = maxproc * ALPHA_MAX_PTSIZE; /* XXX limit it */ + pt_map = kmem_suballoc(kernel_map, &addr, &addr2, s, TRUE); + + /* + * Now it is safe to enable pv_table recording. + */ + vm_first_phys = phys_start; + vm_last_phys = phys_end; +#if 0 + printf("vm_first_phys = 0x%lx\n", vm_first_phys); + printf("vm_last_phys = 0x%lx\n", vm_last_phys); +#endif + pmap_initialized = TRUE; +} + +/* + * 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; +{ +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_map(%lx, %lx, %lx, %lx)\n", virt, start, end, prot); +#endif + while (start < end) { + pmap_enter(pmap_kernel(), virt, start, prot, FALSE); + virt += PAGE_SIZE; + start += PAGE_SIZE; + } + return(virt); +} + +/* + * Create and return a physical map. + * + * If the size specified for the map + * is zero, the map is an actual physical + * map, and may be referenced by the + * hardware. + * + * If the size specified is non-zero, + * the map will be used in software only, and + * is bounded by that size. + */ +pmap_t +pmap_create(size) + vm_size_t size; +{ + register pmap_t pmap; + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) + printf("pmap_create(%lx)\n", size); +#endif + /* + * Software use map does not need a pmap + */ + if (size) + return(NULL); + + /* XXX: is it ok to wait here? */ + pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK); +#ifdef notifwewait + if (pmap == NULL) + panic("pmap_create: cannot allocate a pmap"); +#endif + bzero(pmap, sizeof(*pmap)); + pmap_pinit(pmap); + return (pmap); +} + +/* + * Initialize a preallocated and zeroed pmap structure, + * such as one in a vmspace structure. + */ +void +pmap_pinit(pmap) + register struct pmap *pmap; +{ + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) + printf("pmap_pinit(%lx)\n", pmap); +#endif + /* + * No need to allocate page table space yet but we do need a + * valid segment table. Initially, we point everyone at the + * "null" segment table. On the first pmap_enter, a real + * segment table will be allocated. + */ + pmap->pm_stab = Segtabzero; + pmap->pm_stpte = Segtabzeropte; + pmap->pm_stchanged = TRUE; + pmap->pm_count = 1; + simple_lock_init(&pmap->pm_lock); +} + +/* + * Retire the given physical map from service. + * Should only be called if the map contains + * no valid mappings. + */ +void +pmap_destroy(pmap) + register pmap_t pmap; +{ + int count; + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_destroy(%lx)\n", pmap); +#endif + if (pmap == NULL) + return; + + simple_lock(&pmap->pm_lock); + count = --pmap->pm_count; + simple_unlock(&pmap->pm_lock); + if (count == 0) { + pmap_release(pmap); + free((caddr_t)pmap, M_VMPMAP); + } +} + +/* + * 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) + register struct pmap *pmap; +{ + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_release(%lx)\n", pmap); +#endif +#ifdef notdef /* DIAGNOSTIC */ + /* count would be 0 from pmap_destroy... */ + simple_lock(&pmap->pm_lock); + if (pmap->pm_count != 1) + panic("pmap_release count"); +#endif + if (pmap->pm_ptab) + kmem_free_wakeup(pt_map, (vm_offset_t)pmap->pm_ptab, + ALPHA_MAX_PTSIZE); + if (pmap->pm_stab != Segtabzero) + kmem_free_wakeup(st_map, (vm_offset_t)pmap->pm_stab, + ALPHA_STSIZE); +} + +/* + * Add a reference to the specified pmap. + */ +void +pmap_reference(pmap) + pmap_t pmap; +{ +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_reference(%lx)\n", pmap); +#endif + if (pmap != NULL) { + simple_lock(&pmap->pm_lock); + pmap->pm_count++; + simple_unlock(&pmap->pm_lock); + } +} + +/* + * 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, sva, eva) + register pmap_t pmap; + register vm_offset_t sva, eva; +{ + register vm_offset_t nssva; + register pt_entry_t *pte; + boolean_t firstpage, needcflush; + int flags; + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) + printf("pmap_remove(%lx, %lx, %lx)\n", pmap, sva, eva); +#endif + + if (pmap == NULL) + return; + +#ifdef PMAPSTATS + remove_stats.calls++; +#endif + firstpage = TRUE; + needcflush = FALSE; + flags = active_pmap(pmap) ? PRM_TFLUSH : 0; + while (sva < eva) { + nssva = alpha_trunc_seg(sva) + ALPHA_SEG_SIZE; + if (nssva == 0 || nssva > eva) + nssva = eva; + /* + * If VA belongs to an unallocated segment, + * skip to the next segment boundary. + */ + if (!pmap_ste_v(pmap, sva)) { + sva = nssva; + continue; + } + /* + * Invalidate every valid mapping within this segment. + */ + pte = pmap_pte(pmap, sva); + while (sva < nssva) { + if (pmap_pte_v(pte)) { + pmap_remove_mapping(pmap, sva, pte, flags); + firstpage = FALSE; + } + pte++; + sva += PAGE_SIZE; + } + } + /* + * Didn't do anything, no need for cache flushes + */ + if (firstpage) + return; +} + +/* + * pmap_page_protect: + * + * Lower the permission for all mappings to a given page. + */ +void +pmap_page_protect(pa, prot) + vm_offset_t pa; + vm_prot_t prot; +{ + register pv_entry_t pv; + int s; + +#ifdef DEBUG + if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) || + (prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE))) + printf("pmap_page_protect(%lx, %lx)\n", pa, prot); +#endif + if (!PAGE_IS_MANAGED(pa)) + return; + + switch (prot) { + case VM_PROT_READ|VM_PROT_WRITE: + case VM_PROT_ALL: + return; + /* copy_on_write */ + case VM_PROT_READ: + case VM_PROT_READ|VM_PROT_EXECUTE: +/* XXX */ pmap_changebit(pa, PG_KWE | PG_UWE, FALSE); + return; + /* remove_all */ + default: + break; + } + pv = pa_to_pvh(pa); + s = splimp(); + while (pv->pv_pmap != NULL) { + register pt_entry_t *pte; + + pte = pmap_pte(pv->pv_pmap, pv->pv_va); +#ifdef DEBUG + if (!pmap_ste_v(pv->pv_pmap, pv->pv_va) || + pmap_pte_pa(pte) != pa) + panic("pmap_page_protect: bad mapping"); +#endif + if (!pmap_pte_w(pte)) + pmap_remove_mapping(pv->pv_pmap, pv->pv_va, + pte, PRM_TFLUSH|PRM_CFLUSH); + else { + pv = pv->pv_next; +#ifdef DEBUG + if (pmapdebug & PDB_PARANOIA) + printf("%s wired mapping for %lx not removed\n", + "pmap_page_protect:", pa); +#endif + } + } + splx(s); +} + +/* + * Set the physical protection on the + * specified range of this map as requested. + */ +void +pmap_protect(pmap, sva, eva, prot) + register pmap_t pmap; + register vm_offset_t sva, eva; + vm_prot_t prot; +{ + register vm_offset_t nssva; + register pt_entry_t *pte, bits; + boolean_t firstpage, needtflush; + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) + printf("pmap_protect(%lx, %lx, %lx, %lx)\n", pmap, sva, eva, prot); +#endif + + if (pmap == NULL) + return; + +#ifdef PMAPSTATS + protect_stats.calls++; +#endif + if ((prot & VM_PROT_READ) == VM_PROT_NONE) { + pmap_remove(pmap, sva, eva); + return; + } + if (prot & VM_PROT_WRITE) + return; + + bits = pte_prot(pmap, prot); + needtflush = active_pmap(pmap); + firstpage = TRUE; + while (sva < eva) { + nssva = alpha_trunc_seg(sva) + ALPHA_SEG_SIZE; + if (nssva == 0 || nssva > eva) + nssva = eva; + /* + * If VA belongs to an unallocated segment, + * skip to the next segment boundary. + */ + if (!pmap_ste_v(pmap, sva)) { + sva = nssva; + continue; + } + /* + * Change protection on mapping if it is valid and doesn't + * already have the correct protection. + */ + pte = pmap_pte(pmap, sva); + while (sva < nssva) { + if (pmap_pte_v(pte) && pmap_pte_prot_chg(pte, bits)) { + pmap_pte_set_prot(pte, bits); + if (needtflush) + ALPHA_TBIS(sva); +#ifdef PMAPSTATS + protect_stats.changed++; +#endif + firstpage = FALSE; + } +#ifdef PMAPSTATS + else if (pmap_pte_v(pte)) { + if (isro) + protect_stats.alreadyro++; + else + protect_stats.alreadyrw++; + } +#endif + pte++; + 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, va, pa, prot, wired) + register pmap_t pmap; + vm_offset_t va; + register vm_offset_t pa; + vm_prot_t prot; + boolean_t wired; +{ + register pt_entry_t *pte; + register pt_entry_t npte; + vm_offset_t opa; + boolean_t checkpv = TRUE; + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_ENTER)) + printf("pmap_enter(%lx, %lx, %lx, %lx, %lx)\n", + pmap, va, pa, prot, wired); +#endif + if (pmap == NULL) + return; + +#ifdef PMAPSTATS + if (pmap == pmap_kernel()) + enter_stats.kernel++; + else + enter_stats.user++; +#endif + /* + * For user mapping, allocate kernel VM resources if necessary. + */ + if (pmap->pm_ptab == NULL) + pmap->pm_ptab = (pt_entry_t *) + kmem_alloc_wait(pt_map, ALPHA_MAX_PTSIZE); + /* + * Segment table entry not valid, we need a new PT page + */ + if (!pmap_ste_v(pmap, va)) + pmap_enter_ptpage(pmap, va); + + pa = alpha_trunc_page(pa); + pte = pmap_pte(pmap, va); + opa = pmap_pte_pa(pte); +#ifdef DEBUG + if (pmapdebug & PDB_ENTER) + printf("enter: pte %lx, *pte %lx\n", pte, *pte); +#endif + + /* + * Mapping has not changed, must be protection or wiring change. + */ + if (opa == pa) { +#ifdef PMAPSTATS + enter_stats.pwchange++; +#endif + /* + * 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 (pmap_pte_w_chg(pte, wired ? PG_WIRED : 0)) { +#ifdef DEBUG + if (pmapdebug & PDB_ENTER) + printf("enter: wiring change -> %lx\n", wired); +#endif + if (wired) + pmap->pm_stats.wired_count++; + else + pmap->pm_stats.wired_count--; +#ifdef PMAPSTATS + if (pmap_pte_prot(pte) == pte_prot(pmap, prot)) + enter_stats.wchange++; +#endif + } +#ifdef PMAPSTATS + else if (pmap_pte_prot(pte) != pte_prot(pmap, prot)) + enter_stats.pchange++; + else + enter_stats.nochange++; +#endif + /* + * Retain cache inhibition status + */ + checkpv = FALSE; + goto validate; + } + + /* + * Mapping has changed, invalidate old range and fall through to + * handle validating new mapping. + */ + if (opa) { +#ifdef DEBUG + if (pmapdebug & PDB_ENTER) + printf("enter: removing old mapping %lx\n", va); +#endif + pmap_remove_mapping(pmap, va, pte, PRM_TFLUSH|PRM_CFLUSH); +#ifdef PMAPSTATS + enter_stats.mchange++; +#endif + } + + /* + * If this is a new user mapping, increment the wiring count + * on this PT page. PT pages are wired down as long as there + * is a valid mapping in the page. + */ + if (pmap != pmap_kernel()) + (void) vm_map_pageable(pt_map, trunc_page(pte), + round_page(pte+1), FALSE); + + /* + * 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 (PAGE_IS_MANAGED(pa)) { + register pv_entry_t pv, npv; + int s; + +#ifdef PMAPSTATS + enter_stats.managed++; +#endif + pv = pa_to_pvh(pa); + s = splimp(); +#ifdef DEBUG + if (pmapdebug & PDB_ENTER) + printf("enter: pv at %lx: %lx/%lx/%lx\n", + pv, pv->pv_va, pv->pv_pmap, pv->pv_next); +#endif + /* + * No entries yet, use header as the first entry + */ + if (pv->pv_pmap == NULL) { +#ifdef PMAPSTATS + enter_stats.firstpv++; +#endif + pv->pv_va = va; + pv->pv_pmap = pmap; + pv->pv_next = NULL; + pv->pv_ptpte = NULL; + pv->pv_ptpmap = NULL; + pv->pv_flags = 0; + } + /* + * There is at least one other VA mapping this page. + * Place this entry after the header. + */ + else { +#ifdef DEBUG + for (npv = pv; npv; npv = npv->pv_next) + if (pmap == npv->pv_pmap && va == npv->pv_va) + panic("pmap_enter: already in pv_tab"); +#endif + npv = (pv_entry_t) + malloc(sizeof *npv, M_VMPVENT, M_NOWAIT); + npv->pv_va = va; + npv->pv_pmap = pmap; + npv->pv_next = pv->pv_next; + npv->pv_ptpte = NULL; + npv->pv_ptpmap = NULL; + npv->pv_flags = 0; + pv->pv_next = npv; +#ifdef PMAPSTATS + if (!npv->pv_next) + enter_stats.secondpv++; +#endif + } + splx(s); + } + /* + * Assumption: if it is not part of our managed memory + * then it must be device memory which may be volitile. + */ + else if (pmap_initialized) { + checkpv = FALSE; +#ifdef PMAPSTATS + enter_stats.unmanaged++; +#endif + } + + /* + * Increment counters + */ + pmap->pm_stats.resident_count++; + if (wired) + pmap->pm_stats.wired_count++; + +validate: + /* + * Build the new PTE. + */ + npte = ((pa >> PGSHIFT) << PG_SHIFT) | pte_prot(pmap, prot) | PG_V; + if (PAGE_IS_MANAGED(pa)) { + if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_REF) == 0) + npte |= PG_FOR | PG_FOW | PG_FOE; + else if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_MOD) == 0) + npte |= PG_FOW; + } + if (wired) + npte |= PG_WIRED; +#ifdef DEBUG + if (pmapdebug & PDB_ENTER) + printf("enter: new pte value %lx\n", npte); +#endif + /* + * Remember if this was a wiring-only change. + * If so, we need not flush the TLB and caches. + */ + wired = ((*pte ^ npte) == PG_WIRED); + *pte = npte; + if (!wired && active_pmap(pmap)) + ALPHA_TBIS(va); +#ifdef DEBUG + if ((pmapdebug & PDB_WIRING) && pmap != pmap_kernel()) + pmap_check_wiring("enter", trunc_page(pmap_pte(pmap, va))); +#endif +} + +/* + * 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; +{ + register pt_entry_t *pte; + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_change_wiring(%lx, %lx, %lx)\n", pmap, va, wired); +#endif + if (pmap == NULL) + return; + + pte = pmap_pte(pmap, va); +#ifdef DEBUG + /* + * Page table page is not allocated. + * Should this ever happen? Ignore it for now, + * we don't want to force allocation of unnecessary PTE pages. + */ + if (!pmap_ste_v(pmap, va)) { + if (pmapdebug & PDB_PARANOIA) + printf("pmap_change_wiring: invalid STE for %lx\n", va); + return; + } + /* + * Page not valid. Should this ever happen? + * Just continue and change wiring anyway. + */ + if (!pmap_pte_v(pte)) { + if (pmapdebug & PDB_PARANOIA) + printf("pmap_change_wiring: invalid PTE for %lx\n", va); + } +#endif + /* + * If wiring actually changed (always?) set the wire bit and + * update the wire count. Note that wiring is not a hardware + * characteristic so there is no need to invalidate the TLB. + */ + if (pmap_pte_w_chg(pte, wired ? PG_WIRED : 0)) { + pmap_pte_set_w(pte, wired); + if (wired) + pmap->pm_stats.wired_count++; + else + pmap->pm_stats.wired_count--; + } +} + +/* + * 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; + register vm_offset_t pa; + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_extract(%lx, %lx) -> ", pmap, va); +#endif + pa = 0; + if (pmap && pmap_ste_v(pmap, va)) { + pte = *pmap_pte(pmap, va); + if (pte & PG_V) + pa = ctob(PG_PFNUM(pte)) | (va & PGOFSET); + } + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("%lx\n", pa); +#endif + return(pa); +} + +/* + * 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(dst_pmap, src_pmap, dst_addr, len, src_addr) + pmap_t dst_pmap; + pmap_t src_pmap; + vm_offset_t dst_addr; + vm_size_t len; + vm_offset_t src_addr; +{ +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_copy(%lx, %lx, %lx, %lx, %lx)\n", + dst_pmap, src_pmap, dst_addr, len, src_addr); +#endif +} + +/* + * Require that all active physical maps contain no + * incorrect entries NOW. [This update includes + * forcing updates of any address map caching.] + * + * Generally used to insure that a thread about + * to run will see a semantically correct world. + */ +void pmap_update() +{ +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_update()\n"); +#endif + ALPHA_TBIA(); +} + +/* + * Routine: pmap_collect + * Function: + * Garbage collects the physical map system for + * pages which are no longer used. + * Success need not be guaranteed -- that is, there + * may well be pages which are not referenced, but + * others may be collected. + * Usage: + * Called by the pageout daemon when pages are scarce. + */ +void +pmap_collect(pmap) + pmap_t pmap; +{ + register vm_offset_t pa; + register pv_entry_t pv; + register pt_entry_t *pte; + vm_offset_t kpa; + int s; + +#ifdef DEBUG + pt_entry_t *ste; + int opmapdebug; +#endif + if (pmap != pmap_kernel()) + return; + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_collect(%lx)\n", pmap); +#endif +#ifdef PMAPSTATS + kpt_stats.collectscans++; +#endif + s = splimp(); + for (pa = vm_first_phys; pa < vm_last_phys; pa += PAGE_SIZE) { + register struct kpt_page *kpt, **pkpt; + + /* + * Locate physical pages which are being used as kernel + * page table pages. + */ + pv = pa_to_pvh(pa); + if (pv->pv_pmap != pmap_kernel() || !(pv->pv_flags & PV_PTPAGE)) + continue; + do { + if (pv->pv_ptpte && pv->pv_ptpmap == pmap_kernel()) + break; + } while ((pv = pv->pv_next) != NULL); + if (pv == NULL) + continue; +#ifdef DEBUG + if (pv->pv_va < (vm_offset_t)Sysmap || + pv->pv_va >= (vm_offset_t)Sysmap + ALPHA_MAX_PTSIZE) + printf("collect: kernel PT VA out of range\n"); + else + goto ok; + pmap_pvdump(pa); + continue; +ok: +#endif + pte = (pt_entry_t *)(pv->pv_va + ALPHA_PAGE_SIZE); + while (--pte >= (pt_entry_t *)pv->pv_va && *pte == PG_NV) + ; + if (pte >= (pt_entry_t *)pv->pv_va) + continue; + +#ifdef DEBUG + if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) { + printf("collect: freeing KPT page at %lx (ste %lx@%lx)\n", + pv->pv_va, *pv->pv_ptpte, pv->pv_ptpte); + opmapdebug = pmapdebug; + pmapdebug |= PDB_PTPAGE; + } + + ste = pv->pv_ptpte; +#endif + /* + * If all entries were invalid we can remove the page. + * We call pmap_remove_entry to take care of invalidating + * ST and Sysptmap entries. + */ + kpa = pmap_extract(pmap, pv->pv_va); + pmap_remove_mapping(pmap, pv->pv_va, PT_ENTRY_NULL, + PRM_TFLUSH|PRM_CFLUSH); + /* + * Use the physical address to locate the original + * (kmem_alloc assigned) address for the page and put + * that page back on the free list. + */ + for (pkpt = &kpt_used_list, kpt = *pkpt; + kpt != (struct kpt_page *)0; + pkpt = &kpt->kpt_next, kpt = *pkpt) + if (kpt->kpt_pa == kpa) + break; +#ifdef DEBUG + if (kpt == (struct kpt_page *)0) + panic("pmap_collect: lost a KPT page"); + if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) + printf("collect: %lx (%lx) to free list\n", + kpt->kpt_va, kpa); +#endif + *pkpt = kpt->kpt_next; + kpt->kpt_next = kpt_free_list; + kpt_free_list = kpt; +#ifdef PMAPSTATS + kpt_stats.kptinuse--; + kpt_stats.collectpages++; +#endif +#ifdef DEBUG + if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) + pmapdebug = opmapdebug; + + if (*ste) + printf("collect: kernel STE at %lx still valid (%lx)\n", + ste, *ste); + ste = &Sysptmap[(pt_entry_t *)ste-pmap_ste(pmap_kernel(), 0)]; + if (*ste) + printf("collect: kernel PTmap at %lx still valid (%lx)\n", + ste, *ste); +#endif + } + splx(s); +} + +void +pmap_activate(pmap) + register pmap_t pmap; +{ + int iscurproc; + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_SEGTAB)) + printf("pmap_activate(%lx)\n", pmap); +#endif + + iscurproc = curproc != NULL && pmap == curproc->p_vmspace->vm_map.pmap; + PMAP_ACTIVATE(pmap, iscurproc); +} + +/* + * 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(phys) + vm_offset_t phys; +{ + caddr_t p; + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_zero_page(%lx)\n", phys); +#endif + p = (caddr_t)ALPHA_PHYS_TO_K0SEG(phys); + bzero(p, 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(src, dst) + vm_offset_t src, dst; +{ + caddr_t s, d; + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_copy_page(%lx, %lx)\n", src, dst); +#endif + s = (caddr_t)ALPHA_PHYS_TO_K0SEG(src); + d = (caddr_t)ALPHA_PHYS_TO_K0SEG(dst); + bcopy(s, d, 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; +{ +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_pageable(%lx, %lx, %lx, %lx)\n", + pmap, sva, eva, pageable); +#endif + /* + * If we are making a PT page pageable then all valid + * mappings must be gone from that page. Hence it should + * be all zeros and there is no need to clean it. + * Assumptions: + * - we are called with only one page at a time + * - PT pages have only one pv_table entry + */ + if (pmap == pmap_kernel() && pageable && sva + PAGE_SIZE == eva) { + register pv_entry_t pv; + register vm_offset_t pa; + +#ifdef DEBUG + if ((pmapdebug & (PDB_FOLLOW|PDB_PTPAGE)) == PDB_PTPAGE) + printf("pmap_pageable(%lx, %lx, %lx, %lx)\n", + pmap, sva, eva, pageable); +#endif + if (!pmap_ste_v(pmap, sva)) + return; + pa = pmap_pte_pa(pmap_pte(pmap, sva)); + if (!PAGE_IS_MANAGED(pa)) + return; + pv = pa_to_pvh(pa); + if (pv->pv_ptpte == NULL) + return; +#ifdef DEBUG + if (pv->pv_va != sva || pv->pv_next) { + printf("pmap_pageable: bad PT page va %lx next %lx\n", + pv->pv_va, pv->pv_next); + return; + } +#endif + /* + * Mark it unmodified to avoid pageout + */ + pmap_clear_modify(pa); +#ifdef DEBUG + if ((PHYS_TO_VM_PAGE(pa)->flags & PG_CLEAN) == 0) { + printf("pa %lx: flags=%lx: not clean\n", + pa, PHYS_TO_VM_PAGE(pa)->flags); + PHYS_TO_VM_PAGE(pa)->flags |= PG_CLEAN; + } + if (pmapdebug & PDB_PTPAGE) + printf("pmap_pageable: PT page %lx(%lx) unmodified\n", + sva, *pmap_pte(pmap, sva)); + if (pmapdebug & PDB_WIRING) + pmap_check_wiring("pageable", sva); +#endif + } +} + +/* + * Clear the modify bits on the specified physical page. + */ + +void +pmap_clear_modify(pa) + vm_offset_t pa; +{ +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_clear_modify(%lx)\n", pa); +#endif + if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */ + return; + if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_MOD) != 0) { + pmap_changebit(pa, PG_FOW, TRUE); + pmap_attributes[pa_index(pa)] &= ~PMAP_ATTR_MOD; + } +} + +/* + * pmap_clear_reference: + * + * Clear the reference bit on the specified physical page. + */ + +void pmap_clear_reference(pa) + vm_offset_t pa; +{ +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_clear_reference(%lx)\n", pa); +#endif + if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */ + return; + if ((pmap_attributes[pa_index(pa)] & PMAP_ATTR_REF) != 0) { + pmap_changebit(pa, PG_FOR | PG_FOW | PG_FOE, TRUE); + pmap_attributes[pa_index(pa)] &= ~PMAP_ATTR_REF; + } +} + +/* + * pmap_is_referenced: + * + * Return whether or not the specified physical page is referenced + * by any physical maps. + */ + +boolean_t +pmap_is_referenced(pa) + vm_offset_t pa; +{ + boolean_t rv; + + if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */ + return 0; + rv = (pmap_attributes[pa_index(pa)] & PMAP_ATTR_REF) != 0; +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) { + printf("pmap_is_referenced(%lx) -> %c\n", pa, "FT"[rv]); + } +#endif + return rv; +} + +/* + * pmap_is_modified: + * + * Return whether or not the specified physical page is modified + * by any physical maps. + */ + +boolean_t +pmap_is_modified(pa) + vm_offset_t pa; +{ + boolean_t rv; + + if (!PAGE_IS_MANAGED(pa)) /* XXX why not panic? */ + return 0; + rv = (pmap_attributes[pa_index(pa)] & PMAP_ATTR_MOD) != 0; +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) { + printf("pmap_is_modified(%lx) -> %c\n", pa, "FT"[rv]); + } +#endif + return rv; +} + +vm_offset_t +pmap_phys_address(ppn) + int ppn; +{ + return(alpha_ptob(ppn)); +} + +/* + * Miscellaneous support routines follow + */ + +/* + * Initialize Alpha protection code array. + */ +/* 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; + } + } +} + +/* + * Invalidate a single page denoted by pmap/va. + * If (pte != NULL), it is the already computed PTE for the page. + * If (flags & PRM_TFLUSH), we must invalidate any TLB information. + * If (flags & PRM_CFLUSH), we must flush/invalidate any cache information. + */ +/* static */ +void +pmap_remove_mapping(pmap, va, pte, flags) + register pmap_t pmap; + register vm_offset_t va; + register pt_entry_t *pte; + int flags; +{ + register vm_offset_t pa; + register pv_entry_t pv, npv; + pmap_t ptpmap; + pt_entry_t *ste; + int s; +#ifdef DEBUG + pt_entry_t opte; + + if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) + printf("pmap_remove_mapping(%lx, %lx, %lx, %lx)\n", + pmap, va, pte, flags); +#endif + + /* + * PTE not provided, compute it from pmap and va. + */ + if (pte == PT_ENTRY_NULL) { + pte = pmap_pte(pmap, va); + if (*pte == PG_NV) + return; + } + pa = pmap_pte_pa(pte); +#ifdef DEBUG + opte = *pte; +#endif +#ifdef PMAPSTATS + remove_stats.removes++; +#endif + /* + * Update statistics + */ + if (pmap_pte_w(pte)) + pmap->pm_stats.wired_count--; + pmap->pm_stats.resident_count--; + + /* + * Invalidate the PTE after saving the reference modify info. + */ +#ifdef DEBUG + if (pmapdebug & PDB_REMOVE) + printf("remove: invalidating pte at %lx\n", pte); +#endif + *pte = PG_NV; + if ((flags & PRM_TFLUSH) && active_pmap(pmap)) + ALPHA_TBIS(va); + /* + * For user mappings decrement the wiring count on + * the PT page. We do this after the PTE has been + * invalidated because vm_map_pageable winds up in + * pmap_pageable which clears the modify bit for the + * PT page. + */ + if (pmap != pmap_kernel()) { + (void) vm_map_pageable(pt_map, trunc_page(pte), + round_page(pte+1), TRUE); +#ifdef DEBUG + if (pmapdebug & PDB_WIRING) + pmap_check_wiring("remove", trunc_page(pte)); +#endif + } + /* + * If this isn't a managed page, we are all done. + */ + if (!PAGE_IS_MANAGED(pa)) + return; + /* + * Otherwise remove it from the PV table + * (raise IPL since we may be called at interrupt time). + */ + pv = pa_to_pvh(pa); + ste = NULL; + s = splimp(); + /* + * 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. + */ + if (pmap == pv->pv_pmap && va == pv->pv_va) { + ste = pv->pv_ptpte; + ptpmap = pv->pv_ptpmap; + npv = pv->pv_next; + if (npv) { + npv->pv_flags = pv->pv_flags; + *pv = *npv; + free((caddr_t)npv, M_VMPVENT); + } else + pv->pv_pmap = NULL; +#ifdef PMAPSTATS + remove_stats.pvfirst++; +#endif + } else { + for (npv = pv->pv_next; npv; npv = npv->pv_next) { +#ifdef PMAPSTATS + remove_stats.pvsearch++; +#endif + if (pmap == npv->pv_pmap && va == npv->pv_va) + break; + pv = npv; + } +#ifdef DEBUG + if (npv == NULL) + panic("pmap_remove: PA not in pv_tab"); +#endif + ste = npv->pv_ptpte; + ptpmap = npv->pv_ptpmap; + pv->pv_next = npv->pv_next; + free((caddr_t)npv, M_VMPVENT); + pv = pa_to_pvh(pa); + } + /* + * If this was a PT page we must also remove the + * mapping from the associated segment table. + */ + if (ste) { +#ifdef PMAPSTATS + remove_stats.ptinvalid++; +#endif +#ifdef DEBUG + if (pmapdebug & (PDB_REMOVE|PDB_PTPAGE)) + printf("remove: ste was %lx@%lx pte was %lx@%lx\n", + *ste, ste, opte, pmap_pte(pmap, va)); +#endif + *ste = PG_NV; + /* + * If it was a user PT page, we decrement the + * reference count on the segment table as well, + * freeing it if it is now empty. + */ + if (ptpmap != pmap_kernel()) { +#ifdef DEBUG + if (pmapdebug & (PDB_REMOVE|PDB_SEGTAB)) + printf("remove: stab %lx, refcnt %d\n", + ptpmap->pm_stab, ptpmap->pm_sref - 1); + if ((pmapdebug & PDB_PARANOIA) && + ptpmap->pm_stab != (pt_entry_t *)trunc_page(ste)) + panic("remove: bogus ste"); +#endif + if (--(ptpmap->pm_sref) == 0) { +#ifdef DEBUG + if (pmapdebug&(PDB_REMOVE|PDB_SEGTAB)) + printf("remove: free stab %lx\n", + ptpmap->pm_stab); +#endif + kmem_free_wakeup(st_map, + (vm_offset_t)ptpmap->pm_stab, + ALPHA_STSIZE); + ptpmap->pm_stab = Segtabzero; + ptpmap->pm_stpte = Segtabzeropte; + ptpmap->pm_stchanged = TRUE; + /* + * XXX may have changed segment table + * pointer for current process so + * update now to reload hardware. + * (curproc may be NULL if exiting.) + */ + if (curproc != NULL && + ptpmap == curproc->p_vmspace->vm_map.pmap) + PMAP_ACTIVATE(ptpmap, 1); + } +#ifdef DEBUG + else if (ptpmap->pm_sref < 0) + panic("remove: sref < 0"); +#endif + } +#if 0 + /* + * XXX this should be unnecessary as we have been + * flushing individual mappings as we go. + */ + if (ptpmap == pmap_kernel()) + ALPHA_TBIAS(); + else + ALPHA_TBIAU(); +#endif + pv->pv_flags &= ~PV_PTPAGE; + ptpmap->pm_ptpages--; + } + splx(s); +} + +/* static */ +void +pmap_changebit(pa, bit, setem) + register vm_offset_t pa; + u_long bit; + boolean_t setem; +{ + register pv_entry_t pv; + register pt_entry_t *pte, npte; + vm_offset_t va; + int s; +#ifdef PMAPSTATS + struct chgstats *chgp; +#endif + +#ifdef DEBUG + if (pmapdebug & PDB_BITS) + printf("pmap_changebit(%lx, %lx, %s)\n", + pa, bit, setem ? "set" : "clear"); +#endif + if (!PAGE_IS_MANAGED(pa)) + return; + +#ifdef PMAPSTATS + chgp = &changebit_stats[(bit>>2)-1]; + if (setem) + chgp->setcalls++; + else + chgp->clrcalls++; +#endif + pv = pa_to_pvh(pa); + s = splimp(); + /* + * Loop over all current mappings setting/clearing as appropos + * If setting RO do we need to clear the VAC? + */ + if (pv->pv_pmap != NULL) { +#ifdef DEBUG + int toflush = 0; +#endif + for (; pv; pv = pv->pv_next) { +#ifdef DEBUG + toflush |= (pv->pv_pmap == pmap_kernel()) ? 2 : 1; +#endif + va = pv->pv_va; + + /* + * XXX don't write protect pager mappings + */ +/* XXX */ if (bit == (PG_UWE | PG_KWE)) { + extern vm_offset_t pager_sva, pager_eva; + + if (va >= pager_sva && va < pager_eva) + continue; + } + + pte = pmap_pte(pv->pv_pmap, va); + if (setem) + npte = *pte | bit; + else + npte = *pte & ~bit; + if (*pte != npte) { + *pte = npte; + if (active_pmap(pv->pv_pmap)) + ALPHA_TBIS(va); +#ifdef PMAPSTATS + if (setem) + chgp->sethits++; + else + chgp->clrhits++; +#endif + } +#ifdef PMAPSTATS + else { + if (setem) + chgp->setmiss++; + else + chgp->clrmiss++; + } +#endif + } + } + splx(s); +} + +/* static */ +void +pmap_enter_ptpage(pmap, va) + register pmap_t pmap; + register vm_offset_t va; +{ + register vm_offset_t ptpa; + register pv_entry_t pv; + pt_entry_t *ste; + int s; + +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_ENTER|PDB_PTPAGE)) + printf("pmap_enter_ptpage: pmap %lx, va %lx\n", pmap, va); +#endif +#ifdef PMAPSTATS + enter_stats.ptpneeded++; +#endif + /* + * Allocate a segment table if necessary. Note that it is allocated + * from a private map and not pt_map. This keeps user page tables + * aligned on segment boundaries in the kernel address space. + * The segment table is wired down. It will be freed whenever the + * reference count drops to zero. + */ + if (pmap->pm_stab == Segtabzero) { + pmap->pm_stab = (pt_entry_t *) + kmem_alloc(st_map, ALPHA_STSIZE); + pmap->pm_stpte = *kvtopte(pmap->pm_stab); + pmap->pm_stchanged = TRUE; + /* + * XXX may have changed segment table pointer for current + * process so update now to reload hardware. + */ + if (pmap == curproc->p_vmspace->vm_map.pmap) + PMAP_ACTIVATE(pmap, 1); +#ifdef DEBUG + if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB)) + printf("enter: pmap %lx stab %lx(%lx)\n", + pmap, pmap->pm_stab, pmap->pm_stpte); +#endif + } + + ste = pmap_ste(pmap, va); + va = trunc_page((vm_offset_t)pmap_pte(pmap, va)); + + /* + * In the kernel we allocate a page from the kernel PT page + * free list and map it into the kernel page table map (via + * pmap_enter). + */ + if (pmap == pmap_kernel()) { + register struct kpt_page *kpt; + + s = splimp(); + if ((kpt = kpt_free_list) == (struct kpt_page *)0) { + /* + * No PT pages available. + * Try once to free up unused ones. + */ +#ifdef DEBUG + if (pmapdebug & PDB_COLLECT) + printf("enter: no KPT pages, collecting...\n"); +#endif + pmap_collect(pmap_kernel()); + if ((kpt = kpt_free_list) == (struct kpt_page *)0) + panic("pmap_enter_ptpage: can't get KPT page"); + } +#ifdef PMAPSTATS + if (++kpt_stats.kptinuse > kpt_stats.kptmaxuse) + kpt_stats.kptmaxuse = kpt_stats.kptinuse; +#endif + kpt_free_list = kpt->kpt_next; + kpt->kpt_next = kpt_used_list; + kpt_used_list = kpt; + ptpa = kpt->kpt_pa; + bzero((caddr_t)kpt->kpt_va, ALPHA_PAGE_SIZE); + pmap_enter(pmap, va, ptpa, VM_PROT_DEFAULT, TRUE); +#ifdef DEBUG + if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) { + int ix = pmap_ste(pmap, va) - pmap_ste(pmap, 0); + + printf("enter: add &Sysptmap[%d]: %lx (KPT page %lx)\n", + ix, Sysptmap[ix], kpt->kpt_va); + } +#endif + splx(s); + } + /* + * For user processes we just simulate a fault on that location + * letting the VM system allocate a zero-filled page. + */ + else { + /* + * Count the segment table reference now so that we won't + * lose the segment table when low on memory. + */ + pmap->pm_sref++; +#ifdef DEBUG + if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) + printf("enter: about to fault UPT pg at %lx\n", va); +#endif + s = vm_fault(pt_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE); + if (s != KERN_SUCCESS) { + printf("vm_fault(pt_map, %lx, RW, 0) -> %d\n", va, s); + panic("pmap_enter: vm_fault failed"); + } + ptpa = pmap_extract(pmap_kernel(), va); + /* + * Mark the page clean now to avoid its pageout (and + * hence creation of a pager) between now and when it + * is wired; i.e. while it is on a paging queue. + */ + PHYS_TO_VM_PAGE(ptpa)->flags |= PG_CLEAN; +#ifdef DEBUG + PHYS_TO_VM_PAGE(ptpa)->flags |= PG_PTPAGE; +#endif + } + /* + * Locate the PV entry in the kernel for this PT page and + * record the STE address. This is so that we can invalidate + * the STE when we remove the mapping for the page. + */ + pv = pa_to_pvh(ptpa); + s = splimp(); + if (pv) { + pv->pv_flags |= PV_PTPAGE; + do { + if (pv->pv_pmap == pmap_kernel() && pv->pv_va == va) + break; + } while ((pv = pv->pv_next) != NULL); + } +#ifdef DEBUG + if (pv == NULL) + panic("pmap_enter_ptpage: PT page not entered"); +#endif + pv->pv_ptpte = ste; + pv->pv_ptpmap = pmap; +#ifdef DEBUG + if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) + printf("enter: new PT page at PA %lx, ste at %lx\n", ptpa, ste); +#endif + + /* + * Map the new PT page into the segment table. + * Reference count on the user segment tables incremented above + * to prevent race conditions. Note that we don't use vm_map_pageable + * to keep the count like we do for PT pages, this is mostly because + * it would be difficult to identify ST pages in pmap_pageable to + * release them. We also avoid the overhead of vm_map_pageable. + */ + *ste = ((ptpa >> PGSHIFT) << PG_SHIFT) | PG_KRE | PG_KWE | PG_V | + (pmap == pmap_kernel() ? PG_ASM : 0); + if (pmap != pmap_kernel()) { +#ifdef DEBUG + if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB)) + printf("enter: stab %lx refcnt %d\n", + pmap->pm_stab, pmap->pm_sref); +#endif + } +#if 0 + /* + * Flush stale TLB info. + */ + if (pmap == pmap_kernel()) + ALPHA_TBIAS(); + else + ALPHA_TBIAU(); +#endif + pmap->pm_ptpages++; + splx(s); +} + +/* + * Emulate reference and/or modified bit hits. + */ +void +pmap_emulate_reference(p, v, user, write) + struct proc *p; + vm_offset_t v; + int user; + int write; +{ + pt_entry_t faultoff, *pte; + vm_offset_t pa; + char attr; + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_emulate_reference: 0x%lx, 0x%lx, %d, %d\n", + p, v, user, write); +#endif + + /* + * 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 = kvtopte(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_pte(&p->p_vmspace->vm_pmap, v); + } +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) { + printf("\tpte = 0x%lx, ", pte); + printf("*pte = 0x%lx\n", *pte); + } +#endif +#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 DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("\tpa = 0x%lx\n", pa); +#endif +#ifdef DIAGNOSTIC + if (!PAGE_IS_MANAGED(pa)) + printf("WARNING: pmap_emulate_reference(0x%lx, 0x%lx, %d, %d): pa 0x%lx not managed\n", 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. + */ + attr = PMAP_ATTR_REF; + faultoff = PG_FOR | PG_FOE; + if (write) { + attr |= PMAP_ATTR_MOD; + faultoff |= PG_FOW; + } + pmap_attributes[pa_index(pa)] |= attr; + 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); + } +} + +#ifdef DEBUG +/* static */ +void +pmap_pvdump(pa) + vm_offset_t pa; +{ + register pv_entry_t pv; + + printf("pa %lx", pa); + for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next) + printf(" -> pmap %lx, va %lx, stpte %lx, ptpmap %lx, flags %lx", + pv->pv_pmap, pv->pv_va, pv->pv_ptpte, pv->pv_ptpmap, + pv->pv_flags); + printf("\n"); +} + +/* static */ +void +pmap_check_wiring(str, va) + char *str; + vm_offset_t va; +{ + vm_map_entry_t entry; + pt_entry_t *pte; + register int count; + + va = trunc_page(va); + if (!pmap_ste_v(pmap_kernel(), va) || + !pmap_pte_v(pmap_pte(pmap_kernel(), va))) + return; + + if (!vm_map_lookup_entry(pt_map, va, &entry)) { + printf("wired_check: entry for %lx not found\n", va); + return; + } + count = 0; + for (pte = (pt_entry_t *)va; pte < (pt_entry_t *)(va+PAGE_SIZE); pte++) + if (*pte) + count++; + if (entry->wired_count != count) + printf("*%s*: %lx: w%d/a%d\n", + str, va, entry->wired_count, count); +} +#endif + +vm_offset_t +vtophys(vaddr) + vm_offset_t vaddr; +{ + vm_offset_t paddr; + + if (vaddr < ALPHA_K0SEG_BASE) { + printf("vtophys: invalid vaddr 0x%lx", vaddr); + paddr = vaddr; + } else if (vaddr <= ALPHA_K0SEG_END) + paddr = ALPHA_K0SEG_TO_PHYS(vaddr); + else + paddr = vatopa(vaddr); + +#if 0 + printf("vtophys(0x%lx) -> %lx\n", vaddr, paddr); +#endif + + return (paddr); +} diff --git a/sys/arch/alpha/alpha/process_machdep.c b/sys/arch/alpha/alpha/process_machdep.c index c9f6b8af9d9..be249eec38c 100644 --- a/sys/arch/alpha/alpha/process_machdep.c +++ b/sys/arch/alpha/alpha/process_machdep.c @@ -1,5 +1,5 @@ -/* $OpenBSD: process_machdep.c,v 1.3 1996/07/29 22:57:56 niklas Exp $ */ -/* $NetBSD: process_machdep.c,v 1.3 1995/11/23 02:34:29 cgd Exp $ */ +/* $OpenBSD: process_machdep.c,v 1.4 1996/10/30 22:38:23 niklas Exp $ */ +/* $NetBSD: process_machdep.c,v 1.7 1996/07/11 20:14:21 cgd Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -64,7 +64,8 @@ #include <machine/frame.h> #define process_frame(p) ((p)->p_md.md_tf) -#define process_fpframe(p) (&(p)->p_addr->u_pcb.pcb_fp) +#define process_pcb(p) (&(p)->p_addr->u_pcb) +#define process_fpframe(p) (&(process_pcb(p)->pcb_fp)) int process_read_regs(p, regs) @@ -73,7 +74,8 @@ process_read_regs(p, regs) { frametoreg(process_frame(p), regs); - regs->r_regs[R_ZERO] = process_frame(p)->tf_pc; + regs->r_regs[R_ZERO] = process_frame(p)->tf_regs[FRAME_PC]; + regs->r_regs[R_SP] = process_pcb(p)->pcb_hw.apcb_usp; return (0); } @@ -83,8 +85,9 @@ process_write_regs(p, regs) struct reg *regs; { - process_frame(p)->tf_pc = regs->r_regs[R_ZERO]; regtoframe(regs, process_frame(p)); + process_frame(p)->tf_regs[FRAME_PC] = regs->r_regs[R_ZERO]; + process_pcb(p)->pcb_hw.apcb_usp = regs->r_regs[R_SP]; return (0); } @@ -107,7 +110,7 @@ process_set_pc(p, addr) { struct trapframe *frame = process_frame(p); - frame->tf_pc = (u_int64_t)addr; + frame->tf_regs[FRAME_PC] = (u_int64_t)addr; return (0); } @@ -119,9 +122,9 @@ process_read_fpregs(p, regs) extern struct proc *fpcurproc; if (p == fpcurproc) { - pal_wrfen(1); + alpha_pal_wrfen(1); savefpstate(process_fpframe(p)); - pal_wrfen(0); + alpha_pal_wrfen(0); } bcopy(process_fpframe(p), regs, sizeof(struct fpreg)); diff --git a/sys/arch/alpha/alpha/prom.c b/sys/arch/alpha/alpha/prom.c index 8678f12be04..f3df0cb78a7 100644 --- a/sys/arch/alpha/alpha/prom.c +++ b/sys/arch/alpha/alpha/prom.c @@ -1,5 +1,5 @@ -/* $OpenBSD: prom.c,v 1.3 1996/07/29 22:57:57 niklas Exp $ */ -/* $NetBSD: prom.c,v 1.5.4.2 1996/06/13 18:35:21 cgd Exp $ */ +/* $OpenBSD: prom.c,v 1.4 1996/10/30 22:38:23 niklas Exp $ */ +/* $NetBSD: prom.c,v 1.11 1996/10/16 00:00:40 cgd Exp $ */ /* * Copyright (c) 1992, 1994, 1995, 1996 Carnegie Mellon University @@ -27,16 +27,25 @@ */ #include <sys/param.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/systm.h> #include <machine/rpb.h> #include <machine/prom.h> -#include <machine/pte.h> +#ifdef NEW_PMAP +#include <vm/vm.h> +#include <vm/pmap.h> +#endif #include <dev/cons.h> /* XXX this is to fake out the console routines, while booting. */ void promcnputc __P((dev_t, int)); int promcngetc __P((dev_t)); +u_int64_t hwrpb_checksum __P((void)); +long console_restart __P((u_int64_t, u_int64_t, u_int64_t)); + struct consdev promcons = { NULL, NULL, promcngetc, promcnputc, nullcnpollc, makedev(23,0), 1 }; @@ -48,6 +57,10 @@ extern struct prom_vec prom_dispatch_v; pt_entry_t *rom_ptep, rom_pte, saved_pte; /* XXX */ +#ifdef NEW_PMAP +#define rom_ptep (curproc ? &curproc->p_vmspace->vm_pmap.dir[0] : rom_ptep) +#endif + void init_prom_interface() { @@ -82,7 +95,7 @@ promcnputc(dev, c) int c; { prom_return_t ret; - unsigned char *to = (unsigned char *)0x20000000; + u_char *to = (u_char *)0x20000000; int s; #ifdef notdef /* XXX */ @@ -94,7 +107,7 @@ promcnputc(dev, c) if (!prom_mapped) { /* XXX */ saved_pte = *rom_ptep; /* XXX */ *rom_ptep = rom_pte; /* XXX */ - TBIA(); /* XXX */ + ALPHA_TBIA(); /* XXX */ } /* XXX */ *to = c; @@ -104,7 +117,7 @@ promcnputc(dev, c) if (!prom_mapped) { /* XXX */ *rom_ptep = saved_pte; /* XXX */ - TBIA(); /* XXX */ + ALPHA_TBIA(); /* XXX */ } /* XXX */ splx(s); } @@ -131,12 +144,12 @@ promcngetc(dev) if (!prom_mapped) { /* XXX */ saved_pte = *rom_ptep; /* XXX */ *rom_ptep = rom_pte; /* XXX */ - TBIA(); /* XXX */ + ALPHA_TBIA(); /* XXX */ } /* XXX */ - ret.bits = prom_dispatch(PROM_R_GETC, alpha_console); + ret.bits = prom_dispatch(PROM_R_GETC, alpha_console, 0, 0); if (!prom_mapped) { /* XXX */ *rom_ptep = saved_pte; /* XXX */ - TBIA(); /* XXX */ + ALPHA_TBIA(); /* XXX */ } /* XXX */ splx(s); if (ret.u.status == 0 || ret.u.status == 1) @@ -166,12 +179,12 @@ promcnlookc(dev, cp) if (!prom_mapped) { /* XXX */ saved_pte = *rom_ptep; /* XXX */ *rom_ptep = rom_pte; /* XXX */ - TBIA(); /* XXX */ + ALPHA_TBIA(); /* XXX */ } /* XXX */ - ret.bits = prom_dispatch(PROM_R_GETC, alpha_console); + ret.bits = prom_dispatch(PROM_R_GETC, alpha_console, 0, 0); if (!prom_mapped) { /* XXX */ *rom_ptep = saved_pte; /* XXX */ - TBIA(); /* XXX */ + ALPHA_TBIA(); /* XXX */ } splx(s); if (ret.u.status == 0 || ret.u.status == 1) { @@ -199,13 +212,13 @@ prom_getenv(id, buf, len) if (!prom_mapped) { /* XXX */ saved_pte = *rom_ptep; /* XXX */ *rom_ptep = rom_pte; /* XXX */ - TBIA(); /* XXX */ + ALPHA_TBIA(); /* XXX */ } /* XXX */ ret.bits = prom_dispatch(PROM_R_GETENV, id, to, len); bcopy(to, buf, len); if (!prom_mapped) { /* XXX */ *rom_ptep = saved_pte; /* XXX */ - TBIA(); /* XXX */ + ALPHA_TBIA(); /* XXX */ } /* XXX */ splx(s); @@ -232,8 +245,7 @@ prom_halt(halt) * we want to happen when we halt. */ p = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off); - /* XXX BIP should have been cleared long ago. */ - p->pcs_flags &= ~(PCS_RC | PCS_HALT_REQ | PCS_BIP); + p->pcs_flags &= ~(PCS_RC | PCS_HALT_REQ); if (halt) p->pcs_flags |= PCS_HALT_STAY_HALTED; else @@ -242,5 +254,66 @@ prom_halt(halt) /* * Halt the machine. */ - pal_halt(); + alpha_pal_halt(); +} + +u_int64_t +hwrpb_checksum() +{ + u_int64_t *p, sum; + int i; + +#define offsetof(type, member) ((size_t)(&((type *)0)->member)) /* XXX */ + + 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 XentRestart __P((void)); + +void +hwrbp_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 = (long (*) __P((long)))&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 = (long (*) __P((long)))&XentRestart; + hwrpb->rpb_restart_val = 0x2; +#endif + + hwrpb->rpb_checksum = hwrpb_checksum(); + + p->pcs_flags |= (PCS_RC | PCS_CV); +} + +long +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/arch/alpha/alpha/prom_disp.s b/sys/arch/alpha/alpha/prom_disp.s index 68b176394b1..73ac11d8348 100644 --- a/sys/arch/alpha/alpha/prom_disp.s +++ b/sys/arch/alpha/alpha/prom_disp.s @@ -1,5 +1,5 @@ -/* $OpenBSD: prom_disp.s,v 1.3 1996/07/29 22:57:59 niklas Exp $ */ -/* $NetBSD: prom_disp.s,v 1.4 1996/04/12 06:07:38 cgd Exp $ */ +/* $OpenBSD: prom_disp.s,v 1.4 1996/10/30 22:38:24 niklas Exp $ */ +/* $NetBSD: prom_disp.s,v 1.5 1996/09/17 21:17:14 cgd Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -30,12 +30,10 @@ #ifndef _LOCORE #include <machine/asm.h> -#include <machine/prom.h> -#include <machine/rpb.h> #endif .globl prom_dispatch_v - .comm prom_dispatch_v 16 + .comm prom_dispatch_v,16 .text .align 4 diff --git a/sys/arch/alpha/alpha/promcons.c b/sys/arch/alpha/alpha/promcons.c index cafa9a8e8c0..60382a24814 100644 --- a/sys/arch/alpha/alpha/promcons.c +++ b/sys/arch/alpha/alpha/promcons.c @@ -1,5 +1,5 @@ -/* $OpenBSD: promcons.c,v 1.3 1996/07/29 22:58:00 niklas Exp $ */ -/* $NetBSD: promcons.c,v 1.2.6.1 1996/06/03 18:54:31 cgd Exp $ */ +/* $OpenBSD: promcons.c,v 1.4 1996/10/30 22:38:25 niklas Exp $ */ +/* $NetBSD: promcons.c,v 1.3 1996/05/30 18:44:30 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -43,10 +43,18 @@ #include <sys/types.h> #include <sys/device.h> +#include <dev/cons.h> + +#include <machine/rpb.h> +#include <machine/prom.h> + static struct tty *prom_tty[1]; -void promstart(), promtimeout(); -int promparam(); +void promstart __P((struct tty *)); +void promtimeout __P((void *)); +int promparam __P((struct tty *, struct termios *)); +cdev_decl(prom); +cons_decl(prom); int promopen(dev, flag, mode, p) @@ -55,7 +63,6 @@ promopen(dev, flag, mode, p) struct proc *p; { int unit = minor(dev); - u_short iobase; struct tty *tp; int s; int error = 0, setuptimeout = 0; @@ -193,9 +200,10 @@ out: /* * Stop output on a line. */ -void +int promstop(tp, flag) struct tty *tp; + int flag; { int s; @@ -204,12 +212,14 @@ promstop(tp, flag) if ((tp->t_state & TS_TTSTOP) == 0) tp->t_state |= TS_FLUSH; splx(s); + return 0; } void -promtimeout(tp) - struct tty *tp; +promtimeout(v) + void *v; { + struct tty *tp = v; u_char c; while (promcnlookc(tp->t_dev, &c)) { diff --git a/sys/arch/alpha/alpha/rd_root.c b/sys/arch/alpha/alpha/rd_root.c new file mode 100644 index 00000000000..ac46e33d9ee --- /dev/null +++ b/sys/arch/alpha/alpha/rd_root.c @@ -0,0 +1,84 @@ +/* $OpenBSD: rd_root.c,v 1.1 1996/10/30 22:38:26 niklas Exp $ */ +/* $NetBSD: rd_root.c,v 1.5 1996/10/13 02:59:47 christos Exp $ */ + +/* + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * Copyright (c) 1995 Gordon W. Ross + * 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. 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/systm.h> +#include <sys/reboot.h> + +#include <dev/ramdisk.h> + +extern int boothowto; + +#ifndef MINIROOTSIZE +#define MINIROOTSIZE 512 +#endif + +#define ROOTBYTES (MINIROOTSIZE << DEV_BSHIFT) + +/* + * This array will be patched to contain a file-system image. + */ +u_int32_t rd_root_size = ROOTBYTES; +char rd_root_image[ROOTBYTES] = "|This is the root ramdisk!\n"; + +/* + * This is called during autoconfig. + */ +void +rd_attach_hook(unit, rd) + int unit; + struct rd_conf *rd; +{ + + if (unit == 0) { + /* Setup root ramdisk */ + rd->rd_addr = (caddr_t)rd_root_image; + rd->rd_size = (size_t)rd_root_size; + rd->rd_type = RD_KMEM_FIXED; + printf("rd%d: internal %dK image area\n", unit, + ROOTBYTES / 1024); + } +} + +/* + * This is called during open (i.e. mountroot) + */ +void +rd_open_hook(unit, rd) + int unit; + struct rd_conf *rd; +{ + + if (unit == 0) { + /* The root ramdisk only works single-user. */ + boothowto |= RB_SINGLE; + } +} diff --git a/sys/arch/alpha/alpha/support.c b/sys/arch/alpha/alpha/support.c index 48c7010794e..51a0cae1ce1 100644 --- a/sys/arch/alpha/alpha/support.c +++ b/sys/arch/alpha/alpha/support.c @@ -1,4 +1,4 @@ -/* $OpenBSD: support.c,v 1.3 1996/07/29 22:58:02 niklas Exp $ */ +/* $OpenBSD: support.c,v 1.4 1996/10/30 22:38:27 niklas Exp $ */ /* $NetBSD: support.c,v 1.2 1995/11/23 02:34:32 cgd Exp $ */ /* diff --git a/sys/arch/alpha/alpha/swapgeneric.c b/sys/arch/alpha/alpha/swapgeneric.c index 9d0c3d51ae0..66648a92192 100644 --- a/sys/arch/alpha/alpha/swapgeneric.c +++ b/sys/arch/alpha/alpha/swapgeneric.c @@ -1,5 +1,5 @@ -/* $OpenBSD: swapgeneric.c,v 1.3 1996/07/29 22:58:03 niklas Exp $ */ -/* $NetBSD: swapgeneric.c,v 1.4.4.1 1996/06/13 18:02:37 cgd Exp $ */ +/* $OpenBSD: swapgeneric.c,v 1.4 1996/10/30 22:38:27 niklas Exp $ */ +/* $NetBSD: swapgeneric.c,v 1.5 1996/06/12 01:26:37 cgd Exp $ */ /*- * Copyright (c) 1994 diff --git a/sys/arch/alpha/alpha/sys_machdep.c b/sys/arch/alpha/alpha/sys_machdep.c index f1bdce6a8c5..eabe550b2ec 100644 --- a/sys/arch/alpha/alpha/sys_machdep.c +++ b/sys/arch/alpha/alpha/sys_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_machdep.c,v 1.3 1996/07/29 22:58:05 niklas Exp $ */ +/* $OpenBSD: sys_machdep.c,v 1.4 1996/10/30 22:38:28 niklas Exp $ */ /* $NetBSD: sys_machdep.c,v 1.3 1995/11/23 02:34:35 cgd Exp $ */ /* @@ -40,10 +40,12 @@ sys_sysarch(p, v, retval) void *v; register_t *retval; { +#if 0 struct sys_sysarch_args /* { syscallarg(int) op; syscallarg(char *) parms; } */ *uap = v; +#endif return (ENOSYS); } diff --git a/sys/arch/alpha/alpha/trap.c b/sys/arch/alpha/alpha/trap.c index c489c7162fd..ce38dec1827 100644 --- a/sys/arch/alpha/alpha/trap.c +++ b/sys/arch/alpha/alpha/trap.c @@ -1,5 +1,5 @@ -/* $OpenBSD: trap.c,v 1.4 1996/07/29 22:58:06 niklas Exp $ */ -/* $NetBSD: trap.c,v 1.5 1995/11/23 02:34:37 cgd Exp $ */ +/* $OpenBSD: trap.c,v 1.5 1996/10/30 22:38:29 niklas Exp $ */ +/* $NetBSD: trap.c,v 1.16 1996/10/13 02:59:48 christos Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -33,18 +33,29 @@ #include <sys/proc.h> #include <sys/user.h> #include <sys/syscall.h> +#include <sys/buf.h> #ifdef KTRACE #include <sys/ktrace.h> #endif #include <machine/cpu.h> #include <machine/reg.h> -#include <machine/trap.h> #ifdef COMPAT_OSF1 #include <compat/osf1/osf1_syscall.h> #endif +static __inline void userret __P((struct proc *, u_int64_t, u_quad_t)); +void trap __P((const u_long, const u_long, const u_long, const u_long, + struct trapframe *)); +int unaligned_fixup __P((u_long, u_long, u_long, struct proc *)); +void syscall __P((u_int64_t, struct trapframe *)); +void child_return __P((struct proc *)); +void ast __P((struct trapframe *)); +u_long Sfloat_to_reg __P((u_int)); +u_int reg_to_Sfloat __P((u_long)); +u_long Tfloat_reg_cvt __P((u_long)); + struct proc *fpcurproc; /* current user of the FPU */ /* @@ -94,230 +105,314 @@ userret(p, pc, oticks) } /* - * Trap is called from locore to handle most types of processor traps, - * including events such as simulated software interrupts/AST's. - * System calls are broken out for efficiency. + * 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*/ -trap(type, code, v, framep) - unsigned long type; - unsigned long code; - register unsigned long v; +void +trap(a0, a1, a2, entry, framep) + const unsigned long a0, a1, a2, entry; struct trapframe *framep; { - extern char fswintr[]; register struct proc *p; register int i; u_int64_t ucode; u_quad_t sticks; + int user; cnt.v_trap++; p = curproc; ucode = 0; - if (USERMODE(framep->tf_ps)) { - type |= T_USER; + if ((framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0) { + user = 1; sticks = p->p_sticks; p->p_md.md_tf = framep; - } -#ifdef DDB - if (type == T_BPT) { - if (kdb_trap(type, framep)) - return; - } -#endif - switch (type) { + } else + user = 0; - default: -dopanic: - printf("trap type %ld, code = 0x%lx, v = 0x%lx\n", type, - code, v); - printf("pc = 0x%lx\n", framep->tf_pc); - printf("curproc = 0x%lx\n", curproc); - if (curproc != NULL) - printf("curproc->p_pid = 0x%d\n", curproc->p_pid); - -#ifdef DDB - if (kdb_trap(type, framep)) - return; -#endif - regdump(framep); - type &= ~T_USER; -#ifdef XXX - if ((unsigned)type < trap_types) - panic(trap_type[type]); -#endif - panic("trap"); - - case T_ASTFLT: - /* oops. this can't happen. */ - goto dopanic; + 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; - case T_ASTFLT|T_USER: - astpending = 0; - cnt.v_soft++; - if (p->p_flag & P_OWEUPC) { - p->p_flag &= ~P_OWEUPC; - ADDUPROF(p); + ucode = a0; /* VA */ + break; } - goto out; - case T_UNAFLT: /* Always an error of some kind. */ - if (p == NULL || p->p_addr->u_pcb.pcb_onfault == NULL) - goto dopanic; - else { - framep->tf_pc = (u_int64_t)p->p_addr->u_pcb.pcb_onfault; - p->p_addr->u_pcb.pcb_onfault = NULL; - } - goto out; + /* + * 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 T_UNAFLT|T_USER: /* "Here, have a SIGBUS instead!" */ - i = SIGBUS; - ucode = v; - break; + 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) { +sigfpe: i = SIGFPE; + ucode = a0; /* exception summary */ + break; + } - case T_ARITHFLT|T_USER: -sigfpe: i = SIGFPE; - ucode = v; - break; + /* Always fatal in kernel. Should never happen. */ + goto dopanic; - case T_FPDISABLED|T_USER: + case ALPHA_KENTRY_IF: /* - * on exit from the kernel, if proc == fpcurproc, FP is - * enabled. + * These are always fatal in kernel, and should never + * happen. */ - if (fpcurproc == p) - panic("fp disabled for fpcurproc == %lx", p); + if (!user) + goto dopanic; - pal_wrfen(1); - if (fpcurproc) - savefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); - fpcurproc = p; - restorefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); - pal_wrfen(0); + switch (a0) { + case ALPHA_IF_CODE_GENTRAP: + if (framep->tf_regs[FRAME_A0] == -2) /* weird! */ + goto sigfpe; + case ALPHA_IF_CODE_BPT: + case ALPHA_IF_CODE_BUGCHK: + ucode = a0; /* trap type */ + i = SIGTRAP; + break; - p->p_md.md_flags |= MDP_FPUSED; - goto out; + case ALPHA_IF_CODE_OPDEC: + ucode = a0; /* trap type */ +#ifdef NEW_PMAP +{ +int instr; +printf("REAL SIGILL: PC = 0x%lx, RA = 0x%lx\n", framep->tf_regs[FRAME_PC], framep->tf_regs[FRAME_RA]); +printf("INSTRUCTION (%d) = 0x%lx\n", copyin((void*)framep->tf_regs[FRAME_PC] - 4, &instr, 4), instr); +regdump(framep); +panic("foo"); +} +#endif + i = SIGILL; + break; - case T_GENTRAP|T_USER: - if (framep->tf_a0 == -2) /* weird! */ - goto sigfpe; - case T_BPT|T_USER: - case T_BUGCHK|T_USER: - ucode = code; - i = SIGTRAP; - 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; - case T_OPDEC|T_USER: - ucode = code; - i = SIGILL; + default: + printf("trap: unknown IF type 0x%lx\n", a0); + goto dopanic; + } break; - case T_INVALTRANS: - case T_INVALTRANS|T_USER: - case T_ACCESS: - case T_ACCESS|T_USER: - { - register vm_offset_t va; - register struct vmspace *vm; - register vm_map_t map; - vm_prot_t ftype; - int rv; - extern int fswintrberr(); - extern vm_map_t kernel_map; - - /* if it was caused by fuswintr or suswintr, just punt. */ - if ((type & T_USER) == 0 && p != NULL && - p->p_addr->u_pcb.pcb_onfault == (caddr_t)fswintrberr) { - framep->tf_pc = (u_int64_t)p->p_addr->u_pcb.pcb_onfault; - p->p_addr->u_pcb.pcb_onfault = NULL; + case ALPHA_KENTRY_MM: +#ifdef NEW_PMAP + printf("mmfault: 0x%lx, 0x%lx, %d\n", a0, a1, a2); +#endif + switch (a1) { + case ALPHA_MMCSR_FOR: + case ALPHA_MMCSR_FOE: +#ifdef NEW_PMAP + printf("mmfault for/foe in\n"); +#endif + pmap_emulate_reference(p, a0, user, 0); +#ifdef NEW_PMAP + printf("mmfault for/foe out\n"); +#endif goto out; - } - /* - * It is only a kernel address space fault iff: - * 1. (type & T_USER) == 0 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 ((type & T_USER) == 0 && (v >= VM_MIN_KERNEL_ADDRESS || - p == NULL || p->p_addr->u_pcb.pcb_onfault == NULL)) - map = kernel_map; - else { - vm = p->p_vmspace; - map = &vm->vm_map; - } + case ALPHA_MMCSR_FOW: +#ifdef NEW_PMAP + printf("mmfault fow in\n"); +#endif + pmap_emulate_reference(p, a0, user, 1); +#ifdef NEW_PMAP + printf("mmfault fow out\n"); +#endif + goto out; - switch (code) { - case -1: /* instruction fetch fault */ - case 0: /* load instruction */ - ftype = VM_PROT_READ; - break; - case 1: /* store instruction */ - ftype = VM_PROT_WRITE; - break; - } + case ALPHA_MMCSR_INVALTRANS: + case ALPHA_MMCSR_ACCESS: + { + register vm_offset_t va; + register struct vmspace *vm; + register vm_map_t map; + vm_prot_t ftype; + int rv; + extern int fswintrberr __P((void)); + extern vm_map_t kernel_map; + +#ifdef NEW_PMAP + printf("mmfault invaltrans/access in\n"); +#endif + /* + * 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) { +#ifdef NEW_PMAP + printf("mmfault nfintr in\n"); +#endif + framep->tf_regs[FRAME_PC] = + p->p_addr->u_pcb.pcb_onfault; + p->p_addr->u_pcb.pcb_onfault = 0; +#ifdef NEW_PMAP + printf("mmfault nfintr out\n"); +#endif + goto out; + } - va = trunc_page((vm_offset_t)v); - rv = vm_fault(map, va, ftype, FALSE); -#ifdef VMFAULT_TRACE - printf("vm_fault(0x%lx (pmap 0x%lx), 0x%lx (0x%lx), 0x%lx, %d) -> 0x%lx at pc 0x%lx\n", - map, map == kernel_map ? pmap_kernel() : &vm->vm_pmap, - va, v, ftype, FALSE, rv, framep->tf_pc); + /* + * 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; + } + + va = trunc_page((vm_offset_t)a0); +#ifdef NEW_PMAP + printf("mmfault going to vm_fault\n"); #endif - /* - * 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) { + rv = vm_fault(map, va, ftype, FALSE); +#ifdef NEW_PMAP + printf("mmfault back from vm_fault\n"); +#endif + /* + * 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 = clrnd(btoc(USRSTACK - + (unsigned long)va)); + if (nss > vm->vm_ssize) + vm->vm_ssize = nss; + } else if (rv == KERN_PROTECTION_FAILURE) + rv = KERN_INVALID_ADDRESS; + } if (rv == KERN_SUCCESS) { - unsigned nss; - - nss = clrnd(btoc(USRSTACK-(unsigned)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 (!USERMODE(framep->tf_ps)) { - if (p != NULL && - p->p_addr->u_pcb.pcb_onfault != NULL) { - framep->tf_pc = - (u_int64_t)p->p_addr->u_pcb.pcb_onfault; - p->p_addr->u_pcb.pcb_onfault = NULL; +#ifdef NEW_PMAP + printf("mmfault vm_fault success\n"); +#endif goto out; } + + if (!user) { +#ifdef NEW_PMAP + printf("mmfault check copyfault\n"); +#endif + /* 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; + break; + } + + default: + printf("trap: unknown MMCSR value 0x%lx\n", a1); goto dopanic; } - ucode = v; - i = SIGSEGV; break; - } - - case T_FOR: - case T_FOR|T_USER: - case T_FOE: - case T_FOE|T_USER: - pmap_emulate_reference(p, v, (type & T_USER) != 0, 0); - goto out; - case T_FOW: - case T_FOW|T_USER: - pmap_emulate_reference(p, v, (type & T_USER) != 0, 1); - goto out; + default: + goto dopanic; } trapsignal(p, i, ucode); out: - if ((type & T_USER) == 0) - return; - userret(p, framep->tf_pc, sticks); + if (user) + userret(p, framep->tf_regs[FRAME_PC], sticks); + return; + +dopanic: + printf("\n"); + printf("fatal %s trap:\n", user ? "user" : "kernel"); + printf("\n"); + printf(" trap entry = 0x%lx\n", entry); + 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"); + + /* XXX dump registers */ + /* XXX kernel debugger */ + + panic("trap"); } /* @@ -351,25 +446,24 @@ syscall(code, framep) #endif #if notdef /* can't happen, ever. */ - if (!USERMODE(framep->tf_ps)) + 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_pc - 4; + opc = framep->tf_regs[FRAME_PC] - 4; sticks = p->p_sticks; callp = p->p_emul->e_sysent; numsys = p->p_emul->e_nsysent; - #ifdef COMPAT_OSF1 if (p->p_emul == &emul_osf1) switch (code) { case OSF1_SYS_syscall: /* OSF/1 syscall() */ - code = framep->tf_a0; + code = framep->tf_regs[FRAME_A0]; hidden = 1; break; default: @@ -384,7 +478,7 @@ syscall(code, framep) * syscall() and __syscall() are handled the same on * the alpha, as everything is 64-bit aligned, anyway. */ - code = framep->tf_a0; + code = framep->tf_regs[FRAME_A0]; hidden = 1; break; default: @@ -402,7 +496,7 @@ syscall(code, framep) default: if (nargs > 10) /* XXX */ panic("syscall: too many args (%d)", nargs); - error = copyin((caddr_t)(framep->tf_regs[FRAME_SP]), &args[6], + error = copyin((caddr_t)(alpha_pal_rdusp()), &args[6], (nargs - 6) * sizeof(u_int64_t)); case 6: args[5] = framep->tf_regs[FRAME_A5]; @@ -411,11 +505,11 @@ syscall(code, framep) case 4: args[3] = framep->tf_regs[FRAME_A3]; case 3: - args[2] = framep->tf_a2; + args[2] = framep->tf_regs[FRAME_A2]; case 2: - args[1] = framep->tf_a1; + args[1] = framep->tf_regs[FRAME_A1]; case 1: - args[0] = framep->tf_a0; + args[0] = framep->tf_regs[FRAME_A0]; case 0: break; } @@ -425,6 +519,9 @@ syscall(code, framep) #endif #ifdef SYSCALL_DEBUG scdebug_call(p, code, args + hidden); +#ifdef NEW_PMAP + printf("called from 0x%lx, ra 0x%lx\n", framep->tf_regs[FRAME_PC], framep->tf_regs[FRAME_RA]); +#endif #endif if (error == 0) { rval[0] = 0; @@ -439,7 +536,7 @@ syscall(code, framep) framep->tf_regs[FRAME_A3] = 0; break; case ERESTART: - framep->tf_pc = opc; + framep->tf_regs[FRAME_PC] = opc; break; case EJUSTRETURN: break; @@ -456,9 +553,12 @@ syscall(code, framep) p = curproc; #ifdef SYSCALL_DEBUG scdebug_ret(p, code, error, rval); +#ifdef NEW_PMAP + printf("outgoing pc 0x%lx, ra 0x%lx\n", framep->tf_regs[FRAME_PC], framep->tf_regs[FRAME_RA]); +#endif #endif - userret(p, framep->tf_pc, sticks); + userret(p, framep->tf_regs[FRAME_PC], sticks); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) ktrsysret(p->p_tracep, code, error, rval[0]); @@ -477,9 +577,375 @@ child_return(p) * Return values in the frame set by cpu_fork(). */ - userret(p, p->p_md.md_tf->tf_pc, 0); + 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; + ADDUPROF(p); + } + + 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=%:\n", + p->p_pid, p->p_comm, va, p->p_md.md_tf->tf_regs[FRAME_PC], + p->p_md.md_tf->tf_regs[FRAME_PC], type, opcode); + } + + /* + * 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/arch/alpha/alpha/vm_machdep.c b/sys/arch/alpha/alpha/vm_machdep.c index b49d2dfd39b..2e92985a491 100644 --- a/sys/arch/alpha/alpha/vm_machdep.c +++ b/sys/arch/alpha/alpha/vm_machdep.c @@ -1,5 +1,5 @@ -/* $OpenBSD: vm_machdep.c,v 1.4 1996/07/29 22:58:08 niklas Exp $ */ -/* $NetBSD: vm_machdep.c,v 1.9 1996/04/23 15:26:10 cgd Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.5 1996/10/30 22:38:30 niklas Exp $ */ +/* $NetBSD: vm_machdep.c,v 1.20 1996/10/13 02:59:50 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -45,9 +45,13 @@ #include <vm/vm.h> #include <vm/vm_kern.h> +extern void exception_return __P((void)); +extern void child_return __P((struct proc *)); + /* * Dump the machine specific header information at the start of a core dump. */ +int cpu_coredump(p, vp, cred, chdr) struct proc *p; struct vnode *vp; @@ -55,11 +59,7 @@ cpu_coredump(p, vp, cred, chdr) struct core *chdr; { int error; - register struct user *up = p->p_addr; - struct cpustate { - struct trapframe regs; - struct fpreg fpstate; - } cpustate; + struct md_coredump cpustate; struct coreseg cseg; extern struct proc *fpcurproc; @@ -68,16 +68,17 @@ cpu_coredump(p, vp, cred, chdr) chdr->c_seghdrsize = ALIGN(sizeof(cseg)); chdr->c_cpusize = sizeof(cpustate); - cpustate.regs = *p->p_md.md_tf; + cpustate.md_tf = *p->p_md.md_tf; + cpustate.md_tf.tf_regs[FRAME_SP] = alpha_pal_rdusp(); /* XXX */ if (p->p_md.md_flags & MDP_FPUSED) if (p == fpcurproc) { - pal_wrfen(1); - savefpstate(&cpustate.fpstate); - pal_wrfen(0); + alpha_pal_wrfen(1); + savefpstate(&cpustate.md_fpstate); + alpha_pal_wrfen(0); } else - cpustate.fpstate = p->p_addr->u_pcb.pcb_fp; + cpustate.md_fpstate = p->p_addr->u_pcb.pcb_fp; else - bzero(&cpustate.fpstate, sizeof(cpustate.fpstate)); + bzero(&cpustate.md_fpstate, sizeof(cpustate.md_fpstate)); CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ALPHA, CORE_CPU); cseg.c_addr = 0; @@ -139,7 +140,6 @@ cpu_fork(p1, p2) pt_entry_t *ptep; int i; extern struct proc *fpcurproc; - extern void proc_trampoline(), rei(), child_return(); p2->p_md.md_tf = p1->p_md.md_tf; p2->p_md.md_flags = p1->p_md.md_flags & MDP_FPUSED; @@ -148,9 +148,15 @@ cpu_fork(p1, p2) * Cache the physical address of the pcb, so we can * swap to it easily. */ +#ifndef NEW_PMAP ptep = kvtopte(up); p2->p_md.md_pcbpaddr = &((struct user *)(PG_PFNUM(*ptep) << PGSHIFT))->u_pcb; +#else + p2->p_md.md_pcbpaddr = (void *)vtophys((vm_offset_t)&up->u_pcb); + printf("process %d pcbpaddr = 0x%lx, pmap = %p\n", + p2->p_pid, p2->p_md.md_pcbpaddr, &p2->p_vmspace->vm_pmap); +#endif /* * Simulate a write to the process's U-area pages, @@ -167,9 +173,9 @@ cpu_fork(p1, p2) * if this process has state stored there. */ if (p1 == fpcurproc) { - pal_wrfen(1); + alpha_pal_wrfen(1); savefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); - pal_wrfen(0); + alpha_pal_wrfen(0); } /* @@ -178,7 +184,12 @@ cpu_fork(p1, p2) * part of the stack. The stack and pcb need to agree; */ p2->p_addr->u_pcb = p1->p_addr->u_pcb; + p2->p_addr->u_pcb.pcb_hw.apcb_usp = alpha_pal_rdusp(); +#ifndef NEW_PMAP PMAP_ACTIVATE(&p2->p_vmspace->vm_pmap, 0); +#else +printf("NEW PROCESS %d USP = %p\n", p2->p_pid, p2->p_addr->u_pcb.pcb_hw.apcb_usp); +#endif /* * Arrange for a non-local goto when the new process @@ -187,7 +198,7 @@ cpu_fork(p1, p2) #ifdef DIAGNOSTIC if (p1 != curproc) panic("cpu_fork: curproc"); - if (up->u_pcb.pcb_fen != 0) + if ((up->u_pcb.pcb_hw.apcb_flags & ALPHA_PCB_FLAGS_FEN) != 0) printf("DANGER WILL ROBINSON: FEN SET IN cpu_fork!\n"); #endif @@ -196,7 +207,6 @@ cpu_fork(p1, p2) */ { struct trapframe *p2tf; - extern void rei(); /* * Pick a stack pointer, leaving room for a trapframe; @@ -208,6 +218,9 @@ cpu_fork(p1, p2) bcopy(p1->p_md.md_tf, p2->p_md.md_tf, sizeof(struct trapframe)); +#ifdef NEW_PMAP +printf("FORK CHILD: pc = %p, ra = %p\n", p2tf->tf_regs[FRAME_PC], p2tf->tf_regs[FRAME_RA]); +#endif /* * Set up return-value registers as fork() libc stub expects. */ @@ -217,18 +230,18 @@ cpu_fork(p1, p2) /* * Arrange for continuation at child_return(), which - * will return to rei(). Note that the child process - * doesn't stay in the kernel for long! + * will return to exception_return(). Note that the child + * process doesn't stay in the kernel for long! * * This is an inlined version of cpu_set_kpc. */ - up->u_pcb.pcb_ksp = (u_int64_t)p2tf; + up->u_pcb.pcb_hw.apcb_ksp = (u_int64_t)p2tf; up->u_pcb.pcb_context[0] = (u_int64_t)child_return; /* s0: pc */ up->u_pcb.pcb_context[1] = - (u_int64_t)rei; /* s1: ra */ + (u_int64_t)exception_return; /* s1: ra */ up->u_pcb.pcb_context[7] = - (u_int64_t)proc_trampoline; /* ra: assembly magic */ + (u_int64_t)switch_trampoline; /* ra: assembly magic */ } } @@ -239,8 +252,8 @@ cpu_fork(p1, p2) * named pc, as if the code at that address were called as a function * with argument, the current process's process pointer. * - * Note that it's assumed that when the named process returns, rei() - * should be invoked, to return to user mode. + * Note that it's assumed that when the named process returns, + * exception_return() should be invoked, to return to user mode. * * (Note that cpu_fork(), above, uses an open-coded version of this.) */ @@ -250,14 +263,12 @@ cpu_set_kpc(p, pc) void (*pc) __P((struct proc *)); { struct pcb *pcbp; - extern void proc_trampoline(); - extern void rei(); pcbp = &p->p_addr->u_pcb; pcbp->pcb_context[0] = (u_int64_t)pc; /* s0 - pc to invoke */ - pcbp->pcb_context[1] = (u_int64_t)rei; /* s1 - return address */ + pcbp->pcb_context[1] = (u_int64_t)exception_return; /* s1 - return address */ pcbp->pcb_context[7] = - (u_int64_t)proc_trampoline; /* ra - assembly magic */ + (u_int64_t)switch_trampoline; /* ra - assembly magic */ } /* @@ -277,9 +288,13 @@ cpu_swapin(p) * Cache the physical address of the pcb, so we can swap to * it easily. */ +#ifndef NEW_PMAP ptep = kvtopte(up); p->p_md.md_pcbpaddr = &((struct user *)(PG_PFNUM(*ptep) << PGSHIFT))->u_pcb; +#else + p->p_md.md_pcbpaddr = (void *)vtophys((vm_offset_t)&up->u_pcb); +#endif /* * Simulate a write to the process's U-area pages, @@ -308,9 +323,9 @@ cpu_swapout(p) if (p != fpcurproc) return; - pal_wrfen(1); + alpha_pal_wrfen(1); savefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); - pal_wrfen(0); + alpha_pal_wrfen(0); fpcurproc = NULL; } @@ -329,11 +344,16 @@ pagemove(from, to, size) if (size % CLBYTES) panic("pagemove"); +#ifndef NEW_PMAP fpte = kvtopte(from); tpte = kvtopte(to); +#else + fpte = pmap_pte(kernel_pmap, (vm_offset_t)from); + tpte = pmap_pte(kernel_pmap, (vm_offset_t)to); +#endif todo = size; /* if testing > 0, need sign... */ while (todo > 0) { - TBIS(from); + ALPHA_TBIS((vm_offset_t)from); *tpte++ = *fpte; *fpte = 0; fpte++; diff --git a/sys/arch/alpha/compile/.cvsignore b/sys/arch/alpha/compile/.cvsignore index 7a0b2488b29..d09b918e852 100644 --- a/sys/arch/alpha/compile/.cvsignore +++ b/sys/arch/alpha/compile/.cvsignore @@ -10,3 +10,5 @@ NOSY NOSY.PROF OPAL OPAL.PROF +RAMDISK +RAMDISK.PROF diff --git a/sys/arch/alpha/compile/.keep_me b/sys/arch/alpha/compile/.keep_me index c92516d7ab9..2d357971ff0 100644 --- a/sys/arch/alpha/compile/.keep_me +++ b/sys/arch/alpha/compile/.keep_me @@ -1,4 +1,4 @@ -$OpenBSD: .keep_me,v 1.2 1996/07/29 22:58:15 niklas Exp $ +$OpenBSD: .keep_me,v 1.3 1996/10/30 22:38:34 niklas Exp $ $NetBSD: .keep_me,v 1.1 1995/02/13 23:07:19 cgd Exp $ This normally empty directory needs to be kept in the distribution. diff --git a/sys/arch/alpha/compile/build_all b/sys/arch/alpha/compile/build_all index b90abb6a68f..3eea2368d0d 100644 --- a/sys/arch/alpha/compile/build_all +++ b/sys/arch/alpha/compile/build_all @@ -1,9 +1,9 @@ #!/bin/sh - # -# $OpenBSD: build_all,v 1.3 1996/07/29 22:58:17 niklas Exp $ -# $NetBSD: build_all,v 1.4.4.1 1996/06/15 03:46:17 cgd Exp $ +# $OpenBSD: build_all,v 1.4 1996/10/30 22:38:35 niklas Exp $ +# $NetBSD: build_all,v 1.6 1996/08/20 22:28:37 cgd Exp $ -cflist=`cd ../conf ; find . -type f ! -name "*[a-z.]*" ! -name ".*" | \ +cflist=`cd ../conf ; find . -type f ! -name "*[a-z]*" ! -name ".*" | \ sed -e 's,^\./,,'` docmd() diff --git a/sys/arch/alpha/compile/rebuild_all b/sys/arch/alpha/compile/rebuild_all index bff75fac1c6..30eea0f5d8f 100644 --- a/sys/arch/alpha/compile/rebuild_all +++ b/sys/arch/alpha/compile/rebuild_all @@ -1,9 +1,9 @@ #!/bin/sh - # -# $OpenBSD: rebuild_all,v 1.3 1996/07/29 22:58:18 niklas Exp $ -# $NetBSD: rebuild_all,v 1.4.4.1 1996/06/15 03:46:19 cgd Exp $ +# $OpenBSD: rebuild_all,v 1.4 1996/10/30 22:38:35 niklas Exp $ +# $NetBSD: rebuild_all,v 1.6 1996/08/20 22:28:40 cgd Exp $ -cflist=`cd ../conf ; find . -type f ! -name "*[a-z.]*" ! -name ".*" | \ +cflist=`cd ../conf ; find . -type f ! -name "*[a-z]*" ! -name ".*" | \ sed -e 's,^\./,,'` docmd() diff --git a/sys/arch/alpha/conf/ALPHA b/sys/arch/alpha/conf/ALPHA index 084b89e53c6..c02d1012167 100644 --- a/sys/arch/alpha/conf/ALPHA +++ b/sys/arch/alpha/conf/ALPHA @@ -1,9 +1,9 @@ -# $OpenBSD: ALPHA,v 1.7 1996/09/20 06:44:49 deraadt Exp $ -# $NetBSD: ALPHA,v 1.14.4.4 1996/06/13 19:21:59 cgd Exp $ +# $OpenBSD: ALPHA,v 1.8 1996/10/30 22:38:37 niklas Exp $ +# $NetBSD: ALPHA,v 1.24 1996/09/27 17:08:32 cgd Exp $ # # Alpha kernel with all the options you'd want, and more. -include "std.alpha" +include "arch/alpha/conf/std.alpha" maxusers 8 @@ -60,6 +60,7 @@ options COMPAT_43 #options COMPAT_09 options COMPAT_10 options COMPAT_11 +options COMPAT_12 # OSF/1 binary compatibility -- CURRENTLY DOES NOT WORK #options COMPAT_OSF1 @@ -81,7 +82,11 @@ options LKM #options INSECURE # Misc. options -options PCIVERBOSE # recognize "unknown" PCI devices +options EISAVERBOSE # recognize "unknown" EISA devices +options FIX_UNALIGNED_VAX_FP # fix unaligned VAX FP loads & stores +options PCIVERBOSE # recognize "unknown" PCI devices +options TCVERBOSE # recognize "unknown" TC devices +options UCONSOLE # users can use TIOCCONS (for xconsole) config bsd swap generic #config bsd root on sd0 swap on sd0 @@ -122,15 +127,18 @@ pci* at lca? pci* at ppb? # PCI devices -de* at pci? -le* at pci? -ncr* at pci? -pceb* at pci? -pcivga* at pci? -ppb* at pci? -sio* at pci? -tga* at pci? +#ahc* at pci? dev ? function ? # AHA-28xx SCSI (NOT 64-BIT) +de* at pci? dev ? function ? # 21x4[012]-based Ethernet +en* at pci? dev ? function ? # ENI PCI ATM (untested) +ep* at pci? dev ? function ? # 3COM 3c59x (untested) fpa* at pci? dev ? function ? # DEC DEFPA FDDI cards +le* at pci? dev ? function ? # PCI LANCE Ethernet (untested) +ncr* at pci? dev ? function ? # NCR 53c8xx SCSI +pceb* at pci? dev ? function ? # Intel PCI-EISA brige +pcivga* at pci? dev ? function ? # PCI VGA graphics +ppb* at pci? dev ? function ? # PCI-PCI bridges +sio* at pci? dev ? function ? # Intel PCI-ISA bridge +tga* at pci? dev ? function ? # DEC ZLXp-E[123] graphics # ISA/EISA bus support isa* at pceb? @@ -172,3 +180,4 @@ pseudo-device sl 4 pseudo-device strip 4 pseudo-device tun 4 pseudo-device vnd 4 +pseudo-device rd 1 diff --git a/sys/arch/alpha/conf/BUNNY b/sys/arch/alpha/conf/BUNNY index 88803eec57e..1ba7650e2ee 100644 --- a/sys/arch/alpha/conf/BUNNY +++ b/sys/arch/alpha/conf/BUNNY @@ -1,12 +1,12 @@ -# $OpenBSD: BUNNY,v 1.6 1996/09/20 06:44:50 deraadt Exp $ -# $NetBSD: BUNNY,v 1.5.4.1 1996/06/13 19:22:03 cgd Exp $ +# $OpenBSD: BUNNY,v 1.7 1996/10/30 22:38:38 niklas Exp $ +# $NetBSD: BUNNY,v 1.9 1996/09/27 17:08:35 cgd Exp $ # # Kernel for bunnahabhain.pdl.cs.cmu.edu. # # Trimmed down kernel for AlphaStation [24]xx systems, with lots # of buffer cache. -include "std.alpha" +include "arch/alpha/conf/std.alpha" maxusers 8 @@ -42,6 +42,7 @@ options COMPAT_43 #options COMPAT_09 options COMPAT_10 options COMPAT_11 +options COMPAT_12 # Loadable Kernel Modules options LKM @@ -50,7 +51,8 @@ options LKM #options INSECURE # Misc. options -options PCIVERBOSE # recognize "unknown" PCI devices +options PCIVERBOSE # recognize "unknown" PCI devices +options UCONSOLE # users can use TIOCCONS (for xconsole) config bsd swap generic diff --git a/sys/arch/alpha/conf/GENERIC b/sys/arch/alpha/conf/GENERIC index 801a4e0fde1..42d0eb2facb 100644 --- a/sys/arch/alpha/conf/GENERIC +++ b/sys/arch/alpha/conf/GENERIC @@ -1,9 +1,9 @@ -# $OpenBSD: GENERIC,v 1.8 1996/09/20 06:44:50 deraadt Exp $ -# $NetBSD: GENERIC,v 1.15.4.3 1996/06/13 19:22:07 cgd Exp $ +# $OpenBSD: GENERIC,v 1.9 1996/10/30 22:38:38 niklas Exp $ +# $NetBSD: GENERIC,v 1.24 1996/09/27 17:08:32 cgd Exp $ # # Generic Alpha kernel. Enough to get booted, etc., but not much more. -include "std.alpha" +include "arch/alpha/conf/std.alpha" maxusers 8 @@ -41,6 +41,7 @@ options COMPAT_43 #options COMPAT_09 options COMPAT_10 options COMPAT_11 +options COMPAT_12 # OSF/1 binary compatibility -- CURRENTLY DOES NOT WORK #options COMPAT_OSF1 @@ -52,7 +53,10 @@ options LKM #options INSECURE # Misc. options -options PCIVERBOSE # recognize "unknown" PCI devices +options EISAVERBOSE # recognize "unknown" EISA devices +options PCIVERBOSE # recognize "unknown" PCI devices +options TCVERBOSE # recognize "unknown" TC devices +options UCONSOLE # users can use TIOCCONS (for xconsole) config bsd swap generic #config bsd root on sd0 swap on sd0 @@ -93,15 +97,18 @@ pci* at lca? pci* at ppb? # PCI devices -de* at pci? -le* at pci? -ncr* at pci? -pceb* at pci? -pcivga* at pci? -ppb* at pci? -sio* at pci? -tga* at pci? +#ahc* at pci? dev ? function ? # AHA-28xx SCSI (NOT 64-BIT) +de* at pci? dev ? function ? # 21x4[012]-based Ethernet +en* at pci? dev ? function ? # ENI PCI ATM (untested) +ep* at pci? dev ? function ? # 3COM 3c59x (untested) fpa* at pci? dev ? function ? # DEC DEFPA FDDI cards +le* at pci? dev ? function ? # PCI LANCE Ethernet (untested) +ncr* at pci? dev ? function ? # NCR 53c8xx SCSI +pceb* at pci? dev ? function ? # Intel PCI-EISA brige +pcivga* at pci? dev ? function ? # PCI VGA graphics +ppb* at pci? dev ? function ? # PCI-PCI bridges +sio* at pci? dev ? function ? # Intel PCI-ISA bridge +tga* at pci? dev ? function ? # DEC ZLXp-E[123] graphics # ISA/EISA bus support isa* at pceb? @@ -140,3 +147,4 @@ pseudo-device loop pseudo-device pty 64 pseudo-device sl 4 pseudo-device vnd 4 +pseudo-device rd 1 diff --git a/sys/arch/alpha/conf/GENERIC.PROF b/sys/arch/alpha/conf/GENERIC.PROF new file mode 100644 index 00000000000..5de20fc93c8 --- /dev/null +++ b/sys/arch/alpha/conf/GENERIC.PROF @@ -0,0 +1,153 @@ +# $OpenBSD: GENERIC.PROF,v 1.1 1996/10/30 22:38:39 niklas Exp $ +# $NetBSD: GENERIC.PROF,v 1.4 1996/09/27 17:08:33 cgd Exp $ +# +# Generic Alpha kernel. Enough to get booted, etc., but not much more. + +include "arch/alpha/conf/std.alpha" + +maxusers 8 + +# Always include profiling support; does not need 'config -p'. +makeoptions PROF="-pg" +options GPROF + +# CPU Support +options DEC_3000_500 # Flamingo etc: 3000/[4-9]00* +options DEC_3000_300 # Pelican etc: 3000/300* +options DEC_2100_A50 # Avanti etc: AlphaStation 400, 200, etc. +options DEC_KN20AA # KN20AA: AlphaStation 600 +options DEC_AXPPCI_33 # NoName: AXPpci33, etc. +#options DEC_2000_300 # "Jensen": 2000/300 (DECpc AXP 150) + +# needs to be set per system +options TIMEZONE="5*60" # Minutes west of GMT (for param.c) +options DST=1 # Daylight savings rules (for param.c) + +# Standard system options +options SWAPPAGER, DEVPAGER # Paging (mandatory) +options DEBUG, DIAGNOSTIC # Extra kernel debugging +options KTRACE # System call tracing support + +# File system options +options FIFO # POSIX fifo support (in all file systems) +options FFS # Fast file system +options MFS # Memory-based file system +options NFSSERVER # Sun NFS-compatible file system server +options NFSCLIENT # Sun NFS-compatible file system client + +# Networking options +options INET # Internet protocol suite + +# 4.3BSD compatibility. Should be optional, but necessary for now. +options COMPAT_43 + +# Binary compatibility with previous versions of NetBSD. +#options COMPAT_09 +options COMPAT_10 +options COMPAT_11 +options COMPAT_12 + +# OSF/1 binary compatibility -- CURRENTLY DOES NOT WORK +#options COMPAT_OSF1 + +# Loadable Kernel Modules +options LKM + +# Disable kernel security. +#options INSECURE + +# Misc. options +options EISAVERBOSE # recognize "unknown" EISA devices +options PCIVERBOSE # recognize "unknown" PCI devices +options TCVERBOSE # recognize "unknown" TC devices +options UCONSOLE # users can use TIOCCONS (for xconsole) + +config bsd swap generic +#config bsd root on sd0 swap on sd0 +#config bsd root nfs swap nfs + +mainbus0 at root +cpu* at mainbus0 + +# TurboChannel host bus adapter support +tcasic* at mainbus0 + +# TurboChannel bus support +tc* at tcasic? + +# TurboChannel devices +ioasic0 at tc? slot ? offset ? +mcclock0 at ioasic? offset ? +le* at ioasic? offset ? +scc0 at ioasic? offset ? +scc1 at ioasic? offset ? +tcds0 at tc? slot ? offset ? +esp0 at tcds? slot ? +esp1 at tcds? slot ? +cfb* at tc? slot ? offset ? +sfb* at tc? slot ? offset ? +le* at tc? slot ? offset ? +fta* at tc? slot ? offset ? # DEC DEFTA FDDI cards + +# PCI host bus adapter support +apecs* at mainbus? +cia* at mainbus? +lca* at mainbus? + +# PCI bus support +pci* at apecs? +pci* at cia? +pci* at lca? +pci* at ppb? + +# PCI devices +#ahc* at pci? dev ? function ? # AHA-28xx SCSI (NOT 64-BIT) +de* at pci? dev ? function ? # 21x4[012]-based Ethernet +en* at pci? dev ? function ? # ENI PCI ATM (untested) +ep* at pci? dev ? function ? # 3COM 3c59x (untested) +fpa* at pci? dev ? function ? # DEC DEFPA FDDI cards +le* at pci? dev ? function ? # PCI LANCE Ethernet (untested) +ncr* at pci? dev ? function ? # NCR 53c8xx SCSI +pceb* at pci? dev ? function ? # Intel PCI-EISA brige +pcivga* at pci? dev ? function ? # PCI VGA graphics +ppb* at pci? dev ? function ? # PCI-PCI bridges +sio* at pci? dev ? function ? # Intel PCI-ISA bridge +tga* at pci? dev ? function ? # DEC ZLXp-E[123] graphics + +# ISA/EISA bus support +isa* at pceb? +eisa* at pceb? +isa* at sio? + +# ISA devices +mcclock0 at isa? port 0x70 +pckbd0 at isa? port 0x60 irq 1 # PC-ish ISA keyboard +pms0 at isa? port 0x60 irq 12 # PS/2 auxiliary +com0 at isa? port 0x3f8 irq 4 # standard serial ports +com1 at isa? port 0x2f8 irq 3 +lpt0 at isa? port 0x3bc irq 7 # standard parallel port +#wss0 at isa? port 0x530 irq 9 drq 0 # Windows Sound System + +# EISA devices +fea* at eisa? slot ? # DEC DEFEA FDDI cards + +# SCSI bus support +scsibus* at esp? +scsibus* at ncr? + +# SCSI devices +sd* at scsibus? target ? lun ? +st* at scsibus? target ? lun ? +cd* at scsibus? target ? lun ? + +# Workstation Console attachments +wscons* at cfb? +wscons* at pcivga? +wscons* at sfb? +wscons* at tga? + +pseudo-device bpfilter 16 +pseudo-device loop +pseudo-device pty 64 +pseudo-device sl 4 +pseudo-device vnd 4 diff --git a/sys/arch/alpha/conf/JURA b/sys/arch/alpha/conf/JURA index de3ab57d1e4..fd66de8e82d 100644 --- a/sys/arch/alpha/conf/JURA +++ b/sys/arch/alpha/conf/JURA @@ -1,11 +1,11 @@ -# $OpenBSD: JURA,v 1.6 1996/09/20 06:44:51 deraadt Exp $ -# $NetBSD: JURA,v 1.6.4.1 1996/06/13 19:22:10 cgd Exp $ +# $OpenBSD: JURA,v 1.7 1996/10/30 22:38:40 niklas Exp $ +# $NetBSD: JURA,v 1.9 1996/09/27 17:08:34 cgd Exp $ # # Kernel for jura.pdl.cs.cmu.edu. # # THIS KERNEL DOES NOT CURRENTLY WORK, OR EVEN CONFIGURE! -include "std.alpha" +include "arch/alpha/conf/std.alpha" maxusers 8 @@ -39,6 +39,7 @@ options COMPAT_43 #options COMPAT_09 options COMPAT_10 options COMPAT_11 +options COMPAT_12 # Loadable Kernel Modules options LKM diff --git a/sys/arch/alpha/conf/Makefile.alpha b/sys/arch/alpha/conf/Makefile.alpha index 26f39dcae83..68f5a96b5cf 100644 --- a/sys/arch/alpha/conf/Makefile.alpha +++ b/sys/arch/alpha/conf/Makefile.alpha @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile.alpha,v 1.7 1996/07/29 20:01:25 niklas Exp $ -# $NetBSD: Makefile.alpha,v 1.16 1996/05/19 21:16:51 cgd Exp $ +# $OpenBSD: Makefile.alpha,v 1.8 1996/10/30 22:38:41 niklas Exp $ +# $NetBSD: Makefile.alpha,v 1.25 1996/09/27 17:33:04 cgd Exp $ -# Makefile for NetBSD +# Makefile for OpenBSD # # This makefile is constructed from a machine description: # config machineid @@ -22,22 +22,32 @@ # DEBUG is set to -g if debugging. # PROF is set to -pg if profiling. -AS?= as CC?= cc -CPP?= cpp LD?= ld -STRIP?= strip -g -X -x -TOUCH?= touch -f -c +MKDEP?= mkdep +STRIP?= strip # source tree is located via $S relative to the compilation directory -S= ../../../.. -ALPHA= ../.. +.ifndef S +S!= cd ../../../..; pwd +.endif +ALPHA= $S/arch/alpha + +INCLUDES= -I. -I$S/arch -I$S -nostdinc +CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Dalpha + +CDIAGFLAGS?= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ + -Wno-uninitialized -Wno-format -INCLUDES= -I. -I$S/arch -I$S -CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL -Dalpha -CFLAGS= ${DEBUG} -O2 -Werror -mno-fp-regs -AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE +CMACHFLAGS= -mno-fp-regs +CFLAGS= ${DEBUG} -O2 ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} +AFLAGS= -traditional -D_LOCORE LINKFLAGS= -N -Ttext fffffc0000230000 -e __start -G 4 +STRIPFLAGS= -g -X -x + +HOSTED_CC= ${CC} +HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//} +HOSTED_CFLAGS= ${CFLAGS} ### find out what to use for libkern .include "$S/lib/libkern/Makefile.inc" @@ -55,19 +65,13 @@ LIBCOMPAT= ${COMPATLIB} LIBCOMPAT= ${COMPATLIB_PROF} .endif -# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP} -# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix, -# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file -# is marked as config-dependent. +# compile rules: rules are named ${TYPE}_${SUFFIX} where TYPE is NORMAL or +# HOSTED}, and SUFFIX is the file suffix, capitalized (e.g. C for a .c file). NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< -NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< - -DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< -DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< +NORMAL_S= ${CPP} ${AFLAGS} ${CPPFLAGS} $< | sed -e 's,^\#.*,,' | ${AS} -o ${.TARGET} -NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< -NORMAL_S_C= ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -c $< +HOSTED_C= ${HOSTED_CC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $< %OBJS @@ -93,9 +97,9 @@ DEBUG?= LINKFLAGS+= -X SYSTEM_LD_TAIL+=; \ echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \ - echo ${STRIP} $@; ${STRIP} $@ + echo ${STRIP} ${STRIPFLAGS} $@; ${STRIP} ${STRIPFLAGS} $@ .else -LINKFLAGS+= -x +LINKFLAGS+= -S .endif %LOAD @@ -107,14 +111,14 @@ genassym: genassym.o ${CC} -o $@ genassym.o genassym.o: ${ALPHA}/alpha/genassym.c - ${NORMAL_C_C} + ${HOSTED_C} param.c: $S/conf/param.c rm -f param.c cp $S/conf/param.c . param.o: param.c Makefile - ${NORMAL_C_C} + ${NORMAL_C} ioconf.o: ioconf.c ${NORMAL_C} @@ -125,11 +129,11 @@ newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} clean:: - rm -f eddep *bsd netbsd.gdb tags *.[io] [a-z]*.s \ + rm -f eddep *bsd bsd.gdb tags *.[io] [a-z]*.s \ [Ee]rrs linterrs makelinks genassym genassym.o assym.h lint: - @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} ${PARAM} -UKGDB \ + @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} -UKGDB \ ${ALPHA}/alpha/Locore.c ${CFILES} ${ALPHA}/alpha/swapgeneric.c \ ioconf.c param.c | \ grep -v 'static function .* unused' @@ -149,10 +153,11 @@ SRCS= ${ALPHA}/alpha/locore.s \ param.c ioconf.c ${CFILES} ${SFILES} depend:: .depend .depend: ${SRCS} assym.h param.c - mkdep ${AFLAGS} ${CPPFLAGS} ${ALPHA}/alpha/locore.s - mkdep -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} - mkdep -a ${AFLAGS} ${CPPFLAGS} ${SFILES} - mkdep -a ${CFLAGS} ${CPPFLAGS} ${PARAM} ${ALPHA}/alpha/genassym.c + ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${ALPHA}/alpha/locore.s + ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} + ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES} + ${MKDEP} -a ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} \ + ${ALPHA}/alpha/genassym.c # depend on root or device configuration diff --git a/sys/arch/alpha/conf/NOSY b/sys/arch/alpha/conf/NOSY index 5fddc1c81e5..61eddd751eb 100644 --- a/sys/arch/alpha/conf/NOSY +++ b/sys/arch/alpha/conf/NOSY @@ -1,10 +1,10 @@ -# $OpenBSD: NOSY,v 1.4 1996/09/20 06:44:51 deraadt Exp $ -# $NetBSD: NOSY,v 1.5.4.2 1996/06/13 19:22:15 cgd Exp $ +# $OpenBSD: NOSY,v 1.5 1996/10/30 22:38:42 niklas Exp $ +# $NetBSD: NOSY,v 1.9 1996/09/27 17:08:34 cgd Exp $ # # Jason's DEC 3000/400 in the lab... # -include "std.alpha" +include "arch/alpha/conf/std.alpha" maxusers 8 @@ -38,6 +38,7 @@ options COMPAT_43 #options COMPAT_09 options COMPAT_10 options COMPAT_11 +options COMPAT_12 # OSF/1 binary compatibility -- CURRENTLY DOES NOT WORK #options COMPAT_OSF1 diff --git a/sys/arch/alpha/conf/OPAL b/sys/arch/alpha/conf/OPAL index af1be26d67e..43440918adb 100644 --- a/sys/arch/alpha/conf/OPAL +++ b/sys/arch/alpha/conf/OPAL @@ -1,8 +1,8 @@ -# $OpenBSD: OPAL,v 1.3 1996/09/20 06:44:52 deraadt Exp $ +# $OpenBSD: OPAL,v 1.4 1996/10/30 22:38:43 niklas Exp $ # # OPAL, kernel for a DEC Multia at Applitron -include "std.alpha" +include "arch/alpha/conf/std.alpha" maxusers 8 @@ -25,9 +25,9 @@ option FFS # Fast file system option MFS # Memory-based file system option NFSSERVER # Sun NFS-compatible file system server option NFSCLIENT # Sun NFS-compatible file system client -option NULLFS # Loopback file system +#option NULLFS # Loopback file system #option MSDOSFS # MS-DOS file system -option UNION # Union file system +#option UNION # Union file system option CD9660 # ISO 9660 + Rock Ridge file system # SVR IPC @@ -45,6 +45,7 @@ option COMPAT_43 #option COMPAT_09 option COMPAT_10 option COMPAT_11 +option COMPAT_12 # OSF/1 binary compatibility -- CURRENTLY DOES NOT WORK option COMPAT_OSF1 @@ -151,3 +152,4 @@ pseudo-device loop pseudo-device pty 64 pseudo-device sl 4 pseudo-device vnd 4 +pseudo-device rd 1 diff --git a/sys/arch/alpha/conf/RAMDISK b/sys/arch/alpha/conf/RAMDISK new file mode 100644 index 00000000000..115116e2ad4 --- /dev/null +++ b/sys/arch/alpha/conf/RAMDISK @@ -0,0 +1,154 @@ +# $OpenBSD: RAMDISK,v 1.1 1996/10/30 22:38:44 niklas Exp $ +# $NetBSD: RAMDISK,v 1.4 1996/10/03 20:47:19 cgd Exp $ +# +# Generic Alpha kernel. Enough to get booted, etc., but not much more. + +include "arch/alpha/conf/std.alpha" + +maxusers 8 + +# CPU Support +options DEC_3000_500 # Flamingo etc: 3000/[4-9]00* +options DEC_3000_300 # Pelican etc: 3000/300* +options DEC_2100_A50 # Avanti etc: AlphaStation 400, 200, etc. +options DEC_KN20AA # KN20AA: AlphaStation 600 +options DEC_AXPPCI_33 # NoName: AXPpci33, etc. +#options DEC_2000_300 # "Jensen": 2000/300 (DECpc AXP 150) + +# Enable the hooks used for initializing the ram-disk. +options RAMDISK_HOOKS +options MINIROOTSIZE=8192 # 4 Megabytes! + +# needs to be set per system +options TIMEZONE="5*60" # Minutes west of GMT (for param.c) +options DST=1 # Daylight savings rules (for param.c) + +# Standard system options +options SWAPPAGER, DEVPAGER # Paging (mandatory) +options DEBUG, DIAGNOSTIC # Extra kernel debugging +options KTRACE # System call tracing support + +# File system options +options FIFO # POSIX fifo support (in all file systems) +options FFS # Fast file system +options MFS # Memory-based file system +options NFSSERVER # Sun NFS-compatible file system server +options NFSCLIENT # Sun NFS-compatible file system client + +# Networking options +options INET # Internet protocol suite + +# 4.3BSD compatibility. Should be optional, but necessary for now. +options COMPAT_43 + +# Binary compatibility with previous versions of NetBSD. +#options COMPAT_09 +options COMPAT_10 +options COMPAT_11 +options COMPAT_12 + +# OSF/1 binary compatibility -- CURRENTLY DOES NOT WORK +#options COMPAT_OSF1 + +# Loadable Kernel Modules +options LKM + +# Disable kernel security. +#options INSECURE + +# Misc. options +options EISAVERBOSE # recognize "unknown" EISA devices +options PCIVERBOSE # recognize "unknown" PCI devices +options TCVERBOSE # recognize "unknown" TC devices +options UCONSOLE # users can use TIOCCONS (for xconsole) + +config bsd swap generic +#config bsd root on sd0 swap on sd0 +#config bsd root nfs swap nfs + +mainbus0 at root +cpu* at mainbus0 + +# TurboChannel host bus adapter support +tcasic* at mainbus0 + +# TurboChannel bus support +tc* at tcasic? + +# TurboChannel devices +ioasic0 at tc? slot ? offset ? +mcclock0 at ioasic? offset ? +le* at ioasic? offset ? +scc0 at ioasic? offset ? +scc1 at ioasic? offset ? +tcds0 at tc? slot ? offset ? +esp0 at tcds? slot ? +esp1 at tcds? slot ? +cfb* at tc? slot ? offset ? +sfb* at tc? slot ? offset ? +le* at tc? slot ? offset ? +fta* at tc? slot ? offset ? # DEC DEFTA FDDI cards + +# PCI host bus adapter support +apecs* at mainbus? +cia* at mainbus? +lca* at mainbus? + +# PCI bus support +pci* at apecs? +pci* at cia? +pci* at lca? +pci* at ppb? + +# PCI devices +#ahc* at pci? dev ? function ? # AHA-28xx SCSI (NOT 64-BIT) +de* at pci? dev ? function ? # 21x4[012]-based Ethernet +en* at pci? dev ? function ? # ENI PCI ATM (untested) +ep* at pci? dev ? function ? # 3COM 3c59x (untested) +fpa* at pci? dev ? function ? # DEC DEFPA FDDI cards +le* at pci? dev ? function ? # PCI LANCE Ethernet (untested) +ncr* at pci? dev ? function ? # NCR 53c8xx SCSI +pceb* at pci? dev ? function ? # Intel PCI-EISA brige +pcivga* at pci? dev ? function ? # PCI VGA graphics +ppb* at pci? dev ? function ? # PCI-PCI bridges +sio* at pci? dev ? function ? # Intel PCI-ISA bridge +tga* at pci? dev ? function ? # DEC ZLXp-E[123] graphics + +# ISA/EISA bus support +isa* at pceb? +eisa* at pceb? +isa* at sio? + +# ISA devices +mcclock0 at isa? port 0x70 +pckbd0 at isa? port 0x60 irq 1 # PC-ish ISA keyboard +pms0 at isa? port 0x60 irq 12 # PS/2 auxiliary +com0 at isa? port 0x3f8 irq 4 # standard serial ports +com1 at isa? port 0x2f8 irq 3 +lpt0 at isa? port 0x3bc irq 7 # standard parallel port +#wss0 at isa? port 0x530 irq 9 drq 0 # Windows Sound System + +# EISA devices +fea* at eisa? slot ? # DEC DEFEA FDDI cards + +# SCSI bus support +scsibus* at esp? +scsibus* at ncr? + +# SCSI devices +sd* at scsibus? target ? lun ? +st* at scsibus? target ? lun ? +cd* at scsibus? target ? lun ? + +# Workstation Console attachments +wscons* at cfb? +wscons* at pcivga? +wscons* at sfb? +wscons* at tga? + +pseudo-device bpfilter 16 +pseudo-device loop +pseudo-device pty 64 +pseudo-device sl 4 +pseudo-device vnd 4 +pseudo-device rd 1 diff --git a/sys/arch/alpha/conf/files.alpha b/sys/arch/alpha/conf/files.alpha index e8dc3b51654..8df2ea1b219 100644 --- a/sys/arch/alpha/conf/files.alpha +++ b/sys/arch/alpha/conf/files.alpha @@ -1,9 +1,9 @@ -# $OpenBSD: files.alpha,v 1.5 1996/07/29 20:01:27 niklas Exp $ -# $NetBSD: files.alpha,v 1.19.4.2 1996/05/30 23:20:37 cgd Exp $ +# $OpenBSD: files.alpha,v 1.6 1996/10/30 22:38:45 niklas Exp $ +# $NetBSD: files.alpha,v 1.26 1996/09/27 17:14:35 cgd Exp $ # # alpha-specific configuration info -# maxpartitions must be first item in files.${ARCH}.newconf +# maxpartitions must be first item in files.${ARCH} maxpartitions 8 maxusers 2 8 64 @@ -25,18 +25,23 @@ file arch/alpha/alpha/cpu.c cpu # Machine-independent SCSI drivers # -include "../../../scsi/files.scsi" +include "scsi/files.scsi" major { st = 2 } major { cd = 3 } major { sd = 8 } +# RAM Disk +pseudo-device rd +file dev/ramdisk.c rd needs-flag +file arch/alpha/alpha/rd_root.c ramdisk_hooks +major { rd = 6 } # # raster console routines # define raster -include "../../../dev/rcons/files.rcons" +include "dev/rcons/files.rcons" file arch/alpha/wscons/wscons_rinit.c raster file arch/alpha/wscons/wscons_rops.c raster @@ -59,7 +64,7 @@ file arch/alpha/wscons/ms.c wscons # TurboChannel Devices # -include "../../../dev/tc/files.tc" +include "dev/tc/files.tc" device tcasic: tcbus attach tcasic at mainbus @@ -114,13 +119,13 @@ file dev/tc/if_le_tc.c le_tc # # Machine-independent ATAPI drivers # -include "../../../dev/atapi/files.atapi" +include "dev/atapi/files.atapi" # XXX Dummy bus needed for some multi-homed devices specified in files.isa define pcmcia {} -include "../../../dev/pci/files.pci" # XXX some ISA devs are 'at pci' too. -include "../../../dev/isa/files.isa" +include "dev/pci/files.pci" # XXX some ISA devs are 'at pci' too. +include "dev/isa/files.isa" #file arch/alpha/isa/isafcns_jensen.c dec_2000_300 @@ -145,14 +150,14 @@ file arch/alpha/isa/pms.c pms needs-flag # EISA Bus support # -include "../../../dev/eisa/files.eisa" +include "dev/eisa/files.eisa" # # PCI Bus support # -# include "../../../dev/pci/files.pci" XXX SEE ABOVE +# include "dev/pci/files.pci" XXX SEE ABOVE device apecs: pcibus attach apecs at mainbus @@ -227,10 +232,11 @@ file arch/alpha/alpha/interrupt.c file arch/alpha/alpha/machdep.c file arch/alpha/alpha/mainbus.c file arch/alpha/alpha/mem.c -file arch/alpha/alpha/pmap.c +file arch/alpha/alpha/pmap.c new_pmap +file arch/alpha/alpha/pmap.old.c !new_pmap file arch/alpha/alpha/process_machdep.c file arch/alpha/alpha/prom.c -file arch/alpha/alpha/support.c +#file arch/alpha/alpha/support.c file arch/alpha/alpha/sys_machdep.c file arch/alpha/alpha/trap.c file arch/alpha/alpha/vm_machdep.c @@ -242,7 +248,8 @@ file dev/cons.c # Optional/miscellaneous files # -file arch/alpha/alpha/in_cksum.c inet +file arch/alpha/alpha/in_cksum.c inet & !generic_in_cksum +file netinet/in_cksum.c inet & generic_in_cksum file netns/ns_cksum.c ns # XXX @@ -257,4 +264,4 @@ file arch/alpha/alpha/dec_axppci_33.c dec_axppci_33 file arch/alpha/alpha/dec_21000.c dec_21000 # OSF/1 Binary Compatibility (COMPAT_OSF1) -include "../../../compat/osf1/files.osf1" +include "compat/osf1/files.osf1" diff --git a/sys/arch/alpha/conf/std.alpha b/sys/arch/alpha/conf/std.alpha index a81b37efa17..21d789851c8 100644 --- a/sys/arch/alpha/conf/std.alpha +++ b/sys/arch/alpha/conf/std.alpha @@ -1,10 +1,13 @@ -# $OpenBSD: std.alpha,v 1.2 1996/07/29 20:01:27 niklas Exp $ -# $NetBSD: std.alpha,v 1.4 1995/11/25 01:34:38 cgd Exp $ +# $OpenBSD: std.alpha,v 1.3 1996/10/30 22:38:46 niklas Exp $ +# $NetBSD: std.alpha,v 1.8 1996/09/27 17:18:02 cgd Exp $ # # Standard/required configuration info for OpenBSD/alpha. machine alpha makeoptions DEBUG="-g" +#makeoptions CWARNFLAGS="-Werror" options EXEC_ECOFF +options EXEC_ELF64 +options EXEC_SCRIPT diff --git a/sys/arch/alpha/eisa/eisa_machdep.h b/sys/arch/alpha/eisa/eisa_machdep.h index ce8ac9e426d..589f705592c 100644 --- a/sys/arch/alpha/eisa/eisa_machdep.h +++ b/sys/arch/alpha/eisa/eisa_machdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: eisa_machdep.h,v 1.2 1996/07/29 22:58:21 niklas Exp $ */ +/* $OpenBSD: eisa_machdep.h,v 1.3 1996/10/30 22:38:47 niklas Exp $ */ /* $NetBSD: eisa_machdep.h,v 1.1 1996/04/12 05:39:51 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/alpha_cpu.h b/sys/arch/alpha/include/alpha_cpu.h new file mode 100644 index 00000000000..0c695e1612f --- /dev/null +++ b/sys/arch/alpha/include/alpha_cpu.h @@ -0,0 +1,281 @@ +/* $OpenBSD: alpha_cpu.h,v 1.1 1996/10/30 22:38:49 niklas Exp $ */ +/* $NetBSD: alpha_cpu.h,v 1.6 1996/08/20 23:02:17 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. + */ + +#ifndef __ALPHA_ALPHA_CPU_H__ +#define __ALPHA_ALPHA_CPU_H__ + +/* + * Alpha CPU + OSF/1 PALcode definitions for use by the kernel. + * + * Definitions for: + * + * Process Control Block + * Interrupt/Exception/Syscall Stack Frame + * Processor Status Register + * Machine Check Error Summary Register + * Machine Check Logout Area + * Virtual Memory Management + * Kernel Entry Vectors + * MMCSR Fault Type Codes + * Translation Buffer Invalidation + * + * and miscellaneous PALcode operations. + */ + + +/* + * Process Control Block definitions [OSF/1 PALcode Specific] + */ + +struct alpha_pcb { + unsigned long apcb_ksp; /* kernel stack ptr */ + unsigned long apcb_usp; /* user stack ptr */ + unsigned long apcb_ptbr; /* page table base reg */ + unsigned int apcb_cpc; /* charged process cycles */ + unsigned int apcb_asn; /* address space number */ + unsigned long apcb_unique; /* process unique value */ + unsigned long apcb_flags; /* flags; see below */ + unsigned long apcb_decrsv0; /* DEC reserved */ + unsigned long apcb_decrsv1; /* DEC reserved */ +}; + +#define ALPHA_PCB_FLAGS_FEN 0x0000000000000001 +#define ALPHA_PCB_FLAGS_PME 0x4000000000000000 + +/* + * Interrupt/Exception/Syscall "Hardware" (really PALcode) + * Stack Frame definitions + * + * These are quadword offsets from the sp on kernel entry, i.e. + * to get to the value in question you access (sp + (offset * 8)). + * + * On syscall entry, A0-A2 aren't written to memory but space + * _is_ reserved for them. + */ + +#define ALPHA_HWFRAME_PS 0 /* processor status register */ +#define ALPHA_HWFRAME_PC 1 /* program counter */ +#define ALPHA_HWFRAME_GP 2 /* global pointer */ +#define ALPHA_HWFRAME_A0 3 /* a0 */ +#define ALPHA_HWFRAME_A1 4 /* a1 */ +#define ALPHA_HWFRAME_A2 5 /* a2 */ + +#define ALPHA_HWFRAME_SIZE 6 /* 6 8-byte words */ + +/* + * Processor Status Register [OSF/1 PALcode Specific] + * + * Includes user/kernel mode bit, interrupt priority levels, etc. + */ + +#define ALPHA_PSL_USERMODE 0x0008 /* set -> user mode */ +#define ALPHA_PSL_IPL_MASK 0x0007 /* interrupt level mask */ + +#define ALPHA_PSL_IPL_0 0x0000 /* all interrupts enabled */ +#define ALPHA_PSL_IPL_SOFT 0x0001 /* software ints disabled */ +#define ALPHA_PSL_IPL_IO 0x0004 /* I/O dev ints disabled */ +#define ALPHA_PSL_IPL_CLOCK 0x0005 /* clock ints disabled */ +#define ALPHA_PSL_IPL_HIGH 0x0006 /* all but mchecks disabled */ + +#define ALPHA_PSL_MUST_BE_ZERO 0xfffffffffffffff0 + +/* Convenience constants: what must be set/clear in user mode */ +#define ALPHA_PSL_USERSET ALPHA_PSL_USERMODE +#define ALPHA_PSL_USERCLR (ALPHA_PSL_MUST_BE_ZERO | ALPHA_PSL_IPL_MASK) + +/* + * Machine Check Error Summary Register definitions [OSF/1 PALcode Specific] + * + * The following bits are values as read. On write, _PCE, _SCE, and + * _MIP are "write 1 to clear." + */ + +#define ALPHA_MCES_IMP \ + 0xffffffff00000000 /* impl. dependent */ +#define ALPHA_MCES_RSVD \ + 0x00000000ffffffe0 /* reserved */ +#define ALPHA_MCES_DSC \ + 0x0000000000000010 /* disable system correctable error reporting */ +#define ALPHA_MCES_DPC \ + 0x0000000000000008 /* disable processor correctable error reporting */ +#define ALPHA_MCES_PCE \ + 0x0000000000000004 /* processor correctable error in progress */ +#define ALPHA_MCES_SCE \ + 0x0000000000000002 /* system correctable error in progress */ +#define ALPHA_MCES_MIP \ + 0x0000000000000001 /* machine check in progress */ + +/* + * Machine Check Error Summary Register definitions [OSF/1 PALcode Specific] + */ + +struct alpha_logout_area { + unsigned int la_frame_size; /* frame size */ + unsigned int la_flags; /* flags; see below */ + unsigned int la_cpu_offset; /* offset to cpu area */ + unsigned int la_system_offset; /* offset to system area */ +}; + +#define ALPHA_LOGOUT_FLAGS_RETRY 0x80000000 /* OK to continue */ +#define ALPHA_LOGOUT_FLAGS_SE 0x40000000 /* second error */ +#define ALPHA_LOGOUT_FLAGS_SBZ 0x3fffffff /* should be zero */ + +#define ALPHA_LOGOUT_NOT_BUILT \ + (struct alpha_logout_area *)0xffffffffffffffff) + +#define ALPHA_LOGOUT_PAL_AREA(lap) \ + (unsigned long *)((unsigned char *)(lap) + 16) +#define ALPHA_LOGOUT_PAL_SIZE(lap) \ + ((lap)->la_cpu_offset - 16) +#define ALPHA_LOGOUT_CPU_AREA(lap) \ + (unsigned long *)((unsigned char *)(lap) + (lap)->la_cpu_offset) +#define ALPHA_LOGOUT_CPU_SIZE(lap) \ + ((lap)->la_system_offset - (lap)->la_cpu_offset) +#define ALPHA_LOGOUT_SYSTEM_AREA(lap) \ + (unsigned long *)((unsigned char *)(lap) + (lap)->la_system_offset) +#define ALPHA_LOGOUT_SYSTEM_SIZE(lap) \ + ((lap)->la_frame_size - (lap)->la_system_offset) + +/* + * Virtual Memory Management definitions [OSF/1 PALcode Specific] + * + * Includes user and kernel space addresses and information, + * page table entry definitions, etc. + * + * NOTE THAT THESE DEFINITIONS MAY CHANGE IN FUTURE ALPHA CPUS! + */ + +#define ALPHA_PGSHIFT 13 +#define ALPHA_PGBYTES (1 << ALPHA_PGSHIFT) + +#define ALPHA_USEG_BASE 0 /* virtual */ +#define ALPHA_USEG_END 0x000003ffffffffff + +#define ALPHA_K0SEG_BASE 0xfffffc0000000000 /* direct-mapped */ +#define ALPHA_K0SEG_END 0xfffffdffffffffff +#define ALPHA_K1SEG_BASE 0xfffffe0000000000 /* virtual */ +#define ALPHA_K1SEG_END 0xffffffffffffffff + +#define ALPHA_K0SEG_TO_PHYS(x) ((x) & 0x00000003ffffffff) +#define ALPHA_PHYS_TO_K0SEG(x) ((x) | ALPHA_K0SEG_BASE) + +#define ALPHA_PTE_VALID 0x0001 + +#define ALPHA_PTE_FAULT_ON_READ 0x0002 +#define ALPHA_PTE_FAULT_ON_WRITE 0x0004 +#define ALPHA_PTE_FAULT_ON_EXECUTE 0x0008 + +#define ALPHA_PTE_ASM 0x0010 /* addr. space match */ +#define ALPHA_PTE_GRANULARITY 0x0060 /* granularity hint */ + +#define ALPHA_PTE_PROT 0xff00 +#define ALPHA_PTE_KR 0x0100 +#define ALPHA_PTE_UR 0x0200 +#define ALPHA_PTE_KW 0x1000 +#define ALPHA_PTE_UW 0x2000 + +#define ALPHA_PTE_WRITE (ALPHA_PTE_KW | ALPHA_PTE_KW) + +#define ALPHA_PTE_SOFTWARE 0xffff0000 + +#define ALPHA_PTE_PFN 0xffffffff00000000 + +#define ALPHA_PTE_TO_PFN(pte) ((pte) >> 32) +#define ALPHA_PTE_FROM_PFN(pfn) ((pfn) << 32) + +typedef unsigned long alpha_pt_entry_t; + +/* + * Kernel Entry Vectors. [OSF/1 PALcode Specific] + */ + +#define ALPHA_KENTRY_INT 0 +#define ALPHA_KENTRY_ARITH 1 +#define ALPHA_KENTRY_MM 2 +#define ALPHA_KENTRY_IF 3 +#define ALPHA_KENTRY_UNA 4 +#define ALPHA_KENTRY_SYS 5 + +/* + * MMCSR Fault Type Codes. [OSF/1 PALcode Specific] + */ + +#define ALPHA_MMCSR_INVALTRANS 0 +#define ALPHA_MMCSR_ACCESS 1 +#define ALPHA_MMCSR_FOR 2 +#define ALPHA_MMCSR_FOE 3 +#define ALPHA_MMCSR_FOW 4 + +/* + * Instruction Fault Type Codes. [OSF/1 PALcode Specific] + */ + +#define ALPHA_IF_CODE_BPT 0 +#define ALPHA_IF_CODE_BUGCHK 1 +#define ALPHA_IF_CODE_GENTRAP 2 +#define ALPHA_IF_CODE_FEN 3 +#define ALPHA_IF_CODE_OPDEC 4 + +/* + * Translation Buffer Invalidation definitions [OSF/1 PALcode Specific] + */ + +#define ALPHA_TBIA() alpha_pal_tbi(-2, 0) /* all TB entries */ +#define ALPHA_TBIAP() alpha_pal_tbi(-1, 0) /* all per-process */ +#define ALPHA_TBISI(va) alpha_pal_tbi(1, (va)) /* ITB entry for va */ +#define ALPHA_TBISD(va) alpha_pal_tbi(2, (va)) /* DTB entry for va */ +#define ALPHA_TBIS(va) alpha_pal_tbi(3, (va)) /* all for va */ + +/* + * Stubs for Alpha instructions normally inaccessible from C. + */ +unsigned long alpha_rpcc __P((void)); +void alpha_mb __P((void)); +void alpha_wmb __P((void)); + +/* + * Stubs for OSF/1 PALcode operations. + */ +void alpha_pal_imb __P((void)); +void alpha_pal_draina __P((void)); +void alpha_pal_halt __P((void)) __attribute__((__noreturn__)); +unsigned long alpha_pal_rdmces __P((void)); +unsigned long alpha_pal_rdusp __P((void)); +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)); +unsigned long alpha_pal_whami __P((void)); +void alpha_pal_wrent __P((void *, unsigned long)); +void alpha_pal_wrfen __P((unsigned long)); +void alpha_pal_wrusp __P((unsigned long)); +void alpha_pal_wrvptptr __P((unsigned long)); +void alpha_pal_wrmces __P((unsigned long)); + +#endif __ALPHA_ALPHA_CPU_H__ diff --git a/sys/arch/alpha/include/ansi.h b/sys/arch/alpha/include/ansi.h index 6e005d9b3b6..7e529f40e07 100644 --- a/sys/arch/alpha/include/ansi.h +++ b/sys/arch/alpha/include/ansi.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ansi.h,v 1.4 1996/07/29 22:58:23 niklas Exp $ */ -/* $NetBSD: ansi.h,v 1.4 1996/03/16 01:31:45 jtc Exp $ */ +/* $OpenBSD: ansi.h,v 1.5 1996/10/30 22:38:50 niklas Exp $ */ +/* $NetBSD: ansi.h,v 1.5 1996/10/09 21:13:04 cgd Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -55,7 +55,8 @@ #define _BSD_TIME_T_ int /* time() */ typedef struct { char *base; - long offset; + int offset; + int pad; } __va_list; #define _BSD_VA_LIST_ __va_list /* va_list */ diff --git a/sys/arch/alpha/include/trap.h b/sys/arch/alpha/include/aout_machdep.h index 78a6ef53ec6..badaa8c07d8 100644 --- a/sys/arch/alpha/include/trap.h +++ b/sys/arch/alpha/include/aout_machdep.h @@ -1,5 +1,4 @@ -/* $OpenBSD: trap.h,v 1.2 1996/07/29 22:59:25 niklas Exp $ */ -/* $NetBSD: trap.h,v 1.1 1995/02/13 23:07:58 cgd Exp $ */ +/* $NetBSD: aout_machdep.h,v 1.1 1995/02/13 23:07:37 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -28,22 +27,12 @@ * rights to redistribute these changes. */ -#define T_ASTFLT 0x00 -#define T_UNAFLT 0x01 -#define T_ARITHFLT 0x02 +#ifndef _ALPHA_EXEC_H_ +#define _ALPHA_EXEC_H_ -#define T_IFLT 0x10 -#define T_BPT (T_IFLT|0x00) -#define T_BUGCHK (T_IFLT|0x01) -#define T_GENTRAP (T_IFLT|0x02) -#define T_FPDISABLED (T_IFLT|0x03) -#define T_OPDEC (T_IFLT|0x04) +#define cpu_exec_aout_makecmds(p, epp) ENOEXEC -#define T_MMFLT 0x20 -#define T_INVALTRANS (T_MMFLT|0x00) -#define T_ACCESS (T_MMFLT|0x01) -#define T_FOR (T_MMFLT|0x02) -#define T_FOE (T_MMFLT|0x03) -#define T_FOW (T_MMFLT|0x04) +/* Size of a page in an object file. */ +#define __LDPGSZ 8192 -#define T_USER 0x80 /* user-mode flag or'ed with type */ +#endif /* !_ALPHA_EXEC_H_ */ diff --git a/sys/arch/alpha/include/asm.h b/sys/arch/alpha/include/asm.h index 2c96e4c625c..0dbea2e046f 100644 --- a/sys/arch/alpha/include/asm.h +++ b/sys/arch/alpha/include/asm.h @@ -1,5 +1,5 @@ -/* $OpenBSD: asm.h,v 1.4 1996/07/29 22:58:25 niklas Exp $ */ -/* $NetBSD: asm.h,v 1.4 1996/04/12 01:36:51 cgd Exp $ */ +/* $OpenBSD: asm.h,v 1.5 1996/10/30 22:38:52 niklas Exp $ */ +/* $NetBSD: asm.h,v 1.10 1996/10/17 18:33:53 cgd Exp $ */ /* * Copyright (c) 1991,1990,1989,1994,1995,1996 Carnegie Mellon University @@ -130,6 +130,22 @@ #define ai $25 /* (T) argument information */ #define pv $27 /* (T) procedure value */ + +/* + * Useful stuff. + */ +#ifdef __STDC__ +#define __CONCAT(a,b) a ## b +#else +#define __CONCAT(a,b) a/**/b +#endif +#define ___CONCAT(a,b) __CONCAT(a,b) + +/* + * Macro to make a local label name. + */ +#define LLABEL(name,num) ___CONCAT(___CONCAT(L,name),num) + /* * * Debuggers need symbol table information to be able to properly @@ -203,18 +219,9 @@ #define MCOUNT /* nothing */ #else #define MCOUNT \ - lda sp, -16(sp); \ - stq pv, 0(sp); \ - \ - br pv, 1f; \ -1: ldgp gp, 0(pv); \ - lda pv, _mcount; \ - jsr at_reg, (pv); \ - br pv, 2f; \ -2: ldgp gp, 0(pv); \ - \ - ldq pv, 0(sp); \ - lda sp, 16(sp) + .set noat; \ + jsr at_reg,_mcount; \ + .set at #endif /* @@ -434,26 +441,26 @@ _name_:; \ * Allocate space for a message (a read-only ascii string) */ #define ASCIZ .asciz -#define MSG(msg,reg) \ - lda reg, 9f; \ +#define MSG(msg,reg,label) \ + lda reg, label; \ .data; \ -9: ASCIZ msg; \ +label: ASCIZ msg; \ .text; /* * PRINTF * Print a message */ -#define PRINTF(msg) \ - MSG(msg,a0); \ +#define PRINTF(msg,label) \ + MSG(msg,a0,label); \ CALL(printf) /* * PANIC * Fatal error (KERNEL) */ -#define PANIC(msg) \ - MSG(msg,a0); \ +#define PANIC(msg,label) \ + MSG(msg,a0,label); \ CALL(panic) /* @@ -541,9 +548,10 @@ _name_:; \ * are unprivileged. */ -/* Common PAL codes. */ +/* Common PAL function codes. */ #define PAL_halt 0x0000 /* P */ #define PAL_draina 0x0002 /* P */ +#define PAL_cserve 0x0009 /* P */ #define PAL_swppal 0x000a /* P */ #define PAL_bpt 0x0080 /* U */ #define PAL_bugchk 0x0081 /* U */ @@ -552,7 +560,7 @@ _name_:; \ #define PAL_wrunique 0x009f /* U */ #define PAL_gentrap 0x00aa /* U */ -/* VMS PAL codes. */ +/* VMS PAL function codes. */ #define PAL_VMS_ldqp 0x0003 /* P */ #define PAL_VMS_stqp 0x0004 /* P */ #define PAL_VMS_mtpr_fen 0x000c /* P */ @@ -575,7 +583,9 @@ _name_:; \ #define PAL_VMS_mfpr_whami 0x003f /* P */ #define PAL_VMS_rei 0x0092 /* U */ -/* OSF/1 PAL codes. */ +/* OSF/1 PAL function codes. */ +#define PAL_OSF1_rdmces 0x0010 /* P */ +#define PAL_OSF1_wrmces 0x0011 /* P */ #define PAL_OSF1_wrfen 0x002b /* P */ #define PAL_OSF1_wrvptptr 0x002d /* P */ #define PAL_OSF1_swpctx 0x0030 /* P */ @@ -594,13 +604,28 @@ _name_:; \ #define PAL_OSF1_callsys 0x0083 /* U */ #define PAL_OSF1_imb 0x0086 /* U */ + /* - * Defintions to make things portable between gcc and OSF/1 cc. + * System call glue. */ -#define SETGP(pv) ldgp gp,0(pv) +#define SYSCALLNUM(name) \ + ___CONCAT(SYS_,name) -#define MF_FPCR(x) mf_fpcr x -#define MT_FPCR(x) mt_fpcr x -#define JMP(loc) jmp zero,loc -#define CONST(c,reg) ldiq reg, c +#define CALLSYS_NOERROR(name) \ + ldiq v0, SYSCALLNUM(name); \ + call_pal PAL_OSF1_callsys + +/* + * Load the global pointer. + */ +#define LDGP(reg) \ + ldgp gp, 0(reg) +/* + * WEAK_ALIAS: create a weak alias (ELF only). + */ +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym +#endif diff --git a/sys/arch/alpha/include/autoconf.h b/sys/arch/alpha/include/autoconf.h index 5531aa9d3f6..517d0f2fc5f 100644 --- a/sys/arch/alpha/include/autoconf.h +++ b/sys/arch/alpha/include/autoconf.h @@ -1,5 +1,5 @@ -/* $OpenBSD: autoconf.h,v 1.5 1996/10/18 14:47:07 niklas Exp $ */ -/* $NetBSD: autoconf.h,v 1.2.4.2 1996/06/13 18:35:23 cgd Exp $ */ +/* $OpenBSD: autoconf.h,v 1.6 1996/10/30 22:38:54 niklas Exp $ */ +/* $NetBSD: autoconf.h,v 1.5 1996/07/14 04:12:59 cgd Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -81,10 +81,12 @@ struct bootdev_data { char *ctrl_dev_type; }; -void device_register __P((struct device *, void *)); -void set_clockintr __P((void)); -void set_iointr __P((void (*)(void *, int))); -int badaddr __P((void *, u_int64_t)); +void set_clockintr __P((void)); +void set_iointr __P((void (*)(void *, unsigned long))); +int badaddr __P((void *, size_t)); +void configure __P((void)); +void device_register __P((struct device *, void *)); +void dumpconf __P((void)); #ifdef EVCNT_COUNTERS extern struct evcnt clock_intr_evcnt; diff --git a/sys/arch/alpha/include/bus.h b/sys/arch/alpha/include/bus.h index 61cd8cbcbe5..75e7d3fe992 100644 --- a/sys/arch/alpha/include/bus.h +++ b/sys/arch/alpha/include/bus.h @@ -1,5 +1,5 @@ -/* $OpenBSD: bus.h,v 1.2 1996/07/29 22:58:29 niklas Exp $ */ -/* $NetBSD: bus.h,v 1.2.4.2 1996/06/13 17:44:45 cgd Exp $ */ +/* $OpenBSD: bus.h,v 1.3 1996/10/30 22:38:55 niklas Exp $ */ +/* $NetBSD: bus.h,v 1.4 1996/06/11 21:16:21 cgd Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/include/cdefs.h b/sys/arch/alpha/include/cdefs.h index c39c2620736..05b289d79c4 100644 --- a/sys/arch/alpha/include/cdefs.h +++ b/sys/arch/alpha/include/cdefs.h @@ -1,8 +1,8 @@ -/* $OpenBSD: cdefs.h,v 1.4 1996/07/29 22:58:30 niklas Exp $ */ -/* $NetBSD: cdefs.h,v 1.2 1995/05/03 00:13:55 cgd Exp $ */ +/* $OpenBSD: cdefs.h,v 1.5 1996/10/30 22:38:56 niklas Exp $ */ +/* $NetBSD: cdefs.h,v 1.5 1996/10/12 18:08:12 cgd Exp $ */ /* - * Copyright (c) 1995 Carnegie-Mellon University. + * Copyright (c) 1995, 1996 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou @@ -33,7 +33,35 @@ #define _C_LABEL(x) _STRING(x) -#define __indr_references(sym,msg) /* nothing */ +#ifdef __ELF__ + +#define __indr_reference(sym,alias) /* nada, since we do weak refs */ + +#ifdef __STDC__ + +#define __weak_alias(alias,sym) \ + __asm__(".weak " #alias " ; " #alias " = " #sym) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." #sym " ; .ascii \"" msg "\" ; .text") + +#else /* !__STDC__ */ + +#define __weak_alias(alias,sym) \ + __asm__(".weak alias ; alias = sym") +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning.sym ; .ascii msg ; .text") + +#endif /* !__STDC__ */ + +#else /* !__ELF__ */ + +/* + * Very little to do if not ELF: we support neither indirect or + * weak references, and don't do anything with warnings. + */ + #define __warn_references(sym,msg) /* nothing */ +#endif /* !__ELF__ */ + #endif /* !_MACHINE_CDEFS_H_ */ diff --git a/sys/arch/alpha/include/cfbreg.h b/sys/arch/alpha/include/cfbreg.h index 4707077c82b..d5e7222a6ad 100644 --- a/sys/arch/alpha/include/cfbreg.h +++ b/sys/arch/alpha/include/cfbreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cfbreg.h,v 1.2 1996/07/29 22:58:32 niklas Exp $ */ +/* $OpenBSD: cfbreg.h,v 1.3 1996/10/30 22:38:57 niklas Exp $ */ /* $NetBSD: cfbreg.h,v 1.1 1996/05/01 23:25:00 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/cpu.h b/sys/arch/alpha/include/cpu.h index 9dbabd53d4a..cb08112157d 100644 --- a/sys/arch/alpha/include/cpu.h +++ b/sys/arch/alpha/include/cpu.h @@ -1,5 +1,5 @@ -/* $OpenBSD: cpu.h,v 1.4 1996/07/29 22:58:33 niklas Exp $ */ -/* $NetBSD: cpu.h,v 1.7.4.1 1996/06/14 20:42:44 cgd Exp $ */ +/* $OpenBSD: cpu.h,v 1.5 1996/10/30 22:38:58 niklas Exp $ */ +/* $NetBSD: cpu.h,v 1.12 1996/07/14 04:15:10 cgd Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -66,9 +66,11 @@ struct clockframe { struct trapframe cf_tf; }; -#define CLKF_USERMODE(framep) (((framep)->cf_tf.tf_ps & PSL_U) != 0) -#define CLKF_BASEPRI(framep) (((framep)->cf_tf.tf_ps & PSL_IPL) == 0) -#define CLKF_PC(framep) ((framep)->cf_tf.tf_pc) +#define CLKF_USERMODE(framep) \ + (((framep)->cf_tf.tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0) +#define CLKF_BASEPRI(framep) \ + (((framep)->cf_tf.tf_regs[FRAME_PS] & ALPHA_PSL_IPL_MASK) == 0) +#define CLKF_PC(framep) ((framep)->cf_tf.tf_regs[FRAME_PC]) /* * XXX No way to accurately tell if we were in interrupt mode before taking * clock interrupt. @@ -101,28 +103,22 @@ u_int64_t want_resched; /* resched() was called */ /* - * simulated software interrupt register - */ -extern u_int64_t ssir; - -#define SIR_NET 0x1 -#define SIR_CLOCK 0x2 - -#define siroff(x) ssir &= ~(x) -#define setsoftnet() ssir |= SIR_NET -#define setsoftclock() ssir |= SIR_CLOCK - -/* * CTL_MACHDEP definitions. */ #define CPU_CONSDEV 1 /* dev_t: console terminal device */ #define CPU_ROOT_DEVICE 2 /* string: root device name */ -#define CPU_MAXID 3 /* number of valid machdep ids */ +#define CPU_UNALIGNED_PRINT 3 /* int: print unaligned accesses */ +#define CPU_UNALIGNED_FIX 4 /* int: fix unaligned accesses */ +#define CPU_UNALIGNED_SIGBUS 5 /* int: SIGBUS unaligned accesses */ +#define CPU_MAXID 6 /* 5 valid machdep IDs */ #define CTL_MACHDEP_NAMES { \ { 0, 0 }, \ { "console_device", CTLTYPE_STRUCT }, \ { "root_device", CTLTYPE_STRING }, \ + { "unaligned_print", CTLTYPE_INT }, \ + { "unaligned_fix", CTLTYPE_INT }, \ + { "unaligned_sigbus", CTLTYPE_INT }, \ } #endif /* _ALPHA_CPU_H_ */ diff --git a/sys/arch/alpha/include/db_machdep.h b/sys/arch/alpha/include/db_machdep.h index d7f713a78ba..7a5aadc64b6 100644 --- a/sys/arch/alpha/include/db_machdep.h +++ b/sys/arch/alpha/include/db_machdep.h @@ -1,5 +1,5 @@ -/* $OpenBSD: db_machdep.h,v 1.2 1996/07/29 22:58:35 niklas Exp $ */ -/* $NetBSD: db_machdep.h,v 1.1 1995/11/23 02:35:54 cgd Exp $ */ +/* $OpenBSD: db_machdep.h,v 1.3 1996/10/30 22:38:58 niklas Exp $ */ +/* $NetBSD: db_machdep.h,v 1.2 1996/07/11 05:31:31 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -46,12 +46,12 @@ 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_pc) +#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) -#define FIXUP_PC_AFTER_BREAK ddb_regs.tf_pc -= BKPT_SIZE; +#define FIXUP_PC_AFTER_BREAK ddb_regs.tf_regs[FRAME_PC] -= BKPT_SIZE; #endif /* _ALPHA_DB_MACHDEP_H_ */ diff --git a/sys/arch/alpha/include/disklabel.h b/sys/arch/alpha/include/disklabel.h index fe4987cfead..0bdfb430483 100644 --- a/sys/arch/alpha/include/disklabel.h +++ b/sys/arch/alpha/include/disklabel.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.2 1996/07/29 22:58:37 niklas Exp $ */ +/* $OpenBSD: disklabel.h,v 1.3 1996/10/30 22:38:59 niklas Exp $ */ /* $NetBSD: disklabel.h,v 1.1 1995/02/13 23:07:34 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/ecoff.h b/sys/arch/alpha/include/ecoff.h index a6d8b13363f..b605b5421f2 100644 --- a/sys/arch/alpha/include/ecoff.h +++ b/sys/arch/alpha/include/ecoff.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ecoff.h,v 1.5 1996/07/29 22:58:39 niklas Exp $ */ +/* $OpenBSD: ecoff.h,v 1.6 1996/10/30 22:39:00 niklas Exp $ */ /* $NetBSD: ecoff.h,v 1.3 1996/05/09 23:47:25 cgd Exp $ */ /* @@ -43,10 +43,10 @@ u_long gp_value #define ECOFF_MAGIC_ALPHA 0603 -#define ECOFF_MAGIC_NETBSD_ALPHA 0605 +#define ECOFF_MAGIC_NATIVE_ALPHA 0605 #define ECOFF_BADMAG(ep) \ ((ep)->f.f_magic != ECOFF_MAGIC_ALPHA && \ - (ep)->f.f_magic != ECOFF_MAGIC_NETBSD_ALPHA) + (ep)->f.f_magic != ECOFF_MAGIC_NATIVE_ALPHA) #define ECOFF_FLAG_EXEC 0002 #define ECOFF_SEGMENT_ALIGNMENT(ep) \ @@ -93,3 +93,8 @@ struct ecoff_extsym { unsigned :29; int es_indexfld; }; + +#ifdef _KERNEL +void cpu_exec_ecoff_setregs + __P((struct proc *, struct exec_package *, u_long, register_t *)); +#endif diff --git a/sys/arch/alpha/include/ecoff_machdep.h b/sys/arch/alpha/include/ecoff_machdep.h new file mode 100644 index 00000000000..9f2d2447113 --- /dev/null +++ b/sys/arch/alpha/include/ecoff_machdep.h @@ -0,0 +1,95 @@ +/* $OpenBSD: ecoff_machdep.h,v 1.1 1996/10/30 22:39:01 niklas Exp $ */ +/* $NetBSD: ecoff_machdep.h,v 1.3 1996/05/09 23:47:25 cgd Exp $ */ + +/* + * Copyright (c) 1994 Adam Glass + * 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 Adam Glass. + * 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 Adam Glass ``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 Adam Glass 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. + */ + +#define ECOFF_LDPGSZ 4096 + +#define ECOFF_PAD \ + u_short bldrev; /* XXX */ + +#define ECOFF_MACHDEP \ + u_int gprmask; \ + u_int fprmask; \ + u_long gp_value + +#define ECOFF_MAGIC_ALPHA 0603 +#define ECOFF_MAGIC_NATIVE_ALPHA 0605 +#define ECOFF_BADMAG(ep) \ + ((ep)->f.f_magic != ECOFF_MAGIC_ALPHA && \ + (ep)->f.f_magic != ECOFF_MAGIC_NATIVE_ALPHA) + +#define ECOFF_FLAG_EXEC 0002 +#define ECOFF_SEGMENT_ALIGNMENT(ep) \ + (((ep)->f.f_flags & ECOFF_FLAG_EXEC) == 0 ? 8 : 16) + +struct ecoff_symhdr { + int16_t magic; + int16_t vstamp; + int32_t lineMax; + int32_t densenumMax; + int32_t procMax; + int32_t lsymMax; + int32_t optsymMax; + int32_t auxsymMax; + int32_t lstrMax; + int32_t estrMax; + int32_t fdMax; + int32_t rfdMax; + int32_t esymMax; + long linesize; + long cbLineOffset; + long cbDnOffset; + long cbPdOffset; + long cbSymOffset; + long cbOptOffset; + long cbAuxOffset; + long cbSsOffset; + long cbSsExtOffset; + long cbFdOffset; + long cbRfdOffset; + long cbExtOffset; +}; + +struct ecoff_extsym { + long es_value; + int es_strindex; + unsigned es_type:6; + unsigned es_class:5; + unsigned :1; + unsigned es_symauxindex:20; + unsigned es_jmptbl:1; + unsigned es_cmain:1; + unsigned es_weakext:1; + unsigned :29; + int es_indexfld; +}; diff --git a/sys/arch/alpha/include/elf_machdep.h b/sys/arch/alpha/include/elf_machdep.h new file mode 100644 index 00000000000..5f6c6b545f7 --- /dev/null +++ b/sys/arch/alpha/include/elf_machdep.h @@ -0,0 +1,9 @@ +/* $OpenBSD: elf_machdep.h,v 1.1 1996/10/30 22:39:02 niklas Exp $ */ +/* $NetBSD: elf_machdep.h,v 1.1 1996/09/26 21:50:57 cgd Exp $ */ + +#define ELF32_MACHDEP_ID_CASES \ + /* no 32-bit ELF machine types supported */ + +#define ELF64_MACHDEP_ID_CASES \ + case Elf_em_alpha: \ + break; diff --git a/sys/arch/alpha/include/endian.h b/sys/arch/alpha/include/endian.h index 4cbdb950046..ec524c5f64e 100644 --- a/sys/arch/alpha/include/endian.h +++ b/sys/arch/alpha/include/endian.h @@ -1,5 +1,5 @@ -/* $OpenBSD: endian.h,v 1.2 1996/07/29 22:58:40 niklas Exp $ */ -/* $NetBSD: endian.h,v 1.1 1995/02/13 23:07:36 cgd Exp $ */ +/* $OpenBSD: endian.h,v 1.3 1996/10/30 22:39:03 niklas Exp $ */ +/* $NetBSD: endian.h,v 1.3 1996/10/13 19:57:59 cgd Exp $ */ /* * Copyright (c) 1987, 1991, 1993 @@ -58,11 +58,14 @@ #include <sys/cdefs.h> +typedef u_int32_t in_addr_t; +typedef u_int16_t in_port_t; + __BEGIN_DECLS -unsigned long htonl __P((unsigned long)); -unsigned short htons __P((unsigned short)); -unsigned long ntohl __P((unsigned long)); -unsigned short ntohs __P((unsigned short)); +in_addr_t htonl __P((in_addr_t)); +in_port_t htons __P((in_port_t)); +in_addr_t ntohl __P((in_addr_t)); +in_port_t ntohs __P((in_port_t)); __END_DECLS /* @@ -81,10 +84,10 @@ __END_DECLS #else -#define NTOHL(x) (x) = ntohl((u_long)x) -#define NTOHS(x) (x) = ntohs((u_short)x) -#define HTONL(x) (x) = htonl((u_long)x) -#define HTONS(x) (x) = htons((u_short)x) +#define NTOHL(x) (x) = ntohl((in_addr_t)x) +#define NTOHS(x) (x) = ntohs((in_port_t)x) +#define HTONL(x) (x) = htonl((in_addr_t)x) +#define HTONS(x) (x) = htons((in_port_t)x) #endif #endif /* !_POSIX_SOURCE */ #endif /* !_ENDIAN_H_ */ diff --git a/sys/arch/alpha/include/fbio.h b/sys/arch/alpha/include/fbio.h index a9a4c40eae2..bce6db8ba24 100644 --- a/sys/arch/alpha/include/fbio.h +++ b/sys/arch/alpha/include/fbio.h @@ -1,5 +1,5 @@ -/* $OpenBSD: fbio.h,v 1.2 1996/07/29 22:58:43 niklas Exp $ */ -/* $NetBSD: fbio.h,v 1.2 1996/05/01 19:44:21 cgd Exp $ */ +/* $OpenBSD: fbio.h,v 1.3 1996/10/30 22:39:04 niklas Exp $ */ +/* $NetBSD: fbio.h,v 1.3 1996/08/23 00:50:25 cgd Exp $ */ /* * Copyright (c) 1992 Regents of the University of California. @@ -57,8 +57,9 @@ #define FBTYPE_PCIVGA 7 /* PCI VGA */ #define FBTYPE_TGA 8 /* TGA (PCI) */ #define FBTYPE_SFBP 9 /* SFB+ (TurboChannel) */ +#define FBTYPE_TGA2 10 /* TGA2 (PCI) */ -#define FBTYPE_LASTPLUSONE 10 +#define FBTYPE_LASTPLUSONE 11 /* * Frame buffer descriptor as returned by FBIOGTYPE. diff --git a/sys/arch/alpha/include/float.h b/sys/arch/alpha/include/float.h index 24358b119bc..fa51cc4a5ea 100644 --- a/sys/arch/alpha/include/float.h +++ b/sys/arch/alpha/include/float.h @@ -1,4 +1,4 @@ -/* $OpenBSD: float.h,v 1.2 1996/07/29 22:58:45 niklas Exp $ */ +/* $OpenBSD: float.h,v 1.3 1996/10/30 22:39:05 niklas Exp $ */ /* $NetBSD: float.h,v 1.4 1995/06/20 20:45:22 jtc Exp $ */ /* diff --git a/sys/arch/alpha/include/frame.h b/sys/arch/alpha/include/frame.h index 981d26dd4ef..a05fc112370 100644 --- a/sys/arch/alpha/include/frame.h +++ b/sys/arch/alpha/include/frame.h @@ -1,5 +1,5 @@ -/* $OpenBSD: frame.h,v 1.2 1996/07/29 22:58:47 niklas Exp $ */ -/* $NetBSD: frame.h,v 1.1 1995/02/13 23:07:39 cgd Exp $ */ +/* $OpenBSD: frame.h,v 1.3 1996/10/30 22:39:06 niklas Exp $ */ +/* $NetBSD: frame.h,v 1.3 1996/07/11 05:31:32 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -31,23 +31,22 @@ #ifndef _ALPHA_FRAME_H_ #define _ALPHA_FRAME_H_ -/* - * XXX where did this info come from? - */ +#include <machine/alpha_cpu.h> /* - * Trap and syscall frame. + * Software trap, exception, and syscall frame. * - * Hardware puts fields marked "[HW]" on stack. We have to add - * all of the general-purpose registers except for zero, for sp, - * which is automatically saved in usp for traps, and implicitly - * saved for syscalls, and for a0-a2, which are saved by hardware. + * Includes "hardware" (PALcode) frame. + * + * PALcode puts ALPHA_HWFRAME_* fields on stack. We have to add + * all of the general-purpose registers except for zero, for sp + * (which is automatically saved in the PCB's USP field for entries + * from user mode, and which is implicitly saved and restored by the + * calling conventions for entries from kernel mode), and (on traps + * and exceptions) for a0, a1, and a2 (which are saved by PALcode). */ -/* Number of registers saved, including padding. */ -#define FRAME_NSAVEREGS 28 - -/* The offsets of the registers to be saved, into the array. */ +/* Quadword offsets of the registers to be saved. */ #define FRAME_V0 0 #define FRAME_T0 1 #define FRAME_T1 2 @@ -75,16 +74,22 @@ #define FRAME_T12 24 #define FRAME_AT 25 #define FRAME_SP 26 -#define FRAME_SPARE 27 /* spare; padding */ + +#define FRAME_SW_SIZE (FRAME_SP + 1) +#define FRAME_HW_OFFSET FRAME_SW_SIZE + +#define FRAME_PS (FRAME_HW_OFFSET + ALPHA_HWFRAME_PS) +#define FRAME_PC (FRAME_HW_OFFSET + ALPHA_HWFRAME_PC) +#define FRAME_GP (FRAME_HW_OFFSET + ALPHA_HWFRAME_GP) +#define FRAME_A0 (FRAME_HW_OFFSET + ALPHA_HWFRAME_A0) +#define FRAME_A1 (FRAME_HW_OFFSET + ALPHA_HWFRAME_A1) +#define FRAME_A2 (FRAME_HW_OFFSET + ALPHA_HWFRAME_A2) + +#define FRAME_HW_SIZE ALPHA_HWFRAME_SIZE +#define FRAME_SIZE (FRAME_HW_OFFSET + FRAME_HW_SIZE) struct trapframe { - u_int64_t tf_regs[FRAME_NSAVEREGS]; /* GPRs (listed above) */ - u_int64_t tf_ps; /* processor status [HW] */ - u_int64_t tf_pc; /* program counter [HW] */ - u_int64_t tf_gp; /* global pointer [HW] */ - u_int64_t tf_a0; /* saved a0 [HW] */ - u_int64_t tf_a1; /* saved a1 [HW] */ - u_int64_t tf_a2; /* saved a2 [HW] */ + unsigned long tf_regs[FRAME_SIZE]; /* See above */ }; #endif /* _ALPHA_FRAME_H_ */ diff --git a/sys/arch/alpha/include/ieee.h b/sys/arch/alpha/include/ieee.h index eed83d82d9e..943ac5052e8 100644 --- a/sys/arch/alpha/include/ieee.h +++ b/sys/arch/alpha/include/ieee.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee.h,v 1.2 1996/07/29 22:58:48 niklas Exp $ */ +/* $OpenBSD: ieee.h,v 1.3 1996/10/30 22:39:07 niklas Exp $ */ /* $NetBSD: ieee.h,v 1.1 1995/02/13 23:07:40 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/ieeefp.h b/sys/arch/alpha/include/ieeefp.h index 731366c1ae3..4ebb20b0aa5 100644 --- a/sys/arch/alpha/include/ieeefp.h +++ b/sys/arch/alpha/include/ieeefp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieeefp.h,v 1.2 1996/07/29 22:58:50 niklas Exp $ */ +/* $OpenBSD: ieeefp.h,v 1.3 1996/10/30 22:39:08 niklas Exp $ */ /* $NetBSD: ieeefp.h,v 1.1 1995/04/29 01:09:17 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/intr.h b/sys/arch/alpha/include/intr.h index 1e1edaae517..e638077e95d 100644 --- a/sys/arch/alpha/include/intr.h +++ b/sys/arch/alpha/include/intr.h @@ -1,5 +1,5 @@ -/* $OpenBSD: intr.h,v 1.2 1996/07/29 22:58:52 niklas Exp $ */ -/* $NetBSD: intr.h,v 1.1 1996/04/12 01:42:17 cgd Exp $ */ +/* $OpenBSD: intr.h,v 1.3 1996/10/30 22:39:09 niklas Exp $ */ +/* $NetBSD: intr.h,v 1.2 1996/07/09 00:33:25 cgd Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -28,6 +28,9 @@ * rights to redistribute these changes. */ +#ifndef _ALPHA_INTR_H_ +#define _ALPHA_INTR_H_ + #define IPL_NONE 0 /* disable only this interrupt */ #define IPL_BIO 1 /* disable block I/O interrupts */ #define IPL_NET 2 /* disable network interrupts */ @@ -39,3 +42,30 @@ #define IST_PULSE 1 /* pulsed */ #define IST_EDGE 2 /* edge-triggered */ #define IST_LEVEL 3 /* level-triggered */ + +#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() +#define splnet() alpha_pal_swpipl(ALPHA_PSL_IPL_IO) +#define splbio() alpha_pal_swpipl(ALPHA_PSL_IPL_IO) +#define splimp() alpha_pal_swpipl(ALPHA_PSL_IPL_IO) +#define spltty() alpha_pal_swpipl(ALPHA_PSL_IPL_IO) +#define splclock() alpha_pal_swpipl(ALPHA_PSL_IPL_CLOCK) +#define splstatclock() alpha_pal_swpipl(ALPHA_PSL_IPL_CLOCK) +#define splhigh() alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH) + +/* + * simulated software interrupt register + */ +extern u_int64_t ssir; + +#define SIR_NET 0x1 +#define SIR_CLOCK 0x2 + +#define siroff(x) ssir &= ~(x) +#define setsoftnet() ssir |= SIR_NET +#define setsoftclock() ssir |= SIR_CLOCK + +#endif diff --git a/sys/arch/alpha/include/intrcnt.h b/sys/arch/alpha/include/intrcnt.h index fbc8d214a43..50a451798ff 100644 --- a/sys/arch/alpha/include/intrcnt.h +++ b/sys/arch/alpha/include/intrcnt.h @@ -1,5 +1,5 @@ -/* $OpenBSD: intrcnt.h,v 1.3 1996/07/29 22:58:53 niklas Exp $ */ -/* $NetBSD: intrcnt.h,v 1.4.4.2 1996/06/05 03:42:24 cgd Exp $ */ +/* $OpenBSD: intrcnt.h,v 1.4 1996/10/30 22:39:10 niklas Exp $ */ +/* $NetBSD: intrcnt.h,v 1.6 1996/06/05 03:38:02 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/include/kbio.h b/sys/arch/alpha/include/kbio.h index 1923e84da77..30dc944ba83 100644 --- a/sys/arch/alpha/include/kbio.h +++ b/sys/arch/alpha/include/kbio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kbio.h,v 1.2 1996/07/29 22:58:55 niklas Exp $ */ +/* $OpenBSD: kbio.h,v 1.3 1996/10/30 22:39:11 niklas Exp $ */ /* $NetBSD: kbio.h,v 1.1 1996/04/12 01:45:45 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/kcore.h b/sys/arch/alpha/include/kcore.h new file mode 100644 index 00000000000..87da4d36d0c --- /dev/null +++ b/sys/arch/alpha/include/kcore.h @@ -0,0 +1,40 @@ +/* $OpenBSD: kcore.h,v 1.1 1996/10/30 22:39:11 niklas Exp $ */ +/* $NetBSD: kcore.h,v 1.1 1996/10/01 18:38:05 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. + */ + +#ifndef _ALPHA_KCORE_H_ +#define _ALPHA_KCORE_H_ + +typedef struct cpu_kcore_hdr { + u_int64_t lev1map_pa; /* PA of Lev1map */ + u_int64_t page_size; /* Page size */ + phys_ram_seg_t core_seg; /* Core addrs; only one seg */ +} cpu_kcore_hdr_t; + +#endif /* _ALPHA_KCORE_H_ */ diff --git a/sys/arch/alpha/include/limits.h b/sys/arch/alpha/include/limits.h index 2ff6b3fcf78..1d2799a3f06 100644 --- a/sys/arch/alpha/include/limits.h +++ b/sys/arch/alpha/include/limits.h @@ -1,4 +1,4 @@ -/* $OpenBSD: limits.h,v 1.3 1996/07/29 22:58:56 niklas Exp $ */ +/* $OpenBSD: limits.h,v 1.4 1996/10/30 22:39:12 niklas Exp $ */ /* $NetBSD: limits.h,v 1.2 1996/04/12 01:38:25 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/param.h b/sys/arch/alpha/include/param.h index e7d8ed09324..40878d41a71 100644 --- a/sys/arch/alpha/include/param.h +++ b/sys/arch/alpha/include/param.h @@ -1,5 +1,5 @@ -/* $OpenBSD: param.h,v 1.5 1996/07/29 22:58:58 niklas Exp $ */ -/* $NetBSD: param.h,v 1.12 1996/03/04 05:04:10 cgd Exp $ */ +/* $OpenBSD: param.h,v 1.6 1996/10/30 22:39:13 niklas Exp $ */ +/* $NetBSD: param.h,v 1.13 1996/07/09 00:33:23 cgd Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -52,9 +52,7 @@ #define MACHINE_ARCH "alpha" #define MID_MACHINE MID_ALPHA -#ifdef _KERNEL /* XXX */ -#include <machine/cpu.h> /* XXX */ -#endif /* XXX */ +#include <machine/alpha_cpu.h> /* * Round p (pointer or byte index) up to a correctly-aligned value for all @@ -64,9 +62,9 @@ #define ALIGNBYTES 7 #define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES) -#define NBPG 8192 /* bytes/page */ +#define NBPG (1 << ALPHA_PGSHIFT) /* bytes/page */ #define PGOFSET (NBPG-1) /* byte off. into pg */ -#define PGSHIFT 13 /* LOG2(NBPG) */ +#define PGSHIFT ALPHA_PGSHIFT /* LOG2(NBPG) */ #define NPTEPG (1 << (PGSHIFT-PTESHIFT)) /* pte's/page */ #define SEGSHIFT (PGSHIFT + (PGSHIFT-PTESHIFT)) /* LOG2(NBSEG) */ @@ -145,34 +143,17 @@ #define alpha_btop(x) ((unsigned long)(x) >> PGSHIFT) #define alpha_ptob(x) ((unsigned long)(x) << PGSHIFT) -#include <machine/psl.h> - -#define splx(s) (s == PSL_IPL_0 ? spl0() : pal_swpipl(s)) -#define splsoft() pal_swpipl(PSL_IPL_SOFT) -#define splsoftclock() splsoft() -#define splsoftnet() splsoft() -#define splnet() pal_swpipl(PSL_IPL_IO) -#define splbio() pal_swpipl(PSL_IPL_IO) -#define splimp() pal_swpipl(PSL_IPL_IO) -#define spltty() pal_swpipl(PSL_IPL_IO) -#define splclock() pal_swpipl(PSL_IPL_CLOCK) -#define splstatclock() pal_swpipl(PSL_IPL_CLOCK) -#define splhigh() pal_swpipl(PSL_IPL_HIGH) +#include <machine/intr.h> #ifdef _KERNEL #ifndef _LOCORE -/* This was calibrated empirically */ -extern u_int64_t cycles_per_usec; -int delay __P((int)); +void delay __P((unsigned long)); #define DELAY(n) delay(n) +/* XXX ALL OF THE FOLLOWING BELONG IN INTR.H */ int spl0 __P((void)); /* drop ipl to zero */ +/* XXX END INTR.H */ #endif #endif /* !_KERNEL */ - -int prtloc; -extern int ticks; -#define LOC() do { if (prtloc) printf("(%ld:%ld) %s: %d\n", curproc ? curproc->p_pid : -1, (long)ticks, __FILE__, __LINE__); } while (0) -#define PLOC(str) panic("XXX: (%ld:%ld) %s at %s: %d\n", curproc ? curproc->p_pid : -1, (long)ticks, str, __FILE__, __LINE__); diff --git a/sys/arch/alpha/include/pcb.h b/sys/arch/alpha/include/pcb.h index e24132f82db..bd7530fb65a 100644 --- a/sys/arch/alpha/include/pcb.h +++ b/sys/arch/alpha/include/pcb.h @@ -1,5 +1,5 @@ -/* $OpenBSD: pcb.h,v 1.2 1996/07/29 22:58:59 niklas Exp $ */ -/* $NetBSD: pcb.h,v 1.1 1995/02/13 23:07:43 cgd Exp $ */ +/* $OpenBSD: pcb.h,v 1.3 1996/10/30 22:39:14 niklas Exp $ */ +/* $NetBSD: pcb.h,v 1.4 1996/10/07 23:57:21 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -31,9 +31,7 @@ #include <machine/frame.h> #include <machine/reg.h> -/* - * XXX where did this info come from? - */ +#include <machine/alpha_cpu.h> /* * PCB: process control block @@ -49,17 +47,11 @@ * So we cache the physical address of the pcb in the md_proc struct. */ struct pcb { - u_int64_t pcb_ksp; /* kernel stack ptr [HW] */ - u_int64_t pcb_usp; /* user stack ptr [HW] */ - u_int64_t pcb_ptbr; /* page table base reg [HW] */ - u_int32_t pcb_pcc; /* process cycle cntr [HW] */ - u_int32_t pcb_asn; /* address space number [HW] */ - u_int64_t pcb_unique; /* process unique value [HW] */ - u_int64_t pcb_fen; /* FP enable (in bit 0) [HW] */ - u_int64_t pcb_decrsv[2]; /* DEC reserved [HW] */ - u_int64_t pcb_context[9]; /* s[0-6], ra, ps [SW] */ + struct alpha_pcb pcb_hw; /* PALcode defined */ + unsigned long pcb_context[9]; /* s[0-6], ra, ps [SW] */ struct fpreg pcb_fp; /* FP registers [SW] */ - caddr_t pcb_onfault; /* for copy faults [SW] */ + unsigned long pcb_onfault; /* for copy faults [SW] */ + unsigned long pcb_accessaddr; /* for [fs]uswintr [SW] */ }; /* @@ -69,4 +61,9 @@ struct pcb { */ struct md_coredump { struct trapframe md_tf; + struct fpreg md_fpstate; }; + +#ifdef _KERNEL +void savectx __P((struct pcb *)); +#endif diff --git a/sys/arch/alpha/include/pmap.h b/sys/arch/alpha/include/pmap.h index ed63680b21d..9b2120cd6ce 100644 --- a/sys/arch/alpha/include/pmap.h +++ b/sys/arch/alpha/include/pmap.h @@ -1,127 +1,10 @@ -/* $OpenBSD: pmap.h,v 1.3 1996/07/29 22:59:01 niklas Exp $ */ -/* $NetBSD: pmap.h,v 1.4 1995/11/23 02:36:25 cgd Exp $ */ +/* $OpenBSD: pmap.h,v 1.4 1996/10/30 22:39:16 niklas Exp $ */ +/* $NetBSD: pmap.h,v 1.9 1996/08/20 23:02:30 cgd Exp $ */ -/* - * Copyright (c) 1987 Carnegie-Mellon University - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. 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. - * - * @(#)pmap.h 8.1 (Berkeley) 6/10/93 - */ +#ifndef NEW_PMAP +#include <machine/pmap.old.h> +#else +#include <machine/pmap.new.h> +#endif -#ifndef _PMAP_MACHINE_ -#define _PMAP_MACHINE_ - -#include <machine/pte.h> - -#define ALPHA_PAGE_SIZE NBPG -#define ALPHA_SEG_SIZE NBSEG - -#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) - -/* - * Pmap stuff - */ -struct pmap { - pt_entry_t *pm_ptab; /* KVA of page table */ - pt_entry_t *pm_stab; /* KVA of segment table */ - int pm_stchanged; /* ST changed */ - 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 */ -}; - -typedef struct pmap *pmap_t; - -extern struct pmap kernel_pmap_store; - -#define pmap_kernel() (&kernel_pmap_store) -#define active_pmap(pm) \ - ((pm) == pmap_kernel() || (pm) == curproc->p_vmspace->vm_map.pmap) - -/* - * Macros for speed - */ -#define PMAP_ACTIVATE(pmapp, iscurproc) \ - if ((pmapp) != NULL && (pmapp)->pm_stchanged) { \ - if (iscurproc) \ - loadustp((pmapp)->pm_stpte); \ - (pmapp)->pm_stchanged = FALSE; \ - } -#define PMAP_DEACTIVATE(pmapp, pcbp) - -/* - * 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 { - 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; - -#define PV_PTPAGE 0x01 /* header: entry maps a page table page */ - -/* - * bits of pmap_attributes[] - */ -#define PMAP_ATTR_MOD 0x01 /* modified */ -#define PMAP_ATTR_REF 0x02 /* referenced */ - -#ifdef _KERNEL -pv_entry_t pv_table; /* array of entries, one per page */ - -#define pa_index(pa) atop(pa - vm_first_phys) -#define pa_to_pvh(pa) (&pv_table[pa_index(pa)]) - -#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) -#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) - -extern pt_entry_t *Sysmap; -extern char *vmmap; /* map for mem, dumps, etc. */ - -/* Machine-specific functions. */ -void pmap_emulate_reference __P((struct proc *p, vm_offset_t v, - int user, int write)); -#endif /* _KERNEL */ - -#endif /* _PMAP_MACHINE_ */ +void pmap_unmap_prom __P((void)); diff --git a/sys/arch/alpha/include/pmap.new.h b/sys/arch/alpha/include/pmap.new.h new file mode 100644 index 00000000000..d70ee7302c9 --- /dev/null +++ b/sys/arch/alpha/include/pmap.new.h @@ -0,0 +1,363 @@ +/* $OpenBSD: pmap.new.h,v 1.1 1996/10/30 22:39:17 niklas Exp $ */ +/* $NetBSD: pmap.new.h,v 1.3 1996/08/20 23:02:59 cgd Exp $ */ + +/* + * Copyright (c) 1992, 1993, 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. + */ + +/* + * File: pmap.h + * + * Author: David Golub (mods for Alpha by Alessandro Forin) + Mods for use in {Net,Open}BSD/Alpha by Chris Demetriou. + * Date: 1988 ca. + * + * Machine-dependent structures for the physical map module. + */ + +#ifndef _PMAP_MACHINE_ +#define _PMAP_MACHINE_ + +#include <machine/alpha_cpu.h> + +/* XXX */ +typedef struct pcb *pcb_t; + +/* + * Alpha Page Table Entry + */ + +typedef alpha_pt_entry_t pt_entry_t; +#define PT_ENTRY_NULL ((pt_entry_t *) 0) + +#define ALPHA_OFFMASK (ALPHA_PGBYTES-1) /* offset within page */ + +#define SEG_MASK ((ALPHA_PGBYTES / 8)-1) /* masks for segments */ +#define SEG3_SHIFT (ALPHA_PGSHIFT) /* shifts for segments */ +#define SEG2_SHIFT (SEG3_SHIFT+(ALPHA_PGSHIFT-3)) +#define SEG1_SHIFT (SEG2_SHIFT+(ALPHA_PGSHIFT-3)) + +/* + * Convert address offset to page descriptor index + */ +#define pdenum(a) (((a) >> SEG1_SHIFT) & SEG_MASK) + +/* + * Convert page descriptor index to user virtual address + */ +#define pdetova(a) ((vm_offset_t)(a) << SEG1_SHIFT) +#define pde2tova(a) ((vm_offset_t)(a) << SEG2_SHIFT) +#define pde3tova(a) ((vm_offset_t)(a) << SEG3_SHIFT) + +/* + * Convert address offset to second level page table index + */ +#define pte2num(a) (((a) >> SEG2_SHIFT) & SEG_MASK) + +/* + * Convert address offset to third level page table index + */ +#define pte3num(a) (((a) >> SEG3_SHIFT) & SEG_MASK) + +#define NPTES (alpha_ptob(1)/sizeof(pt_entry_t)) +#define NPDES (alpha_ptob(1)/sizeof(pt_entry_t)) + +/* + * Hardware/PALcode pte bit definitions (to be used directly + * on the ptes without using the bit fields) are defined in + * <machine/alpha_cpu.h>. Software-defined bits are defined + * here. + */ + +#define ALPHA_PTE_WIRED 0x00010000 +#define ALPHA_PTE_REF 0x00020000 +#define ALPHA_PTE_MOD 0x00040000 + + +#define pa_to_pte(a) ALPHA_PTE_FROM_PFN(alpha_btop(a)) +#define pte_to_pa(p) alpha_ptob(ALPHA_PTE_TO_PFN(p)) +#define pte_increment_pa(p) ((p) += pa_to_pte(ALPHA_PGBYTES)) + +/* + * Convert page table entry to kernel virtual address + */ +#define ptetokv(a) (phystokv(pte_to_pa(a))) + +typedef volatile long cpu_set; /* set of CPUs - must be <= 64 */ + /* changed by other processors */ + +#define decl_simple_lock_data(x,y) simple_lock_data_t y; + +struct pmap { + pt_entry_t *dirbase; /* page directory pointer register */ + unsigned long dirpfn; /* cached dirbase physical PFN */ + int pid; /* TLBPID when in use */ + int ref_count; /* reference count */ + decl_simple_lock_data(,lock) + /* lock on map */ + struct pmap_statistics stats; /* map statistics */ + cpu_set cpus_using; /* bitmap of cpus using pmap */ + int (*hacking)(); /* horrible things needed */ +}; + +typedef struct pmap *pmap_t; + +#define PMAP_NULL ((pmap_t) 0) + +#define vtophys(x) kvtophys(x) +extern vm_offset_t kvtophys __P((vm_offset_t)); +extern void set_ptbr(pmap_t map, pcb_t pcb, boolean_t); + +#if NCPUS > 1 +/* + * List of cpus that are actively using mapped memory. Any + * pmap update operation must wait for all cpus in this list. + * Update operations must still be queued to cpus not in this + * list. + */ +extern cpu_set cpus_active; + +/* + * List of cpus that are idle, but still operating, and will want + * to see any kernel pmap updates when they become active. + */ +extern cpu_set cpus_idle; + +/* + * Quick test for pmap update requests. + */ +extern volatile +boolean_t cpu_update_needed[NCPUS]; + +/* + * External declarations for PMAP_ACTIVATE. + */ + +void pmap_activate __P((pmap_t, struct alpha_pcb *, int)); +void pmap_deactivate __P((pmap_t, struct alpha_pcb *, int)); +void pmap_bootstrap __P((vm_offset_t, vm_offset_t, int)); +void process_pmap_updates __P((pmap_t)); +void pmap_update_interrupt __P((void)); +extern pmap_t kernel_pmap; + +#endif /* NCPUS > 1 */ + +/* + * Machine dependent routines that are used only for Alpha. + */ + +pt_entry_t *pmap_pte(pmap_t, vm_offset_t); + +/* + * Macros for speed. + */ + +#if NCPUS > 1 + +/* + * For multiple CPUS, PMAP_ACTIVATE and PMAP_DEACTIVATE must manage + * fields to control TLB invalidation on other CPUS. + */ + +#define PMAP_ACTIVATE_KERNEL(my_cpu) { \ + \ + /* \ + * Let pmap updates proceed while we wait for this pmap. \ + */ \ + i_bit_clear((my_cpu), &cpus_active); \ + \ + /* \ + * Lock the pmap to put this cpu in its active set. \ + * Wait for updates here. \ + */ \ + simple_lock(&kernel_pmap->lock); \ + \ + /* \ + * Process invalidate requests for the kernel pmap. \ + */ \ + if (cpu_update_needed[(my_cpu)]) \ + process_pmap_updates(kernel_pmap); \ + \ + /* \ + * Mark that this cpu is using the pmap. \ + */ \ + i_bit_set((my_cpu), &kernel_pmap->cpus_using); \ + \ + /* \ + * Mark this cpu active - IPL will be lowered by \ + * load_context(). \ + */ \ + i_bit_set((my_cpu), &cpus_active); \ + \ + simple_unlock(&kernel_pmap->lock); \ +} + +#define PMAP_DEACTIVATE_KERNEL(my_cpu) { \ + /* \ + * Mark pmap no longer in use by this cpu even if \ + * pmap is locked against updates. \ + */ \ + i_bit_clear((my_cpu), &kernel_pmap->cpus_using); \ +} + +#define PMAP_ACTIVATE_USER(pmap, th, my_cpu) { \ + register pmap_t tpmap = (pmap); \ + register pcb_t pcb = (th)->pcb; \ + \ + if (tpmap == kernel_pmap) { \ + /* \ + * If this is the kernel pmap, switch to its page tables. \ + */ \ + set_ptbr(tpmap,pcb,TRUE); \ + } \ + else { \ + /* \ + * Let pmap updates proceed while we wait for this pmap. \ + */ \ + i_bit_clear((my_cpu), &cpus_active); \ + \ + /* \ + * Lock the pmap to put this cpu in its active set. \ + * Wait for updates here. \ + */ \ + simple_lock(&tpmap->lock); \ + \ + /* \ + * No need to invalidate the TLB - the entire user pmap \ + * will be invalidated by reloading dirbase. \ + */ \ + if (tpmap->pid < 0) pmap_assign_tlbpid(tpmap); \ + set_ptbr(tpmap, pcb, TRUE); \ + \ + /* \ + * Mark that this cpu is using the pmap. \ + */ \ + i_bit_set((my_cpu), &tpmap->cpus_using); \ + \ + /* \ + * Mark this cpu active - IPL will be lowered by \ + * load_context(). \ + */ \ + i_bit_set((my_cpu), &cpus_active); \ + \ + simple_unlock(&tpmap->lock); \ + } \ +} + +#define PMAP_DEACTIVATE_USER(pmap, thread, my_cpu) { \ + register pmap_t tpmap = (pmap); \ + \ + /* \ + * Do nothing if this is the kernel pmap. \ + */ \ + if (tpmap != kernel_pmap) { \ + /* \ + * Mark pmap no longer in use by this cpu even if \ + * pmap is locked against updates. \ + */ \ + i_bit_clear((my_cpu), &(pmap)->cpus_using); \ + } \ +} + +#define MARK_CPU_IDLE(my_cpu) { \ + /* \ + * Mark this cpu idle, and remove it from the active set, \ + * since it is not actively using any pmap. Signal_cpus \ + * will notice that it is idle, and avoid signaling it, \ + * but will queue the update request for when the cpu \ + * becomes active. \ + */ \ + spl_t s = splvm(); \ + i_bit_set((my_cpu), &cpus_idle); \ + i_bit_clear((my_cpu), &cpus_active); \ + splx(s); \ +} + +#define MARK_CPU_ACTIVE(my_cpu) { \ + \ + spl_t s = splvm(); \ + /* \ + * If a kernel_pmap update was requested while this cpu \ + * was idle, process it as if we got the interrupt. \ + * Before doing so, remove this cpu from the idle set. \ + * Since we do not grab any pmap locks while we flush \ + * our TLB, another cpu may start an update operation \ + * before we finish. Removing this cpu from the idle \ + * set assures that we will receive another update \ + * interrupt if this happens. \ + */ \ + i_bit_clear((my_cpu), &cpus_idle); \ + \ + if (cpu_update_needed[(my_cpu)]) \ + pmap_update_interrupt(); \ + \ + /* \ + * Mark that this cpu is now active. \ + */ \ + i_bit_set((my_cpu), &cpus_active); \ + splx(s); \ +} + +#else /* NCPUS > 1 */ + +/* + * With only one CPU, we just have to indicate whether the pmap is + * in use. + */ + +#define PMAP_ACTIVATE_KERNEL(my_cpu) { \ + kernel_pmap->cpus_using = TRUE; \ +} + +#define PMAP_DEACTIVATE_KERNEL(my_cpu) { \ + kernel_pmap->cpus_using = FALSE; \ +} + +#define PMAP_ACTIVATE_USER(pmap, th, my_cpu) { \ + register pmap_t tpmap = (pmap); \ + register pcb_t pcb = (th)->pcb; \ + \ + if (tpmap->pid < 0) pmap_assign_tlbpid(tpmap); \ + set_ptbr(tpmap,pcb,TRUE); \ + if (tpmap != kernel_pmap) { \ + tpmap->cpus_using = TRUE; \ + } \ +} + +#define PMAP_DEACTIVATE_USER(pmap, thread, cpu) { \ + if ((pmap) != kernel_pmap) \ + (pmap)->cpus_using = FALSE; \ +} + +#endif /* NCPUS > 1 */ + +#define pmap_kernel() (kernel_pmap) +#define pmap_resident_count(pmap) ((pmap)->stats.resident_count) + +/* + * Data structures this module exports + */ +extern pmap_t kernel_pmap; /* pointer to the kernel pmap */ + +#endif _PMAP_MACHINE_ diff --git a/sys/arch/alpha/include/pmap.old.h b/sys/arch/alpha/include/pmap.old.h new file mode 100644 index 00000000000..c60dfc9c485 --- /dev/null +++ b/sys/arch/alpha/include/pmap.old.h @@ -0,0 +1,131 @@ +/* $OpenBSD: pmap.old.h,v 1.1 1996/10/30 22:39:18 niklas Exp $ */ +/* $NetBSD: pmap.old.h,v 1.5 1996/07/09 00:39:24 cgd Exp $ */ + +/* + * Copyright (c) 1987 Carnegie-Mellon University + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + * + * @(#)pmap.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _PMAP_MACHINE_ +#define _PMAP_MACHINE_ + +#include <machine/pte.h> + +extern vm_offset_t vtophys(vm_offset_t); + +#define ALPHA_PAGE_SIZE NBPG +#define ALPHA_SEG_SIZE NBSEG + +#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) + +/* + * Pmap stuff + */ +struct pmap { + pt_entry_t *pm_ptab; /* KVA of page table */ + pt_entry_t *pm_stab; /* KVA of segment table */ + int pm_stchanged; /* ST changed */ + 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 */ +}; + +typedef struct pmap *pmap_t; + +extern struct pmap kernel_pmap_store; + +#define pmap_kernel() (&kernel_pmap_store) +#define active_pmap(pm) \ + ((pm) == pmap_kernel() || (pm) == curproc->p_vmspace->vm_map.pmap) + +/* + * Macros for speed + */ +#define PMAP_ACTIVATE(pmapp, iscurproc) \ + if ((pmapp) != NULL && (pmapp)->pm_stchanged) { \ + if (iscurproc) \ + loadustp((pmapp)->pm_stpte); \ + (pmapp)->pm_stchanged = FALSE; \ + } +#define PMAP_DEACTIVATE(pmapp, pcbp) + +/* + * 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 { + 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; + +#define PV_PTPAGE 0x01 /* header: entry maps a page table page */ + +/* + * bits of pmap_attributes[] + */ +#define PMAP_ATTR_MOD 0x01 /* modified */ +#define PMAP_ATTR_REF 0x02 /* referenced */ + +#ifdef _KERNEL +pv_entry_t pv_table; /* array of entries, one per page */ + +#define pa_index(pa) atop(pa - vm_first_phys) +#define pa_to_pvh(pa) (&pv_table[pa_index(pa)]) + +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) + +extern pt_entry_t *Sysmap; +extern char *vmmap; /* map for mem, dumps, etc. */ + +/* Machine-specific functions. */ +void pmap_activate __P((pmap_t)); +void pmap_emulate_reference __P((struct proc *p, vm_offset_t v, + int user, int write)); +void pmap_bootstrap __P((vm_offset_t, vm_offset_t)); +#endif /* _KERNEL */ + +#endif /* _PMAP_MACHINE_ */ diff --git a/sys/arch/alpha/include/proc.h b/sys/arch/alpha/include/proc.h index 4460c2e8c25..5794e0244de 100644 --- a/sys/arch/alpha/include/proc.h +++ b/sys/arch/alpha/include/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.2 1996/07/29 22:59:03 niklas Exp $ */ +/* $OpenBSD: proc.h,v 1.3 1996/10/30 22:39:19 niklas Exp $ */ /* $NetBSD: proc.h,v 1.2 1995/03/24 15:01:36 cgd Exp $ */ /* @@ -39,3 +39,8 @@ struct mdproc { }; #define MDP_FPUSED 0x0001 /* Process used the FPU */ + +#ifdef _KERNEL +void switch_exit __P((struct proc *)); +void switch_trampoline __P((void (*) __P((struct proc *)), void *)); +#endif diff --git a/sys/arch/alpha/include/profile.h b/sys/arch/alpha/include/profile.h index dd163bc13a6..34b748366d4 100644 --- a/sys/arch/alpha/include/profile.h +++ b/sys/arch/alpha/include/profile.h @@ -1,5 +1,5 @@ -/* $OpenBSD: profile.h,v 1.3 1996/07/29 22:59:05 niklas Exp $ */ -/* $NetBSD: profile.h,v 1.3 1995/11/23 02:36:28 cgd Exp $ */ +/* $OpenBSD: profile.h,v 1.4 1996/10/30 22:39:20 niklas Exp $ */ +/* $NetBSD: profile.h,v 1.6 1996/09/15 22:33:28 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -92,8 +92,8 @@ LEAF(_mcount,0) /* XXX */ stq t12, OFFSET_T12(sp) stq gp, OFFSET_GP(sp) - br pv, 1f -1: SETGP(pv) + br pv, LX99 +LX99: SETGP(pv) mov ra, a0 mov at_reg, a1 CALL(mcount) @@ -118,8 +118,9 @@ LEAF(_mcount,0) /* XXX */ ldq t9, OFFSET_T9(sp) ldq t10, OFFSET_T10(sp) ldq t11, OFFSET_T11(sp) - ldq gp, OFFSET_GP(sp) ldq ra, OFFSET_RA(sp) + stq t12, OFFSET_T12(sp) + ldq gp, OFFSET_GP(sp) ldq at_reg, OFFSET_AT(sp) @@ -164,8 +165,8 @@ _mcount:; \ stq $27, 176($30); \ stq $29, 184($30); \ \ - br $27, 1f; \ -1: ldgp $29,0($27); \ + br $27, LX98; \ +LX98: ldgp $29,0($27); \ mov $26, $16; \ mov $28, $17; \ jsr $26,mcount; \ @@ -191,10 +192,10 @@ _mcount:; \ ldq $23, 144($30); \ ldq $24, 152($30); \ ldq $25, 160($30); \ - ldq $29, 184($30); \ + ldq $25, 160($30); \ ldq $26, 168($30); \ - \ - ldq $28, 0($30); \ + ldq $27, 176($30); \ + ldq $29, 184($30); \ \ lda $30, 192($30); \ ret $31, ($28), 1; \ @@ -204,13 +205,13 @@ _mcount:; \ #ifdef _KERNEL /* * The following two macros do splhigh and splx respectively. - * profile_swpipl is a special version of pal_swpipl which + * _alpha_pal_swpipl is a special version of alpha_pal_swpipl which * doesn't include profiling support. * * XXX These macros should probably use inline assembly. */ #define MCOUNT_ENTER \ - s = profile_swpipl(PSL_IPL_HIGH) + s = _alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH) #define MCOUNT_EXIT \ - (void)profile_swpipl(s); + (void)_alpha_pal_swpipl(s); #endif diff --git a/sys/arch/alpha/include/prom.h b/sys/arch/alpha/include/prom.h index d27f11e7b46..827054942bb 100644 --- a/sys/arch/alpha/include/prom.h +++ b/sys/arch/alpha/include/prom.h @@ -1,5 +1,5 @@ -/* $OpenBSD: prom.h,v 1.3 1996/07/29 22:59:07 niklas Exp $ */ -/* $NetBSD: prom.h,v 1.2 1996/04/23 15:23:18 cgd Exp $ */ +/* $OpenBSD: prom.h,v 1.4 1996/10/30 22:39:21 niklas Exp $ */ +/* $NetBSD: prom.h,v 1.4 1996/10/15 23:52:49 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -30,7 +30,7 @@ #ifndef ASSEMBLER struct prom_vec { - int (*routine)(); + int (*routine) __P((struct crd *)); struct crd *routine_arg; }; @@ -55,6 +55,11 @@ void putchar __P((int)); void prom_halt __P((int)) __attribute__((__noreturn__)); int prom_getenv __P((int, char *, int)); + +void init_prom_interface __P((void)); +void hwrbp_restart_setup __P((void)); +int prom_dispatch __P((int, int, u_char *, int)); +int promcnlookc __P((dev_t, char *)); #endif /* Prom operation values. */ @@ -64,6 +69,7 @@ int prom_getenv __P((int, char *, int)); #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 @@ -80,3 +86,5 @@ int prom_getenv __P((int, char *, int)); #define prom_close(chan) prom_dispatch(PROM_R_CLOSE, chan) #define prom_read(chan, len, buf, blkno) \ prom_dispatch(PROM_R_READ, chan, len, buf, blkno) +#define prom_write(chan, len, buf, blkno) \ + prom_dispatch(PROM_R_WRITE, chan, len, buf, blkno) diff --git a/sys/arch/alpha/include/psl.h b/sys/arch/alpha/include/psl.h index ef86bc4c563..e37308e86bf 100644 --- a/sys/arch/alpha/include/psl.h +++ b/sys/arch/alpha/include/psl.h @@ -1,97 +1,10 @@ -/* $OpenBSD: psl.h,v 1.5 1996/10/17 22:19:45 niklas Exp $ */ -/* $NetBSD: psl.h,v 1.5 1996/04/23 15:24:09 cgd Exp $ */ +/* $OpenBSD: psl.h,v 1.6 1996/10/30 22:39:22 niklas Exp $ */ +/* $NetBSD: psl.h,v 1.6 1996/07/09 00:37:51 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. + * Everything which would be defined here is defined in + * alpha_cpu.h, and this file is no longer necessary for the + * Alpha. However, some machine-independent code (e.g. + * /sys/compat/common/kern_exit_43.c) still wants a file with + * this name to be around. */ - -#ifndef __ALPHA_PSL_H__ -#define __ALPHA_PSL_H__ - -/* - * Processor Status register definitions. - */ -#define PSL_U 0x08 /* PS<3> == 1 -> User mode */ -#define PSL_IPL 0x07 /* PS<2:0> -> Interrupt mask */ - -/* - * The interrupt priority levels. - * Other IPL's are configured in software, and are listed below. - */ -#define PSL_IPL_0 0 /* all interrupts enabled */ -#define PSL_IPL_SOFT 1 /* block software interrupts */ -#define PSL_IPL_IO 4 /* block I/O device interrupts */ -#define PSL_IPL_CLOCK 5 /* block clock interrupts */ -#define PSL_IPL_HIGH 6 /* block everything except mchecks */ - -/* - * Miscellaneous PSL definitions - */ -#define PSL_MBZ (0xfffffffffffffff0) /* Must be always zero */ -#define PSL_USERSET (PSL_U) /* Must be set for user-mode */ -#define PSL_USERCLR (PSL_MBZ|PSL_IPL) /* Must be clr for user-mode */ -#define USERMODE(ps) ((ps & PSL_U) != 0) /* Is it user-mode? */ - -#ifdef _KERNEL -/* - * Translation buffer invalidation macro definitions. - */ -#define TBI_A -2 /* Flush all TB entries */ -#define TBI_AP -1 /* Flush all per-process TB entries */ -#define TBI_SI 1 /* Invalidate ITB entry for va */ -#define TBI_SD 2 /* Invalidate DTB entry for va */ -#define TBI_S 3 /* Invalidate all entries for va */ - -#define TBIA() pal_tbi(TBI_A, NULL) -#define TBIAP() pal_tbi(TBI_AP, NULL) -#define TBISI(va) pal_tbi(TBI_SI, va) -#define TBISD(va) pal_tbi(TBI_SD, va) -#define TBIS(va) pal_tbi(TBI_S, va) - -/* - * Cache invalidation/flush routines. - */ - -/* Flush all write buffers */ -static __inline void wbflush __P((void)); -static __inline void -wbflush() -{ - /* XXX? wmb */ - __asm __volatile("mb" : : : "memory"); -} - -#define IMB() pal_imb() /* Sync instruction cache w/data */ - -void alpha_mb __P((void)); /* Flush all write buffers */ -void pal_imb __P((void)); /* Sync instruction cache */ -u_int64_t pal_swpipl __P((u_int64_t)); /* write new IPL, return old */ -u_int64_t profile_swpipl __P((u_int64_t)); /* pal_swpipl w/o profiling */ -void pal_tbi __P((u_int64_t, void *)); /* Invalidate TLB entries */ -void pal_halt __P((void)) __attribute__((__noreturn__)); /* halt/reboot */ -#endif /* _KERNEL */ - -#endif /* !__ALPHA_PSL_H__ */ diff --git a/sys/arch/alpha/include/pte.h b/sys/arch/alpha/include/pte.h index f8a669a6206..6fcec6de1b9 100644 --- a/sys/arch/alpha/include/pte.h +++ b/sys/arch/alpha/include/pte.h @@ -1,5 +1,5 @@ -/* $OpenBSD: pte.h,v 1.4 1996/07/29 22:59:10 niklas Exp $ */ -/* $NetBSD: pte.h,v 1.4 1996/02/01 22:28:56 mycroft Exp $ */ +/* $OpenBSD: pte.h,v 1.5 1996/10/30 22:39:23 niklas Exp $ */ +/* $NetBSD: pte.h,v 1.7 1996/10/01 20:21:05 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -41,42 +41,53 @@ /* * Alpha Page Table Entry */ -typedef u_int64_t pt_entry_t; + +#include <machine/alpha_cpu.h> + +typedef alpha_pt_entry_t pt_entry_t; + #define PT_ENTRY_NULL ((pt_entry_t *) 0) #define PTESHIFT 3 /* pte size == 1 << PTESHIFT */ -#define PG_V 0x0000000000000001 /* PFN Valid */ -#define PG_NV 0x0000000000000000 /* PFN NOT Valid */ -#define PG_FOR 0x0000000000000002 /* Fault on read */ -#define PG_FOW 0x0000000000000004 /* Fault on write */ -#define PG_FOE 0x0000000000000008 /* Fault on execute */ -#define PG_ASM 0x0000000000000010 /* Address space match */ -#define PG_GH 0x0000000000000060 /* Granularity hint */ -#define PG_KRE 0x0000000000000100 /* Kernel read enable */ -#define PG_URE 0x0000000000000200 /* User read enable */ -#define PG_KWE 0x0000000000001000 /* Kernel write enable */ -#define PG_UWE 0x0000000000002000 /* User write enable */ -#define PG_PROT 0x000000000000ff00 +#define PG_V ALPHA_PTE_VALID +#define PG_NV 0 +#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_RSVD 0x000000000000cc80 /* Reserved fpr hardware */ #define PG_WIRED 0x0000000000010000 /* Wired. [SOFTWARE] */ -#define PG_FRAME 0xffffffff00000000 +#define PG_FRAME ALPHA_PTE_RAME #define PG_SHIFT 32 -#define PG_PFNUM(x) (((x) & PG_FRAME) >> PG_SHIFT) +#define PG_PFNUM(x) ALPHA_PTE_TO_PFN(x) +#if 0 /* XXX NOT HERE */ #define K0SEG_BEGIN 0xfffffc0000000000 /* unmapped, cached */ #define K0SEG_END 0xfffffe0000000000 #define PHYS_UNCACHED 0x0000000040000000 +#endif #ifndef _LOCORE +#if 0 /* XXX NOT HERE */ #define k0segtophys(x) ((vm_offset_t)(x) & 0x00000003ffffffff) #define phystok0seg(x) ((vm_offset_t)(x) | K0SEG_BEGIN) #define phystouncached(x) ((vm_offset_t)(x) | PHYS_UNCACHED) #define uncachedtophys(x) ((vm_offset_t)(x) & ~PHYS_UNCACHED) +#endif #define PTEMASK (NPTEPG - 1) #define vatopte(va) (((va) >> PGSHIFT) & PTEMASK) #define vatoste(va) (((va) >> SEGSHIFT) & PTEMASK) +#define kvtol1pte(va) \ + (((vm_offset_t)(va) >> (PGSHIFT + 2*(PGSHIFT-PTESHIFT))) & PTEMASK) + #define vatopa(va) \ ((PG_PFNUM(*kvtopte(va)) << PGSHIFT) | ((vm_offset_t)(va) & PGOFSET)) @@ -92,15 +103,9 @@ typedef u_int64_t pt_entry_t; #define ptetokv(pte) \ ((((pt_entry_t *)(pte) - Sysmap) << PGSHIFT) + VM_MIN_KERNEL_ADDRESS) -/* - * Kernel virtual address to Lev1map entry index. - */ -#define kvtol1pte(va) \ - (((vm_offset_t)(va) >> (PGSHIFT + 2*(PGSHIFT-PTESHIFT))) & PTEMASK) - #define loadustp(stpte) { \ Lev1map[kvtol1pte(VM_MIN_ADDRESS)] = stpte; \ - TBIAP(); \ + ALPHA_TBIAP(); \ } extern pt_entry_t *Lev1map; /* Alpha Level One page table */ diff --git a/sys/arch/alpha/include/ptrace.h b/sys/arch/alpha/include/ptrace.h index c729976d16b..a38169df9d0 100644 --- a/sys/arch/alpha/include/ptrace.h +++ b/sys/arch/alpha/include/ptrace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ptrace.h,v 1.2 1996/07/29 22:59:11 niklas Exp $ */ +/* $OpenBSD: ptrace.h,v 1.3 1996/10/30 22:39:24 niklas Exp $ */ /* $NetBSD: ptrace.h,v 1.1 1995/02/13 23:07:51 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/reg.h b/sys/arch/alpha/include/reg.h index 6dbb8d0ed41..f7f9dcde9ed 100644 --- a/sys/arch/alpha/include/reg.h +++ b/sys/arch/alpha/include/reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: reg.h,v 1.2 1996/07/29 22:59:13 niklas Exp $ */ +/* $OpenBSD: reg.h,v 1.3 1996/10/30 22:39:25 niklas Exp $ */ /* $NetBSD: reg.h,v 1.2 1995/03/28 18:14:07 jtc Exp $ */ /* @@ -94,6 +94,8 @@ struct fpreg { #ifdef _KERNEL void restorefpstate __P((struct fpreg *)); void savefpstate __P((struct fpreg *)); +void frametoreg __P((struct trapframe *, struct reg *)); +void regtoframe __P((struct reg *, struct trapframe *)); #endif #endif /* _ALPHA_REG_H_ */ diff --git a/sys/arch/alpha/include/rpb.h b/sys/arch/alpha/include/rpb.h index ca1f09ab7e8..cbe4b76eccf 100644 --- a/sys/arch/alpha/include/rpb.h +++ b/sys/arch/alpha/include/rpb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rpb.h,v 1.4 1996/07/29 22:59:15 niklas Exp $ */ +/* $OpenBSD: rpb.h,v 1.5 1996/10/30 22:39:26 niklas Exp $ */ /* $NetBSD: rpb.h,v 1.7 1996/04/29 16:23:11 cgd Exp $ */ /* @@ -136,11 +136,15 @@ struct rpb { 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 */ - long (*rpb_save_term)(); /* E0: terminal save */ + /* XXX Are the protos below correct? */ + long (*rpb_save_term) __P((long)); + /* E0: terminal save */ long rpb_save_term_val; /* E8: */ - long (*rpb_rest_term)(); /* F0: terminal restore */ + long (*rpb_rest_term) __P((long)); + /* F0: terminal restore */ long rpb_rest_term_val; /* F8: */ - long (*rpb_restart)(); /* 100: restart */ + long (*rpb_restart) __P((long)); + /* 100: restart */ long rpb_restart_val; /* 108: */ u_int64_t rpb_reserve_os; /* 110: */ u_int64_t rpb_reserve_hw; /* 118: */ @@ -313,7 +317,7 @@ struct ctb { */ struct crd { int64_t descriptor; - int (*code)(); + int (*code) __P((struct crd *)); }; /* diff --git a/sys/arch/alpha/include/setjmp.h b/sys/arch/alpha/include/setjmp.h index 44cc80a4de4..7b032bb312e 100644 --- a/sys/arch/alpha/include/setjmp.h +++ b/sys/arch/alpha/include/setjmp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: setjmp.h,v 1.2 1996/07/29 22:59:16 niklas Exp $ */ +/* $OpenBSD: setjmp.h,v 1.3 1996/10/30 22:39:27 niklas Exp $ */ /* $NetBSD: setjmp.h,v 1.1 1995/02/13 23:07:55 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/sfbreg.h b/sys/arch/alpha/include/sfbreg.h index cdef5423be9..1adff8f3578 100644 --- a/sys/arch/alpha/include/sfbreg.h +++ b/sys/arch/alpha/include/sfbreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sfbreg.h,v 1.2 1996/07/29 22:59:18 niklas Exp $ */ +/* $OpenBSD: sfbreg.h,v 1.3 1996/10/30 22:39:28 niklas Exp $ */ /* $NetBSD: sfbreg.h,v 1.1 1996/05/01 21:15:46 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/signal.h b/sys/arch/alpha/include/signal.h index 33fd77a3a79..8df58e92099 100644 --- a/sys/arch/alpha/include/signal.h +++ b/sys/arch/alpha/include/signal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: signal.h,v 1.2 1996/07/29 22:59:20 niklas Exp $ */ +/* $OpenBSD: signal.h,v 1.3 1996/10/30 22:39:29 niklas Exp $ */ /* $NetBSD: signal.h,v 1.2 1995/02/16 03:08:08 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/stdarg.h b/sys/arch/alpha/include/stdarg.h index 714090bcd28..6d3b043d87c 100644 --- a/sys/arch/alpha/include/stdarg.h +++ b/sys/arch/alpha/include/stdarg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: stdarg.h,v 1.3 1996/07/29 22:59:21 niklas Exp $ */ -/* $NetBSD: stdarg.h,v 1.3 1995/12/26 00:15:47 mycroft Exp $ */ +/* $OpenBSD: stdarg.h,v 1.4 1996/10/30 22:39:30 niklas Exp $ */ +/* $NetBSD: stdarg.h,v 1.4 1996/10/09 21:13:05 cgd Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -47,7 +47,7 @@ typedef _BSD_VA_LIST_ va_list; (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long)) #define va_start(ap, last) \ - (__builtin_next_arg(last), (ap) = *(va_list *)__builtin_saveregs()) + (__builtin_next_arg(last), (ap) = *(va_list *)__builtin_saveregs(), (ap).pad = 0) #define __REAL_TYPE_CLASS 8 #define __va_arg_offset(ap, type) \ diff --git a/sys/arch/alpha/include/tgareg.h b/sys/arch/alpha/include/tgareg.h index 59a5f2cc740..f64d01b693c 100644 --- a/sys/arch/alpha/include/tgareg.h +++ b/sys/arch/alpha/include/tgareg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tgareg.h,v 1.2 1996/07/29 22:59:23 niklas Exp $ */ +/* $OpenBSD: tgareg.h,v 1.3 1996/10/30 22:39:31 niklas Exp $ */ /* $NetBSD: tgareg.h,v 1.1 1996/04/12 01:44:23 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/types.h b/sys/arch/alpha/include/types.h index 8f4367884a4..a068d7920fb 100644 --- a/sys/arch/alpha/include/types.h +++ b/sys/arch/alpha/include/types.h @@ -1,5 +1,5 @@ -/* $OpenBSD: types.h,v 1.2 1996/07/29 22:59:27 niklas Exp $ */ -/* $NetBSD: types.h,v 1.4 1995/07/06 03:39:32 cgd Exp $ */ +/* $OpenBSD: types.h,v 1.3 1996/10/30 22:39:32 niklas Exp $ */ +/* $NetBSD: types.h,v 1.5 1996/10/01 14:26:18 cgd Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -70,6 +70,4 @@ typedef unsigned long u_int64_t; typedef int64_t register_t; -#define __BDEVSW_DUMP_OLD_TYPE - #endif /* _MACHTYPES_H_ */ diff --git a/sys/arch/alpha/include/varargs.h b/sys/arch/alpha/include/varargs.h index e6a8c3346dd..38be90fdf3d 100644 --- a/sys/arch/alpha/include/varargs.h +++ b/sys/arch/alpha/include/varargs.h @@ -1,5 +1,5 @@ -/* $OpenBSD: varargs.h,v 1.3 1996/07/29 22:59:29 niklas Exp $ */ -/* $NetBSD: varargs.h,v 1.4 1995/12/26 01:16:24 mycroft Exp $ */ +/* $OpenBSD: varargs.h,v 1.4 1996/10/30 22:39:33 niklas Exp $ */ +/* $NetBSD: varargs.h,v 1.5 1996/10/09 21:13:05 cgd Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -57,6 +57,6 @@ #undef va_start #define va_start(ap) \ - ((ap) = *(va_list *)__builtin_saveregs()) + ((ap) = *(va_list *)__builtin_saveregs(), (ap).pad = 0) #endif /* !_ALPHA_VARARGS_H_ */ diff --git a/sys/arch/alpha/include/vmparam.h b/sys/arch/alpha/include/vmparam.h index 34f99d525cb..62eb118299c 100644 --- a/sys/arch/alpha/include/vmparam.h +++ b/sys/arch/alpha/include/vmparam.h @@ -1,5 +1,5 @@ -/* $OpenBSD: vmparam.h,v 1.3 1996/07/29 22:59:31 niklas Exp $ */ -/* $NetBSD: vmparam.h,v 1.2 1995/11/23 02:36:46 cgd Exp $ */ +/* $OpenBSD: vmparam.h,v 1.4 1996/10/30 22:39:34 niklas Exp $ */ +/* $NetBSD: vmparam.h,v 1.3 1996/07/09 00:28:25 cgd Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -84,15 +84,6 @@ #define DMMIN 32 /* smallest swap allocation */ #define DMMAX 4096 /* largest potential swap allocation */ -#ifdef THESE_ARE_WRONG -/* - * Sizes of the system and user portions of the system page table. - */ -/* SYSPTSIZE IS SILLY; (really number of buffers for I/O) */ -#define SYSPTSIZE 1228 -#define USRPTSIZE 1024 -#endif /* WRONG */ - /* * PTEs for mapping user space into the kernel for phyio operations. * 64 pte's are enough to cover 8 disks * MAXBSIZE. @@ -138,31 +129,21 @@ * swapped in you deserve some resources. We protect the last SAFERSS * pages against paging and will just swap you out rather than paging you. * Note that each process has at least UPAGES+CLSIZE pages which are not - * paged anyways (this is currently 8+2=10 pages or 5k bytes), so this - * number just means a swapped in process is given around 25k bytes. - * Just for fun: current memory prices are 4600$ a megabyte on VAX (4/22/81), - * so we loan each swapped in process memory worth 100$, or just admit - * that we don't consider it worthwhile and swap it out to disk which costs - * $30/mb or about $0.75. + * paged anyways, in addition to SAFERSS. */ -#define SAFERSS 4 /* nominal ``small'' resident set size +#define SAFERSS 10 /* nominal ``small'' resident set size protected against replacement */ -#ifdef THESE_ARE_WRONG -#define mapin(pte, v, pfnum, prot) \ - (*(int *)(pte) = ((pfnum) << PG_SHIFT) | (prot), MachTLBFlushAddr(v)) -#endif /* WRONG */ - /* * Mach derived constants */ /* user/kernel map constants */ -#define VM_MIN_ADDRESS ((vm_offset_t)0x0000000000000000) /* 0 */ -#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x0000000200000000) /* 8G */ +#define VM_MIN_ADDRESS ((vm_offset_t)ALPHA_USEG_BASE) /* 0 */ +#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x0000000200000000) /* 8G XXX */ #define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS -#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xfffffe0000000000) -#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xffffffffffffffff) +#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 */ #define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES) @@ -171,8 +152,3 @@ /* some Alpha-specific constants */ #define VPTBASE ((vm_offset_t)0xfffffffc00000000) /* Virt. pg table */ - -#ifdef THESE_ARE_WRONG -/* pcb base */ -#define pcbb(p) ((u_int)(p)->p_addr) -#endif /* WRONG */ diff --git a/sys/arch/alpha/include/vuid_event.h b/sys/arch/alpha/include/vuid_event.h index a9ca5c9d112..833040b542e 100644 --- a/sys/arch/alpha/include/vuid_event.h +++ b/sys/arch/alpha/include/vuid_event.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vuid_event.h,v 1.2 1996/07/29 22:59:33 niklas Exp $ */ +/* $OpenBSD: vuid_event.h,v 1.3 1996/10/30 22:39:35 niklas Exp $ */ /* $NetBSD: vuid_event.h,v 1.1 1996/04/12 01:45:47 cgd Exp $ */ /* diff --git a/sys/arch/alpha/include/wsconsio.h b/sys/arch/alpha/include/wsconsio.h index 1f4bb1a418d..8dc493b5547 100644 --- a/sys/arch/alpha/include/wsconsio.h +++ b/sys/arch/alpha/include/wsconsio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wsconsio.h,v 1.2 1996/07/29 22:59:35 niklas Exp $ */ +/* $OpenBSD: wsconsio.h,v 1.3 1996/10/30 22:39:35 niklas Exp $ */ /* $NetBSD: wsconsio.h,v 1.1 1996/04/12 01:43:06 cgd Exp $ */ /* diff --git a/sys/arch/alpha/isa/isa_machdep.h b/sys/arch/alpha/isa/isa_machdep.h index e229a164276..75d6cbe4020 100644 --- a/sys/arch/alpha/isa/isa_machdep.h +++ b/sys/arch/alpha/isa/isa_machdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isa_machdep.h,v 1.2 1996/07/29 22:59:44 niklas Exp $ */ +/* $OpenBSD: isa_machdep.h,v 1.3 1996/10/30 22:39:37 niklas Exp $ */ /* $NetBSD: isa_machdep.h,v 1.2 1996/04/12 05:39:02 cgd Exp $ */ /* diff --git a/sys/arch/alpha/isa/isafcns_jensen.c b/sys/arch/alpha/isa/isafcns_jensen.c index 285d75a90ac..d702ab51f03 100644 --- a/sys/arch/alpha/isa/isafcns_jensen.c +++ b/sys/arch/alpha/isa/isafcns_jensen.c @@ -1,5 +1,5 @@ -/* $OpenBSD: isafcns_jensen.c,v 1.3 1996/07/29 22:59:46 niklas Exp $ */ -/* $NetBSD: isafcns_jensen.c,v 1.2 1996/04/12 01:54:04 cgd Exp $ */ +/* $OpenBSD: isafcns_jensen.c,v 1.4 1996/10/30 22:39:38 niklas Exp $ */ +/* $NetBSD: isafcns_jensen.c,v 1.4 1996/10/13 02:59:54 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/isa/mcclock_isa.c b/sys/arch/alpha/isa/mcclock_isa.c index 30ea94aa83c..11667b25338 100644 --- a/sys/arch/alpha/isa/mcclock_isa.c +++ b/sys/arch/alpha/isa/mcclock_isa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mcclock_isa.c,v 1.2 1996/07/29 22:59:47 niklas Exp $ */ +/* $OpenBSD: mcclock_isa.c,v 1.3 1996/10/30 22:39:39 niklas Exp $ */ /* $NetBSD: mcclock_isa.c,v 1.2 1996/04/17 22:22:46 cgd Exp $ */ /* diff --git a/sys/arch/alpha/isa/pckbd.c b/sys/arch/alpha/isa/pckbd.c index c10ab4a0a20..f43a4961137 100644 --- a/sys/arch/alpha/isa/pckbd.c +++ b/sys/arch/alpha/isa/pckbd.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pckbd.c,v 1.5 1996/07/29 22:59:49 niklas Exp $ */ -/* $NetBSD: pckbd.c,v 1.7 1996/05/05 01:41:53 thorpej Exp $ */ +/* $OpenBSD: pckbd.c,v 1.6 1996/10/30 22:39:40 niklas Exp $ */ +/* $NetBSD: pckbd.c,v 1.9 1996/10/13 02:59:56 christos Exp $ */ /*- * Copyright (c) 1993, 1994, 1995 Charles Hannum. All rights reserved. @@ -64,6 +64,7 @@ #include <machine/wsconsio.h> #include <alpha/wscons/wsconsvar.h> +#include <alpha/wscons/kbd.h> #include "wscons.h" static volatile u_char ack, nak; /* Don't ask. */ @@ -126,6 +127,15 @@ struct wscons_idev_spec pckbd_wscons_idev = { void pckbd_bell_stop __P((void *)); +static __inline int kbd_wait_output __P((void)); +static __inline int kbd_wait_input __P((void)); +static __inline void kbd_flush_input __P((void)); +u_char kbc_get8042cmd __P((void)); +int kbc_put8042cmd __P((u_char)); +int kbd_cmd __P((u_char, u_char)); +void do_async_update __P((void *)); +void async_update __P((void)); + /* * DANGER WIL ROBINSON -- the values of SCROLL, NUM, CAPS, and ALT are * important. @@ -142,12 +152,14 @@ void pckbd_bell_stop __P((void *)); #define NONE 0x0400 /* no function */ #define KBD_DELAY \ - { u_char x = bus_io_read_1(pckbd_bc, pckbd_delay_ioh, 0); } \ - { u_char x = bus_io_read_1(pckbd_bc, pckbd_delay_ioh, 0); } \ - { u_char x = bus_io_read_1(pckbd_bc, pckbd_delay_ioh, 0); } \ - { u_char x = bus_io_read_1(pckbd_bc, pckbd_delay_ioh, 0); } - -static inline int + do { \ + bus_io_read_1(pckbd_bc, pckbd_delay_ioh, 0); \ + bus_io_read_1(pckbd_bc, pckbd_delay_ioh, 0); \ + bus_io_read_1(pckbd_bc, pckbd_delay_ioh, 0); \ + bus_io_read_1(pckbd_bc, pckbd_delay_ioh, 0); \ + } while(0) + +static __inline int kbd_wait_output() { u_int i; @@ -161,7 +173,7 @@ kbd_wait_output() return 0; } -static inline int +static __inline int kbd_wait_input() { u_int i; @@ -175,7 +187,7 @@ kbd_wait_input() return 0; } -static inline void +static __inline void kbd_flush_input() { u_int i; @@ -193,7 +205,7 @@ kbd_flush_input() /* * Get the current command byte. */ -static u_char +u_char kbc_get8042cmd() { @@ -209,7 +221,7 @@ kbc_get8042cmd() /* * Pass command byte to keyboard controller (8042). */ -static int +int kbc_put8042cmd(val) u_char val; { @@ -416,7 +428,6 @@ int pckbdintr(arg) void *arg; { - struct pckbd_softc *sc = arg; u_char data; static u_char last; @@ -450,11 +461,10 @@ pckbdintr(arg) } void -do_async_update(poll) - u_char poll; +do_async_update(vp) + void *vp; { - int pos; - static int old_pos = -1; + int poll = *(int *)vp; async = 0; @@ -479,16 +489,18 @@ do_async_update(poll) void async_update() { + static int nopoll = 0; + static int poll = 1; if (kernel || polling) { if (async) - untimeout(do_async_update, NULL); - do_async_update(1); + untimeout(do_async_update, &nopoll); + do_async_update(&poll); } else { if (async) return; async = 1; - timeout(do_async_update, NULL, 1); + timeout(do_async_update, &nopoll, 1); } } @@ -582,134 +594,134 @@ typedef struct { } Scan_def; static Scan_def scan_codes[] = { - NONE, "", "", "", /* 0 unused */ - ASCII, "\033", "\033", "\033", /* 1 ESCape */ - ASCII, "1", "!", "!", /* 2 1 */ - ASCII, "2", "@", "\000", /* 3 2 */ - ASCII, "3", "#", "#", /* 4 3 */ - ASCII, "4", "$", "$", /* 5 4 */ - ASCII, "5", "%", "%", /* 6 5 */ - ASCII, "6", "^", "\036", /* 7 6 */ - ASCII, "7", "&", "&", /* 8 7 */ - ASCII, "8", "*", "\010", /* 9 8 */ - ASCII, "9", "(", "(", /* 10 9 */ - ASCII, "0", ")", ")", /* 11 0 */ - ASCII, "-", "_", "\037", /* 12 - */ - ASCII, "=", "+", "+", /* 13 = */ - ASCII, "\177", "\177", "\010", /* 14 backspace */ - ASCII, "\t", "\177\t", "\t", /* 15 tab */ - ASCII, "q", "Q", "\021", /* 16 q */ - ASCII, "w", "W", "\027", /* 17 w */ - ASCII, "e", "E", "\005", /* 18 e */ - ASCII, "r", "R", "\022", /* 19 r */ - ASCII, "t", "T", "\024", /* 20 t */ - ASCII, "y", "Y", "\031", /* 21 y */ - ASCII, "u", "U", "\025", /* 22 u */ - ASCII, "i", "I", "\011", /* 23 i */ - ASCII, "o", "O", "\017", /* 24 o */ - ASCII, "p", "P", "\020", /* 25 p */ - ASCII, "[", "{", "\033", /* 26 [ */ - ASCII, "]", "}", "\035", /* 27 ] */ - ASCII, "\r", "\r", "\n", /* 28 return */ - CTL, "", "", "", /* 29 control */ - ASCII, "a", "A", "\001", /* 30 a */ - ASCII, "s", "S", "\023", /* 31 s */ - ASCII, "d", "D", "\004", /* 32 d */ - ASCII, "f", "F", "\006", /* 33 f */ - ASCII, "g", "G", "\007", /* 34 g */ - ASCII, "h", "H", "\010", /* 35 h */ - ASCII, "j", "J", "\n", /* 36 j */ - ASCII, "k", "K", "\013", /* 37 k */ - ASCII, "l", "L", "\014", /* 38 l */ - ASCII, ";", ":", ";", /* 39 ; */ - ASCII, "'", "\"", "'", /* 40 ' */ - ASCII, "`", "~", "`", /* 41 ` */ - SHIFT, "", "", "", /* 42 shift */ - ASCII, "\\", "|", "\034", /* 43 \ */ - ASCII, "z", "Z", "\032", /* 44 z */ - ASCII, "x", "X", "\030", /* 45 x */ - ASCII, "c", "C", "\003", /* 46 c */ - ASCII, "v", "V", "\026", /* 47 v */ - ASCII, "b", "B", "\002", /* 48 b */ - ASCII, "n", "N", "\016", /* 49 n */ - ASCII, "m", "M", "\r", /* 50 m */ - ASCII, ",", "<", "<", /* 51 , */ - ASCII, ".", ">", ">", /* 52 . */ - ASCII, "/", "?", "\037", /* 53 / */ - SHIFT, "", "", "", /* 54 shift */ - KP, "*", "*", "*", /* 55 kp * */ - ALT, "", "", "", /* 56 alt */ - ASCII, " ", " ", "\000", /* 57 space */ - CAPS, "", "", "", /* 58 caps */ - FUNC, "\033[M", "\033[Y", "\033[k", /* 59 f1 */ - FUNC, "\033[N", "\033[Z", "\033[l", /* 60 f2 */ - FUNC, "\033[O", "\033[a", "\033[m", /* 61 f3 */ - FUNC, "\033[P", "\033[b", "\033[n", /* 62 f4 */ - FUNC, "\033[Q", "\033[c", "\033[o", /* 63 f5 */ - FUNC, "\033[R", "\033[d", "\033[p", /* 64 f6 */ - FUNC, "\033[S", "\033[e", "\033[q", /* 65 f7 */ - FUNC, "\033[T", "\033[f", "\033[r", /* 66 f8 */ - FUNC, "\033[U", "\033[g", "\033[s", /* 67 f9 */ - FUNC, "\033[V", "\033[h", "\033[t", /* 68 f10 */ - NUM, "", "", "", /* 69 num lock */ - SCROLL, "", "", "", /* 70 scroll lock */ - KP, "7", "\033[H", "7", /* 71 kp 7 */ - KP, "8", "\033[A", "8", /* 72 kp 8 */ - KP, "9", "\033[I", "9", /* 73 kp 9 */ - KP, "-", "-", "-", /* 74 kp - */ - KP, "4", "\033[D", "4", /* 75 kp 4 */ - KP, "5", "\033[E", "5", /* 76 kp 5 */ - KP, "6", "\033[C", "6", /* 77 kp 6 */ - KP, "+", "+", "+", /* 78 kp + */ - KP, "1", "\033[F", "1", /* 79 kp 1 */ - KP, "2", "\033[B", "2", /* 80 kp 2 */ - KP, "3", "\033[G", "3", /* 81 kp 3 */ - KP, "0", "\033[L", "0", /* 82 kp 0 */ - KP, ".", "\177", ".", /* 83 kp . */ - NONE, "", "", "", /* 84 0 */ - NONE, "100", "", "", /* 85 0 */ - NONE, "101", "", "", /* 86 0 */ - FUNC, "\033[W", "\033[i", "\033[u", /* 87 f11 */ - FUNC, "\033[X", "\033[j", "\033[v", /* 88 f12 */ - NONE, "102", "", "", /* 89 0 */ - NONE, "103", "", "", /* 90 0 */ - NONE, "", "", "", /* 91 0 */ - NONE, "", "", "", /* 92 0 */ - NONE, "", "", "", /* 93 0 */ - NONE, "", "", "", /* 94 0 */ - NONE, "", "", "", /* 95 0 */ - NONE, "", "", "", /* 96 0 */ - NONE, "", "", "", /* 97 0 */ - NONE, "", "", "", /* 98 0 */ - NONE, "", "", "", /* 99 0 */ - NONE, "", "", "", /* 100 */ - NONE, "", "", "", /* 101 */ - NONE, "", "", "", /* 102 */ - NONE, "", "", "", /* 103 */ - NONE, "", "", "", /* 104 */ - NONE, "", "", "", /* 105 */ - NONE, "", "", "", /* 106 */ - NONE, "", "", "", /* 107 */ - NONE, "", "", "", /* 108 */ - NONE, "", "", "", /* 109 */ - NONE, "", "", "", /* 110 */ - NONE, "", "", "", /* 111 */ - NONE, "", "", "", /* 112 */ - NONE, "", "", "", /* 113 */ - NONE, "", "", "", /* 114 */ - NONE, "", "", "", /* 115 */ - NONE, "", "", "", /* 116 */ - NONE, "", "", "", /* 117 */ - NONE, "", "", "", /* 118 */ - NONE, "", "", "", /* 119 */ - NONE, "", "", "", /* 120 */ - NONE, "", "", "", /* 121 */ - NONE, "", "", "", /* 122 */ - NONE, "", "", "", /* 123 */ - NONE, "", "", "", /* 124 */ - NONE, "", "", "", /* 125 */ - NONE, "", "", "", /* 126 */ - NONE, "", "", "", /* 127 */ + { NONE, "", "", "" }, /* 0 unused */ + { ASCII, "\033", "\033", "\033" }, /* 1 ESCape */ + { ASCII, "1", "!", "!" }, /* 2 1 */ + { ASCII, "2", "@", "\000" }, /* 3 2 */ + { ASCII, "3", "#", "#" }, /* 4 3 */ + { ASCII, "4", "$", "$" }, /* 5 4 */ + { ASCII, "5", "%", "%" }, /* 6 5 */ + { ASCII, "6", "^", "\036" }, /* 7 6 */ + { ASCII, "7", "&", "&" }, /* 8 7 */ + { ASCII, "8", "*", "\010" }, /* 9 8 */ + { ASCII, "9", "(", "(" }, /* 10 9 */ + { ASCII, "0", ")", ")" }, /* 11 0 */ + { ASCII, "-", "_", "\037" }, /* 12 - */ + { ASCII, "=", "+", "+" }, /* 13 = */ + { ASCII, "\177", "\177", "\010" }, /* 14 backspace */ + { ASCII, "\t", "\177\t", "\t" }, /* 15 tab */ + { ASCII, "q", "Q", "\021" }, /* 16 q */ + { ASCII, "w", "W", "\027" }, /* 17 w */ + { ASCII, "e", "E", "\005" }, /* 18 e */ + { ASCII, "r", "R", "\022" }, /* 19 r */ + { ASCII, "t", "T", "\024" }, /* 20 t */ + { ASCII, "y", "Y", "\031" }, /* 21 y */ + { ASCII, "u", "U", "\025" }, /* 22 u */ + { ASCII, "i", "I", "\011" }, /* 23 i */ + { ASCII, "o", "O", "\017" }, /* 24 o */ + { ASCII, "p", "P", "\020" }, /* 25 p */ + { ASCII, "[", "{", "\033" }, /* 26 [ */ + { ASCII, "]", "}", "\035" }, /* 27 ] */ + { ASCII, "\r", "\r", "\n" }, /* 28 return */ + { CTL, "", "", "" }, /* 29 control */ + { ASCII, "a", "A", "\001" }, /* 30 a */ + { ASCII, "s", "S", "\023" }, /* 31 s */ + { ASCII, "d", "D", "\004" }, /* 32 d */ + { ASCII, "f", "F", "\006" }, /* 33 f */ + { ASCII, "g", "G", "\007" }, /* 34 g */ + { ASCII, "h", "H", "\010" }, /* 35 h */ + { ASCII, "j", "J", "\n" }, /* 36 j */ + { ASCII, "k", "K", "\013" }, /* 37 k */ + { ASCII, "l", "L", "\014" }, /* 38 l */ + { ASCII, ";", ":", ";" }, /* 39 ; */ + { ASCII, "'", "\"", "'" }, /* 40 ' */ + { ASCII, "`", "~", "`" }, /* 41 ` */ + { SHIFT, "", "", "" }, /* 42 shift */ + { ASCII, "\\", "|", "\034" }, /* 43 \ */ + { ASCII, "z", "Z", "\032" }, /* 44 z */ + { ASCII, "x", "X", "\030" }, /* 45 x */ + { ASCII, "c", "C", "\003" }, /* 46 c */ + { ASCII, "v", "V", "\026" }, /* 47 v */ + { ASCII, "b", "B", "\002" }, /* 48 b */ + { ASCII, "n", "N", "\016" }, /* 49 n */ + { ASCII, "m", "M", "\r" }, /* 50 m */ + { ASCII, ",", "<", "<" }, /* 51 , */ + { ASCII, ".", ">", ">" }, /* 52 . */ + { ASCII, "/", "?", "\037" }, /* 53 / */ + { SHIFT, "", "", "" }, /* 54 shift */ + { KP, "*", "*", "*" }, /* 55 kp * */ + { ALT, "", "", "" }, /* 56 alt */ + { ASCII, " ", " ", "\000" }, /* 57 space */ + { CAPS, "", "", "" }, /* 58 caps */ + { FUNC, "\033[M", "\033[Y", "\033[k" }, /* 59 f1 */ + { FUNC, "\033[N", "\033[Z", "\033[l" }, /* 60 f2 */ + { FUNC, "\033[O", "\033[a", "\033[m" }, /* 61 f3 */ + { FUNC, "\033[P", "\033[b", "\033[n" }, /* 62 f4 */ + { FUNC, "\033[Q", "\033[c", "\033[o" }, /* 63 f5 */ + { FUNC, "\033[R", "\033[d", "\033[p" }, /* 64 f6 */ + { FUNC, "\033[S", "\033[e", "\033[q" }, /* 65 f7 */ + { FUNC, "\033[T", "\033[f", "\033[r" }, /* 66 f8 */ + { FUNC, "\033[U", "\033[g", "\033[s" }, /* 67 f9 */ + { FUNC, "\033[V", "\033[h", "\033[t" }, /* 68 f10 */ + { NUM, "", "", "" }, /* 69 num lock */ + { SCROLL, "", "", "" }, /* 70 scroll lock */ + { KP, "7", "\033[H", "7" }, /* 71 kp 7 */ + { KP, "8", "\033[A", "8" }, /* 72 kp 8 */ + { KP, "9", "\033[I", "9" }, /* 73 kp 9 */ + { KP, "-", "-", "-" }, /* 74 kp - */ + { KP, "4", "\033[D", "4" }, /* 75 kp 4 */ + { KP, "5", "\033[E", "5" }, /* 76 kp 5 */ + { KP, "6", "\033[C", "6" }, /* 77 kp 6 */ + { KP, "+", "+", "+" }, /* 78 kp + */ + { KP, "1", "\033[F", "1" }, /* 79 kp 1 */ + { KP, "2", "\033[B", "2" }, /* 80 kp 2 */ + { KP, "3", "\033[G", "3" }, /* 81 kp 3 */ + { KP, "0", "\033[L", "0" }, /* 82 kp 0 */ + { KP, ".", "\177", "." }, /* 83 kp . */ + { NONE, "", "", "" }, /* 84 0 */ + { NONE, "100", "", "" }, /* 85 0 */ + { NONE, "101", "", "" }, /* 86 0 */ + { FUNC, "\033[W", "\033[i", "\033[u" }, /* 87 f11 */ + { FUNC, "\033[X", "\033[j", "\033[v" }, /* 88 f12 */ + { NONE, "102", "", "" }, /* 89 0 */ + { NONE, "103", "", "" }, /* 90 0 */ + { NONE, "", "", "" }, /* 91 0 */ + { NONE, "", "", "" }, /* 92 0 */ + { NONE, "", "", "" }, /* 93 0 */ + { NONE, "", "", "" }, /* 94 0 */ + { NONE, "", "", "" }, /* 95 0 */ + { NONE, "", "", "" }, /* 96 0 */ + { NONE, "", "", "" }, /* 97 0 */ + { NONE, "", "", "" }, /* 98 0 */ + { NONE, "", "", "" }, /* 99 0 */ + { NONE, "", "", "" }, /* 100 */ + { NONE, "", "", "" }, /* 101 */ + { NONE, "", "", "" }, /* 102 */ + { NONE, "", "", "" }, /* 103 */ + { NONE, "", "", "" }, /* 104 */ + { NONE, "", "", "" }, /* 105 */ + { NONE, "", "", "" }, /* 106 */ + { NONE, "", "", "" }, /* 107 */ + { NONE, "", "", "" }, /* 108 */ + { NONE, "", "", "" }, /* 109 */ + { NONE, "", "", "" }, /* 110 */ + { NONE, "", "", "" }, /* 111 */ + { NONE, "", "", "" }, /* 112 */ + { NONE, "", "", "" }, /* 113 */ + { NONE, "", "", "" }, /* 114 */ + { NONE, "", "", "" }, /* 115 */ + { NONE, "", "", "" }, /* 116 */ + { NONE, "", "", "" }, /* 117 */ + { NONE, "", "", "" }, /* 118 */ + { NONE, "", "", "" }, /* 119 */ + { NONE, "", "", "" }, /* 120 */ + { NONE, "", "", "" }, /* 121 */ + { NONE, "", "", "" }, /* 122 */ + { NONE, "", "", "" }, /* 123 */ + { NONE, "", "", "" }, /* 124 */ + { NONE, "", "", "" }, /* 125 */ + { NONE, "", "", "" }, /* 126 */ + { NONE, "", "", "" } /* 127 */ }; /* diff --git a/sys/arch/alpha/isa/pckbdreg.h b/sys/arch/alpha/isa/pckbdreg.h index 0f5aa607fff..10e63b35074 100644 --- a/sys/arch/alpha/isa/pckbdreg.h +++ b/sys/arch/alpha/isa/pckbdreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pckbdreg.h,v 1.2 1996/07/29 22:59:51 niklas Exp $ */ +/* $OpenBSD: pckbdreg.h,v 1.3 1996/10/30 22:39:41 niklas Exp $ */ /* $NetBSD: pckbdreg.h,v 1.1 1995/08/03 00:48:30 cgd Exp $ */ /* diff --git a/sys/arch/alpha/isa/pms.c b/sys/arch/alpha/isa/pms.c index 3c13fe88153..7b758f43916 100644 --- a/sys/arch/alpha/isa/pms.c +++ b/sys/arch/alpha/isa/pms.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pms.c,v 1.2 1996/07/29 22:59:53 niklas Exp $ */ -/* $NetBSD: pms.c,v 1.1 1996/04/12 01:53:06 cgd Exp $ */ +/* $OpenBSD: pms.c,v 1.3 1996/10/30 22:39:42 niklas Exp $ */ +/* $NetBSD: pms.c,v 1.3 1996/10/13 02:59:58 christos Exp $ */ /*- * Copyright (c) 1994 Charles Hannum. @@ -53,6 +53,7 @@ #include <machine/intr.h> #include <dev/isa/isavar.h> #include <alpha/wscons/wsconsvar.h> +#include <alpha/wscons/ms.h> #define PMS_DATA 0x60 /* offset for data port, read-write */ #define PMS_CNTRL 0x64 /* offset for control port, write-only */ @@ -126,12 +127,17 @@ struct wscons_mdev_spec pms_mdev_spec = { pms_disable, }; -static inline void +static __inline void pms_flush __P((void)); +static __inline void pms_dev_cmd __P((u_char)); +static __inline void pms_aux_cmd __P((u_char)); +static __inline void pms_pit_cmd __P((u_char)); + +static __inline void pms_flush() { u_char c; - while (c = bus_io_read_1(pms_bc, pms_status_ioh, 0) & 0x03) + while ((c = bus_io_read_1(pms_bc, pms_status_ioh, 0)) & 0x03) if ((c & PMS_OBUF_FULL) == PMS_OBUF_FULL) { /* XXX - delay is needed to prevent some keyboards from wedging when the system boots */ @@ -140,7 +146,7 @@ pms_flush() } } -static inline void +static __inline void pms_dev_cmd(value) u_char value; { @@ -151,7 +157,7 @@ pms_dev_cmd(value) bus_io_write_1(pms_bc, pms_data_ioh, 0, value); } -static inline void +static __inline void pms_aux_cmd(value) u_char value; { @@ -160,7 +166,7 @@ pms_aux_cmd(value) bus_io_write_1(pms_bc, pms_cntrl_ioh, 0, value); } -static inline void +static __inline void pms_pit_cmd(value) u_char value; { @@ -288,7 +294,6 @@ pmsintr(arg) static u_char buttons; u_char changed; static char dx, dy; - u_char buffer[5]; if ((sc->sc_state & PMS_OPEN) == 0) { /* Interrupts are not expected. Discard the byte. */ diff --git a/sys/arch/alpha/isa/spkrreg.h b/sys/arch/alpha/isa/spkrreg.h index 89a89edd0f5..d6fe4e6c877 100644 --- a/sys/arch/alpha/isa/spkrreg.h +++ b/sys/arch/alpha/isa/spkrreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: spkrreg.h,v 1.2 1996/07/29 22:59:55 niklas Exp $ */ +/* $OpenBSD: spkrreg.h,v 1.3 1996/10/30 22:39:43 niklas Exp $ */ /* $NetBSD: spkrreg.h,v 1.1 1996/04/12 01:54:46 cgd Exp $ */ /* diff --git a/sys/arch/alpha/isa/timerreg.h b/sys/arch/alpha/isa/timerreg.h index 98dfaa75ceb..7314fb10dde 100644 --- a/sys/arch/alpha/isa/timerreg.h +++ b/sys/arch/alpha/isa/timerreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: timerreg.h,v 1.2 1996/07/29 22:59:57 niklas Exp $ */ +/* $OpenBSD: timerreg.h,v 1.3 1996/10/30 22:39:44 niklas Exp $ */ /* $NetBSD: timerreg.h,v 1.1 1996/04/12 01:54:56 cgd Exp $ */ /*- diff --git a/sys/arch/alpha/pci/apecs.c b/sys/arch/alpha/pci/apecs.c index 9c57dbb14a8..fee67e04274 100644 --- a/sys/arch/alpha/pci/apecs.c +++ b/sys/arch/alpha/pci/apecs.c @@ -1,5 +1,5 @@ -/* $OpenBSD: apecs.c,v 1.4 1996/07/29 23:00:01 niklas Exp $ */ -/* $NetBSD: apecs.c,v 1.7 1996/04/12 06:08:01 cgd Exp $ */ +/* $OpenBSD: apecs.c,v 1.5 1996/10/30 22:39:46 niklas Exp $ */ +/* $NetBSD: apecs.c,v 1.12 1996/10/13 03:00:00 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -45,7 +45,10 @@ #include <dev/pci/pcivar.h> #include <alpha/pci/apecsreg.h> #include <alpha/pci/apecsvar.h> +#include <alpha/pci/apecs_lca.h> +#if defined(DEC_2100_A50) #include <alpha/pci/pci_2100_a50.h> +#endif int apecsmatch __P((struct device *, void *, void *)); void apecsattach __P((struct device *, struct device *, void *)); @@ -58,7 +61,7 @@ struct cfdriver apecs_cd = { NULL, "apecs", DV_DULL, }; -static int apecsprint __P((void *, char *pnp)); +int apecsprint __P((void *, /* const */ char *pnp)); /* There can be only one. */ int apecsfound; @@ -69,7 +72,6 @@ apecsmatch(parent, match, aux) struct device *parent; void *match, *aux; { - struct cfdata *cf = match; struct confargs *ca = aux; /* Make sure that we're looking for an APECS. */ @@ -107,7 +109,7 @@ apecs_init(acp) /* Turn off DMA window enables in PCI Base Reg 1. */ REGVAL(EPIC_PCI_BASE_1) = 0; - wbflush(); + alpha_mb(); /* XXX SGMAP? */ } @@ -161,10 +163,10 @@ apecsattach(parent, self, aux) config_found(self, &pba, apecsprint); } -static int +int apecsprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { register struct pcibus_attach_args *pba = aux; diff --git a/sys/arch/alpha/pci/apecs_lca.h b/sys/arch/alpha/pci/apecs_lca.h new file mode 100644 index 00000000000..5fd663e8ad4 --- /dev/null +++ b/sys/arch/alpha/pci/apecs_lca.h @@ -0,0 +1,35 @@ +/* $OpenBSD: apecs_lca.h,v 1.1 1996/10/30 22:39:47 niklas Exp $ */ + +/* + * Copyright (c) 1996 Niklas Hallqvist + * 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 Niklas Hallqvist. + * 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 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. + */ + +void apecs_lca_bus_io_init __P((bus_chipset_tag_t, void *)); +void apecs_lca_bus_mem_init __P((bus_chipset_tag_t, void *)); diff --git a/sys/arch/alpha/pci/apecs_lca_bus_io.c b/sys/arch/alpha/pci/apecs_lca_bus_io.c index 4aa40d80ab2..8b2fa459a34 100644 --- a/sys/arch/alpha/pci/apecs_lca_bus_io.c +++ b/sys/arch/alpha/pci/apecs_lca_bus_io.c @@ -1,5 +1,5 @@ -/* $OpenBSD: apecs_lca_bus_io.c,v 1.2 1996/07/29 23:00:04 niklas Exp $ */ -/* $NetBSD: apecs_lca_bus_io.c,v 1.2.4.1 1996/06/13 18:14:55 cgd Exp $ */ +/* $OpenBSD: apecs_lca_bus_io.c,v 1.3 1996/10/30 22:39:48 niklas Exp $ */ +/* $NetBSD: apecs_lca_bus_io.c,v 1.4 1996/08/27 16:29:23 cgd Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/device.h> @@ -38,6 +39,7 @@ #include <alpha/pci/apecsreg.h> #include <alpha/pci/lcareg.h> +#include <alpha/pci/apecs_lca.h> #if (APECS_PCI_SIO != LCA_PCI_SIO) #error Sparse I/O addresses do not match up? diff --git a/sys/arch/alpha/pci/apecs_lca_bus_mem.c b/sys/arch/alpha/pci/apecs_lca_bus_mem.c index 6d03c167530..e06744504ac 100644 --- a/sys/arch/alpha/pci/apecs_lca_bus_mem.c +++ b/sys/arch/alpha/pci/apecs_lca_bus_mem.c @@ -1,5 +1,5 @@ -/* $OpenBSD: apecs_lca_bus_mem.c,v 1.2 1996/07/29 23:00:06 niklas Exp $ */ -/* $NetBSD: apecs_lca_bus_mem.c,v 1.2.4.2 1996/06/13 18:14:58 cgd Exp $ */ +/* $OpenBSD: apecs_lca_bus_mem.c,v 1.3 1996/10/30 22:39:48 niklas Exp $ */ +/* $NetBSD: apecs_lca_bus_mem.c,v 1.5 1996/08/27 16:29:24 cgd Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/device.h> @@ -38,6 +39,7 @@ #include <alpha/pci/apecsreg.h> #include <alpha/pci/lcareg.h> +#include <alpha/pci/apecs_lca.h> #if (APECS_PCI_SPARSE != LCA_PCI_SPARSE) || (APECS_PCI_DENSE != LCA_PCI_DENSE) #error Memory addresses do not match up? diff --git a/sys/arch/alpha/pci/apecs_pci.c b/sys/arch/alpha/pci/apecs_pci.c index 6086b9807b5..c61fed79b98 100644 --- a/sys/arch/alpha/pci/apecs_pci.c +++ b/sys/arch/alpha/pci/apecs_pci.c @@ -1,5 +1,5 @@ -/* $OpenBSD: apecs_pci.c,v 1.4 1996/07/29 23:00:07 niklas Exp $ */ -/* $NetBSD: apecs_pci.c,v 1.6 1996/04/12 06:08:09 cgd Exp $ */ +/* $OpenBSD: apecs_pci.c,v 1.5 1996/10/30 22:39:49 niklas Exp $ */ +/* $NetBSD: apecs_pci.c,v 1.9 1996/10/13 03:00:02 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -34,6 +34,8 @@ #include <sys/device.h> #include <vm/vm.h> +#include <machine/autoconf.h> /* badaddr() proto */ + #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <alpha/pci/apecsreg.h> @@ -119,12 +121,12 @@ apecs_conf_read(cpv, tag, offset) if (secondary) { s = splhigh(); old_haxr2 = REGVAL(EPIC_HAXR2); - wbflush(); + alpha_mb(); REGVAL(EPIC_HAXR2) = old_haxr2 | 0x1; - wbflush(); + alpha_mb(); } - datap = (pcireg_t *)phystok0seg(APECS_PCI_CONF | + datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(APECS_PCI_CONF | tag << 5UL | /* XXX */ (offset & ~0x03) << 5 | /* XXX */ 0 << 5 | /* XXX */ @@ -134,9 +136,9 @@ apecs_conf_read(cpv, tag, offset) data = *datap; if (secondary) { - wbflush(); + alpha_mb(); REGVAL(EPIC_HAXR2) = old_haxr2; - wbflush(); + alpha_mb(); splx(s); } @@ -165,12 +167,12 @@ apecs_conf_write(cpv, tag, offset, data) if (secondary) { s = splhigh(); old_haxr2 = REGVAL(EPIC_HAXR2); - wbflush(); + alpha_mb(); REGVAL(EPIC_HAXR2) = old_haxr2 | 0x1; - wbflush(); + alpha_mb(); } - datap = (pcireg_t *)phystok0seg(APECS_PCI_CONF | + datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(APECS_PCI_CONF | tag << 5UL | /* XXX */ (offset & ~0x03) << 5 | /* XXX */ 0 << 5 | /* XXX */ @@ -178,9 +180,9 @@ apecs_conf_write(cpv, tag, offset, data) *datap = data; if (secondary) { - wbflush(); + alpha_mb(); REGVAL(EPIC_HAXR2) = old_haxr2; - wbflush(); + alpha_mb(); splx(s); } diff --git a/sys/arch/alpha/pci/apecsreg.h b/sys/arch/alpha/pci/apecsreg.h index 5bf5eab8dc6..169faaf6cf1 100644 --- a/sys/arch/alpha/pci/apecsreg.h +++ b/sys/arch/alpha/pci/apecsreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: apecsreg.h,v 1.3 1996/07/29 23:00:10 niklas Exp $ */ -/* $NetBSD: apecsreg.h,v 1.3 1995/11/23 02:37:19 cgd Exp $ */ +/* $OpenBSD: apecsreg.h,v 1.4 1996/10/30 22:39:51 niklas Exp $ */ +/* $NetBSD: apecsreg.h,v 1.4 1996/07/09 00:54:34 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -35,7 +35,7 @@ * Sheet'' (DEC order number EC-QAEMA-TE), pages 4-1 - 4-27, 10-21 - 10-38. */ -#define REGVAL(r) (*(int32_t *)phystok0seg(r)) +#define REGVAL(r) (*(int32_t *)ALPHA_PHYS_TO_K0SEG(r)) /* * Base addresses diff --git a/sys/arch/alpha/pci/apecsvar.h b/sys/arch/alpha/pci/apecsvar.h index 1b9d71b799e..7028f9cb039 100644 --- a/sys/arch/alpha/pci/apecsvar.h +++ b/sys/arch/alpha/pci/apecsvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: apecsvar.h,v 1.3 1996/07/29 23:00:11 niklas Exp $ */ +/* $OpenBSD: apecsvar.h,v 1.4 1996/10/30 22:39:51 niklas Exp $ */ /* $NetBSD: apecsvar.h,v 1.3 1996/04/12 06:08:14 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/bt485reg.h b/sys/arch/alpha/pci/bt485reg.h index 4cc8f30bb1c..fcd1b16fc21 100644 --- a/sys/arch/alpha/pci/bt485reg.h +++ b/sys/arch/alpha/pci/bt485reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bt485reg.h,v 1.3 1996/07/29 23:00:13 niklas Exp $ */ +/* $OpenBSD: bt485reg.h,v 1.4 1996/10/30 22:39:52 niklas Exp $ */ /* $NetBSD: bt485reg.h,v 1.4 1996/04/12 06:08:17 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/cia.c b/sys/arch/alpha/pci/cia.c index 1b2a5dec748..8337d47c48c 100644 --- a/sys/arch/alpha/pci/cia.c +++ b/sys/arch/alpha/pci/cia.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cia.c,v 1.3 1996/07/29 23:00:15 niklas Exp $ */ -/* $NetBSD: cia.c,v 1.5.4.1 1996/06/10 00:02:39 cgd Exp $ */ +/* $OpenBSD: cia.c,v 1.4 1996/10/30 22:39:53 niklas Exp $ */ +/* $NetBSD: cia.c,v 1.11 1996/10/13 03:00:03 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -60,9 +60,7 @@ struct cfdriver cia_cd = { NULL, "cia", DV_DULL, }; -static int ciaprint __P((void *, char *pnp)); - -#define REGVAL(r) (*(int32_t *)phystok0seg(r)) +int ciaprint __P((void *, /* const */ char *pnp)); /* There can be only one. */ int ciafound; @@ -73,7 +71,6 @@ ciamatch(parent, match, aux) struct device *parent; void *match, *aux; { - struct cfdata *cf = match; struct confargs *ca = aux; /* Make sure that we're looking for a CIA. */ @@ -111,7 +108,6 @@ ciaattach(parent, self, aux) struct device *parent, *self; void *aux; { - struct confargs *ca = aux; struct cia_softc *sc = (struct cia_softc *)self; struct cia_config *ccp; struct pcibus_attach_args pba; @@ -149,10 +145,10 @@ ciaattach(parent, self, aux) config_found(self, &pba, ciaprint); } -static int +int ciaprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { register struct pcibus_attach_args *pba = aux; diff --git a/sys/arch/alpha/pci/cia_bus_io.c b/sys/arch/alpha/pci/cia_bus_io.c index 0416a519c36..75f7d27fc1e 100644 --- a/sys/arch/alpha/pci/cia_bus_io.c +++ b/sys/arch/alpha/pci/cia_bus_io.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cia_bus_io.c,v 1.2 1996/07/29 23:00:17 niklas Exp $ */ -/* $NetBSD: cia_bus_io.c,v 1.2.4.2 1996/06/13 18:14:59 cgd Exp $ */ +/* $OpenBSD: cia_bus_io.c,v 1.3 1996/10/30 22:39:54 niklas Exp $ */ +/* $NetBSD: cia_bus_io.c,v 1.5 1996/08/27 16:29:25 cgd Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/device.h> diff --git a/sys/arch/alpha/pci/cia_bus_mem.c b/sys/arch/alpha/pci/cia_bus_mem.c index 63760ad8fc2..47d83a467fc 100644 --- a/sys/arch/alpha/pci/cia_bus_mem.c +++ b/sys/arch/alpha/pci/cia_bus_mem.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cia_bus_mem.c,v 1.2 1996/07/29 23:00:19 niklas Exp $ */ -/* $NetBSD: cia_bus_mem.c,v 1.2.4.2 1996/06/13 18:15:01 cgd Exp $ */ +/* $OpenBSD: cia_bus_mem.c,v 1.3 1996/10/30 22:39:55 niklas Exp $ */ +/* $NetBSD: cia_bus_mem.c,v 1.5 1996/08/27 16:29:26 cgd Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/device.h> diff --git a/sys/arch/alpha/pci/cia_pci.c b/sys/arch/alpha/pci/cia_pci.c index 03f98709a24..ac66d48a0ea 100644 --- a/sys/arch/alpha/pci/cia_pci.c +++ b/sys/arch/alpha/pci/cia_pci.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cia_pci.c,v 1.3 1996/07/29 23:00:21 niklas Exp $ */ -/* $NetBSD: cia_pci.c,v 1.2 1996/04/12 23:37:10 cgd Exp $ */ +/* $OpenBSD: cia_pci.c,v 1.4 1996/10/30 22:39:56 niklas Exp $ */ +/* $NetBSD: cia_pci.c,v 1.5 1996/10/13 03:00:04 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -34,6 +34,8 @@ #include <sys/device.h> #include <vm/vm.h> +#include <machine/autoconf.h> /* badaddr proto */ + #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <alpha/pci/ciareg.h> @@ -119,12 +121,12 @@ cia_conf_read(cpv, tag, offset) if (secondary) { s = splhigh(); old_haxr2 = REGVAL(CIA_CSRS + 0x480); /* XXX */ - wbflush(); + alpha_mb(); REGVAL(CIA_CSRS + 0x480) = old_haxr2 | 0x1; /* XXX */ - wbflush(); + alpha_mb(); } - datap = (pcireg_t *)phystok0seg(CIA_PCI_CONF | + datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_PCI_CONF | tag << 5UL | /* XXX */ (offset & ~0x03) << 5 | /* XXX */ 0 << 5 | /* XXX */ @@ -134,9 +136,9 @@ cia_conf_read(cpv, tag, offset) data = *datap; if (secondary) { - wbflush(); + alpha_mb(); REGVAL(CIA_CSRS + 0x480) = old_haxr2; /* XXX */ - wbflush(); + alpha_mb(); splx(s); } @@ -165,12 +167,12 @@ cia_conf_write(cpv, tag, offset, data) if (secondary) { s = splhigh(); old_haxr2 = REGVAL(CIA_CSRS + 0x480); /* XXX */ - wbflush(); + alpha_mb(); REGVAL(CIA_CSRS + 0x480) = old_haxr2 | 0x1; /* XXX */ - wbflush(); + alpha_mb(); } - datap = (pcireg_t *)phystok0seg(CIA_PCI_CONF | + datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_PCI_CONF | tag << 5UL | /* XXX */ (offset & ~0x03) << 5 | /* XXX */ 0 << 5 | /* XXX */ @@ -178,9 +180,9 @@ cia_conf_write(cpv, tag, offset, data) *datap = data; if (secondary) { - wbflush(); + alpha_mb(); REGVAL(CIA_CSRS + 0x480) = old_haxr2; /* XXX */ - wbflush(); + alpha_mb(); splx(s); } diff --git a/sys/arch/alpha/pci/ciareg.h b/sys/arch/alpha/pci/ciareg.h index b3cf98b78f3..aa33bf767ae 100644 --- a/sys/arch/alpha/pci/ciareg.h +++ b/sys/arch/alpha/pci/ciareg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ciareg.h,v 1.3 1996/07/29 23:00:23 niklas Exp $ */ -/* $NetBSD: ciareg.h,v 1.1.4.3 1996/06/13 18:35:27 cgd Exp $ */ +/* $OpenBSD: ciareg.h,v 1.4 1996/10/30 22:39:57 niklas Exp $ */ +/* $NetBSD: ciareg.h,v 1.5 1996/07/09 00:54:44 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -34,7 +34,7 @@ * Taken from XXX */ -#define REGVAL(r) (*(int32_t *)phystok0seg(r)) +#define REGVAL(r) (*(int32_t *)ALPHA_PHYS_TO_K0SEG(r)) /* * Base addresses diff --git a/sys/arch/alpha/pci/ciavar.h b/sys/arch/alpha/pci/ciavar.h index 31f9b18b158..a0b5e82be37 100644 --- a/sys/arch/alpha/pci/ciavar.h +++ b/sys/arch/alpha/pci/ciavar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ciavar.h,v 1.3 1996/07/29 23:00:24 niklas Exp $ */ -/* $NetBSD: ciavar.h,v 1.3.4.1 1996/06/10 00:04:12 cgd Exp $ */ +/* $OpenBSD: ciavar.h,v 1.4 1996/10/30 22:39:58 niklas Exp $ */ +/* $NetBSD: ciavar.h,v 1.4 1996/06/10 00:03:59 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/pci/lca.c b/sys/arch/alpha/pci/lca.c index 264cab0ec6b..64994855849 100644 --- a/sys/arch/alpha/pci/lca.c +++ b/sys/arch/alpha/pci/lca.c @@ -1,5 +1,5 @@ -/* $OpenBSD: lca.c,v 1.3 1996/07/29 23:00:26 niklas Exp $ */ -/* $NetBSD: lca.c,v 1.5 1996/04/23 14:00:53 cgd Exp $ */ +/* $OpenBSD: lca.c,v 1.4 1996/10/30 22:39:59 niklas Exp $ */ +/* $NetBSD: lca.c,v 1.10 1996/10/13 03:00:07 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -45,6 +45,10 @@ #include <dev/pci/pcivar.h> #include <alpha/pci/lcareg.h> #include <alpha/pci/lcavar.h> +#include <alpha/pci/apecs_lca.h> +#if defined(DEC_AXPPCI_33) +#include <alpha/pci/pci_axppci_33.h> +#endif int lcamatch __P((struct device *, void *, void *)); void lcaattach __P((struct device *, struct device *, void *)); @@ -57,7 +61,7 @@ struct cfdriver lca_cd = { NULL, "lca", DV_DULL, }; -static int lcaprint __P((void *, char *pnp)); +int lcaprint __P((void *, /* const */ char *pnp)); /* There can be only one. */ int lcafound; @@ -68,7 +72,6 @@ lcamatch(parent, match, aux) struct device *parent; void *match, *aux; { - struct cfdata *cf = match; struct confargs *ca = aux; /* Make sure that we're looking for a LCA. */ @@ -125,7 +128,7 @@ lca_init(lcp) /* Turn off DMA window enables in Window Base Registers */ /* REGVAL(LCA_IOC_W_BASE0) = 0; REGVAL(LCA_IOC_W_BASE1) = 0; */ - wbflush(); + alpha_mb(); } #ifdef notdef @@ -139,7 +142,7 @@ lca_init_sgmap(lcp) bzero(lcp->lc_sgmap, 1024 * 8); /* clear all entries. */ REGVAL(LCA_IOC_W_BASE0) = 0; - wbflush(); + alpha_mb(); /* Set up Translated Base Register 1; translate to sybBus addr 0. */ /* check size against APEC XXX JH */ @@ -150,7 +153,7 @@ lca_init_sgmap(lcp) /* Enable window 1; from PCI address 8MB, direct mapped. */ REGVAL(LCA_IOC_W_BASE0) = 0x300800000; - wbflush(); + alpha_mb(); } #endif @@ -197,10 +200,10 @@ lcaattach(parent, self, aux) config_found(self, &pba, lcaprint); } -static int +int lcaprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { register struct pcibus_attach_args *pba = aux; diff --git a/sys/arch/alpha/pci/lca_pci.c b/sys/arch/alpha/pci/lca_pci.c index cdee66d1396..837fbec97be 100644 --- a/sys/arch/alpha/pci/lca_pci.c +++ b/sys/arch/alpha/pci/lca_pci.c @@ -1,5 +1,5 @@ -/* $OpenBSD: lca_pci.c,v 1.3 1996/07/29 23:00:28 niklas Exp $ */ -/* $NetBSD: lca_pci.c,v 1.3 1996/04/23 14:01:00 cgd Exp $ */ +/* $OpenBSD: lca_pci.c,v 1.4 1996/10/30 22:40:00 niklas Exp $ */ +/* $NetBSD: lca_pci.c,v 1.6 1996/10/13 03:00:08 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -34,6 +34,8 @@ #include <sys/device.h> #include <vm/vm.h> +#include <machine/autoconf.h> /* badaddr proto */ + #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <alpha/pci/lcareg.h> @@ -120,9 +122,9 @@ lca_conf_read(cpv, tag, offset) pci_decompose_tag(&lcp->lc_pc, tag, &secondary, &device, 0); if (secondary) { s = splhigh(); - wbflush(); + alpha_mb(); REGVAL(LCA_IOC_CONF) = 0x01; - wbflush(); + alpha_mb(); } else { /* * on the LCA, must frob the tag used for @@ -133,7 +135,7 @@ lca_conf_read(cpv, tag, offset) tag = (1 << (device + 11)) | (tag & 0x7ff); } - datap = (pcireg_t *)phystok0seg(LCA_PCI_CONF | + datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(LCA_PCI_CONF | tag << 5UL | /* XXX */ (offset & ~0x03) << 5 | /* XXX */ 0 << 5 | /* XXX */ @@ -143,9 +145,9 @@ lca_conf_read(cpv, tag, offset) data = *datap; if (secondary) { - wbflush(); + alpha_mb(); REGVAL(LCA_IOC_CONF) = 0x00; - wbflush(); + alpha_mb(); splx(s); } @@ -172,9 +174,9 @@ lca_conf_write(cpv, tag, offset, data) pci_decompose_tag(&lcp->lc_pc, tag, &secondary, &device, 0); if (secondary) { s = splhigh(); - wbflush(); + alpha_mb(); REGVAL(LCA_IOC_CONF) = 0x01; - wbflush(); + alpha_mb(); } else { /* * on the LCA, must frob the tag used for @@ -185,7 +187,7 @@ lca_conf_write(cpv, tag, offset, data) tag = (1 << (device + 11)) | (tag & 0x7ff); } - datap = (pcireg_t *)phystok0seg(LCA_PCI_CONF | + datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(LCA_PCI_CONF | tag << 5UL | /* XXX */ (offset & ~0x03) << 5 | /* XXX */ 0 << 5 | /* XXX */ @@ -193,9 +195,9 @@ lca_conf_write(cpv, tag, offset, data) *datap = data; if (secondary) { - wbflush(); + alpha_mb(); REGVAL(LCA_IOC_CONF) = 0x00; - wbflush(); + alpha_mb(); splx(s); } diff --git a/sys/arch/alpha/pci/lcareg.h b/sys/arch/alpha/pci/lcareg.h index 0542039990f..d9e9bffd448 100644 --- a/sys/arch/alpha/pci/lcareg.h +++ b/sys/arch/alpha/pci/lcareg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: lcareg.h,v 1.3 1996/07/29 23:00:30 niklas Exp $ */ -/* $NetBSD: lcareg.h,v 1.2 1996/04/23 14:03:46 cgd Exp $ */ +/* $OpenBSD: lcareg.h,v 1.4 1996/10/30 22:40:00 niklas Exp $ */ +/* $NetBSD: lcareg.h,v 1.3 1996/07/09 00:54:51 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -32,7 +32,7 @@ * 21066 chip registers */ -#define REGVAL(r) (*(int32_t *)phystok0seg(r)) +#define REGVAL(r) (*(int32_t *)ALPHA_PHYS_TO_K0SEG(r)) /* * Base addresses diff --git a/sys/arch/alpha/pci/lcavar.h b/sys/arch/alpha/pci/lcavar.h index 7ebd8e751a9..25762783af6 100644 --- a/sys/arch/alpha/pci/lcavar.h +++ b/sys/arch/alpha/pci/lcavar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: lcavar.h,v 1.3 1996/07/29 23:00:32 niklas Exp $ */ +/* $OpenBSD: lcavar.h,v 1.4 1996/10/30 22:40:02 niklas Exp $ */ /* $NetBSD: lcavar.h,v 1.3 1996/04/12 06:08:35 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/pci_2100_a50.c b/sys/arch/alpha/pci/pci_2100_a50.c index d396695ef09..1fa315bd8ae 100644 --- a/sys/arch/alpha/pci/pci_2100_a50.c +++ b/sys/arch/alpha/pci/pci_2100_a50.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pci_2100_a50.c,v 1.6 1996/07/29 23:00:34 niklas Exp $ */ -/* $NetBSD: pci_2100_a50.c,v 1.7 1996/04/23 14:15:55 cgd Exp $ */ +/* $OpenBSD: pci_2100_a50.c,v 1.7 1996/10/30 22:40:03 niklas Exp $ */ +/* $NetBSD: pci_2100_a50.c,v 1.10 1996/10/13 03:00:09 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -36,6 +36,7 @@ #include <sys/device.h> #include <vm/vm.h> +#include <machine/autoconf.h> #include <machine/bus.h> #include <machine/intr.h> @@ -191,8 +192,6 @@ dec_2100_a50_intr_string(acv, ih) void *acv; pci_intr_handle_t ih; { - struct apecs_config *acp = acv; - return sio_intr_string(NULL /*XXX*/, ih); } @@ -204,8 +203,6 @@ dec_2100_a50_intr_establish(acv, ih, level, func, arg, name) int (*func) __P((void *)); char *name; { - struct apecs_config *acp = acv; - return sio_intr_establish(NULL /*XXX*/, ih, IST_LEVEL, level, func, arg, name); } @@ -214,7 +211,5 @@ void dec_2100_a50_intr_disestablish(acv, cookie) void *acv, *cookie; { - struct apecs_config *acp = acv; - sio_intr_disestablish(NULL /*XXX*/, cookie); } diff --git a/sys/arch/alpha/pci/pci_2100_a50.h b/sys/arch/alpha/pci/pci_2100_a50.h index 48f02de1d39..adee2d737cb 100644 --- a/sys/arch/alpha/pci/pci_2100_a50.h +++ b/sys/arch/alpha/pci/pci_2100_a50.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_2100_a50.h,v 1.3 1996/07/29 23:00:35 niklas Exp $ */ +/* $OpenBSD: pci_2100_a50.h,v 1.4 1996/10/30 22:40:04 niklas Exp $ */ /* $NetBSD: pci_2100_a50.h,v 1.3 1996/04/12 06:08:42 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/pci_axppci_33.c b/sys/arch/alpha/pci/pci_axppci_33.c index 7c70243290c..2cf58634136 100644 --- a/sys/arch/alpha/pci/pci_axppci_33.c +++ b/sys/arch/alpha/pci/pci_axppci_33.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pci_axppci_33.c,v 1.5 1996/07/29 23:00:37 niklas Exp $ */ -/* $NetBSD: pci_axppci_33.c,v 1.5 1996/04/23 14:15:28 cgd Exp $ */ +/* $OpenBSD: pci_axppci_33.c,v 1.6 1996/10/30 22:40:05 niklas Exp $ */ +/* $NetBSD: pci_axppci_33.c,v 1.8 1996/10/13 03:00:11 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -36,6 +36,7 @@ #include <sys/device.h> #include <vm/vm.h> +#include <machine/autoconf.h> #include <machine/bus.h> #include <machine/intr.h> @@ -195,8 +196,6 @@ dec_axppci_33_intr_string(lcv, ih) void *lcv; pci_intr_handle_t ih; { - struct lca_config *lcp = lcv; - return sio_intr_string(NULL /*XXX*/, ih); } @@ -208,8 +207,6 @@ dec_axppci_33_intr_establish(lcv, ih, level, func, arg, name) int (*func) __P((void *)); char *name; { - struct lca_config *lcp = lcv; - return sio_intr_establish(NULL /*XXX*/, ih, IST_LEVEL, level, func, arg, name); } @@ -218,7 +215,5 @@ void dec_axppci_33_intr_disestablish(lcv, cookie) void *lcv, *cookie; { - struct lca_config *lcp = lcv; - sio_intr_disestablish(NULL /*XXX*/, cookie); } diff --git a/sys/arch/alpha/pci/pci_axppci_33.h b/sys/arch/alpha/pci/pci_axppci_33.h index 9f669510798..ef9a3856111 100644 --- a/sys/arch/alpha/pci/pci_axppci_33.h +++ b/sys/arch/alpha/pci/pci_axppci_33.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_axppci_33.h,v 1.3 1996/07/29 23:00:39 niklas Exp $ */ +/* $OpenBSD: pci_axppci_33.h,v 1.4 1996/10/30 22:40:05 niklas Exp $ */ /* $NetBSD: pci_axppci_33.h,v 1.3 1996/04/12 06:08:47 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/pci_kn20aa.c b/sys/arch/alpha/pci/pci_kn20aa.c index 179d7c56b1b..1106261c1cf 100644 --- a/sys/arch/alpha/pci/pci_kn20aa.c +++ b/sys/arch/alpha/pci/pci_kn20aa.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pci_kn20aa.c,v 1.6 1996/10/04 03:06:04 deraadt Exp $ */ -/* $NetBSD: pci_kn20aa.c,v 1.3.4.2 1996/06/13 18:35:31 cgd Exp $ */ +/* $OpenBSD: pci_kn20aa.c,v 1.7 1996/10/30 22:40:06 niklas Exp $ */ +/* $NetBSD: pci_kn20aa.c,v 1.18 1996/10/13 03:00:12 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -39,6 +39,8 @@ #include <vm/vm.h> +#include <machine/autoconf.h> + #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -69,7 +71,7 @@ void dec_kn20aa_intr_disestablish __P((void *, void *)); struct kn20aa_intrhand { TAILQ_ENTRY(kn20aa_intrhand) ih_q; - int (*ih_fun)(); + int (*ih_fun) __P((void *)); void *ih_arg; u_long ih_count; int ih_level; @@ -83,7 +85,7 @@ struct evcnt kn20aa_intr_evcnt; #endif void kn20aa_pci_strayintr __P((int irq)); -void kn20aa_iointr __P((void *framep, int vec)); +void kn20aa_iointr __P((void *framep, unsigned long vec)); void kn20aa_enable_intr __P((int irq)); void kn20aa_disable_intr __P((int irq)); struct kn20aa_intrhand *kn20aa_attach_intr __P((struct kn20aa_intrchain *, @@ -94,7 +96,6 @@ pci_kn20aa_pickintr(ccp) struct cia_config *ccp; { int i; - struct kn20aa_intrhand *nintrhand; bus_chipset_tag_t bc = &ccp->cc_bc; pci_chipset_tag_t pc = &ccp->cc_pc; @@ -132,7 +133,6 @@ dec_kn20aa_intr_map(ccv, bustag, buspin, line, ihp) pci_chipset_tag_t pc = &ccp->cc_pc; int device; int kn20aa_irq; - void *ih; if (buspin == 0) { /* No IRQ used. */ @@ -174,6 +174,12 @@ dec_kn20aa_intr_map(ccv, bustag, buspin, line, ihp) break; default: +#ifdef KN20AA_BOGUS_IRQ_FROB + *ihp = 0xdeadbeef; + printf("\n\n BOGUS INTERRUPT MAPPING: dev %d, pin %d\n", + device, buspin); + return (0); +#endif panic("pci_kn20aa_map_int: invalid device number %d\n", device); } @@ -192,9 +198,14 @@ dec_kn20aa_intr_string(ccv, ih) void *ccv; pci_intr_handle_t ih; { - struct cia_config *ccp = ccv; static char irqstr[15]; /* 11 + 2 + NULL + sanity */ +#ifdef KN20AA_BOGUS_IRQ_FROB + if (ih == 0xdeadbeef) { + sprintf(irqstr, "BOGUS"); + return (irqstr); + } +#endif if (ih > KN20AA_MAX_IRQ) panic("dec_kn20aa_a50_intr_string: bogus kn20aa IRQ 0x%x\n", ih); @@ -211,9 +222,24 @@ dec_kn20aa_intr_establish(ccv, ih, level, func, arg, name) int (*func) __P((void *)); char *name; { - struct cia_config *ccp = ccv; void *cookie; +#ifdef KN20AA_BOGUS_IRQ_FROB + if (ih == 0xdeadbeef) { + int i; + char chars[10]; + + printf("dec_kn20aa_intr_establish: BOGUS IRQ\n"); + do { + printf("IRQ to enable? "); + getstr(chars, 10); + i = atoi(chars); + } while (i < 0 || i > 32); + printf("ENABLING IRQ %d\n", i); + kn20aa_enable_intr(i); + return ((void *)0xbabefacedeadbeef); + } +#endif if (ih > KN20AA_MAX_IRQ) panic("dec_kn20aa_intr_establish: bogus kn20aa IRQ 0x%x\n", ih); @@ -227,8 +253,6 @@ void dec_kn20aa_intr_disestablish(ccv, cookie) void *ccv, *cookie; { - struct cia_config *ccp = ccv; - panic("dec_kn20aa_intr_disestablish not implemented"); /* XXX */ } @@ -252,7 +276,7 @@ kn20aa_pci_strayintr(irq) void kn20aa_iointr(framep, vec) void *framep; - int vec; + unsigned long vec; { struct kn20aa_intrhand *ih; int irq, handled; @@ -303,9 +327,9 @@ kn20aa_enable_intr(irq) * "blech." I'd give valuable body parts for better docs or * for a good decompiler. */ - wbflush(); + alpha_mb(); REGVAL(0x8780000000L + 0x40L) |= (1 << irq); /* XXX */ - wbflush(); + alpha_mb(); } void @@ -313,9 +337,9 @@ kn20aa_disable_intr(irq) int irq; { - wbflush(); + alpha_mb(); REGVAL(0x8780000000L + 0x40L) &= ~(1 << irq); /* XXX */ - wbflush(); + alpha_mb(); } struct kn20aa_intrhand * diff --git a/sys/arch/alpha/pci/pci_kn20aa.h b/sys/arch/alpha/pci/pci_kn20aa.h index beaa93248a4..f4abae0c91a 100644 --- a/sys/arch/alpha/pci/pci_kn20aa.h +++ b/sys/arch/alpha/pci/pci_kn20aa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_kn20aa.h,v 1.3 1996/07/29 23:00:42 niklas Exp $ */ +/* $OpenBSD: pci_kn20aa.h,v 1.4 1996/10/30 22:40:07 niklas Exp $ */ /* $NetBSD: pci_kn20aa.h,v 1.2 1996/04/13 00:24:35 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/pci_machdep.c b/sys/arch/alpha/pci/pci_machdep.c index bc163c277f0..7e6573e0fbb 100644 --- a/sys/arch/alpha/pci/pci_machdep.c +++ b/sys/arch/alpha/pci/pci_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_machdep.c,v 1.4 1996/07/29 23:00:43 niklas Exp $ */ +/* $OpenBSD: pci_machdep.c,v 1.5 1996/10/30 22:40:08 niklas Exp $ */ /* $NetBSD: pci_machdep.c,v 1.5 1996/04/12 06:08:49 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/pci_machdep.h b/sys/arch/alpha/pci/pci_machdep.h index 3dd29d4c87c..928a78f09a5 100644 --- a/sys/arch/alpha/pci/pci_machdep.h +++ b/sys/arch/alpha/pci/pci_machdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_machdep.h,v 1.4 1996/07/29 23:00:45 niklas Exp $ */ +/* $OpenBSD: pci_machdep.h,v 1.5 1996/10/30 22:40:09 niklas Exp $ */ /* $NetBSD: pci_machdep.h,v 1.4 1996/04/12 06:08:52 cgd Exp $ */ /* @@ -86,3 +86,8 @@ struct alpha_pci_chipset { (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (h), (a), (nm)) #define pci_intr_disestablish(c, iv) \ (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv)) + +#ifdef _KERNEL +void pci_display_console + __P((bus_chipset_tag_t, pci_chipset_tag_t, int, int, int)); +#endif /* _KERNEL */ diff --git a/sys/arch/alpha/pci/pcivga.c b/sys/arch/alpha/pci/pcivga.c index 68b5f2d4814..1cbcabde789 100644 --- a/sys/arch/alpha/pci/pcivga.c +++ b/sys/arch/alpha/pci/pcivga.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pcivga.c,v 1.6 1996/07/29 23:00:46 niklas Exp $ */ -/* $NetBSD: pcivga.c,v 1.8 1996/04/17 21:49:58 cgd Exp $ */ +/* $OpenBSD: pcivga.c,v 1.7 1996/10/30 22:40:10 niklas Exp $ */ +/* $NetBSD: pcivga.c,v 1.11 1996/10/13 03:00:13 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -49,7 +49,7 @@ int pcivgamatch __P((struct device *, void *, void *)); void pcivgaattach __P((struct device *, struct device *, void *)); -int pcivgaprint __P((void *, char *)); +int pcivgaprint __P((void *, /* const */ char *)); struct cfattach pcivga_ca = { sizeof(struct pcivga_softc), pcivgamatch, pcivgaattach, @@ -89,7 +89,6 @@ pcivgamatch(parent, match, aux) struct device *parent; void *match, *aux; { - struct cfdata *cf = match; struct pci_attach_args *pa = aux; /* @@ -222,7 +221,7 @@ pcivgaattach(parent, self, aux) int pcivgaprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { if (pnp) @@ -248,7 +247,9 @@ pcivgammap(dev, offset, prot) off_t offset; int prot; { +#if 0 struct pcivga_softc *sc = (struct pcivga_softc *)dev; +#endif int rv; rv = -1; @@ -335,7 +336,6 @@ pcivga_putstr(id, row, col, cp, len) struct pcivga_devconfig *dc = id; bus_chipset_tag_t bc = dc->dc_bc; bus_mem_handle_t memh = dc->dc_memh; - char *dcp; int i, off; off = (row * dc->dc_ncol + col) * 2; diff --git a/sys/arch/alpha/pci/pcivgavar.h b/sys/arch/alpha/pci/pcivgavar.h index f306534cf91..c8a947a98dd 100644 --- a/sys/arch/alpha/pci/pcivgavar.h +++ b/sys/arch/alpha/pci/pcivgavar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcivgavar.h,v 1.4 1996/07/29 23:00:48 niklas Exp $ */ +/* $OpenBSD: pcivgavar.h,v 1.5 1996/10/30 22:40:11 niklas Exp $ */ /* $NetBSD: pcivgavar.h,v 1.5 1996/04/12 06:08:58 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/pcs_bus_io_common.c b/sys/arch/alpha/pci/pcs_bus_io_common.c index 8c995d30915..59626ded968 100644 --- a/sys/arch/alpha/pci/pcs_bus_io_common.c +++ b/sys/arch/alpha/pci/pcs_bus_io_common.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pcs_bus_io_common.c,v 1.2 1996/07/29 23:00:50 niklas Exp $ */ -/* $NetBSD: pcs_bus_io_common.c,v 1.2.4.2 1996/06/13 18:16:59 cgd Exp $ */ +/* $OpenBSD: pcs_bus_io_common.c,v 1.3 1996/10/30 22:40:12 niklas Exp $ */ +/* $NetBSD: pcs_bus_io_common.c,v 1.8 1996/10/13 03:00:15 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -123,14 +123,14 @@ __C(CHIP,_io_map)(v, ioaddr, iosize, iohp) #ifdef CHIP_IO_W1_START if (ioaddr >= CHIP_IO_W1_START(v) && ioaddr <= CHIP_IO_W1_END(v)) { - *iohp = (phystok0seg(CHIP_IO_W1_BASE(v)) >> 5) + + *iohp = (ALPHA_PHYS_TO_K0SEG(CHIP_IO_W1_BASE(v)) >> 5) + (ioaddr & CHIP_IO_W1_MASK(v)); } else #endif #ifdef CHIP_IO_W2_START if (ioaddr >= CHIP_IO_W2_START(v) && ioaddr <= CHIP_IO_W2_END(v)) { - *iohp = (phystok0seg(CHIP_IO_W2_BASE(v)) >> 5) + + *iohp = (ALPHA_PHYS_TO_K0SEG(CHIP_IO_W2_BASE(v)) >> 5) + (ioaddr & CHIP_IO_W2_MASK(v)); } else #endif @@ -185,7 +185,7 @@ __C(CHIP,_io_read_1)(v, ioh, off) register u_int8_t rval; register int offset; - wbflush(); + alpha_mb(); tmpioh = ioh + off; offset = tmpioh & 3; @@ -207,7 +207,7 @@ __C(CHIP,_io_read_2)(v, ioh, off) register u_int16_t rval; register int offset; - wbflush(); + alpha_mb(); tmpioh = ioh + off; offset = tmpioh & 3; @@ -229,7 +229,7 @@ __C(CHIP,_io_read_4)(v, ioh, off) register u_int32_t rval; register int offset; - wbflush(); + alpha_mb(); tmpioh = ioh + off; offset = tmpioh & 3; @@ -266,7 +266,7 @@ __C(CHIP,_io_read_multi_1)(v, ioh, off, addr, count) register u_int32_t *port, val; register int offset; - wbflush(); + alpha_mb(); while (count--) { tmpioh = ioh + off; @@ -289,7 +289,7 @@ __C(CHIP,_io_read_multi_2)(v, ioh, off, addr, count) register u_int32_t *port, val; register int offset; - wbflush(); + alpha_mb(); while (count--) { tmpioh = ioh + off; @@ -312,7 +312,7 @@ __C(CHIP,_io_read_multi_4)(v, ioh, off, addr, count) register u_int32_t *port, val; register int offset; - wbflush(); + alpha_mb(); while (count--) { tmpioh = ioh + off; @@ -356,7 +356,7 @@ __C(CHIP,_io_write_1)(v, ioh, off, val) nval = val << (8 * offset); port = (u_int32_t *)((tmpioh << 5) | (0 << 3)); *port = nval; - wbflush(); + alpha_mb(); } void @@ -375,7 +375,7 @@ __C(CHIP,_io_write_2)(v, ioh, off, val) nval = val << (8 * offset); port = (u_int32_t *)((tmpioh << 5) | (1 << 3)); *port = nval; - wbflush(); + alpha_mb(); } void @@ -394,7 +394,7 @@ __C(CHIP,_io_write_4)(v, ioh, off, val) nval = val /*<< (8 * offset)*/; port = (u_int32_t *)((tmpioh << 5) | (3 << 3)); *port = nval; - wbflush(); + alpha_mb(); } void @@ -407,7 +407,7 @@ __C(CHIP,_io_write_8)(v, ioh, off, val) /* XXX XXX XXX */ panic("%s not implemented\n", __S(__C(CHIP,_io_write_8))); - wbflush(); + alpha_mb(); } void @@ -429,7 +429,7 @@ __C(CHIP,_io_write_multi_1)(v, ioh, off, addr, count) *port = nval; off++; } - wbflush(); + alpha_mb(); } void @@ -451,7 +451,7 @@ __C(CHIP,_io_write_multi_2)(v, ioh, off, addr, count) *port = nval; off++; } - wbflush(); + alpha_mb(); } void @@ -473,7 +473,7 @@ __C(CHIP,_io_write_multi_4)(v, ioh, off, addr, count) *port = nval; off++; } - wbflush(); + alpha_mb(); } void diff --git a/sys/arch/alpha/pci/pcs_bus_mem_common.c b/sys/arch/alpha/pci/pcs_bus_mem_common.c index 79833a1f9da..3eb14c01f0c 100644 --- a/sys/arch/alpha/pci/pcs_bus_mem_common.c +++ b/sys/arch/alpha/pci/pcs_bus_mem_common.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pcs_bus_mem_common.c,v 1.2 1996/07/29 23:00:51 niklas Exp $ */ -/* $NetBSD: pcs_bus_mem_common.c,v 1.1.4.4 1996/06/13 18:17:01 cgd Exp $ */ +/* $OpenBSD: pcs_bus_mem_common.c,v 1.3 1996/10/30 22:40:13 niklas Exp $ */ +/* $NetBSD: pcs_bus_mem_common.c,v 1.9 1996/10/13 03:00:17 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -106,7 +106,7 @@ __C(CHIP,_mem_map)(v, memaddr, memsize, cacheable, memhp) #ifdef CHIP_D_MEM_W1_START if (memaddr >= CHIP_D_MEM_W1_START(v) && memaddr <= CHIP_D_MEM_W1_END(v)) { - *memhp = phystok0seg(CHIP_D_MEM_W1_BASE(v)) + + *memhp = ALPHA_PHYS_TO_K0SEG(CHIP_D_MEM_W1_BASE(v)) + (memaddr & CHIP_D_MEM_W1_MASK(v)); } else #endif @@ -124,21 +124,21 @@ __C(CHIP,_mem_map)(v, memaddr, memsize, cacheable, memhp) #ifdef CHIP_S_MEM_W1_START if (memaddr >= CHIP_S_MEM_W1_START(v) && memaddr <= CHIP_S_MEM_W1_END(v)) { - *memhp = (phystok0seg(CHIP_S_MEM_W1_BASE(v)) >> 5) + + *memhp = (ALPHA_PHYS_TO_K0SEG(CHIP_S_MEM_W1_BASE(v)) >> 5) + (memaddr & CHIP_S_MEM_W1_MASK(v)); } else #endif #ifdef CHIP_S_MEM_W2_START if (memaddr >= CHIP_S_MEM_W2_START(v) && memaddr <= CHIP_S_MEM_W2_END(v)) { - *memhp = (phystok0seg(CHIP_S_MEM_W2_BASE(v)) >> 5) + + *memhp = (ALPHA_PHYS_TO_K0SEG(CHIP_S_MEM_W2_BASE(v)) >> 5) + (memaddr & CHIP_S_MEM_W2_MASK(v)); } else #endif #ifdef CHIP_S_MEM_W3_START if (memaddr >= CHIP_S_MEM_W3_START(v) && memaddr <= CHIP_S_MEM_W3_END(v)) { - *memhp = (phystok0seg(CHIP_S_MEM_W3_BASE(v)) >> 5) + + *memhp = (ALPHA_PHYS_TO_K0SEG(CHIP_S_MEM_W3_BASE(v)) >> 5) + (memaddr & CHIP_S_MEM_W3_MASK(v)); } else #endif @@ -199,7 +199,7 @@ __C(CHIP,_mem_read_1)(v, memh, off) register u_int8_t rval; register int offset; - wbflush(); + alpha_mb(); if ((memh >> 63) != 0) return (*(u_int8_t *)(memh + off)); @@ -224,7 +224,7 @@ __C(CHIP,_mem_read_2)(v, memh, off) register u_int16_t rval; register int offset; - wbflush(); + alpha_mb(); if ((memh >> 63) != 0) return (*(u_int16_t *)(memh + off)); @@ -249,7 +249,7 @@ __C(CHIP,_mem_read_4)(v, memh, off) register u_int32_t rval; register int offset; - wbflush(); + alpha_mb(); if ((memh >> 63) != 0) return (*(u_int32_t *)(memh + off)); @@ -274,7 +274,7 @@ __C(CHIP,_mem_read_8)(v, memh, off) bus_mem_size_t off; { - wbflush(); + alpha_mb(); if ((memh >> 63) != 0) return (*(u_int64_t *)(memh + off)); @@ -303,7 +303,7 @@ __C(CHIP,_mem_write_1)(v, memh, off, val) port = (u_int32_t *)((tmpmemh << 5) | (0 << 3)); *port = nval; } - wbflush(); + alpha_mb(); } void @@ -326,7 +326,7 @@ __C(CHIP,_mem_write_2)(v, memh, off, val) port = (u_int32_t *)((tmpmemh << 5) | (1 << 3)); *port = nval; } - wbflush(); + alpha_mb(); } void @@ -349,7 +349,7 @@ __C(CHIP,_mem_write_4)(v, memh, off, val) port = (u_int32_t *)((tmpmemh << 5) | (3 << 3)); *port = nval; } - wbflush(); + alpha_mb(); } void @@ -367,7 +367,7 @@ __C(CHIP,_mem_write_8)(v, memh, off, val) panic("%s not implemented\n", __S(__C(CHIP,_mem_write_8))); } - wbflush(); + alpha_mb(); } vm_offset_t @@ -375,5 +375,5 @@ __C(CHIP,_XXX_dmamap)(addr) void *addr; { - return (vtophys(addr) | 0x40000000); + return (vtophys((vm_offset_t)addr) | 0x40000000); } diff --git a/sys/arch/alpha/pci/sio.c b/sys/arch/alpha/pci/sio.c index 6a4e6901fd2..0923402ac7f 100644 --- a/sys/arch/alpha/pci/sio.c +++ b/sys/arch/alpha/pci/sio.c @@ -1,5 +1,5 @@ -/* $OpenBSD: sio.c,v 1.4 1996/07/29 23:00:53 niklas Exp $ */ -/* $NetBSD: sio.c,v 1.8 1996/04/13 00:23:34 cgd Exp $ */ +/* $OpenBSD: sio.c,v 1.5 1996/10/30 22:40:14 niklas Exp $ */ +/* $NetBSD: sio.c,v 1.11 1996/10/13 03:00:18 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -72,7 +72,7 @@ union sio_attach_args { struct eisabus_attach_args sa_eba; }; -int sioprint __P((void *, char *pnp)); +int sioprint __P((void *, /* const */ char *pnp)); void sio_isa_attach_hook __P((struct device *, struct device *, struct isabus_attach_args *)); void sio_eisa_attach_hook __P((struct device *, struct device *, @@ -85,7 +85,6 @@ siomatch(parent, match, aux) struct device *parent; void *match, *aux; { - struct cfdata *cf = match; struct pci_attach_args *pa = aux; if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || @@ -100,7 +99,6 @@ pcebmatch(parent, match, aux) struct device *parent; void *match, *aux; { - struct cfdata *cf = match; struct pci_attach_args *pa = aux; if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || @@ -172,7 +170,7 @@ sioattach(parent, self, aux) int sioprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { register union sio_attach_args *sa = aux; diff --git a/sys/arch/alpha/pci/sio_pic.c b/sys/arch/alpha/pci/sio_pic.c index 585c14edab6..0a6952ea2a3 100644 --- a/sys/arch/alpha/pci/sio_pic.c +++ b/sys/arch/alpha/pci/sio_pic.c @@ -1,5 +1,5 @@ -/* $OpenBSD: sio_pic.c,v 1.5 1996/07/29 23:00:55 niklas Exp $ */ -/* $NetBSD: sio_pic.c,v 1.7.4.3 1996/06/05 22:50:23 cgd Exp $ */ +/* $OpenBSD: sio_pic.c,v 1.6 1996/10/30 22:40:15 niklas Exp $ */ +/* $NetBSD: sio_pic.c,v 1.13 1996/10/13 03:00:20 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -70,7 +70,7 @@ bus_io_handle_t sio_ioh_icu1, sio_ioh_icu2, sio_ioh_elcr; * the list. The handler is called with its (single) argument. */ struct intrhand { - int (*ih_fun)(); + int (*ih_fun) __P((void *)); void *ih_arg; u_long ih_count; struct intrhand *ih_next; @@ -115,6 +115,8 @@ u_int8_t initial_elcr[2]; #define INITIALLY_LEVEL_TRIGGERED(irq) 0 #endif +void sio_setirqstat __P((int, int, int)); + void sio_setirqstat(irq, enabled, type) int irq, enabled; @@ -358,16 +360,27 @@ sio_strayintr(irq) int irq; { - if (++sio_strayintrcnt[irq] <= STRAY_MAX) - log(LOG_ERR, "stray interrupt %d%s\n", irq, + sio_strayintrcnt[irq]++; + +#ifdef notyet + if (sio_strayintrcnt[irq] == STRAY_MAX) + sio_disable_intr(irq); + + log(LOG_ERR, "stray isa irq %d\n", irq); + if (sio_strayintrcnt[irq] == STRAY_MAX) + log(LOG_ERR, "disabling interrupts on isa irq %d\n", irq); +#else + if (sio_strayintrcnt[irq] <= STRAY_MAX) + log(LOG_ERR, "stray isa irq %d%s\n", irq, sio_strayintrcnt[irq] >= STRAY_MAX ? "; stopped logging" : ""); +#endif } void sio_iointr(framep, vec) void *framep; - int vec; + unsigned long vec; { int irq, handled; struct intrhand *ih; diff --git a/sys/arch/alpha/pci/sioreg.h b/sys/arch/alpha/pci/sioreg.h index c678b3b6f76..277a60dcdac 100644 --- a/sys/arch/alpha/pci/sioreg.h +++ b/sys/arch/alpha/pci/sioreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sioreg.h,v 1.2 1996/07/29 23:00:57 niklas Exp $ */ +/* $OpenBSD: sioreg.h,v 1.3 1996/10/30 22:40:16 niklas Exp $ */ /* $NetBSD: sioreg.h,v 1.1 1996/04/23 14:10:53 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/siovar.h b/sys/arch/alpha/pci/siovar.h index 0537724dc0c..288341d293a 100644 --- a/sys/arch/alpha/pci/siovar.h +++ b/sys/arch/alpha/pci/siovar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: siovar.h,v 1.3 1996/07/29 23:00:58 niklas Exp $ */ -/* $NetBSD: siovar.h,v 1.3 1996/04/12 06:09:06 cgd Exp $ */ +/* $OpenBSD: siovar.h,v 1.4 1996/10/30 22:40:17 niklas Exp $ */ +/* $NetBSD: siovar.h,v 1.4 1996/07/14 04:08:42 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -29,7 +29,7 @@ */ void sio_intr_setup __P((bus_chipset_tag_t)); -void sio_iointr __P((void *framep, int vec)); +void sio_iointr __P((void *framep, unsigned long vec)); const char *sio_intr_string __P((void *, int)); void *sio_intr_establish __P((void *, int, int, int, int (*)(void *), diff --git a/sys/arch/alpha/pci/tga.c b/sys/arch/alpha/pci/tga.c index e70ddbab10d..7f5b1a12560 100644 --- a/sys/arch/alpha/pci/tga.c +++ b/sys/arch/alpha/pci/tga.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tga.c,v 1.4 1996/07/29 23:01:00 niklas Exp $ */ -/* $NetBSD: tga.c,v 1.6 1996/04/12 06:09:08 cgd Exp $ */ +/* $OpenBSD: tga.c,v 1.5 1996/10/30 22:40:19 niklas Exp $ */ +/* $NetBSD: tga.c,v 1.10 1996/10/13 03:00:22 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -57,7 +57,7 @@ int tgamatch __P((struct device *, void *, void *)); void tgaattach __P((struct device *, struct device *, void *)); -int tgaprint __P((void *, char *)); +int tgaprint __P((void *, /* const */ char *)); struct cfattach tga_ca = { sizeof(struct tga_softc), tgamatch, tgaattach, @@ -94,7 +94,6 @@ tgamatch(parent, match, aux) struct device *parent; void *match, *aux; { - struct cfdata *cf = match; struct pci_attach_args *pa = aux; if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_DEC || @@ -132,7 +131,7 @@ tga_getdevconfig(bc, pc, tag, dc) /* XXX XXX XXX */ if (bus_mem_map(bc, dc->dc_pcipaddr, pcisize, 1, &dc->dc_vaddr)) return; - dc->dc_paddr = k0segtophys(dc->dc_vaddr); /* XXX */ + dc->dc_paddr = ALPHA_K0SEG_TO_PHYS(dc->dc_vaddr); /* XXX */ dc->dc_regs = (tga_reg_t *)(dc->dc_vaddr + TGA_MEM_CREGS); dc->dc_tga_type = tga_identify(dc->dc_regs); @@ -242,6 +241,7 @@ tgaattach(parent, self, aux) } /* XXX say what's going on. */ + intrstr = NULL; if (sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_intr != NULL) { if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, pa->pa_intrline, &intrh)) { @@ -312,7 +312,7 @@ tgaattach(parent, self, aux) int tgaprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { if (pnp) @@ -465,7 +465,10 @@ tga_builtin_set_cursor(dc, fbc) struct tga_devconfig *dc; struct fbcursor *fbc; { - int v, count; + int v; +#if 0 + int count; +#endif v = fbc->set; #if 0 @@ -544,6 +547,7 @@ tga_builtin_set_curpos(dc, fbp) dc->dc_regs[TGA_REG_CXYR] = ((fbp->y & 0xfff) << 12) | (fbp->x & 0xfff); + return (0); } int @@ -554,6 +558,7 @@ tga_builtin_get_curpos(dc, fbp) fbp->x = dc->dc_regs[TGA_REG_CXYR] & 0xfff; fbp->y = (dc->dc_regs[TGA_REG_CXYR] >> 12) & 0xfff; + return (0); } int @@ -563,4 +568,5 @@ tga_builtin_get_curmax(dc, fbp) { fbp->x = fbp->y = 64; + return (0); } diff --git a/sys/arch/alpha/pci/tga_bt463.c b/sys/arch/alpha/pci/tga_bt463.c index 54ecdf8087a..b628a0ead93 100644 --- a/sys/arch/alpha/pci/tga_bt463.c +++ b/sys/arch/alpha/pci/tga_bt463.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tga_bt463.c,v 1.2 1996/07/29 23:01:02 niklas Exp $ */ +/* $OpenBSD: tga_bt463.c,v 1.3 1996/10/30 22:40:19 niklas Exp $ */ /* $NetBSD: tga_bt463.c,v 1.2 1996/04/12 06:09:13 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/tga_bt485.c b/sys/arch/alpha/pci/tga_bt485.c index 11e9d46e9c3..cefd7d05ed1 100644 --- a/sys/arch/alpha/pci/tga_bt485.c +++ b/sys/arch/alpha/pci/tga_bt485.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tga_bt485.c,v 1.2 1996/07/29 23:01:04 niklas Exp $ */ -/* $NetBSD: tga_bt485.c,v 1.2 1996/04/12 06:09:16 cgd Exp $ */ +/* $OpenBSD: tga_bt485.c,v 1.3 1996/10/30 22:40:21 niklas Exp $ */ +/* $NetBSD: tga_bt485.c,v 1.3 1996/07/09 00:55:05 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -33,6 +33,9 @@ #include <sys/buf.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/systm.h> +#include <vm/vm.h> +#include <vm/vm_extern.h> #include <dev/pci/pcivar.h> #include <machine/tgareg.h> @@ -199,7 +202,7 @@ tga_bt485_set_cmap(dc, fbc) struct fbcmap *fbc; { struct bt485data *data = dc->dc_ramdac_private; - int error, count, index, s; + int count, index, s; if ((u_int)fbc->index >= 256 || ((u_int)fbc->index + (u_int)fbc->count) > 256) @@ -256,7 +259,7 @@ tga_bt485_set_cursor(dc, fbc) struct fbcursor *fbc; { struct bt485data *data = dc->dc_ramdac_private; - int error, count, index, v, s; + int count, index, v, s; v = fbc->set; @@ -398,8 +401,6 @@ tga_bt485_get_curmax(dc, fbp) struct tga_devconfig *dc; struct fbcurpos *fbp; { - struct bt485data *data = dc->dc_ramdac_private; - fbp->x = fbp->y = CURSOR_MAX_SIZE; return (0); } @@ -434,7 +435,7 @@ tga_bt485_wr_d(tgaregs, btreg, val) panic("tga_bt485_wr_d: reg %d out of range\n", btreg); tgaregs[TGA_REG_EPDR] = (btreg << 9) | (0 << 8 ) | val; /* XXX */ - wbflush(); + alpha_mb(); } inline u_int8_t @@ -448,7 +449,7 @@ tga_bt485_rd_d(tgaregs, btreg) panic("tga_bt485_rd_d: reg %d out of range\n", btreg); tgaregs[TGA_REG_EPSR] = (btreg << 1) | 0x1; /* XXX */ - wbflush(); + alpha_mb(); rdval = tgaregs[TGA_REG_EPDR]; return (rdval >> 16) & 0xff; /* XXX */ diff --git a/sys/arch/alpha/pci/tga_conf.c b/sys/arch/alpha/pci/tga_conf.c index abc1fd1b86a..73a65a85a23 100644 --- a/sys/arch/alpha/pci/tga_conf.c +++ b/sys/arch/alpha/pci/tga_conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tga_conf.c,v 1.2 1996/07/29 23:01:05 niklas Exp $ */ +/* $OpenBSD: tga_conf.c,v 1.3 1996/10/30 22:40:22 niklas Exp $ */ /* $NetBSD: tga_conf.c,v 1.2 1996/04/12 06:09:18 cgd Exp $ */ /* diff --git a/sys/arch/alpha/pci/tgavar.h b/sys/arch/alpha/pci/tgavar.h index 2b01f701f92..9b833436a97 100644 --- a/sys/arch/alpha/pci/tgavar.h +++ b/sys/arch/alpha/pci/tgavar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tgavar.h,v 1.4 1996/07/29 23:01:07 niklas Exp $ */ +/* $OpenBSD: tgavar.h,v 1.5 1996/10/30 22:40:22 niklas Exp $ */ /* $NetBSD: tgavar.h,v 1.5 1996/04/12 06:09:21 cgd Exp $ */ /* diff --git a/sys/arch/alpha/stand/Makefile b/sys/arch/alpha/stand/Makefile index a5346cabaf3..e2b081bc13b 100644 --- a/sys/arch/alpha/stand/Makefile +++ b/sys/arch/alpha/stand/Makefile @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile,v 1.3 1996/07/29 23:01:13 niklas Exp $ -# $NetBSD: Makefile,v 1.3 1995/11/23 02:38:45 cgd Exp $ +# $OpenBSD: Makefile,v 1.4 1996/10/30 22:40:26 niklas Exp $ +# $NetBSD: Makefile,v 1.4 1996/09/23 04:28:23 cgd Exp $ -SUBDIR= boot bootxx installboot +SUBDIR= boot bootxx installboot netboot .include <bsd.subdir.mk> diff --git a/sys/arch/alpha/stand/Makefile.inc b/sys/arch/alpha/stand/Makefile.inc index ba63f5a62ea..351d0e2ef81 100644 --- a/sys/arch/alpha/stand/Makefile.inc +++ b/sys/arch/alpha/stand/Makefile.inc @@ -1,5 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.2 1996/07/29 23:01:14 niklas Exp $ -# $NetBSD: Makefile.inc,v 1.1 1995/11/23 02:38:48 cgd Exp $ +# $OpenBSD: Makefile.inc,v 1.3 1996/10/30 22:40:27 niklas Exp $ +# $NetBSD: Makefile.inc,v 1.3 1996/10/06 18:32:22 cgd Exp $ + +.include <bsd.own.mk> # for ELF_TOOLCHAIN definition BINDIR= /usr/mdec @@ -8,3 +10,8 @@ SECONDARY_LOAD_ADDRESS= 20020000 CPPFLAGS+= -DPRIMARY_LOAD_ADDRESS="0x${PRIMARY_LOAD_ADDRESS}" CPPFLAGS+= -DSECONDARY_LOAD_ADDRESS="0x${SECONDARY_LOAD_ADDRESS}" + +.if !defined(ELF_TOOLCHAIN) +CPPFLAGS+= -DECOFF_COMPAT +.endif + diff --git a/sys/arch/alpha/stand/OSFpal.c b/sys/arch/alpha/stand/OSFpal.c index 0dfe77e087f..0bf89c96fd0 100644 --- a/sys/arch/alpha/stand/OSFpal.c +++ b/sys/arch/alpha/stand/OSFpal.c @@ -1,5 +1,5 @@ -/* $OpenBSD: OSFpal.c,v 1.3 1996/07/29 23:01:16 niklas Exp $ */ -/* $NetBSD: OSFpal.c,v 1.2 1996/04/12 06:09:30 cgd Exp $ */ +/* $OpenBSD: OSFpal.c,v 1.4 1996/10/30 22:40:27 niklas Exp $ */ +/* $NetBSD: OSFpal.c,v 1.4 1996/10/13 03:00:24 christos Exp $ */ /* * Copyright (c) 1994, 1996 Carnegie-Mellon University. diff --git a/sys/arch/alpha/stand/bbinfo.h b/sys/arch/alpha/stand/bbinfo.h index 71c2bcdbde7..ee15a99b7aa 100644 --- a/sys/arch/alpha/stand/bbinfo.h +++ b/sys/arch/alpha/stand/bbinfo.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bbinfo.h,v 1.3 1996/07/29 23:01:17 niklas Exp $ */ +/* $OpenBSD: bbinfo.h,v 1.4 1996/10/30 22:40:28 niklas Exp $ */ /* $NetBSD: bbinfo.h,v 1.2 1996/04/12 06:09:34 cgd Exp $ */ /* diff --git a/sys/arch/alpha/stand/boot/Makefile b/sys/arch/alpha/stand/boot/Makefile index d3c510de833..bf32ff1073a 100644 --- a/sys/arch/alpha/stand/boot/Makefile +++ b/sys/arch/alpha/stand/boot/Makefile @@ -1,12 +1,13 @@ -# $OpenBSD: Makefile,v 1.4 1996/07/29 23:01:31 niklas Exp $ -# $NetBSD: Makefile,v 1.6 1996/04/12 01:35:15 cgd Exp $ +# $OpenBSD: Makefile,v 1.5 1996/10/30 22:40:38 niklas Exp $ +# $NetBSD: Makefile,v 1.10 1996/10/18 06:01:41 thorpej Exp $ .PATH: ${.CURDIR}/.. ${.CURDIR}/../../../../lib/libsa BOOT_PROG = boot BOOT_RELOC = ${SECONDARY_LOAD_ADDRESS} -BOOT_SRCS = start.S boot.c disk.c conf.c prom.c prom_disp.S OSFpal.c +BOOT_SRCS = start.S boot.c loadfile.c disk.c conf.c prom.c prom_disp.S OSFpal.c + BOOT_SRCS+= alloc.c bzero.c close.c dev.c devopen.c disklabel.c dkcksum.c BOOT_SRCS+= getfile.c gets.c ioctl.c lseek.c open.c printf.c read.c BOOT_SRCS+= strcmp.c ufs.c write.c bcopy.c filesystem.c strlen.c @@ -15,9 +16,11 @@ BOOT_OBJS = ${BOOT_SRCS:N*.h:R:S/$/.o/g} HEADERSIZE_PROG = headersize -AFLAGS += -DASSEMBLER +DEFNS= -DCOMPAT_UFS -DALPHA_BOOT_ECOFF -DALPHA_BOOT_ELF + +AFLAGS += -DASSEMBLER ${DEFNS} CPPFLAGS += -I${.CURDIR}/../.. -I${.CURDIR}/../../../.. -CFLAGS = -Werror -mno-fp-regs -g -DCOMPAT_UFS +CFLAGS = -Werror -mno-fp-regs -g ${DEFNS} CLEANFILES+= vers.c vers.o @@ -28,21 +31,21 @@ all: ${BOOT_PROG} ${BOOT_PROG}: ${BOOT_OBJS} ${HEADERSIZE_PROG} sh ${.CURDIR}/newvers.sh ${.CURDIR}/version ${COMPILE.c} vers.c - ${LD} -Ttext ${BOOT_RELOC} -N -e start -o ${BOOT_PROG}.coff \ + ${LD} -Ttext ${BOOT_RELOC} -N -e start -o ${BOOT_PROG}.hdr \ ${BOOT_OBJS} vers.o -lc # XXX - size ${BOOT_PROG}.coff - strip ${BOOT_PROG}.coff - dd if=${BOOT_PROG}.coff of=${BOOT_PROG} \ - bs=`./${HEADERSIZE_PROG} < ${BOOT_PROG}.coff` skip=1 + size ${BOOT_PROG}.hdr + strip ${BOOT_PROG}.hdr + dd if=${BOOT_PROG}.hdr of=${BOOT_PROG} \ + bs=`./${HEADERSIZE_PROG} ${BOOT_RELOC} ${BOOT_PROG}.hdr` skip=1 install: - install -c -o bin -g bin -m 444 ${BOOT_PROG} \ + ${INSTALL} -c -o bin -g bin -m 444 ${BOOT_PROG} \ ${DESTDIR}${BINDIR}/${BOOT_PROG} clean: _SUBDIRUSE rm -f a.out [Ee]rrs mklog core *.core \ ${BOOT_PROG} ${BOOT_OBJS} ${CLEANFILES} \ - ${BOOT_PROG}.coff ${HEADERSIZE_PROG} + ${BOOT_PROG}.hdr ${HEADERSIZE_PROG} cleandir: _SUBDIRUSE clean diff --git a/sys/arch/alpha/stand/boot/boot.c b/sys/arch/alpha/stand/boot/boot.c index 2ce83ae8f00..a585b2b3ed6 100644 --- a/sys/arch/alpha/stand/boot/boot.c +++ b/sys/arch/alpha/stand/boot/boot.c @@ -1,5 +1,5 @@ -/* $OpenBSD: boot.c,v 1.5 1996/07/31 16:24:11 niklas Exp $ */ -/* $NetBSD: boot.c,v 1.6 1996/05/10 00:15:08 cgd Exp $ */ +/* $OpenBSD: boot.c,v 1.6 1996/10/30 22:40:39 niklas Exp $ */ +/* $NetBSD: boot.c,v 1.8 1996/09/17 22:00:26 cgd Exp $ */ /* * Copyright (c) 1992, 1993 @@ -51,52 +51,25 @@ #define _KERNEL #include "include/pte.h" -static int aout_exec __P((int, struct exec *, u_int64_t *)); -static int coff_exec __P((int, struct ecoff_exechdr *, u_int64_t *)); -static int loadfile __P((char *, u_int64_t *)); - -char line[64] = "/bsd"; +int loadfile __P((char *, u_int64_t *)); char boot_file[128]; -char boot_dev[128]; char boot_flags[128]; -char boot_console[8]; extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; -#define KERNEL_ARGC 4 -char *kernel_argv[KERNEL_ARGC+1] = { - boot_file, - boot_flags, - boot_console, - boot_dev, - NULL -}; - vm_offset_t ffp_save, ptbr_save; void -main(argc, argv, envp) - int argc; - char **argv; - char **envp; +main() { u_int64_t entry; - int ask; - prom_return_t ret; - -#ifdef notdef - { - extern char *_EDATA, *_end; - bzero(_EDATA, _end - _EDATA); - } -#endif /* Init prom callback vector. */ init_prom_calls(); /* print a banner */ - printf("\n\n"); + printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); printf("\n"); @@ -106,177 +79,19 @@ main(argc, argv, envp) printf("\n"); - prom_getenv(PROM_E_BOOTED_DEV, boot_dev, sizeof(boot_dev)); prom_getenv(PROM_E_BOOTED_FILE, boot_file, sizeof(boot_file)); prom_getenv(PROM_E_BOOTED_OSFLAGS, boot_flags, sizeof(boot_flags)); - prom_getenv(PROM_E_TTY_DEV, boot_console, sizeof(boot_console)); - - printf("boot_dev = \"%s\"\n", boot_dev); - printf("boot_file = \"%s\"\n", boot_file); - printf("boot_flags = \"%s\"\n", boot_flags); - printf("boot_console = \"%s\"\n", boot_console); if (boot_file[0] == '\0') - bcopy(line, boot_file, strlen(line)+1); - -#ifdef JUSTASK - ask = 1; -#else - ask = 0; -#endif - for (;;) { - if (ask) { - (void)printf("Boot: "); - gets(line); - if (line[0] == '\0') - continue; - if (!strcmp(line, "halt")) - halt(); -/* XXX TURN LINE INTO BOOT FILE/FLAGS */ - bcopy(line, boot_file, strlen(line)+1); - } else - (void)printf("Boot: %s %s\n", boot_file, boot_flags); - - if (!loadfile(boot_file, &entry)) { - -printf("calling %lx with %lx, %lx, %lx, %lx, %lx\n", entry, -ffp_save, ptbr_save, KERNEL_ARGC, kernel_argv, NULL); - (*(void (*)())entry)(ffp_save, ptbr_save, KERNEL_ARGC, - kernel_argv, NULL); - } - - ask = 1; - } - /* NOTREACHED */ -} - -/* - * Open 'filename', read in program and return the entry point or -1 if error. - */ -static int -loadfile(fname, entryp) - char *fname; - u_int64_t *entryp; -{ - struct devices *dp; - union { - struct exec aout; - struct ecoff_exechdr coff; - } hdr; - ssize_t nr; - int fd, rval; - - /* Open the file. */ - rval = 1; - if ((fd = open(fname, 0)) < 0) { - (void)printf("open error: %d\n", errno); - goto err; - } - - /* Read the exec header. */ - if ((nr = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr)) { - (void)printf("read error: %d\n", errno); - goto err; - } - - /* Exec a.out or COFF. */ - rval = ECOFF_BADMAG(&hdr.coff) ? /* XXX check aouthdr */ - aout_exec(fd, &hdr.aout, entryp) : - coff_exec(fd, &hdr.coff, entryp); + bcopy("bsd", boot_file, sizeof "bsd"); -err: -#ifndef SMALL - if (fd >= 0) - (void)close(fd); -#endif - if (rval) - (void)printf("can't boot '%s'\n", fname); - return (rval); -} - -static int -aout_exec(fd, aout, entryp) - int fd; - struct exec *aout; - u_int64_t *entryp; -{ - size_t sz; + (void)printf("Boot: %s %s\n", boot_file, boot_flags); - /* Check the magic number. */ - if (N_GETMAGIC(*aout) != OMAGIC) { - (void)printf("bad magic: %o\n", N_GETMAGIC(*aout)); - return (1); - } - - /* Read in text, data. */ - (void)printf("%lu+%lu", aout->a_text, aout->a_data); - if (lseek(fd, (off_t)N_TXTOFF(*aout), SEEK_SET) < 0) { - (void)printf("lseek: %d\n", errno); - return (1); - } - sz = aout->a_text + aout->a_data; - if (read(fd, (void *)aout->a_entry, sz) != sz) { - (void)printf("read text/data: %d\n", errno); - return (1); + if (!loadfile(boot_file, &entry)) { + (void)printf("Entering kernel at 0x%lx...\n", entry); + (*(void (*)())entry)(ffp_save, ptbr_save, 0); } - /* Zero out bss. */ - if (aout->a_bss != 0) { - (void)printf("+%lu", aout->a_bss); - bzero(aout->a_entry + sz, aout->a_bss); - } - - ffp_save = aout->a_entry + aout->a_text + aout->a_data + aout->a_bss; - ffp_save = k0segtophys((ffp_save + PGOFSET & ~PGOFSET)) >> PGSHIFT; - ffp_save += 2; /* XXX OSF/1 does this, no idea why. */ - - (void)printf("\n"); - *entryp = aout->a_entry; - return (0); -} - -static int -coff_exec(fd, coff, entryp) - int fd; - struct ecoff_exechdr *coff; - u_int64_t *entryp; -{ - - /* Read in text. */ - (void)printf("%lu", coff->a.tsize); - (void)lseek(fd, ECOFF_TXTOFF(coff), 0); - if (read(fd, (void *)coff->a.text_start, coff->a.tsize) != - coff->a.tsize) { - (void)printf("read text: %d\n", errno); - return (1); - } - - /* Read in data. */ - if (coff->a.dsize != 0) { - (void)printf("+%lu", coff->a.dsize); - if (read(fd, (void *)coff->a.data_start, coff->a.dsize) != - coff->a.dsize) { - (void)printf("read data: %d\n", errno); - return (1); - } - } - - - /* Zero out bss. */ - if (coff->a.bsize != 0) { - (void)printf("+%lu", coff->a.bsize); - bzero(coff->a.bss_start, coff->a.bsize); - } - - ffp_save = coff->a.text_start + coff->a.tsize; - if (ffp_save < coff->a.data_start + coff->a.dsize) - ffp_save = coff->a.data_start + coff->a.dsize; - if (ffp_save < coff->a.bss_start + coff->a.bsize) - ffp_save = coff->a.bss_start + coff->a.bsize; - ffp_save = k0segtophys((ffp_save + PGOFSET & ~PGOFSET)) >> PGSHIFT; - ffp_save += 2; /* XXX OSF/1 does this, no idea why. */ - - (void)printf("\n"); - *entryp = coff->a.entry; - return (0); + (void)printf("Boot failed! Halting...\n"); + halt(); } diff --git a/sys/arch/alpha/stand/boot/conf.c b/sys/arch/alpha/stand/boot/conf.c index 4c275c4513c..3883551a738 100644 --- a/sys/arch/alpha/stand/boot/conf.c +++ b/sys/arch/alpha/stand/boot/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.3 1996/07/29 23:01:35 niklas Exp $ */ +/* $OpenBSD: conf.c,v 1.4 1996/10/30 22:40:40 niklas Exp $ */ /* $NetBSD: conf.c,v 1.3 1995/11/23 02:39:31 cgd Exp $ */ /* diff --git a/sys/arch/alpha/stand/boot/devopen.c b/sys/arch/alpha/stand/boot/devopen.c index b25bdfb7318..2e9cbc1951d 100644 --- a/sys/arch/alpha/stand/boot/devopen.c +++ b/sys/arch/alpha/stand/boot/devopen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: devopen.c,v 1.2 1996/07/29 23:01:36 niklas Exp $ */ +/* $OpenBSD: devopen.c,v 1.3 1996/10/30 22:40:41 niklas Exp $ */ /* $NetBSD: devopen.c,v 1.1 1995/11/23 02:39:37 cgd Exp $ */ /*- diff --git a/sys/arch/alpha/stand/boot/disk.c b/sys/arch/alpha/stand/boot/disk.c index 3566a0036b3..5b70adf9a61 100644 --- a/sys/arch/alpha/stand/boot/disk.c +++ b/sys/arch/alpha/stand/boot/disk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disk.c,v 1.3 1996/07/29 23:01:38 niklas Exp $ */ +/* $OpenBSD: disk.c,v 1.4 1996/10/30 22:40:42 niklas Exp $ */ /* $NetBSD: disk.c,v 1.3 1995/11/23 02:39:40 cgd Exp $ */ /* diff --git a/sys/arch/alpha/stand/boot/disk.h b/sys/arch/alpha/stand/boot/disk.h index 43f5e0be52b..264c773ceea 100644 --- a/sys/arch/alpha/stand/boot/disk.h +++ b/sys/arch/alpha/stand/boot/disk.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disk.h,v 1.2 1996/07/29 23:01:39 niklas Exp $ */ +/* $OpenBSD: disk.h,v 1.3 1996/10/30 22:40:42 niklas Exp $ */ /* $NetBSD: disk.h,v 1.1 1995/11/23 02:39:42 cgd Exp $ */ int diskstrategy __P((void *, int, daddr_t, size_t, void *, size_t *)); diff --git a/sys/arch/alpha/stand/boot/filesystem.c b/sys/arch/alpha/stand/boot/filesystem.c index 4833ce6acec..1956f3504fa 100644 --- a/sys/arch/alpha/stand/boot/filesystem.c +++ b/sys/arch/alpha/stand/boot/filesystem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: filesystem.c,v 1.2 1996/07/29 23:01:41 niklas Exp $ */ +/* $OpenBSD: filesystem.c,v 1.3 1996/10/30 22:40:43 niklas Exp $ */ /* $NetBSD: filesystem.c,v 1.1 1995/11/23 02:39:46 cgd Exp $ */ /* diff --git a/sys/arch/alpha/stand/boot/newvers.sh b/sys/arch/alpha/stand/boot/newvers.sh index a65d3cfb37d..605d7141d93 100644 --- a/sys/arch/alpha/stand/boot/newvers.sh +++ b/sys/arch/alpha/stand/boot/newvers.sh @@ -1,7 +1,7 @@ #!/bin/sh - # -# $OpenBSD: newvers.sh,v 1.4 1996/07/31 16:24:12 niklas Exp $ -# $NetBSD: newvers.sh,v 1.2 1995/11/23 02:39:48 cgd Exp $ +# $OpenBSD: newvers.sh,v 1.5 1996/10/30 22:40:44 niklas Exp $ +# $NetBSD: newvers.sh,v 1.3 1996/06/14 20:03:04 cgd Exp $ # # Copyright (c) 1984, 1986, 1990, 1993 # The Regents of the University of California. All rights reserved. @@ -37,9 +37,9 @@ # @(#)newvers.sh 8.1 (Berkeley) 4/20/94 u=${USER-root} h=`hostname` t=`date` -r=`head -1 $1` +r=`head -1 $1 | awk ' { print $3 } '` -echo "char bootprog_name[] = \"OpenBSD/Alpha boot\";" > vers.c +echo "char bootprog_name[] = \"OpenBSD/Alpha Secondary Boot\";" > vers.c echo "char bootprog_rev[] = \"${r}\";" >> vers.c echo "char bootprog_date[] = \"${t}\";" >> vers.c echo "char bootprog_maker[] = \"${u}@${h}\";" >> vers.c diff --git a/sys/arch/alpha/stand/boot/prom_swpal.S b/sys/arch/alpha/stand/boot/prom_swpal.S index 718ad653260..6b0c010ffde 100644 --- a/sys/arch/alpha/stand/boot/prom_swpal.S +++ b/sys/arch/alpha/stand/boot/prom_swpal.S @@ -1,5 +1,5 @@ -/* $OpenBSD: prom_swpal.S,v 1.2 1996/07/29 23:01:44 niklas Exp $ */ -/* $NetBSD: prom_swpal.S,v 1.2 1995/02/16 02:32:58 cgd Exp $ */ +/* $OpenBSD: prom_swpal.S,v 1.3 1996/10/30 22:40:45 niklas Exp $ */ +/* $NetBSD: prom_swpal.S,v 1.4 1996/10/17 02:50:41 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -61,13 +61,13 @@ #define PALSW_FRAME_SIZE (14*8) #define PALSW_REGS IM_RA|IM_S0|IM_S1|IM_S2|IM_S3|IM_S4|IM_S5 - .comm ptbr_save 8 + .comm ptbr_save,8 .text .align 4 NESTED(switch_palcode, 0, PALSW_FRAME_SIZE, ra, PALSW_REGS, 0) - SETGP(pv) + LDGP(pv) /* ldgp gp, 0(pv)*/ lda sp, -PALSW_FRAME_SIZE(sp) @@ -105,8 +105,7 @@ NESTED(switch_palcode, 0, PALSW_FRAME_SIZE, ra, PALSW_REGS, 0) call_pal PAL_VMS_mfpr_vptb mov v0, a3 -/* movi PAL_OSF, a0 */ - CONST(PAL_OSF, a0) + ldiq a0, PAL_OSF lda a1, contin ldq a2, 16(sp) diff --git a/sys/arch/alpha/stand/boot/test.c b/sys/arch/alpha/stand/boot/test.c index 3da120e34b8..82fb6684ffe 100644 --- a/sys/arch/alpha/stand/boot/test.c +++ b/sys/arch/alpha/stand/boot/test.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test.c,v 1.2 1996/07/29 23:01:46 niklas Exp $ */ +/* $OpenBSD: test.c,v 1.3 1996/10/30 22:40:46 niklas Exp $ */ /* $NetBSD: test.c,v 1.2 1995/02/16 02:33:00 cgd Exp $ */ /* diff --git a/sys/arch/alpha/stand/boot/version b/sys/arch/alpha/stand/boot/version index f396a5a7ebf..4343db37627 100644 --- a/sys/arch/alpha/stand/boot/version +++ b/sys/arch/alpha/stand/boot/version @@ -1,5 +1,5 @@ -$OpenBSD: version,v 1.4 1996/07/29 23:01:48 niklas Exp $ -$NetBSD: version,v 1.5 1996/05/09 23:54:18 cgd Exp $ +$OpenBSD: version,v 1.5 1996/10/30 22:40:47 niklas Exp $ +$NetBSD: version,v 1.6 1996/06/14 20:03:07 cgd Exp $ 1.1: Initial version 1.2: don't forget the Id string! @@ -7,3 +7,6 @@ $NetBSD: version,v 1.5 1996/05/09 23:54:18 cgd Exp $ 1.4-1: Re-import from master sources 1.4-2: Complete rewrite of boot block code 1.5: Update for new ECOFF headers +1.6: Don't pass arguments to the kernel, trim unnecessary environment + calls, kill 'ask' loop (i.e. if boot fails, halt), seperate + ECOFF and a.out support into seperate options. diff --git a/sys/arch/alpha/stand/bootxx.c b/sys/arch/alpha/stand/bootxx.c index 6e6e5315e50..6586fff8011 100644 --- a/sys/arch/alpha/stand/bootxx.c +++ b/sys/arch/alpha/stand/bootxx.c @@ -1,5 +1,5 @@ -/* $OpenBSD: bootxx.c,v 1.4 1996/07/31 10:38:46 niklas Exp $ */ -/* $NetBSD: bootxx.c,v 1.2 1996/04/12 06:09:36 cgd Exp $ */ +/* $OpenBSD: bootxx.c,v 1.5 1996/10/30 22:40:29 niklas Exp $ */ +/* $NetBSD: bootxx.c,v 1.3 1996/06/14 20:04:45 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -136,7 +136,7 @@ main() /* Init prom callback vector. */ init_prom_calls(); - puts("\nOpenBSD/Alpha primary boot...\n"); + puts("\nOpenBSD/Alpha Primary Boot\n"); bbinfop = (struct bbinfo *)&_end; loadaddr = (char *)SECONDARY_LOAD_ADDRESS; diff --git a/sys/arch/alpha/stand/bootxx/Makefile b/sys/arch/alpha/stand/bootxx/Makefile index 9bd8a2fc518..f2a724efda2 100644 --- a/sys/arch/alpha/stand/bootxx/Makefile +++ b/sys/arch/alpha/stand/bootxx/Makefile @@ -1,5 +1,5 @@ -# $OpenBSD: Makefile,v 1.3 1996/07/29 23:01:50 niklas Exp $ -# $NetBSD: Makefile,v 1.4 1995/11/23 02:40:29 cgd Exp $ +# $OpenBSD: Makefile,v 1.4 1996/10/30 22:40:48 niklas Exp $ +# $NetBSD: Makefile,v 1.6 1996/10/18 06:02:02 thorpej Exp $ .PATH: ${.CURDIR}/.. ${.CURDIR}/../../../../lib/libsa @@ -12,7 +12,7 @@ BOOT_OBJS = ${BOOT_SRCS:N*.h:R:S/$/.o/g} HEADERSIZE_PROG = headersize AFLAGS += -DASSEMBLER -CPPFLAGS += -I${.CURDIR}/../.. -DPRIMARY_BOOTBLOCK +CPPFLAGS += -I${.CURDIR}/../.. -I${.CURDIR}/../../../.. -DPRIMARY_BOOTBLOCK CFLAGS = -Werror -mno-fp-regs -g .PATH: ${.CURDIR}/../../../../lib/libkern @@ -20,22 +20,22 @@ CFLAGS = -Werror -mno-fp-regs -g all: ${BOOT_PROG} ${BOOT_PROG}: ${BOOT_OBJS} ${HEADERSIZE_PROG} - ${LD} -Ttext ${BOOT_RELOC} -N -e start -o ${BOOT_PROG}.coff \ + ${LD} -Ttext ${BOOT_RELOC} -N -e start -o ${BOOT_PROG}.hdr \ ${BOOT_OBJS} - size ${BOOT_PROG}.coff - strip ${BOOT_PROG}.coff - dd if=${BOOT_PROG}.coff of=${BOOT_PROG}.nohdr \ - bs=`./${HEADERSIZE_PROG} < ${BOOT_PROG}.coff` skip=1 + size ${BOOT_PROG}.hdr + strip ${BOOT_PROG}.hdr + dd if=${BOOT_PROG}.hdr of=${BOOT_PROG}.nohdr \ + bs=`./${HEADERSIZE_PROG} ${BOOT_RELOC} ${BOOT_PROG}.hdr` skip=1 dd if=${BOOT_PROG}.nohdr of=${BOOT_PROG} bs=`expr 15 \* 512` conv=sync install: - install -c -o bin -g bin -m 444 ${BOOT_PROG} \ + ${INSTALL} -c -o bin -g bin -m 444 ${BOOT_PROG} \ ${DESTDIR}${BINDIR}/${BOOT_PROG} clean: _SUBDIRUSE rm -f a.out [Ee]rrs mklog core *.core \ ${BOOT_PROG} ${BOOT_OBJS} ${CLEANFILES} \ - ${BOOT_PROG}.coff ${BOOT_PROG}.nohdr ${HEADERSIZE_PROG} + ${BOOT_PROG}.hdr ${BOOT_PROG}.nohdr ${HEADERSIZE_PROG} cleandir: _SUBDIRUSE clean diff --git a/sys/arch/alpha/stand/headersize.c b/sys/arch/alpha/stand/headersize.c index 3b2024e4f25..c7e853d5e18 100644 --- a/sys/arch/alpha/stand/headersize.c +++ b/sys/arch/alpha/stand/headersize.c @@ -1,5 +1,5 @@ -/* $OpenBSD: headersize.c,v 1.3 1996/07/29 23:01:20 niklas Exp $ */ -/* $NetBSD: headersize.c,v 1.3.4.1 1996/06/13 18:35:33 cgd Exp $ */ +/* $OpenBSD: headersize.c,v 1.4 1996/10/30 22:40:30 niklas Exp $ */ +/* $NetBSD: headersize.c,v 1.5 1996/09/23 04:32:59 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -28,22 +28,58 @@ * rights to redistribute these changes. */ +#define ELFSIZE 64 + #include <sys/types.h> +#include <sys/fcntl.h> #include <sys/exec.h> #include <sys/exec_ecoff.h> +#include <sys/exec_elf.h> + +#include <unistd.h> +#include <stdio.h> #define HDR_BUFSIZE 512 -main() +int +main(argc, argv) + int argc; + char *argv[]; { - char buf[HDR_BUFSIZE]; - struct ecoff_exechdr *execp; + char buf[HDR_BUFSIZE], *fname; + struct ecoff_exechdr *ecoffp; + Elf_Ehdr *elfp; + int fd; + unsigned long loadaddr; + + if (argc != 3) + errx(1, "must be given two arguments (load addr, file name)"); + if (sscanf(argv[1], "%lx", &loadaddr) != 1) + errx(1, "load addr argument (%s) not valid", argv[1]); + fname = argv[2]; + + if ((fd = open(fname, O_RDONLY, 0)) == -1) + err(1, "%s: open failed", 0); + + if (read(fd, &buf, HDR_BUFSIZE) < HDR_BUFSIZE) + err(1, "%s: read failed", fname); + ecoffp = (struct ecoff_exechdr *)buf; + elfp = (Elf_Ehdr *)buf; + + if (!ECOFF_BADMAG(ecoffp)) { + printf("%d\n", ECOFF_TXTOFF(ecoffp)); + } else if (memcmp(Elf_e_ident, elfp->e_ident, Elf_e_siz) == 0) { + Elf_Phdr phdr; + + /* XXX assume the first segment is the one we want */ + if (lseek(fd, elfp->e_phoff, SEEK_SET) == -1) + err(1, "%s: lseek phdr failed", fname); + if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) + err(1, "%s: read phdr failed", fname); - if (read(0, &buf, HDR_BUFSIZE) < HDR_BUFSIZE) { - perror("read"); - exit(1); - } - execp = (struct ecoff_exechdr *)buf; + printf("%d\n", phdr.p_offset + (loadaddr - phdr.p_vaddr)); + } else + errx(1, "%s: bad magic number", fname); - printf("%d\n", ECOFF_TXTOFF(execp)); + close(fd); } diff --git a/sys/arch/alpha/stand/installboot.c b/sys/arch/alpha/stand/installboot.c index 38744a982c0..f5f664b0075 100644 --- a/sys/arch/alpha/stand/installboot.c +++ b/sys/arch/alpha/stand/installboot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: installboot.c,v 1.3 1996/07/29 23:01:22 niklas Exp $ */ +/* $OpenBSD: installboot.c,v 1.4 1996/10/30 22:40:31 niklas Exp $ */ /* $NetBSD: installboot.c,v 1.2 1995/12/20 00:17:49 cgd Exp $ */ /* diff --git a/sys/arch/alpha/stand/installboot/Makefile b/sys/arch/alpha/stand/installboot/Makefile index a06945bb820..68fbe7a5412 100644 --- a/sys/arch/alpha/stand/installboot/Makefile +++ b/sys/arch/alpha/stand/installboot/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.2 1996/07/29 23:01:53 niklas Exp $ +# $OpenBSD: Makefile,v 1.3 1996/10/30 22:40:49 niklas Exp $ # $NetBSD: Makefile,v 1.1 1995/11/23 02:41:18 cgd Exp $ .PATH: ${.CURDIR}/.. diff --git a/sys/arch/alpha/stand/loadfile.c b/sys/arch/alpha/stand/loadfile.c new file mode 100644 index 00000000000..ffe364ffde1 --- /dev/null +++ b/sys/arch/alpha/stand/loadfile.c @@ -0,0 +1,216 @@ +/* $OpenBSD: loadfile.c,v 1.1 1996/10/30 22:40:33 niklas Exp $ */ +/* $NetBSD: loadfile.c,v 1.3 1996/09/23 04:32:44 cgd Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * 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. + * + * @(#)boot.c 8.1 (Berkeley) 6/10/93 + */ + +#define ELFSIZE 64 + +#include <lib/libsa/stand.h> +#include <lib/libkern/libkern.h> + +#include <sys/param.h> +#include <sys/exec.h> +#include <sys/exec_ecoff.h> +#include <sys/exec_elf.h> + +#include <machine/prom.h> + +#define _KERNEL +#include "include/pte.h" + +#ifdef ALPHA_BOOT_ECOFF +static int coff_exec __P((int, struct ecoff_exechdr *, u_int64_t *)); +#endif +#ifdef ALPHA_BOOT_ELF +static int elf_exec __P((int, Elf_Ehdr *, u_int64_t *)); +#endif +int loadfile __P((char *, u_int64_t *)); + +vm_offset_t ffp_save, ptbr_save; + +/* + * Open 'filename', read in program and return the entry point or -1 if error. + */ +int +loadfile(fname, entryp) + char *fname; + u_int64_t *entryp; +{ + struct devices *dp; + union { +#ifdef ALPHA_BOOT_ECOFF + struct ecoff_exechdr coff; +#endif +#ifdef ALPHA_BOOT_ELF + Elf_Ehdr elf; +#endif + } hdr; + ssize_t nr; + int fd, rval; + + /* Open the file. */ + rval = 1; + if ((fd = open(fname, 0)) < 0) { + (void)printf("open %s: error %d\n", fname, errno); + goto err; + } + + /* Read the exec header. */ + if ((nr = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr)) { + (void)printf("read header: error %d\n", errno); + goto err; + } + +#ifdef ALPHA_BOOT_ECOFF + if (!ECOFF_BADMAG(&hdr.coff)) { + rval = coff_exec(fd, &hdr.coff, entryp); + } else +#endif +#ifdef ALPHA_BOOT_ELF + if (memcmp(Elf_e_ident, hdr.elf.e_ident, Elf_e_siz) == 0) { + rval = elf_exec(fd, &hdr.elf, entryp); + } else +#endif + { + (void)printf("%s: unknown executable format\n", fname); + } + +err: + if (fd >= 0) + (void)close(fd); + return (rval); +} + +#ifdef ALPHA_BOOT_ECOFF +static int +coff_exec(fd, coff, entryp) + int fd; + struct ecoff_exechdr *coff; + u_int64_t *entryp; +{ + + /* Read in text. */ + (void)printf("%lu", coff->a.tsize); + (void)lseek(fd, ECOFF_TXTOFF(coff), 0); + if (read(fd, (void *)coff->a.text_start, coff->a.tsize) != + coff->a.tsize) { + (void)printf("read text: %d\n", errno); + return (1); + } + + /* Read in data. */ + if (coff->a.dsize != 0) { + (void)printf("+%lu", coff->a.dsize); + if (read(fd, (void *)coff->a.data_start, coff->a.dsize) != + coff->a.dsize) { + (void)printf("read data: %d\n", errno); + return (1); + } + } + + + /* Zero out bss. */ + if (coff->a.bsize != 0) { + (void)printf("+%lu", coff->a.bsize); + bzero(coff->a.bss_start, coff->a.bsize); + } + + ffp_save = coff->a.text_start + coff->a.tsize; + if (ffp_save < coff->a.data_start + coff->a.dsize) + ffp_save = coff->a.data_start + coff->a.dsize; + if (ffp_save < coff->a.bss_start + coff->a.bsize) + ffp_save = coff->a.bss_start + coff->a.bsize; + ffp_save = ALPHA_K0SEG_TO_PHYS((ffp_save + PGOFSET & ~PGOFSET)) >> PGSHIFT; + ffp_save += 2; /* XXX OSF/1 does this, no idea why. */ + + (void)printf("\n"); + *entryp = coff->a.entry; + return (0); +} +#endif /* ALPHA_BOOT_ECOFF */ + +#ifdef ALPHA_BOOT_ELF +static int +elf_exec(fd, elf, entryp) + int fd; + Elf_Ehdr *elf; + u_int64_t *entryp; +{ + int i; + int first = 1; + + for (i = 0; i < elf->e_phnum; i++) { + Elf_Phdr phdr; + (void)lseek(fd, elf->e_phoff + sizeof(phdr) * i, 0); + if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) { + (void)printf("read phdr: %d\n", errno); + return (1); + } + if (phdr.p_type != Elf_pt_load || + (phdr.p_flags & (Elf_pf_w|Elf_pf_x)) == 0) + continue; + + /* Read in segment. */ + (void)printf("%s%lu", first ? "" : "+", phdr.p_filesz); + (void)lseek(fd, phdr.p_offset, 0); + if (read(fd, (void *)phdr.p_vaddr, phdr.p_filesz) != + phdr.p_filesz) { + (void)printf("read text: %d\n", errno); + return (1); + } + if (first || ffp_save < phdr.p_vaddr + phdr.p_memsz) + ffp_save = phdr.p_vaddr + phdr.p_memsz; + + /* Zero out bss. */ + if (phdr.p_filesz < phdr.p_memsz) { + (void)printf("+%lu", phdr.p_memsz - phdr.p_filesz); + bzero(phdr.p_vaddr + phdr.p_filesz, + phdr.p_memsz - phdr.p_filesz); + } + first = 0; + } + + ffp_save = ALPHA_K0SEG_TO_PHYS((ffp_save + PGOFSET & ~PGOFSET)) >> PGSHIFT; + ffp_save += 2; /* XXX OSF/1 does this, no idea why. */ + + (void)printf("\n"); + *entryp = elf->e_entry; + return (0); +} +#endif /* ALPHA_BOOT_ELF */ diff --git a/sys/arch/alpha/stand/netboot/Makefile b/sys/arch/alpha/stand/netboot/Makefile new file mode 100644 index 00000000000..f83b46d45ac --- /dev/null +++ b/sys/arch/alpha/stand/netboot/Makefile @@ -0,0 +1,61 @@ +# $OpenBSD: Makefile,v 1.1 1996/10/30 22:40:51 niklas Exp $ +# $NetBSD: Makefile,v 1.3 1996/10/18 06:02:24 thorpej Exp $ + +.PATH: ${.CURDIR}/.. ${.CURDIR}/../../../../lib/libsa + +BOOT_PROG = netboot +BOOT_RELOC = ${PRIMARY_LOAD_ADDRESS} + +BOOT_SRCS = start.S netboot.c prom.c prom_disp.S OSFpal.c prom_swpal.S +BOOT_SRCS+= printf.c bzero.c rpcc.S + +BOOT_SRCS+= dev_net.c conf.c devopen.c +BOOT_SRCS+= nfs.c rpc.c alloc.c ntohl.c htonl.c ntohs.c htons.c net.c bootp.c +BOOT_SRCS+= strlen.c bcopy.c dev.c bcmp.c strerror.c rarp.c read.c lseek.c +BOOT_SRCS+= in_cksum.c exit.c closeall.c arp.c strncpy.c globals.c open.c +BOOT_SRCS+= close.c ether.c netif.c + +BOOT_SRCS+= if_prom.c loadfile.c getsecs.c + +BOOT_OBJS = ${BOOT_SRCS:N*.h:R:S/$/.o/g} + +HEADERSIZE_PROG = headersize + +AFLAGS += -DASSEMBLER +CPPFLAGS += -I${.CURDIR}/../../../../ \ + -I${.CURDIR}/../../../../lib/libsa \ + -I${.CURDIR}/../.. -DPRIMARY_BOOTBLOCK \ + -DALPHA_BOOT_ECOFF -DALPHA_BOOT_ELF +CFLAGS = -Werror -mno-fp-regs -g + +CLEANFILES+= vers.c vers.o + +.PATH: ${.CURDIR} ${.CURDIR}/../../../../lib/libkern ${.CURDIR}/../boot + +all: ${BOOT_PROG} + +${BOOT_PROG}: ${BOOT_OBJS} ${HEADERSIZE_PROG} + sh ${.CURDIR}/newvers.sh ${.CURDIR}/version + ${COMPILE.c} vers.c + ${LD} -Ttext ${BOOT_RELOC} -N -e start -o ${BOOT_PROG}.hdr \ + ${BOOT_OBJS} vers.o -lc # XXX + size ${BOOT_PROG}.hdr + strip ${BOOT_PROG}.hdr + dd if=${BOOT_PROG}.hdr of=${BOOT_PROG} \ + bs=`./${HEADERSIZE_PROG} ${BOOT_RELOC} ${BOOT_PROG}.hdr` skip=1 + +install: + ${INSTALL} -c -o bin -g bin -m 444 ${BOOT_PROG} \ + ${DESTDIR}${BINDIR}/${BOOT_PROG} + +clean: _SUBDIRUSE + rm -f a.out [Ee]rrs mklog core *.core \ + ${BOOT_PROG} ${BOOT_OBJS} ${CLEANFILES} \ + ${BOOT_PROG}.hdr ${BOOT_PROG}.nohdr ${HEADERSIZE_PROG} + +cleandir: _SUBDIRUSE clean + +.include "${.CURDIR}/../Makefile.inc" +.include <bsd.obj.mk> +.include <bsd.dep.mk> +.include <bsd.subdir.mk> diff --git a/sys/arch/alpha/stand/netboot/conf.c b/sys/arch/alpha/stand/netboot/conf.c new file mode 100644 index 00000000000..b40ffacf7be --- /dev/null +++ b/sys/arch/alpha/stand/netboot/conf.c @@ -0,0 +1,26 @@ +/* $OpenBSD: conf.c,v 1.1 1996/10/30 22:40:52 niklas Exp $ */ +/* $NetBSD: conf.c,v 1.2 1996/10/02 21:18:45 cgd Exp $ */ + +#include <sys/types.h> +#include <netinet/in.h> + +#include "stand.h" +#include "nfs.h" +#include "dev_net.h" + +struct fs_ops file_system[] = { + { nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, nfs_stat }, +}; +int nfsys = 1; + +struct devsw devsw[] = { + { "net", net_strategy, net_open, net_close, net_ioctl }, +}; +int ndevs = 1; + +extern struct netif_driver prom_netif_driver; + +struct netif_driver *netif_drivers[] = { + &prom_netif_driver, +}; +int n_netif_drivers = (sizeof(netif_drivers) / sizeof(netif_drivers[0])); diff --git a/sys/arch/alpha/stand/netboot/dev_net.c b/sys/arch/alpha/stand/netboot/dev_net.c new file mode 100644 index 00000000000..ddb84da844c --- /dev/null +++ b/sys/arch/alpha/stand/netboot/dev_net.c @@ -0,0 +1,255 @@ +/* $OpenBSD: dev_net.c,v 1.1 1996/10/30 22:40:53 niklas Exp $ */ +/* $NetBSD: dev_net.c,v 1.1 1996/09/18 20:03:07 cgd Exp $ */ + +/* + * Copyright (c) 1995 Gordon W. Ross + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * 4. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Gordon W. Ross + * + * 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. + */ + +/* + * This module implements a "raw device" interface suitable for + * use by the stand-alone I/O library NFS code. This interface + * does not support any "block" access, and exists only for the + * purpose of initializing the network interface, getting boot + * parameters, and performing the NFS mount. + * + * At open time, this does: + * + * find interface - netif_open() + * RARP for IP address - rarp_getipaddress() + * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...) + * RPC/mountd - nfs_mount(sock, ip, path) + * + * the root file handle from mountd is saved in a global + * for use by the NFS open code (NFS/lookup). + */ + +#include <stdarg.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <netinet/if_ether.h> +#include <netinet/in_systm.h> + +#include "stand.h" +#include "net.h" +#include "netif.h" +#include "bootparam.h" +#include "dev_net.h" + +extern int debug; +extern int nfs_root_node[]; /* XXX - get from nfs_mount() */ + +/* + * Various globals needed by the network code: + */ + +#if 0 +/* for arp.c, rarp.c */ +u_char bcea[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#endif + +struct in_addr myip; /* my ip address */ +struct in_addr rootip; /* root ip address */ +struct in_addr gateip; /* swap ip address */ +n_long netmask; /* subnet or net mask */ + +char rootpath[FNAME_SIZE]; + +int hostnamelen; +char hostname[FNAME_SIZE]; + +int domainnamelen; +char domainname[FNAME_SIZE]; + +/* + * Local things... + */ +static int netdev_sock = -1; +static int netdev_opens; + +/* + * Called by devopen after it sets f->f_dev to our devsw entry. + * This opens the low-level device and sets f->f_devdata. + * This is declared with variable arguments... + */ +int +net_open(struct open_file *f, ...) +{ + va_list ap; + char *devname; /* Device part of file name (or NULL). */ + int error = 0; + + va_start(ap, f); + devname = va_arg(ap, char*); + va_end(ap); + +#ifdef NETIF_DEBUG + if (debug) + printf("net_open: %s\n", devname); +#endif + + /* On first open, do netif open, mount, etc. */ + if (netdev_opens == 0) { + /* Find network interface. */ + if (netdev_sock < 0) { + netdev_sock = netif_open(devname); + if (netdev_sock < 0) { + printf("net_open: netif_open() failed\n"); + return (ENXIO); + } + if (debug) + printf("net_open: netif_open() succeeded\n"); + } + if (rootip.s_addr == 0) { + /* Get root IP address, and path, etc. */ + error = net_getparams(netdev_sock); + if (error) { + /* getparams makes its own noise */ + goto fail; + } + /* Get the NFS file handle (mountd). */ + error = nfs_mount(netdev_sock, rootip, rootpath); + if (error) { + printf("net_open: NFS mount error=%d\n", error); + rootip.s_addr = 0; + fail: + netif_close(netdev_sock); + netdev_sock = -1; + return (error); + } + if (debug) + printf("net_open: NFS mount succeeded\n"); + } + } + netdev_opens++; + f->f_devdata = nfs_root_node; + return (error); +} + +int +net_close(f) + struct open_file *f; +{ + +#ifdef NETIF_DEBUG + if (debug) + printf("net_close: opens=%d\n", netdev_opens); +#endif + + /* On last close, do netif close, etc. */ + f->f_devdata = NULL; + /* Extra close call? */ + if (netdev_opens <= 0) + return (0); + netdev_opens--; + /* Not last close? */ + if (netdev_opens > 0) + return(0); + rootip.s_addr = 0; + if (netdev_sock >= 0) { + if (debug) + printf("net_close: calling netif_close()\n"); + netif_close(netdev_sock); + netdev_sock = -1; + } + return (0); +} + +int +net_ioctl() +{ + return EIO; +} + +int +net_strategy() +{ + return EIO; +} + +int +net_getparams(sock) + int sock; +{ + /* + * Get info for NFS boot: our IP address, our hostname, + * server IP address, and our root path on the server. + * There are two ways to do this: The old, Sun way, + * and the more modern, BOOTP way. (RFC951, RFC1048) + */ + +#ifdef SUN_BOOTPARAMS + /* Get our IP address. (rarp.c) */ + if (rarp_getipaddress(sock)) { + printf("net_open: RARP failed\n"); + return (EIO); + } +#else /* BOOTPARAMS */ + /* + * Get boot info using BOOTP. (RFC951, RFC1048) + * This also gets the server IP address, gateway, + * root path, etc. + */ + bootp(sock); + if (myip.s_addr == 0) { + printf("net_open: BOOTP failed\n"); + return (EIO); + } +#endif /* BOOTPARAMS */ + + printf("boot: client addr: %s\n", inet_ntoa(myip)); + +#ifdef SUN_BOOTPARAMS + /* Get our hostname, server IP address, gateway. */ + if (bp_whoami(sock)) { + printf("net_open: bootparam/whoami RPC failed\n"); + return (EIO); + } +#endif /* BOOTPARAMS */ + + printf("boot: client name: %s\n", hostname); + if (gateip.s_addr) { + printf("boot: subnet mask: %s\n", intoa(netmask)); + printf("boot: net gateway: %s\n", inet_ntoa(gateip)); + } + +#ifdef SUN_BOOTPARAMS + /* Get the root pathname. */ + if (bp_getfile(sock, "root", &rootip, rootpath)) { + printf("net_open: bootparam/getfile RPC failed\n"); + return (EIO); + } +#endif /* BOOTPARAMS */ + + printf("boot: server addr: %s\n", inet_ntoa(rootip)); + printf("boot: server path: %s\n", rootpath); + + return (0); +} diff --git a/sys/arch/alpha/stand/netboot/dev_net.h b/sys/arch/alpha/stand/netboot/dev_net.h new file mode 100644 index 00000000000..3e3d4b091d6 --- /dev/null +++ b/sys/arch/alpha/stand/netboot/dev_net.h @@ -0,0 +1,8 @@ +/* $OpenBSD: dev_net.h,v 1.1 1996/10/30 22:40:53 niklas Exp $ */ + + +int net_open __P((struct open_file *, ...)); +int net_close __P((struct open_file *)); +int net_ioctl(); +int net_strategy(); + diff --git a/sys/arch/alpha/stand/netboot/devopen.c b/sys/arch/alpha/stand/netboot/devopen.c new file mode 100644 index 00000000000..601960fcef4 --- /dev/null +++ b/sys/arch/alpha/stand/netboot/devopen.c @@ -0,0 +1,162 @@ +/* $OpenBSD: devopen.c,v 1.1 1996/10/30 22:40:54 niklas Exp $ */ +/* $NetBSD: devopen.c,v 1.1 1996/09/18 20:03:09 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * 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. + * + * @(#)devopen.c 8.1 (Berkeley) 6/10/93 + */ + +#include <stand.h> + +/* + * Decode the string 'fname', open the device and return the remaining + * file name if any. + */ +devopen(f, fname, file) + struct open_file *f; + const char *fname; + char **file; /* out */ +{ + register char *cp; + register char *ncp; + register struct devsw *dp; + register int c, i; + int ctlr = 0, unit = 0, part = 0; + char namebuf[20]; + int rc; + + cp = (char *)fname; + ncp = namebuf; + +#if 0 + /* look for a string like '5/rz0/vmunix' or '5/rz3f/vmunix */ + if ((c = *cp) >= '0' && c <= '9') { + ctlr = c - '0'; + /* skip the '/' */ + if (*++cp != '/') + return (ENXIO); + cp++; + while ((c = *cp) != '\0') { + if (c == '/') + break; + if (c >= '0' && c <= '9') { + /* read unit number */ + unit = c - '0'; + + /* look for a partition */ + if ((c = *++cp) >= 'a' && c <= 'h') { + part = c - 'a'; + c = *++cp; + } + if (c != '/') + return (ENXIO); + break; + } + if (ncp < namebuf + sizeof(namebuf) - 1) + *ncp++ = c; + cp++; + } + *ncp = '\0'; + /* + * XXX + * pulling strchr from the C library, should pull from libkern. + */ + } else if (strchr(cp, '(')) { + /* expect a string like 'rz(0,0,0)vmunix' */ + while ((c = *cp) != '\0') { + if (c == '(') { + cp++; + break; + } + if (ncp < namebuf + sizeof(namebuf) - 1) + *ncp++ = c; + cp++; + } + + /* get controller number */ + if ((c = *cp) >= '0' && c <= '9') { + ctlr = c - '0'; + c = *++cp; + } + + if (c == ',') { + /* get SCSI device number */ + if ((c = *++cp) >= '0' && c <= '9') { + unit = c - '0'; + c = *++cp; + } + + if (c == ',') { + /* get partition number */ + if ((c = *++cp) >= '0' && c <= '9') { + part = c - '0'; + c = *++cp; + } + } + } + if (c != ')') + return (ENXIO); + cp++; + *ncp = '\0'; + } else { +#endif + dp = devsw; + ctlr = unit = part = 0; + goto fnd; +#if 0 + } + + for (dp = devsw, i = 0; i < ndevs; dp++, i++) + if (dp->dv_name && strcmp(namebuf, dp->dv_name) == 0) + goto fnd; + printf("Unknown device '%s'\nKnown devices are:", namebuf); + for (dp = devsw, i = 0; i < ndevs; dp++, i++) + if (dp->dv_name) + printf(" %s", dp->dv_name); + printf("\n"); + return (ENXIO); +#endif + +fnd: + rc = (dp->dv_open)(f, ctlr, unit, part); + if (rc) + return (rc); + + f->f_dev = dp; + if (file && *cp != '\0') + *file = cp; + return (0); +} diff --git a/sys/arch/alpha/stand/netboot/getsecs.c b/sys/arch/alpha/stand/netboot/getsecs.c new file mode 100644 index 00000000000..07ca9e539d1 --- /dev/null +++ b/sys/arch/alpha/stand/netboot/getsecs.c @@ -0,0 +1,34 @@ +/* $OpenBSD: getsecs.c,v 1.1 1996/10/30 22:40:55 niklas Exp $ */ + +#include <sys/param.h> +#include "include/prom.h" +#include "include/rpb.h" + +int +getsecs() +{ + static long tnsec; + static long lastpcc, wrapsecs; + long curpcc, pccdiff; + + if (tnsec == 0) { + tnsec = 1; + lastpcc = alpha_rpcc() & 0xffffffff; + wrapsecs = (0xffffffff / + ((struct rpb *)HWRPB_ADDR)->rpb_cc_freq) + 1; + +#if 0 + printf("getsecs: cc freq = %d, time to wrap = %d\n", + ((struct rpb *)HWRPB_ADDR)->rpb_cc_freq, wrapsecs); +#endif + } + + curpcc = alpha_rpcc() & 0xffffffff; + if (curpcc < lastpcc) + curpcc += 0x100000000; + + tnsec += ((curpcc - lastpcc) * 1000000000) / ((struct rpb *)HWRPB_ADDR)->rpb_cc_freq; + lastpcc = curpcc; + + return (tnsec / 1000000000); +} diff --git a/sys/arch/alpha/stand/netboot/if_prom.c b/sys/arch/alpha/stand/netboot/if_prom.c new file mode 100644 index 00000000000..97664bb66ff --- /dev/null +++ b/sys/arch/alpha/stand/netboot/if_prom.c @@ -0,0 +1,201 @@ +/* $OpenBSD: if_prom.c,v 1.1 1996/10/30 22:40:56 niklas Exp $ */ +/* $NetBSD: if_prom.c,v 1.4 1996/10/02 21:18:49 cgd Exp $ */ + +/* + * Copyright (c) 1993 Adam Glass + * 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 Adam Glass. + * 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 Adam Glass ``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. + */ + +#include <sys/param.h> +#include <sys/types.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> + +#include "netif.h" +#include "include/prom.h" +#include "lib/libkern/libkern.h" + +int prom_probe(); +int prom_match(); +void prom_init(); +int prom_get(); +int prom_put(); +void prom_end(); + +extern struct netif_stats prom_stats[]; + +struct netif_dif prom_ifs[] = { +/* dif_unit dif_nsel dif_stats dif_private */ +{ 0, 1, &prom_stats[0], 0, }, +}; + +struct netif_stats prom_stats[NENTS(prom_ifs)]; + +struct netif_driver prom_netif_driver = { + "prom", /* netif_bname */ + prom_match, /* netif_match */ + prom_probe, /* netif_probe */ + prom_init, /* netif_init */ + prom_get, /* netif_get */ + prom_put, /* netif_put */ + prom_end, /* netif_end */ + prom_ifs, /* netif_ifs */ + NENTS(prom_ifs) /* netif_nifs */ +}; + +int netfd; + +int +prom_match(nif, machdep_hint) + struct netif *nif; + void *machdep_hint; +{ + + return (1); +} + +int +prom_probe(nif, machdep_hint) + struct netif *nif; + void *machdep_hint; +{ + + return 0; +} + +int +prom_put(desc, pkt, len) + struct iodesc *desc; + void *pkt; + int len; +{ + + prom_write(netfd, len, pkt, 0); + + return len; +} + + +int +prom_get(desc, pkt, len, timeout) + struct iodesc *desc; + void *pkt; + int len; + time_t timeout; +{ + prom_return_t ret; + time_t t; + int cc; + char hate[2000]; + + t = getsecs(); + cc = 0; + while (((getsecs() - t) < timeout) && !cc) { + ret.bits = prom_read(netfd, sizeof hate, hate, 0); + if (ret.u.status == 0) + cc += ret.u.retval; + } + cc = len; + bcopy(hate, pkt, cc); + + return cc; +} + +extern char *strchr(); + +void +prom_init(desc, machdep_hint) + struct iodesc *desc; + void *machdep_hint; +{ + prom_return_t ret; + char devname[64]; + int devlen, i; + char *enet_addr; + + ret.bits = prom_getenv(PROM_E_BOOTED_DEV, devname, sizeof(devname)); + devlen = ret.u.retval; + + /* Ethernet address is the 9th component of the booted_dev string. */ + enet_addr = devname; + for (i = 0; i < 8; i++) { + enet_addr = strchr(enet_addr, ' '); + if (enet_addr == NULL) { + printf("Boot device name does not contain ethernet address.\n"); + goto punt; + } + enet_addr++; + } + if (enet_addr != NULL) { + int hv, lv; + +#define dval(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ + (((c) >= 'A' && (c) <= 'F') ? (10 + (c) - 'A') : \ + (((c) >= 'a' && (c) <= 'f') ? (10 + (c) - 'a') : -1))) + + for (i = 0; i < 6; i++) { + hv = dval(*enet_addr); enet_addr++; + lv = dval(*enet_addr); enet_addr++; + enet_addr++; + + if (hv == -1 || lv == -1) { + printf("Bogus ethernet address.\n"); + goto punt; + } + + desc->myea[i] = (hv << 4) | lv; + } +#undef dval + } + + printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea)); + + ret.bits = prom_open(devname, devlen + 1); + if (ret.u.status) { + printf("prom_init: open failed: %d\n", ret.u.status); + goto punt; + } + netfd = ret.u.retval; + return; + +punt: + printf("Boot device name was: \"%s\"\n", devname); + printf("\n"); + printf("Your firmware may be too old to network-boot OpenBSD/Alpha.\n"); + halt(); +} + +void +prom_end(nif) + struct netif *nif; +{ + + prom_close(netfd); +} diff --git a/sys/arch/alpha/stand/netboot/netboot.c b/sys/arch/alpha/stand/netboot/netboot.c new file mode 100644 index 00000000000..ce23e0918b1 --- /dev/null +++ b/sys/arch/alpha/stand/netboot/netboot.c @@ -0,0 +1,99 @@ +/* $OpenBSD: netboot.c,v 1.1 1996/10/30 22:40:57 niklas Exp $ */ +/* $NetBSD: netboot.c,v 1.1 1996/09/18 20:03:12 cgd Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * 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. + * + * @(#)boot.c 8.1 (Berkeley) 6/10/93 + */ + +#include <lib/libsa/stand.h> +#include <lib/libkern/libkern.h> + +#include <sys/param.h> +#include <sys/exec.h> +#include <sys/exec_ecoff.h> + +#include <machine/prom.h> + +#define _KERNEL +#include "include/pte.h" + +int loadfile __P((char *, u_int64_t *)); + +char boot_file[128]; +char boot_flags[128]; + +extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; + +vm_offset_t ffp_save, ptbr_save; + +int debug; + +void +main() +{ + u_int64_t entry; + + /* Init prom callback vector. */ + init_prom_calls(); + + /* print a banner */ + printf("\n"); + printf("%s, Revision %s\n", bootprog_name, bootprog_rev); + printf("(%s, %s)\n", bootprog_maker, bootprog_date); + printf("\n"); + + /* switch to OSF pal code. */ + OSFpal(); + + printf("\n"); + + prom_getenv(PROM_E_BOOTED_FILE, boot_file, sizeof(boot_file)); + prom_getenv(PROM_E_BOOTED_OSFLAGS, boot_flags, sizeof(boot_flags)); + + if (boot_file[0] == '\0') + bcopy("bsd", boot_file, sizeof "bsd"); + + (void)printf("Boot: %s %s\n", boot_file, boot_flags); + + if (!loadfile(boot_file, &entry)) { + (void)printf("Entering kernel at 0x%lx...\n", entry); + (*(void (*)())entry)(ffp_save, ptbr_save, 0); + } + + (void)printf("Boot failed! Halting...\n"); + halt(); +} diff --git a/sys/arch/alpha/stand/netboot/newvers.sh b/sys/arch/alpha/stand/netboot/newvers.sh new file mode 100644 index 00000000000..9699e4f9ee7 --- /dev/null +++ b/sys/arch/alpha/stand/netboot/newvers.sh @@ -0,0 +1,45 @@ +#!/bin/sh - +# +# $OpenBSD: newvers.sh,v 1.1 1996/10/30 22:40:58 niklas Exp $ +# $NetBSD: newvers.sh,v 1.1 1996/09/18 20:03:13 cgd Exp $ +# +# Copyright (c) 1984, 1986, 1990, 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. +# +# @(#)newvers.sh 8.1 (Berkeley) 4/20/94 + +u=${USER-root} h=`hostname` t=`date` +r=`head -1 $1 | awk ' { print $3 } '` + +echo "char bootprog_name[] = \"OpenBSD/Alpha Network Boot\";" > vers.c +echo "char bootprog_rev[] = \"${r}\";" >> vers.c +echo "char bootprog_date[] = \"${t}\";" >> vers.c +echo "char bootprog_maker[] = \"${u}@${h}\";" >> vers.c diff --git a/sys/arch/alpha/stand/netboot/rpcc.S b/sys/arch/alpha/stand/netboot/rpcc.S new file mode 100644 index 00000000000..598534d50bd --- /dev/null +++ b/sys/arch/alpha/stand/netboot/rpcc.S @@ -0,0 +1,10 @@ +/* $OpenBSD: rpcc.S,v 1.1 1996/10/30 22:40:59 niklas Exp $ */ +/* $NetBSD: rpcc.S,v 1.2 1996/10/02 21:18:50 cgd Exp $ */ + +#include <machine/asm.h> + + .text +LEAF(alpha_rpcc,1) + rpcc v0 + RET + END(alpha_rpcc) diff --git a/sys/arch/alpha/stand/netboot/version b/sys/arch/alpha/stand/netboot/version new file mode 100644 index 00000000000..16253a53f4d --- /dev/null +++ b/sys/arch/alpha/stand/netboot/version @@ -0,0 +1,5 @@ +$OpenBSD: version,v 1.1 1996/10/30 22:41:00 niklas Exp $ +$NetBSD: version,v 1.2 1996/10/02 21:26:17 cgd Exp $ + +1.1 Initial version +1.2 Cleaned and polished a bit diff --git a/sys/arch/alpha/stand/prom.c b/sys/arch/alpha/stand/prom.c index 79cee77d833..b8e524ee874 100644 --- a/sys/arch/alpha/stand/prom.c +++ b/sys/arch/alpha/stand/prom.c @@ -1,4 +1,4 @@ -/* $OpenBSD: prom.c,v 1.2 1996/07/29 23:01:24 niklas Exp $ */ +/* $OpenBSD: prom.c,v 1.3 1996/10/30 22:40:33 niklas Exp $ */ /* $NetBSD: prom.c,v 1.1 1995/11/23 02:39:07 cgd Exp $ */ /* diff --git a/sys/arch/alpha/stand/prom_disp.S b/sys/arch/alpha/stand/prom_disp.S index c6346865366..8b56160dc19 100644 --- a/sys/arch/alpha/stand/prom_disp.S +++ b/sys/arch/alpha/stand/prom_disp.S @@ -1,5 +1,5 @@ -/* $OpenBSD: prom_disp.S,v 1.3 1996/07/29 23:01:25 niklas Exp $ */ -/* $NetBSD: prom_disp.S,v 1.3 1996/04/12 06:09:38 cgd Exp $ */ +/* $OpenBSD: prom_disp.S,v 1.4 1996/10/30 22:40:34 niklas Exp $ */ +/* $NetBSD: prom_disp.S,v 1.5 1996/10/17 02:50:39 cgd Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -35,7 +35,7 @@ #endif .globl prom_dispatch_v - .comm prom_dispatch_v 16 + .comm prom_dispatch_v,16 .text .align 4 @@ -56,7 +56,7 @@ #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) - SETGP(pv) + LDGP(pv) lda sp, -DISPATCH_FRAME_SIZE(sp) stq ra, D_RA(sp) diff --git a/sys/arch/alpha/stand/puts.c b/sys/arch/alpha/stand/puts.c index 47ee3340751..06c0b066e38 100644 --- a/sys/arch/alpha/stand/puts.c +++ b/sys/arch/alpha/stand/puts.c @@ -1,4 +1,4 @@ -/* $OpenBSD: puts.c,v 1.2 1996/07/29 23:01:27 niklas Exp $ */ +/* $OpenBSD: puts.c,v 1.3 1996/10/30 22:40:35 niklas Exp $ */ void diff --git a/sys/arch/alpha/stand/start.S b/sys/arch/alpha/stand/start.S index 6990832353b..a3eb03974e4 100644 --- a/sys/arch/alpha/stand/start.S +++ b/sys/arch/alpha/stand/start.S @@ -1,5 +1,5 @@ -/* $OpenBSD: start.S,v 1.2 1996/07/29 23:01:28 niklas Exp $ */ -/* $NetBSD: start.S,v 1.1 1995/11/23 02:39:15 cgd Exp $ */ +/* $OpenBSD: start.S,v 1.3 1996/10/30 22:40:36 niklas Exp $ */ +/* $NetBSD: start.S,v 1.4 1996/10/17 02:50:40 cgd Exp $ */ /* * Mach Operating System @@ -45,21 +45,27 @@ #define ENTRY_FRAME 32 NESTED(start, 1, ENTRY_FRAME, ra, 0, 0) - br pv,1f -1: SETGP(pv) + br pv,Lstartgp +Lstartgp: + LDGP(pv) #ifndef PRIMARY_BOOTBLOCK lda sp,start /* start stack below text */ lda sp,-ENTRY_FRAME(sp) #endif +#ifdef ECOFF_COMPAT lda a0,_EDATA +#else + lda a0,_edata +#endif lda a1,_end subq a1,a0,a1 CALL(bzero) CALL(main) /* transfer to C */ +XLEAF(_rtt, 0) XLEAF(halt, 0) call_pal PAL_halt /* halt if we ever return */ END(start) diff --git a/sys/arch/alpha/tc/cfb.c b/sys/arch/alpha/tc/cfb.c index 3db8a4d2783..0f78f75e769 100644 --- a/sys/arch/alpha/tc/cfb.c +++ b/sys/arch/alpha/tc/cfb.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cfb.c,v 1.2 1996/07/29 23:01:56 niklas Exp $ */ -/* $NetBSD: cfb.c,v 1.1 1996/05/01 23:25:03 cgd Exp $ */ +/* $OpenBSD: cfb.c,v 1.3 1996/10/30 22:41:01 niklas Exp $ */ +/* $NetBSD: cfb.c,v 1.5 1996/10/13 03:00:27 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -57,7 +57,7 @@ int cfbmatch __P((struct device *, void *, void *)); void cfbattach __P((struct device *, struct device *, void *)); -int cfbprint __P((void *, char *)); +int cfbprint __P((void *, /* const */ char *)); struct cfattach cfb_ca = { sizeof(struct cfb_softc), cfbmatch, cfbattach, @@ -89,7 +89,6 @@ cfbmatch(parent, match, aux) struct device *parent; void *match, *aux; { - struct cfdata *cf = match; struct tc_attach_args *ta = aux; if (strncmp("PMAG-BA ", ta->ta_modname, TC_ROM_LLEN) != 0) @@ -109,7 +108,7 @@ cfb_getdevconfig(dense_addr, dc) int i; dc->dc_vaddr = dense_addr; - dc->dc_paddr = k0segtophys(dc->dc_vaddr); /* XXX */ + dc->dc_paddr = ALPHA_K0SEG_TO_PHYS(dc->dc_vaddr); /* XXX */ dc->dc_size = CFB_SIZE; ramdacregp = (char *)dc->dc_vaddr + CFB_RAMDAC_OFFSET; @@ -169,7 +168,6 @@ cfbattach(parent, self, aux) struct wscons_attach_args waa; struct wscons_odev_spec *wo; int console; - char *x; console = 0; /* XXX */ if (console) @@ -208,7 +206,7 @@ cfbattach(parent, self, aux) int cfbprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { if (pnp) diff --git a/sys/arch/alpha/tc/cfbvar.h b/sys/arch/alpha/tc/cfbvar.h index 8434cf92910..73a514ece37 100644 --- a/sys/arch/alpha/tc/cfbvar.h +++ b/sys/arch/alpha/tc/cfbvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cfbvar.h,v 1.2 1996/07/29 23:01:58 niklas Exp $ */ +/* $OpenBSD: cfbvar.h,v 1.3 1996/10/30 22:41:03 niklas Exp $ */ /* $NetBSD: cfbvar.h,v 1.1 1996/05/01 23:25:04 cgd Exp $ */ /* diff --git a/sys/arch/alpha/tc/esp.c b/sys/arch/alpha/tc/esp.c index 5e6cfb9fb8d..cb18590130c 100644 --- a/sys/arch/alpha/tc/esp.c +++ b/sys/arch/alpha/tc/esp.c @@ -1,5 +1,38 @@ -/* $OpenBSD: esp.c,v 1.5 1996/10/18 16:12:01 niklas Exp $ */ -/* $NetBSD: esp.c,v 1.8.4.1 1996/06/05 00:39:03 cgd Exp $ */ +/* $OpenBSD: esp.c,v 1.6 1996/10/30 22:41:04 niklas Exp $ */ +/* $NetBSD: esp.c,v 1.22 1996/10/15 21:30:19 mycroft Exp $ */ + +#ifdef __sparc__ +#define SPARC_DRIVER +#endif + +/* + * Copyright (c) 1996 Charles M. Hannum. 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 Charles M. Hannum. + * 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. + */ /* * Copyright (c) 1994 Peter Galbavy @@ -17,7 +50,7 @@ * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Peter Galbavy - * 4. The name of the author may not be used to endorse or promote products + * 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 @@ -66,7 +99,7 @@ #include <sparc/dev/espreg.h> #include <sparc/dev/espvar.h> #else -#include <machine/autoconf.h> +#include <machine/autoconf.h> /* badaddr() prototype */ #include <dev/tc/tcvar.h> #include <alpha/tc/tcdsvar.h> #include <alpha/tc/espreg.h> @@ -76,33 +109,39 @@ int esp_debug = 0; /*ESP_SHOWPHASE|ESP_SHOWMISC|ESP_SHOWTRAC|ESP_SHOWCMDS;*/ /*static*/ void espattach __P((struct device *, struct device *, void *)); -/*static*/ int espmatch __P((struct device *, void *, void *)); /*static*/ int espprint __P((void *, char *)); +/*static*/ int espmatch __P((struct device *, void *, void *)); +/*static*/ u_int esp_adapter_info __P((struct esp_softc *)); /*static*/ void espreadregs __P((struct esp_softc *)); -/*static*/ void espselect __P((struct esp_softc *, - u_char, u_char, u_char *, u_char)); +/*static*/ void esp_select __P((struct esp_softc *, struct esp_ecb *)); +/*static*/ int esp_reselect __P((struct esp_softc *, int)); /*static*/ void esp_scsi_reset __P((struct esp_softc *)); /*static*/ void esp_reset __P((struct esp_softc *)); /*static*/ void esp_init __P((struct esp_softc *, int)); /*static*/ int esp_scsi_cmd __P((struct scsi_xfer *)); -/*static*/ int esp_poll __P((struct esp_softc *, struct ecb *)); +/*static*/ int esp_poll __P((struct esp_softc *, struct scsi_xfer *, int)); /*static*/ void esp_sched __P((struct esp_softc *)); -/*static*/ void esp_done __P((struct ecb *)); +/*static*/ void esp_done __P((struct esp_softc *, struct esp_ecb *)); /*static*/ void esp_msgin __P((struct esp_softc *)); /*static*/ void esp_msgout __P((struct esp_softc *)); /*static*/ int espintr __P((struct esp_softc *)); /*static*/ void esp_timeout __P((void *arg)); -/*static*/ void esp_abort __P((struct esp_softc *, struct ecb *)); -int esp_cpb2stp __P((struct esp_softc *, int)); -int esp_stp2cpb __P((struct esp_softc *, int)); +/*static*/ void esp_abort __P((struct esp_softc *, struct esp_ecb *)); +/*static*/ void esp_dequeue __P((struct esp_softc *, struct esp_ecb *)); +void esp_sense __P((struct esp_softc *, struct esp_ecb *)); +void esp_free_ecb __P((struct esp_softc *, struct esp_ecb *, int)); +struct esp_ecb *esp_get_ecb __P((struct esp_softc *, int)); +static inline int esp_stp2cpb __P((struct esp_softc *, int)); +static inline int esp_cpb2stp __P((struct esp_softc *, int)); +static inline void esp_setsync __P((struct esp_softc *, struct esp_tinfo *)); /* Linkup to the rest of the kernel */ struct cfattach esp_ca = { - sizeof(struct esp_softc), espmatch, espattach, + sizeof(struct esp_softc), espmatch, espattach }; struct cfdriver esp_cd = { - NULL, "esp", DV_DULL, + NULL, "esp", DV_DULL }; struct scsi_adapter esp_switch = { @@ -119,6 +158,9 @@ struct scsi_device esp_dev = { NULL, /* Use default 'done' routine */ }; +/* + * XXX should go when new generic scsiprint finds its way here + */ int espprint(aux, name) void *aux; @@ -170,7 +212,7 @@ espattach(parent, self, aux) struct esp_softc *sc = (void *)self; #ifdef SPARC_DRIVER struct bootpath *bp; - int dmachild = strncmp(parent->dv_xname, "espdma", 6) == 0; + int dmachild = strncmp(parent->dv_xname, "dma", 3) == 0; #endif #ifdef SPARC_DRIVER @@ -256,6 +298,8 @@ espattach(parent, self, aux) */ if (sc->sc_dma) sc->sc_dma->sc_esp = sc; + else + panic("espattach: no dma found"); } #else sc->sc_dma->sc_esp = sc; /* XXX */ @@ -276,7 +320,7 @@ espattach(parent, self, aux) printf(": ESP100"); sc->sc_rev = ESP100; } else { - sc->sc_cfg2 = ESPCFG2_SCSI2 | ESPCFG2_FE; + sc->sc_cfg2 = ESPCFG2_SCSI2; ESP_WRITE_REG(sc, ESP_CFG2, sc->sc_cfg2); sc->sc_cfg3 = 0; ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); @@ -286,6 +330,8 @@ espattach(parent, self, aux) printf(": ESP100A"); sc->sc_rev = ESP100A; } else { + /* ESPCFG2_FE enables > 64K transfers */ + sc->sc_cfg2 |= ESPCFG2_FE; sc->sc_cfg3 = 0; ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); printf(": ESP200"); @@ -318,14 +364,19 @@ espattach(parent, self, aux) */ switch (sc->sc_rev) { case ESP100: + sc->sc_maxxfer = 64 * 1024; sc->sc_minsync = 0; /* No synch on old chip? */ break; case ESP100A: + sc->sc_maxxfer = 64 * 1024; sc->sc_minsync = esp_cpb2stp(sc, 5); /* Min clocks/byte is 5 */ break; case ESP200: + sc->sc_maxxfer = 16 * 1024 * 1024; /* XXX - do actually set FAST* bits */ } +#else + sc->sc_maxxfer = 64 * 1024; #endif sc->sc_ccf = FREQTOCCF(sc->sc_freq); @@ -380,6 +431,7 @@ espattach(parent, self, aux) /* * fill in the prototype scsi_link. */ + /* sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE; */ sc->sc_link.adapter_softc = sc; sc->sc_link.adapter_target = sc->sc_id; sc->sc_link.adapter = &esp_switch; @@ -410,7 +462,7 @@ espattach(parent, self, aux) /* * Now try to attach all the sub-devices */ - config_found(self, &sc->sc_link, espprint); + config_found(self, &sc->sc_link, /* scsiprint */ espprint); /* XXX */ #ifdef SPARC_DRIVER bootpath_store(1, NULL); @@ -425,7 +477,7 @@ espattach(parent, self, aux) * After reset, registers are loaded with the defaults from the attach * routine above. */ -void +void esp_reset(sc) struct esp_softc *sc; { @@ -491,12 +543,13 @@ esp_init(sc, doreset) struct esp_softc *sc; int doreset; { - struct ecb *ecb; + struct esp_ecb *ecb; int r; ESP_TRACE(("[ESP_INIT(%d)] ", doreset)); - if (sc->sc_state == 0) { /* First time through */ + if (sc->sc_state == 0) { + /* First time through; initialize. */ TAILQ_INIT(&sc->ready_list); TAILQ_INIT(&sc->nexus_list); TAILQ_INIT(&sc->free_list); @@ -505,21 +558,21 @@ esp_init(sc, doreset) bzero(ecb, sizeof(sc->sc_ecb)); for (r = 0; r < sizeof(sc->sc_ecb) / sizeof(*ecb); r++) { TAILQ_INSERT_TAIL(&sc->free_list, ecb, chain); - ECB_SETQ(ecb, ECB_QFREE); ecb++; } bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo)); } else { - sc->sc_flags |= ESP_ABORTING; - sc->sc_state = ESP_IDLE; - if (sc->sc_nexus != NULL) { - sc->sc_nexus->xs->error = XS_TIMEOUT; - esp_done(sc->sc_nexus); + /* Cancel any active commands. */ + sc->sc_state = ESP_CLEANING; + if ((ecb = sc->sc_nexus) != NULL) { + ecb->xs->error = XS_DRIVER_STUFFUP; + untimeout(esp_timeout, ecb); + esp_done(sc, ecb); } - sc->sc_nexus = NULL; while ((ecb = sc->nexus_list.tqh_first) != NULL) { - ecb->xs->error = XS_TIMEOUT; - esp_done(ecb); + ecb->xs->error = XS_DRIVER_STUFFUP; + untimeout(esp_timeout, ecb); + esp_done(sc, ecb); } } @@ -530,24 +583,24 @@ esp_init(sc, doreset) sc->sc_phase = sc->sc_prevphase = INVALID_PHASE; for (r = 0; r < 8; r++) { - struct esp_tinfo *tp = &sc->sc_tinfo[r]; - - tp->flags = (sc->sc_minsync ? T_NEGOTIATE : 0) | - T_NEED_TO_RESET | (tp->flags & T_XXX); - tp->period = sc->sc_minsync; - tp->offset = 0; + struct esp_tinfo *ti = &sc->sc_tinfo[r]; +/* XXX - config flags per target: low bits: no reselect; high bits: no synch */ + int fl = sc->sc_dev.dv_cfdata->cf_flags; + + ti->flags = ((sc->sc_minsync && !(fl & (1<<(r+8)))) + ? T_NEGOTIATE : 0) | + ((fl & (1<<r)) ? T_RSELECTOFF : 0) | + T_NEED_TO_RESET; + ti->period = sc->sc_minsync; + ti->offset = 0; } - sc->sc_flags &= ~ESP_ABORTING; if (doreset) { sc->sc_state = ESP_SBR; ESPCMD(sc, ESPCMD_RSTSCSI); - return; + } else { + sc->sc_state = ESP_IDLE; } - - sc->sc_state = ESP_IDLE; - esp_sched(sc); - return; } /* @@ -587,9 +640,20 @@ espreadregs(sc) } /* + * Convert chip register Clock Per Byte value to Synchronous Transfer Period. + */ +static inline int +esp_cpb2stp(sc, cpb) + struct esp_softc *sc; + int cpb; +{ + return ((250 * cpb) / sc->sc_freq); +} + +/* * Convert Synchronous Transfer Period to chip register Clock Per Byte value. */ -int +static inline int esp_stp2cpb(sc, period) struct esp_softc *sc; int period; @@ -602,15 +666,19 @@ esp_stp2cpb(sc, period) return v; } -/* - * Convert chip register Clock Per Byte value to Synchronous Transfer Period. - */ -int -esp_cpb2stp(sc, cpb) +static inline void +esp_setsync(sc, ti) struct esp_softc *sc; - int cpb; + struct esp_tinfo *ti; { - return ((250 * cpb) / sc->sc_freq); + + if (ti->flags & T_SYNCMODE) { + ESP_WRITE_REG(sc, ESP_SYNCOFF, ti->offset); + ESP_WRITE_REG(sc, ESP_SYNCTP, esp_stp2cpb(sc, ti->period)); + } else { + ESP_WRITE_REG(sc, ESP_SYNCOFF, 0); + ESP_WRITE_REG(sc, ESP_SYNCTP, 0); + } } /* @@ -621,38 +689,36 @@ esp_cpb2stp(sc, cpb) * by DMA instead of programmed I/O soon. */ void -espselect(sc, target, lun, cmd, clen) +esp_select(sc, ecb) struct esp_softc *sc; - u_char target, lun; - u_char *cmd; - u_char clen; + struct esp_ecb *ecb; { + struct scsi_link *sc_link = ecb->xs->sc_link; + int target = sc_link->target; struct esp_tinfo *ti = &sc->sc_tinfo[target]; - int i; + u_char *cmd; + int clen; - ESP_TRACE(("[espselect(t%d,l%d,cmd:%x)] ", target, lun, *(u_char *)cmd)); + ESP_TRACE(("[esp_select(t%d,l%d,cmd:%x)] ", sc_link->target, sc_link->lun, ecb->cmd.opcode)); /* new state ESP_SELECTING */ sc->sc_state = ESP_SELECTING; + ESPCMD(sc, ESPCMD_FLUSH); + /* * The docs say the target register is never reset, and I * can't think of a better place to set it */ ESP_WRITE_REG(sc, ESP_SELID, target); - if (ti->flags & T_SYNCMODE) { - ESP_WRITE_REG(sc, ESP_SYNCOFF, ti->offset); - ESP_WRITE_REG(sc, ESP_SYNCTP, esp_stp2cpb(sc, ti->period)); - } else { - ESP_WRITE_REG(sc, ESP_SYNCOFF, 0); - ESP_WRITE_REG(sc, ESP_SYNCTP, 0); - } + esp_setsync(sc, ti); /* * Who am I. This is where we tell the target that we are * happy for it to disconnect etc. */ - ESP_WRITE_REG(sc, ESP_FIFO, MSG_IDENTIFY(lun, 1)); + ESP_WRITE_REG(sc, ESP_FIFO, + MSG_IDENTIFY(sc_link->lun, (ti->flags & T_RSELECTOFF)?0:1)); if (ti->flags & T_NEGOTIATE) { /* Arbitrate, select and stop after IDENTIFY message */ @@ -661,13 +727,60 @@ espselect(sc, target, lun, cmd, clen) } /* Now the command into the FIFO */ - for (i = 0; i < clen; i++) + cmd = (u_char *)&ecb->cmd; + clen = ecb->clen; + while (clen--) ESP_WRITE_REG(sc, ESP_FIFO, *cmd++); /* And get the targets attention */ ESPCMD(sc, ESPCMD_SELATN); } +void +esp_free_ecb(sc, ecb, flags) + struct esp_softc *sc; + struct esp_ecb *ecb; + int flags; +{ + int s; + + s = splbio(); + + ecb->flags = 0; + TAILQ_INSERT_HEAD(&sc->free_list, ecb, chain); + + /* + * If there were none, wake anybody waiting for one to come free, + * starting with queued entries. + */ + if (ecb->chain.tqe_next == 0) + wakeup(&sc->free_list); + + splx(s); +} + +struct esp_ecb * +esp_get_ecb(sc, flags) + struct esp_softc *sc; + int flags; +{ + struct esp_ecb *ecb; + int s; + + s = splbio(); + + while ((ecb = sc->free_list.tqh_first) == NULL && + (flags & SCSI_NOSLEEP) == 0) + tsleep(&sc->free_list, PRIBIO, "especb", 0); + if (ecb) { + TAILQ_REMOVE(&sc->free_list, ecb, chain); + ecb->flags |= ECB_ALLOC; + } + + splx(s); + return ecb; +} + /* * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS */ @@ -677,73 +790,70 @@ espselect(sc, target, lun, cmd, clen) * This function is called by the higher level SCSI-driver to queue/run * SCSI-commands. */ -int +int esp_scsi_cmd(xs) struct scsi_xfer *xs; { struct scsi_link *sc_link = xs->sc_link; struct esp_softc *sc = sc_link->adapter_softc; - struct ecb *ecb; + struct esp_ecb *ecb; int s, flags; - + ESP_TRACE(("[esp_scsi_cmd] ")); - ESP_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen, + ESP_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen, sc_link->target)); flags = xs->flags; - - /* Get a esp command block */ - s = splbio(); - ecb = sc->free_list.tqh_first; - if (ecb) { - TAILQ_REMOVE(&sc->free_list, ecb, chain); - ECB_SETQ(ecb, ECB_QNONE); - } - splx(s); - - if (ecb == NULL) { - ESP_MISC(("TRY_AGAIN_LATER")); + if ((ecb = esp_get_ecb(sc, flags)) == NULL) { + xs->error = XS_DRIVER_STUFFUP; return TRY_AGAIN_LATER; } /* Initialize ecb */ ecb->xs = xs; - bcopy(xs->cmd, &ecb->cmd, xs->cmdlen); - ecb->clen = xs->cmdlen; - ecb->daddr = xs->data; - ecb->dleft = xs->datalen; + ecb->timeout = xs->timeout; + + if (xs->flags & SCSI_RESET) { + ecb->flags |= ECB_RESET; + ecb->clen = 0; + ecb->dleft = 0; + } else { + bcopy(xs->cmd, &ecb->cmd, xs->cmdlen); + ecb->clen = xs->cmdlen; + ecb->daddr = xs->data; + ecb->dleft = xs->datalen; + } ecb->stat = 0; - + s = splbio(); - TAILQ_INSERT_TAIL(&sc->ready_list, ecb, chain); - ECB_SETQ(ecb, ECB_QREADY); - timeout(esp_timeout, ecb, (xs->timeout*hz)/1000); + TAILQ_INSERT_TAIL(&sc->ready_list, ecb, chain); if (sc->sc_state == ESP_IDLE) esp_sched(sc); splx(s); - if (flags & SCSI_POLL) { - /* Not allowed to use interrupts, use polling instead */ - return esp_poll(sc, ecb); - } - - ESP_MISC(("SUCCESSFULLY_QUEUED")); - return SUCCESSFULLY_QUEUED; + if ((flags & SCSI_POLL) == 0) + return SUCCESSFULLY_QUEUED; + /* Not allowed to use interrupts, use polling instead */ + if (esp_poll(sc, xs, ecb->timeout)) { + esp_timeout(ecb); + if (esp_poll(sc, xs, ecb->timeout)) + esp_timeout(ecb); + } + return COMPLETE; } /* * Used when interrupt driven I/O isn't allowed, e.g. during boot. */ int -esp_poll(sc, ecb) +esp_poll(sc, xs, count) struct esp_softc *sc; - struct ecb *ecb; + struct scsi_xfer *xs; + int count; { - struct scsi_xfer *xs = ecb->xs; - int count = xs->timeout * 100; ESP_TRACE(("[esp_poll] ")); while (count) { @@ -754,22 +864,16 @@ esp_poll(sc, ecb) if (ESP_READ_REG(sc, ESP_STAT) & ESPSTAT_INT) espintr(sc); #endif - if (xs->flags & ITSDONE) - break; - DELAY(10); + if ((xs->flags & ITSDONE) != 0) + return 0; if (sc->sc_state == ESP_IDLE) { ESP_TRACE(("[esp_poll: rescheduling] ")); esp_sched(sc); } + DELAY(1000); count--; } - - if (count == 0) { - ESP_MISC(("esp_poll: timeout")); - esp_timeout((caddr_t)ecb); - } - - return COMPLETE; + return 1; } @@ -787,46 +891,62 @@ void esp_sched(sc) struct esp_softc *sc; { + struct esp_ecb *ecb; struct scsi_link *sc_link; - struct ecb *ecb; - int t; - + struct esp_tinfo *ti; + ESP_TRACE(("[esp_sched] ")); if (sc->sc_state != ESP_IDLE) panic("esp_sched: not IDLE (state=%d)", sc->sc_state); - if (sc->sc_flags & ESP_ABORTING) - return; - /* * Find first ecb in ready queue that is for a target/lunit * combinations that is not busy. */ for (ecb = sc->ready_list.tqh_first; ecb; ecb = ecb->chain.tqe_next) { sc_link = ecb->xs->sc_link; - t = sc_link->target; - if (!(sc->sc_tinfo[t].lubusy & (1 << sc_link->lun))) { - struct esp_tinfo *ti = &sc->sc_tinfo[t]; - - if ((ecb->flags & ECB_QBITS) != ECB_QREADY) - panic("esp: busy entry on ready list"); + ti = &sc->sc_tinfo[sc_link->target]; + if ((ti->lubusy & (1 << sc_link->lun)) == 0) { TAILQ_REMOVE(&sc->ready_list, ecb, chain); - ECB_SETQ(ecb, ECB_QNONE); sc->sc_nexus = ecb; - sc->sc_flags = 0; - sc->sc_prevphase = INVALID_PHASE; - sc->sc_dp = ecb->daddr; - sc->sc_dleft = ecb->dleft; - ti->lubusy |= (1<<sc_link->lun); -/*XXX*/if (sc->sc_msgpriq) { - printf("esp: message queue not empty: %x!\n", sc->sc_msgpriq); -} -/*XXX*/sc->sc_msgpriq = sc->sc_msgout = 0; - espselect(sc, t, sc_link->lun, - (u_char *)&ecb->cmd, ecb->clen); + esp_select(sc, ecb); break; } else - ESP_MISC(("%d:%d busy\n", t, sc_link->lun)); + ESP_MISC(("%d:%d busy\n", + sc_link->target, sc_link->lun)); + } +} + +void +esp_sense(sc, ecb) + struct esp_softc *sc; + struct esp_ecb *ecb; +{ + struct scsi_xfer *xs = ecb->xs; + struct scsi_link *sc_link = xs->sc_link; + struct esp_tinfo *ti = &sc->sc_tinfo[sc_link->target]; + struct scsi_sense *ss = (void *)&ecb->cmd; + + ESP_MISC(("requesting sense ")); + /* Next, setup a request sense command block */ + bzero(ss, sizeof(*ss)); + ss->opcode = REQUEST_SENSE; + ss->byte2 = sc_link->lun << 5; + ss->length = sizeof(struct scsi_sense_data); + ecb->clen = sizeof(*ss); + ecb->daddr = (char *)&xs->sense; + ecb->dleft = sizeof(struct scsi_sense_data); + ecb->flags |= ECB_SENSE; + ti->senses++; + if (ecb->flags & ECB_NEXUS) + ti->lubusy &= ~(1 << sc_link->lun); + if (ecb == sc->sc_nexus) { + esp_select(sc, ecb); + } else { + esp_dequeue(sc, ecb); + TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain); + if (sc->sc_state == ESP_IDLE) + esp_sched(sc); } } @@ -834,57 +954,34 @@ esp_sched(sc) * POST PROCESSING OF SCSI_CMD (usually current) */ void -esp_done(ecb) - struct ecb *ecb; +esp_done(sc, ecb) + struct esp_softc *sc; + struct esp_ecb *ecb; { struct scsi_xfer *xs = ecb->xs; struct scsi_link *sc_link = xs->sc_link; - struct esp_softc *sc = sc_link->adapter_softc; struct esp_tinfo *ti = &sc->sc_tinfo[sc_link->target]; ESP_TRACE(("[esp_done(error:%x)] ", xs->error)); - untimeout(esp_timeout, ecb); - /* - * Now, if we've come here with no error code, i.e. we've kept the + * Now, if we've come here with no error code, i.e. we've kept the * initial XS_NOERROR, and the status code signals that we should - * check sense, we'll need to set up a request sense cmd block and - * push the command back into the ready queue *before* any other + * check sense, we'll need to set up a request sense cmd block and + * push the command back into the ready queue *before* any other * commands for this target/lunit, else we lose the sense info. * We don't support chk sense conditions for the request sense cmd. */ if (xs->error == XS_NOERROR) { - if ((ecb->flags & ECB_ABORTED) != 0) { - xs->error = XS_TIMEOUT; - } else if ((ecb->flags & ECB_CHKSENSE) != 0) { + if ((ecb->flags & ECB_ABORT) != 0) { + xs->error = XS_DRIVER_STUFFUP; + } else if ((ecb->flags & ECB_SENSE) != 0) { xs->error = XS_SENSE; } else if ((ecb->stat & ST_MASK) == SCSI_CHECK) { - struct scsi_sense *ss = (void *)&ecb->cmd; - ESP_MISC(("requesting sense ")); /* First, save the return values */ xs->resid = ecb->dleft; xs->status = ecb->stat; - /* Next, setup a request sense command block */ - bzero(ss, sizeof(*ss)); - ss->opcode = REQUEST_SENSE; - /*ss->byte2 = sc_link->lun << 5;*/ - ss->length = sizeof(struct scsi_sense_data); - ecb->clen = sizeof(*ss); - ecb->daddr = (char *)&xs->sense; - ecb->dleft = sizeof(struct scsi_sense_data); - ecb->flags |= ECB_CHKSENSE; -/*XXX - must take off queue here */ - TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain); - ECB_SETQ(ecb, ECB_QREADY); - ti->lubusy &= ~(1<<sc_link->lun); - ti->senses++; - timeout(esp_timeout, ecb, (xs->timeout*hz)/1000); - if (sc->sc_nexus == ecb) { - sc->sc_nexus = NULL; - sc->sc_state = ESP_IDLE; - esp_sched(sc); - } + esp_sense(sc, ecb); return; } else { xs->resid = ecb->dleft; @@ -895,52 +992,43 @@ esp_done(ecb) #ifdef ESP_DEBUG if (esp_debug & ESP_SHOWMISC) { - printf("err=0x%02x ",xs->error); - if (xs->error == XS_SENSE) { - printf("sense=%2x; ", xs->sense.error_code); - if (xs->sense.error_code == 0x70) - printf("extcode: %x; ", xs->sense.flags); - } - } - if ((xs->resid || xs->error > XS_SENSE) && esp_debug & ESP_SHOWMISC) { - if (xs->resid) - printf("esp_done: resid=%d\n", xs->resid); - if (xs->error) - printf("esp_done: error=%d\n", xs->error); + if (xs->resid != 0) + printf("resid=%d ", xs->resid); + if (xs->error == XS_SENSE) + printf("sense=0x%02x\n", xs->sense.error_code); + else + printf("error=%d\n", xs->error); } #endif /* * Remove the ECB from whatever queue it's on. */ - switch (ecb->flags & ECB_QBITS) { - case ECB_QNONE: - if (ecb != sc->sc_nexus) { - panic("%s: floating ecb", sc->sc_dev.dv_xname); - } + if (ecb->flags & ECB_NEXUS) + ti->lubusy &= ~(1 << sc_link->lun); + if (ecb == sc->sc_nexus) { + sc->sc_nexus = NULL; sc->sc_state = ESP_IDLE; - ti->lubusy &= ~(1<<sc_link->lun); esp_sched(sc); - break; - case ECB_QREADY: - TAILQ_REMOVE(&sc->ready_list, ecb, chain); - break; - case ECB_QNEXUS: - TAILQ_REMOVE(&sc->nexus_list, ecb, chain); - ti->lubusy &= ~(1<<sc_link->lun); - break; - case ECB_QFREE: - panic("%s: busy ecb on free list", sc->sc_dev.dv_xname); - break; - } - - /* Put it on the free list, and clear flags. */ - TAILQ_INSERT_HEAD(&sc->free_list, ecb, chain); - ecb->flags = ECB_QFREE; - + } else + esp_dequeue(sc, ecb); + + esp_free_ecb(sc, ecb, xs->flags); ti->cmds++; scsi_done(xs); - return; +} + +void +esp_dequeue(sc, ecb) + struct esp_softc *sc; + struct esp_ecb *ecb; +{ + + if (ecb->flags & ECB_NEXUS) { + TAILQ_REMOVE(&sc->nexus_list, ecb, chain); + } else { + TAILQ_REMOVE(&sc->ready_list, ecb, chain); + } } /* @@ -953,12 +1041,83 @@ esp_done(ecb) * else there will be an illegal command interrupt. */ #define esp_sched_msgout(m) \ - do { \ - ESP_MISC(("esp_sched_msgout %d ", m)); \ - ESPCMD(sc, ESPCMD_SETATN); \ - sc->sc_msgpriq |= (m); \ + do { \ + ESP_MISC(("esp_sched_msgout %d ", m)); \ + ESPCMD(sc, ESPCMD_SETATN); \ + sc->sc_flags |= ESP_ATN; \ + sc->sc_msgpriq |= (m); \ } while (0) +int +esp_reselect(sc, message) + struct esp_softc *sc; + int message; +{ + u_char selid, target, lun; + struct esp_ecb *ecb; + struct scsi_link *sc_link; + struct esp_tinfo *ti; + + /* + * The SCSI chip made a snapshot of the data bus while the reselection + * was being negotiated. This enables us to determine which target did + * the reselect. + */ + selid = sc->sc_selid & ~(1 << sc->sc_id); + if (selid & (selid - 1)) { + printf("%s: reselect with invalid selid %02x; sending DEVICE RESET\n", + sc->sc_dev.dv_xname, selid); + goto reset; + } + + /* + * Search wait queue for disconnected cmd + * The list should be short, so I haven't bothered with + * any more sophisticated structures than a simple + * singly linked list. + */ + target = ffs(selid) - 1; + lun = message & 0x07; + for (ecb = sc->nexus_list.tqh_first; ecb != NULL; + ecb = ecb->chain.tqe_next) { + sc_link = ecb->xs->sc_link; + if (sc_link->target == target && sc_link->lun == lun) + break; + } + if (ecb == NULL) { + printf("%s: reselect from target %d lun %d with no nexus; sending ABORT\n", + sc->sc_dev.dv_xname, target, lun); + goto abort; + } + + /* Make this nexus active again. */ + TAILQ_REMOVE(&sc->nexus_list, ecb, chain); + sc->sc_state = ESP_CONNECTED; + sc->sc_nexus = ecb; + ti = &sc->sc_tinfo[target]; + ti->lubusy |= (1 << lun); + esp_setsync(sc, ti); + + if (ecb->flags & ECB_RESET) + esp_sched_msgout(SEND_DEV_RESET); + else if (ecb->flags & ECB_ABORT) + esp_sched_msgout(SEND_ABORT); + + /* Do an implicit RESTORE POINTERS. */ + sc->sc_dp = ecb->daddr; + sc->sc_dleft = ecb->dleft; + + return (0); + +reset: + esp_sched_msgout(SEND_DEV_RESET); + return (1); + +abort: + esp_sched_msgout(SEND_ABORT); + return (1); +} + #define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80) #define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20) #define ISEXTMSG(m) ((m) == 1) @@ -974,7 +1133,7 @@ esp_msgin(sc) register struct esp_softc *sc; { register int v; - + ESP_TRACE(("[esp_msgin(curmsglen:%d)] ", sc->sc_imlen)); if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) == 0) { @@ -1003,7 +1162,6 @@ esp_msgin(sc) * Which target is reselecting us? (The ID bit really) */ sc->sc_selid = v; - sc->sc_selid &= ~(1<<sc->sc_id); ESP_MISC(("selid=0x%2x ", sc->sc_selid)); return; } @@ -1017,7 +1175,6 @@ esp_msgin(sc) */ if ((sc->sc_flags & ESP_DROP_MSGI)) { - ESPCMD(sc, ESPCMD_SETATN); ESPCMD(sc, ESPCMD_MSGOK); printf("<dropping msg byte %x>", sc->sc_imess[sc->sc_imlen]); @@ -1029,7 +1186,7 @@ esp_msgin(sc) sc->sc_flags |= ESP_DROP_MSGI; } else { sc->sc_imlen++; - /* + /* * This testing is suboptimal, but most * messages will be of the one byte variety, so * it should not effect performance @@ -1055,209 +1212,159 @@ gotit: * extended messages which total length is shorter than * ESP_MAX_MSG_LEN. Longer messages will be amputated. */ - if (sc->sc_state == ESP_HASNEXUS) { - struct ecb *ecb = sc->sc_nexus; - struct esp_tinfo *ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; + switch (sc->sc_state) { + struct esp_ecb *ecb; + struct scsi_link *sc_link; + struct esp_tinfo *ti; + + case ESP_CONNECTED: + ecb = sc->sc_nexus; + ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; switch (sc->sc_imess[0]) { case MSG_CMDCOMPLETE: ESP_MSGS(("cmdcomplete ")); if (sc->sc_dleft < 0) { - struct scsi_link *sc_link = ecb->xs->sc_link; - printf("esp: %d extra bytes from %d:%d\n", - -sc->sc_dleft, - sc_link->target, sc_link->lun); + sc_link = ecb->xs->sc_link; + printf("%s: %d extra bytes from %d:%d\n", + sc->sc_dev.dv_xname, -sc->sc_dleft, + sc_link->target, sc_link->lun); sc->sc_dleft = 0; } ecb->xs->resid = ecb->dleft = sc->sc_dleft; - sc->sc_flags |= ESP_BUSFREE_OK; + sc->sc_state = ESP_CMDCOMPLETE; break; case MSG_MESSAGE_REJECT: if (esp_debug & ESP_SHOWMSGS) printf("%s: our msg rejected by target\n", sc->sc_dev.dv_xname); -#if 0 /* XXX - must remember last message */ -printf("<<target%d: MSG_MESSAGE_REJECT>>", ecb->xs->sc_link->target); -ti->period = ti->offset = 0; -sc->sc_flags &= ~ESP_SYNCHNEGO; -ti->flags &= ~T_NEGOTIATE; -#endif - if (sc->sc_flags & ESP_SYNCHNEGO) { - ti->period = ti->offset = 0; + switch (sc->sc_msgout) { + case SEND_SDTR: sc->sc_flags &= ~ESP_SYNCHNEGO; - ti->flags &= ~T_NEGOTIATE; + ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE); + esp_setsync(sc, ti); + break; + case SEND_INIT_DET_ERR: + goto abort; } - /* Not all targets understand INITIATOR_DETECTED_ERR */ - if (sc->sc_msgout == SEND_INIT_DET_ERR) - esp_sched_msgout(SEND_ABORT); break; + case MSG_NOOP: ESP_MSGS(("noop ")); break; + case MSG_DISCONNECT: ESP_MSGS(("disconnect ")); ti->dconns++; - sc->sc_flags |= ESP_DISCON; - sc->sc_flags |= ESP_BUSFREE_OK; - break; + sc->sc_state = ESP_DISCONNECT; + if ((ecb->xs->sc_link->quirks & SDEV_AUTOSAVE) == 0) + break; + /*FALLTHROUGH*/ + case MSG_SAVEDATAPOINTER: ESP_MSGS(("save datapointer ")); - ecb->dleft = sc->sc_dleft; ecb->daddr = sc->sc_dp; + ecb->dleft = sc->sc_dleft; break; + case MSG_RESTOREPOINTERS: ESP_MSGS(("restore datapointer ")); - if (!ecb) { - esp_sched_msgout(SEND_ABORT); - printf("%s: no DATAPOINTERs to restore\n", - sc->sc_dev.dv_xname); - break; - } sc->sc_dp = ecb->daddr; sc->sc_dleft = ecb->dleft; break; - case MSG_PARITY_ERROR: -printf("<<esp:target%d: MSG_PARITY_ERROR>>", ecb->xs->sc_link->target); - break; + case MSG_EXTENDED: ESP_MSGS(("extended(%x) ", sc->sc_imess[2])); switch (sc->sc_imess[2]) { case MSG_EXT_SDTR: ESP_MSGS(("SDTR period %d, offset %d ", sc->sc_imess[3], sc->sc_imess[4])); - /*XXX*/if (ti->flags & T_XXX) { - printf("%s:%d: rejecting SDTR\n", - "esp", ecb->xs->sc_link->target); - sc->sc_flags &= ~ESP_SYNCHNEGO; - esp_sched_msgout(SEND_REJECT); - break; - } + if (sc->sc_imess[1] != 3) + goto reject; ti->period = sc->sc_imess[3]; ti->offset = sc->sc_imess[4]; - if (sc->sc_minsync == 0) { - /* We won't do synch */ - ti->offset = 0; - esp_sched_msgout(SEND_SDTR); - } else if (ti->offset == 0) { - printf("%s:%d: async\n", "esp", - ecb->xs->sc_link->target); - ti->offset = 0; - sc->sc_flags &= ~ESP_SYNCHNEGO; - } else if (ti->period > 124) { + ti->flags &= ~T_NEGOTIATE; + if (sc->sc_minsync == 0 || + ti->offset == 0 || + ti->period > 124) { printf("%s:%d: async\n", "esp", ecb->xs->sc_link->target); - ti->offset = 0; - esp_sched_msgout(SEND_SDTR); + if ((sc->sc_flags&ESP_SYNCHNEGO) == 0) { + /* target initiated negotiation */ + ti->offset = 0; + ti->flags &= ~T_SYNCMODE; + esp_sched_msgout(SEND_SDTR); + } else { + /* we are async */ + ti->flags &= ~T_SYNCMODE; + } } else { int r = 250/ti->period; int s = (100*250)/ti->period - 100*r; int p; + p = esp_stp2cpb(sc, ti->period); ti->period = esp_cpb2stp(sc, p); - if ((sc->sc_flags&ESP_SYNCHNEGO) == 0) { - /* Target initiated negotiation */ - sc->sc_flags |= ESP_SYNCHNEGO; - if (ti->flags & T_SYNCMODE) { - sc_print_addr(ecb->xs->sc_link); #ifdef ESP_DEBUG - printf("%s:%d: dropping out of sync mode\n"); + sc_print_addr(ecb->xs->sc_link); + printf("max sync rate %d.%02dMb/s\n", + r, s); #endif - } + if ((sc->sc_flags&ESP_SYNCHNEGO) == 0) { + /* target initiated negotiation */ + if (ti->period < sc->sc_minsync) + ti->period = sc->sc_minsync; + if (ti->offset > 15) + ti->offset = 15; ti->flags &= ~T_SYNCMODE; - ESP_WRITE_REG(sc, - ESP_SYNCOFF, 0); esp_sched_msgout(SEND_SDTR); } else { /* we are sync */ - sc->sc_flags &= ~ESP_SYNCHNEGO; - ESP_WRITE_REG(sc, - ESP_SYNCOFF, ti->offset); - ESP_WRITE_REG(sc, - ESP_SYNCTP, p); ti->flags |= T_SYNCMODE; - sc_print_addr(ecb->xs->sc_link); -#ifdef ESP_DEBUG - printf("max sync " - "rate %d.%02dMb/s\n", - r, s); -#endif } } - ti->flags &= ~T_NEGOTIATE; - break; - default: /* Extended messages we don't handle */ - ESPCMD(sc, ESPCMD_SETATN); + sc->sc_flags &= ~ESP_SYNCHNEGO; + esp_setsync(sc, ti); break; + + default: + printf("%s: unrecognized MESSAGE EXTENDED; sending REJECT\n", + sc->sc_dev.dv_xname); + goto reject; } break; + default: ESP_MSGS(("ident ")); - /* thanks for that ident... */ - if (!MSG_ISIDENTIFY(sc->sc_imess[0])) { - ESP_MISC(("unknown ")); -printf("%s: unimplemented message: %d\n", sc->sc_dev.dv_xname, sc->sc_imess[0]); - ESPCMD(sc, ESPCMD_SETATN); - } + printf("%s: unrecognized MESSAGE; sending REJECT\n", + sc->sc_dev.dv_xname); + reject: + esp_sched_msgout(SEND_REJECT); break; } - } else if (sc->sc_state == ESP_RESELECTED) { - struct scsi_link *sc_link; - struct ecb *ecb; - struct esp_tinfo *ti; - u_char lunit; - - if (MSG_ISIDENTIFY(sc->sc_imess[0])) { /* Identify? */ - ESP_MISC(("searching ")); - /* - * Search wait queue for disconnected cmd - * The list should be short, so I haven't bothered with - * any more sophisticated structures than a simple - * singly linked list. - */ - lunit = sc->sc_imess[0] & 0x07; - for (ecb = sc->nexus_list.tqh_first; ecb; - ecb = ecb->chain.tqe_next) { - sc_link = ecb->xs->sc_link; - if (sc_link->lun == lunit && - sc->sc_selid == (1<<sc_link->target)) { - TAILQ_REMOVE(&sc->nexus_list, ecb, - chain); - ECB_SETQ(ecb, ECB_QNONE); - break; - } - } + break; - if (!ecb) { /* Invalid reselection! */ - esp_sched_msgout(SEND_ABORT); - printf("esp: invalid reselect (idbit=0x%2x)\n", - sc->sc_selid); - } else { /* Reestablish nexus */ - /* - * Setup driver data structures and - * do an implicit RESTORE POINTERS - */ - ti = &sc->sc_tinfo[sc_link->target]; - sc->sc_nexus = ecb; - sc->sc_dp = ecb->daddr; - sc->sc_dleft = ecb->dleft; - sc->sc_tinfo[sc_link->target].lubusy - |= (1<<sc_link->lun); - ESP_WRITE_REG(sc, ESP_SYNCOFF, ti->offset); - ESP_WRITE_REG(sc, ESP_SYNCTP, - esp_stp2cpb(sc, ti->period)); - ESP_MISC(("... found ecb")); - sc->sc_state = ESP_HASNEXUS; - } - } else { - printf("%s: bogus reselect (no IDENTIFY) %0x2x\n", - sc->sc_dev.dv_xname, sc->sc_selid); - esp_sched_msgout(SEND_DEV_RESET); + case ESP_RESELECTED: + if (!MSG_ISIDENTIFY(sc->sc_imess[0])) { + printf("%s: reselect without IDENTIFY; sending DEVICE RESET\n", + sc->sc_dev.dv_xname); + goto reset; } - } else { /* Neither ESP_HASNEXUS nor ESP_RESELECTED! */ - printf("%s: unexpected message in; will send DEV_RESET\n", + + (void) esp_reselect(sc, sc->sc_imess[0]); + break; + + default: + printf("%s: unexpected MESSAGE IN; sending DEVICE RESET\n", sc->sc_dev.dv_xname); + reset: esp_sched_msgout(SEND_DEV_RESET); + break; + + abort: + esp_sched_msgout(SEND_ABORT); + break; } /* Ack last message byte */ @@ -1277,18 +1384,37 @@ esp_msgout(sc) register struct esp_softc *sc; { struct esp_tinfo *ti; - struct ecb *ecb; + struct esp_ecb *ecb; + size_t size; ESP_TRACE(("[esp_msgout(priq:%x, prevphase:%x)]", sc->sc_msgpriq, sc->sc_prevphase)); - if (sc->sc_prevphase != MESSAGE_OUT_PHASE) { + if (sc->sc_flags & ESP_ATN) { + if (sc->sc_prevphase != MESSAGE_OUT_PHASE) { + new: + ESPCMD(sc, ESPCMD_FLUSH); + DELAY(1); + sc->sc_msgoutq = 0; + sc->sc_omlen = 0; + } + } else { + if (sc->sc_prevphase == MESSAGE_OUT_PHASE) { + esp_sched_msgout(sc->sc_msgoutq); + goto new; + } else { + printf("esp at line %d: unexpected MESSAGE OUT phase\n", __LINE__); + } + } + + if (sc->sc_omlen == 0) { /* Pick up highest priority message */ sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq; + sc->sc_msgoutq |= sc->sc_msgout; + sc->sc_msgpriq &= ~sc->sc_msgout; sc->sc_omlen = 1; /* "Default" message len */ switch (sc->sc_msgout) { case SEND_SDTR: ecb = sc->sc_nexus; - sc->sc_flags |= ESP_SYNCHNEGO; ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; sc->sc_omess[0] = MSG_EXTENDED; sc->sc_omess[1] = 3; @@ -1296,17 +1422,21 @@ esp_msgout(sc) sc->sc_omess[3] = ti->period; sc->sc_omess[4] = ti->offset; sc->sc_omlen = 5; + if ((sc->sc_flags & ESP_SYNCHNEGO) == 0) { + ti->flags |= T_SYNCMODE; + esp_setsync(sc, ti); + } break; case SEND_IDENTIFY: - if (sc->sc_state != ESP_HASNEXUS) { - printf("esp at line %d: no nexus", __LINE__); + if (sc->sc_state != ESP_CONNECTED) { + printf("esp at line %d: no nexus\n", __LINE__); } ecb = sc->sc_nexus; sc->sc_omess[0] = MSG_IDENTIFY(ecb->xs->sc_link->lun,0); break; case SEND_DEV_RESET: + sc->sc_flags |= ESP_ABORTING; sc->sc_omess[0] = MSG_BUS_DEV_RESET; - sc->sc_flags |= ESP_BUSFREE_OK; ecb = sc->sc_nexus; ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; ti->flags &= ~T_SYNCMODE; @@ -1316,8 +1446,8 @@ esp_msgout(sc) sc->sc_omess[0] = MSG_PARITY_ERROR; break; case SEND_ABORT: + sc->sc_flags |= ESP_ABORTING; sc->sc_omess[0] = MSG_ABORT; - sc->sc_flags |= ESP_BUSFREE_OK; break; case SEND_INIT_DET_ERR: sc->sc_omess[0] = MSG_INITIATOR_DET_ERR; @@ -1326,6 +1456,8 @@ esp_msgout(sc) sc->sc_omess[0] = MSG_MESSAGE_REJECT; break; default: + ESPCMD(sc, ESPCMD_RSTATN); + sc->sc_flags &= ~ESP_ATN; sc->sc_omess[0] = MSG_NOOP; break; } @@ -1334,16 +1466,24 @@ esp_msgout(sc) #if 1 /* (re)send the message */ - DMA_START(sc->sc_dma, &sc->sc_omp, &sc->sc_omlen, 0); + size = min(sc->sc_omlen, sc->sc_maxxfer); + DMA_SETUP(sc->sc_dma, &sc->sc_omp, &sc->sc_omlen, 0, &size); + /* Program the SCSI counter */ + ESP_WRITE_REG(sc, ESP_TCL, size); + ESP_WRITE_REG(sc, ESP_TCM, size >> 8); + if (sc->sc_cfg2 & ESPCFG2_FE) { + ESP_WRITE_REG(sc, ESP_TCH, size >> 16); + } + /* load the count in */ + ESPCMD(sc, ESPCMD_NOP|ESPCMD_DMA); + ESPCMD(sc, ESPCMD_TRANS|ESPCMD_DMA); + DMA_GO(sc->sc_dma); #else { int i; - ESPCMD(sc, ESPCMD_FLUSH); for (i = 0; i < sc->sc_omlen; i++) ESP_WRITE_REG(sc, FIFO, sc->sc_omess[i]); ESPCMD(sc, ESPCMD_TRANS); -#if test_stuck_on_msgout -printf("<<XXXmsgoutdoneXXX>>"); -#endif + sc->sc_omlen = 0; } #endif } @@ -1357,17 +1497,18 @@ printf("<<XXXmsgoutdoneXXX>>"); * * Most of this needs verifying. */ -int +int espintr(sc) register struct esp_softc *sc; { - register struct ecb *ecb; + register struct esp_ecb *ecb; register struct scsi_link *sc_link; struct esp_tinfo *ti; int loop; + size_t size; ESP_TRACE(("[espintr]")); - + /* * I have made some (maybe seriously flawed) assumptions here, * but basic testing (uncomment the printf() below), show that @@ -1387,7 +1528,7 @@ espintr(sc) * This is a heuristic. It is 2 when at 20Mhz, 2 at 25Mhz and 1 * at 40Mhz. This needs testing. */ - for (loop = 0; ; loop++, DELAY(50/sc->sc_freq)) { + for (loop = 0; 1;loop++, DELAY(50/sc->sc_freq)) { /* a feeling of deja-vu */ if (!DMA_ISINTR(sc->sc_dma)) return (loop != 0); @@ -1439,9 +1580,7 @@ espintr(sc) if (sc->sc_nexus) panic("%s: nexus in reset state", sc->sc_dev.dv_xname); - sc->sc_state = ESP_IDLE; - esp_sched(sc); - return 1; + goto sched; } ecb = sc->sc_nexus; @@ -1456,10 +1595,10 @@ espintr(sc) ESPCMD(sc, ESPCMD_FLUSH); DELAY(1); } - if (sc->sc_state == ESP_HASNEXUS || + if (sc->sc_state == ESP_CONNECTED || sc->sc_state == ESP_SELECTING) { ecb->xs->error = XS_DRIVER_STUFFUP; - esp_done(ecb); + esp_done(sc, ecb); } return 1; } @@ -1486,14 +1625,30 @@ espintr(sc) * again in case there is no more DMA queued, but a phase * change is expected. */ - if (sc->sc_dma->sc_active && DMA_INTR(sc->sc_dma)) { + if (DMA_ISACTIVE(sc->sc_dma)) { + DMA_INTR(sc->sc_dma); /* If DMA active here, then go back to work... */ - if (sc->sc_dma->sc_active) + if (DMA_ISACTIVE(sc->sc_dma)) return 1; - if (!(sc->sc_espstat & ESPSTAT_TC)) - printf("%s: !TC\n", sc->sc_dev.dv_xname); - continue; + + if (sc->sc_dleft == 0 && + (sc->sc_espstat & ESPSTAT_TC) == 0) + printf("%s: !TC [intr %x, stat %x, step %d]" + " prevphase %x, resid %x\n", + sc->sc_dev.dv_xname, + sc->sc_espintr, + sc->sc_espstat, + sc->sc_espstep, + sc->sc_prevphase, + ecb?ecb->dleft:-1); + } + +#if 0 /* Unreliable on some ESP revisions? */ + if ((sc->sc_espstat & ESPSTAT_INT) == 0) { + printf("%s: spurious interrupt\n", sc->sc_dev.dv_xname); + return 1; } +#endif /* * check for less serious errors @@ -1503,12 +1658,13 @@ espintr(sc) sc->sc_dev.dv_xname); if (sc->sc_prevphase == MESSAGE_IN_PHASE) esp_sched_msgout(SEND_PARITY_ERROR); - else + else esp_sched_msgout(SEND_INIT_DET_ERR); } if (sc->sc_espintr & ESPINTR_DIS) { - ESP_MISC(("<DISC [intr %x, stat %x, step %d]>", sc->sc_espintr, sc->sc_espstat, sc->sc_espstep)); + ESP_MISC(("<DISC [intr %x, stat %x, step %d]>", + sc->sc_espintr,sc->sc_espstat,sc->sc_espstep)); if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { ESPCMD(sc, ESPCMD_FLUSH); DELAY(1); @@ -1518,38 +1674,59 @@ espintr(sc) * 250mS of a disconnect. So here you are... */ ESPCMD(sc, ESPCMD_ENSEL); - if (sc->sc_state != ESP_IDLE) { + switch (sc->sc_state) { + case ESP_RESELECTED: + goto sched; + + case ESP_SELECTING: + ecb->xs->error = XS_SELTIMEOUT; + goto finish; + + case ESP_CONNECTED: if ((sc->sc_flags & ESP_SYNCHNEGO)) { - printf("%s: sync nego not completed!\n", - sc->sc_dev.dv_xname); +#ifdef ESP_DEBUG + if (ecb) + sc_print_addr(ecb->xs->sc_link); + printf("sync nego not completed!\n"); +#endif + ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; + sc->sc_flags &= ~ESP_SYNCHNEGO; + ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE); } - /*XXX*/sc->sc_msgpriq = sc->sc_msgout = 0; /* it may be OK to disconnect */ - if (!(sc->sc_flags & ESP_BUSFREE_OK)) - ecb->xs->error = XS_TIMEOUT; - else if (sc->sc_flags & ESP_DISCON) { - TAILQ_INSERT_HEAD(&sc->nexus_list, ecb, chain); - ECB_SETQ(ecb, ECB_QNEXUS); - sc->sc_nexus = NULL; - sc->sc_flags &= ~ESP_DISCON; - sc->sc_state = ESP_IDLE; - esp_sched(sc); - return 1; + if ((sc->sc_flags & ESP_ABORTING) == 0) { + /* + * Section 5.1.1 of the SCSI 2 spec + * suggests issuing a REQUEST SENSE + * following an unexpected disconnect. + * Some devices go into a contingent + * allegiance condition when + * disconnecting, and this is necessary + * to clean up their state. + */ + printf("%s: unexpected disconnect; ", + sc->sc_dev.dv_xname); + if (ecb->flags & ECB_SENSE) { + printf("resetting\n"); + goto reset; + } + printf("sending REQUEST SENSE\n"); + esp_sense(sc, ecb); + goto out; } - esp_done(ecb); - return 1; - } - printf("DISCONNECT in IDLE state!\n"); - } + ecb->xs->error = XS_DRIVER_STUFFUP; + goto finish; + + case ESP_DISCONNECT: + TAILQ_INSERT_HEAD(&sc->nexus_list, ecb, chain); + sc->sc_nexus = NULL; + goto sched; - /* did a message go out OK ? This must be broken */ - if (sc->sc_prevphase == MESSAGE_OUT_PHASE && - sc->sc_phase != MESSAGE_OUT_PHASE) { - /* we have sent it */ - sc->sc_msgpriq &= ~sc->sc_msgout; - sc->sc_msgout = 0; + case ESP_CMDCOMPLETE: + goto finish; + } } switch (sc->sc_state) { @@ -1572,7 +1749,7 @@ espintr(sc) printf("<<RESELECT CONT'd>>"); #if XXXX esp_msgin(sc); - if (sc->sc_state != ESP_HASNEXUS) { + if (sc->sc_state != ESP_CONNECTED) { /* IDENTIFY fail?! */ printf("%s: identify failed\n", sc->sc_dev.dv_xname); @@ -1585,6 +1762,8 @@ printf("<<RESELECT CONT'd>>"); case ESP_IDLE: if (sc->sc_flags & ESP_ICCS) printf("[[esp: BUMMER]]"); case ESP_SELECTING: + sc->sc_msgpriq = sc->sc_msgout = sc->sc_msgoutq = 0; + sc->sc_flags = 0; if (sc->sc_espintr & ESPINTR_RESEL) { /* @@ -1598,8 +1777,6 @@ if (sc->sc_flags & ESP_ICCS) printf("[[esp: BUMMER]]"); ti = &sc->sc_tinfo[sc_link->target]; TAILQ_INSERT_HEAD(&sc->ready_list, sc->sc_nexus, chain); - ECB_SETQ(sc->sc_nexus, ECB_QREADY); - ti->lubusy &= ~(1<<sc_link->lun); ecb = sc->sc_nexus = NULL; } sc->sc_state = ESP_RESELECTED; @@ -1608,19 +1785,23 @@ if (sc->sc_flags & ESP_ICCS) printf("[[esp: BUMMER]]"); * Things are seriously fucked up. * Pull the brakes, i.e. reset */ - printf("%s: target didn't identify\n", + printf("%s: target didn't identify\n", sc->sc_dev.dv_xname); esp_init(sc, 1); return 1; } if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) != 2) { -printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF); + printf("%s: RESELECT: %d bytes in FIFO!\n", + sc->sc_dev.dv_xname, + ESP_READ_REG(sc, ESP_FFLAG) & + ESPFIFO_FF); + esp_init(sc, 1); + return 1; } sc->sc_selid = ESP_READ_REG(sc, ESP_FIFO); - sc->sc_selid &= ~(1<<sc->sc_id); ESP_MISC(("selid=0x%2x ", sc->sc_selid)); esp_msgin(sc); /* Handle identify message */ - if (sc->sc_state != ESP_HASNEXUS) { + if (sc->sc_state != ESP_CONNECTED) { /* IDENTIFY fail?! */ printf("%s: identify failed\n", sc->sc_dev.dv_xname); @@ -1643,25 +1824,24 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) case 0: printf("%s: select timeout/no disconnect\n", sc->sc_dev.dv_xname); - esp_abort(sc, ecb); - return 1; + ecb->xs->error = XS_SELTIMEOUT; + goto finish; case 1: if ((ti->flags & T_NEGOTIATE) == 0) { printf("%s: step 1 & !NEG\n", sc->sc_dev.dv_xname); - esp_abort(sc, ecb); - return 1; + goto reset; } if (sc->sc_phase != MESSAGE_OUT_PHASE) { printf("%s: !MSGOUT\n", sc->sc_dev.dv_xname); - esp_abort(sc, ecb); - return 1; + goto reset; } /* Start negotiating */ ti->period = sc->sc_minsync; ti->offset = 15; - sc->sc_msgpriq = SEND_SDTR; + sc->sc_flags |= ESP_SYNCHNEGO; + esp_sched_msgout(SEND_SDTR); break; case 3: /* @@ -1686,7 +1866,7 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF, sc->sc_espintr, sc->sc_espstat, sc->sc_espstep); - sc->sc_flags |= ESP_ABORTING; + ESPCMD(sc, ESPCMD_FLUSH); esp_sched_msgout(SEND_ABORT); return 1; case 2: @@ -1694,25 +1874,31 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) ESPCMD(sc, ESPCMD_FLUSH); case 4: /* So far, everything went fine */ - sc->sc_msgpriq = 0; break; } #if 0 -/* Why set msgpriq? (and not raise ATN) */ if (ecb->xs->flags & SCSI_RESET) - sc->sc_msgpriq = SEND_DEV_RESET; + esp_sched_msgout(SEND_DEV_RESET); else if (ti->flags & T_NEGOTIATE) - sc->sc_msgpriq = - SEND_IDENTIFY | SEND_SDTR; + esp_sched_msgout( + SEND_IDENTIFY | SEND_SDTR); else - sc->sc_msgpriq = SEND_IDENTIFY; + esp_sched_msgout(SEND_IDENTIFY); #endif - sc->sc_state = ESP_HASNEXUS; - /*???sc->sc_flags = 0; */ + + ecb->flags |= ECB_NEXUS; + ti->lubusy |= (1 << sc_link->lun); + sc->sc_prevphase = INVALID_PHASE; /* ?? */ + /* Do an implicit RESTORE POINTERS. */ sc->sc_dp = ecb->daddr; sc->sc_dleft = ecb->dleft; - ti->lubusy |= (1<<sc_link->lun); + + /* On our first connection, schedule a timeout. */ + if ((ecb->xs->flags & SCSI_POLL) == 0) + timeout(esp_timeout, ecb, (ecb->timeout * hz) / 1000); + + sc->sc_state = ESP_CONNECTED; break; } else { printf("%s: unexpected status after select" @@ -1722,7 +1908,7 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) sc->sc_espstep); ESPCMD(sc, ESPCMD_FLUSH); DELAY(1); - esp_abort(sc, ecb); + goto reset; } if (sc->sc_state == ESP_IDLE) { printf("%s: stray interrupt\n", sc->sc_dev.dv_xname); @@ -1730,9 +1916,9 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) } break; - case ESP_HASNEXUS: + case ESP_CONNECTED: if (sc->sc_flags & ESP_ICCS) { - unsigned char msg; + u_char msg; sc->sc_flags &= ~ESP_ICCS; @@ -1744,22 +1930,16 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) sc->sc_espstep); } if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) != 2) { - printf("%s: ICCS: expected 2, got %d " - ": [intr %x, stat %x, step %x]\n", - sc->sc_dev.dv_xname, - ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - ESPCMD(sc, ESPCMD_FLUSH); - esp_abort(sc, ecb); - return 1; + int i = (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) - 2; + while (i--) + (void) ESP_READ_REG(sc, ESP_FIFO); } ecb->stat = ESP_READ_REG(sc, ESP_FIFO); msg = ESP_READ_REG(sc, ESP_FIFO); ESP_PHASE(("<stat:(%x,%x)>", ecb->stat, msg)); if (msg == MSG_CMDCOMPLETE) { - sc->sc_flags |= ESP_BUSFREE_OK; ecb->xs->resid = ecb->dleft = sc->sc_dleft; + sc->sc_state = ESP_CMDCOMPLETE; } else printf("%s: STATUS_PHASE: msg %d\n", sc->sc_dev.dv_xname, msg); @@ -1774,10 +1954,10 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) } /* - * Driver is now in state ESP_HASNEXUS, i.e. we + * Driver is now in state ESP_CONNECTED, i.e. we * have a current command working the SCSI bus. */ - if (sc->sc_state != ESP_HASNEXUS || ecb == NULL) { + if (sc->sc_state != ESP_CONNECTED || ecb == NULL) { panic("esp no nexus"); } @@ -1833,31 +2013,39 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) case DATA_OUT_PHASE: ESP_PHASE(("DATA_OUT_PHASE [%d] ", sc->sc_dleft)); ESPCMD(sc, ESPCMD_FLUSH); - DMA_START(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft, 0); + size = min(sc->sc_dleft, sc->sc_maxxfer); + DMA_SETUP(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft, + 0, &size); sc->sc_prevphase = DATA_OUT_PHASE; - return 1; + goto setup_xfer; case DATA_IN_PHASE: ESP_PHASE(("DATA_IN_PHASE ")); if (sc->sc_rev == ESP100) ESPCMD(sc, ESPCMD_FLUSH); -#if 0 /* Why is the fifo sometimes full after re-connect? */ - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - static int xxx; - if (xxx <= 3) { - printf("%s: lost %d bytes from FIFO ", - sc->sc_dev.dv_xname, - ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF); - printf(" previous phase %x\n", - sc->sc_prevphase); - if (xxx == 3) - printf("(stopped logging)"); - ++xxx; - } - } -#endif - DMA_DRAIN(sc->sc_dma); - DMA_START(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft, 1); + size = min(sc->sc_dleft, sc->sc_maxxfer); + DMA_SETUP(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft, + 1, &size); sc->sc_prevphase = DATA_IN_PHASE; + setup_xfer: + /* Program the SCSI counter */ + ESP_WRITE_REG(sc, ESP_TCL, size); + ESP_WRITE_REG(sc, ESP_TCM, size >> 8); + if (sc->sc_cfg2 & ESPCFG2_FE) { + ESP_WRITE_REG(sc, ESP_TCH, size >> 16); + } + /* load the count in */ + ESPCMD(sc, ESPCMD_NOP|ESPCMD_DMA); + + /* + * Note that if `size' is 0, we've already transceived + * all the bytes we want but we're still in DATA PHASE. + * Apparently, the device needs padding. Also, a + * transfer size of 0 means "maximum" to the chip + * DMA logic. + */ + ESPCMD(sc, + (size==0?ESPCMD_TRPAD:ESPCMD_TRANS)|ESPCMD_DMA); + DMA_GO(sc->sc_dma); return 1; case STATUS_PHASE: ESP_PHASE(("STATUS_PHASE ")); @@ -1867,31 +2055,52 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) break; case INVALID_PHASE: break; - case BUSFREE_PHASE: - if (sc->sc_flags & ESP_BUSFREE_OK) { - /*It's fun the 1st time.. */ - sc->sc_flags &= ~ESP_BUSFREE_OK; - } - break; default: - panic("esp: bogus bus phase\n"); + printf("%s: unexpected bus phase; resetting\n", + sc->sc_dev.dv_xname); + goto reset; } } panic("esp: should not get here.."); + +reset: + esp_init(sc, 1); + return 1; + +finish: + untimeout(esp_timeout, ecb); + esp_done(sc, ecb); + goto out; + +sched: + sc->sc_state = ESP_IDLE; + esp_sched(sc); + goto out; + +out: + return 1; } void esp_abort(sc, ecb) struct esp_softc *sc; - struct ecb *ecb; + struct esp_ecb *ecb; { + + /* 2 secs for the abort */ + ecb->timeout = ESP_ABORT_TIMEOUT; + ecb->flags |= ECB_ABORT; + if (ecb == sc->sc_nexus) { -/*XXX*/sc->sc_tinfo[ecb->xs->sc_link->target].flags |= T_XXX; - if (sc->sc_state == ESP_HASNEXUS) { - sc->sc_flags |= ESP_ABORTING; + /* + * If we're still selecting, the message will be scheduled + * after selection is complete. + */ + if (sc->sc_state == ESP_CONNECTED) esp_sched_msgout(SEND_ABORT); - } } else { + esp_dequeue(sc, ecb); + TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain); if (sc->sc_state == ESP_IDLE) esp_sched(sc); } @@ -1901,58 +2110,36 @@ void esp_timeout(arg) void *arg; { - int s = splbio(); - struct ecb *ecb = (struct ecb *)arg; - struct esp_softc *sc; + struct esp_ecb *ecb = arg; struct scsi_xfer *xs = ecb->xs; + struct scsi_link *sc_link = xs->sc_link; + struct esp_softc *sc = sc_link->adapter_softc; + int s; + + sc_print_addr(sc_link); + printf("%s: timed out [ecb %p (flags 0x%x, dleft %x, stat %x)], " + "<state %d, nexus %p, phase(c %x, p %x), resid %x, msg(q %x,o %x) %s>", + sc->sc_dev.dv_xname, + ecb, ecb->flags, ecb->dleft, ecb->stat, + sc->sc_state, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase, + sc->sc_dleft, sc->sc_msgpriq, sc->sc_msgout, + DMA_ISACTIVE(sc->sc_dma) ? "DMA active" : ""); +#if ESP_DEBUG > 0 + printf("TRACE: %s.", ecb->trace); +#endif - sc = xs->sc_link->adapter_softc; - sc_print_addr(xs->sc_link); -again: - printf("timed out (ecb 0x%x (flags 0x%x, dleft %x), state %d, phase %d, msgpriq %x, msgout %x)", - ecb, ecb->flags, ecb->dleft, sc->sc_state, sc->sc_phase, - sc->sc_msgpriq, sc->sc_msgout); + s = splbio(); - if (ecb->flags == ECB_QFREE) { - printf("note: ecb already on free list\n"); - splx(s); - return; - } - if (ecb->flags & ECB_ABORTED) { + if (ecb->flags & ECB_ABORT) { /* abort timed out */ printf(" AGAIN\n"); - xs->retries = 0; esp_init(sc, 1); } else { /* abort the operation that has timed out */ printf("\n"); xs->error = XS_TIMEOUT; - ecb->flags |= ECB_ABORTED; -#if 0 -if (sc->sc_dma->sc_active) { - int x = esp_debug; esp_debug=0x3ff; - DMA_INTR(sc->sc_dma); - esp_debug = x; -} -#endif esp_abort(sc, ecb); - /* 2 secs for the abort */ - if ((xs->flags & SCSI_POLL) == 0) - timeout(esp_timeout, ecb, 2 * hz); - else { - int count = 200000; - while (count) { - if (DMA_ISINTR(sc->sc_dma)) { - espintr(sc); - } - if (xs->flags & ITSDONE) - break; - DELAY(10); - --count; - } - if (count == 0) - goto again; - } } + splx(s); } diff --git a/sys/arch/alpha/tc/espreg.h b/sys/arch/alpha/tc/espreg.h index d6602261f90..8492f1d5378 100644 --- a/sys/arch/alpha/tc/espreg.h +++ b/sys/arch/alpha/tc/espreg.h @@ -1,9 +1,8 @@ -/* $OpenBSD: espreg.h,v 1.3 1996/07/29 23:02:02 niklas Exp $ */ -/* $NetBSD: espreg.h,v 1.2 1995/12/20 00:40:25 cgd Exp $ */ +/* $OpenBSD: espreg.h,v 1.4 1996/10/30 22:41:06 niklas Exp $ */ +/* $NetBSD: espreg.h,v 1.3 1996/09/09 18:10:37 cgd Exp $ */ /* * Copyright (c) 1994 Peter Galbavy. All rights reserved. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -132,10 +131,8 @@ #define ESP_TEST 0x0a /* WO - Test (Chip Test Only) */ #define ESP_CFG2 0x0b /* RW - Configuration #2 */ -#if 0 -#define ESPCFG2_RSVD 0xa0 /* reserved */ +#define ESPCFG2_RSVD 0xa0 /* reserved */ #define ESPCFG2_FE 0x40 /* Features Enable */ -#endif #define ESPCFG2_DREQ 0x10 /* DREQ High Impedance */ #define ESPCFG2_SCSI2 0x08 /* SCSI-2 Enable */ #define ESPCFG2_BPA 0x04 /* Target Bad Parity Abort */ @@ -144,11 +141,9 @@ /* Config #3 only on 53C9X */ #define ESP_CFG3 0x0c /* RW - Configuration #3 */ -#if 0 #define ESPCFG3_RSVD 0xe0 /* reserved */ #define ESPCFG3_IDM 0x10 /* ID Message Res Check */ #define ESPCFG3_QTE 0x08 /* Queue Tag Enable */ #define ESPCFG3_CDB 0x04 /* CDB 10-bytes OK */ #define ESPCFG3_FSCSI 0x02 /* Fast SCSI */ #define ESPCFG3_FCLK 0x01 /* Fast Clock (>25Mhz) */ -#endif diff --git a/sys/arch/alpha/tc/espvar.h b/sys/arch/alpha/tc/espvar.h index 0564fcbdc1e..c21eb0d92c9 100644 --- a/sys/arch/alpha/tc/espvar.h +++ b/sys/arch/alpha/tc/espvar.h @@ -1,5 +1,9 @@ -/* $OpenBSD: espvar.h,v 1.4 1996/10/18 16:12:03 niklas Exp $ */ -/* $NetBSD: espvar.h,v 1.3 1995/12/20 00:40:26 cgd Exp $ */ +/* $OpenBSD: espvar.h,v 1.5 1996/10/30 22:41:07 niklas Exp $ */ +/* $NetBSD: espvar.h,v 1.10 1996/10/15 21:31:37 mycroft Exp $ */ + +#if defined(__sparc__) && !defined(SPARC_DRIVER) +#define SPARC_DRIVER +#endif /* * Copyright (c) 1994 Peter Galbavy. All rights reserved. @@ -30,7 +34,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define ESP_DEBUG 0 +#define ESP_DEBUG 0 + +#define ESP_ABORT_TIMEOUT 2000 /* time to wait for abort */ #define FREQTOCCF(freq) (((freq + 4) / 5)) @@ -40,7 +46,7 @@ #define ESP200 0x03 #define NCR53C94 0x04 -/* +/* * ECB. Holds additional information for each SCSI command Comments: We * need a separate scsi command block because we may need to overwrite it * with a request sense command. Basicly, we refrain from fiddling with @@ -48,28 +54,41 @@ * We'll generally update: xs->{flags,resid,error,sense,status} and * occasionally xs->retries. */ -struct ecb { - TAILQ_ENTRY(ecb) chain; +struct esp_ecb { + TAILQ_ENTRY(esp_ecb) chain; struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */ - int flags; /* Status */ -#define ECB_QNONE 0 -#define ECB_QFREE 1 -#define ECB_QREADY 2 -#define ECB_QNEXUS 3 -#define ECB_QBITS 0x07 -#define ECB_CHKSENSE 0x08 -#define ECB_ABORTED 0x10 -#define ECB_SETQ(e, q) do (e)->flags = ((e)->flags&~ECB_QBITS)|(q); while(0) + int flags; +#define ECB_ALLOC 0x01 +#define ECB_NEXUS 0x02 +#define ECB_SENSE 0x04 +#define ECB_ABORT 0x40 +#define ECB_RESET 0x80 + int timeout; + struct scsi_generic cmd; /* SCSI command block */ int clen; char *daddr; /* Saved data pointer */ int dleft; /* Residue */ u_char stat; /* SCSI status byte */ + +#if ESP_DEBUG > 0 + char trace[1000]; +#endif }; +#if ESP_DEBUG > 0 +#define ECB_TRACE(ecb, msg, a, b) do { \ + const char *f = "[" msg "]"; \ + int n = strlen((ecb)->trace); \ + if (n < (sizeof((ecb)->trace)-100)) \ + sprintf((ecb)->trace + n, f, a, b); \ +} while(0) +#else +#define ECB_TRACE(ecb, msg, a, b) +#endif -/* - * Some info about each (possible) target on the SCSI bus. This should - * probably have been a "per target+lunit" structure, but we'll leave it at +/* + * Some info about each (possible) target on the SCSI bus. This should + * probably have been a "per target+lunit" structure, but we'll leave it at * this for now. Is there a way to reliably hook it up to sc->fordriver?? */ struct esp_tinfo { @@ -84,8 +103,8 @@ struct esp_tinfo { #define T_NEGOTIATE 0x02 /* (Re)Negotiate synchronous options */ #define T_BUSY 0x04 /* Target is busy, i.e. cmd in progress */ #define T_SYNCMODE 0x08 /* sync mode has been negotiated */ -#define T_XXX 0x10 /* Target is XXX */ -#define T_SYNCHNEGO 0x20 /* .. */ +#define T_SYNCHOFF 0x10 /* .. */ +#define T_RSELECTOFF 0x20 /* .. */ u_char period; /* Period suggestion */ u_char offset; /* Offset suggestion */ } tinfo_t; @@ -106,15 +125,15 @@ struct esp_tinfo { #ifdef ESP_DEBUG extern int esp_debug; -#define ESP_ECBS(str) do {if (esp_debug & ESP_SHOWECBS) printf str;} while (0) -#define ESP_MISC(str) do {if (esp_debug & ESP_SHOWMISC) printf str;} while (0) -#define ESP_INTS(str) do {if (esp_debug & ESP_SHOWINTS) printf str;} while (0) -#define ESP_TRACE(str) do {if (esp_debug & ESP_SHOWTRAC) printf str;} while (0) -#define ESP_CMDS(str) do {if (esp_debug & ESP_SHOWCMDS) printf str;} while (0) -#define ESP_START(str) do {if (esp_debug & ESP_SHOWSTART) printf str;}while (0) -#define ESP_PHASE(str) do {if (esp_debug & ESP_SHOWPHASE) printf str;}while (0) -#define ESP_DMA(str) do {if (esp_debug & ESP_SHOWDMA) printf str;} while (0) -#define ESP_MSGS(str) do {if (esp_debug & ESP_SHOWMSGS) printf str;} while (0) +#define ESP_ECBS(str) do {if (esp_debug & ESP_SHOWECBS) printf str;} while (0) +#define ESP_MISC(str) do {if (esp_debug & ESP_SHOWMISC) printf str;} while (0) +#define ESP_INTS(str) do {if (esp_debug & ESP_SHOWINTS) printf str;} while (0) +#define ESP_TRACE(str) do {if (esp_debug & ESP_SHOWTRAC) printf str;} while (0) +#define ESP_CMDS(str) do {if (esp_debug & ESP_SHOWCMDS) printf str;} while (0) +#define ESP_START(str) do {if (esp_debug & ESP_SHOWSTART) printf str;}while (0) +#define ESP_PHASE(str) do {if (esp_debug & ESP_SHOWPHASE) printf str;}while (0) +#define ESP_DMA(str) do {if (esp_debug & ESP_SHOWDMA) printf str;}while (0) +#define ESP_MSGS(str) do {if (esp_debug & ESP_SHOWMSGS) printf str;}while (0) #else #define ESP_ECBS(str) #define ESP_MISC(str) @@ -160,12 +179,12 @@ struct esp_softc { u_char sc_espfflags; /* Lists of command blocks */ - TAILQ_HEAD(ecb_list, ecb) free_list, - ready_list, - nexus_list; + TAILQ_HEAD(ecb_list, esp_ecb) free_list, + ready_list, + nexus_list; - struct ecb *sc_nexus; /* current command */ - struct ecb sc_ecb[8]; /* one per target */ + struct esp_ecb *sc_nexus; /* current command */ + struct esp_ecb sc_ecb[16]; /* one per target */ struct esp_tinfo sc_tinfo[8]; /* Data about the current nexus (updated for every cmd switch) */ @@ -183,6 +202,7 @@ struct esp_softc { /* Message stuff */ u_char sc_msgpriq; /* One or more messages to send (encoded) */ u_char sc_msgout; /* What message is on its way out? */ + u_char sc_msgoutq; /* What messages have been sent so far? */ u_char sc_omess[ESP_MAX_MSG_LEN]; caddr_t sc_omp; /* Message pointer (for multibyte messages) */ size_t sc_omlen; @@ -199,48 +219,39 @@ struct esp_softc { int sc_id; /* our scsi id */ int sc_rev; /* esp revision */ int sc_minsync; /* minimum sync period / 4 */ + int sc_maxxfer; /* maximum transfer size */ }; /* values for sc_state */ -#define ESP_IDLE 0x01 /* waiting for something to do */ -#define ESP_TMP_UNAVAIL 0x02 /* Don't accept SCSI commands */ -#define ESP_SELECTING 0x03 /* SCSI command is arbiting */ -#define ESP_RESELECTED 0x04 /* Has been reselected */ -#define ESP_HASNEXUS 0x05 /* Actively using the SCSI bus */ -#define ESP_CLEANING 0x06 -#define ESP_SBR 0x07 /* Expect a SCSI RST because we commanded it */ +#define ESP_IDLE 1 /* waiting for something to do */ +#define ESP_SELECTING 2 /* SCSI command is arbiting */ +#define ESP_RESELECTED 3 /* Has been reselected */ +#define ESP_CONNECTED 4 /* Actively using the SCSI bus */ +#define ESP_DISCONNECT 5 /* MSG_DISCONNECT received */ +#define ESP_CMDCOMPLETE 6 /* MSG_CMDCOMPLETE received */ +#define ESP_CLEANING 7 +#define ESP_SBR 8 /* Expect a SCSI RST because we commanded it */ /* values for sc_flags */ #define ESP_DROP_MSGI 0x01 /* Discard all msgs (parity err detected) */ -#define ESP_DOINGDMA 0x02 /* The FIFO data path is active! */ -#define ESP_BUSFREE_OK 0x04 /* Bus free phase is OK. */ +#define ESP_ABORTING 0x02 /* Bailing out */ +#define ESP_DOINGDMA 0x04 /* The FIFO data path is active! */ #define ESP_SYNCHNEGO 0x08 /* Synch negotiation in progress. */ -/*#define ESP_BLOCKED 0x10 * Don't schedule new scsi bus operations */ -#define ESP_DISCON 0x10 /* Target sent DISCONNECT msg */ -#define ESP_ABORTING 0x20 /* Bailing out */ -#define ESP_ICCS 0x40 /* Expect status phase results */ -#define ESP_WAITI 0x80 /* Waiting for non-DMA data to arrive */ +#define ESP_ICCS 0x10 /* Expect status phase results */ +#define ESP_WAITI 0x20 /* Waiting for non-DMA data to arrive */ +#define ESP_ATN 0x40 /* ATN asserted */ /* values for sc_msgout */ #define SEND_DEV_RESET 0x01 #define SEND_PARITY_ERROR 0x02 -#define SEND_ABORT 0x04 +#define SEND_INIT_DET_ERR 0x04 #define SEND_REJECT 0x08 -#define SEND_INIT_DET_ERR 0x10 -#define SEND_IDENTIFY 0x20 +#define SEND_IDENTIFY 0x10 +#define SEND_ABORT 0x20 #define SEND_SDTR 0x40 +#define SEND_WDTR 0x80 /* SCSI Status codes */ -#define ST_GOOD 0x00 -#define ST_CHKCOND 0x02 -#define ST_CONDMET 0x04 -#define ST_BUSY 0x08 -#define ST_INTERMED 0x10 -#define ST_INTERMED_CONDMET 0x14 -#define ST_RESERVATION_CONFLICT 0x18 -#define ST_CMD_TERM 0x22 -#define ST_QUEUE_FULL 0x28 - #define ST_MASK 0x3e /* bit 0,6,7 is reserved */ /* phase bits */ @@ -263,8 +274,21 @@ struct esp_softc { #define INVALID_PHASE 0x101 /* Re/Selection valid, but no REQ yet */ #define PSEUDO_PHASE 0x100 /* "pseudo" bit */ +/* + * Macros to read and write the chip's registers. + */ +#ifdef SPARC_DRIVER +#define ESP_READ_REG(sc, reg) \ + ((sc)->sc_reg[(reg) * 4]) +#define ESP_WRITE_REG(sc, reg, val) \ + do { \ + u_char v = (val); \ + (sc)->sc_reg[(reg) * 4] = v; \ + } while (0) +#else /* ! SPARC_DRIVER */ #if 1 static __inline u_char ESP_READ_REG __P((struct esp_softc *, int)); + static __inline u_char ESP_READ_REG(sc, reg) struct esp_softc *sc; @@ -273,7 +297,7 @@ ESP_READ_REG(sc, reg) u_char v; v = sc->sc_reg[reg * 2] & 0xff; - wbflush(); + alpha_mb(); return v; } #else @@ -284,8 +308,9 @@ ESP_READ_REG(sc, reg) do { \ u_char v = (val); \ (sc)->sc_reg[(reg) * 2] = v; \ - wbflush(); \ + alpha_mb(); \ } while (0) +#endif /* SPARC_DRIVER */ #ifdef ESP_DEBUG #define ESPCMD(sc, cmd) do { \ @@ -302,24 +327,13 @@ ESP_READ_REG(sc, reg) ((bp->val[0] == ca->ca_slot && bp->val[1] == ca->ca_offset) || \ (bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit)) +#ifndef SPARC_DRIVER /* DMA macros for ESP */ -#ifdef SPARC_DRIVER -#define DMA_ENINTR(r) ((r->enintr)(r)) -#define DMA_ISINTR(r) ((r->isintr)(r)) -#define DMA_RESET(r) ((r->reset)(r)) -#define DMA_START(a, b, c, d) ((a->start)(a, b, c, d)) -#define DMA_INTR(r) ((r->intr)(r)) -#define DMA_DRAIN(sc) if (sc->sc_rev < DMAREV_2) { \ - DMACSR(sc) |= D_DRAIN; \ - DMAWAIT1(sc); \ - } -#else -int tcds_dma_intr __P((struct tcds_slotconfig *)); - -#define DMA_ENINTR(r) tcds_dma_enintr(r) -#define DMA_ISINTR(r) tcds_dma_isintr(r) -#define DMA_RESET(r) tcds_dma_reset(r) -#define DMA_START(a, b, c, d) tcds_dma_start(a, b, c, d) -#define DMA_INTR(r) tcds_dma_intr(r) -#define DMA_DRAIN(sc) +#define DMA_ISINTR(sc) tcds_dma_isintr(sc) +#define DMA_RESET(sc) tcds_dma_reset(sc) +#define DMA_INTR(sc) tcds_dma_intr(sc) +#define DMA_SETUP(sc, addr, len, datain, dmasize) \ + tcds_dma_setup(sc, addr, len, datain, dmasize) +#define DMA_GO(sc) tcds_dma_go(sc) +#define DMA_ISACTIVE(sc) tcds_dma_isactive(sc) #endif diff --git a/sys/arch/alpha/tc/ioasic.c b/sys/arch/alpha/tc/ioasic.c index b6e09102e31..37e6d1bf17d 100644 --- a/sys/arch/alpha/tc/ioasic.c +++ b/sys/arch/alpha/tc/ioasic.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ioasic.c,v 1.3 1996/07/29 23:02:06 niklas Exp $ */ -/* $NetBSD: ioasic.c,v 1.4.4.1 1996/06/05 00:39:05 cgd Exp $ */ +/* $OpenBSD: ioasic.c,v 1.4 1996/10/30 22:41:08 niklas Exp $ */ +/* $NetBSD: ioasic.c,v 1.9 1996/10/13 03:00:32 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -54,7 +54,7 @@ struct ioasic_softc { /* Definition of the driver for autoconfig. */ int ioasicmatch __P((struct device *, void *, void *)); void ioasicattach __P((struct device *, struct device *, void *)); -int ioasicprint(void *, char *); +int ioasicprint(void *, /* const */ char *); struct cfattach ioasic_ca = { sizeof(struct ioasic_softc), ioasicmatch, ioasicattach, @@ -190,7 +190,7 @@ ioasicattach(parent, self, aux) int ioasicprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { struct ioasicdev_attach_args *d = aux; @@ -288,10 +288,10 @@ ioasic_intr(val) void *val; { register struct ioasic_softc *sc = val; - register int i, ifound; + register int ifound; int gifound; - u_int32_t sir, junk; - volatile u_int32_t *sirp, *junkp; + u_int32_t sir; + volatile u_int32_t *sirp; sirp = (volatile u_int32_t *)IOASIC_REG_INTR(sc->sc_base); diff --git a/sys/arch/alpha/tc/ioasicreg.h b/sys/arch/alpha/tc/ioasicreg.h index 370c0d47d14..2c09ef47776 100644 --- a/sys/arch/alpha/tc/ioasicreg.h +++ b/sys/arch/alpha/tc/ioasicreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ioasicreg.h,v 1.2 1996/07/29 23:02:07 niklas Exp $ */ +/* $OpenBSD: ioasicreg.h,v 1.3 1996/10/30 22:41:09 niklas Exp $ */ /* $NetBSD: ioasicreg.h,v 1.1 1995/12/20 00:43:22 cgd Exp $ */ /* diff --git a/sys/arch/alpha/tc/mcclock_ioasic.c b/sys/arch/alpha/tc/mcclock_ioasic.c index 6a01a25b5ee..235fff4e901 100644 --- a/sys/arch/alpha/tc/mcclock_ioasic.c +++ b/sys/arch/alpha/tc/mcclock_ioasic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mcclock_ioasic.c,v 1.2 1996/07/29 23:02:09 niklas Exp $ */ +/* $OpenBSD: mcclock_ioasic.c,v 1.3 1996/10/30 22:41:10 niklas Exp $ */ /* $NetBSD: mcclock_ioasic.c,v 1.2 1996/04/17 22:22:58 cgd Exp $ */ /* diff --git a/sys/arch/alpha/tc/scc.c b/sys/arch/alpha/tc/scc.c index eeae075cba2..bfa713ad8d0 100644 --- a/sys/arch/alpha/tc/scc.c +++ b/sys/arch/alpha/tc/scc.c @@ -1,27 +1,27 @@ -/* $OpenBSD: scc.c,v 1.5 1996/07/29 23:02:11 niklas Exp $ */ -/* $NetBSD: scc.c,v 1.16.4.2 1996/06/03 19:44:41 cgd Exp $ */ +/* $OpenBSD: scc.c,v 1.6 1996/10/30 22:41:11 niklas Exp $ */ +/* $NetBSD: scc.c,v 1.26 1996/10/16 05:07:57 jonathan Exp $ */ -/* +/* * Copyright (c) 1991,1990,1989,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 + * + * 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. */ @@ -101,6 +101,7 @@ #include <pmax/dev/fbreg.h> #endif +#include <machine/autoconf.h> /* For the badaddr() proto */ #include <machine/rpb.h> #include <dev/tc/tcvar.h> @@ -112,14 +113,24 @@ extern void ttrstrt __P((void *)); #undef SCCDEV #define SCCDEV 15 /* XXX */ -#define NSCCLINE (NSCC*2) +/* + * rcons glass-tty console (as used on pmax) needs lk-201 ASCII input + * support from the tty drivers. This is ugly and broken and won't + * compile on Alphas. + */ +#ifdef pmax +#define HAVE_RCONS +extern int pending_remcons; +#endif + +#define NSCCLINE (NSCC*2) #define SCCUNIT(dev) (minor(dev) >> 1) #define SCCLINE(dev) (minor(dev) & 0x1) -struct tty *scc_tty[NSCCLINE]; -void (*sccDivertXInput)(); /* X windows keyboard input routine */ -void (*sccMouseEvent)(); /* X windows mouse motion event routine */ -void (*sccMouseButtons)(); /* X windows mouse buttons event routine */ +/* QVSS-compatible in-kernel X input event parser, pointer tracker */ +void (*sccDivertXInput) __P((int cc)); /* X windows keyboard input routine */ +void (*sccMouseEvent) __P((int)); /* X windows mouse motion event routine */ +void (*sccMouseButtons) __P((int)); /* X windows mouse buttons event routine */ #ifdef DEBUG int debugChar; #endif @@ -134,13 +145,21 @@ struct scc_softc { u_char wr5; u_char wr14; } scc_wreg[2]; + struct tty *scc_tty[2]; int scc_softCAR; + + int scc_flags[2]; +#define SCC_CHAN_NEEDSDELAY 0x01 /* sw must delay 1.6us between output*/ +#define SCC_CHAN_NOMODEM 0x02 /* don't touch modem ctl lines (may + be left floating or x-wired */ +#define SCC_CHAN_MODEM_CROSSED 0x04 /* modem lines wired to other channel*/ +#define SCC_CHAN_KBDLINE 0x08 /* XXX special-case keyboard lines */ }; /* * BRG formula is: * ClockFrequency - * BRGconstant = --------------------------- - 2 + * BRGconstant = --------------------------- - 2 * 2 * BaudRate * ClockDivider * * Speed selections with Pclk=7.3728Mhz, clock x16 @@ -159,9 +178,13 @@ struct speedtab sccspeedtab[] = { { 1800, 126, }, { 2400, 94, }, { 4800, 46, }, + { 7200, 30, }, /* non-POSIX */ { 9600, 22, }, + { 14400, 14, }, /* non-POSIX */ { 19200, 10, }, - { 38400, 4, }, + { 28800, 6, }, /* non-POSIX */ + { 38400, 4, }, /* non-POSIX */ + { 57600, 2, }, /* non-POSIX */ { -1, -1, }, }; @@ -174,9 +197,10 @@ struct speedtab sccspeedtab[] = { #endif /* Definition of the driver for autoconfig. */ -static int sccmatch(struct device *, void *, void *); -static void sccattach(struct device *, struct device *, void *); - +static int sccmatch __P((struct device * parent, void *cfdata, + void *aux)); +static void sccattach __P((struct device *parent, struct device *self, + void *aux)); struct cfattach scc_ca = { sizeof (struct scc_softc), sccmatch, sccattach, }; @@ -185,12 +209,21 @@ struct cfdriver scc_cd = { NULL, "scc", DV_TTY, }; +int sccopen __P((dev_t, int, int, struct proc *)); +int sccclose __P((dev_t, int, int, struct proc *)); +int sccread __P((dev_t, struct uio *, int)); +int sccwrite __P((dev_t, struct uio *, int)); +struct tty *scctty __P((dev_t)); +int sccioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +void sccstop __P((struct tty *, int)); int sccGetc __P((dev_t)); void sccPutc __P((dev_t, int)); void sccPollc __P((dev_t, int)); int sccparam __P((struct tty *, struct termios *)); void sccstart __P((struct tty *)); int sccmctl __P((dev_t, int, int)); +static int cold_sccparam __P((struct tty *, struct termios *, + struct scc_softc *sc)); #ifdef SCC_DEBUG static void rr __P((char *, scc_regmap_t *)); @@ -201,9 +234,97 @@ static void sccreset __P((struct scc_softc *)); int sccintr __P((void *)); void scc_alphaintr __P((int)); + +/* + * console variables, for using serial console while still cold and + * autoconfig has not attached the scc device. + */ +extern int cold; +scc_regmap_t *scc_cons_addr = 0; +static struct scc_softc coldcons_softc; +static struct consdev scccons = { + NULL, NULL, sccGetc, sccPutc, sccPollc, NODEV, 0 +}; +void scc_consinit __P((dev_t dev, scc_regmap_t *sccaddr)); +void scc_oconsinit __P((struct scc_softc *, dev_t)); + + +/* + * Set up a given unit as a serial console device. + * We need console output when cold, and before any device is configured. + * Should be callable when cold, to reset the chip and set parameters + * for a remote (serial) console or kgdb line. + * XXX + * As most DECstations only bring out one rs-232 lead from an SCC + * to the bulkhead, and use the other for mouse and keyboard, we + * only allow one unit per SCC to be console. + */ +void +scc_consinit(dev, sccaddr) + dev_t dev; + scc_regmap_t *sccaddr; +{ + struct scc_softc *sc; + struct termios cterm; + struct tty ctty; + int s; + + /* Save address in case we're cold. */ + if (cold && scc_cons_addr == 0) { + scc_cons_addr = sccaddr; + sc = &coldcons_softc; + coldcons_softc.scc_pdma[0].p_addr = sccaddr; + coldcons_softc.scc_pdma[1].p_addr = sccaddr; + } else { + /* being called from sccattach() to reset console */ + sc = scc_cd.cd_devs[SCCUNIT(dev)]; + } + + /* Reset chip. */ + sccreset(sc); + /* XXX make sure sccreset() called only once for this chip? */ + + /* set console-line parameters */ + s = spltty(); + ctty.t_dev = dev; + scccons.cn_dev = dev; + cterm.c_cflag = CS8; +#ifdef pmax + /* XXX -- why on pmax, not on Alpha? */ + cterm.c_cflag |= CLOCAL; +#endif + cterm.c_ospeed = cterm.c_ispeed = 9600; + (void) cold_sccparam(&ctty, &cterm, sc); + *cn_tab = scccons; + DELAY(1000); + splx(s); +} + +void +scc_oconsinit(sc, dev) + struct scc_softc *sc; + dev_t dev; +{ + struct termios cterm; + struct tty ctty; + int s; + + s = spltty(); + ctty.t_dev = dev; + cterm.c_cflag = CS8; +#ifdef pmax + /* XXX -- why on pmax, not on Alpha? */ + cterm.c_cflag |= CLOCAL; +#endif + cterm.c_ospeed = cterm.c_ispeed = 9600; + (void) sccparam(&ctty, &cterm); + DELAY(1000); + splx(s); +} + /* * Test to see if device is present. - * Return true if found and initialized ok. + * Return true if found. */ int sccmatch(parent, cfdata, aux) @@ -215,10 +336,16 @@ sccmatch(parent, cfdata, aux) struct ioasicdev_attach_args *d = aux; void *sccaddr; - /* XXX BUS TYPE? */ + if (parent->dv_cfdata->cf_driver != &ioasic_cd) { +#ifdef DIAGNOSTIC + printf("Cannot attach scc on %s\n", parent->dv_xname); +#endif + return (0); + } /* Make sure that we're looking for this type of device. */ - if (strncmp(d->iada_modname, "z8530 ", TC_ROM_LLEN)) + if ((strncmp(d->iada_modname, "z8530 ", TC_ROM_LLEN) != 0) && + (strncmp(d->iada_modname, "scc", TC_ROM_LLEN)!= 0)) return (0); /* XXX MATCH CFLOC */ @@ -236,6 +363,11 @@ sccmatch(parent, cfdata, aux) return (1); } +#ifdef alpha +/* + * Enable ioasic SCC interrupts and scc DMA engine interrupts. + * XXX does not really belong here. + */ void scc_alphaintr(onoff) int onoff; @@ -257,14 +389,15 @@ scc_alphaintr(onoff) IOASIC_CSR_DMAEN_T2 | IOASIC_CSR_DMAEN_R2); #endif } - wbflush(); + tc_mb(); } +#endif /* alpha */ void sccattach(parent, self, aux) - struct device *parent; - struct device *self; - void *aux; + struct device *parent; + struct device *self; + void *aux; { struct scc_softc *sc = (struct scc_softc *)self; struct ioasicdev_attach_args *d = aux; @@ -272,9 +405,9 @@ sccattach(parent, self, aux) struct tty *tp; void *sccaddr; int cntr; - struct termios cterm; - struct tty ctty; - int s; + struct termios cterm; + struct tty ctty; + int s; extern int cputype; /* Get the address, and check it for validity. */ @@ -285,7 +418,7 @@ sccattach(parent, self, aux) /* Register the interrupt handler. */ ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_TTY, - sccintr, (void *)(long)sc->sc_dv.dv_unit); + sccintr, (void *)sc); /* * For a remote console, wait a while for previous output to @@ -305,68 +438,73 @@ sccattach(parent, self, aux) /* init pseudo DMA structures */ for (cntr = 0; cntr < 2; cntr++) { pdp->p_addr = (void *)sccaddr; - tp = scc_tty[sc->sc_dv.dv_unit * 2 + cntr] = ttymalloc(); + tp = sc->scc_tty[cntr] = ttymalloc(); if (cntr == 0) tty_attach(tp); pdp->p_arg = (long)tp; - pdp->p_fcn = (void (*)())0; + pdp->p_fcn = (void (*)__P((struct tty*)))0; tp->t_dev = (dev_t)((sc->sc_dv.dv_unit << 1) | cntr); pdp++; } + /* What's the warning here? Defaulting to softCAR on line 2? */ sc->scc_softCAR = 0x2; /* XXX */ - /* reset chip */ + /* reset chip, initialize register-copies in softc */ sccreset(sc); - /* - * Special handling for consoles. - */ - if (0 /* cn_tab.cn_screen */) { - if (1 /* cn_tab.cn_kbdgetc == sccGetc */) { - if (sc->sc_dv.dv_unit == 1) { - s = spltty(); - ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT); - cterm.c_cflag = CS8; - cterm.c_ospeed = cterm.c_ispeed = 4800; - (void) sccparam(&ctty, &cterm); - DELAY(10000); + /* + * Special handling for consoles. + */ + if (0 /* cn_tab.cn_screen */) { + if (1 /* cn_tab.cn_kbdgetc == sccGetc */) { + if (sc->sc_dv.dv_unit == 1) { + s = spltty(); + ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT); + cterm.c_cflag = CS8; +#ifdef pmax + /* XXX -- why on pmax, not on Alpha? */ + cterm.c_cflag |= CLOCAL; +#endif /* pmax */ + cterm.c_ospeed = cterm.c_ispeed = 4800; + (void) sccparam(&ctty, &cterm); + DELAY(10000); #ifdef notyet - /* - * For some reason doing this hangs the 3min - * during booting. Fortunately the keyboard - * works ok without it. - */ - KBDReset(ctty.t_dev, sccPutc); + /* + * For some reason doing this hangs the 3min + * during booting. Fortunately the keyboard + * works ok without it. + */ + KBDReset(ctty.t_dev, sccPutc); #endif - DELAY(10000); - splx(s); - } else if (sc->sc_dv.dv_unit == 0) { - s = spltty(); - ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT); - cterm.c_cflag = CS8 | PARENB | PARODD; - cterm.c_ospeed = cterm.c_ispeed = 4800; - (void) sccparam(&ctty, &cterm); + DELAY(10000); + splx(s); + } else if (sc->sc_dv.dv_unit == 0) { + s = spltty(); + ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT); + cterm.c_cflag = CS8 | PARENB | PARODD; + cterm.c_ospeed = cterm.c_ispeed = 4800; + (void) sccparam(&ctty, &cterm); #ifdef TK_NOTYET - DELAY(10000); - MouseInit(ctty.t_dev, sccPutc, sccGetc); - DELAY(10000); + DELAY(10000); + MouseInit(ctty.t_dev, sccPutc, sccGetc); + DELAY(10000); #endif - splx(s); - } - } - } else if (1 /* SCCUNIT(cn_tab.cn_dev) == sc->sc_dv.dv_unit */) { - s = spltty(); - ctty.t_dev = makedev(SCCDEV, - sc->sc_dv.dv_unit == 0 ? SCCCOMM2_PORT : SCCCOMM3_PORT); - cterm.c_cflag = (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8; - cterm.c_ospeed = cterm.c_ispeed = 9600; - (void) sccparam(&ctty, &cterm); - DELAY(1000); + splx(s); + } + } + } else if (1 /* SCCUNIT(cn_tab.cn_dev) == sc->sc_dv.dv_unit */) { + s = spltty(); + ctty.t_dev = makedev(SCCDEV, + sc->sc_dv.dv_unit == 0 ? SCCCOMM2_PORT : SCCCOMM3_PORT); + cterm.c_cflag = (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8; + cterm.c_ospeed = cterm.c_ispeed = 9600; + (void) sccparam(&ctty, &cterm); + DELAY(1000); #ifdef TK_NOTYET - cn_tab.cn_disabled = 0; + cn_tab.cn_disabled = 0; #endif - splx(s); - } + splx(s); + } /* * XXX @@ -374,9 +512,6 @@ sccattach(parent, self, aux) */ if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) || (cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0)) { - static struct consdev scccons = { - NULL, NULL, sccGetc, sccPutc, sccPollc, NODEV, 0 - }; cn_tab = &scccons; cn_tab->cn_dev = makedev(SCCDEV, sc->sc_dv.dv_unit * 2); @@ -475,9 +610,9 @@ sccopen(dev, flag, mode, p) line = SCCLINE(dev); if (sc->scc_pdma[line].p_addr == NULL) return (ENXIO); - tp = scc_tty[minor(dev)]; + tp = sc->scc_tty[line]; if (tp == NULL) { - tp = scc_tty[minor(dev)] = ttymalloc(); + tp = sc->scc_tty[line] = ttymalloc(); tty_attach(tp); } tp->t_oproc = sccstart; @@ -506,7 +641,7 @@ sccopen(dev, flag, mode, p) (void) sccmctl(dev, DML_DTR, DMSET); s = spltty(); while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && - !(tp->t_state & TS_CARR_ON)) { + !(tp->t_state & TS_CARR_ON)) { tp->t_state |= TS_WOPEN; if ((error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, ttopen, 0)) != 0) @@ -529,8 +664,8 @@ sccclose(dev, flag, mode, p) register struct tty *tp; register int line; - tp = scc_tty[minor(dev)]; line = SCCLINE(dev); + tp = sc->scc_tty[line]; if (sc->scc_wreg[line].wr5 & ZSWR5_BREAK) { sc->scc_wreg[line].wr5 &= ~ZSWR5_BREAK; ttyoutput(0, tp); @@ -548,9 +683,11 @@ sccread(dev, uio, flag) struct uio *uio; int flag; { + register struct scc_softc *sc; register struct tty *tp; - tp = scc_tty[minor(dev)]; + sc = scc_cd.cd_devs[SCCUNIT(dev)]; /* XXX*/ + tp = sc->scc_tty[SCCLINE(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } @@ -560,9 +697,11 @@ sccwrite(dev, uio, flag) struct uio *uio; int flag; { + register struct scc_softc *sc; register struct tty *tp; - tp = scc_tty[minor(dev)]; + sc = scc_cd.cd_devs[SCCUNIT(dev)]; /* XXX*/ + tp = sc->scc_tty[SCCLINE(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } @@ -570,9 +709,14 @@ struct tty * scctty(dev) dev_t dev; { - struct tty *tp = scc_tty[minor(dev)]; /* XXX */ + register struct scc_softc *sc; + register struct tty *tp; + register int unit = SCCUNIT(dev); - return (tp); + if ((unit >= scc_cd.cd_ndevs) || (sc = scc_cd.cd_devs[unit]) == 0) + return (0); + tp = sc->scc_tty[SCCLINE(dev)]; + return (tp); } /*ARGSUSED*/ @@ -588,7 +732,9 @@ sccioctl(dev, cmd, data, flag, p) register struct tty *tp; int error, line; - tp = scc_tty[minor(dev)]; + line = SCCLINE(dev); + sc = scc_cd.cd_devs[SCCUNIT(dev)]; + tp = sc->scc_tty[line]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error >= 0) return (error); @@ -596,8 +742,6 @@ sccioctl(dev, cmd, data, flag, p) if (error >= 0) return (error); - line = SCCLINE(dev); - sc = scc_cd.cd_devs[SCCUNIT(dev)]; switch (cmd) { case TIOCSBRK: @@ -640,32 +784,55 @@ sccioctl(dev, cmd, data, flag, p) return (0); } + + +/* + * Set line parameters -- tty t_param entry point. + */ int sccparam(tp, t) register struct tty *tp; register struct termios *t; { register struct scc_softc *sc; + + /* Extract the softc and call cold_sccparam to do all the work. */ + sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)]; + return cold_sccparam(tp, t, sc); +} + + +/* + * Do what sccparam() (t_param entry point) does, but callable when cold. + */ +static int +cold_sccparam(tp, t, sc) + register struct tty *tp; + register struct termios *t; + register struct scc_softc *sc; +{ register scc_regmap_t *regs; register int line; register u_char value, wvalue; register int cflag = t->c_cflag; int ospeed; - if (t->c_ispeed && t->c_ispeed != t->c_ospeed) - return (EINVAL); + /* Check arguments */ + if (t->c_ispeed && t->c_ispeed != t->c_ospeed) + return (EINVAL); ospeed = ttspeedtab(t->c_ospeed, sccspeedtab); - if (ospeed < 0) - return (EINVAL); - /* and copy to tty */ - tp->t_ispeed = t->c_ispeed; - tp->t_ospeed = t->c_ospeed; - tp->t_cflag = cflag; + if (ospeed < 0) + return (EINVAL); + /* and copy to tty */ + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = cflag; /* * Handle console specially. */ - if (0 /* cn_tab.cn_screen */) { +#ifdef HAVE_RCONS + if (cn_tab->cn_getc == LKgetc) { if (minor(tp->t_dev) == SCCKBD_PORT) { cflag = CS8; ospeed = ttspeedtab(4800, sccspeedtab); @@ -673,7 +840,9 @@ sccparam(tp, t) cflag = CS8 | PARENB | PARODD; ospeed = ttspeedtab(4800, sccspeedtab); } - } else /* if (tp->t_dev == cn_tab.cn_dev) */ { + } else if (tp->t_dev == cn_tab->cn_dev) +#endif /*HAVE_RCONS*/ + { cflag = CS8; ospeed = ttspeedtab(9600, sccspeedtab); } @@ -682,10 +851,14 @@ sccparam(tp, t) return (0); } - sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)]; line = SCCLINE(tp->t_dev); regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; + /* + * pmax driver used to reset the SCC here. That reset causes the + * other channel on the SCC to drop outpur chars: at least that's + * what CGD reports for the Alpha. It's a bug. + */ #if 0 /* reset line */ if (line == SCC_CHANNEL_A) @@ -715,7 +888,7 @@ sccparam(tp, t) SCC_WRITE_REG(regs, line, ZSWR_IVEC, 0xf0); /* clear break, keep rts dtr */ - wvalue = sc->scc_wreg[line].wr5 & (ZSWR5_DTR | ZSWR5_RTS); + wvalue = sc->scc_wreg[line].wr5 & (ZSWR5_DTR|ZSWR5_RTS); switch (cflag & CSIZE) { case CS5: value = ZSWR3_RX_5; @@ -740,9 +913,14 @@ sccparam(tp, t) sc->scc_wreg[line].wr5 = wvalue; SCC_WRITE_REG(regs, line, SCC_WR5, wvalue); + /* + * XXX Does the SCC chip require us to refresh the WR5 register + * for the other channel after writing the other, or not? + */ #ifdef notdef /* XXX */ - {int otherline = (line + 1) & 1; + { + int otherline = (line + 1) & 1; SCC_WRITE_REG(regs, otherline, SCC_WR5, sc->scc_wreg[otherline].wr5); } #endif @@ -757,11 +935,15 @@ sccparam(tp, t) SCC_SET_TIMING_BASE(regs, line, ospeed); value = sc->scc_wreg[line].wr14; SCC_WRITE_REG(regs, line, SCC_WR14, value); - if (SCCUNIT(tp->t_dev) != 1) { - value = ZSWR15_BREAK_IE | ZSWR15_CTS_IE | ZSWR15_DCD_IE; - } else { + +#ifdef alpha + if (SCCUNIT(tp->t_dev) == 1) { /* On unit one, on the flamingo, modem control is floating! */ value = ZSWR15_BREAK_IE; + } else +#endif + { + value = ZSWR15_BREAK_IE | ZSWR15_CTS_IE | ZSWR15_DCD_IE; } SCC_WRITE_REG(regs, line, SCC_WR15, value); @@ -776,28 +958,32 @@ sccparam(tp, t) value = ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT; SCC_WRITE_REG(regs, line, SCC_WR9, value); SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1); + tc_mb(); +#ifdef alpha scc_alphaintr(1); /* XXX XXX XXX */ +#endif /*alpha*/ return (0); } + /* * Check for interrupts from all devices. */ int -sccintr(xxxunit) - void *xxxunit; +sccintr(xxxsc) + void *xxxsc; { - register int unit = (long)xxxunit; + register struct scc_softc *sc = (struct scc_softc *)xxxsc; + register int unit = (long)sc->sc_dv.dv_unit; register scc_regmap_t *regs; register struct tty *tp; register struct pdma *dp; - register struct scc_softc *sc; register int cc, chan, rr1, rr2, rr3; int overrun = 0; - sc = scc_cd.cd_devs[unit]; + rr1 = 0; /* shut up gcc -Wall */ regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; unit <<= 1; for (;;) { @@ -807,18 +993,21 @@ sccintr(xxxunit) if (rr2 == 6) { /* strange, distinguished value */ SCC_READ_REG(regs, SCC_CHANNEL_A, ZSRR_IPEND, rr3); if (rr3 == 0) - return; + return 0; /* XXX */ } SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, ZSWR0_CLR_INTR); if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) { chan = (rr2 == SCC_RR2_A_XMIT_DONE) ? SCC_CHANNEL_A : SCC_CHANNEL_B; - tp = scc_tty[unit | chan]; + tp = sc->scc_tty[chan]; dp = &sc->scc_pdma[chan]; if (dp->p_mem < dp->p_end) { SCC_WRITE_DATA(regs, chan, *dp->p_mem++); - wbflush(); +#ifdef pmax /* Alpha handles the 1.6 msec settle time in hardware */ + DELAY(2); +#endif + tc_mb(); } else { tp->t_state &= ~TS_BUSY; if (tp->t_state & TS_FLUSH) @@ -839,7 +1028,7 @@ sccintr(xxxunit) cc = sc->scc_wreg[chan].wr1 & ~ZSWR1_TIE; SCC_WRITE_REG(regs, chan, SCC_WR1, cc); sc->scc_wreg[chan].wr1 = cc; - wbflush(); + tc_mb(); } } } else if (rr2 == SCC_RR2_A_RECV_DONE || @@ -849,7 +1038,7 @@ sccintr(xxxunit) chan = SCC_CHANNEL_A; else chan = SCC_CHANNEL_B; - tp = scc_tty[unit | chan]; + tp = sc->scc_tty[chan]; SCC_READ_DATA(regs, chan, cc); if (rr2 == SCC_RR2_A_RECV_SPECIAL || rr2 == SCC_RR2_B_RECV_SPECIAL) { @@ -865,12 +1054,12 @@ sccintr(xxxunit) /* * Keyboard needs special treatment. */ - if (tp == scc_tty[SCCKBD_PORT] /* && cn_tab.cn_screen */) { + if (tp == scctty(makedev(SCCDEV, SCCKBD_PORT)) /* && cn_tab.cn_screen */) { #ifdef KADB if (cc == LK_DO) { spl0(); kdbpanic(); - return; + return 0; /* XXX */ } #endif #ifdef DEBUG @@ -887,40 +1076,11 @@ sccintr(xxxunit) /* * Now for mousey */ - } else if (tp == scc_tty[SCCMOUSE_PORT] && sccMouseButtons) { -#if 0 - register MouseReport *mrp; - static MouseReport currentRep; - - mrp = ¤tRep; - mrp->byteCount++; - if (cc & MOUSE_START_FRAME) { - /* - * The first mouse report byte (button state). - */ - mrp->state = cc; - if (mrp->byteCount > 1) - mrp->byteCount = 1; - } else if (mrp->byteCount == 2) { - /* - * The second mouse report byte (delta x). - */ - mrp->dx = cc; - } else if (mrp->byteCount == 3) { - /* - * The final mouse report byte (delta y). - */ - mrp->dy = cc; - mrp->byteCount = 0; - if (mrp->dx != 0 || mrp->dy != 0) { - /* - * If the mouse moved, - * post a motion event. - */ - (*sccMouseEvent)(mrp); - } - (*sccMouseButtons)(mrp); - } + } else if (tp == scctty(makedev(SCCDEV, SCCMOUSE_PORT)) && + sccMouseButtons) { +#ifdef HAVE_RCONS + /*XXX*/ + mouseInput(cc); #endif continue; } @@ -941,11 +1101,12 @@ sccintr(xxxunit) (*linesw[tp->t_line].l_rint)(cc, tp); } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) { chan = (rr2 == SCC_RR2_A_EXT_STATUS) ? - SCC_CHANNEL_A : SCC_CHANNEL_B; + SCC_CHANNEL_A : SCC_CHANNEL_B; SCC_WRITE_REG(regs, chan, SCC_RR0, ZSWR0_RESET_STATUS); scc_modem_intr(unit | chan); } } + return 0; /* XXX */ } void @@ -975,7 +1136,7 @@ sccstart(tp) if (tp->t_outq.c_cc == 0) goto out; /* handle console specially */ - if (tp == scc_tty[SCCKBD_PORT] /* && cn_tab.cn_screen */) { + if (tp == scctty(makedev(SCCDEV,SCCKBD_PORT)) /* && cn_tab.cn_screen */) { while (tp->t_outq.c_cc > 0) { cc = getc(&tp->t_outq) & 0x7f; cnputc(cc); @@ -993,21 +1154,8 @@ sccstart(tp) } goto out; } -#if 0 - if (tp->t_flags & (RAW|LITOUT)) - cc = ndqb(&tp->t_outq, 0); - else { - cc = ndqb(&tp->t_outq, 0200); - if (cc == 0) { - cc = getc(&tp->t_outq); - timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); - tp->t_state |= TS_TIMEOUT; - goto out; - } - } -#else cc = ndqb(&tp->t_outq, 0); -#endif + tp->t_state |= TS_BUSY; dp->p_end = dp->p_mem = tp->t_outq.c_cf; dp->p_end += cc; @@ -1030,8 +1178,11 @@ sccstart(tp) panic("sccstart: No chars"); #endif SCC_WRITE_DATA(regs, chan, *dp->p_mem++); +#ifdef pmax /* Alpha handles the 1.6 msec settle time in hardware */ + DELAY(2); +#endif } - wbflush(); + tc_mb(); out: splx(s); } @@ -1040,7 +1191,7 @@ out: * Stop output on a line. */ /*ARGSUSED*/ -int +void sccstop(tp, flag) register struct tty *tp; int flag; @@ -1058,8 +1209,6 @@ sccstop(tp, flag) tp->t_state |= TS_FLUSH; } splx(s); - - return 0; /* XXX should be void */ } int @@ -1118,7 +1267,7 @@ sccmctl(dev, bits, how) sc->scc_wreg[SCC_CHANNEL_A].wr5); } if ((mbits & DML_DTR) || (sc->scc_softCAR & (1 << line))) - scc_tty[minor(dev)]->t_state |= TS_CARR_ON; + sc->scc_tty[line]->t_state |= TS_CARR_ON; (void) splx(s); return (mbits); } @@ -1137,9 +1286,9 @@ scc_modem_intr(dev) register u_char value; int s; - sc = scc_cd.cd_devs[SCCUNIT(dev)]; - tp = scc_tty[minor(dev)]; chan = SCCLINE(dev); + sc = scc_cd.cd_devs[SCCUNIT(dev)]; + tp = sc->scc_tty[chan]; regs = (scc_regmap_t *)sc->scc_pdma[chan].p_addr; if (chan == SCC_CHANNEL_A) return; @@ -1150,6 +1299,13 @@ scc_modem_intr(dev) SCC_READ_REG_ZERO(regs, chan, value); car = value & ZSRR0_DCD; } + + /* + * The pmax driver follows carrier-detect. The Alpha does not. + * XXX Why doesn't the Alpha driver follow carrier-detect? + * (in the Alpha driver, this is an "#ifdef notdef"). + * Is it related to console handling? + */ #ifdef notdef if (car) { /* carrier present */ @@ -1171,15 +1327,25 @@ sccGetc(dev) register scc_regmap_t *regs; register int c, line; register u_char value; - struct scc_softc *sc; int s; line = SCCLINE(dev); - sc = scc_cd.cd_devs[SCCUNIT(dev)]; - regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; + if (cold && scc_cons_addr) { + regs = scc_cons_addr; + } else { + register struct scc_softc *sc; + sc = scc_cd.cd_devs[SCCUNIT(dev)]; + regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; + } + if (!regs) return (0); +#ifdef pmax + /*s = spltty(); */ /* XXX why different spls? */ + s = splhigh(); +#else s = splhigh(); +#endif for (;;) { SCC_READ_REG(regs, line, SCC_RR0, value); if (value & ZSRR0_RX_READY) { @@ -1212,13 +1378,21 @@ sccPutc(dev, c) register scc_regmap_t *regs; register int line; register u_char value; - struct scc_softc *sc; int s; +#ifdef pmax + s = spltty(); /* XXX why different spls? */ +#else s = splhigh(); +#endif line = SCCLINE(dev); - sc = scc_cd.cd_devs[SCCUNIT(dev)]; - regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; + if (cold && scc_cons_addr) { + regs = scc_cons_addr; + } else { + register struct scc_softc *sc; + sc = scc_cd.cd_devs[SCCUNIT(dev)]; + regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; + } /* * Wait for transmitter to be not busy. @@ -1234,7 +1408,7 @@ sccPutc(dev, c) * Send the char. */ SCC_WRITE_DATA(regs, line, c); - wbflush(); + tc_mb(); splx(s); return; @@ -1285,5 +1459,5 @@ rr(msg, regs) printf("B: 0: %x 1: %x 2(state): %x 10: %x 15: %x\n", r0, r1, r2, r10, r15); } -#endif +#endif /* SCC_DEBUG */ #endif /* NSCC */ diff --git a/sys/arch/alpha/tc/sccreg.h b/sys/arch/alpha/tc/sccreg.h index 2207605a58a..f51a1083921 100644 --- a/sys/arch/alpha/tc/sccreg.h +++ b/sys/arch/alpha/tc/sccreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sccreg.h,v 1.2 1996/07/29 23:02:13 niklas Exp $ */ +/* $OpenBSD: sccreg.h,v 1.3 1996/10/30 22:41:12 niklas Exp $ */ /* $NetBSD: sccreg.h,v 1.2 1995/04/11 03:41:10 mycroft Exp $ */ /* diff --git a/sys/arch/alpha/tc/sccvar.h b/sys/arch/alpha/tc/sccvar.h index 5ffdb5baa11..c0c8285fb35 100644 --- a/sys/arch/alpha/tc/sccvar.h +++ b/sys/arch/alpha/tc/sccvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: sccvar.h,v 1.2 1996/07/29 23:02:15 niklas Exp $ */ -/* $NetBSD: sccvar.h,v 1.2 1995/08/03 00:52:23 cgd Exp $ */ +/* $OpenBSD: sccvar.h,v 1.3 1996/10/30 22:41:13 niklas Exp $ */ +/* $NetBSD: sccvar.h,v 1.3 1996/07/09 00:55:21 cgd Exp $ */ /* * Copyright (c) 1991,1990,1989,1994,1995 Carnegie Mellon University @@ -98,7 +98,7 @@ typedef struct { #define scc_get_datum(d, v) \ do { (v) = ((d) >> 8) & 0xff; } while (0) #define scc_set_datum(d, v) \ - do { (d) = (volatile unsigned int)(v) << 8; wbflush(); } while (0) + do { (d) = (volatile unsigned int)(v) << 8; alpha_mb(); } while (0) /* * Minor device numbers for scc. Weird because B channel comes first and diff --git a/sys/arch/alpha/tc/sfb.c b/sys/arch/alpha/tc/sfb.c index d593bc89fa1..1d6abccf59b 100644 --- a/sys/arch/alpha/tc/sfb.c +++ b/sys/arch/alpha/tc/sfb.c @@ -1,5 +1,5 @@ -/* $OpenBSD: sfb.c,v 1.2 1996/07/29 23:02:16 niklas Exp $ */ -/* $NetBSD: sfb.c,v 1.1 1996/05/01 21:15:50 cgd Exp $ */ +/* $OpenBSD: sfb.c,v 1.3 1996/10/30 22:41:14 niklas Exp $ */ +/* $NetBSD: sfb.c,v 1.5 1996/10/13 03:00:35 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -57,7 +57,7 @@ int sfbmatch __P((struct device *, void *, void *)); void sfbattach __P((struct device *, struct device *, void *)); -int sfbprint __P((void *, char *)); +int sfbprint __P((void *, /* const */ char *)); struct cfattach sfb_ca = { sizeof(struct sfb_softc), sfbmatch, sfbattach, @@ -92,7 +92,6 @@ sfbmatch(parent, match, aux) struct device *parent; void *match, *aux; { - struct cfdata *cf = match; struct tc_attach_args *ta = aux; if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0) @@ -112,7 +111,7 @@ sfb_getdevconfig(dense_addr, dc) int i; dc->dc_vaddr = dense_addr; - dc->dc_paddr = k0segtophys(dc->dc_vaddr); /* XXX */ + dc->dc_paddr = ALPHA_K0SEG_TO_PHYS(dc->dc_vaddr); /* XXX */ dc->dc_size = SFB_SIZE; regp = (char *)dc->dc_vaddr + SFB_ASIC_OFFSET; @@ -209,7 +208,6 @@ sfbattach(parent, self, aux) struct wscons_attach_args waa; struct wscons_odev_spec *wo; int console; - char *x; console = 0; /* XXX */ if (console) @@ -253,7 +251,7 @@ sfbattach(parent, self, aux) int sfbprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { if (pnp) diff --git a/sys/arch/alpha/tc/sfbvar.h b/sys/arch/alpha/tc/sfbvar.h index a1fa2952d72..c1e46e511a2 100644 --- a/sys/arch/alpha/tc/sfbvar.h +++ b/sys/arch/alpha/tc/sfbvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sfbvar.h,v 1.2 1996/07/29 23:02:18 niklas Exp $ */ +/* $OpenBSD: sfbvar.h,v 1.3 1996/10/30 22:41:15 niklas Exp $ */ /* $NetBSD: sfbvar.h,v 1.1 1996/05/01 21:15:51 cgd Exp $ */ /* diff --git a/sys/arch/alpha/tc/tc_3000_300.c b/sys/arch/alpha/tc/tc_3000_300.c index dc7c0b41fb9..890bfa6fc7f 100644 --- a/sys/arch/alpha/tc/tc_3000_300.c +++ b/sys/arch/alpha/tc/tc_3000_300.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_3000_300.c,v 1.4 1996/07/29 23:02:19 niklas Exp $ */ -/* $NetBSD: tc_3000_300.c,v 1.7.4.1 1996/06/05 00:39:06 cgd Exp $ */ +/* $OpenBSD: tc_3000_300.c,v 1.5 1996/10/30 22:41:16 niklas Exp $ */ +/* $NetBSD: tc_3000_300.c,v 1.12 1996/10/13 03:00:37 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/device.h> #include <machine/autoconf.h> @@ -46,12 +47,12 @@ void tc_3000_300_intr_setup __P((void)); void tc_3000_300_intr_establish __P((struct device *, void *, tc_intrlevel_t, int (*)(void *), void *)); void tc_3000_300_intr_disestablish __P((struct device *, void *)); -void tc_3000_300_iointr __P((void *, int)); +void tc_3000_300_iointr __P((void *, unsigned long)); int tc_3000_300_intrnull __P((void *)); #define C(x) ((void *)(u_long)x) -#define KV(x) (phystok0seg(x)) +#define KV(x) (ALPHA_PHYS_TO_K0SEG(x)) /* * We have to read and modify the IOASIC registers directly, because @@ -184,18 +185,19 @@ tc_3000_300_intrnull(val) void tc_3000_300_iointr(framep, vec) void *framep; - int vec; + unsigned long vec; { u_int32_t tcir, ioasicir, ioasicimr; - int opt0intr, opt1intr, ifound; + int ifound; #ifdef DIAGNOSTIC int s; if (vec != 0x800) - panic("INVALID ASSUMPTION: vec %x, not 0x800", vec); + panic("INVALID ASSUMPTION: vec 0x%lx, not 0x800", vec); s = splhigh(); - if (s != PSL_IPL_IO) - panic("INVALID ASSUMPTION: IPL %d, not %d", s, PSL_IPL_IO); + if (s != ALPHA_PSL_IPL_IO) + panic("INVALID ASSUMPTION: IPL %d, not %d", s, + ALPHA_PSL_IPL_IO); splx(s); #endif diff --git a/sys/arch/alpha/tc/tc_3000_300.h b/sys/arch/alpha/tc/tc_3000_300.h index 8ef82e58802..475eefad00b 100644 --- a/sys/arch/alpha/tc/tc_3000_300.h +++ b/sys/arch/alpha/tc/tc_3000_300.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tc_3000_300.h,v 1.3 1996/07/29 23:02:21 niklas Exp $ */ +/* $OpenBSD: tc_3000_300.h,v 1.4 1996/10/30 22:41:17 niklas Exp $ */ /* $NetBSD: tc_3000_300.h,v 1.2 1995/12/20 00:43:28 cgd Exp $ */ /* diff --git a/sys/arch/alpha/tc/tc_3000_500.c b/sys/arch/alpha/tc/tc_3000_500.c index ccda3b062bd..9e8133619b2 100644 --- a/sys/arch/alpha/tc/tc_3000_500.c +++ b/sys/arch/alpha/tc/tc_3000_500.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_3000_500.c,v 1.4 1996/07/29 23:02:23 niklas Exp $ */ -/* $NetBSD: tc_3000_500.c,v 1.4.4.3 1996/06/13 18:35:35 cgd Exp $ */ +/* $OpenBSD: tc_3000_500.c,v 1.5 1996/10/30 22:41:18 niklas Exp $ */ +/* $NetBSD: tc_3000_500.c,v 1.11 1996/10/13 03:00:38 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/device.h> #include <machine/autoconf.h> @@ -45,12 +46,12 @@ void tc_3000_500_intr_setup __P((void)); void tc_3000_500_intr_establish __P((struct device *, void *, tc_intrlevel_t, int (*)(void *), void *)); void tc_3000_500_intr_disestablish __P((struct device *, void *)); -void tc_3000_500_iointr __P((void *, int)); +void tc_3000_500_iointr __P((void *, unsigned long)); int tc_3000_500_intrnull __P((void *)); #define C(x) ((void *)(u_long)x) -#define KV(x) (phystok0seg(x)) +#define KV(x) (ALPHA_PHYS_TO_K0SEG(x)) struct tc_slotdesc tc_3000_500_slots[] = { { KV(0x100000000), C(TC_3000_500_DEV_OPT0), }, /* 0 - opt slot 0 */ @@ -175,7 +176,7 @@ tc_3000_500_intrnull(val) void tc_3000_500_iointr(framep, vec) void *framep; - int vec; + unsigned long vec; { u_int32_t ir; int ifound; @@ -183,10 +184,11 @@ tc_3000_500_iointr(framep, vec) #ifdef DIAGNOSTIC int s; if (vec != 0x800) - panic("INVALID ASSUMPTION: vec %x, not 0x800", vec); + panic("INVALID ASSUMPTION: vec 0x%lx, not 0x800", vec); s = splhigh(); - if (s != PSL_IPL_IO) - panic("INVALID ASSUMPTION: IPL %d, not %d", s, PSL_IPL_IO); + if (s != ALPHA_PSL_IPL_IO) + panic("INVALID ASSUMPTION: IPL %d, not %d", s, + ALPHA_PSL_IPL_IO); splx(s); #endif @@ -248,6 +250,7 @@ tc_3000_500_iointr(framep, vec) } while (ifound); } +#if 0 /* * tc_3000_500_ioslot -- * Set the PBS bits for devices on the TC. @@ -273,3 +276,4 @@ tc_3000_500_ioslot(slot, flags, set) tc_mb(); splx(s); } +#endif diff --git a/sys/arch/alpha/tc/tc_3000_500.h b/sys/arch/alpha/tc/tc_3000_500.h index ea5a236e165..b9249b9a857 100644 --- a/sys/arch/alpha/tc/tc_3000_500.h +++ b/sys/arch/alpha/tc/tc_3000_500.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tc_3000_500.h,v 1.3 1996/07/29 23:02:24 niklas Exp $ */ +/* $OpenBSD: tc_3000_500.h,v 1.4 1996/10/30 22:41:19 niklas Exp $ */ /* $NetBSD: tc_3000_500.h,v 1.2 1995/12/20 00:43:31 cgd Exp $ */ /* diff --git a/sys/arch/alpha/tc/tc_bus_io.c b/sys/arch/alpha/tc/tc_bus_io.c index e553611c1b4..731d237b820 100644 --- a/sys/arch/alpha/tc/tc_bus_io.c +++ b/sys/arch/alpha/tc/tc_bus_io.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_bus_io.c,v 1.2 1996/07/29 23:02:26 niklas Exp $ */ -/* $NetBSD: tc_bus_io.c,v 1.1.4.1 1996/06/13 17:41:51 cgd Exp $ */ +/* $OpenBSD: tc_bus_io.c,v 1.3 1996/10/30 22:41:20 niklas Exp $ */ +/* $NetBSD: tc_bus_io.c,v 1.3 1996/07/09 00:55:31 cgd Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -34,12 +34,14 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/device.h> #include <vm/vm.h> #include <machine/bus.h> +#include <dev/tc/tcvar.h> int tc_io_map __P((void *, bus_io_addr_t, bus_io_size_t, bus_io_handle_t *)); diff --git a/sys/arch/alpha/tc/tc_bus_mem.c b/sys/arch/alpha/tc/tc_bus_mem.c index b82678694fc..558dd764c0f 100644 --- a/sys/arch/alpha/tc/tc_bus_mem.c +++ b/sys/arch/alpha/tc/tc_bus_mem.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_bus_mem.c,v 1.2 1996/07/29 23:02:27 niklas Exp $ */ -/* $NetBSD: tc_bus_mem.c,v 1.2.4.2 1996/06/13 17:42:51 cgd Exp $ */ +/* $OpenBSD: tc_bus_mem.c,v 1.3 1996/10/30 22:41:21 niklas Exp $ */ +/* $NetBSD: tc_bus_mem.c,v 1.7 1996/07/09 00:55:33 cgd Exp $ */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -33,6 +33,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/device.h> @@ -105,9 +106,9 @@ tc_mem_map(v, memaddr, memsize, cacheable, memhp) if (memaddr & 0x7) panic("tc_mem_map needs 8 byte alignment"); if (cacheable) - *memhp = phystok0seg(memaddr); + *memhp = ALPHA_PHYS_TO_K0SEG(memaddr); else - *memhp = phystok0seg(TC_DENSE_TO_SPARSE(memaddr)); + *memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr)); return (0); } @@ -148,7 +149,7 @@ tc_mem_read_1(v, memh, off) { volatile u_int8_t *p; - wbflush(); + alpha_mb(); if ((memh & TC_SPACE_SPARSE) != 0) panic("tc_mem_read_1 not implemented for sparse space"); @@ -165,7 +166,7 @@ tc_mem_read_2(v, memh, off) { volatile u_int16_t *p; - wbflush(); + alpha_mb(); if ((memh & TC_SPACE_SPARSE) != 0) panic("tc_mem_read_2 not implemented for sparse space"); @@ -182,7 +183,7 @@ tc_mem_read_4(v, memh, off) { volatile u_int32_t *p; - wbflush(); + alpha_mb(); if ((memh & TC_SPACE_SPARSE) != 0) /* Nothing special to do for 4-byte sparse space accesses */ @@ -200,7 +201,7 @@ tc_mem_read_8(v, memh, off) { volatile u_int64_t *p; - wbflush(); + alpha_mb(); if ((memh & TC_SPACE_SPARSE) != 0) panic("tc_mem_read_8 not implemented for sparse space"); @@ -236,7 +237,7 @@ tc_mem_write_1(v, memh, off, val) p = (u_int8_t *)(memh + off); *p = val; } - wbflush(); + alpha_mb(); } void @@ -266,7 +267,7 @@ tc_mem_write_2(v, memh, off, val) p = (u_int16_t *)(memh + off); *p = val; } - wbflush(); + alpha_mb(); } void @@ -284,7 +285,7 @@ tc_mem_write_4(v, memh, off, val) else p = (u_int32_t *)(memh + off); *p = val; - wbflush(); + alpha_mb(); } void @@ -301,7 +302,7 @@ tc_mem_write_8(v, memh, off, val) p = (u_int64_t *)(memh + off); *p = val; - wbflush(); + alpha_mb(); } /* XXX DOES NOT BELONG */ @@ -310,5 +311,5 @@ tc_XXX_dmamap(addr) void *addr; { - return (vtophys(addr)); + return (vtophys((vm_offset_t)addr)); } diff --git a/sys/arch/alpha/tc/tc_conf.h b/sys/arch/alpha/tc/tc_conf.h index 948014a6e3f..479cea7eb6b 100644 --- a/sys/arch/alpha/tc/tc_conf.h +++ b/sys/arch/alpha/tc/tc_conf.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_conf.h,v 1.2 1996/07/29 23:02:29 niklas Exp $ */ -/* $NetBSD: tc_conf.h,v 1.1 1995/12/20 00:43:32 cgd Exp $ */ +/* $OpenBSD: tc_conf.h,v 1.3 1996/10/30 22:41:22 niklas Exp $ */ +/* $NetBSD: tc_conf.h,v 1.2 1996/07/14 04:06:30 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -34,7 +34,7 @@ #ifdef DEC_3000_500 extern void tc_3000_500_intr_setup __P((void)); -extern void tc_3000_500_iointr __P((void *, int)); +extern void tc_3000_500_iointr __P((void *, unsigned long)); extern void tc_3000_500_intr_establish __P((struct device *, void *, tc_intrlevel_t, int (*)(void *), void *)); @@ -48,7 +48,7 @@ extern struct tc_builtin tc_3000_500_builtins[]; #ifdef DEC_3000_300 extern void tc_3000_300_intr_setup __P((void)); -extern void tc_3000_300_iointr __P((void *, int)); +extern void tc_3000_300_iointr __P((void *, unsigned long)); extern void tc_3000_300_intr_establish __P((struct device *, void *, tc_intrlevel_t, int (*)(void *), void *)); diff --git a/sys/arch/alpha/tc/tc_machdep.h b/sys/arch/alpha/tc/tc_machdep.h index f5a55ec646b..842c8bc023a 100644 --- a/sys/arch/alpha/tc/tc_machdep.h +++ b/sys/arch/alpha/tc/tc_machdep.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tc_machdep.h,v 1.2 1996/07/29 23:02:31 niklas Exp $ */ -/* $NetBSD: tc_machdep.h,v 1.1 1995/12/20 00:09:29 cgd Exp $ */ +/* $OpenBSD: tc_machdep.h,v 1.3 1996/10/30 22:41:23 niklas Exp $ */ +/* $NetBSD: tc_machdep.h,v 1.2 1996/07/09 00:55:35 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -61,8 +61,8 @@ typedef u_int64_t tc_addr_t; typedef int32_t tc_offset_t; -#define tc_mb() wbflush() -#define tc_wmb() wbflush() +#define tc_mb() alpha_mb() +#define tc_wmb() alpha_wmb() /* * A junk address to read from, to make sure writes are complete. See @@ -73,7 +73,7 @@ typedef int32_t tc_offset_t; do { \ volatile u_int32_t no_optimize; \ no_optimize = \ - *(volatile u_int32_t *)phystok0seg(0x00000001f0080220); \ + *(volatile u_int32_t *)ALPHA_PHYS_TO_K0SEG(0x00000001f0080220); \ } while (0) #define tc_badaddr(tcaddr) \ @@ -91,3 +91,6 @@ typedef int32_t tc_offset_t; #define TC_PHYS_TO_UNCACHED(addr) \ (addr) + +void tc_bus_io_init __P((bus_chipset_tag_t bc, void *iov));; +void tc_bus_mem_init __P((bus_chipset_tag_t bc, void *memv));; diff --git a/sys/arch/alpha/tc/tcasic.c b/sys/arch/alpha/tc/tcasic.c index c1f2223032f..6ea1615408c 100644 --- a/sys/arch/alpha/tc/tcasic.c +++ b/sys/arch/alpha/tc/tcasic.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tcasic.c,v 1.3 1996/07/29 23:02:32 niklas Exp $ */ -/* $NetBSD: tcasic.c,v 1.5 1996/05/17 23:58:43 cgd Exp $ */ +/* $OpenBSD: tcasic.c,v 1.4 1996/10/30 22:41:24 niklas Exp $ */ +/* $NetBSD: tcasic.c,v 1.10 1996/10/13 03:00:39 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -29,6 +29,7 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/device.h> #include <machine/autoconf.h> @@ -49,7 +50,7 @@ struct cfdriver tcasic_cd = { NULL, "tcasic", DV_DULL, }; -int tcasicprint __P((void *, char *)); +int tcasicprint __P((void *, /* const */ char *)); extern int cputype; @@ -86,7 +87,7 @@ tcasicattach(parent, self, aux) { struct tcbus_attach_args tba; void (*intr_setup) __P((void)); - void (*iointr) __P((void *, int)); + void (*iointr) __P((void *, unsigned long)); struct alpha_bus_chipset bc; printf("\n"); @@ -144,7 +145,7 @@ tcasicattach(parent, self, aux) int tcasicprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { /* only TCs can attach to tcasics; easy. */ diff --git a/sys/arch/alpha/tc/tcds.c b/sys/arch/alpha/tc/tcds.c index dd8da7b9903..a3cb6ae6b1b 100644 --- a/sys/arch/alpha/tc/tcds.c +++ b/sys/arch/alpha/tc/tcds.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tcds.c,v 1.4 1996/07/29 23:02:34 niklas Exp $ */ -/* $NetBSD: tcds.c,v 1.9.4.2 1996/06/05 01:32:26 cgd Exp $ */ +/* $OpenBSD: tcds.c,v 1.5 1996/10/30 22:41:27 niklas Exp $ */ +/* $NetBSD: tcds.c,v 1.15 1996/10/13 03:00:41 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -58,7 +58,7 @@ struct tcds_softc { /* Definition of the driver for autoconfig. */ int tcdsmatch __P((struct device *, void *, void *)); void tcdsattach __P((struct device *, struct device *, void *)); -int tcdsprint(void *, char *); +int tcdsprint __P((void *, /* const */ char *)); struct cfattach tcds_ca = { sizeof(struct tcds_softc), tcdsmatch, tcdsattach, @@ -120,7 +120,7 @@ tcdsattach(parent, self, aux) * not useful) bits set in it when the system boots. Clear it. */ *sc->sc_imer = 0; - wbflush(); + alpha_mb(); /* XXX Initial contents of CIR? */ @@ -204,7 +204,7 @@ tcdsattach(parent, self, aux) int tcdsprint(aux, pnp) void *aux; - char *pnp; + /* const */ char *pnp; { struct tc_attach_args *ta = aux; @@ -279,10 +279,10 @@ tcds_scsi_reset(sc) tcds_scsi_enable(sc, 0); TCDS_CIR_CLR(*sc->sc_tcds->sc_cir, sc->sc_resetbits); - wbflush(); + alpha_mb(); DELAY(1); TCDS_CIR_SET(*sc->sc_tcds->sc_cir, sc->sc_resetbits); - wbflush(); + alpha_mb(); tcds_scsi_enable(sc, 1); tcds_dma_enable(sc, 1); @@ -298,7 +298,7 @@ tcds_scsi_enable(sc, on) *sc->sc_tcds->sc_imer |= sc->sc_intrmaskbits; else *sc->sc_tcds->sc_imer &= ~sc->sc_intrmaskbits; - wbflush(); + alpha_mb(); } void @@ -312,7 +312,7 @@ tcds_dma_enable(sc, on) TCDS_CIR_SET(*sc->sc_tcds->sc_cir, sc->sc_dmabits); else TCDS_CIR_CLR(*sc->sc_tcds->sc_cir, sc->sc_dmabits); - wbflush(); + alpha_mb(); } int @@ -324,7 +324,7 @@ tcds_scsi_isintr(sc, clear) if ((*sc->sc_tcds->sc_cir & sc->sc_intrbits) != 0) { if (clear) { TCDS_CIR_CLR(*sc->sc_tcds->sc_cir, sc->sc_intrbits); - wbflush(); + alpha_mb(); } return (1); } else @@ -353,11 +353,11 @@ tcds_intr(val) * Copy and clear (gag!) the interrupts. */ ir = *sc->sc_cir; - wbflush(); + alpha_mb(); TCDS_CIR_CLR(*sc->sc_cir, TCDS_CIR_ALLINTR); - wbflush(); + alpha_mb(); tc_syncbus(); - wbflush(); + alpha_mb(); #ifdef EVCNT_COUNTERS /* No interrupt counting via evcnt counters */ @@ -411,4 +411,6 @@ tcds_intr(val) * This is wrong, but machine keeps dying. */ DELAY(1); + + return (1); } diff --git a/sys/arch/alpha/tc/tcds_dma.c b/sys/arch/alpha/tc/tcds_dma.c index c62f8ea7926..b7173fdc931 100644 --- a/sys/arch/alpha/tc/tcds_dma.c +++ b/sys/arch/alpha/tc/tcds_dma.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tcds_dma.c,v 1.3 1996/07/29 23:02:36 niklas Exp $ */ -/* $NetBSD: tcds_dma.c,v 1.6 1995/12/20 00:40:32 cgd Exp $ */ +/* $OpenBSD: tcds_dma.c,v 1.4 1996/10/30 22:41:28 niklas Exp $ */ +/* $NetBSD: tcds_dma.c,v 1.13 1996/10/13 03:00:43 christos Exp $ */ /* * Copyright (c) 1994 Peter Galbavy. All rights reserved. @@ -61,15 +61,6 @@ tcds_dma_reset(sc) sc->sc_active = 0; /* and of course we aren't */ } - -void -tcds_dma_enintr(sc) - struct tcds_slotconfig *sc; -{ - - /* XXX */ -} - int tcds_dma_isintr(sc) struct tcds_slotconfig *sc; @@ -85,79 +76,6 @@ tcds_dma_isintr(sc) return x; } -#define ESPMAX (64 * 1024) -#define DMAMAX(a) (0x02000 - ((a) & 0x1fff)) - -/* - * start a dma transfer or keep it going - */ -void -tcds_dma_start(sc, addr, len, datain) - struct tcds_slotconfig *sc; - caddr_t *addr; - size_t *len; - int datain; /* DMA into main memory */ -{ - u_int32_t dic; - size_t size; - - sc->sc_dmaaddr = addr; - sc->sc_dmalen = len; - sc->sc_iswrite = datain; - - ESP_DMA(("tcds_dma %d: start %d@0x%lx,%d\n", sc->sc_slot, *sc->sc_dmalen, *sc->sc_dmaaddr, sc->sc_iswrite)); - - /* - * the rules say we cannot transfer more than the limit - * of this DMA chip (64k) and we cannot cross a 8k boundary. - */ - size = min(*sc->sc_dmalen, ESPMAX); - size = min(size, DMAMAX((size_t) *sc->sc_dmaaddr)); - sc->sc_dmasize = size; - - ESP_DMA(("dma_start: dmasize = %d\n", sc->sc_dmasize)); - - /* Load address, set/clear unaligned transfer and read/write bits. */ - /* XXX PICK AN ADDRESS TYPE, AND STICK TO IT! */ - if ((u_long)*addr > VM_MIN_KERNEL_ADDRESS) { - *sc->sc_sda = vatopa((u_long)*addr) >> 2; - } else { - *sc->sc_sda = k0segtophys((u_long)*addr) >> 2; - } - wbflush(); - dic = *sc->sc_dic; - dic &= ~TCDS_DIC_ADDRMASK; - dic |= (vm_offset_t)*addr & TCDS_DIC_ADDRMASK; - if (datain) - dic |= TCDS_DIC_WRITE; - else - dic &= ~TCDS_DIC_WRITE; - *sc->sc_dic = dic; - wbflush(); - - /* Program the SCSI counter */ - ESP_WRITE_REG(sc->sc_esp, ESP_TCL, size); - ESP_WRITE_REG(sc->sc_esp, ESP_TCM, size >> 8); - if (sc->sc_esp->sc_rev == ESP200) { - ESP_WRITE_REG(sc->sc_esp, ESP_TCH, size >> 16); - } - /* load the count in */ - ESPCMD(sc->sc_esp, ESPCMD_NOP|ESPCMD_DMA); - - /* - * Note that if `size' is 0, we've already transceived all - * the bytes we want but we're still in the DATA PHASE. - * Apparently, the device needs padding. Also, a transfer - * size of 0 means "maximum" to the chip DMA logic. - */ - ESPCMD(sc->sc_esp, (size==0?ESPCMD_TRPAD:ESPCMD_TRANS)|ESPCMD_DMA); - - sc->sc_active = 1; - - /* Start DMA */ - tcds_dma_enable(sc, 1); -} - /* * Pseudo (chained) interrupt from the esp driver to kick the * current running DMA transfer. I am replying on espintr() to @@ -246,7 +164,7 @@ tcds_dma_intr(sc) #endif ESP_DMA(("dud0 at 0x%lx dudmask 0x%x\n", addr, dudmask)); - addr = (u_int32_t *)phystok0seg(addr); + addr = (u_int32_t *)ALPHA_PHYS_TO_K0SEG((vm_offset_t)addr); *addr = (*addr & ~dudmask) | (dud & dudmask); } dud = *sc->sc_dud1; @@ -267,7 +185,7 @@ tcds_dma_intr(sc) #endif ESP_DMA(("dud1 at 0x%lx dudmask 0x%x\n", addr, dudmask)); - addr = (u_int32_t *)phystok0seg(addr); + addr = (u_int32_t *)ALPHA_PHYS_TO_K0SEG((vm_offset_t)addr); *addr = (*addr & ~dudmask) | (dud & dudmask); } /* XXX deal with saved residual byte? */ @@ -287,3 +205,75 @@ tcds_dma_intr(sc) #endif return 0; } + +#define DMAMAX(a) (0x02000 - ((a) & 0x1fff)) + +/* + * start a dma transfer or keep it going + */ +int +tcds_dma_setup(sc, addr, len, datain, dmasize) + struct tcds_slotconfig *sc; + caddr_t *addr; + size_t *len, *dmasize; + int datain; /* DMA into main memory */ +{ + u_int32_t dic; + size_t size; + + sc->sc_dmaaddr = addr; + sc->sc_dmalen = len; + sc->sc_iswrite = datain; + + ESP_DMA(("tcds_dma %d: start %d@0x%lx,%d\n", sc->sc_slot, *sc->sc_dmalen, *sc->sc_dmaaddr, sc->sc_iswrite)); + + /* + * the rules say we cannot transfer more than the limit + * of this DMA chip (64k) and we cannot cross a 8k boundary. + */ + + size = min(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr)); + *dmasize = sc->sc_dmasize = size; + + ESP_DMA(("dma_start: dmasize = %d\n", sc->sc_dmasize)); + + /* Load address, set/clear unaligned transfer and read/write bits. */ + /* XXX PICK AN ADDRESS TYPE, AND STICK TO IT! */ + if ((u_long)*addr > VM_MIN_KERNEL_ADDRESS) { + *sc->sc_sda = vatopa((u_long)*addr) >> 2; + } else { + *sc->sc_sda = ALPHA_K0SEG_TO_PHYS((u_long)*addr) >> 2; + } + alpha_mb(); + dic = *sc->sc_dic; + dic &= ~TCDS_DIC_ADDRMASK; + dic |= (vm_offset_t)*addr & TCDS_DIC_ADDRMASK; + if (datain) + dic |= TCDS_DIC_WRITE; + else + dic &= ~TCDS_DIC_WRITE; + *sc->sc_dic = dic; + alpha_mb(); + + return (0); +} + +void +tcds_dma_go(sc) + struct tcds_slotconfig *sc; +{ + + /* mark unit as DMA-active */ + sc->sc_active = 1; + + /* Start DMA */ + tcds_dma_enable(sc, 1); +} + +int +tcds_dma_isactive(sc) + struct tcds_slotconfig *sc; +{ + + return (sc->sc_active); +} diff --git a/sys/arch/alpha/tc/tcdsreg.h b/sys/arch/alpha/tc/tcdsreg.h index beec02040ea..c8839b8cf7c 100644 --- a/sys/arch/alpha/tc/tcdsreg.h +++ b/sys/arch/alpha/tc/tcdsreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tcdsreg.h,v 1.2 1996/07/29 23:02:38 niklas Exp $ */ -/* $NetBSD: tcdsreg.h,v 1.1 1995/12/20 00:40:36 cgd Exp $ */ +/* $OpenBSD: tcdsreg.h,v 1.3 1996/10/30 22:41:29 niklas Exp $ */ +/* $NetBSD: tcdsreg.h,v 1.2 1996/07/09 00:55:42 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -132,7 +132,7 @@ void tcds_scsi_reset __P((int)); /* * XXX - * Start of MACH #defines, minimal changes to port to NetBSD. + * Start of MACH #defines, minimal changes to port to {Net/Open}BSD. * * The following register is the SCSI control interrupt register. It * starts, stops and resets scsi DMA. It takes over the SCSI funtions @@ -209,7 +209,7 @@ void tcds_scsi_reset __P((int)); # define SCSI_DUDE_MASK01 0x2000000 /* Mask bit for byte[01] */ # define SCSI_DUDE_MASK10 0x4000000 /* Mask bit for byte[10] */ -#define SCSI_CIR phystok0seg(KN15AA_REG_SCSI_CIR) -#define SCSI_IMER phystok0seg(KN15AA_REG_SCSI_IMER) +#define SCSI_CIR ALPHA_PHYS_TO_K0SEG(KN15AA_REG_SCSI_CIR) +#define SCSI_IMER ALPHA_PHYS_TO_K0SEG(KN15AA_REG_SCSI_IMER) #endif diff --git a/sys/arch/alpha/tc/tcdsvar.h b/sys/arch/alpha/tc/tcdsvar.h index 82dd5f57b50..a877de2dc7f 100644 --- a/sys/arch/alpha/tc/tcdsvar.h +++ b/sys/arch/alpha/tc/tcdsvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: tcdsvar.h,v 1.3 1996/07/29 23:02:40 niklas Exp $ */ -/* $NetBSD: tcdsvar.h,v 1.3 1996/04/12 06:10:18 cgd Exp $ */ +/* $OpenBSD: tcdsvar.h,v 1.4 1996/10/30 22:41:31 niklas Exp $ */ +/* $NetBSD: tcdsvar.h,v 1.4 1996/09/09 18:10:39 cgd Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -91,16 +91,18 @@ void tcds_dma_enable __P((struct tcds_slotconfig *, int)); void tcds_scsi_enable __P((struct tcds_slotconfig *, int)); int tcds_scsi_isintr __P((struct tcds_slotconfig *, int)); void tcds_scsi_reset __P((struct tcds_slotconfig *)); +int tcds_scsi_iserr __P((struct tcds_slotconfig *)); /* * TCDS DMA functions (used the the 53c94 driver) */ -void tcds_dma_reset __P((struct tcds_slotconfig *)); -void tcds_dma_enintr __P((struct tcds_slotconfig *)); int tcds_dma_isintr __P((struct tcds_slotconfig *)); -void tcds_dma_start __P((struct tcds_slotconfig *, caddr_t *, - size_t *, int)); -int tcds_dmaintr __P((struct tcds_slotconfig *)); +void tcds_dma_reset __P((struct tcds_slotconfig *)); +int tcds_dma_intr __P((struct tcds_slotconfig *)); +int tcds_dma_setup __P((struct tcds_slotconfig *, caddr_t *, size_t *, + int, size_t *)); +void tcds_dma_go __P((struct tcds_slotconfig *)); +int tcds_dma_isactive __P((struct tcds_slotconfig *)); /* * The TCDS (bus) cfdriver, so that subdevices can more diff --git a/sys/arch/alpha/wscons/ascii.h b/sys/arch/alpha/wscons/ascii.h index 7569e04fa31..e5a508d5d9c 100644 --- a/sys/arch/alpha/wscons/ascii.h +++ b/sys/arch/alpha/wscons/ascii.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ascii.h,v 1.2 1996/07/29 23:02:46 niklas Exp $ */ +/* $OpenBSD: ascii.h,v 1.3 1996/10/30 22:41:35 niklas Exp $ */ /* $NetBSD: ascii.h,v 1.1 1996/04/12 02:00:42 cgd Exp $ */ #define ASCII_BEL 0x07 /* bell */ diff --git a/sys/arch/alpha/wscons/event.c b/sys/arch/alpha/wscons/event.c index 614704b3f9d..57874c90736 100644 --- a/sys/arch/alpha/wscons/event.c +++ b/sys/arch/alpha/wscons/event.c @@ -1,5 +1,5 @@ -/* $OpenBSD: event.c,v 1.2 1996/07/29 23:02:48 niklas Exp $ */ -/* $NetBSD: event.c,v 1.1.4.1 1996/05/29 22:26:54 cgd Exp $ */ +/* $OpenBSD: event.c,v 1.3 1996/10/30 22:41:36 niklas Exp $ */ +/* $NetBSD: event.c,v 1.3 1996/09/15 17:15:26 cgd Exp $ */ /* * Copyright (c) 1992, 1993 @@ -55,6 +55,10 @@ #include <sys/proc.h> #include <sys/systm.h> #include <sys/vnode.h> +#include <sys/select.h> +#ifdef notyet +#include <sys/poll.h> +#endif #include <machine/vuid_event.h> #include <alpha/wscons/event_var.h> @@ -85,7 +89,7 @@ ev_fini(ev) } /* - * User-level interface: read, select. + * User-level interface: read, poll. * (User cannot write an event queue.) */ int @@ -145,6 +149,26 @@ ev_read(ev, uio, flags) return (error); } +#ifdef notyet +int +ev_poll(ev, events, p) + register struct evvar *ev; + int events; + struct proc *p; +{ + int revents = 0; + int s = splev(); + + if (events & (POLLIN | POLLRDNORM)) + if (ev->ev_get != ev->ev_put) + revents |= events & (POLLIN | POLLRDNORM); + else + selrecord(p, &ev->ev_sel); + + splx(s); + return (revents); +} +#else int ev_select(ev, rw, p) register struct evvar *ev; @@ -171,3 +195,4 @@ ev_select(ev, rw, p) splx(s); return (0); } +#endif diff --git a/sys/arch/alpha/wscons/event_var.h b/sys/arch/alpha/wscons/event_var.h index bb8d9337c32..f9f0e00070c 100644 --- a/sys/arch/alpha/wscons/event_var.h +++ b/sys/arch/alpha/wscons/event_var.h @@ -1,5 +1,5 @@ -/* $OpenBSD: event_var.h,v 1.2 1996/07/29 23:02:50 niklas Exp $ */ -/* $NetBSD: event_var.h,v 1.1 1996/04/12 02:00:45 cgd Exp $ */ +/* $OpenBSD: event_var.h,v 1.3 1996/10/30 22:41:37 niklas Exp $ */ +/* $NetBSD: event_var.h,v 1.2 1996/09/15 17:15:27 cgd Exp $ */ /* * Copyright (c) 1992, 1993 @@ -79,7 +79,11 @@ struct evvar { void ev_init __P((struct evvar *)); void ev_fini __P((struct evvar *)); int ev_read __P((struct evvar *, struct uio *, int)); +#ifdef notyet +int ev_poll __P((struct evvar *, int, struct proc *)); +#else int ev_select __P((struct evvar *, int, struct proc *)); +#endif /* * PEVENT is set just above PSOCK, which is just above TTIPRI, on the diff --git a/sys/arch/alpha/wscons/kbd.c b/sys/arch/alpha/wscons/kbd.c index dbc00f0c542..c2782435e2b 100644 --- a/sys/arch/alpha/wscons/kbd.c +++ b/sys/arch/alpha/wscons/kbd.c @@ -1,5 +1,5 @@ -/* $OpenBSD: kbd.c,v 1.2 1996/07/29 23:02:51 niklas Exp $ */ -/* $NetBSD: kbd.c,v 1.1 1996/04/12 02:00:46 cgd Exp $ */ +/* $OpenBSD: kbd.c,v 1.3 1996/10/30 22:41:39 niklas Exp $ */ +/* $NetBSD: kbd.c,v 1.2 1996/09/15 17:15:28 cgd Exp $ */ /* * Copyright (c) 1992, 1993 @@ -57,6 +57,7 @@ #include <sys/ioctl.h> #include <sys/kernel.h> #include <sys/proc.h> +#include <sys/signalvar.h> #include <sys/syslog.h> #include <sys/systm.h> #include <sys/tty.h> @@ -68,6 +69,7 @@ #include <machine/wsconsio.h> /* XXX for bell ioctls */ #include <alpha/wscons/event_var.h> #include <alpha/wscons/wsconsvar.h> +#include <alpha/wscons/kbd.h> struct kbd_softc { struct device *k_idev; /* the input device */ @@ -169,9 +171,6 @@ kbd_input(register int c) int kbdopen(dev_t dev, int flags, int mode, struct proc *p) { - int s; - struct tty *tp; - if (kbd_softc.k_events.ev_io) return (EBUSY); kbd_softc.k_events.ev_io = p; @@ -286,12 +285,19 @@ kbdioctl(dev_t dev, u_long cmd, register caddr_t data, int flag, struct proc *p) return (rv); } +#ifdef notyet +int +kbdpoll(dev_t dev, int events, struct proc *p) +{ + return (ev_poll(&kbd_softc.k_events, events, p)); +} +#else int kbdselect(dev_t dev, int rw, struct proc *p) { - return (ev_select(&kbd_softc.k_events, rw, p)); } +#endif /* Ring the console bell. (For wscons terminal emulator and other code) */ void diff --git a/sys/arch/alpha/wscons/kbd.h b/sys/arch/alpha/wscons/kbd.h new file mode 100644 index 00000000000..e2bcf6ed5af --- /dev/null +++ b/sys/arch/alpha/wscons/kbd.h @@ -0,0 +1,49 @@ +/* $OpenBSD: kbd.h,v 1.1 1996/10/30 22:41:41 niklas Exp $ */ + +/* + * Copyright (c) 1996 Niklas Hallqvist + * 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 Niklas Hallqvist. + * 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 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. + */ + +extern void kbdattach __P((struct device *, struct wscons_idev_spec *)); +extern void kbd_repeat __P((void *)); +extern void kbd_input __P((int)); +extern int kbdopen __P((dev_t, int, int, struct proc *)); +extern int kbdclose __P((dev_t, int, int, struct proc *p)); +extern int kbdread __P((dev_t, struct uio *, int)); +extern int kbdwrite __P((dev_t, struct uio *, int)); +extern int kbdioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +#ifdef notyet +extern int kbdpoll __P((dev_t, int, struct proc *)); +#else +extern int kbdselect __P((dev_t, int, struct proc *)); +#endif +extern int kbd_cngetc __P((dev_t)); +extern void kbd_cnpollc __P((dev_t, int)); +extern void wscons_kbd_bell __P((void)); diff --git a/sys/arch/alpha/wscons/ms.c b/sys/arch/alpha/wscons/ms.c index ed544fec876..938cffd4b8d 100644 --- a/sys/arch/alpha/wscons/ms.c +++ b/sys/arch/alpha/wscons/ms.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ms.c,v 1.2 1996/07/29 23:02:53 niklas Exp $ */ -/* $NetBSD: ms.c,v 1.1 1996/04/12 02:00:47 cgd Exp $ */ +/* $OpenBSD: ms.c,v 1.3 1996/10/30 22:41:43 niklas Exp $ */ +/* $NetBSD: ms.c,v 1.2 1996/09/15 17:15:29 cgd Exp $ */ /* * Copyright (c) 1992, 1993 @@ -54,6 +54,7 @@ #include <sys/ioctl.h> #include <sys/kernel.h> #include <sys/proc.h> +#include <sys/signalvar.h> #include <sys/syslog.h> #include <sys/systm.h> #include <sys/tty.h> @@ -61,6 +62,7 @@ #include <machine/vuid_event.h> #include <alpha/wscons/event_var.h> #include <alpha/wscons/wsconsvar.h> +#include <alpha/wscons/ms.h> struct ms_softc { struct device *ms_dev; @@ -177,7 +179,7 @@ msopen(dev, flags, mode, p) int flags, mode; struct proc *p; { - int s, error; + int error; if (ms_softc.ms_dev == NULL) /* never attached! */ return (ENXIO); @@ -246,8 +248,6 @@ msioctl(dev, cmd, data, flag, p) int flag; struct proc *p; { - int s; - switch (cmd) { case FIONBIO: /* we will remove this someday (soon???) */ @@ -275,12 +275,22 @@ msioctl(dev, cmd, data, flag, p) return (ENOTTY); } +#ifdef notyet +int +mspoll(dev, events, p) + dev_t dev; + int events; + struct proc *p; +{ + return (ev_poll(&ms_softc.ms_events, events, p)); +} +#else int msselect(dev, rw, p) dev_t dev; int rw; struct proc *p; { - return (ev_select(&ms_softc.ms_events, rw, p)); } +#endif diff --git a/sys/arch/alpha/wscons/ms.h b/sys/arch/alpha/wscons/ms.h new file mode 100644 index 00000000000..cedfd65f73b --- /dev/null +++ b/sys/arch/alpha/wscons/ms.h @@ -0,0 +1,45 @@ +/* $OpenBSD: ms.h,v 1.1 1996/10/30 22:41:44 niklas Exp $ */ + +/* + * Copyright (c) 1996 Niklas Hallqvist + * 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 Niklas Hallqvist. + * 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 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. + */ + +extern void msattach __P((struct device *, struct wscons_mdev_spec *)); +extern void ms_event __P((char, int, int)); +extern int msopen __P((dev_t, int, int, struct proc *)); +extern int msclose __P((dev_t, int, int, struct proc *)); +extern int msread __P((dev_t, struct uio *, int)); +extern int mswrite __P((dev_t, struct uio *, int)); +extern int msioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +#ifdef notyet +extern int mspoll __P((dev_t, int, struct proc *)); +#else +extern int msselect __P((dev_t, int, struct proc *)); +#endif diff --git a/sys/arch/alpha/wscons/wscons.c b/sys/arch/alpha/wscons/wscons.c index 9d8be9ab787..c86feeea15e 100644 --- a/sys/arch/alpha/wscons/wscons.c +++ b/sys/arch/alpha/wscons/wscons.c @@ -1,5 +1,5 @@ -/* $OpenBSD: wscons.c,v 1.2 1996/07/29 23:02:55 niklas Exp $ */ -/* $NetBSD: wscons.c,v 1.3.4.1 1996/06/03 18:54:35 cgd Exp $ */ +/* $OpenBSD: wscons.c,v 1.3 1996/10/30 22:41:46 niklas Exp $ */ +/* $NetBSD: wscons.c,v 1.7 1996/10/13 03:00:45 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -42,6 +42,7 @@ #include <dev/cons.h> #include <alpha/wscons/wsconsvar.h> #include <alpha/wscons/wscons_emul.h> +#include <alpha/wscons/kbd.h> #include <machine/wsconsio.h> cdev_decl(wscons); @@ -432,6 +433,7 @@ wsconsstop(tp, flag) if (!ISSET(tp->t_state, TS_TTSTOP)) SET(tp->t_state, TS_FLUSH); splx(s); + return 0; } /* @@ -492,5 +494,5 @@ wscons_cnpollc(dev, i) int i; { - kbd_cngetc(dev, i); /* XXX XXX */ + kbd_cnpollc(dev, i); /* XXX XXX */ } diff --git a/sys/arch/alpha/wscons/wscons_emul.c b/sys/arch/alpha/wscons/wscons_emul.c index 623ee8d2511..0fd4450c4a3 100644 --- a/sys/arch/alpha/wscons/wscons_emul.c +++ b/sys/arch/alpha/wscons/wscons_emul.c @@ -1,5 +1,5 @@ -/* $OpenBSD: wscons_emul.c,v 1.2 1996/07/29 23:02:57 niklas Exp $ */ -/* $NetBSD: wscons_emul.c,v 1.2 1996/04/12 06:10:29 cgd Exp $ */ +/* $OpenBSD: wscons_emul.c,v 1.3 1996/10/30 22:41:47 niklas Exp $ */ +/* $NetBSD: wscons_emul.c,v 1.4 1996/10/13 03:00:47 christos Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -36,8 +36,18 @@ #include <sys/systm.h> #include <alpha/wscons/wsconsvar.h> #include <alpha/wscons/wscons_emul.h> +#include <alpha/wscons/kbd.h> #include <alpha/wscons/ascii.h> +static __inline int wscons_emul_input_normal + __P((struct wscons_emul_data *, char)); +static __inline int wscons_emul_input_haveesc + __P((struct wscons_emul_data *, char)); +static __inline void wscons_emul_docontrol + __P((struct wscons_emul_data *, char)); +static __inline int wscons_emul_input_control + __P((struct wscons_emul_data *, char)); + void wscons_emul_attach(we, wo) struct wscons_emul_data *we; @@ -74,7 +84,7 @@ wscons_emul_attach(we, wo) (*we->ac_ef->wef_cursor)(we->ac_efa, 1, we->ac_crow, we->ac_ccol); } -static inline int +static __inline int wscons_emul_input_normal(we, c) struct wscons_emul_data *we; char c; @@ -195,7 +205,7 @@ wscons_emul_input_normal(we, c) return newstate; } -static inline int +static __inline int wscons_emul_input_haveesc(we, c) struct wscons_emul_data *we; char c; @@ -219,7 +229,7 @@ wscons_emul_input_haveesc(we, c) return newstate; } -static inline void +static __inline void wscons_emul_docontrol(we, c) struct wscons_emul_data *we; char c; @@ -349,7 +359,7 @@ wscons_emul_docontrol(we, c) } } -static inline int +static __inline int wscons_emul_input_control(we, c) struct wscons_emul_data *we; char c; diff --git a/sys/arch/alpha/wscons/wscons_emul.h b/sys/arch/alpha/wscons/wscons_emul.h index 334e556464d..12368860050 100644 --- a/sys/arch/alpha/wscons/wscons_emul.h +++ b/sys/arch/alpha/wscons/wscons_emul.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wscons_emul.h,v 1.2 1996/07/29 23:02:59 niklas Exp $ */ +/* $OpenBSD: wscons_emul.h,v 1.3 1996/10/30 22:41:49 niklas Exp $ */ /* $NetBSD: wscons_emul.h,v 1.2 1996/04/12 06:10:32 cgd Exp $ */ /* diff --git a/sys/arch/alpha/wscons/wscons_raster.h b/sys/arch/alpha/wscons/wscons_raster.h index 9de352b40cd..5a1d4a6b336 100644 --- a/sys/arch/alpha/wscons/wscons_raster.h +++ b/sys/arch/alpha/wscons/wscons_raster.h @@ -1,5 +1,5 @@ -/* $OpenBSD: wscons_raster.h,v 1.2 1996/07/29 23:03:00 niklas Exp $ */ -/* $NetBSD: wscons_raster.h,v 1.1 1996/04/12 02:00:51 cgd Exp $ */ +/* $OpenBSD: wscons_raster.h,v 1.3 1996/10/30 22:41:50 niklas Exp $ */ +/* $NetBSD: wscons_raster.h,v 1.2 1996/07/09 00:55:47 cgd Exp $ */ /* * Copyright (c) 1992, 1993 @@ -75,7 +75,9 @@ struct rcons { }; #define RC_STANDOUT 0x001 /* standout mode */ -/* #define RC_BOLD 0x? /* boldface mode */ +#if 0 +#define RC_BOLD 0x? /* boldface mode */ +#endif #define RC_INVERT 0x002 /* inverted screen colors */ #define RC_CURSOR 0x004 /* cursor currently displayed */ diff --git a/sys/arch/alpha/wscons/wscons_rfont.h b/sys/arch/alpha/wscons/wscons_rfont.h index b9321173025..65c1e878dc9 100644 --- a/sys/arch/alpha/wscons/wscons_rfont.h +++ b/sys/arch/alpha/wscons/wscons_rfont.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wscons_rfont.h,v 1.2 1996/07/29 23:03:02 niklas Exp $ */ +/* $OpenBSD: wscons_rfont.h,v 1.3 1996/10/30 22:41:52 niklas Exp $ */ /* $NetBSD: wscons_rfont.h,v 1.1 1996/04/12 02:00:52 cgd Exp $ */ /* diff --git a/sys/arch/alpha/wscons/wscons_rinit.c b/sys/arch/alpha/wscons/wscons_rinit.c index 66e3dcaeb6d..3556c285800 100644 --- a/sys/arch/alpha/wscons/wscons_rinit.c +++ b/sys/arch/alpha/wscons/wscons_rinit.c @@ -1,5 +1,5 @@ -/* $OpenBSD: wscons_rinit.c,v 1.2 1996/07/29 23:03:04 niklas Exp $ */ -/* $NetBSD: wscons_rinit.c,v 1.1 1996/04/12 02:00:54 cgd Exp $ */ +/* $OpenBSD: wscons_rinit.c,v 1.3 1996/10/30 22:41:54 niklas Exp $ */ +/* $NetBSD: wscons_rinit.c,v 1.2 1996/07/09 00:55:50 cgd Exp $ */ /* * Copyright (c) 1991, 1993 @@ -46,7 +46,7 @@ */ #include <sys/param.h> -#include <sys/kernel.h> +#include <sys/systm.h> #include <sys/device.h> #include <dev/rcons/raster.h> @@ -54,6 +54,8 @@ #include <alpha/wscons/wscons_rfont.h> +void rcons_initfont __P((struct rcons *, struct raster_font *)); + void rcons_initfont(rc, fp) struct rcons *rc; diff --git a/sys/arch/alpha/wscons/wscons_rops.c b/sys/arch/alpha/wscons/wscons_rops.c index 98ed8eab10b..24a461cca38 100644 --- a/sys/arch/alpha/wscons/wscons_rops.c +++ b/sys/arch/alpha/wscons/wscons_rops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wscons_rops.c,v 1.2 1996/07/29 23:03:06 niklas Exp $ */ +/* $OpenBSD: wscons_rops.c,v 1.3 1996/10/30 22:41:55 niklas Exp $ */ /* $NetBSD: wscons_rops.c,v 1.1 1996/04/12 02:00:55 cgd Exp $ */ /* diff --git a/sys/arch/alpha/wscons/wsconsvar.h b/sys/arch/alpha/wscons/wsconsvar.h index 361113545eb..27db5939d40 100644 --- a/sys/arch/alpha/wscons/wsconsvar.h +++ b/sys/arch/alpha/wscons/wsconsvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wsconsvar.h,v 1.2 1996/07/29 23:03:07 niklas Exp $ */ +/* $OpenBSD: wsconsvar.h,v 1.3 1996/10/30 22:41:56 niklas Exp $ */ /* $NetBSD: wsconsvar.h,v 1.2 1996/04/12 06:10:36 cgd Exp $ */ /* |