diff options
Diffstat (limited to 'sys/arch/sparc')
163 files changed, 7433 insertions, 5602 deletions
diff --git a/sys/arch/sparc/conf/GENERIC b/sys/arch/sparc/conf/GENERIC index 6b92f12c767..66e4e9956a1 100644 --- a/sys/arch/sparc/conf/GENERIC +++ b/sys/arch/sparc/conf/GENERIC @@ -41,6 +41,7 @@ sbus0 at iommu0 # sun4m audio0 at mainbus0 # sun4c audio0 at obio0 # sun4m +audio0 at sbus0 slot ? offset ? # sun4m auxreg0 at mainbus0 # sun4c auxreg0 at obio0 # sun4m @@ -119,9 +120,11 @@ esp* at dma? flags 0xff0f # depending on model ledma0 at sbus0 slot ? offset ? # sun4m on-board le0 at ledma0 # -# Additional SBus LANCE devices - glued on by lebuffer (not yet implemented) -#lebuffer* at sbus0 slot ? offset ? # sun4m SBus -#le* at lebuffer? # +# Additional SBus LANCE devices - glued on by lebuffer +lebuffer0 at sbus0 slot ? offset ? # sun4m SBus +lebuffer* at sbus? slot ? offset ? # sun4m SBus +le0 at lebuffer0 # +le* at lebuffer? # # sun4/300 and sun4c Ethernet - an AMD 7990 LANCE le0 at sbus0 slot ? offset ? # sun4c on-board @@ -209,9 +212,17 @@ cgsix0 at obio0 addr 0x0b000000 level 4 # sun4/100 P4 cgeight0 at obio0 addr 0xfb300000 level 4 # sun4/300 P4 cgeight0 at obio0 addr 0x0b300000 level 4 # sun4/100 P4 +# Sun "tcx" accelerated color framebuffer. +tcx0 at sbus? slot ? offset ? +tcx* at sbus? slot ? offset ? + +# Sun "cgfourteen" accelerated 24-bit framebuffer. +cgfourteen0 at obio0 # sun4m + # SCSI bus layer. SCSI devices attach to the SCSI bus, which attaches # to the underlying hardware controller. scsibus* at esp? +#scsibus* at isp? scsibus* at si? scsibus* at sw? diff --git a/sys/arch/sparc/conf/files.sparc b/sys/arch/sparc/conf/files.sparc index 15dd29e1559..2615ba65760 100644 --- a/sys/arch/sparc/conf/files.sparc +++ b/sys/arch/sparc/conf/files.sparc @@ -1,4 +1,5 @@ -# $NetBSD: files.sparc,v 1.23 1996/05/21 19:06:26 pk Exp $ +# $OpenBSD: files.sparc,v 1.12 1997/08/08 08:24:35 downsj Exp $ +# $NetBSD: files.sparc,v 1.40 1997/07/07 21:53:43 pk Exp $ # @(#)files.sparc 8.1 (Berkeley) 7/19/93 # sparc-specific configuration info @@ -13,15 +14,19 @@ attach mainbus at root device obio { [addr = -1], [level = -1] } attach obio at mainbus + +device iommu {} +attach iommu at mainbus +file arch/sparc/sparc/iommu.c iommu + +device vme {} +attach vme at iommu + device vmel { [addr = -1], [level = -1], [vect = -1] } -attach vmel at mainbus +attach vmel at mainbus, vme device vmes { [addr = -1], [level = -1], [vect = -1] } -attach vmes at mainbus -file arch/sparc/dev/obio.c obio | vmel | vmes - -device audio -attach audio at mainbus, obio -file arch/sparc/dev/amd7930.c audio +attach vmes at mainbus, vme +file arch/sparc/dev/obio.c obio | vmel | vmes | vme device auxreg attach auxreg at mainbus, obio @@ -63,10 +68,6 @@ attach fd at fdc file arch/sparc/dev/fd.c fdc | fd needs-flag file arch/sparc/sparc/bsd_fdintr.s fdc -device iommu {} -attach iommu at mainbus -file arch/sparc/sparc/iommu.c iommu - device sbus { slot = -1, offset = -1 } attach sbus at mainbus, iommu file arch/sparc/dev/sbus.c sbus @@ -92,11 +93,19 @@ attach dma at sbus, obio device ledma {} attach ledma at sbus file arch/sparc/dev/dma.c dma | ledma +device lebuffer {} +attach lebuffer at sbus +file arch/sparc/dev/lebuffer.c lebuffer -device esp: scsi +device esp: scsi, ncr53c9x attach esp at sbus, dma, obio file arch/sparc/dev/esp.c esp +device audio +attach audio at mainbus, obio, sbus +file arch/sparc/dev/amd7930.c audio +file arch/sparc/sparc/amd7930intr.s audio + # Brooktree DAC attribute define bt_dac @@ -124,10 +133,18 @@ device cgeight: bt_dac attach cgeight at obio file arch/sparc/dev/cgeight.c cgeight needs-flag +device tcx: bt_dac +attach tcx at sbus +file arch/sparc/dev/tcx.c tcx needs-flag + +device cgfourteen +attach cgfourteen at obio +file arch/sparc/dev/cgfourteen.c cgfourteen needs-flag + file arch/sparc/dev/bt_subr.c bt_dac # device definition in sys/conf/files -attach le at sbus, ledma, obio +attach le at sbus, ledma, lebuffer, obio file arch/sparc/dev/if_le.c le device ie: ifnet, ether @@ -154,10 +171,24 @@ device sw: scsi, ncr5380sbc attach sw at obio file arch/sparc/dev/si.c si | sw +# Efficient Networks, Inc. ATM interface +# device declaration in sys/conf/files +#attach en at sbus with en_sbus +#file arch/sparc/dev/if_en_sbus.c en_sbus + +# Qlogic ISP 10x0 (Sbus) family +# device declaration in sys/conf/files +#attach isp at sbus with isp_sbus +#file arch/sparc/dev/isp_sbus.c isp_sbus + pseudo-device kbd +# +# Generic Sun stuff +# +include "../../../dev/sun/files.sun" + file arch/sparc/dev/cons.c -file arch/sparc/dev/event.c file arch/sparc/dev/fb.c file arch/sparc/dev/ms.c file arch/sparc/dev/kbd.c kbd @@ -175,9 +206,9 @@ file arch/sparc/fpu/fpu_subr.c # N.B.: optimizer breaks pmap.c and/or cache.c somehow -- have not # identified the exact problem yet. NOOPT_C suffices for now. file arch/sparc/sparc/autoconf.c -file arch/sparc/sparc/amd7930intr.s audio file arch/sparc/sparc/cache.c file arch/sparc/sparc/conf.c +file arch/sparc/sparc/emul.c file arch/sparc/sparc/in_cksum.c file arch/sparc/sparc/intr.c file arch/sparc/sparc/kgdb_stub.c diff --git a/sys/arch/sparc/dev/amd7930.c b/sys/arch/sparc/dev/amd7930.c index bb250924af1..998e89f5d1f 100644 --- a/sys/arch/sparc/dev/amd7930.c +++ b/sys/arch/sparc/dev/amd7930.c @@ -1,4 +1,4 @@ -/* $OpenBSD: amd7930.c,v 1.8 1997/07/13 21:48:42 angelos Exp $ */ +/* $OpenBSD: amd7930.c,v 1.9 1997/08/08 08:24:37 downsj Exp $ */ /* $NetBSD: amd7930.c,v 1.10 1996/03/31 22:38:29 pk Exp $ */ /* @@ -304,8 +304,7 @@ amd7930attach(parent, self, args) pri = ra->ra_intr[0].int_pri; printf(" pri %d, softpri %d\n", pri, PIL_AUSOFT); amd = (volatile struct amd7930 *)(ra->ra_vaddr ? - ra->ra_vaddr : mapiodev(ra->ra_reg, 0, sizeof (*amd), - ca->ca_bustype)); + ra->ra_vaddr : mapiodev(ra->ra_reg, 0, sizeof (*amd))); sc->sc_map.mr_mmr1 = AMD_MMR1_GX | AMD_MMR1_GER | AMD_MMR1_GR | AMD_MMR1_STG; diff --git a/sys/arch/sparc/dev/amd7930var.h b/sys/arch/sparc/dev/amd7930var.h index 2d2e5f28257..8e6cf85e529 100644 --- a/sys/arch/sparc/dev/amd7930var.h +++ b/sys/arch/sparc/dev/amd7930var.h @@ -1,3 +1,4 @@ +/* $OpenBSD: amd7930var.h,v 1.3 1997/08/08 08:24:38 downsj Exp $ */ /* $NetBSD: amd7930var.h,v 1.3 1996/02/01 22:32:25 mycroft Exp $ */ /* diff --git a/sys/arch/sparc/dev/bt_subr.c b/sys/arch/sparc/dev/bt_subr.c index 2a1df0ad71b..11105ffa29d 100644 --- a/sys/arch/sparc/dev/bt_subr.c +++ b/sys/arch/sparc/dev/bt_subr.c @@ -1,3 +1,4 @@ +/* $OpenBSD: bt_subr.c,v 1.3 1997/08/08 08:24:39 downsj Exp $ */ /* $NetBSD: bt_subr.c,v 1.5 1996/03/14 19:44:32 christos Exp $ */ /* diff --git a/sys/arch/sparc/dev/btreg.h b/sys/arch/sparc/dev/btreg.h index aa3f5fbc0db..e146117c25b 100644 --- a/sys/arch/sparc/dev/btreg.h +++ b/sys/arch/sparc/dev/btreg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: btreg.h,v 1.3 1997/08/08 08:24:40 downsj Exp $ */ /* $NetBSD: btreg.h,v 1.4 1996/02/27 22:09:21 thorpej Exp $ */ /* diff --git a/sys/arch/sparc/dev/btvar.h b/sys/arch/sparc/dev/btvar.h index 68be1189422..e08df3b8b1c 100644 --- a/sys/arch/sparc/dev/btvar.h +++ b/sys/arch/sparc/dev/btvar.h @@ -1,3 +1,4 @@ +/* $OpenBSD: btvar.h,v 1.2 1997/08/08 08:24:41 downsj Exp $ */ /* $NetBSD: btvar.h,v 1.2 1994/11/20 20:51:56 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/dev/bwtwo.c b/sys/arch/sparc/dev/bwtwo.c index f629c0cffa4..e8f1177fea5 100644 --- a/sys/arch/sparc/dev/bwtwo.c +++ b/sys/arch/sparc/dev/bwtwo.c @@ -1,5 +1,5 @@ -/* $OpenBSD: bwtwo.c,v 1.13 1996/08/13 08:05:18 downsj Exp $ */ -/* $NetBSD: bwtwo.c,v 1.26 1996/04/01 17:30:15 christos Exp $ */ +/* $OpenBSD: bwtwo.c,v 1.14 1997/08/08 08:24:43 downsj Exp $ */ +/* $NetBSD: bwtwo.c,v 1.33 1997/05/24 20:16:02 pk Exp $ */ /* * Copyright (c) 1996 Jason R. Thorpe. All rights reserved. @@ -105,14 +105,13 @@ struct bwtwo_softc { /* autoconfiguration driver */ static void bwtwoattach __P((struct device *, struct device *, void *)); static int bwtwomatch __P((struct device *, void *, void *)); -int bwtwoopen __P((dev_t, int, int, struct proc *)); -int bwtwoclose __P((dev_t, int, int, struct proc *)); -int bwtwoioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -int bwtwommap __P((dev_t, int, int)); static void bwtwounblank __P((struct device *)); static void bwtwo_set_video __P((struct bwtwo_softc *, int)); static int bwtwo_get_video __P((struct bwtwo_softc *)); +/* cdevsw prototypes */ +cdev_decl(bwtwo); + struct cfattach bwtwo_ca = { sizeof(struct bwtwo_softc), bwtwomatch, bwtwoattach }; @@ -212,14 +211,13 @@ bwtwoattach(parent, self, args) * Map the control register. */ if (fb->fb_flags & FB_PFOUR) { - fb->fb_pfour = - (volatile u_int32_t *)mapiodev(ca->ca_ra.ra_reg, 0, - sizeof(u_int32_t), ca->ca_bustype); + fb->fb_pfour = (volatile u_int32_t *) + mapiodev(ca->ca_ra.ra_reg, 0, sizeof(u_int32_t)); sc->sc_reg = NULL; } else { - sc->sc_reg = - (volatile struct fbcontrol *)mapiodev(ca->ca_ra.ra_reg, - BWREG_REG, sizeof(struct fbcontrol), ca->ca_bustype); + sc->sc_reg = (volatile struct fbcontrol *) + mapiodev(ca->ca_ra.ra_reg, BWREG_REG, + sizeof(struct fbcontrol)); fb->fb_pfour = NULL; } @@ -291,13 +289,13 @@ bwtwoattach(parent, self, args) #if defined(SUN4) if (CPU_ISSUN4) { struct eeprom *eep = (struct eeprom *)eeprom_va; - int constype = (fb->fb_flags & FB_PFOUR) ? EED_CONS_P4 : - EED_CONS_BW; + int constype = (fb->fb_flags & FB_PFOUR) ? EE_CONS_P4OPT : + EE_CONS_BW; /* * Assume this is the console if there's no eeprom info * to be found. */ - if (eep == NULL || eep->ee_diag.eed_console == constype) + if (eep == NULL || eep->eeConsole == constype) isconsole = (fbconstty != NULL); else isconsole = 0; @@ -316,8 +314,7 @@ bwtwoattach(parent, self, args) if ((fb->fb_pixels = ca->ca_ra.ra_vaddr) == NULL && isconsole) { /* this probably cannot happen (on sun4c), but what the heck */ fb->fb_pixels = - mapiodev(ca->ca_ra.ra_reg, sc->sc_pixeloffset, - ramsize, ca->ca_bustype); + mapiodev(ca->ca_ra.ra_reg, sc->sc_pixeloffset, ramsize); } /* Insure video is enabled */ @@ -326,7 +323,16 @@ bwtwoattach(parent, self, args) if (isconsole) { printf(" (console)\n"); #ifdef RASTERCONSOLE - fbrcons_init(fb); +#if defined(SUN4) + /* + * XXX rcons doesn't seem to work properly on the overlay + * XXX plane. This is a temporary kludge until someone + * XXX fixes it. + */ + if ((fb->fb_flags & FB_PFOUR) == 0 || + (sc->sc_ovtype == BWO_NONE)) +#endif + fbrcons_init(fb); #endif } else printf("\n"); @@ -456,8 +462,7 @@ bwtwommap(dev, off, prot) * I turned on PMAP_NC here to disable the cache as I was * getting horribly broken behaviour with it on. */ - return (REG2PHYS(&sc->sc_phys, sc->sc_pixeloffset + off, - sc->sc_bustype) | PMAP_NC); + return (REG2PHYS(&sc->sc_phys, sc->sc_pixeloffset + off) | PMAP_NC); } static int diff --git a/sys/arch/sparc/dev/bwtworeg.h b/sys/arch/sparc/dev/bwtworeg.h index 236f4a44929..f773d3c237e 100644 --- a/sys/arch/sparc/dev/bwtworeg.h +++ b/sys/arch/sparc/dev/bwtworeg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: bwtworeg.h,v 1.3 1997/08/08 08:24:43 downsj Exp $ */ /* $NetBSD: bwtworeg.h,v 1.3 1996/02/27 00:32:39 pk Exp $ */ /* diff --git a/sys/arch/sparc/dev/cgeight.c b/sys/arch/sparc/dev/cgeight.c index b720a24744a..48a1675266e 100644 --- a/sys/arch/sparc/dev/cgeight.c +++ b/sys/arch/sparc/dev/cgeight.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cgeight.c,v 1.7 1996/08/13 08:05:20 downsj Exp $ */ -/* $NetBSD: cgeight.c,v 1.7 1996/04/01 17:29:57 christos Exp $ */ +/* $OpenBSD: cgeight.c,v 1.8 1997/08/08 08:24:44 downsj Exp $ */ +/* $NetBSD: cgeight.c,v 1.13 1997/05/24 20:16:04 pk Exp $ */ /* * Copyright (c) 1996 Jason R. Thorpe. All rights reserved. @@ -91,14 +91,13 @@ struct cgeight_softc { /* autoconfiguration driver */ static void cgeightattach(struct device *, struct device *, void *); static int cgeightmatch(struct device *, void *, void *); -int cgeightopen __P((dev_t, int, int, struct proc *)); -int cgeightclose __P((dev_t, int, int, struct proc *)); -int cgeightioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -int cgeightmmap __P((dev_t, int, int)); #if defined(SUN4) static void cgeightunblank __P((struct device *)); #endif +/* cdevsw prototypes */ +cdev_decl(cgeight); + struct cfattach cgeight_ca = { sizeof(struct cgeight_softc), cgeightmatch, cgeightattach }; @@ -203,8 +202,8 @@ cgeightattach(parent, self, args) } /* Map the pfour register. */ - fb->fb_pfour = (volatile u_int32_t *)mapiodev(ca->ca_ra.ra_reg, 0, - sizeof(u_int32_t), ca->ca_bustype); + fb->fb_pfour = (volatile u_int32_t *) + mapiodev(ca->ca_ra.ra_reg, 0, sizeof(u_int32_t)); ramsize = PFOUR_COLOR_OFF_END - PFOUR_COLOR_OFF_OVERLAY; @@ -225,7 +224,7 @@ cgeightattach(parent, self, args) * Assume this is the console if there's no eeprom info * to be found. */ - if (eep == NULL || eep->ee_diag.eed_console == EED_CONS_P4) + if (eep == NULL || eep->eeConsole == EE_CONS_P4OPT) isconsole = (fbconstty != NULL); } @@ -248,13 +247,14 @@ cgeightattach(parent, self, args) if (isconsole) { /* XXX this is kind of a waste */ fb->fb_pixels = mapiodev(ca->ca_ra.ra_reg, - PFOUR_COLOR_OFF_OVERLAY, ramsize, ca->ca_bustype); + PFOUR_COLOR_OFF_OVERLAY, ramsize); } #endif /* Map the Brooktree. */ - sc->sc_fbc = (volatile struct fbcontrol *)mapiodev(ca->ca_ra.ra_reg, - PFOUR_COLOR_OFF_CMAP, sizeof(struct fbcontrol), ca->ca_bustype); + sc->sc_fbc = (volatile struct fbcontrol *) + mapiodev(ca->ca_ra.ra_reg, + PFOUR_COLOR_OFF_CMAP, sizeof(struct fbcontrol)); sc->sc_phys = ca->ca_ra.ra_reg[0]; sc->sc_bustype = ca->ca_bustype; @@ -405,7 +405,7 @@ cgeightmmap(dev, off, prot) panic("cgeightmap"); if ((u_int)off >= NOOVERLAY) { - off =- NOOVERLAY; + off -= NOOVERLAY; /* * X11 maps a huge chunk of the frame buffer; far more than @@ -426,7 +426,7 @@ cgeightmmap(dev, off, prot) * in enable plane */ poff = (off - START_ENABLE) + PFOUR_COLOR_OFF_ENABLE; - } else if ((u_int)off < END_COLOR) { + } else if ((u_int)off < sc->sc_fb.fb_type.fb_size) { /* * in colour plane */ @@ -458,7 +458,7 @@ cgeightmmap(dev, off, prot) * I turned on PMAP_NC here to disable the cache as I was * getting horribly broken behaviour with it on. */ - return (REG2PHYS(&sc->sc_phys, poff, sc->sc_bustype) | PMAP_NC); + return (REG2PHYS(&sc->sc_phys, poff) | PMAP_NC); } #if defined(SUN4) diff --git a/sys/arch/sparc/dev/cgeightreg.h b/sys/arch/sparc/dev/cgeightreg.h deleted file mode 100644 index 1fac1d4227c..00000000000 --- a/sys/arch/sparc/dev/cgeightreg.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $NetBSD: cgeightreg.h,v 1.4 1994/11/20 20:52:03 deraadt Exp $ */ - -/* - * Copyright (c) 1995 Theo de Raadt - * 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 Theo de Raadt. - * 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. - */ - -/* - * cgeight display registers. Much like bwtwo registers, except that - * there is a Brooktree Video DAC in there (so we also use btreg.h). - */ - -/* offsets */ -#define CG8REG_CMAP 0x200000 -#define CG8REG_P4REG 0x300000 -#define CG8REG_OVERLAY 0x400000 -#define CG8REG_ENABLE 0x600000 -#define CG8REG_COLOUR 0x800000 -#define CG8REG_END 0xa00000 - -/* same, but for gdb */ -struct cgeight_all { - char ba_nothing[0x200000]; - struct bt_regs ba_btreg; /* Brooktree registers */ - char ba_xxx1[0x100000-sizeof(struct bt_regs)]; - char ba_pfourreg[0x100000]; - char ba_overlay[0x200000]; - char ba_enable[0x200000]; - char ba_color[0x200000]; -}; diff --git a/sys/arch/sparc/dev/cgfour.c b/sys/arch/sparc/dev/cgfour.c index 279d1cb0fea..4284b1c5781 100644 --- a/sys/arch/sparc/dev/cgfour.c +++ b/sys/arch/sparc/dev/cgfour.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cgfour.c,v 1.7 1996/08/13 08:05:21 downsj Exp $ */ -/* $NetBSD: cgfour.c,v 1.7 1996/04/01 17:29:58 christos Exp $ */ +/* $OpenBSD: cgfour.c,v 1.8 1997/08/08 08:24:46 downsj Exp $ */ +/* $NetBSD: cgfour.c,v 1.13 1997/05/24 20:16:06 pk Exp $ */ /* * Copyright (c) 1996 Jason R. Thorpe. All rights reserved. @@ -95,14 +95,13 @@ struct cgfour_softc { /* autoconfiguration driver */ static void cgfourattach __P((struct device *, struct device *, void *)); static int cgfourmatch __P((struct device *, void *, void *)); -int cgfouropen __P((dev_t, int, int, struct proc *)); -int cgfourclose __P((dev_t, int, int, struct proc *)); -int cgfourioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -int cgfourmmap __P((dev_t, int, int)); #if defined(SUN4) static void cgfourunblank __P((struct device *)); #endif +/* cdevsw prototypes */ +cdev_decl(cgfour); + struct cfattach cgfour_ca = { sizeof(struct cgfour_softc), cgfourmatch, cgfourattach }; @@ -207,8 +206,8 @@ cgfourattach(parent, self, args) } /* Map the pfour register. */ - fb->fb_pfour = (volatile u_int32_t *)mapiodev(ca->ca_ra.ra_reg, 0, - sizeof(u_int32_t), ca->ca_bustype); + fb->fb_pfour = (volatile u_int32_t *) + mapiodev(ca->ca_ra.ra_reg, 0, sizeof(u_int32_t)); ramsize = PFOUR_COLOR_OFF_END - PFOUR_COLOR_OFF_OVERLAY; @@ -229,7 +228,7 @@ cgfourattach(parent, self, args) * Assume this is the console if there's no eeprom info * to be found. */ - if (eep == NULL || eep->ee_diag.eed_console == EED_CONS_P4) + if (eep == NULL || eep->eeConsole == EE_CONS_P4OPT) isconsole = (fbconstty != NULL); } @@ -252,13 +251,14 @@ cgfourattach(parent, self, args) if (isconsole) { /* XXX this is kind of a waste */ fb->fb_pixels = mapiodev(ca->ca_ra.ra_reg, - PFOUR_COLOR_OFF_OVERLAY, ramsize, ca->ca_bustype); + PFOUR_COLOR_OFF_OVERLAY, ramsize); } #endif /* Map the Brooktree. */ - sc->sc_fbc = (volatile struct fbcontrol *)mapiodev(ca->ca_ra.ra_reg, - PFOUR_COLOR_OFF_CMAP, sizeof(struct fbcontrol), ca->ca_bustype); + sc->sc_fbc = (volatile struct fbcontrol *) + mapiodev(ca->ca_ra.ra_reg, + PFOUR_COLOR_OFF_CMAP, sizeof(struct fbcontrol)); sc->sc_phys = ca->ca_ra.ra_reg[0]; sc->sc_bustype = ca->ca_bustype; @@ -403,7 +403,7 @@ cgfourmmap(dev, off, prot) panic("cgfourmap"); if ((u_int)off >= NOOVERLAY) { - off =- NOOVERLAY; + off -= NOOVERLAY; /* * X11 maps a huge chunk of the frame buffer; far more than @@ -424,7 +424,7 @@ cgfourmmap(dev, off, prot) * in enable plane */ poff = (off - START_ENABLE) + PFOUR_COLOR_OFF_ENABLE; - } else if ((u_int)off < END_COLOR) { + } else if ((u_int)off < sc->sc_fb.fb_type.fb_size) { /* * in colour plane */ @@ -432,7 +432,7 @@ cgfourmmap(dev, off, prot) } else return (-1); - return (REG2PHYS(&sc->sc_phys, poff, sc->sc_bustype) | PMAP_NC); + return (REG2PHYS(&sc->sc_phys, poff) | PMAP_NC); } #if defined(SUN4) diff --git a/sys/arch/sparc/dev/cgfourteen.c b/sys/arch/sparc/dev/cgfourteen.c new file mode 100644 index 00000000000..2786bb6a9ff --- /dev/null +++ b/sys/arch/sparc/dev/cgfourteen.c @@ -0,0 +1,877 @@ +/* $OpenBSD: cgfourteen.c,v 1.1 1997/08/08 08:24:48 downsj Exp $ */ +/* $NetBSD: cgfourteen.c,v 1.7 1997/05/24 20:16:08 pk Exp $ */ + +/* + * Copyright (c) 1996 + * The President and Fellows of Harvard College. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Harvard University. + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * 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. + * This product includes software developed by Harvard University 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. + * + * Based on: + * NetBSD: cgthree.c,v 1.28 1996/05/31 09:59:22 pk Exp + * NetBSD: cgsix.c,v 1.25 1996/04/01 17:30:00 christos Exp + */ + +/* + * Driver for Campus-II on-board mbus-based video (cgfourteen). + * Provides minimum emulation of a Sun cgthree 8-bit framebuffer to + * allow X to run. + * + * Does not handle interrupts, even though they can occur. + * + * XXX should defer colormap updates to vertical retrace interrupts + */ + +/* + * The following is for debugging only; it opens up a security hole + * enabled by allowing any user to map the control registers for the + * cg14 into their space. + */ +#undef CG14_MAP_REGS + +/* + * The following enables 24-bit operation: when opened, the framebuffer + * will switch to 24-bit mode (actually 32-bit mode), and provide a + * simple cg8 emulation. + * + * XXX Note that the code enabled by this define is currently untested/broken. + */ +#undef CG14_CG8 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <sys/ioctl.h> +#include <sys/malloc.h> +#include <sys/mman.h> +#include <sys/tty.h> +#include <sys/conf.h> + +#include <vm/vm.h> + +#include <machine/fbio.h> +#include <machine/autoconf.h> +#include <machine/pmap.h> +#include <machine/fbvar.h> +#include <machine/cpu.h> +#include <machine/conf.h> + +#include <sparc/dev/cgfourteenreg.h> +#include <sparc/dev/cgfourteenvar.h> + +/* autoconfiguration driver */ +static void cgfourteenattach(struct device *, struct device *, void *); +static int cgfourteenmatch(struct device *, void *, void *); +static void cgfourteenunblank(struct device *); + +/* cdevsw prototypes */ +cdev_decl(cgfourteen); + +struct cfattach cgfourteen_ca = { + sizeof(struct cgfourteen_softc), cgfourteenmatch, cgfourteenattach +}; + +struct cfdriver cgfourteen_cd = { + NULL, "cgfourteen", DV_DULL +}; + +/* frame buffer generic driver */ +static struct fbdriver cgfourteenfbdriver = { + cgfourteenunblank, cgfourteenopen, cgfourteenclose, cgfourteenioctl, + cgfourteenmmap +}; + +extern int fbnode; +extern struct tty *fbconstty; + +static void cg14_set_video __P((struct cgfourteen_softc *, int)); +static int cg14_get_video __P((struct cgfourteen_softc *)); +static int cg14_get_cmap __P((struct fbcmap *, union cg14cmap *, int)); +static int cg14_put_cmap __P((struct fbcmap *, union cg14cmap *, int)); +static void cg14_load_hwcmap __P((struct cgfourteen_softc *, int, int)); +static void cg14_init __P((struct cgfourteen_softc *)); +static void cg14_reset __P((struct cgfourteen_softc *)); +static void cg14_loadomap __P((struct cgfourteen_softc *));/* cursor overlay */ +static void cg14_setcursor __P((struct cgfourteen_softc *));/* set position */ +static void cg14_loadcursor __P((struct cgfourteen_softc *));/* set shape */ + +/* + * Match a cgfourteen. + */ +int +cgfourteenmatch(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct cfdata *cf = vcf; + struct confargs *ca = aux; + struct romaux *ra = &ca->ca_ra; + + /* + * Mask out invalid flags from the user. + */ + cf->cf_flags &= FB_USERMASK; + + /* Check driver name */ + if (strcmp(cf->cf_driver->cd_name, ra->ra_name)) + return (0); + + /* + * The cgfourteen is a local-bus video adaptor, accessed directly + * via the processor, and not through device space or an external + * bus. Thus we look _only_ at the obio bus. + * Additionally, these things exist only on the Sun4m. + */ + if (CPU_ISSUN4M && ca->ca_bustype == BUS_OBIO) + return(1); + return (0); +} + +/* + * Attach a display. We need to notice if it is the console, too. + */ +void +cgfourteenattach(parent, self, args) + struct device *parent, *self; + void *args; +{ + register struct cgfourteen_softc *sc = (struct cgfourteen_softc *)self; + register struct confargs *ca = args; + register int node = 0, ramsize; + register u_int32_t *lut; + int i, isconsole; + + sc->sc_fb.fb_driver = &cgfourteenfbdriver; + sc->sc_fb.fb_device = &sc->sc_dev; + sc->sc_fb.fb_flags = sc->sc_dev.dv_cfdata->cf_flags; + + /* + * We're emulating a cg3/8, so represent ourselves as one + */ +#ifdef CG14_CG8 + sc->sc_fb.fb_type.fb_type = FBTYPE_MEMCOLOR; +#else + sc->sc_fb.fb_type.fb_type = FBTYPE_SUN3COLOR; +#endif + + node = ca->ca_ra.ra_node; +#ifdef CG14_CG8 + sc->sc_fb.fb_type.fb_depth = 32; +#else + sc->sc_fb.fb_type.fb_depth = 8; +#endif + fb_setsize(&sc->sc_fb, sc->sc_fb.fb_type.fb_depth, + 1152, 900, node, ca->ca_bustype); + + ramsize = roundup(sc->sc_fb.fb_type.fb_height * sc->sc_fb.fb_linebytes, + NBPG); + + sc->sc_fb.fb_type.fb_cmsize = CG14_CLUT_SIZE; + sc->sc_fb.fb_type.fb_size = ramsize; + + /* + * Now map in the 8 useful pages of registers + */ + if (ca->ca_ra.ra_len < 0x10000) { +#ifdef DIAGNOSTIC + printf("warning: can't find all cgfourteen registers...\n"); +#endif + ca->ca_ra.ra_len = 0x10000; + } + sc->sc_ctl = (struct cg14ctl *) mapiodev(ca->ca_ra.ra_reg, 0, + ca->ca_ra.ra_len); + + sc->sc_hwc = (struct cg14curs *) ((u_int)sc->sc_ctl + + CG14_OFFSET_CURS); + sc->sc_dac = (struct cg14dac *) ((u_int)sc->sc_ctl + + CG14_OFFSET_DAC); + sc->sc_xlut = (struct cg14xlut *) ((u_int)sc->sc_ctl + + CG14_OFFSET_XLUT); + sc->sc_clut1 = (struct cg14clut *) ((u_int)sc->sc_ctl + + CG14_OFFSET_CLUT1); + sc->sc_clut2 = (struct cg14clut *) ((u_int)sc->sc_ctl + + CG14_OFFSET_CLUT2); + sc->sc_clut3 = (struct cg14clut *) ((u_int)sc->sc_ctl + + CG14_OFFSET_CLUT3); + sc->sc_clutincr = (u_int *) ((u_int)sc->sc_ctl + + CG14_OFFSET_CLUTINCR); + + /* + * Stash the physical address of the framebuffer for use by mmap + */ + if (ca->ca_ra.ra_nreg < 2) + panic("cgfourteen with only one register set; can't find" + " framebuffer"); + sc->sc_phys = ca->ca_ra.ra_reg[1]; + +#if defined(DEBUG) && defined(CG14_MAP_REGS) + /* Store the physical address of the control registers */ + sc->sc_regphys = ca->ca_ra.ra_reg[0]; +#endif + + /* + * Let the user know that we're here + */ +#ifdef CG14_CG8 + printf(": cgeight emulated at %dx%dx24bpp", + sc->sc_fb.fb_type.fb_width, sc->sc_fb.fb_type.fb_height); +#else + printf(": cgthree emulated at %dx%dx8bpp", + sc->sc_fb.fb_type.fb_width, sc->sc_fb.fb_type.fb_height); +#endif + /* + * Enable the video, but don't change the pixel depth. + */ + cg14_set_video(sc, 1); + + /* + * Grab the initial colormap + */ + lut = (u_int32_t *) sc->sc_clut1->clut_lut; + for (i = 0; i < CG14_CLUT_SIZE; i++) + sc->sc_cmap.cm_chip[i] = lut[i]; + + /* See if we're the console */ + isconsole = node == fbnode && fbconstty != NULL; + + /* + * We don't use the raster console since the cg14 is fast enough + * already. + */ +#ifdef notdef + /* + * When the ROM has mapped in a cgfourteen display, the address + * maps only the video RAM, so in any case we have to map the + * registers ourselves. We only need the video RAM if we are + * going to print characters via rconsole. + */ + if ((sc->sc_fb.fb_pixels = ca->ca_ra.ra_vaddr) == NULL && isconsole) { + /* this probably cannot happen, but what the heck */ + sc->sc_fb.fb_pixels = mapiodev(ca->ca_ra.ra_reg, CG3REG_MEM, + ramsize); + } +#endif /* notdef */ + + + if (isconsole) { + printf(" (console)\n"); +#ifdef notdef +#ifdef RASTERCONSOLE + fbrcons_init(&sc->sc_fb); +#endif +#endif /* notdef */ + } else + printf("\n"); + + /* Attach to /dev/fb */ + if (node == fbnode) + fb_attach(&sc->sc_fb, isconsole); +} + +/* + * Keep track of the number of opens made. In the 24-bit driver, we need to + * switch to 24-bit mode on the first open, and switch back to 8-bit on + * the last close. This kind of nonsense is needed to give screenblank + * a fighting chance of working. + */ +static int cg14_opens = 0; + +int +cgfourteenopen(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; +{ + register struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; + int unit = minor(dev); + int s, oldopens; + + if (unit >= cgfourteen_cd.cd_ndevs || + cgfourteen_cd.cd_devs[unit] == NULL) + return (ENXIO); + + s = splhigh(); + oldopens = cg14_opens++; + splx(s); + + /* Setup the cg14 as we want it, and save the original PROM state */ + if (oldopens == 0) /* first open only, to make screenblank work */ + cg14_init(sc); + + return (0); +} + +int +cgfourteenclose(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; +{ + register struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; + int s, opens; + + s = splhigh(); + opens = --cg14_opens; + if (cg14_opens < 0) + opens = cg14_opens = 0; + splx(s); + + /* + * Restore video state to make the PROM happy, on last close. + */ + if (opens == 0) + cg14_reset(sc); + + return (0); +} + +int +cgfourteenioctl(dev, cmd, data, flags, p) + dev_t dev; + u_long cmd; + register caddr_t data; + int flags; + struct proc *p; +{ + register struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; + register struct fbgattr *fba; + union cg14cursor_cmap tcm; + int v, error; + u_int count; + + switch (cmd) { + + case FBIOGTYPE: + *(struct fbtype *)data = sc->sc_fb.fb_type; + break; + + case FBIOGATTR: + fba = (struct fbgattr *)data; + fba->real_type = FBTYPE_MDICOLOR; + fba->owner = 0; /* XXX ??? */ + fba->fbtype = sc->sc_fb.fb_type; + fba->sattr.flags = 0; + fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; + fba->sattr.dev_specific[0] = -1; + fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; + fba->emu_types[1] = -1; + break; + + case FBIOGETCMAP: + return (cg14_get_cmap((struct fbcmap *)data, &sc->sc_cmap, + CG14_CLUT_SIZE)); + + case FBIOPUTCMAP: + /* copy to software map */ +#define p ((struct fbcmap *)data) +#ifdef CG14_CG8 + p->index &= 0xffffff; +#endif + error = cg14_put_cmap(p, &sc->sc_cmap, CG14_CLUT_SIZE); + if (error) + return (error); + /* now blast them into the chip */ + /* XXX should use retrace interrupt */ + cg14_load_hwcmap(sc, p->index, p->count); +#undef p + break; + + case FBIOGVIDEO: + *(int *)data = cg14_get_video(sc); + break; + + case FBIOSVIDEO: + cg14_set_video(sc, *(int *)data); + break; + +/* these are for both FBIOSCURSOR and FBIOGCURSOR */ +#define p ((struct fbcursor *)data) +#define cc (&sc->sc_cursor) + case FBIOGCURSOR: + /* do not quite want everything here... */ + p->set = FB_CUR_SETALL; /* close enough, anyway */ + p->enable = cc->cc_enable; + p->pos = cc->cc_pos; + p->hot = cc->cc_hot; + p->size = cc->cc_size; + + /* begin ugh ... can we lose some of this crap?? */ + if (p->image != NULL) { + count = cc->cc_size.y * 32 / NBBY; + error = copyout((caddr_t)cc->cc_cplane, + (caddr_t)p->image, count); + if (error) + return (error); + error = copyout((caddr_t)cc->cc_eplane, + (caddr_t)p->mask, count); + if (error) + return (error); + } + if (p->cmap.red != NULL) { + error = cg14_get_cmap(&p->cmap, + (union cg14cmap *)&cc->cc_color, 2); + if (error) + return (error); + } else { + p->cmap.index = 0; + p->cmap.count = 2; + } + /* end ugh */ + break; + + case FBIOSCURSOR: + /* + * For setcmap and setshape, verify parameters, so that + * we do not get halfway through an update and then crap + * out with the software state screwed up. + */ + v = p->set; + if (v & FB_CUR_SETCMAP) { + /* + * This use of a temporary copy of the cursor + * colormap is not terribly efficient, but these + * copies are small (8 bytes)... + */ + tcm = cc->cc_color; + error = cg14_put_cmap(&p->cmap, (union cg14cmap *)&tcm, + 2); + if (error) + return (error); + } + if (v & FB_CUR_SETSHAPE) { + if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32) + return (EINVAL); + count = p->size.y * 32 / NBBY; + if (!useracc(p->image, count, B_READ) || + !useracc(p->mask, count, B_READ)) + return (EFAULT); + } + + /* parameters are OK; do it */ + if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) { + if (v & FB_CUR_SETCUR) + cc->cc_enable = p->enable; + if (v & FB_CUR_SETPOS) + cc->cc_pos = p->pos; + if (v & FB_CUR_SETHOT) + cc->cc_hot = p->hot; + cg14_setcursor(sc); + } + if (v & FB_CUR_SETCMAP) { + cc->cc_color = tcm; + cg14_loadomap(sc); /* XXX defer to vertical retrace */ + } + if (v & FB_CUR_SETSHAPE) { + cc->cc_size = p->size; + count = p->size.y * 32 / NBBY; + bzero((caddr_t)cc->cc_eplane, sizeof cc->cc_eplane); + bzero((caddr_t)cc->cc_cplane, sizeof cc->cc_cplane); + bcopy(p->mask, (caddr_t)cc->cc_eplane, count); + bcopy(p->image, (caddr_t)cc->cc_cplane, count); + cg14_loadcursor(sc); + } + break; + +#undef cc +#undef p + case FBIOGCURPOS: + *(struct fbcurpos *)data = sc->sc_cursor.cc_pos; + break; + + case FBIOSCURPOS: + sc->sc_cursor.cc_pos = *(struct fbcurpos *)data; + cg14_setcursor(sc); + break; + + case FBIOGCURMAX: + /* max cursor size is 32x32 */ + ((struct fbcurpos *)data)->x = 32; + ((struct fbcurpos *)data)->y = 32; + break; + + default: + return (ENOTTY); + } + return (0); +} + +/* + * Undo the effect of an FBIOSVIDEO that turns the video off. + */ +static void +cgfourteenunblank(dev) + struct device *dev; +{ + + cg14_set_video((struct cgfourteen_softc *)dev, 1); +} + +/* + * Return the address that would map the given device at the given + * offset, allowing for the given protection, or return -1 for error. + * + * The cg14 frame buffer can be mapped in either 8-bit or 32-bit mode + * starting at the address stored in the PROM. In 8-bit mode, the X + * channel is not present, and can be ignored. In 32-bit mode, mapping + * at 0K delivers a 32-bpp buffer where the upper 8 bits select the X + * channel information. We hardwire the Xlut to all zeroes to insure + * that, regardless of this value, direct 24-bit color access will be + * used. + * + * Alternatively, mapping the frame buffer at an offset of 16M seems to + * tell the chip to ignore the X channel. XXX where does it get the X value + * to use? + */ +int +cgfourteenmmap(dev, off, prot) + dev_t dev; + int off, prot; +{ + register struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; + +#define CG3START (128*1024 + 128*1024) +#define CG8START (256*1024) +#define NOOVERLAY (0x04000000) + + if (off & PGOFSET) + panic("cgfourteenmmap"); + +#if defined(DEBUG) && defined(CG14_MAP_REGS) /* XXX: security hole */ + /* + * Map the control registers into user space. Should only be + * used for debugging! + */ + if ((u_int)off >= 0x10000000 && (u_int)off < 0x10000000 + 16*4096) { + off -= 0x10000000; + return (REG2PHYS(&sc->sc_regphys, off, 0) | PMAP_NC); + } +#endif + + if ((u_int)off >= NOOVERLAY) + off -= NOOVERLAY; +#ifdef CG14_CG8 + else if ((u_int)off >= CG8START) { + off -= CG8START; + } +#else + else if ((u_int)off >= CG3START) + off -= CG3START; +#endif + else + off = 0; + + if ((unsigned)off >= sc->sc_fb.fb_type.fb_size * + sc->sc_fb.fb_type.fb_depth/8) { +#ifdef DEBUG + printf("\nmmap request out of bounds: request 0x%x, " + "bound 0x%x\n", (unsigned) off, + (unsigned)sc->sc_fb.fb_type.fb_size); +#endif + return (-1); + } + + /* + * Use PMAP_NC to disable the cache, since otherwise refresh is + * very confused. + */ + return (REG2PHYS(&sc->sc_phys, off) | PMAP_NC); +} + +/* + * Miscellaneous helper functions + */ + +/* Initialize the framebuffer, storing away useful state for later reset */ +static void +cg14_init(sc) + struct cgfourteen_softc *sc; +{ + register u_int32_t *clut; + register u_int8_t *xlut; + register int i; + + /* + * We stash away the following to restore on close: + * + * color look-up table 1 (sc->sc_saveclut) + * x look-up table (sc->sc_savexlut) + * control register (sc->sc_savectl) + * cursor control register (sc->sc_savehwc) + */ + sc->sc_savectl = sc->sc_ctl->ctl_mctl; + sc->sc_savehwc = sc->sc_hwc->curs_ctl; + + clut = (u_int32_t *) sc->sc_clut1->clut_lut; + xlut = (u_int8_t *) sc->sc_xlut->xlut_lut; + for (i = 0; i < CG14_CLUT_SIZE; i++) { + sc->sc_saveclut.cm_chip[i] = clut[i]; + sc->sc_savexlut[i] = xlut[i]; + } + +#ifdef CG14_CG8 + /* + * Enable the video, and put in 24 bit mode. + */ + sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | CG14_MCTL_PIXMODE_32 | + CG14_MCTL_POWERCTL; + + /* + * Zero the xlut to enable direct-color mode + */ + bzero(sc->sc_xlut, CG14_CLUT_SIZE); +#else + /* + * Enable the video and put it in 8 bit mode + */ + sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | CG14_MCTL_PIXMODE_8 | + CG14_MCTL_POWERCTL; +#endif +} + +static void +cg14_reset(sc) /* Restore the state saved on cg14_init */ + struct cgfourteen_softc *sc; +{ + register u_int32_t *clut; + register u_int8_t *xlut; + register int i; + + /* + * We restore the following, saved in cg14_init: + * + * color look-up table 1 (sc->sc_saveclut) + * x look-up table (sc->sc_savexlut) + * control register (sc->sc_savectl) + * cursor control register (sc->sc_savehwc) + * + * Note that we don't touch the video enable bits in the + * control register; otherwise, screenblank wouldn't work. + */ + sc->sc_ctl->ctl_mctl = (sc->sc_ctl->ctl_mctl & (CG14_MCTL_ENABLEVID | + CG14_MCTL_POWERCTL)) | + (sc->sc_savectl & ~(CG14_MCTL_ENABLEVID | + CG14_MCTL_POWERCTL)); + sc->sc_hwc->curs_ctl = sc->sc_savehwc; + + clut = (u_int32_t *) sc->sc_clut1->clut_lut; + xlut = (u_int8_t *) sc->sc_xlut->xlut_lut; + for (i = 0; i < CG14_CLUT_SIZE; i++) { + clut[i] = sc->sc_saveclut.cm_chip[i]; + xlut[i] = sc->sc_savexlut[i]; + } +} + +/* Enable/disable video display; power down monitor if DPMS-capable */ +static void +cg14_set_video(sc, enable) + struct cgfourteen_softc *sc; + int enable; +{ + /* + * We can only use DPMS to power down the display if the chip revision + * is greater than 0. + */ + if (enable) { + if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) + sc->sc_ctl->ctl_mctl |= (CG14_MCTL_ENABLEVID | + CG14_MCTL_POWERCTL); + else + sc->sc_ctl->ctl_mctl |= CG14_MCTL_ENABLEVID; + } else { + if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) + sc->sc_ctl->ctl_mctl &= ~(CG14_MCTL_ENABLEVID | + CG14_MCTL_POWERCTL); + else + sc->sc_ctl->ctl_mctl &= ~CG14_MCTL_ENABLEVID; + } +} + +/* Get status of video display */ +static int +cg14_get_video(sc) + struct cgfourteen_softc *sc; +{ + return ((sc->sc_ctl->ctl_mctl & CG14_MCTL_ENABLEVID) != 0); +} + +/* Read the software shadow colormap */ +static int +cg14_get_cmap(p, cm, cmsize) + register struct fbcmap *p; + union cg14cmap *cm; + int cmsize; +{ + register u_int i, start, count; + register u_char *cp; + + start = p->index; + count = p->count; + if (start >= cmsize || start + count > cmsize) +#ifdef DEBUG + { + printf("putcmaperror: start %d cmsize %d count %d\n", + start,cmsize,count); +#endif + return (EINVAL); +#ifdef DEBUG + } +#endif + + if (!useracc(p->red, count, B_WRITE) || + !useracc(p->green, count, B_WRITE) || + !useracc(p->blue, count, B_WRITE)) + return (EFAULT); + for (cp = &cm->cm_map[start][0], i = 0; i < count; cp += 4, i++) { + p->red[i] = cp[3]; + p->green[i] = cp[2]; + p->blue[i] = cp[1]; + } + return (0); +} + +/* Write the software shadow colormap */ +static int +cg14_put_cmap(p, cm, cmsize) + register struct fbcmap *p; + union cg14cmap *cm; + int cmsize; +{ + register u_int i, start, count; + register u_char *cp; + + start = p->index; + count = p->count; + if (start >= cmsize || start + count > cmsize) +#ifdef DEBUG + { + printf("putcmaperror: start %d cmsize %d count %d\n", + start,cmsize,count); +#endif + return (EINVAL); +#ifdef DEBUG + } +#endif + + if (!useracc(p->red, count, B_READ) || + !useracc(p->green, count, B_READ) || + !useracc(p->blue, count, B_READ)) + return (EFAULT); + for (cp = &cm->cm_map[start][0], i = 0; i < count; cp += 4, i++) { + cp[3] = p->red[i]; + cp[2] = p->green[i]; + cp[1] = p->blue[i]; + cp[0] = 0; /* no alpha channel */ + } + return (0); +} + +static void +cg14_load_hwcmap(sc, start, ncolors) + register struct cgfourteen_softc *sc; + register int start, ncolors; +{ + /* XXX switch to auto-increment, and on retrace intr */ + + /* Setup pointers to source and dest */ + register u_int32_t *colp = &sc->sc_cmap.cm_chip[start]; + volatile register u_int32_t *lutp = &sc->sc_clut1->clut_lut[start]; + + /* Copy by words */ + while (--ncolors >= 0) + *lutp++ = *colp++; +} + +/* + * Load the cursor (overlay `foreground' and `background') colors. + */ +static void +cg14_setcursor(sc) + register struct cgfourteen_softc *sc; +{ + /* we need to subtract the hot-spot value here */ +#define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f) + + sc->sc_hwc->curs_ctl = (sc->sc_cursor.cc_enable ? CG14_CURS_ENABLE : 0); + sc->sc_hwc->curs_x = COORD(x); + sc->sc_hwc->curs_y = COORD(y); + +#undef COORD +} + +static void +cg14_loadcursor(sc) + register struct cgfourteen_softc *sc; +{ + register volatile struct cg14curs *hwc; + register u_int edgemask, m; + register int i; + + /* + * Keep the top size.x bits. Here we *throw out* the top + * size.x bits from an all-one-bits word, introducing zeros in + * the top size.x bits, then invert all the bits to get what + * we really wanted as our mask. But this fails if size.x is + * 32---a sparc uses only the low 5 bits of the shift count--- + * so we have to special case that. + */ + edgemask = ~0; + if (sc->sc_cursor.cc_size.x < 32) + edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x); + hwc = sc->sc_hwc; + for (i = 0; i < 32; i++) { + m = sc->sc_cursor.cc_eplane[i] & edgemask; + hwc->curs_plane0[i] = m; + hwc->curs_plane1[i] = m & sc->sc_cursor.cc_cplane[i]; + } +} + +static void +cg14_loadomap(sc) + register struct cgfourteen_softc *sc; +{ + /* set background color */ + sc->sc_hwc->curs_color1 = sc->sc_cursor.cc_color.cm_chip[0]; + /* set foreground color */ + sc->sc_hwc->curs_color2 = sc->sc_cursor.cc_color.cm_chip[1]; +} diff --git a/sys/arch/sparc/dev/cgfourteenreg.h b/sys/arch/sparc/dev/cgfourteenreg.h new file mode 100644 index 00000000000..c0fdb1b5c0a --- /dev/null +++ b/sys/arch/sparc/dev/cgfourteenreg.h @@ -0,0 +1,123 @@ +/* $OpenBSD: cgfourteenreg.h,v 1.1 1997/08/08 08:24:49 downsj Exp $ */ +/* $NetBSD: cgfourteenreg.h,v 1.1 1996/09/30 22:41:02 abrown Exp $ */ + +/* + * Copyright (c) 1996 + * The President and Fellows of Harvard College. 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 Harvard University 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. + */ + +/* + * Register/dac/clut/cursor definitions for cgfourteen frame buffer + */ + +/* Locations of control registers in cg14 register set */ +#define CG14_OFFSET_CURS 0x1000 +#define CG14_OFFSET_DAC 0x2000 +#define CG14_OFFSET_XLUT 0x3000 +#define CG14_OFFSET_CLUT1 0x4000 +#define CG14_OFFSET_CLUT2 0x5000 +#define CG14_OFFSET_CLUT3 0x6000 +#define CG14_OFFSET_CLUTINCR 0xf000 + +/* Main control register set */ +struct cg14ctl { + volatile u_int8_t ctl_mctl; /* main control register */ +#define CG14_MCTL_ENABLEINTR 0x80 /* interrupts */ +#define CG14_MCTL_ENABLEVID 0x40 /* enable video */ +#define CG14_MCTL_PIXMODE_MASK 0x30 +#define CG14_MCTL_PIXMODE_8 0x00 /* data is 16 8-bit pixels */ +#define CG14_MCTL_PIXMODE_16 0x20 /* data is 8 16-bit pixels */ +#define CG14_MCTL_PIXMODE_32 0x30 /* data is 4 32-bit pixels */ +#define CG14_MCTL_PIXMODE_SHIFT 4 +#define CG14_MCTL_TMR 0x0c +#define CG14_MCTL_ENABLETMR 0x02 +#define CG14_MCTL_rev0RESET 0x01 +#define CG14_MCTL_POWERCTL 0x01 + + volatile u_int8_t ctl_ppr; /* packed pixel register */ + volatile u_int8_t ctl_tmsr0; /* test status reg. 0 */ + volatile u_int8_t ctl_tmsr1; /* test status reg. 1 */ + volatile u_int8_t ctl_msr; /* master status register */ + volatile u_int8_t ctl_fsr; /* fault status register */ + volatile u_int8_t ctl_rsr; /* revision status register */ +#define CG14_RSR_REVMASK 0xf0 /* mask to get revision */ +#define CG14_RSR_IMPLMASK 0x0f /* mask to get impl. code */ + volatile u_int8_t ctl_ccr; /* clock control register */ + /* XXX etc. */ +}; + +/* Hardware cursor map */ +#define CG14_CURS_SIZE 32 +struct cg14curs { + volatile u_int32_t curs_plane0[CG14_CURS_SIZE]; /* plane 0 */ + volatile u_int32_t curs_plane1[CG14_CURS_SIZE]; + volatile u_int8_t curs_ctl; /* control register */ +#define CG14_CURS_ENABLE 0x4 +#define CG14_CURS_DOUBLEBUFFER 0x2 /* use X-channel for curs */ + volatile u_int8_t pad0[3]; + volatile u_int16_t curs_x; /* x position */ + volatile u_int16_t curs_y; /* y position */ + volatile u_int32_t curs_color1; /* color register 1 */ + volatile u_int32_t curs_color2; /* color register 2 */ + volatile u_int32_t pad[444]; /* pad to 2KB boundary */ + volatile u_int32_t curs_plane0incr[CG14_CURS_SIZE]; /* autoincr */ + volatile u_int32_t curs_plane1incr[CG14_CURS_SIZE]; /* autoincr */ +}; + +/* DAC */ +struct cg14dac { + volatile u_int8_t dac_addr; /* address register */ + volatile u_int8_t pad0[255]; + volatile u_int8_t dac_gammalut; /* gamma LUT */ + volatile u_int8_t pad1[255]; + volatile u_int8_t dac_regsel; /* register select */ + volatile u_int8_t pad2[255]; + volatile u_int8_t dac_mode; /* mode register */ +}; + +#define CG14_CLUT_SIZE 256 + +/* XLUT registers */ +struct cg14xlut { + volatile u_int8_t xlut_lut[CG14_CLUT_SIZE]; /* the LUT */ + volatile u_int8_t xlut_lutd[CG14_CLUT_SIZE]; /* ??? */ + volatile u_int8_t pad0[0x600]; + volatile u_int8_t xlut_lutinc[CG14_CLUT_SIZE]; /* autoincrLUT*/ + volatile u_int8_t xlut_lutincd[CG14_CLUT_SIZE]; +}; + +/* Color Look-Up Table (CLUT) */ +struct cg14clut { + volatile u_int32_t clut_lut[CG14_CLUT_SIZE]; /* the LUT */ + volatile u_int32_t clut_lutd[CG14_CLUT_SIZE]; /* ??? */ + volatile u_int32_t clut_lutinc[CG14_CLUT_SIZE]; /* autoincr */ + volatile u_int32_t clut_lutincd[CG14_CLUT_SIZE]; +}; diff --git a/sys/arch/sparc/dev/cgfourteenvar.h b/sys/arch/sparc/dev/cgfourteenvar.h new file mode 100644 index 00000000000..654945e01bb --- /dev/null +++ b/sys/arch/sparc/dev/cgfourteenvar.h @@ -0,0 +1,94 @@ +/* $OpenBSD: cgfourteenvar.h,v 1.1 1997/08/08 08:24:50 downsj Exp $ */ +/* $NetBSD: cgfourteenvar.h,v 1.1 1996/09/30 22:41:03 abrown Exp $ */ + +/* + * Copyright (c) 1996 + * The President and Fellows of Harvard College. 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 Harvard University 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. + */ + +/* + * Layout of cg14 hardware colormap + */ +union cg14cmap { + u_char cm_map[256][4]; /* 256 R/G/B/A entries (B is high)*/ + u_int32_t cm_chip[256]; /* the way the chip gets loaded */ +}; + +/* + * cg14 hardware cursor colormap + */ +union cg14cursor_cmap { /* colormap, like bt_cmap, but tiny */ + u_char cm_map[2][4]; /* 2 R/G/B/A entries */ + u_int32_t cm_chip[2]; /* 2 chip equivalents */ +}; + +/* + * cg14 hardware cursor status + */ +struct cg14_cursor { /* cg14 hardware cursor status */ + short cc_enable; /* cursor is enabled */ + struct fbcurpos cc_pos; /* position */ + struct fbcurpos cc_hot; /* hot-spot */ + struct fbcurpos cc_size; /* size of mask & image fields */ + u_int cc_eplane[32]; /* enable plane */ + u_int cc_cplane[32]; /* color plane */ + union cg14cursor_cmap cc_color; /* cursor colormap */ +}; + +/* + * per-cg14 variables/state + */ +struct cgfourteen_softc { + struct device sc_dev; /* base device */ + struct fbdevice sc_fb; /* frame buffer device */ + + struct rom_reg sc_phys; /* phys address of frame buffer */ +#if defined(DEBUG) && defined(CG14_MAP_REGS) + struct rom_reg sc_regphys; /* phys addr of fb regs; for debug */ +#endif + union cg14cmap sc_cmap; /* current colormap */ + + struct cg14_cursor sc_cursor; /* Hardware cursor state */ + + union cg14cmap sc_saveclut; /* a place to stash PROM state */ + u_int8_t sc_savexlut[256]; + u_int8_t sc_savectl; + u_int8_t sc_savehwc; + + struct cg14ctl *sc_ctl; /* various registers */ + struct cg14curs *sc_hwc; + struct cg14dac *sc_dac; + struct cg14xlut *sc_xlut; + struct cg14clut *sc_clut1; + struct cg14clut *sc_clut2; + struct cg14clut *sc_clut3; + u_int *sc_clutincr; +}; diff --git a/sys/arch/sparc/dev/cgsix.c b/sys/arch/sparc/dev/cgsix.c index dd967ebf558..f7cf868f8bb 100644 --- a/sys/arch/sparc/dev/cgsix.c +++ b/sys/arch/sparc/dev/cgsix.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cgsix.c,v 1.7 1996/08/13 08:05:22 downsj Exp $ */ -/* $NetBSD: cgsix.c,v 1.25 1996/04/01 17:30:00 christos Exp $ */ +/* $OpenBSD: cgsix.c,v 1.8 1997/08/08 08:24:51 downsj Exp $ */ +/* $NetBSD: cgsix.c,v 1.32 1997/07/29 09:58:04 fair Exp $ */ /* * Copyright (c) 1993 @@ -122,12 +122,11 @@ struct cgsix_softc { /* autoconfiguration driver */ static void cgsixattach __P((struct device *, struct device *, void *)); static int cgsixmatch __P((struct device *, void *, void *)); -int cgsixopen __P((dev_t, int, int, struct proc *)); -int cgsixclose __P((dev_t, int, int, struct proc *)); -int cgsixioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -int cgsixmmap __P((dev_t, int, int)); static void cg6_unblank __P((struct device *)); +/* cdevsw prototypes */ +cdev_decl(cgsix); + struct cfattach cgsix_ca = { sizeof(struct cgsix_softc), cgsixmatch, cgsixattach }; @@ -186,7 +185,8 @@ cgsixmatch(parent, vcf, aux) * differently on the cgsix than other pfour framebuffers. */ bus_untmp(); - tmp = bus_tmp(ra->ra_paddr + CGSIX_FHC_OFFSET, ca->ca_bustype); + tmp = (caddr_t)mapdev(ra->ra_reg, TMPMAP_VA, CGSIX_FHC_OFFSET, + NBPG); if (probeget(tmp, 4) == -1) return (0); @@ -231,17 +231,13 @@ cgsixattach(parent, self, args) sc->sc_physadr = ca->ca_ra.ra_reg[0]; sc->sc_bustype = ca->ca_bustype; sc->sc_bt = bt = (volatile struct bt_regs *) - mapiodev(ca->ca_ra.ra_reg, O(cg6_bt_un.un_btregs), - sizeof *sc->sc_bt, ca->ca_bustype); + mapiodev(ca->ca_ra.ra_reg, O(cg6_bt_un.un_btregs),sizeof *sc->sc_bt); sc->sc_fhc = (volatile int *) - mapiodev(ca->ca_ra.ra_reg, O(cg6_fhc_un.un_fhc), - sizeof *sc->sc_fhc, ca->ca_bustype); + mapiodev(ca->ca_ra.ra_reg, O(cg6_fhc_un.un_fhc), sizeof *sc->sc_fhc); sc->sc_thc = (volatile struct cg6_thc *) - mapiodev(ca->ca_ra.ra_reg, O(cg6_thc_un.un_thc), - sizeof *sc->sc_thc, ca->ca_bustype); + mapiodev(ca->ca_ra.ra_reg, O(cg6_thc_un.un_thc), sizeof *sc->sc_thc); sc->sc_tec = (volatile struct cg6_tec_xxx *) - mapiodev(ca->ca_ra.ra_reg, O(cg6_tec_un.un_tec), - sizeof *sc->sc_tec, ca->ca_bustype); + mapiodev(ca->ca_ra.ra_reg, O(cg6_tec_un.un_tec), sizeof *sc->sc_tec); switch (ca->ca_bustype) { case BUS_OBIO: @@ -292,13 +288,13 @@ cgsixattach(parent, self, args) #if defined(SUN4) if (CPU_ISSUN4) { struct eeprom *eep = (struct eeprom *)eeprom_va; - int constype = (fb->fb_flags & FB_PFOUR) ? EED_CONS_P4 : - EED_CONS_COLOR; + int constype = (fb->fb_flags & FB_PFOUR) ? EE_CONS_P4OPT : + EE_CONS_COLOR; /* * Assume this is the console if there's no eeprom info * to be found. */ - if (eep == NULL || eep->ee_diag.eed_console == constype) + if (eep == NULL || eep->eeConsole == constype) isconsole = (fbconstty != NULL); else isconsole = 0; @@ -329,8 +325,7 @@ cgsixattach(parent, self, args) printf(" (console)\n"); #ifdef RASTERCONSOLE sc->sc_fb.fb_pixels = (caddr_t) - mapiodev(ca->ca_ra.ra_reg, O(cg6_ram[0]), - ramsize, ca->ca_bustype); + mapiodev(ca->ca_ra.ra_reg, O(cg6_ram[0]), ramsize); fbrcons_init(&sc->sc_fb); #endif } else @@ -535,7 +530,7 @@ cgsixioctl(dev, cmd, data, flags, p) default: #ifdef DEBUG - log(LOG_NOTICE, "cgsixioctl(%lx) (%s[%d])\n", cmd, + log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd, p->p_comm, p->p_pid); #endif return (ENOTTY); @@ -752,13 +747,14 @@ cgsixmmap(dev, off, prot) u = off - mo->mo_uaddr; sz = mo->mo_size ? mo->mo_size : sc->sc_fb.fb_type.fb_size; if (u < sz) - return (REG2PHYS(&sc->sc_physadr, u + mo->mo_physoff, - sc->sc_bustype) | PMAP_NC); + return (REG2PHYS(&sc->sc_physadr, u + mo->mo_physoff) | + PMAP_NC); } #ifdef DEBUG { register struct proc *p = curproc; /* XXX */ - log(LOG_NOTICE, "cgsixmmap(%x) (%s[%d])\n", off, p->p_comm, p->p_pid); + log(LOG_NOTICE, "cgsixmmap(0x%x) (%s[%d])\n", + off, p->p_comm, p->p_pid); } #endif return (-1); /* not a user-map offset */ diff --git a/sys/arch/sparc/dev/cgsixreg.h b/sys/arch/sparc/dev/cgsixreg.h index d9b90977c85..a8a63d0a082 100644 --- a/sys/arch/sparc/dev/cgsixreg.h +++ b/sys/arch/sparc/dev/cgsixreg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: cgsixreg.h,v 1.3 1997/08/08 08:24:52 downsj Exp $ */ /* $NetBSD: cgsixreg.h,v 1.4 1996/02/27 22:09:31 thorpej Exp $ */ /* diff --git a/sys/arch/sparc/dev/cgthree.c b/sys/arch/sparc/dev/cgthree.c index 1599048c61d..b978af5fde4 100644 --- a/sys/arch/sparc/dev/cgthree.c +++ b/sys/arch/sparc/dev/cgthree.c @@ -1,4 +1,5 @@ -/* $NetBSD: cgthree.c,v 1.27 1996/04/01 17:30:03 christos Exp $ */ +/* $OpenBSD: cgthree.c,v 1.6 1997/08/08 08:24:53 downsj Exp $ */ +/* $NetBSD: cgthree.c,v 1.33 1997/05/24 20:16:11 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -90,12 +91,11 @@ struct cgthree_softc { /* autoconfiguration driver */ static void cgthreeattach(struct device *, struct device *, void *); static int cgthreematch(struct device *, void *, void *); -int cgthreeopen __P((dev_t, int, int, struct proc *)); -int cgthreeclose __P((dev_t, int, int, struct proc *)); -int cgthreeioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -int cgthreemmap __P((dev_t, int, int)); static void cgthreeunblank(struct device *); +/* cdevsw prototypes */ +cdev_decl(cgthree); + struct cfattach cgthree_ca = { sizeof(struct cgthree_softc), cgthreematch, cgthreeattach }; @@ -116,6 +116,20 @@ static void cgthreeloadcmap __P((struct cgthree_softc *, int, int)); static void cgthree_set_video __P((struct cgthree_softc *, int)); static int cgthree_get_video __P((struct cgthree_softc *)); +/* Video control parameters */ +struct cg3_videoctrl { + unsigned char sense; /* Monitor sense value */ + unsigned char vctrl[12]; +} cg3_videoctrl[] = { +/* Missing entries: sense 0x10, 0x30, 0x50 */ + { 0x40, /* this happens to be my 19'' 1152x900 gray-scale monitor */ + {0xbb, 0x2b, 0x3, 0xb, 0xb3, 0x3, 0xaf, 0x2b, 0x2, 0xa, 0xff, 0x1} + }, + { 0x00, /* default? must be last */ + {0xbb, 0x2b, 0x3, 0xb, 0xb3, 0x3, 0xaf, 0x2b, 0x2, 0xa, 0xff, 0x1} + } +}; + /* * Match a cgthree. */ @@ -206,11 +220,28 @@ cgthreeattach(parent, self, args) if ((sc->sc_fb.fb_pixels = ca->ca_ra.ra_vaddr) == NULL && isconsole) { /* this probably cannot happen, but what the heck */ sc->sc_fb.fb_pixels = mapiodev(ca->ca_ra.ra_reg, CG3REG_MEM, - ramsize, ca->ca_bustype); + ramsize); } sc->sc_fbc = (volatile struct fbcontrol *) mapiodev(ca->ca_ra.ra_reg, CG3REG_REG, - sizeof(struct fbcontrol), ca->ca_bustype); + sizeof(struct fbcontrol)); + + /* Transfer video magic to board, if it's not running */ + if ((sc->sc_fbc->fbc_ctrl & FBC_TIMING) == 0) + for (i = 0; i < sizeof(cg3_videoctrl)/sizeof(cg3_videoctrl[0]); + i++) { + volatile struct fbcontrol *fbc = sc->sc_fbc; + if ((fbc->fbc_status & FBS_MSENSE) == + cg3_videoctrl[i].sense) { + int j; + printf(" setting video ctrl"); + for (j = 0; j < 12; j++) + fbc->fbc_vcontrol[j] = + cg3_videoctrl[i].vctrl[j]; + fbc->fbc_ctrl |= FBC_TIMING; + break; + } + } sc->sc_phys = ca->ca_ra.ra_reg[0]; sc->sc_bustype = ca->ca_bustype; @@ -408,5 +439,5 @@ cgthreemmap(dev, off, prot) * I turned on PMAP_NC here to disable the cache as I was * getting horribly broken behaviour with it on. */ - return (REG2PHYS(&sc->sc_phys, CG3REG_MEM+off, sc->sc_bustype) | PMAP_NC); + return (REG2PHYS(&sc->sc_phys, CG3REG_MEM+off) | PMAP_NC); } diff --git a/sys/arch/sparc/dev/cgthreereg.h b/sys/arch/sparc/dev/cgthreereg.h index 073cc52e66c..89811921252 100644 --- a/sys/arch/sparc/dev/cgthreereg.h +++ b/sys/arch/sparc/dev/cgthreereg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: cgthreereg.h,v 1.3 1997/08/08 08:24:54 downsj Exp $ */ /* $NetBSD: cgthreereg.h,v 1.5 1996/02/27 00:14:17 pk Exp $ */ /* diff --git a/sys/arch/sparc/dev/cgtwo.c b/sys/arch/sparc/dev/cgtwo.c index 8c5dcc8f11a..e682f6b8a26 100644 --- a/sys/arch/sparc/dev/cgtwo.c +++ b/sys/arch/sparc/dev/cgtwo.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cgtwo.c,v 1.10 1996/08/13 08:05:23 downsj Exp $ */ -/* $NetBSD: cgtwo.c,v 1.16 1996/05/18 12:19:14 mrg Exp $ */ +/* $OpenBSD: cgtwo.c,v 1.11 1997/08/08 08:24:55 downsj Exp $ */ +/* $NetBSD: cgtwo.c,v 1.22 1997/05/24 20:16:12 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -92,14 +92,13 @@ struct cgtwo_softc { /* autoconfiguration driver */ static void cgtwoattach __P((struct device *, struct device *, void *)); static int cgtwomatch __P((struct device *, void *, void *)); -int cgtwoopen __P((dev_t, int, int, struct proc *)); -int cgtwoclose __P((dev_t, int, int, struct proc *)); -int cgtwoioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -int cgtwommap __P((dev_t, int, int)); static void cgtwounblank __P((struct device *)); int cgtwogetcmap __P((struct cgtwo_softc *, struct fbcmap *)); int cgtwoputcmap __P((struct cgtwo_softc *, struct fbcmap *)); +/* cdevsw prototypes */ +cdev_decl(cgtwo); + struct cfattach cgtwo_ca = { sizeof(struct cgtwo_softc), cgtwomatch, cgtwoattach }; @@ -148,7 +147,7 @@ cgtwomatch(parent, vcf, aux) /* XXX - Must do our own mapping at CG2_CTLREG_OFF */ bus_untmp(); - tmp = (caddr_t)bus_tmp(ra->ra_paddr + CG2_CTLREG_OFF, ca->ca_bustype); + tmp = (caddr_t)mapdev(ra->ra_reg, TMPMAP_VA, CG2_CTLREG_OFF, NBPG); if (probeget(tmp, 2) != -1) return 1; #endif @@ -207,20 +206,21 @@ cgtwoattach(parent, self, args) * Assume this is the console if there's no eeprom info * to be found. */ - if (eep == NULL || eep->ee_diag.eed_console == EED_CONS_COLOR) + if (eep == NULL || eep->eeConsole == EE_CONS_COLOR) isconsole = (fbconstty != NULL); else isconsole = 0; } #endif sc->sc_phys = ca->ca_ra.ra_reg[0]; + /* Apparently, the pixels are 32-bit data space */ + sc->sc_phys.rr_iospace = PMAP_VME32; sc->sc_bustype = ca->ca_bustype; if ((sc->sc_fb.fb_pixels = ca->ca_ra.ra_vaddr) == NULL && isconsole) { /* this probably cannot happen, but what the heck */ - sc->sc_fb.fb_pixels = mapiodev(ca->ca_ra.ra_reg, CG2_PIXMAP_OFF, - CG2_PIXMAP_SIZE, - PMAP_VME32/*ca->ca_bustype*/); + sc->sc_fb.fb_pixels = mapiodev(&sc->sc_phys, CG2_PIXMAP_OFF, + CG2_PIXMAP_SIZE); } #ifndef offsetof #define offsetof(type, member) ((size_t)(&((type *)0)->member)) @@ -229,12 +229,12 @@ cgtwoattach(parent, self, args) sc->sc_reg = (volatile struct cg2statusreg *) mapiodev(ca->ca_ra.ra_reg, CG2_ROPMEM_OFF + offsetof(struct cg2fb, status.reg), - sizeof(struct cg2statusreg), ca->ca_bustype); + sizeof(struct cg2statusreg)); sc->sc_cmap = (volatile u_short *) mapiodev(ca->ca_ra.ra_reg, CG2_ROPMEM_OFF + offsetof(struct cg2fb, redmap[0]), - 3 * CG2_CMSIZE, ca->ca_bustype); + 3 * CG2_CMSIZE); if (isconsole) { printf(" (console)\n"); @@ -432,5 +432,5 @@ cgtwommap(dev, off, prot) if ((unsigned)off >= sc->sc_fb.fb_type.fb_size) return (-1); - return (REG2PHYS(&sc->sc_phys, off, PMAP_VME32/*sc->sc_bustype*/) | PMAP_NC); + return (REG2PHYS(&sc->sc_phys, off) | PMAP_NC); } diff --git a/sys/arch/sparc/dev/cons.c b/sys/arch/sparc/dev/cons.c index 11a1606bae8..fba5c2e4eb1 100644 --- a/sys/arch/sparc/dev/cons.c +++ b/sys/arch/sparc/dev/cons.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cons.c,v 1.5 1996/08/13 08:05:24 downsj Exp $ */ -/* $NetBSD: cons.c,v 1.23.4.1 1996/06/02 09:07:53 mrg Exp $ */ +/* $OpenBSD: cons.c,v 1.6 1997/08/08 08:24:56 downsj Exp $ */ +/* $NetBSD: cons.c,v 1.30 1997/07/07 23:30:23 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -70,6 +70,11 @@ #include <machine/autoconf.h> #include <machine/conf.h> +#ifdef RASTERCONSOLE +#include <machine/fbio.h> +#include <machine/fbvar.h> +#endif + #include "zs.h" struct tty *constty = 0; /* virtual console output device */ @@ -286,20 +291,30 @@ cnopen(dev, flag, mode, p) /* output queue doesn't need quoting */ clalloc(&tp->t_outq, 1024, 0); tty_attach(tp); + /* * get the console struct winsize. */ +#ifdef RASTERCONSOLE + if (fbconstty) { + rows = fbrcons_rows(); + cols = fbrcons_cols(); + } +#endif + if (CPU_ISSUN4COR4M) { int i; char *prop; - if ((prop = getpropstring(optionsnode, "screen-#rows"))) { + if (rows == 0 && + (prop = getpropstring(optionsnode, "screen-#rows"))) { i = 0; while (*prop != '\0') i = i * 10 + *prop++ - '0'; rows = (unsigned short)i; } - if ((prop = getpropstring(optionsnode, "screen-#columns"))) { + if (cols == 0 && + (prop = getpropstring(optionsnode, "screen-#columns"))) { i = 0; while (*prop != '\0') i = i * 10 + *prop++ - '0'; @@ -310,8 +325,10 @@ cnopen(dev, flag, mode, p) struct eeprom *ep = (struct eeprom *)eeprom_va; if (ep) { - rows = (u_short)ep->ee_diag.eed_rowsize; - cols = (u_short)ep->ee_diag.eed_colsize; + if (rows == 0) + rows = (u_short)ep->eeTtyRows; + if (cols == 0) + cols = (u_short)ep->eeTtyCols; } } firstopen = 0; diff --git a/sys/arch/sparc/dev/dma.c b/sys/arch/sparc/dev/dma.c index 4c961cac690..c01200a20c1 100644 --- a/sys/arch/sparc/dev/dma.c +++ b/sys/arch/sparc/dev/dma.c @@ -1,4 +1,5 @@ -/* $NetBSD: dma.c,v 1.28.2.2 1996/07/02 23:46:29 jtc Exp $ */ +/* $OpenBSD: dma.c,v 1.8 1997/08/08 08:24:57 downsj Exp $ */ +/* $NetBSD: dma.c,v 1.45 1997/07/29 09:58:06 fair Exp $ */ /* * Copyright (c) 1994 Paul Kranenburg. All rights reserved. @@ -45,19 +46,25 @@ #include <sparc/autoconf.h> #include <sparc/cpu.h> +#include <sparc/sparc/cpuvar.h> + #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> +#include <dev/ic/ncr53c9xreg.h> +#include <dev/ic/ncr53c9xvar.h> + #include <sparc/dev/sbusvar.h> #include <sparc/dev/dmareg.h> #include <sparc/dev/dmavar.h> -#include <sparc/dev/espreg.h> #include <sparc/dev/espvar.h> int dmaprint __P((void *, const char *)); void dmaattach __P((struct device *, struct device *, void *)); int dmamatch __P((struct device *, void *, void *)); -void dma_reset __P((struct dma_softc *)); +void dma_reset __P((struct dma_softc *, int)); +void espdma_reset __P((struct dma_softc *)); +void ledma_reset __P((struct dma_softc *)); void dma_enintr __P((struct dma_softc *)); int dma_isintr __P((struct dma_softc *)); int espdmaintr __P((struct dma_softc *)); @@ -100,7 +107,7 @@ dmamatch(parent, vcf, aux) struct device *parent; void *vcf, *aux; { - struct cfdata *cf = vcf; + register struct cfdata *cf = vcf; register struct confargs *ca = aux; register struct romaux *ra = &ca->ca_ra; @@ -131,8 +138,7 @@ dmaattach(parent, self, aux) if (ca->ca_ra.ra_vaddr == NULL || ca->ca_ra.ra_nvaddrs == 0) ca->ca_ra.ra_vaddr = - mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len, - ca->ca_bustype); + mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len); sc->sc_regs = (struct dma_regs *) ca->ca_ra.ra_vaddr; @@ -156,35 +162,24 @@ dmaattach(parent, self, aux) } delay(20000); /* manual says we need 20ms delay */ } - + /* - * Get transfer burst size from PROM and plug it into the controller - * registers. This is needed on the Sun4m; do others need it too? - * XXX + * Get transfer burst size from PROM and plug it into the + * controller registers. This is needed on the Sun4m; do + * others need it too? */ if (CPU_ISSUN4M) { + int sbusburst = ((struct sbus_softc *)parent)->sc_burst; + if (sbusburst == 0) + sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ + sc->sc_burst = getpropint(ca->ca_ra.ra_node,"burst-sizes", -1); - if (sc->sc_burst == -1) { - /* check parent SBus for burst sizes */ - if (((struct sbus_softc *)parent)->sc_burst == 0) - sc->sc_burst = SBUS_BURST_32 - 1; /* 1->16 */ - else - sc->sc_burst = - ((struct sbus_softc *)parent)->sc_burst; - } - sc->sc_regs->csr &= ~D_BURST_SIZE; /* must clear first */ - if (sc->sc_burst & SBUS_BURST_32) { - sc->sc_regs->csr |= D_BURST_32; - } else if (sc->sc_burst & SBUS_BURST_16) { - sc->sc_regs->csr |= D_BURST_16; - } else if (strcmp(ca->ca_ra.ra_name,"espdma") == 0) { - /* only espdma supports non-burst */ - sc->sc_regs->csr |= D_BURST_0; -#ifdef DIAGNOSTIC - } else { - printf(" <unknown burst size 0x%x>", sc->sc_burst); -#endif - } + if (sc->sc_burst == -1) + /* take SBus burst sizes */ + sc->sc_burst = sbusburst; + + /* Clamp at parent's burst sizes */ + sc->sc_burst &= sbusburst; } printf(": rev "); @@ -193,6 +188,9 @@ dmaattach(parent, self, aux) case DMAREV_0: printf("0"); break; + case DMAREV_ESC: + printf("esc"); + break; case DMAREV_1: printf("1"); break; @@ -203,19 +201,20 @@ dmaattach(parent, self, aux) printf("2"); break; default: - printf("unknown"); + printf("unknown (0x%x)", sc->sc_rev); } printf("\n"); /* indirect functions */ if (sc->sc_dev.dv_cfdata->cf_attach == &dma_ca) { + sc->reset = espdma_reset; sc->intr = espdmaintr; } else { + sc->reset = ledma_reset; sc->intr = ledmaintr; } sc->enintr = dma_enintr; sc->isintr = dma_isintr; - sc->reset = dma_reset; sc->setup = dma_setup; sc->go = dma_go; @@ -272,24 +271,94 @@ espsearch: } } +#define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) { \ + int count = 500000; \ + while ((COND) && --count > 0) DELAY(1); \ + if (count == 0) { \ + printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \ + (SC)->sc_regs->csr); \ + if (DONTPANIC) \ + printf(MSG); \ + else \ + panic(MSG); \ + } \ +} while (0) + +#define DMA_DRAIN(sc, dontpanic) do { \ + /* \ + * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ + * and "drain" bits while it is still thinking about a \ + * request. \ + * other revs: D_R_PEND bit reads as 0 \ + */ \ + DMAWAIT(sc, sc->sc_regs->csr & D_R_PEND, "R_PEND", dontpanic); \ + /* \ + * Select drain bit based on revision \ + * also clears errors and D_TC flag \ + */ \ + if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0) \ + DMACSR(sc) |= D_DRAIN; \ + else \ + DMACSR(sc) |= D_INVALIDATE; \ + /* \ + * Wait for draining to finish \ + * rev0 & rev1 call this PACKCNT \ + */ \ + DMAWAIT(sc, sc->sc_regs->csr & D_DRAINING, "DRAINING", dontpanic);\ +} while(0) + void -dma_reset(sc) +dma_reset(sc, isledma) struct dma_softc *sc; + int isledma; { - DMAWAIT(sc); - DMA_DRAIN(sc); /* Drain (DMA rev 1) */ + DMA_DRAIN(sc, 1); DMACSR(sc) &= ~D_EN_DMA; /* Stop DMA */ - DMAWAIT1(sc); /* let things drain */ DMACSR(sc) |= D_RESET; /* reset DMA */ DELAY(200); /* what should this be ? */ - DMAWAIT1(sc); + /*DMAWAIT1(sc); why was this here? */ DMACSR(sc) &= ~D_RESET; /* de-assert reset line */ DMACSR(sc) |= D_INT_EN; /* enable interrupts */ - if (sc->sc_rev > DMAREV_1) + if (sc->sc_rev > DMAREV_1 && isledma == 0) DMACSR(sc) |= D_FASTER; + + switch (sc->sc_rev) { + case DMAREV_2: + sc->sc_regs->csr &= ~D_BURST_SIZE; /* must clear first */ + if (sc->sc_burst & SBUS_BURST_32) { + DMACSR(sc) |= D_BURST_32; + } else if (sc->sc_burst & SBUS_BURST_16) { + DMACSR(sc) |= D_BURST_16; + } else { + DMACSR(sc) |= D_BURST_0; + } + break; + case DMAREV_ESC: + DMACSR(sc) |= D_AUTODRAIN; /* Auto-drain */ + if (sc->sc_burst & SBUS_BURST_32) { + DMACSR(sc) &= ~0x800; + } else + DMACSR(sc) |= 0x800; + break; + default: + } + sc->sc_active = 0; /* and of course we aren't */ } +void +espdma_reset(sc) + struct dma_softc *sc; +{ + dma_reset(sc, 0); +} + +void +ledma_reset(sc) + struct dma_softc *sc; +{ + dma_reset(sc, 1); +} void dma_enintr(sc) @@ -321,12 +390,7 @@ dma_setup(sc, addr, len, datain, dmasize) { u_long csr; - /* clear errors and D_TC flag */ - DMAWAIT(sc); - DMA_DRAIN(sc); /* ? */ - DMAWAIT1(sc); - DMACSR(sc) |= D_INVALIDATE; - DMAWAIT1(sc); + DMA_DRAIN(sc, 0); #if 0 DMACSR(sc) &= ~D_INT_EN; @@ -334,7 +398,7 @@ dma_setup(sc, addr, len, datain, dmasize) sc->sc_dmaaddr = addr; sc->sc_dmalen = len; - ESP_DMA(("%s: start %d@%p,%d\n", sc->sc_dev.dv_xname, + NCR_DMA(("%s: start %d@%p,%d\n", sc->sc_dev.dv_xname, *sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0)); /* @@ -345,7 +409,7 @@ dma_setup(sc, addr, len, datain, dmasize) *dmasize = sc->sc_dmasize = min(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr)); - ESP_DMA(("dma_setup: dmasize = %d\n", sc->sc_dmasize)); + NCR_DMA(("dma_setup: dmasize = %d\n", sc->sc_dmasize)); /* Program the DMA address */ if (CPU_ISSUN4M && sc->sc_dmasize) { @@ -361,6 +425,14 @@ dma_setup(sc, addr, len, datain, dmasize) } else DMADDR(sc) = *sc->sc_dmaaddr; + if (sc->sc_rev == DMAREV_ESC) { + /* DMA ESC chip bug work-around */ + register long bcnt = sc->sc_dmasize; + register long eaddr = bcnt + (long)*sc->sc_dmaaddr; + if ((eaddr & PGOFSET) != 0) + bcnt = roundup(bcnt, NBPG); + DMACNT(sc) = bcnt; + } /* Setup DMA control register */ csr = DMACSR(sc); if (datain) @@ -394,11 +466,12 @@ int espdmaintr(sc) struct dma_softc *sc; { + struct ncr53c9x_softc *nsc = &sc->sc_esp->sc_ncr53c9x; int trans, resid; u_long csr; csr = DMACSR(sc); - ESP_DMA(("%s: intr: addr %p, csr %b\n", sc->sc_dev.dv_xname, + NCR_DMA(("%s: intr: addr %p, csr %b\n", sc->sc_dev.dv_xname, DMADDR(sc), csr, DMACSRBITS)); if (csr & D_ERR_PEND) { @@ -406,19 +479,14 @@ espdmaintr(sc) DMACSR(sc) |= D_INVALIDATE; printf("%s: error: csr=%b\n", sc->sc_dev.dv_xname, csr, DMACSRBITS); - return 0; + return -1; } /* This is an "assertion" :) */ if (sc->sc_active == 0) panic("dmaintr: DMA wasn't active"); - /* clear errors and D_TC flag */ - DMAWAIT(sc); - DMA_DRAIN(sc); /* ? */ - DMAWAIT1(sc); - DMACSR(sc) |= D_INVALIDATE; - DMAWAIT1(sc); + DMA_DRAIN(sc, 0); /* DMA has stopped */ DMACSR(sc) &= ~D_EN_DMA; @@ -426,11 +494,11 @@ espdmaintr(sc) if (sc->sc_dmasize == 0) { /* A "Transfer Pad" operation completed */ - ESP_DMA(("dmaintr: discarded %d bytes (tcl=%d, tcm=%d)\n", - ESP_READ_REG(sc->sc_esp, ESP_TCL) | - (ESP_READ_REG(sc->sc_esp, ESP_TCM) << 8), - ESP_READ_REG(sc->sc_esp, ESP_TCL), - ESP_READ_REG(sc->sc_esp, ESP_TCM))); + NCR_DMA(("dmaintr: discarded %d bytes (tcl=%d, tcm=%d)\n", + NCR_READ_REG(nsc, NCR_TCL) | + (NCR_READ_REG(nsc, NCR_TCM) << 8), + NCR_READ_REG(nsc, NCR_TCL), + NCR_READ_REG(nsc, NCR_TCM))); return 0; } @@ -442,44 +510,50 @@ espdmaintr(sc) * bytes are clocked into the FIFO. */ if (!(csr & D_WRITE) && - (resid = (ESP_READ_REG(sc->sc_esp, ESP_FFLAG) & ESPFIFO_FF)) != 0) { - ESP_DMA(("dmaintr: empty esp FIFO of %d ", resid)); - ESPCMD(sc->sc_esp, ESPCMD_FLUSH); + (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { + NCR_DMA(("dmaintr: empty esp FIFO of %d ", resid)); } - if ((sc->sc_esp->sc_espstat & ESPSTAT_TC) == 0) { + if ((nsc->sc_espstat & NCRSTAT_TC) == 0) { /* * `Terminal count' is off, so read the residue * out of the ESP counter registers. */ - resid += ( ESP_READ_REG(sc->sc_esp, ESP_TCL) | - (ESP_READ_REG(sc->sc_esp, ESP_TCM) << 8) | - ((sc->sc_esp->sc_cfg2 & ESPCFG2_FE) - ? (ESP_READ_REG(sc->sc_esp, ESP_TCH) << 16) + resid += (NCR_READ_REG(nsc, NCR_TCL) | + (NCR_READ_REG(nsc, NCR_TCM) << 8) | + ((nsc->sc_cfg2 & NCRCFG2_FE) + ? (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0)); if (resid == 0 && sc->sc_dmasize == 65536 && - (sc->sc_esp->sc_cfg2 & ESPCFG2_FE) == 0) + (nsc->sc_cfg2 & NCRCFG2_FE) == 0) /* A transfer of 64K is encoded as `TCL=TCM=0' */ resid = 65536; } trans = sc->sc_dmasize - resid; if (trans < 0) { /* transferred < 0 ? */ +#if 0 + /* + * This situation can happen in perfectly normal operation + * if the ESP is reselected while using DMA to select + * another target. As such, don't print the warning. + */ printf("%s: xfer (%d) > req (%d)\n", sc->sc_dev.dv_xname, trans, sc->sc_dmasize); +#endif trans = sc->sc_dmasize; } - ESP_DMA(("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", - ESP_READ_REG(sc->sc_esp, ESP_TCL), - ESP_READ_REG(sc->sc_esp, ESP_TCM), - (sc->sc_esp->sc_cfg2 & ESPCFG2_FE) - ? ESP_READ_REG(sc->sc_esp, ESP_TCH) : 0, + NCR_DMA(("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", + NCR_READ_REG(nsc, NCR_TCL), + NCR_READ_REG(nsc, NCR_TCM), + (nsc->sc_cfg2 & NCRCFG2_FE) + ? NCR_READ_REG(nsc, NCR_TCH) : 0, trans, resid)); if (csr & D_WRITE) - cache_flush(*sc->sc_dmaaddr, trans); + cpuinfo.cache_flush(*sc->sc_dmaaddr, trans); if (CPU_ISSUN4M && sc->sc_dvmakaddr) dvma_mapout((vm_offset_t)sc->sc_dvmakaddr, @@ -490,7 +564,7 @@ espdmaintr(sc) #if 0 /* this is not normal operation just yet */ if (*sc->sc_dmalen == 0 || - sc->sc_esp->sc_phase != sc->sc_esp->sc_prevphase) + nsc->sc_phase != nsc->sc_prevphase) return 0; /* and again */ @@ -515,11 +589,11 @@ ledmaintr(sc) csr = DMACSR(sc); if (csr & D_ERR_PEND) { - printf("Lance DMA error, see your doctor!\n"); DMACSR(sc) &= ~D_EN_DMA; /* Stop DMA */ DMACSR(sc) |= D_INVALIDATE; printf("%s: error: csr=%b\n", sc->sc_dev.dv_xname, - (u_int)csr, DMACSRBITS); + csr, DMACSRBITS); + DMA_RESET(sc); } return 1; } diff --git a/sys/arch/sparc/dev/dmareg.h b/sys/arch/sparc/dev/dmareg.h index 3998581845a..c9e575a262f 100644 --- a/sys/arch/sparc/dev/dmareg.h +++ b/sys/arch/sparc/dev/dmareg.h @@ -1,4 +1,5 @@ -/* $NetBSD: dmareg.h,v 1.8 1996/04/22 02:34:58 abrown Exp $ */ +/* $OpenBSD: dmareg.h,v 1.4 1997/08/08 08:24:58 downsj Exp $ */ +/* $NetBSD: dmareg.h,v 1.10 1996/11/28 09:37:34 pk Exp $ */ /* * Copyright (c) 1994 Peter Galbavy. All rights reserved. @@ -38,19 +39,21 @@ struct dma_regs { #define D_INT_EN 0x00000010 /* interrupt enable */ #define D_INVALIDATE 0x00000020 /* invalidate fifo */ #define D_SLAVE_ERR 0x00000040 /* slave access size error */ -#define D_DRAIN 0x00000040 /* drain fifo if DMAREV_1 */ +#define D_DRAIN 0x00000040 /* rev0,1,esc: drain fifo */ #define D_RESET 0x00000080 /* reset scsi */ #define D_WRITE 0x00000100 /* 1 = dev -> mem */ #define D_EN_DMA 0x00000200 /* enable DMA requests */ -#define D_R_PEND 0x00000400 /* something only on ver < 2 */ +#define D_R_PEND 0x00000400 /* rev0,1: request pending */ +#define D_ESC_BURST 0x00000800 /* DMA ESC: 16 byte bursts */ #define D_EN_CNT 0x00002000 /* enable byte counter */ #define D_TC 0x00004000 /* terminal count */ #define D_DSBL_CSR_DRN 0x00010000 /* disable fifo drain on csr */ #define D_DSBL_SCSI_DRN 0x00020000 /* disable fifo drain on reg */ #define D_BURST_SIZE 0x000c0000 /* sbus read/write burst size */ #define D_BURST_0 0x00080000 /* no bursts (SCSI-only) */ -#define D_BURST_16 0x00040000 /* 16-byte bursts */ -#define D_BURST_32 0x00000000 /* 32-byte bursts */ +#define D_BURST_16 0x00000000 /* 16-byte bursts */ +#define D_BURST_32 0x00040000 /* 32-byte bursts */ +#define D_AUTODRAIN 0x00040000 /* DMA ESC: Auto-drain */ #define D_DIAG 0x00100000 /* disable fifo drain on addr */ #define D_TWO_CYCLE 0x00200000 /* 2 clocks per transfer */ #define D_FASTER 0x00400000 /* 3 clocks per transfer */ @@ -62,6 +65,7 @@ struct dma_regs { #define D_NA_LOADED 0x08000000 /* next address loaded */ #define D_DEV_ID 0xf0000000 /* device ID */ #define DMAREV_0 0x00000000 /* Sunray DMA */ +#define DMAREV_ESC 0x40000000 /* DMA ESC array */ #define DMAREV_1 0x80000000 /* 'DMA' */ #define DMAREV_PLUS 0x90000000 /* 'DMA+' */ #define DMAREV_2 0xa0000000 /* 'DMA2' */ diff --git a/sys/arch/sparc/dev/dmavar.h b/sys/arch/sparc/dev/dmavar.h index 6bc42333a98..57fbbcad5e4 100644 --- a/sys/arch/sparc/dev/dmavar.h +++ b/sys/arch/sparc/dev/dmavar.h @@ -1,4 +1,5 @@ -/* $NetBSD: dmavar.h,v 1.8 1996/04/22 02:35:00 abrown Exp $ */ +/* $OpenBSD: dmavar.h,v 1.4 1997/08/08 08:24:59 downsj Exp $ */ +/* $NetBSD: dmavar.h,v 1.11 1996/11/27 21:49:53 pk Exp $ */ /* * Copyright (c) 1994 Peter Galbavy. All rights reserved. @@ -35,7 +36,7 @@ struct dma_softc { struct le_softc *sc_le; /* my ethernet */ struct dma_regs *sc_regs; /* the registers */ int sc_active; /* DMA active ? */ - int sc_rev; /* revision */ + u_int sc_rev; /* revision */ int sc_node; /* PROM node ID */ int sc_burst; /* DVMA burst size in effect */ caddr_t sc_dvmakaddr; /* DVMA cookies */ @@ -53,32 +54,7 @@ struct dma_softc { #define DMACSR(sc) (sc->sc_regs->csr) #define DMADDR(sc) (sc->sc_regs->addr) - -/* - * We are not allowed to touch the DMA "flush" and "drain" bits - * while it is still thinking about a request (DMA_RP). - */ - -/* - * TIME WAIT (to debug hanging machine problem) - */ - -#define TIME_WAIT(COND, MSG, SC) { int count = 500000; \ - while (--count > 0 && (COND)) DELAY(1); \ - if (count == 0) { \ - printf("CSR = %lx\n",\ - SC->sc_regs->csr);\ - panic(MSG); } \ - } - -#define DMAWAIT(sc) TIME_WAIT((sc->sc_regs->csr & D_R_PEND), "DMAWAIT", sc) -#define DMAWAIT1(sc) TIME_WAIT((sc->sc_regs->csr & D_DRAINING), "DMAWAIT1", sc) -#define DMAREADY(sc) TIME_WAIT((!(sc->sc_regs->csr & D_DMA_ON)), "DMAREADY", sc) - -#define DMA_DRAIN(sc) if (sc->sc_rev < DMAREV_2) { \ - DMACSR(sc) |= D_DRAIN; \ - DMAWAIT1(sc); \ - } +#define DMACNT(sc) (sc->sc_regs->bcnt) /* DMA engine functions */ #define DMA_ENINTR(r) (((r)->enintr)(r)) diff --git a/sys/arch/sparc/dev/esp.c b/sys/arch/sparc/dev/esp.c index 5cb9d216931..48c211f8ea2 100644 --- a/sys/arch/sparc/dev/esp.c +++ b/sys/arch/sparc/dev/esp.c @@ -1,4 +1,65 @@ -/* $NetBSD: esp.c,v 1.47.2.1 1996/06/12 20:46:52 pk Exp $ */ +/* $OpenBSD: esp.c,v 1.10 1997/08/08 08:25:00 downsj Exp $ */ +/* $NetBSD: esp.c,v 1.68 1997/07/19 21:57:01 pk Exp $ */ + +/* + * Copyright (c) 1997 Jason R. Thorpe. + * 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 for the NetBSD Project + * by Jason R. Thorpe. + * 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) 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 @@ -58,35 +119,17 @@ #include <machine/cpu.h> #include <machine/autoconf.h> + +#include <dev/ic/ncr53c9xreg.h> +#include <dev/ic/ncr53c9xvar.h> + #include <sparc/dev/sbusvar.h> #include <sparc/dev/dmareg.h> #include <sparc/dev/dmavar.h> -#include <sparc/dev/espreg.h> #include <sparc/dev/espvar.h> -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 *, const char *)); -/*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_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*/ void esp_sched __P((struct esp_softc *)); -/*static*/ void esp_done __P((struct 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_stp2cpb __P((struct esp_softc *, int)); -int esp_cpb2stp __P((struct esp_softc *, int)); +void espattach __P((struct device *, struct device *, void *)); +int espmatch __P((struct device *, void *, void *)); /* Linkup to the rest of the kernel */ struct cfattach esp_ca = { @@ -98,7 +141,7 @@ struct cfdriver esp_cd = { }; struct scsi_adapter esp_switch = { - esp_scsi_cmd, + ncr53c9x_scsi_cmd, minphys, /* no max at this level; handled by DMA code */ NULL, NULL, @@ -111,22 +154,39 @@ struct scsi_device esp_dev = { NULL, /* Use default 'done' routine */ }; -int -espprint(aux, name) - void *aux; - const char *name; -{ - if (name != NULL) - printf("%s: scsibus ", name); - return UNCONF; -} +/* + * Functions and the switch for the MI code. + */ +u_char esp_read_reg __P((struct ncr53c9x_softc *, int)); +void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char)); +int esp_dma_isintr __P((struct ncr53c9x_softc *)); +void esp_dma_reset __P((struct ncr53c9x_softc *)); +int esp_dma_intr __P((struct ncr53c9x_softc *)); +int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *, + size_t *, int, size_t *)); +void esp_dma_go __P((struct ncr53c9x_softc *)); +void esp_dma_stop __P((struct ncr53c9x_softc *)); +int esp_dma_isactive __P((struct ncr53c9x_softc *)); + +struct ncr53c9x_glue esp_glue = { + esp_read_reg, + esp_write_reg, + esp_dma_isintr, + esp_dma_reset, + esp_dma_intr, + esp_dma_setup, + esp_dma_go, + esp_dma_stop, + esp_dma_isactive, + NULL, /* gl_clear_latched_intr */ +}; int espmatch(parent, vcf, aux) struct device *parent; void *vcf, *aux; { - struct cfdata *cf = vcf; + register struct cfdata *cf = vcf; register struct confargs *ca = aux; register struct romaux *ra = &ca->ca_ra; @@ -147,11 +207,17 @@ espattach(parent, self, aux) void *aux; { register struct confargs *ca = aux; - struct esp_softc *sc = (void *)self; + struct esp_softc *esc = (void *)self; + struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; struct bootpath *bp; int dmachild = strncmp(parent->dv_xname, "dma", 3) == 0; /* + * Set up glue for MI code early; we use some of it here. + */ + sc->sc_glue = &esp_glue; + + /* * Make sure things are sane. I don't know if this is ever * necessary, but it seem to be in all of Torek's code. */ @@ -160,25 +226,25 @@ espattach(parent, self, aux) return; } - sc->sc_pri = ca->ca_ra.ra_intr[0].int_pri; - printf(" pri %d", sc->sc_pri); + esc->sc_pri = ca->ca_ra.ra_intr[0].int_pri; + printf(" pri %d", esc->sc_pri); /* * Map my registers in, if they aren't already in virtual * address space. */ if (ca->ca_ra.ra_vaddr) - sc->sc_reg = (volatile u_char *) ca->ca_ra.ra_vaddr; + esc->sc_reg = (volatile u_char *) ca->ca_ra.ra_vaddr; else { - sc->sc_reg = (volatile u_char *) - mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len, ca->ca_bustype); + esc->sc_reg = (volatile u_char *) + mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len); } /* Other settings */ - sc->sc_node = ca->ca_ra.ra_node; + esc->sc_node = ca->ca_ra.ra_node; if (ca->ca_bustype == BUS_SBUS) { - sc->sc_id = getpropint(sc->sc_node, "initiator-id", 7); - sc->sc_freq = getpropint(sc->sc_node, "clock-frequency", -1); + sc->sc_id = getpropint(esc->sc_node, "initiator-id", 7); + sc->sc_freq = getpropint(esc->sc_node, "clock-frequency", -1); } else { sc->sc_id = 7; sc->sc_freq = 24000000; @@ -191,8 +257,8 @@ espattach(parent, self, aux) sc->sc_freq /= 1000000; if (dmachild) { - sc->sc_dma = (struct dma_softc *)parent; - sc->sc_dma->sc_esp = sc; + esc->sc_dma = (struct dma_softc *)parent; + esc->sc_dma->sc_esp = esc; } else { /* * find the DMA by poking around the dma device structures @@ -202,56 +268,68 @@ espattach(parent, self, aux) * dma actually gets configured, it does the opposing test, and * if the sc->sc_esp field in it's softc is NULL, then tries to * find the matching esp driver. - * */ - sc->sc_dma = (struct dma_softc *) + esc->sc_dma = (struct dma_softc *) getdevunit("dma", sc->sc_dev.dv_unit); /* * and a back pointer to us, for DMA */ - if (sc->sc_dma) - sc->sc_dma->sc_esp = sc; - else + if (esc->sc_dma) + esc->sc_dma->sc_esp = esc; + else { + printf("\n"); panic("espattach: no dma found"); + } } /* + * XXX More of this should be in ncr53c9x_attach(), but + * XXX should we really poke around the chip that much in + * XXX the MI code? Think about this more... + */ + + /* * It is necessary to try to load the 2nd config register here, - * to find out what rev the esp chip is, else the esp_reset + * to find out what rev the esp chip is, else the ncr53c9x_reset * will not set up the defaults correctly. */ - sc->sc_cfg1 = sc->sc_id | ESPCFG1_PARENB; - sc->sc_cfg2 = ESPCFG2_SCSI2 | ESPCFG2_RPE; - sc->sc_cfg3 = ESPCFG3_CDB; - ESP_WRITE_REG(sc, ESP_CFG2, sc->sc_cfg2); - - if ((ESP_READ_REG(sc, ESP_CFG2) & ~ESPCFG2_RSVD) != (ESPCFG2_SCSI2 | ESPCFG2_RPE)) { - printf(": ESP100"); - sc->sc_rev = ESP100; + sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; + sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE; + sc->sc_cfg3 = NCRCFG3_CDB; + NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); + + if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) != + (NCRCFG2_SCSI2 | NCRCFG2_RPE)) { + sc->sc_rev = NCR_VARIANT_ESP100; } else { - sc->sc_cfg2 = ESPCFG2_SCSI2; - ESP_WRITE_REG(sc, ESP_CFG2, sc->sc_cfg2); + sc->sc_cfg2 = NCRCFG2_SCSI2; + NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); sc->sc_cfg3 = 0; - ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); - sc->sc_cfg3 = (ESPCFG3_CDB | ESPCFG3_FCLK); - ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); - if (ESP_READ_REG(sc, ESP_CFG3) != (ESPCFG3_CDB | ESPCFG3_FCLK)) { - printf(": ESP100A"); - sc->sc_rev = ESP100A; + NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); + sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK); + NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); + if (NCR_READ_REG(sc, NCR_CFG3) != + (NCRCFG3_CDB | NCRCFG3_FCLK)) { + sc->sc_rev = NCR_VARIANT_ESP100A; } else { - /* ESPCFG2_FE enables > 64K transfers */ - sc->sc_cfg2 |= ESPCFG2_FE; + /* NCRCFG2_FE enables > 64K transfers */ + sc->sc_cfg2 |= NCRCFG2_FE; sc->sc_cfg3 = 0; - ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); - printf(": ESP200"); - sc->sc_rev = ESP200; + NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); + sc->sc_rev = NCR_VARIANT_ESP200; } } /* + * XXX minsync and maxxfer _should_ be set up in MI code, + * XXX but it appears to have some dependency on what sort + * XXX of DMA we're hooked up to, etc. + */ + + /* * This is the value used to start sync negotiations - * Note that the ESP register "SYNCTP" is programmed + * Note that the NCR register "SYNCTP" is programmed * in "clocks per byte", and has a minimum value of 4. * The SCSI period used in negotiation is one-fourth * of the time (in nanoseconds) needed to transfer one byte. @@ -262,78 +340,45 @@ espattach(parent, self, aux) /* * Alas, we must now modify the value a bit, because it's - * only valid when can switch on FASTCLK and FASTSCSI bits - * in config register 3... + * only valid when can switch on FASTCLK and FASTSCSI bits + * in config register 3... */ switch (sc->sc_rev) { - case ESP100: + case NCR_VARIANT_ESP100: sc->sc_maxxfer = 64 * 1024; sc->sc_minsync = 0; /* No synch on old chip? */ break; - case ESP100A: + + case NCR_VARIANT_ESP100A: sc->sc_maxxfer = 64 * 1024; - sc->sc_minsync = esp_cpb2stp(sc, 5); /* Min clocks/byte is 5 */ + /* Min clocks/byte is 5 */ + sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5); break; - case ESP200: + + case NCR_VARIANT_ESP200: sc->sc_maxxfer = 16 * 1024 * 1024; /* XXX - do actually set FAST* bits */ + break; } - sc->sc_ccf = FREQTOCCF(sc->sc_freq); - - /* The value *must not* be == 1. Make it 2 */ - if (sc->sc_ccf == 1) - sc->sc_ccf = 2; - - /* - * The recommended timeout is 250ms. This register is loaded - * with a value calculated as follows, from the docs: - * - * (timout period) x (CLK frequency) - * reg = ------------------------------------- - * 8192 x (Clock Conversion Factor) - * - * Since CCF has a linear relation to CLK, this generally computes - * to the constant of 153. - */ - sc->sc_timeout = ((250 * 1000) * sc->sc_freq) / (8192 * sc->sc_ccf); - - /* CCF register only has 3 bits; 0 is actually 8 */ - sc->sc_ccf &= 7; - - /* Reset state & bus */ - sc->sc_state = 0; - esp_init(sc, 1); - - printf(" %dMhz, target %d\n", sc->sc_freq, sc->sc_id); - /* add me to the sbus structures */ - sc->sc_sd.sd_reset = (void *) esp_reset; + esc->sc_sd.sd_reset = (void *) ncr53c9x_reset; #if defined(SUN4C) || defined(SUN4M) if (ca->ca_bustype == BUS_SBUS) { if (dmachild) - sbus_establish(&sc->sc_sd, sc->sc_dev.dv_parent); + sbus_establish(&esc->sc_sd, sc->sc_dev.dv_parent); else - sbus_establish(&sc->sc_sd, &sc->sc_dev); + sbus_establish(&esc->sc_sd, &sc->sc_dev); } #endif /* SUN4C || SUN4M */ /* and the interuppts */ - sc->sc_ih.ih_fun = (void *) espintr; - sc->sc_ih.ih_arg = sc; - intr_establish(sc->sc_pri, &sc->sc_ih); + esc->sc_ih.ih_fun = (void *) ncr53c9x_intr; + esc->sc_ih.ih_arg = sc; + intr_establish(esc->sc_pri, &esc->sc_ih); evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt); /* - * fill in the prototype scsi_link. - */ - sc->sc_link.adapter_softc = sc; - sc->sc_link.adapter_target = sc->sc_id; - sc->sc_link.adapter = &esp_switch; - sc->sc_link.device = &esp_dev; - sc->sc_link.openings = 2; - - /* * If the boot path is "esp" at the moment and it's me, then * walk our pointer to the sub-device, ready for the config * below. @@ -352,1622 +397,104 @@ espattach(parent, self, aux) break; } - /* - * Now try to attach all the sub-devices - */ - config_found(self, &sc->sc_link, espprint); - - bootpath_store(1, NULL); -} - -/* - * This is the generic esp reset function. It does not reset the SCSI bus, - * only this controllers, but kills any on-going commands, and also stops - * and resets the DMA. - * - * After reset, registers are loaded with the defaults from the attach - * routine above. - */ -void -esp_reset(sc) - struct esp_softc *sc; -{ - - /* reset DMA first */ - DMA_RESET(sc->sc_dma); + /* Do the common parts of attachment. */ + ncr53c9x_attach(sc, &esp_switch, &esp_dev); - /* reset SCSI chip */ - ESPCMD(sc, ESPCMD_RSTCHIP); - ESPCMD(sc, ESPCMD_NOP); - DELAY(500); + /* Turn on target selection using the `dma' method */ + ncr53c9x_dmaselect = 1; - /* do these backwards, and fall through */ - switch (sc->sc_rev) { - case ESP200: - ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3); - case ESP100A: - ESP_WRITE_REG(sc, ESP_CFG2, sc->sc_cfg2); - case ESP100: - ESP_WRITE_REG(sc, ESP_CFG1, sc->sc_cfg1); - ESP_WRITE_REG(sc, ESP_CCF, sc->sc_ccf); - ESP_WRITE_REG(sc, ESP_SYNCOFF, 0); - ESP_WRITE_REG(sc, ESP_TIMEOUT, sc->sc_timeout); - break; - default: - printf("%s: unknown revision code, assuming ESP100\n", - sc->sc_dev.dv_xname); - ESP_WRITE_REG(sc, ESP_CFG1, sc->sc_cfg1); - ESP_WRITE_REG(sc, ESP_CCF, sc->sc_ccf); - ESP_WRITE_REG(sc, ESP_SYNCOFF, 0); - ESP_WRITE_REG(sc, ESP_TIMEOUT, sc->sc_timeout); - } + bootpath_store(1, NULL); } /* - * Reset the SCSI bus, but not the chip + * Glue functions. */ -void -esp_scsi_reset(sc) - struct esp_softc *sc; -{ - /* stop DMA first, as the chip will return to Bus Free phase */ - DMACSR(sc->sc_dma) &= ~D_EN_DMA; - - printf("esp: resetting SCSI bus\n"); - ESPCMD(sc, ESPCMD_RSTSCSI); -} -/* - * Initialize esp state machine - */ -void -esp_init(sc, doreset) - struct esp_softc *sc; - int doreset; +u_char +esp_read_reg(sc, reg) + struct ncr53c9x_softc *sc; + int reg; { - struct ecb *ecb; - int r; + struct esp_softc *esc = (struct esp_softc *)sc; - ESP_TRACE(("[ESP_INIT(%d)] ", doreset)); - - if (sc->sc_state == 0) { /* First time through */ - TAILQ_INIT(&sc->ready_list); - TAILQ_INIT(&sc->nexus_list); - TAILQ_INIT(&sc->free_list); - sc->sc_nexus = NULL; - ecb = sc->sc_ecb; - 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; - ecb = sc->sc_nexus; - if (ecb != NULL) { - ecb->xs->error = XS_TIMEOUT; - esp_done(ecb); - sc->sc_nexus = NULL; - } - while ((ecb = sc->nexus_list.tqh_first) != NULL) { - ecb->xs->error = XS_TIMEOUT; - esp_done(ecb); - } - } - - /* - * reset the chip to a known state - */ - esp_reset(sc); - - sc->sc_phase = sc->sc_prevphase = INVALID_PHASE; - for (r = 0; r < 8; r++) { - struct esp_tinfo *tp = &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; - - tp->flags = ((sc->sc_minsync && !(fl & (1<<(r+8)))) - ? T_NEGOTIATE : 0) | - ((fl & (1<<r)) ? T_RSELECTOFF : 0) | - T_NEED_TO_RESET; - tp->period = sc->sc_minsync; - tp->offset = 0; - } - sc->sc_flags &= ~ESP_ABORTING; - - if (doreset) { - sc->sc_state = ESP_SBR; - ESPCMD(sc, ESPCMD_RSTSCSI); - return; - } - - sc->sc_state = ESP_IDLE; - esp_sched(sc); - return; + return (esc->sc_reg[reg * 4]); } -/* - * Read the ESP registers, and save their contents for later use. - * ESP_STAT, ESP_STEP & ESP_INTR are mostly zeroed out when reading - * ESP_INTR - so make sure it is the last read. - * - * I think that (from reading the docs) most bits in these registers - * only make sense when he DMA CSR has an interrupt showing. Call only - * if an interrupt is pending. - */ void -espreadregs(sc) - struct esp_softc *sc; +esp_write_reg(sc, reg, val) + struct ncr53c9x_softc *sc; + int reg; + u_char val; { + struct esp_softc *esc = (struct esp_softc *)sc; + u_char v = val; - sc->sc_espstat = ESP_READ_REG(sc, ESP_STAT); - /* Only the stepo bits are of interest */ - sc->sc_espstep = ESP_READ_REG(sc, ESP_STEP) & ESPSTEP_MASK; - sc->sc_espintr = ESP_READ_REG(sc, ESP_INTR); - - /* - * Determine the SCSI bus phase, return either a real SCSI bus phase - * or some pseudo phase we use to detect certain exceptions. - */ - - sc->sc_phase = (sc->sc_espintr & ESPINTR_DIS) - ? /* Disconnected */ BUSFREE_PHASE - : sc->sc_espstat & ESPSTAT_PHASE; - - ESP_MISC(("regs[intr=%02x,stat=%02x,step=%02x] ", - sc->sc_espintr, sc->sc_espstat, sc->sc_espstep)); + esc->sc_reg[reg * 4] = v; } -/* - * Convert Synchronous Transfer Period to chip register Clock Per Byte value. - */ int -esp_stp2cpb(sc, period) - struct esp_softc *sc; - int period; +esp_dma_isintr(sc) + struct ncr53c9x_softc *sc; { - int v; - v = (sc->sc_freq * period) / 250; - if (esp_cpb2stp(sc, v) < period) - /* Correct round-down error */ - v++; - return v; -} + struct esp_softc *esc = (struct esp_softc *)sc; -/* - * Convert chip register Clock Per Byte value to Synchronous Transfer Period. - */ -int -esp_cpb2stp(sc, cpb) - struct esp_softc *sc; - int cpb; -{ - return ((250 * cpb) / sc->sc_freq); + return (DMA_ISINTR(esc->sc_dma)); } -/* - * Send a command to a target, set the driver state to ESP_SELECTING - * and let the caller take care of the rest. - * - * Keeping this as a function allows me to say that this may be done - * by DMA instead of programmed I/O soon. - */ void -espselect(sc, target, lun, cmd, clen) - struct esp_softc *sc; - u_char target, lun; - u_char *cmd; - u_char clen; +esp_dma_reset(sc) + struct ncr53c9x_softc *sc; { - struct esp_tinfo *ti = &sc->sc_tinfo[target]; - int i; - - ESP_TRACE(("[espselect(t%d,l%d,cmd:%x)] ", target, lun, *(u_char *)cmd)); - - /* 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); - } - - /* - * 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, (ti->flags & T_RSELECTOFF)?0:1)); - - if (ti->flags & T_NEGOTIATE) { - /* Arbitrate, select and stop after IDENTIFY message */ - ESPCMD(sc, ESPCMD_SELATNS); - return; - } - - /* Now the command into the FIFO */ - for (i = 0; i < clen; i++) - ESP_WRITE_REG(sc, ESP_FIFO, *cmd++); - - /* And get the targets attention */ - ESPCMD(sc, ESPCMD_SELATN); + struct esp_softc *esc = (struct esp_softc *)sc; + DMA_RESET(esc->sc_dma); } -/* - * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS - */ - -/* - * Start a SCSI-command - * This function is called by the higher level SCSI-driver to queue/run - * SCSI-commands. - */ int -esp_scsi_cmd(xs) - struct scsi_xfer *xs; +esp_dma_intr(sc) + struct ncr53c9x_softc *sc; { - struct scsi_link *sc_link = xs->sc_link; - struct esp_softc *sc = sc_link->adapter_softc; - struct ecb *ecb; - int s, flags; - - ESP_TRACE(("[esp_scsi_cmd] ")); - 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")); - 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->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); - - 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; + struct esp_softc *esc = (struct esp_softc *)sc; + return (DMA_INTR(esc->sc_dma)); } -/* - * Used when interrupt driven I/O isn't allowed, e.g. during boot. - */ int -esp_poll(sc, ecb) - struct esp_softc *sc; - struct ecb *ecb; +esp_dma_setup(sc, addr, len, datain, dmasize) + struct ncr53c9x_softc *sc; + caddr_t *addr; + size_t *len; + int datain; + size_t *dmasize; { - struct scsi_xfer *xs = ecb->xs; - int count = xs->timeout * 100; + struct esp_softc *esc = (struct esp_softc *)sc; - ESP_TRACE(("[esp_poll] ")); - while (count) { - if (DMA_ISINTR(sc->sc_dma)) { - espintr(sc); - } -#if alternatively - if (ESP_READ_REG(sc, ESP_STAT) & ESPSTAT_INT) - espintr(sc); -#endif - if (xs->flags & ITSDONE) - break; - DELAY(10); - if (sc->sc_state == ESP_IDLE) { - ESP_TRACE(("[esp_poll: rescheduling] ")); - esp_sched(sc); - } - count--; - } - - if (count == 0) { - ESP_MISC(("esp_poll: timeout")); - esp_timeout((caddr_t)ecb); - } - - return COMPLETE; + return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize)); } - -/* - * LOW LEVEL SCSI UTILITIES - */ - -/* - * Schedule a scsi operation. This has now been pulled out of the interrupt - * handler so that we may call it from esp_scsi_cmd and esp_done. This may - * save us an unecessary interrupt just to get things going. Should only be - * called when state == ESP_IDLE and at bio pl. - */ void -esp_sched(sc) - struct esp_softc *sc; +esp_dma_go(sc) + struct ncr53c9x_softc *sc; { - struct scsi_link *sc_link; - struct ecb *ecb; - int t; - - 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]; + struct esp_softc *esc = (struct esp_softc *)sc; - if ((ecb->flags & ECB_QBITS) != ECB_QREADY) - panic("esp: busy entry on ready list"); - 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); - break; - } else - ESP_MISC(("%d:%d busy\n", t, sc_link->lun)); - } + DMA_GO(esc->sc_dma); } -/* - * POST PROCESSING OF SCSI_CMD (usually current) - */ -void -esp_done(ecb) - struct 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 - * 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 - * 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) { - 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 */ - if (ecb != sc->sc_nexus) { - panic("%s: esp_sched: floating ecb %p", - sc->sc_dev.dv_xname, ecb); - } - 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); - } - return; - } else { - xs->resid = ecb->dleft; - } - } - - xs->flags |= ITSDONE; - -#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->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); - } -#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); - } - 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: dequeue: busy ecb on free list", - sc->sc_dev.dv_xname); - break; - default: - panic("%s: dequeue: unknown queue %d", - sc->sc_dev.dv_xname, ecb->flags & ECB_QBITS); - } - - /* Put it on the free list, and clear flags. */ - TAILQ_INSERT_HEAD(&sc->free_list, ecb, chain); - ecb->flags = ECB_QFREE; - - ti->cmds++; - scsi_done(xs); - return; -} - -/* - * INTERRUPT/PROTOCOL ENGINE - */ - -/* - * Schedule an outgoing message by prioritizing it, and asserting - * attention on the bus. We can only do this when we are the initiator - * 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); \ - } while (0) - -#define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80) -#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20) -#define ISEXTMSG(m) ((m) == 1) - -/* - * Get an incoming message as initiator. - * - * The SCSI bus must already be in MESSAGE_IN_PHASE and there is a - * byte in the FIFO - */ void -esp_msgin(sc) - register struct esp_softc *sc; +esp_dma_stop(sc) + struct ncr53c9x_softc *sc; { - register int v; - - ESP_TRACE(("[esp_msgin(curmsglen:%d)] ", sc->sc_imlen)); - - if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) == 0) { - printf("%s: msgin: no msg byte available\n", - sc->sc_dev.dv_xname); - return; - } - - /* - * Prepare for a new message. A message should (according - * to the SCSI standard) be transmitted in one single - * MESSAGE_IN_PHASE. If we have been in some other phase, - * then this is a new message. - */ - if (sc->sc_prevphase != MESSAGE_IN_PHASE) { - sc->sc_flags &= ~ESP_DROP_MSGI; - sc->sc_imlen = 0; - } - - v = ESP_READ_REG(sc, ESP_FIFO); - ESP_MISC(("<msgbyte:0x%02x>", v)); - -#if 0 - if (sc->sc_state == ESP_RESELECTED && sc->sc_imlen == 0) { - /* - * 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; - } -#endif - - sc->sc_imess[sc->sc_imlen] = v; - - /* - * If we're going to reject the message, don't bother storing - * the incoming bytes. But still, we need to ACK them. - */ + struct esp_softc *esc = (struct esp_softc *)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]); - return; - } - - if (sc->sc_imlen >= ESP_MAX_MSG_LEN) { - esp_sched_msgout(SEND_REJECT); - 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 - * significantly. - */ - if (sc->sc_imlen == 1 && IS1BYTEMSG(sc->sc_imess[0])) - goto gotit; - if (sc->sc_imlen == 2 && IS2BYTEMSG(sc->sc_imess[0])) - goto gotit; - if (sc->sc_imlen >= 3 && ISEXTMSG(sc->sc_imess[0]) && - sc->sc_imlen == sc->sc_imess[1] + 2) - goto gotit; - } - /* Ack what we have so far */ - ESPCMD(sc, ESPCMD_MSGOK); - return; - -gotit: - ESP_MSGS(("gotmsg(%x)", sc->sc_imess[0])); - /* - * Now we should have a complete message (1 byte, 2 byte - * and moderately long extended messages). We only handle - * 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_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->sc_dleft = 0; - } - ecb->xs->resid = ecb->dleft = sc->sc_dleft; - sc->sc_flags |= ESP_BUSFREE_OK; - break; - - case MSG_MESSAGE_REJECT: - if (esp_debug & ESP_SHOWMSGS) - printf("%s: our msg rejected by target\n", - sc->sc_dev.dv_xname); -#if 1 /* XXX - must remember last message */ -sc_print_addr(ecb->xs->sc_link); printf("MSG_MESSAGE_REJECT>>"); -#endif - if (sc->sc_flags & ESP_SYNCHNEGO) { - ti->period = ti->offset = 0; - sc->sc_flags &= ~ESP_SYNCHNEGO; - ti->flags &= ~T_NEGOTIATE; - } - /* 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; - 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; - 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("%s:target%d: MSG_PARITY_ERROR\n", - sc->sc_dev.dv_xname, - 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])); - 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) { - printf("%s:%d: async\n", "esp", - ecb->xs->sc_link->target); - ti->offset = 0; - esp_sched_msgout(SEND_SDTR); - } 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); -#ifdef ESP_DEBUG - sc_print_addr(ecb->xs->sc_link); -#endif - if ((sc->sc_flags&ESP_SYNCHNEGO) == 0) { - /* Target initiated negotiation */ - if (ti->flags & T_SYNCMODE) { - ti->flags &= ~T_SYNCMODE; -#ifdef ESP_DEBUG - printf("renegotiated "); -#endif - } - ESP_WRITE_REG(sc, ESP_SYNCOFF, - 0); - ESP_WRITE_REG(sc, ESP_SYNCTP, - 0); - /* Clamp to our maxima */ - if (ti->period < sc->sc_minsync) - ti->period = sc->sc_minsync; - if (ti->offset > 15) - ti->offset = 15; - 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; - } -#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); - break; - } - 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); - } - break; - } - } else if (sc->sc_state == ESP_RESELECTED) { - struct scsi_link *sc_link = NULL; - 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; - } - } - - 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); - 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_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); - } - } else { /* Neither ESP_HASNEXUS nor ESP_RESELECTED! */ - printf("%s: unexpected message in; will send DEV_RESET\n", - sc->sc_dev.dv_xname); - esp_sched_msgout(SEND_DEV_RESET); - } - - /* Ack last message byte */ - ESPCMD(sc, ESPCMD_MSGOK); - - /* Done, reset message pointer. */ - sc->sc_flags &= ~ESP_DROP_MSGI; - sc->sc_imlen = 0; + DMACSR(esc->sc_dma) &= ~D_EN_DMA; } - -/* - * Send the highest priority, scheduled message - */ -void -esp_msgout(sc) - register struct esp_softc *sc; -{ - struct esp_tinfo *ti; - struct 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) { - /* Pick up highest priority message */ - sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq; - sc->sc_omlen = 1; /* "Default" message len */ - switch (sc->sc_msgout) { - case SEND_SDTR: - ecb = sc->sc_nexus; - ti = &sc->sc_tinfo[ecb->xs->sc_link->target]; - sc->sc_omess[0] = MSG_EXTENDED; - sc->sc_omess[1] = 3; - sc->sc_omess[2] = MSG_EXT_SDTR; - sc->sc_omess[3] = ti->period; - sc->sc_omess[4] = ti->offset; - sc->sc_omlen = 5; - break; - case SEND_IDENTIFY: - if (sc->sc_state != ESP_HASNEXUS) { - printf("esp at line %d: no nexus", __LINE__); - } - ecb = sc->sc_nexus; - sc->sc_omess[0] = MSG_IDENTIFY(ecb->xs->sc_link->lun,0); - break; - case SEND_DEV_RESET: - 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; - ti->flags |= T_NEGOTIATE; - break; - case SEND_PARITY_ERROR: - sc->sc_omess[0] = MSG_PARITY_ERROR; - break; - case SEND_ABORT: - 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; - break; - case SEND_REJECT: - sc->sc_omess[0] = MSG_MESSAGE_REJECT; - break; - default: - sc->sc_omess[0] = MSG_NOOP; - break; - } - sc->sc_omp = sc->sc_omess; - } - -#if 1 - /* (re)send the message */ - 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, (size==0?ESPCMD_TRPAD: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 - } -#endif -} - -/* - * This is the most critical part of the driver, and has to know - * how to deal with *all* error conditions and phases from the SCSI - * bus. If there are no errors and the DMA was active, then call the - * DMA pseudo-interrupt handler. If this returns 1, then that was it - * and we can return from here without further processing. - * - * Most of this needs verifying. - */ int -espintr(sc) - register struct esp_softc *sc; +esp_dma_isactive(sc) + struct ncr53c9x_softc *sc; { - register struct 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 - * certainly something happens when this loop is here. - * - * The idea is that many of the SCSI operations take very little - * time, and going away and getting interrupted is too high an - * overhead to pay. For example, selecting, sending a message - * and command and then doing some work can be done in one "pass". - * - * The DELAY is not variable because I do not understand that the - * DELAY loop should be fixed-time regardless of CPU speed, but - * I am *assuming* that the faster SCSI processors get things done - * quicker (sending a command byte etc), and so there is no - * need to be too slow. - * - * This is a heuristic. It is 2 when at 20Mhz, 2 at 25Mhz and 1 - * at 40Mhz. This needs testing. - */ - for (loop = 0; 1;loop++, DELAY(50/sc->sc_freq)) { - /* a feeling of deja-vu */ - if (!DMA_ISINTR(sc->sc_dma)) - return (loop != 0); -#if 0 - if (loop) - printf("*"); -#endif - - /* and what do the registers say... */ - espreadregs(sc); - - sc->sc_intrcnt.ev_count++; - - /* - * At the moment, only a SCSI Bus Reset or Illegal - * Command are classed as errors. A disconnect is a - * valid condition, and we let the code check is the - * "ESP_BUSFREE_OK" flag was set before declaring it - * and error. - * - * Also, the status register tells us about "Gross - * Errors" and "Parity errors". Only the Gross Error - * is really bad, and the parity errors are dealt - * with later - * - * TODO - * If there are too many parity error, go to slow - * cable mode ? - */ - - /* SCSI Reset */ - if (sc->sc_espintr & ESPINTR_SBR) { - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - } - if (sc->sc_state != ESP_SBR) { - printf("%s: SCSI bus reset\n", - sc->sc_dev.dv_xname); - esp_init(sc, 0); /* Restart everything */ - return 1; - } -#if 0 - /*XXX*/ printf("<expected bus reset: " - "[intr %x, stat %x, step %d]>\n", - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); -#endif - 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; - } - - ecb = sc->sc_nexus; - -#define ESPINTR_ERR (ESPINTR_SBR|ESPINTR_ILL) - if (sc->sc_espintr & ESPINTR_ERR || - sc->sc_espstat & ESPSTAT_GE) { - - if (sc->sc_espstat & ESPSTAT_GE) { - /* no target ? */ - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - } - if (sc->sc_state == ESP_HASNEXUS || - sc->sc_state == ESP_SELECTING) { - ecb->xs->error = XS_DRIVER_STUFFUP; - esp_done(ecb); - } - return 1; - } - - if (sc->sc_espintr & ESPINTR_ILL) { - /* illegal command, out of sync ? */ - printf("%s: illegal command: 0x%x (state %d, phase %x, prevphase %x)\n", - sc->sc_dev.dv_xname, sc->sc_lastcmd, - sc->sc_state, sc->sc_phase, - sc->sc_prevphase); - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - } - esp_init(sc, 0); /* Restart everything */ - return 1; - } - } - - /* - * Call if DMA is active. - * - * If DMA_INTR returns true, then maybe go 'round the loop - * again in case there is no more DMA queued, but a phase - * change is expected. - */ - if (DMA_ISACTIVE(sc->sc_dma)) { - DMA_INTR(sc->sc_dma); - /* If DMA active here, then go back to work... */ - if (DMA_ISACTIVE(sc->sc_dma)) - return 1; - - 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 - */ - if (sc->sc_espstat & ESPSTAT_PE) { - printf("%s: SCSI bus parity error\n", - sc->sc_dev.dv_xname); - if (sc->sc_prevphase == MESSAGE_IN_PHASE) - esp_sched_msgout(SEND_PARITY_ERROR); - else - esp_sched_msgout(SEND_INIT_DET_ERR); - } + struct esp_softc *esc = (struct esp_softc *)sc; - if (sc->sc_espintr & ESPINTR_DIS) { - 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); - } - /* - * This command must (apparently) be issued within - * 250mS of a disconnect. So here you are... - */ - ESPCMD(sc, ESPCMD_ENSEL); - if (sc->sc_state != ESP_IDLE) { - if ((sc->sc_flags & ESP_SYNCHNEGO)) { -#ifdef ESP_DEBUG - if (ecb) - sc_print_addr(ecb->xs->sc_link); - printf("sync nego not completed!\n"); -#endif - sc->sc_flags &= ~ESP_SYNCHNEGO; - sc->sc_tinfo[ecb->xs->sc_link->target].offset = 0; - sc->sc_tinfo[ecb->xs->sc_link->target].flags &= ~T_NEGOTIATE; - } - /*XXX*/sc->sc_msgpriq = sc->sc_msgout = 0; - - /* it may be OK to disconnect */ - if (!(sc->sc_flags & ESP_BUSFREE_OK)) { - if (sc->sc_state == ESP_HASNEXUS) { - sc_print_addr(ecb->xs->sc_link); - printf("disconnect without" - "warning\n"); - } - 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; -#if ESP_DEBUG -if ((esp_debug & 0x10000) && ecb->dleft == 0) { - printf("%s: silly disconnect (ecb %p [stat %x])\n", - sc->sc_dev.dv_xname, ecb, ecb->stat); -} -#endif - esp_sched(sc); - return 1; - } - - esp_done(ecb); - return 1; - } - printf("%s: DISCONNECT in IDLE state!\n", - sc->sc_dev.dv_xname); - } - - /* 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 */ - if (sc->sc_msgout == SEND_SDTR && - (sc->sc_flags & ESP_SYNCHNEGO) == 0) { - /* We've just accepted new sync parameters */ - sc->sc_tinfo[ecb->xs->sc_link->target].flags |= - T_SYNCMODE; -if (ecb) sc_print_addr(ecb->xs->sc_link);else printf("NO nexus: "); -printf("target put in SYNC mode\n"); - } - sc->sc_msgpriq &= ~sc->sc_msgout; - sc->sc_msgout = 0; - } - - switch (sc->sc_state) { - - case ESP_SBR: - printf("%s: waiting for SCSI Bus Reset to happen\n", - sc->sc_dev.dv_xname); - return 1; - - case ESP_RESELECTED: - /* - * we must be continuing a message ? - */ - if (sc->sc_phase != MESSAGE_IN_PHASE) { - printf("%s: target didn't identify\n", - sc->sc_dev.dv_xname); - esp_init(sc, 1); - return 1; - } -printf("<<RESELECT CONT'd>>"); -#if XXXX - esp_msgin(sc); - if (sc->sc_state != ESP_HASNEXUS) { - /* IDENTIFY fail?! */ - printf("%s: identify failed\n", - sc->sc_dev.dv_xname); - esp_init(sc, 1); - return 1; - } -#endif - break; - - case ESP_IDLE: -if (sc->sc_flags & ESP_ICCS) printf("[[esp: BUMMER]]"); - case ESP_SELECTING: - - if (sc->sc_espintr & ESPINTR_RESEL) { - /* - * If we're trying to select a - * target ourselves, push our command - * back into the ready list. - */ - if (sc->sc_state == ESP_SELECTING) { - ESP_MISC(("backoff selector ")); - sc_link = sc->sc_nexus->xs->sc_link; - 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; - if (sc->sc_phase != MESSAGE_IN_PHASE) { - /* - * Things are seriously fucked up. - * Pull the brakes, i.e. reset - */ - 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("%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) { - /* IDENTIFY fail?! */ - printf("%s: identify failed\n", - sc->sc_dev.dv_xname); - esp_init(sc, 1); - return 1; - } - continue; /* ie. next phase expected soon */ - } - -#define ESPINTR_DONE (ESPINTR_FC|ESPINTR_BS) - if ((sc->sc_espintr & ESPINTR_DONE) == ESPINTR_DONE) { - ecb = sc->sc_nexus; - if (!ecb) - panic("esp: not nexus at sc->sc_nexus"); - - sc_link = ecb->xs->sc_link; - ti = &sc->sc_tinfo[sc_link->target]; - - switch (sc->sc_espstep) { - case 0: - printf("%s: select timeout/no disconnect\n", - sc->sc_dev.dv_xname); - esp_abort(sc, ecb); - return 1; - 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; - } - if (sc->sc_phase != MESSAGE_OUT_PHASE) { - printf("%s: !MSGOUT\n", - sc->sc_dev.dv_xname); - esp_abort(sc, ecb); - return 1; - } - /* Start negotiating */ - ti->period = sc->sc_minsync; - ti->offset = 15; - sc->sc_msgpriq = SEND_SDTR; - sc->sc_flags |= ESP_SYNCHNEGO; - break; - case 3: - /* - * Grr, this is supposed to mean - * "target left command phase - * prematurely". It seems to happen - * regularly when sync mode is on. - * Look at FIFO to see if command - * went out. - * (Timing problems?) - */ - if ((ESP_READ_REG(sc, ESP_FFLAG)&ESPFIFO_FF) == 0) { - /* Hope for the best.. */ - break; - } - printf("(%s:%d:%d): selection failed;" - " %d left in FIFO " - "[intr %x, stat %x, step %d]\n", - sc->sc_dev.dv_xname, - sc_link->target, - sc_link->lun, - ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - ESPCMD(sc, ESPCMD_FLUSH); - sc->sc_flags |= ESP_ABORTING; - esp_sched_msgout(SEND_ABORT); - return 1; - case 2: - /* Select stuck at Command Phase */ - 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; - else if (ti->flags & T_NEGOTIATE) - sc->sc_msgpriq = - SEND_IDENTIFY | SEND_SDTR; - else - sc->sc_msgpriq = SEND_IDENTIFY; -#endif - sc->sc_state = ESP_HASNEXUS; - /*???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); - break; - } else { - printf("%s: unexpected status after select" - ": [intr %x, stat %x, step %x]\n", - sc->sc_dev.dv_xname, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - esp_abort(sc, ecb); - } - if (sc->sc_state == ESP_IDLE) { - printf("%s: stray interrupt\n", sc->sc_dev.dv_xname); - return 0; - } - break; - - case ESP_HASNEXUS: - if (sc->sc_flags & ESP_ICCS) { - unsigned char msg; - - sc->sc_flags &= ~ESP_ICCS; - - if (!(sc->sc_espintr & ESPINTR_DONE)) { - printf("%s: ICCS: " - ": [intr %x, stat %x, step %x]\n", - sc->sc_dev.dv_xname, - sc->sc_espintr, sc->sc_espstat, - 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; - } - 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; - } else - printf("%s: STATUS_PHASE: msg %d\n", - sc->sc_dev.dv_xname, msg); - ESPCMD(sc, ESPCMD_MSGOK); - continue; /* ie. wait for disconnect */ - } - break; - default: - panic("%s: invalid state: %d", - sc->sc_dev.dv_xname, - sc->sc_state); - } - - /* - * Driver is now in state ESP_HASNEXUS, i.e. we - * have a current command working the SCSI bus. - */ - if (sc->sc_state != ESP_HASNEXUS || ecb == NULL) { - panic("esp no nexus"); - } - - switch (sc->sc_phase) { - case MESSAGE_OUT_PHASE: - ESP_PHASE(("MESSAGE_OUT_PHASE ")); - esp_msgout(sc); - sc->sc_prevphase = MESSAGE_OUT_PHASE; - break; - case MESSAGE_IN_PHASE: - ESP_PHASE(("MESSAGE_IN_PHASE ")); - if (sc->sc_espintr & ESPINTR_BS) { - ESPCMD(sc, ESPCMD_FLUSH); - sc->sc_flags |= ESP_WAITI; - ESPCMD(sc, ESPCMD_TRANS); - } else if (sc->sc_espintr & ESPINTR_FC) { - if ((sc->sc_flags & ESP_WAITI) == 0) { - printf("%s: MSGIN: unexpected FC bit: " - "[intr %x, stat %x, step %x]\n", - sc->sc_dev.dv_xname, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - } - sc->sc_flags &= ~ESP_WAITI; - esp_msgin(sc); - } else { - printf("%s: MSGIN: weird bits: " - "[intr %x, stat %x, step %x]\n", - sc->sc_dev.dv_xname, - sc->sc_espintr, sc->sc_espstat, - sc->sc_espstep); - } - sc->sc_prevphase = MESSAGE_IN_PHASE; - break; - case COMMAND_PHASE: { - /* well, this means send the command again */ - u_char *cmd = (u_char *)&ecb->cmd; - int i; - - ESP_PHASE(("COMMAND_PHASE 0x%02x (%d) ", - ecb->cmd.opcode, ecb->clen)); - if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) { - ESPCMD(sc, ESPCMD_FLUSH); - DELAY(1); - } - /* Now the command into the FIFO */ - for (i = 0; i < ecb->clen; i++) - ESP_WRITE_REG(sc, ESP_FIFO, *cmd++); - ESPCMD(sc, ESPCMD_TRANS); - sc->sc_prevphase = COMMAND_PHASE; - } - break; - case DATA_OUT_PHASE: - ESP_PHASE(("DATA_OUT_PHASE [%d] ", sc->sc_dleft)); - ESPCMD(sc, ESPCMD_FLUSH); - 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; - goto setup_xfer; - case DATA_IN_PHASE: - ESP_PHASE(("DATA_IN_PHASE ")); - if (sc->sc_rev == ESP100) - ESPCMD(sc, ESPCMD_FLUSH); - 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 ")); - sc->sc_flags |= ESP_ICCS; - ESPCMD(sc, ESPCMD_ICCS); - sc->sc_prevphase = STATUS_PHASE; - 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"); - } - } - panic("esp: should not get here.."); -} - -void -esp_abort(sc, ecb) - struct esp_softc *sc; - struct ecb *ecb; -{ - if (ecb == sc->sc_nexus) { - if (sc->sc_state == ESP_HASNEXUS) { - sc->sc_flags |= ESP_ABORTING; - esp_sched_msgout(SEND_ABORT); - } - } else { - if (sc->sc_state == ESP_IDLE) - esp_sched(sc); - } -} - -void -esp_timeout(arg) - void *arg; -{ - int s = splbio(); - struct ecb *ecb = (struct ecb *)arg; - struct esp_softc *sc; - struct scsi_xfer *xs = ecb->xs; - - sc = xs->sc_link->adapter_softc; - sc_print_addr(xs->sc_link); -again: - 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 - - if (ecb->flags & ECB_ABORTED) { - /* abort timed out */ - printf(" AGAIN\n"); - esp_init(sc, 1); - } else { - /* abort the operation that has timed out */ - printf("\n"); - xs->error = XS_TIMEOUT; - ecb->flags |= ECB_ABORTED; - 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); + return (DMA_ISACTIVE(esc->sc_dma)); } diff --git a/sys/arch/sparc/dev/espreg.h b/sys/arch/sparc/dev/espreg.h deleted file mode 100644 index e08eebcad7c..00000000000 --- a/sys/arch/sparc/dev/espreg.h +++ /dev/null @@ -1,148 +0,0 @@ -/* $NetBSD: espreg.h,v 1.7 1995/12/18 23:58:39 pk 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: - * 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 Peter Galbavy. - * 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. - */ - -/* - * Register addresses, relative to some base address - */ - -#define ESP_TCL 0x00 /* RW - Transfer Count Low */ -#define ESP_TCM 0x01 /* RW - Transfer Count Mid */ -#define ESP_TCH 0x0e /* RW - Transfer Count High */ - /* NOT on 53C90 */ - -#define ESP_FIFO 0x02 /* RW - FIFO data */ - -#define ESP_CMD 0x03 /* RW - Command (2 deep) */ -#define ESPCMD_DMA 0x80 /* DMA Bit */ -#define ESPCMD_NOP 0x00 /* No Operation */ -#define ESPCMD_FLUSH 0x01 /* Flush FIFO */ -#define ESPCMD_RSTCHIP 0x02 /* Reset Chip */ -#define ESPCMD_RSTSCSI 0x03 /* Reset SCSI Bus */ -#define ESPCMD_RESEL 0x40 /* Reselect Sequence */ -#define ESPCMD_SELNATN 0x41 /* Select without ATN */ -#define ESPCMD_SELATN 0x42 /* Select with ATN */ -#define ESPCMD_SELATNS 0x43 /* Select with ATN & Stop */ -#define ESPCMD_ENSEL 0x44 /* Enable (Re)Selection */ -#define ESPCMD_DISSEL 0x45 /* Disable (Re)Selection */ -#define ESPCMD_SELATN3 0x46 /* Select with ATN3 */ -#define ESPCMD_RESEL3 0x47 /* Reselect3 Sequence */ -#define ESPCMD_SNDMSG 0x20 /* Send Message */ -#define ESPCMD_SNDSTAT 0x21 /* Send Status */ -#define ESPCMD_SNDDATA 0x22 /* Send Data */ -#define ESPCMD_DISCSEQ 0x23 /* Disconnect Sequence */ -#define ESPCMD_TERMSEQ 0x24 /* Terminate Sequence */ -#define ESPCMD_TCCS 0x25 /* Target Command Comp Seq */ -#define ESPCMD_DISC 0x27 /* Disconnect */ -#define ESPCMD_RECMSG 0x28 /* Receive Message */ -#define ESPCMD_RECCMD 0x29 /* Receive Command */ -#define ESPCMD_RECDATA 0x2a /* Receive Data */ -#define ESPCMD_RECCSEQ 0x2b /* Receive Command Sequence*/ -#define ESPCMD_ABORT 0x04 /* Target Abort DMA */ -#define ESPCMD_TRANS 0x10 /* Transfer Information */ -#define ESPCMD_ICCS 0x11 /* Initiator Cmd Comp Seq */ -#define ESPCMD_MSGOK 0x12 /* Message Accepted */ -#define ESPCMD_TRPAD 0x18 /* Transfer Pad */ -#define ESPCMD_SETATN 0x1a /* Set ATN */ -#define ESPCMD_RSTATN 0x1b /* Reset ATN */ - -#define ESP_STAT 0x04 /* RO - Status */ -#define ESPSTAT_INT 0x80 /* Interrupt */ -#define ESPSTAT_GE 0x40 /* Gross Error */ -#define ESPSTAT_PE 0x20 /* Parity Error */ -#define ESPSTAT_TC 0x10 /* Terminal Count */ -#define ESPSTAT_VGC 0x08 /* Valid Group Code */ -#define ESPSTAT_PHASE 0x07 /* Phase bits */ - -#define ESP_SELID 0x04 /* WO - Select/Reselect Bus ID */ - -#define ESP_INTR 0x05 /* RO - Interrupt */ -#define ESPINTR_SBR 0x80 /* SCSI Bus Reset */ -#define ESPINTR_ILL 0x40 /* Illegal Command */ -#define ESPINTR_DIS 0x20 /* Disconnect */ -#define ESPINTR_BS 0x10 /* Bus Service */ -#define ESPINTR_FC 0x08 /* Function Complete */ -#define ESPINTR_RESEL 0x04 /* Reselected */ -#define ESPINTR_SELATN 0x02 /* Select with ATN */ -#define ESPINTR_SEL 0x01 /* Selected */ - -#define ESP_TIMEOUT 0x05 /* WO - Select/Reselect Timeout */ - -#define ESP_STEP 0x06 /* RO - Sequence Step */ -#define ESPSTEP_MASK 0x07 /* the last 3 bits */ -#define ESPSTEP_DONE 0x04 /* command went out */ - -#define ESP_SYNCTP 0x06 /* WO - Synch Transfer Period */ - /* Default 5 (53C9X) */ - -#define ESP_FFLAG 0x07 /* RO - FIFO Flags */ -#define ESPFIFO_SS 0xe0 /* Sequence Step (Dup) */ -#define ESPFIFO_FF 0x1f /* Bytes in FIFO */ - -#define ESP_SYNCOFF 0x07 /* WO - Synch Offset */ - /* 0 = ASYNC */ - /* 1 - 15 = SYNC bytes */ - -#define ESP_CFG1 0x08 /* RW - Configuration #1 */ -#define ESPCFG1_SLOW 0x80 /* Slow Cable Mode */ -#define ESPCFG1_SRR 0x40 /* SCSI Reset Rep Int Dis */ -#define ESPCFG1_PTEST 0x20 /* Parity Test Mod */ -#define ESPCFG1_PARENB 0x10 /* Enable Parity Check */ -#define ESPCFG1_CTEST 0x08 /* Enable Chip Test */ -#define ESPCFG1_BUSID 0x07 /* Bus ID */ - -#define ESP_CCF 0x09 /* WO - Clock Conversion Factor */ - /* 0 = 35.01 - 40Mhz */ - /* NEVER SET TO 1 */ - /* 2 = 10Mhz */ - /* 3 = 10.01 - 15Mhz */ - /* 4 = 15.01 - 20Mhz */ - /* 5 = 20.01 - 25Mhz */ - /* 6 = 25.01 - 30Mhz */ - /* 7 = 30.01 - 35Mhz */ - -#define ESP_TEST 0x0a /* WO - Test (Chip Test Only) */ - -#define ESP_CFG2 0x0b /* RW - Configuration #2 */ -#define ESPCFG2_RSVD 0xa0 /* reserved */ -#define ESPCFG2_FE 0x40 /* Features Enable */ -#define ESPCFG2_DREQ 0x10 /* DREQ High Impedance */ -#define ESPCFG2_SCSI2 0x08 /* SCSI-2 Enable */ -#define ESPCFG2_BPA 0x04 /* Target Bad Parity Abort */ -#define ESPCFG2_RPE 0x02 /* Register Parity Error */ -#define ESPCFG2_DPE 0x01 /* DMA Parity Error */ - -/* Config #3 only on 53C9X */ -#define ESP_CFG3 0x0c /* RW - Configuration #3 */ -#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) */ diff --git a/sys/arch/sparc/dev/espvar.h b/sys/arch/sparc/dev/espvar.h index 8b0b414a08a..32f81278479 100644 --- a/sys/arch/sparc/dev/espvar.h +++ b/sys/arch/sparc/dev/espvar.h @@ -1,7 +1,10 @@ -/* $NetBSD: espvar.h,v 1.13 1996/05/16 20:31:30 pk Exp $ */ +/* $OpenBSD: espvar.h,v 1.5 1997/08/08 08:25:02 downsj Exp $ */ +/* $NetBSD: espvar.h,v 1.19 1997/02/27 01:16:21 thorpej Exp $ */ /* - * Copyright (c) 1994 Peter Galbavy. All rights reserved. + * Copyright (c) 1997 Jason R. Thorpe. + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +15,8 @@ * 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 Peter Galbavy. + * This product includes software developed for the NetBSD Project + * by Jason R. Thorpe. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * @@ -28,273 +32,20 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define ESP_DEBUG 0 - -#define FREQTOCCF(freq) (((freq + 4) / 5)) - -/* esp revisions */ -#define ESP100 0x01 -#define ESP100A 0x02 -#define ESP200 0x03 - -#if 0 -typedef caddr_t physaddr; - -struct esp_dma_seg { - physaddr addr; - long len; -}; -#endif - -/* - * 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 - * the scsi_xfer struct (except do the expected updating of return values). - * We'll generally update: xs->{flags,resid,error,sense,status} and - * occasionally xs->retries. - */ -struct ecb { - TAILQ_ENTRY(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) - 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 - * this for now. Is there a way to reliably hook it up to sc->fordriver?? - */ -struct esp_tinfo { - int cmds; /* #commands processed */ - int dconns; /* #disconnects */ - int touts; /* #timeouts */ - int perrs; /* #parity errors */ - int senses; /* #request sense commands sent */ - ushort lubusy; /* What local units/subr. are busy? */ - u_char flags; -#define T_NEED_TO_RESET 0x01 /* Should send a BUS_DEV_RESET */ -#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_SYNCHOFF 0x10 /* .. */ -#define T_RSELECTOFF 0x20 /* .. */ - u_char period; /* Period suggestion */ - u_char offset; /* Offset suggestion */ -} tinfo_t; - -/* Register a linenumber (for debugging) */ -#define LOGLINE(p) - -#define ESP_SHOWECBS 0x01 -#define ESP_SHOWINTS 0x02 -#define ESP_SHOWCMDS 0x04 -#define ESP_SHOWMISC 0x08 -#define ESP_SHOWTRAC 0x10 -#define ESP_SHOWSTART 0x20 -#define ESP_SHOWPHASE 0x40 -#define ESP_SHOWDMA 0x80 -#define ESP_SHOWCCMDS 0x100 -#define ESP_SHOWMSGS 0x200 - -#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) -#else -#define ESP_ECBS(str) -#define ESP_MISC(str) -#define ESP_INTS(str) -#define ESP_TRACE(str) -#define ESP_CMDS(str) -#define ESP_START(str) -#define ESP_PHASE(str) -#define ESP_DMA(str) -#endif - -#define ESP_MAX_MSG_LEN 8 - struct esp_softc { - struct device sc_dev; /* us as a device */ + struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ + struct sbusdev sc_sd; /* sbus device */ struct intrhand sc_ih; /* intr handler */ - struct evcnt sc_intrcnt; /* intr count */ - struct scsi_link sc_link; /* scsi lint struct */ + volatile u_char *sc_reg; /* the registers */ struct dma_softc *sc_dma; /* pointer to my dma */ - /* register defaults */ - u_char sc_cfg1; /* Config 1 */ - u_char sc_cfg2; /* Config 2, not ESP100 */ - u_char sc_cfg3; /* Config 3, only ESP200 */ - u_char sc_ccf; /* Clock Conversion */ - u_char sc_timeout; - - /* register copies, see espreadregs() */ - u_char sc_espintr; - u_char sc_espstat; - u_char sc_espstep; - u_char sc_espfflags; - - /* Lists of command blocks */ - TAILQ_HEAD(ecb_list, ecb) free_list, - ready_list, - nexus_list; - - struct ecb *sc_nexus; /* current command */ - struct ecb sc_ecb[8]; /* one per target */ - struct esp_tinfo sc_tinfo[8]; - - /* Data about the current nexus (updated for every cmd switch) */ - caddr_t sc_dp; /* Current data pointer */ - ssize_t sc_dleft; /* Data left to transfer */ - - /* Adapter state */ - int sc_phase; /* Copy of what bus phase we are in */ - int sc_prevphase; /* Copy of what bus phase we were in */ - u_char sc_state; /* State applicable to the adapter */ - u_char sc_flags; - u_char sc_selid; - u_char sc_lastcmd; - - /* 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_omess[ESP_MAX_MSG_LEN]; - caddr_t sc_omp; /* Message pointer (for multibyte messages) */ - size_t sc_omlen; - u_char sc_imess[ESP_MAX_MSG_LEN + 1]; - caddr_t sc_imp; /* Message pointer (for multibyte messages) */ - size_t sc_imlen; - - /* hardware/openprom stuff */ + /* openprom stuff */ int sc_node; /* PROM node ID */ - int sc_freq; /* Freq in HZ */ int sc_pri; /* SBUS priority */ - int sc_id; /* our scsi id */ - int sc_rev; /* esp revision */ - int sc_minsync; /* minimum sync period / 4 */ - int sc_maxxfer; /* maximum transfer size */ }; -/* - * Macros to read and write the chip's registers. - */ -#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) - -/* 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 */ - -/* 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_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 */ - -/* values for sc_msgout */ -#define SEND_DEV_RESET 0x01 -#define SEND_PARITY_ERROR 0x02 -#define SEND_ABORT 0x04 -#define SEND_REJECT 0x08 -#define SEND_INIT_DET_ERR 0x10 -#define SEND_IDENTIFY 0x20 -#define SEND_SDTR 0x40 - -/* 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 */ -#define IOI 0x01 -#define CDI 0x02 -#define MSGI 0x04 - -/* Information transfer phases */ -#define DATA_OUT_PHASE (0) -#define DATA_IN_PHASE (IOI) -#define COMMAND_PHASE (CDI) -#define STATUS_PHASE (CDI|IOI) -#define MESSAGE_OUT_PHASE (MSGI|CDI) -#define MESSAGE_IN_PHASE (MSGI|CDI|IOI) - -#define PHASE_MASK (MSGI|CDI|IOI) - -/* Some pseudo phases for getphase()*/ -#define BUSFREE_PHASE 0x100 /* Re/Selection no longer valid */ -#define INVALID_PHASE 0x101 /* Re/Selection valid, but no REQ yet */ -#define PSEUDO_PHASE 0x100 /* "pseudo" bit */ - -#ifdef ESP_DEBUG -#define ESPCMD(sc, cmd) do { \ - if (esp_debug & ESP_SHOWCCMDS) \ - printf("<cmd:0x%x>", (unsigned)cmd); \ - sc->sc_lastcmd = cmd; \ - ESP_WRITE_REG(sc, ESP_CMD, cmd); \ -} while (0) -#else -#define ESPCMD(sc, cmd) ESP_WRITE_REG(sc, ESP_CMD, cmd) -#endif - #define SAME_ESP(sc, bp, ca) \ ((bp->val[0] == ca->ca_slot && bp->val[1] == ca->ca_offset) || \ (bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit)) - diff --git a/sys/arch/sparc/dev/event.c b/sys/arch/sparc/dev/event.c deleted file mode 100644 index 3e25c91edb4..00000000000 --- a/sys/arch/sparc/dev/event.c +++ /dev/null @@ -1,171 +0,0 @@ -/* $NetBSD: event.c,v 1.3 1994/11/20 20:52:13 deraadt Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * 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, Lawrence Berkeley Laboratory. - * - * 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. - * - * @(#)event.c 8.1 (Berkeley) 6/11/93 - */ - -/* - * Internal `Firm_event' interface for the keyboard and mouse drivers. - */ - -#include <sys/param.h> -#include <sys/fcntl.h> -#include <sys/malloc.h> -#include <sys/proc.h> -#include <sys/systm.h> -#include <sys/vnode.h> - -#include <machine/vuid_event.h> -#include <sparc/dev/event_var.h> - -/* - * Initialize a firm_event queue. - */ -void -ev_init(ev) - register struct evvar *ev; -{ - - ev->ev_get = ev->ev_put = 0; - ev->ev_q = malloc((u_long)EV_QSIZE * sizeof(struct firm_event), - M_DEVBUF, M_WAITOK); - bzero((caddr_t)ev->ev_q, EV_QSIZE * sizeof(struct firm_event)); -} - -/* - * Tear down a firm_event queue. - */ -void -ev_fini(ev) - register struct evvar *ev; -{ - - free(ev->ev_q, M_DEVBUF); -} - -/* - * User-level interface: read, select. - * (User cannot write an event queue.) - */ -int -ev_read(ev, uio, flags) - register struct evvar *ev; - struct uio *uio; - int flags; -{ - int s, n, cnt, error; - - /* - * Make sure we can return at least 1. - */ - if (uio->uio_resid < sizeof(struct firm_event)) - return (EMSGSIZE); /* ??? */ - s = splev(); - while (ev->ev_get == ev->ev_put) { - if (flags & IO_NDELAY) { - splx(s); - return (EWOULDBLOCK); - } - ev->ev_wanted = 1; - error = tsleep((caddr_t)ev, PEVENT | PCATCH, "firm_event", 0); - if (error) { - splx(s); - return (error); - } - } - /* - * Move firm_events from tail end of queue (there is at least one - * there). - */ - if (ev->ev_put < ev->ev_get) - cnt = EV_QSIZE - ev->ev_get; /* events in [get..QSIZE) */ - else - cnt = ev->ev_put - ev->ev_get; /* events in [get..put) */ - splx(s); - n = howmany(uio->uio_resid, sizeof(struct firm_event)); - if (cnt > n) - cnt = n; - error = uiomove((caddr_t)&ev->ev_q[ev->ev_get], - cnt * sizeof(struct firm_event), uio); - n -= cnt; - /* - * If we do not wrap to 0, used up all our space, or had an error, - * stop. Otherwise move from front of queue to put index, if there - * is anything there to move. - */ - if ((ev->ev_get = (ev->ev_get + cnt) % EV_QSIZE) != 0 || - n == 0 || error || (cnt = ev->ev_put) == 0) - return (error); - if (cnt > n) - cnt = n; - error = uiomove((caddr_t)&ev->ev_q[0], - cnt * sizeof(struct firm_event), uio); - ev->ev_get = cnt; - return (error); -} - -int -ev_select(ev, rw, p) - register struct evvar *ev; - int rw; - struct proc *p; -{ - int s = splev(); - - switch (rw) { - - case FREAD: - /* succeed if there is something to read */ - if (ev->ev_get != ev->ev_put) { - splx(s); - return (1); - } - selrecord(p, &ev->ev_sel); - break; - - case FWRITE: - return (1); /* always fails => never blocks */ - } - splx(s); - return (0); -} diff --git a/sys/arch/sparc/dev/event_var.h b/sys/arch/sparc/dev/event_var.h deleted file mode 100644 index 8a7b24fec89..00000000000 --- a/sys/arch/sparc/dev/event_var.h +++ /dev/null @@ -1,87 +0,0 @@ -/* $NetBSD: event_var.h,v 1.2 1994/11/20 20:52:14 deraadt Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * 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, Lawrence Berkeley Laboratory. - * - * 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. - * - * @(#)event_var.h 8.1 (Berkeley) 6/11/93 - */ - -/* - * Internal `Firm_event' interface for the keyboard and mouse drivers. - * The drivers are expected not to place events in the queue above spltty(), - * i.e., are expected to run off serial ports. - */ - -/* EV_QSIZE should be a power of two so that `%' is fast */ -#define EV_QSIZE 256 /* may need tuning; this uses 2k */ - -struct evvar { - u_int ev_get; /* get (read) index (modified synchronously) */ - volatile u_int ev_put; /* put (write) index (modified by interrupt) */ - struct selinfo ev_sel; /* process selecting */ - struct proc *ev_io; /* process that opened queue (can get SIGIO) */ - char ev_wanted; /* wake up on input ready */ - char ev_async; /* send SIGIO on input ready */ - struct firm_event *ev_q;/* circular buffer (queue) of events */ -}; - -#define splev() spltty() - -#define EV_WAKEUP(ev) { \ - selwakeup(&(ev)->ev_sel); \ - if ((ev)->ev_wanted) { \ - (ev)->ev_wanted = 0; \ - wakeup((caddr_t)(ev)); \ - } \ - if ((ev)->ev_async) \ - psignal((ev)->ev_io, SIGIO); \ -} - -void ev_init __P((struct evvar *)); -void ev_fini __P((struct evvar *)); -int ev_read __P((struct evvar *, struct uio *, int)); -int ev_select __P((struct evvar *, int, struct proc *)); - -/* - * PEVENT is set just above PSOCK, which is just above TTIPRI, on the - * theory that mouse and keyboard `user' input should be quick. - */ -#define PEVENT 23 diff --git a/sys/arch/sparc/dev/fb.c b/sys/arch/sparc/dev/fb.c index 37bf3b10be7..5c7e3c70916 100644 --- a/sys/arch/sparc/dev/fb.c +++ b/sys/arch/sparc/dev/fb.c @@ -1,5 +1,5 @@ -/* $OpenBSD: fb.c,v 1.9 1996/08/13 08:05:25 downsj Exp $ */ -/* $NetBSD: fb.c,v 1.18 1996/04/01 17:29:54 christos Exp $ */ +/* $OpenBSD: fb.c,v 1.10 1997/08/08 08:25:04 downsj Exp $ */ +/* $NetBSD: fb.c,v 1.23 1997/07/07 23:30:22 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -299,23 +299,23 @@ fb_setsize(fb, depth, def_width, def_height, node, bustype) break; } } else if (eep != NULL) { - switch (eep->ee_diag.eed_scrsize) { - case EED_SCR_1152X900: + switch (eep->eeScreenSize) { + case EE_SCR_1152X900: fb->fb_type.fb_width = 1152; fb->fb_type.fb_height = 900; break; - case EED_SCR_1024X1024: + case EE_SCR_1024X1024: fb->fb_type.fb_width = 1024; fb->fb_type.fb_height = 1024; break; - case EED_SCR_1600X1280: + case EE_SCR_1600X1280: fb->fb_type.fb_width = 1600; fb->fb_type.fb_height = 1280; break; - case EED_SCR_1440X1440: + case EE_SCR_1440X1440: fb->fb_type.fb_width = 1440; fb->fb_type.fb_height = 1440; break; @@ -354,12 +354,15 @@ fb_setsize(fb, depth, def_width, def_height, node, bustype) } } + #ifdef RASTERCONSOLE #include <machine/kbd.h> -static int a2int __P((char *, int)); static void fb_bell __P((int)); +#if !(defined(RASTERCONS_FULLSCREEN) || defined(RASTERCONS_SMALLFONT)) +static int a2int __P((char *, int)); + static int a2int(cp, deflt) register char *cp; @@ -373,6 +376,7 @@ a2int(cp, deflt) i = i * 10 + *cp++ - '0'; return (i); } +#endif static void fb_bell(on) @@ -413,8 +417,8 @@ fbrcons_init(fb) rc->rc_maxcol = 80; rc->rc_maxrow = 34; } else { - rc->rc_maxcol = eep->ee_diag.eed_colsize; - rc->rc_maxrow = eep->ee_diag.eed_rowsize; + rc->rc_maxcol = eep->eeTtyCols; + rc->rc_maxrow = eep->eeTtyRows; } } #endif /* SUN4 */ @@ -439,7 +443,19 @@ fbrcons_init(fb) /* Hook up virtual console */ v_putc = rcons_cnputc; } -#endif + +int +fbrcons_rows() +{ + return (devfb ? devfb->fb_rcons.rc_maxrow : 0); +} + +int +fbrcons_cols() +{ + return (devfb ? devfb->fb_rcons.rc_maxcol : 0); +} +#endif /* RASTERCONSOLE */ #if defined(SUN4) /* diff --git a/sys/arch/sparc/dev/fd.c b/sys/arch/sparc/dev/fd.c index 456ab415b6e..1643db5b031 100644 --- a/sys/arch/sparc/dev/fd.c +++ b/sys/arch/sparc/dev/fd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fd.c,v 1.19 1997/06/25 13:04:20 downsj Exp $ */ +/* $OpenBSD: fd.c,v 1.20 1997/08/08 08:25:06 downsj Exp $ */ /* $NetBSD: fd.c,v 1.51 1997/05/24 20:16:19 pk Exp $ */ /*- @@ -369,8 +369,7 @@ fdcattach(parent, self, aux) fdc->sc_reg = (caddr_t)ca->ca_ra.ra_vaddr; else fdc->sc_reg = (caddr_t)mapiodev(ca->ca_ra.ra_reg, 0, - ca->ca_ra.ra_len, - ca->ca_bustype); + ca->ca_ra.ra_len); fdc->sc_state = DEVIDLE; fdc->sc_istate = ISTATE_IDLE; diff --git a/sys/arch/sparc/dev/i82586.h b/sys/arch/sparc/dev/i82586.h index 02cd09ef98f..4c5ead2fec3 100644 --- a/sys/arch/sparc/dev/i82586.h +++ b/sys/arch/sparc/dev/i82586.h @@ -1,3 +1,4 @@ +/* $OpenBSD: i82586.h,v 1.2 1997/08/08 08:25:07 downsj Exp $ */ /* $NetBSD: i82586.h,v 1.3 1995/01/27 09:49:55 pk Exp $ */ /*- diff --git a/sys/arch/sparc/dev/if_en_sbus.c b/sys/arch/sparc/dev/if_en_sbus.c index 9ba4cd3ca99..499f80901fc 100644 --- a/sys/arch/sparc/dev/if_en_sbus.c +++ b/sys/arch/sparc/dev/if_en_sbus.c @@ -1,4 +1,5 @@ -/* $OpenBSD: if_en_sbus.c,v 1.2 1996/06/21 21:37:37 chuck Exp $ */ +/* $OpenBSD: if_en_sbus.c,v 1.3 1997/08/08 08:25:08 downsj Exp $ */ +/* $NetBSD: if_en_sbus.c,v 1.4 1997/05/24 20:16:22 pk Exp $ */ /* * @@ -138,8 +139,7 @@ void *aux; return; } - sc->en_base = (caddr_t) mapiodev(ca->ca_ra.ra_reg, 0, 4*1024*1024, - ca->ca_bustype); + sc->en_base = (caddr_t) mapiodev(ca->ca_ra.ra_reg, 0, 4*1024*1024); if (ca->ca_ra.ra_nintr == 1) { sc->ipl = ca->ca_ra.ra_intr[0].int_pri; diff --git a/sys/arch/sparc/dev/if_ie.c b/sys/arch/sparc/dev/if_ie.c index 3bd3defb91a..d57746dbadc 100644 --- a/sys/arch/sparc/dev/if_ie.c +++ b/sys/arch/sparc/dev/if_ie.c @@ -1,4 +1,5 @@ -/* $NetBSD: if_ie.c,v 1.24 1996/05/07 01:28:28 thorpej Exp $ */ +/* $OpenBSD: if_ie.c,v 1.7 1997/08/08 08:25:09 downsj Exp $ */ +/* $NetBSD: if_ie.c,v 1.33 1997/07/29 17:55:38 fair Exp $ */ /*- * Copyright (c) 1993, 1994, 1995 Charles Hannum. @@ -413,23 +414,22 @@ iematch(parent, vcf, aux) if (strcmp(cf->cf_driver->cd_name, ra->ra_name)) /* correct name? */ return (0); - if (ca->ca_bustype == BUS_SBUS) - return (0); - - if (CPU_ISSUN4) { - /* - * XXX need better probe here so we can figure out what we've got - */ - if (ca->ca_bustype == BUS_OBIO) { - if (probeget(ra->ra_vaddr, 1) == -1) - return (0); - return(1); - } - if (probeget(ra->ra_vaddr, 2) == -1) - return (0); + switch (ca->ca_bustype) { + case BUS_SBUS: + default: + return (0); + case BUS_OBIO: + if (probeget(ra->ra_vaddr, 1) != -1) + return (1); + break; + case BUS_VME16: + case BUS_VME32: + if (probeget(ra->ra_vaddr, 2) != -1) + return (1); + break; } - return (1); + return (0); } /* @@ -530,8 +530,7 @@ ieattach(parent, self, aux) sc->memcopy = bcopy; sc->memzero = bzero; sc->sc_msize = 65536; /* XXX */ - sc->sc_reg = mapiodev(ca->ca_ra.ra_reg, 0, sizeof(struct ieob), - ca->ca_bustype); + sc->sc_reg = mapiodev(ca->ca_ra.ra_reg, 0, sizeof(struct ieob)); ieo = (volatile struct ieob *) sc->sc_reg; /* @@ -594,8 +593,8 @@ ieattach(parent, self, aux) sc->memcopy = wcopy; sc->memzero = wzero; sc->sc_msize = 65536; /* XXX */ - sc->sc_reg = mapiodev(ca->ca_ra.ra_reg, 0, sizeof(struct ievme), - ca->ca_bustype); + sc->sc_reg = mapiodev(ca->ca_ra.ra_reg, 0, + sizeof(struct ievme)); iev = (volatile struct ievme *) sc->sc_reg; /* top 12 bits */ rampaddr = (u_long)ca->ca_ra.ra_paddr & 0xfff00000; @@ -603,7 +602,7 @@ ieattach(parent, self, aux) rampaddr = rampaddr | ((iev->status & IEVME_HADDR) << 16); rampaddr -= (u_long)ca->ca_ra.ra_paddr; sc->sc_maddr = mapiodev(ca->ca_ra.ra_reg, rampaddr, - sc->sc_msize, ca->ca_bustype); + sc->sc_msize); sc->sc_iobase = sc->sc_maddr; iev->pectrl = iev->pectrl | IEVME_PARACK; /* clear to start */ @@ -731,7 +730,7 @@ void *v; volatile struct ievme *iev = (volatile struct ievme *)sc->sc_reg ; if (iev->status & IEVME_PERR) { - printf("%s: parity error (ctrl %x @ %02x%04x)\n", + printf("%s: parity error (ctrl 0x%x @ 0x%02x%04x)\n", sc->sc_dev.dv_xname, iev->pectrl, iev->pectrl & IEVME_HADDR, iev->peaddr); iev->pectrl = iev->pectrl | IEVME_PARACK; @@ -1317,7 +1316,8 @@ ie_readframe(sc, num) #ifdef IEDEBUG if (sc->sc_debug & IED_READFRAME) - printf("%s: frame from ether %s type %x\n", sc->sc_dev.dv_xname, + printf("%s: frame from ether %s type 0x%x\n", + sc->sc_dev.dv_xname, ether_sprintf(eh.ether_shost), (u_int)eh.ether_type); #endif @@ -1654,7 +1654,7 @@ run_tdr(sc, cmd) printf("%s: TDR detected a short %d clocks away\n", sc->sc_dev.dv_xname, result & IE_TDR_TIME); else - printf("%s: TDR returned unknown status %x\n", + printf("%s: TDR returned unknown status 0x%x\n", sc->sc_dev.dv_xname, result); } diff --git a/sys/arch/sparc/dev/if_ie.h b/sys/arch/sparc/dev/if_ie.h index 0008a85417d..b9860155b66 100644 --- a/sys/arch/sparc/dev/if_ie.h +++ b/sys/arch/sparc/dev/if_ie.h @@ -1,3 +1,4 @@ +/* $OpenBSD: if_ie.h,v 1.2 1997/08/08 08:25:11 downsj Exp $ */ /* $NetBSD: if_ie.h,v 1.4 1994/12/16 22:01:11 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/dev/if_le.c b/sys/arch/sparc/dev/if_le.c index 4db240f0f62..b0bf63e56e6 100644 --- a/sys/arch/sparc/dev/if_le.c +++ b/sys/arch/sparc/dev/if_le.c @@ -1,6 +1,8 @@ -/* $NetBSD: if_le.c,v 1.35.4.1 1996/07/17 01:46:00 jtc Exp $ */ +/* $OpenBSD: if_le.c,v 1.7 1997/08/08 08:25:12 downsj Exp $ */ +/* $NetBSD: if_le.c,v 1.49 1997/07/07 16:28:44 pk Exp $ */ /*- + * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. * Copyright (c) 1996 * The President and Fellows of Harvard College. All rights reserved. * Copyright (c) 1995 Charles M. Hannum. All rights reserved. @@ -22,6 +24,8 @@ * must display the following acknowledgement: * This product includes software developed by Aaron Brown and * Harvard University. + * This product includes software developed for the NetBSD Project + * by Jason R. Thorpe. * 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 @@ -54,10 +58,18 @@ #include <sys/malloc.h> #include <net/if.h> +#if defined(__NetBSD__) +#include <net/if_ether.h> +#include <net/if_media.h> +#endif /* __NetBSD__ */ #ifdef INET #include <netinet/in.h> +#if defined(__NetBSD__) +#include <netinet/if_inarp.h> +#else #include <netinet/if_ether.h> +#endif /* __NetBSD__ */ #endif #include <machine/autoconf.h> @@ -66,6 +78,7 @@ #include <sparc/dev/sbusvar.h> #include <sparc/dev/dmareg.h> #include <sparc/dev/dmavar.h> +#include <sparc/dev/lebuffervar.h> #include <dev/ic/am7990reg.h> #include <dev/ic/am7990var.h> @@ -73,7 +86,11 @@ #include <sparc/dev/if_lereg.h> #include <sparc/dev/if_levar.h> +#if defined(__NetBSD__) +int lematch __P((struct device *, struct cfdata *, void *)); +#else int lematch __P((struct device *, void *, void *)); +#endif /* __NetBSD__ */ void leattach __P((struct device *, struct device *, void *)); #if defined(SUN4M) /* XXX */ @@ -89,25 +106,41 @@ myleintr(arg) if (lesc->sc_dma->sc_regs->csr & D_ERR_PEND) return ledmaintr(lesc->sc_dma); - /* - * XXX There is a bug somewhere in the interrupt code that causes stray - * ethernet interrupts under high network load. This bug has been - * impossible to locate, so until it is found, we just ignore stray - * interrupts, as they do not in fact correspond to dropped packets. - */ - - /* return */ am7990_intr(arg); - return 1; + return (am7990_intr(arg)); } #endif +#if defined(SUN4M) +#if defined(__NetBSD__) +/* + * Media types supported by the Sun4m. + */ +int lemediasun4m[] = { + IFM_ETHER|IFM_10_T, + IFM_ETHER|IFM_10_5, + IFM_ETHER|IFM_AUTO, +}; +#define NLEMEDIASUN4M (sizeof(lemediasun4m) / sizeof(lemediasun4m[0])) +#endif /* __NetBSD__ */ + +void lesetutp __P((struct am7990_softc *)); +void lesetaui __P((struct am7990_softc *)); + +int lemediachange __P((struct am7990_softc *)); +#if defined(__NetBSD__) +void lemediastatus __P((struct am7990_softc *, struct ifmediareq *)); +#endif /* __NetBSD__ */ +#endif /* SUN4M */ + struct cfattach le_ca = { sizeof(struct le_softc), lematch, leattach }; hide void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t)); hide u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t)); +hide void lehwreset __P((struct am7990_softc *)); hide void lehwinit __P((struct am7990_softc *)); +hide void lenocarrier __P((struct am7990_softc *)); hide void lewrcsr(sc, port, val) @@ -115,9 +148,21 @@ lewrcsr(sc, port, val) u_int16_t port, val; { register struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; +#if defined(SUN4M) + volatile u_int16_t discard; +#endif ler1->ler1_rap = port; ler1->ler1_rdp = val; +#if defined(SUN4M) + /* + * We need to flush the Sbus->Mbus write buffers. This can most + * easily be accomplished by reading back the register that we + * just wrote (thanks to Chris Torek for this solution). + */ + if (CPU_ISSUN4M) + discard = ler1->ler1_rdp; +#endif } hide u_int16_t @@ -133,6 +178,109 @@ lerdcsr(sc, port) return (val); } +#if defined(SUN4M) +void +lesetutp(sc) + struct am7990_softc *sc; +{ + struct le_softc *lesc = (struct le_softc *)sc; + + lesc->sc_dma->sc_regs->csr |= DE_AUI_TP; + delay(20000); /* must not touch le for 20ms */ +} + +void +lesetaui(sc) + struct am7990_softc *sc; +{ + struct le_softc *lesc = (struct le_softc *)sc; + + lesc->sc_dma->sc_regs->csr &= ~DE_AUI_TP; + delay(20000); /* must not touch le for 20ms */ +} + +int +lemediachange(sc) + struct am7990_softc *sc; +{ +#if defined(__NetBSD__) + struct ifmedia *ifm = &sc->sc_media; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + /* + * Switch to the selected media. If autoselect is + * set, we don't really have to do anything. We'll + * switch to the other media when we detect loss of + * carrier. + */ + switch (IFM_SUBTYPE(ifm->ifm_media)) { + case IFM_10_T: + lesetutp(sc); + break; + + case IFM_10_5: + lesetaui(sc); + break; + + case IFM_AUTO: + break; + + default: + return (EINVAL); + } +#else + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + + if (ifp->if_flags & IFF_LINK0) + lesetutp(sc); + else if (ifp->if_flags & IFF_LINK1) + lesetaui(sc); +#endif /* __NetBSD__ */ + return (0); +} + +#if defined(__NetBSD__) +void +lemediastatus(sc, ifmr) + struct am7990_softc *sc; + struct ifmediareq *ifmr; +{ + struct le_softc *lesc = (struct le_softc *)sc; + + if (lesc->sc_dma == NULL) + return; + + /* + * Notify the world which media we're currently using. + */ + if (lesc->sc_dma->sc_regs->csr & DE_AUI_TP) + ifmr->ifm_active = IFM_ETHER|IFM_10_T; + else + ifmr->ifm_active = IFM_ETHER|IFM_10_5; +} +#endif /* __NetBSD__ */ +#endif /* SUN4M */ + +hide void +lehwreset(sc) + struct am7990_softc *sc; +{ +#if defined(SUN4M) + struct le_softc *lesc = (struct le_softc *)sc; + + /* + * Reset DMA channel. + */ + if (CPU_ISSUN4M && lesc->sc_dma) { + DMA_RESET(lesc->sc_dma); + lesc->sc_dma->sc_regs->en_bar = lesc->sc_laddr & 0xff000000; + DMA_ENINTR(lesc->sc_dma); + } +#endif +} + hide void lehwinit(sc) struct am7990_softc *sc; @@ -140,25 +288,100 @@ lehwinit(sc) #if defined(SUN4M) struct le_softc *lesc = (struct le_softc *)sc; + /* + * Make sure we're using the currently-enabled media type. + * XXX Actually, this is probably unnecessary, now. + */ if (CPU_ISSUN4M && lesc->sc_dma) { +#if defined(__NetBSD__) + switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) { + case IFM_10_T: + lesetutp(sc); + break; + + case IFM_10_5: + lesetaui(sc); + break; + } +#else struct ifnet *ifp = &sc->sc_arpcom.ac_if; if (ifp->if_flags & IFF_LINK0) - lesc->sc_dma->sc_regs->csr |= DE_AUI_TP; + lesetutp(sc); else if (ifp->if_flags & IFF_LINK1) - lesc->sc_dma->sc_regs->csr &= ~DE_AUI_TP; - - delay(20000); /* must not touch le for 20ms */ + lesetaui(sc); +#endif /* __NetBSD__ */ } #endif } +hide void +lenocarrier(sc) + struct am7990_softc *sc; +{ +#if defined(SUN4M) + struct le_softc *lesc = (struct le_softc *)sc; +#if !defined(__NetBSD__) + struct ifnet *ifp = &sc->sc_arpcom.ac_if; +#endif /* __NetBSD__ */ + + if (CPU_ISSUN4M && lesc->sc_dma) { + /* + * Check if the user has requested a certain cable type, and + * if so, honor that request. + */ + printf("%s: lost carrier on ", sc->sc_dev.dv_xname); + if (lesc->sc_dma->sc_regs->csr & DE_AUI_TP) { + printf("UTP port"); +#if defined(__NetBSD__) + switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { + case IFM_10_5: + case IFM_AUTO: + printf(", switching to AUI port"); + lesetaui(sc); + } +#else + if (!(ifp->if_flags & IFF_LINK0)) { + printf(", switching to AUI port"); + lesetaui(sc); + } +#endif /* __NetBSD__ */ + } else { + printf("AUI port"); +#if defined(__NetBSD__) + switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { + case IFM_10_T: + case IFM_AUTO: + printf(", switching to UTP port"); + lesetutp(sc); + } +#else + if (!(ifp->if_flags & IFF_LINK1)) { + printf(", switching to UTP port"); + lesetutp(sc); + } +#endif /* __NetBSD__ */ + } + printf("\n"); + } else +#endif + printf("%s: lost carrier\n", sc->sc_dev.dv_xname); +} + int -lematch(parent, match, aux) +#if defined(__NetBSD__) +lematch(parent, cf, aux) struct device *parent; - void *match, *aux; + struct cfdata *cf; + void *aux; { - struct cfdata *cf = match; +#else +lematch(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct cfdata *cf = vcf; +#endif /* __NetBSD__ */ struct confargs *ca = aux; register struct romaux *ra = &ca->ca_ra; @@ -180,9 +403,11 @@ leattach(parent, self, aux) struct confargs *ca = aux; int pri; struct bootpath *bp; - u_long laddr; #if defined(SUN4C) || defined(SUN4M) int sbuschild = strncmp(parent->dv_xname, "sbus", 4) == 0; + int lebufchild = strncmp(parent->dv_xname, "lebuffer", 8) == 0; + int dmachild = strncmp(parent->dv_xname, "ledma", 5) == 0; + struct lebuf_softc *lebuf; #endif /* XXX the following declarations should be elsewhere */ @@ -195,31 +420,62 @@ leattach(parent, self, aux) pri = ca->ca_ra.ra_intr[0].int_pri; printf(" pri %d", pri); - lesc->sc_r1 = (struct lereg1 *)mapiodev(ca->ca_ra.ra_reg, 0, - sizeof(struct lereg1), - ca->ca_bustype); - sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; - laddr = (u_long)dvma_malloc(MEMSIZE, &sc->sc_mem, M_NOWAIT); + lesc->sc_r1 = (struct lereg1 *) + mapiodev(ca->ca_ra.ra_reg, 0, sizeof(struct lereg1)); + +#if defined(SUN4C) || defined(SUN4M) + lebuf = NULL; + if (lebufchild) { + lebuf = (struct lebuf_softc *)parent; + } else if (sbuschild) { + struct sbus_softc *sbus = (struct sbus_softc *)parent; + struct sbusdev *sd; + + /* + * Find last "unallocated" lebuffer and pair it with + * this `le' device on the assumption that we're on + * a pre-historic ROM that doesn't establish le<=>lebuffer + * parent-child relationships. + */ + for (sd = sbus->sc_sbdev; sd != NULL; sd = sd->sd_bchain) { + if (strncmp("lebuffer", sd->sd_dev->dv_xname, 8) != 0) + continue; + if (((struct lebuf_softc *)sd->sd_dev)->attached == 0) { + lebuf = (struct lebuf_softc *)sd->sd_dev; + break; + } + } + } + if (lebuf != NULL) { + sc->sc_mem = lebuf->sc_buffer; + sc->sc_memsize = lebuf->sc_bufsiz; + sc->sc_addr = 0; /* Lance view is offset by buffer location */ + lebuf->attached = 1; + + /* That old black magic... */ + sc->sc_conf3 = getpropint(ca->ca_ra.ra_node, + "busmaster-regval", + LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON); + } else +#endif + { + u_long laddr; + laddr = (u_long)dvma_malloc(MEMSIZE, &sc->sc_mem, M_NOWAIT); #if defined (SUN4M) - if ((laddr & 0xffffff) >= (laddr & 0xffffff) + MEMSIZE) - panic("if_le: Lance buffer crosses 16MB boundary"); + if ((laddr & 0xffffff) >= (laddr & 0xffffff) + MEMSIZE) + panic("if_le: Lance buffer crosses 16MB boundary"); #endif - sc->sc_addr = laddr & 0xffffff; - sc->sc_memsize = MEMSIZE; - - myetheraddr(sc->sc_arpcom.ac_enaddr); - - sc->sc_copytodesc = am7990_copytobuf_contig; - sc->sc_copyfromdesc = am7990_copyfrombuf_contig; - sc->sc_copytobuf = am7990_copytobuf_contig; - sc->sc_copyfrombuf = am7990_copyfrombuf_contig; - sc->sc_zerobuf = am7990_zerobuf_contig; - - sc->sc_rdcsr = lerdcsr; - sc->sc_wrcsr = lewrcsr; - sc->sc_hwinit = lehwinit; - - am7990_config(sc); + sc->sc_addr = laddr & 0xffffff; + sc->sc_memsize = MEMSIZE; + sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; +#if defined(SUN4C) || defined(SUN4M) + if (dmachild) { + lesc->sc_dma = (struct dma_softc *)parent; + lesc->sc_dma->sc_le = lesc; + lesc->sc_laddr = laddr; + } +#endif + } bp = ca->ca_ra.ra_bp; switch (ca->ca_bustype) { @@ -231,12 +487,8 @@ leattach(parent, self, aux) case BUS_SBUS: lesc->sc_sd.sd_reset = (void *)am7990_reset; if (sbuschild) { - lesc->sc_dma = NULL; sbus_establish(&lesc->sc_sd, &sc->sc_dev); } else { - lesc->sc_dma = (struct dma_softc *)parent; - lesc->sc_dma->sc_le = lesc; - lesc->sc_dma->sc_regs->en_bar = laddr & 0xff000000; /* Assume SBus is grandparent */ sbus_establish(&lesc->sc_sd, parent); } @@ -254,16 +506,44 @@ leattach(parent, self, aux) break; } +#if defined(__NetBSD__) + myetheraddr(sc->sc_enaddr); +#else + myetheraddr(sc->sc_arpcom.ac_enaddr); +#endif /* __NetBSD__ */ + + sc->sc_copytodesc = am7990_copytobuf_contig; + sc->sc_copyfromdesc = am7990_copyfrombuf_contig; + sc->sc_copytobuf = am7990_copytobuf_contig; + sc->sc_copyfrombuf = am7990_copyfrombuf_contig; + sc->sc_zerobuf = am7990_zerobuf_contig; + + sc->sc_rdcsr = lerdcsr; + sc->sc_wrcsr = lewrcsr; + sc->sc_hwinit = lehwinit; + sc->sc_nocarrier = lenocarrier; + sc->sc_hwreset = lehwreset; + +#if defined(SUN4M) && defined(__NetBSD__) + if (CPU_ISSUN4M && lesc->sc_dma) { + sc->sc_mediachange = lemediachange; + sc->sc_mediastatus = lemediastatus; + sc->sc_supmedia = lemediasun4m; + sc->sc_nsupmedia = NLEMEDIASUN4M; + sc->sc_defaultmedia = IFM_ETHER|IFM_AUTO; + } +#endif + + am7990_config(sc); + lesc->sc_ih.ih_fun = am7990_intr; #if defined(SUN4M) /*XXX*/ - if (CPU_ISSUN4M) + if (CPU_ISSUN4M && lesc->sc_dma) lesc->sc_ih.ih_fun = myleintr; #endif lesc->sc_ih.ih_arg = sc; intr_establish(pri, &lesc->sc_ih); /* now initialize DMA */ - if (lesc->sc_dma) { - DMA_ENINTR(lesc->sc_dma); - } + lehwreset(sc); } diff --git a/sys/arch/sparc/dev/if_lereg.h b/sys/arch/sparc/dev/if_lereg.h index 5035566a439..429ba05a831 100644 --- a/sys/arch/sparc/dev/if_lereg.h +++ b/sys/arch/sparc/dev/if_lereg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: if_lereg.h,v 1.3 1997/08/08 08:25:13 downsj Exp $ */ /* $NetBSD: if_lereg.h,v 1.5 1995/12/10 10:15:07 mycroft Exp $ */ /*- diff --git a/sys/arch/sparc/dev/if_levar.h b/sys/arch/sparc/dev/if_levar.h index 934d74c932e..2c73d8405d9 100644 --- a/sys/arch/sparc/dev/if_levar.h +++ b/sys/arch/sparc/dev/if_levar.h @@ -1,4 +1,5 @@ -/* $NetBSD: if_levar.h,v 1.5 1996/05/07 01:27:32 thorpej Exp $ */ +/* $OpenBSD: if_levar.h,v 1.3 1997/08/08 08:25:14 downsj Exp $ */ +/* $NetBSD: if_levar.h,v 1.7 1997/04/04 20:29:23 pk Exp $ */ /*- * Copyright (c) 1995 Charles M. Hannum. All rights reserved. @@ -43,7 +44,7 @@ * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, - * arpcom.ac_if, which the routing code uses to locate the interface. + * ethercom.ec_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */ struct le_softc { @@ -53,4 +54,5 @@ struct le_softc { struct intrhand sc_ih; /* interrupt vectoring */ struct lereg1 *sc_r1; /* LANCE registers */ struct dma_softc *sc_dma; /* pointer to my dma */ + u_long sc_laddr; /* LANCE DMA address */ }; diff --git a/sys/arch/sparc/dev/isp_sbus.c b/sys/arch/sparc/dev/isp_sbus.c new file mode 100644 index 00000000000..24fcb5caec2 --- /dev/null +++ b/sys/arch/sparc/dev/isp_sbus.c @@ -0,0 +1,331 @@ +/* $OpenBSD: isp_sbus.c,v 1.1 1997/08/08 08:25:15 downsj Exp $ */ +/* $NetBSD: isp_sbus.c,v 1.6 1997/06/08 06:35:45 thorpej Exp $ */ + +/* + * SBus specific probe and attach routines for Qlogic ISP SCSI adapters. + * + * Copyright (c) 1997 by Matthew Jacob + * NASA AMES Research Center + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/queue.h> +#include <sys/device.h> +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> + +#include <machine/autoconf.h> +#include <sparc/cpu.h> +#include <sparc/sparc/cpuvar.h> +#include <sparc/dev/sbusvar.h> + +#include <dev/ic/ispreg.h> +#include <dev/ic/ispvar.h> +#include <dev/microcode/isp/asm_sbus.h> +#include <machine/param.h> +#include <machine/vmparam.h> + + +static u_int16_t isp_sbus_rd_reg __P((struct ispsoftc *, int)); +static void isp_sbus_wr_reg __P((struct ispsoftc *, int, u_int16_t)); +static int isp_sbus_mbxdma __P((struct ispsoftc *)); +static int isp_sbus_dmasetup __P((struct ispsoftc *, struct scsi_xfer *, + ispreq_t *, u_int8_t *, u_int8_t)); +static void isp_sbus_dmateardown __P((struct ispsoftc *, struct scsi_xfer *, + u_int32_t)); + +static struct ispmdvec mdvec = { + isp_sbus_rd_reg, + isp_sbus_wr_reg, + isp_sbus_mbxdma, + isp_sbus_dmasetup, + isp_sbus_dmateardown, + NULL, + NULL, + ISP_RISC_CODE, + ISP_CODE_LENGTH, + ISP_CODE_ORG, + 0 +}; + +struct isp_sbussoftc { + struct ispsoftc sbus_isp; + struct intrhand sbus_ih; + volatile u_char *sbus_reg; + int sbus_node; + int sbus_pri; + vm_offset_t sbus_kdma_allocs[RQUEST_QUEUE_LEN]; +}; + + +static int isp_match __P((struct device *, void *, void *)); +static void isp_sbus_attach __P((struct device *, struct device *, void *)); +struct cfattach isp_sbus_ca = { + sizeof (struct isp_sbussoftc), isp_match, isp_sbus_attach +}; + +static int +isp_match(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct cfdata *cf = vcf; + struct confargs *ca = aux; + register struct romaux *ra = &ca->ca_ra; + + if (strcmp(cf->cf_driver->cd_name, ra->ra_name) && + strcmp("SUNW,isp", ra->ra_name) && + strcmp("QLGC,isp", ra->ra_name)) { + return (0); + } + if (ca->ca_bustype == BUS_SBUS) + return (1); + ra->ra_len = NBPG; + return (probeget(ra->ra_vaddr, 1) != -1); +} + +static void +isp_sbus_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct confargs *ca = aux; + struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) self; + + if (ca->ca_ra.ra_nintr != 1) { + printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr); + return; + } + + sbc->sbus_pri = ca->ca_ra.ra_intr[0].int_pri; + printf(" pri %d\n", sbc->sbus_pri); + + if (ca->ca_ra.ra_vaddr) { + sbc->sbus_reg = (volatile u_char *) ca->ca_ra.ra_vaddr; + } else { + sbc->sbus_reg = (volatile u_char *) + mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len); + } + sbc->sbus_node = ca->ca_ra.ra_node; + + sbc->sbus_isp.isp_mdvec = &mdvec; + isp_reset(&sbc->sbus_isp); + if (sbc->sbus_isp.isp_state != ISP_RESETSTATE) { + return; + } + isp_init(&sbc->sbus_isp); + if (sbc->sbus_isp.isp_state != ISP_INITSTATE) { + isp_uninit(&sbc->sbus_isp); + return; + } + sbc->sbus_ih.ih_fun = (void *) isp_intr; + sbc->sbus_ih.ih_arg = sbc; + intr_establish(sbc->sbus_pri, &sbc->sbus_ih); + + /* + * Do Generic attach now. + */ + isp_attach(&sbc->sbus_isp); + if (sbc->sbus_isp.isp_state != ISP_RUNSTATE) { + isp_uninit(&sbc->sbus_isp); + } +} + +#define SBUS_BIU_REGS_OFF 0x00 +#define SBUS_MBOX_REGS_OFF 0x80 +#define SBUS_SXP_REGS_OFF 0x200 +#define SBUS_RISC_REGS_OFF 0x400 + +static u_int16_t +isp_sbus_rd_reg(isp, regoff) + struct ispsoftc *isp; + int regoff; +{ + struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; + + int offset; + if ((regoff & BIU_BLOCK) != 0) { + offset = SBUS_BIU_REGS_OFF; + } else if ((regoff & MBOX_BLOCK) != 0) { + offset = SBUS_MBOX_REGS_OFF; + } else if ((regoff & SXP_BLOCK) != 0) { + offset = SBUS_SXP_REGS_OFF; + } else { + offset = SBUS_RISC_REGS_OFF; + } + regoff &= 0xff; + offset += regoff; + return (*((u_int16_t *) &sbc->sbus_reg[offset])); +} + +static void +isp_sbus_wr_reg (isp, regoff, val) + struct ispsoftc *isp; + int regoff; + u_int16_t val; +{ + struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; + int offset; + + if ((regoff & BIU_BLOCK) != 0) { + offset = SBUS_BIU_REGS_OFF; + } else if ((regoff & MBOX_BLOCK) != 0) { + offset = SBUS_MBOX_REGS_OFF; + } else if ((regoff & SXP_BLOCK) != 0) { + offset = SBUS_SXP_REGS_OFF; + } else { + offset = SBUS_RISC_REGS_OFF; + } + regoff &= 0xff; + offset += regoff; + *((u_int16_t *) &sbc->sbus_reg[offset]) = val; +} + +static int +isp_sbus_mbxdma(isp) + struct ispsoftc *isp; +{ + size_t len; + + /* + * NOTE: Since most Sun machines aren't I/O coherent, + * map the mailboxes through kdvma space to force them + * to be uncached. + */ + + /* + * Allocate and map the request queue. + */ + len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); + isp->isp_rquest = (volatile caddr_t)malloc(len, M_DEVBUF, M_NOWAIT); + if (isp->isp_rquest == 0) + return (1); + isp->isp_rquest_dma = (u_int32_t)kdvma_mapin((caddr_t)isp->isp_rquest, + len, 0); + if (isp->isp_rquest_dma == 0) + return (1); + + /* + * Allocate and map the result queue. + */ + len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); + isp->isp_result = (volatile caddr_t)malloc(len, M_DEVBUF, M_NOWAIT); + if (isp->isp_result == 0) + return (1); + isp->isp_result_dma = (u_int32_t)kdvma_mapin((caddr_t)isp->isp_result, + len, 0); + if (isp->isp_result_dma == 0) + return (1); + + return (0); +} + +/* + * TODO: If kdvma_mapin fails, try using multiple smaller chunks.. + */ + +static int +isp_sbus_dmasetup(isp, xs, rq, iptrp, optr) + struct ispsoftc *isp; + struct scsi_xfer *xs; + ispreq_t *rq; + u_int8_t *iptrp; + u_int8_t optr; +{ + struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; + vm_offset_t kdvma; + int dosleep = (xs->flags & SCSI_NOSLEEP) != 0; + + if (xs->datalen == 0) { + rq->req_seg_count = 1; + rq->req_flags |= REQFLAG_DATA_IN; + return (0); + } + + if (rq->req_handle >= RQUEST_QUEUE_LEN) { + panic("%s: bad handle (%d) in isp_sbus_dmasetup\n", + isp->isp_name, rq->req_handle); + /* NOTREACHED */ + } + if (CPU_ISSUN4M) { + kdvma = (vm_offset_t) + kdvma_mapin((caddr_t)xs->data, xs->datalen, dosleep); + if (kdvma == (vm_offset_t) 0) { + return (1); + } + } else { + kdvma = (vm_offset_t) xs->data; + } + + if (sbc->sbus_kdma_allocs[rq->req_handle] != (vm_offset_t) 0) { + panic("%s: kdma handle already allocated\n", isp->isp_name); + /* NOTREACHED */ + } + sbc->sbus_kdma_allocs[rq->req_handle] = kdvma; + if (xs->flags & SCSI_DATA_IN) { + rq->req_flags |= REQFLAG_DATA_IN; + } else { + rq->req_flags |= REQFLAG_DATA_OUT; + } + rq->req_dataseg[0].ds_count = xs->datalen; + rq->req_dataseg[0].ds_base = (u_int32_t) kdvma; + rq->req_seg_count = 1; + return (0); +} + +static void +isp_sbus_dmateardown(isp, xs, handle) + struct ispsoftc *isp; + struct scsi_xfer *xs; + u_int32_t handle; +{ + struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp; + vm_offset_t kdvma; + + if (xs->flags & SCSI_DATA_IN) { + cpuinfo.cache_flush(xs->data, xs->datalen - xs->resid); + } + + if (handle >= RQUEST_QUEUE_LEN) { + panic("%s: bad handle (%d) in isp_sbus_dmateardown\n", + isp->isp_name, handle); + /* NOTREACHED */ + } + if (sbc->sbus_kdma_allocs[handle] == (vm_offset_t) 0) { + panic("%s: kdma handle not already allocated\n", isp->isp_name); + /* NOTREACHED */ + } + kdvma = sbc->sbus_kdma_allocs[handle]; + sbc->sbus_kdma_allocs[handle] = (vm_offset_t) 0; + if (CPU_ISSUN4M) { + dvma_mapout(kdvma, (vm_offset_t) xs->data, xs->datalen); + } +} diff --git a/sys/arch/sparc/dev/kbd.c b/sys/arch/sparc/dev/kbd.c index c4ae36b0aab..9bf291e0a43 100644 --- a/sys/arch/sparc/dev/kbd.c +++ b/sys/arch/sparc/dev/kbd.c @@ -1,5 +1,5 @@ -/* $OpenBSD: kbd.c,v 1.5 1996/08/11 23:34:01 downsj Exp $ */ -/* $NetBSD: kbd.c,v 1.23 1996/04/01 17:34:34 christos Exp $ */ +/* $OpenBSD: kbd.c,v 1.6 1997/08/08 08:25:16 downsj Exp $ */ +/* $NetBSD: kbd.c,v 1.27 1996/10/13 03:00:01 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -66,7 +66,7 @@ #include <machine/conf.h> #include <machine/vuid_event.h> -#include <sparc/dev/event_var.h> +#include <dev/sun/event_var.h> #include <machine/kbd.h> #include <machine/kbio.h> @@ -326,7 +326,6 @@ kbd_reset(ks) break; default: printf("Unknown keyboard type %d\n", ks->kbd_id); - break; } ks->kbd_leds = 0; @@ -720,6 +719,7 @@ kbdioctl(dev, cmd, data, flag, p) *(char *)data = k->k_state.kbd_leds; return (0); + case FIONBIO: /* we will remove this someday (soon???) */ return (0); diff --git a/sys/arch/sparc/dev/lebuffer.c b/sys/arch/sparc/dev/lebuffer.c new file mode 100644 index 00000000000..b97675194c6 --- /dev/null +++ b/sys/arch/sparc/dev/lebuffer.c @@ -0,0 +1,143 @@ +/* $OpenBSD: lebuffer.c,v 1.1 1997/08/08 08:25:16 downsj Exp $ */ +/* $NetBSD: lebuffer.c,v 1.3 1997/05/24 20:16:28 pk Exp $ */ + +/* + * Copyright (c) 1996 Paul Kranenburg. 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 Peter Galbavy. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/proc.h> +#include <sys/user.h> + +#include <sparc/autoconf.h> +#include <sparc/cpu.h> + +#include <sparc/dev/sbusvar.h> +#include <sparc/dev/lebuffervar.h> +#include <sparc/dev/dmareg.h>/*XXX*/ + +int lebufprint __P((void *, const char *)); +void lebufattach __P((struct device *, struct device *, void *)); + +struct cfattach lebuffer_ca = { + sizeof(struct lebuf_softc), matchbyname, lebufattach +}; + +struct cfdriver lebuffer_cd = { + NULL, "lebuffer", DV_DULL +}; + +int +lebufprint(aux, name) + void *aux; + const char *name; +{ + register struct confargs *ca = aux; + + if (name) + printf("[%s at %s]", ca->ca_ra.ra_name, name); + printf(" slot 0x%x offset 0x%x", ca->ca_slot, ca->ca_offset); + return (UNCONF); +} + +/* + * Attach all the sub-devices we can find + */ +void +lebufattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ +#if defined(SUN4C) || defined(SUN4M) + register struct confargs *ca = aux; + struct lebuf_softc *sc = (void *)self; + int node; + struct confargs oca; + char *name; + int sbusburst; + + if (ca->ca_ra.ra_vaddr == NULL || ca->ca_ra.ra_nvaddrs == 0) + ca->ca_ra.ra_vaddr = + mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len); + + /* + * This device's "register space" is just a buffer where the + * Lance ring-buffers can be stored. Note the buffer's location + * and size, so the `le' driver can pick them up. + */ + sc->sc_buffer = (caddr_t)ca->ca_ra.ra_vaddr; + sc->sc_bufsiz = ca->ca_ra.ra_len; + + /* + * Get transfer burst size from PROM + */ + sbusburst = ((struct sbus_softc *)parent)->sc_burst; + if (sbusburst == 0) + sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ + + sc->sc_burst = getpropint(ca->ca_ra.ra_node, "burst-sizes", -1); + if (sc->sc_burst == -1) + /* take SBus burst sizes */ + sc->sc_burst = sbusburst; + + /* Clamp at parent's burst sizes */ + sc->sc_burst &= sbusburst; + + printf("\n"); + + node = sc->sc_node = ca->ca_ra.ra_node; + + if (ca->ca_bustype == BUS_SBUS) + sbus_establish(&sc->sc_sd, &sc->sc_dev); + + /* Propagate bootpath */ + if (ca->ca_ra.ra_bp != NULL) + oca.ca_ra.ra_bp = ca->ca_ra.ra_bp + 1; + else + oca.ca_ra.ra_bp = NULL; + + /* search through children */ + for (node = firstchild(node); node; node = nextsibling(node)) { + name = getpropstring(node, "name"); + if (!romprop(&oca.ca_ra, name, node)) + continue; + + sbus_translate(parent, &oca); + oca.ca_bustype = BUS_SBUS; + (void) config_found(&sc->sc_dev, (void *)&oca, lebufprint); + } +#endif /* SUN4C || SUN4M */ +} diff --git a/sys/arch/sparc/dev/cgfourreg.h b/sys/arch/sparc/dev/lebuffervar.h index 9d53b73de6e..edd47c7b8e9 100644 --- a/sys/arch/sparc/dev/cgfourreg.h +++ b/sys/arch/sparc/dev/lebuffervar.h @@ -1,9 +1,8 @@ -/* $NetBSD: cgfourreg.h,v 1.4 1994/11/20 20:52:03 deraadt Exp $ */ +/* $OpenBSD: lebuffervar.h,v 1.1 1997/08/08 08:25:18 downsj Exp $ */ +/* $NetBSD: lebuffervar.h,v 1.2 1997/03/10 22:56:54 pk Exp $ */ /* - * Copyright (c) 1995 Theo de Raadt - * All rights reserved. - * + * Copyright (c) 1996 Paul Kranenburg. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,7 +13,7 @@ * 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 Theo de Raadt. + * This product includes software developed by Paul Kranenburg. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * @@ -30,25 +29,13 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * cgfour display registers. Much like bwtwo registers, except that - * there is a Brooktree Video DAC in there (so we also use btreg.h). - */ - -/* offsets */ -#define CG4REG_CMAP 0x200000 -#define CG4REG_OVERLAY 0x400000 -#define CG4REG_ENABLE 0x600000 -#define CG4REG_COLOUR 0x800000 -#define CG4REG_END 0xa00000 - -/* same, but for gdb */ -struct cgfour_all { - char ba_nothing[0x200000]; - struct bt_regs ba_btreg; /* Brooktree registers */ - char ba_xxx1[0x100000-sizeof(struct bt_regs)]; - char ba_pfourreg[0x100000]; - char ba_overlay[0x200000]; - char ba_enable[0x200000]; - char ba_color[0x200000]; +struct lebuf_softc { + struct device sc_dev; /* us as a device */ + struct sbusdev sc_sd; /* sbus device */ + u_int sc_rev; /* revision */ + int sc_node; /* PROM node ID */ + int sc_burst; /* DVMA burst size in effect */ + caddr_t sc_buffer; /* VA of the buffer we provide */ + int sc_bufsiz; /* Size of buffer */ + int attached; /* 1: in use by `le' device */ }; diff --git a/sys/arch/sparc/dev/ms.c b/sys/arch/sparc/dev/ms.c index 4bf14f2c9b2..1049fb12e45 100644 --- a/sys/arch/sparc/dev/ms.c +++ b/sys/arch/sparc/dev/ms.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ms.c,v 1.5 1996/08/11 23:28:12 downsj Exp $ */ -/* $NetBSD: ms.c,v 1.8 1996/04/01 17:29:52 christos Exp $ */ +/* $OpenBSD: ms.c,v 1.6 1997/08/08 08:25:19 downsj Exp $ */ +/* $NetBSD: ms.c,v 1.10 1996/09/12 01:36:18 mrg Exp $ */ /* * Copyright (c) 1992, 1993 @@ -64,7 +64,7 @@ #include <machine/kbd.h> #include <machine/conf.h> -#include <sparc/dev/event_var.h> +#include <dev/sun/event_var.h> /* * Mouse state. A Mouse Systems mouse is a fairly simple device, @@ -255,6 +255,12 @@ msopen(dev, flags, mode, p) ms_softc.ms_events.ev_io = p; ev_init(&ms_softc.ms_events); /* may cause sleep */ + if (CPU_ISSUN4) { + /* We need to set the baud rate on the mouse. */ + ms_softc.ms_mouse->t_ispeed = + ms_softc.ms_mouse->t_ospeed = 1200; + } + (*ms_softc.ms_open)(ms_softc.ms_mouse); ms_softc.ms_ready = 1; /* start accepting events */ return (0); diff --git a/sys/arch/sparc/dev/obio.c b/sys/arch/sparc/dev/obio.c index 2787aa91c01..845d97dddd3 100644 --- a/sys/arch/sparc/dev/obio.c +++ b/sys/arch/sparc/dev/obio.c @@ -1,8 +1,9 @@ -/* $NetBSD: obio.c,v 1.24 1996/05/18 12:22:49 mrg Exp $ */ +/* $OpenBSD: obio.c,v 1.7 1997/08/08 08:25:20 downsj Exp $ */ +/* $NetBSD: obio.c,v 1.37 1997/07/29 09:58:11 fair Exp $ */ /* * Copyright (c) 1993, 1994 Theo de Raadt - * Copyright (c) 1995 Paul Kranenburg + * Copyright (c) 1995, 1997 Paul Kranenburg * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,28 +51,42 @@ #include <machine/ctlreg.h> #include <sparc/sparc/asm.h> #include <sparc/sparc/vaddrs.h> +#include <sparc/sparc/cpuvar.h> #include <sparc/dev/sbusvar.h> +#include <sparc/dev/vmereg.h> + +struct vmebus_softc { + struct device sc_dev; /* base device */ + struct vmebusreg *sc_reg; /* VME control registers */ + struct vmebusvec *sc_vec; /* VME interrupt vector */ + struct rom_range *sc_range; /* ROM range property */ + int sc_nrange; +}; +struct vmebus_softc *vmebus_sc;/*XXX*/ struct bus_softc { union { struct device scu_dev; /* base device */ struct sbus_softc scu_sbus; /* obio is another sbus slot */ + struct vmebus_softc scu_vme; } bu; -#define sc_dev bu.scu_dev }; + /* autoconfiguration driver */ static int busmatch __P((struct device *, void *, void *)); static void obioattach __P((struct device *, struct device *, void *)); static void vmesattach __P((struct device *, struct device *, void *)); static void vmelattach __P((struct device *, struct device *, void *)); +static void vmeattach __P((struct device *, struct device *, void *)); int busprint __P((void *, const char *)); +int vmeprint __P((void *, const char *)); static int busattach __P((struct device *, void *, void *, int)); -void * bus_map __P((struct rom_reg *, int, int)); int obio_scan __P((struct device *, void *, void *)); int vmes_scan __P((struct device *, void *, void *)); int vmel_scan __P((struct device *, void *, void *)); +void vmebus_translate __P((struct device *, struct confargs *, int)); int vmeintr __P((void *)); struct cfattach obio_ca = { @@ -98,6 +113,14 @@ struct cfdriver vmes_cd = { NULL, "vmes", DV_DULL }; +struct cfattach vme_ca = { + sizeof(struct bus_softc), busmatch, vmeattach +}; + +struct cfdriver vme_cd = { + NULL, "vme", DV_DULL +}; + struct intrhand **vmeints; @@ -106,7 +129,7 @@ busmatch(parent, vcf, aux) struct device *parent; void *vcf, *aux; { - struct cfdata *cf = vcf; + register struct cfdata *cf = vcf; register struct confargs *ca = aux; register struct romaux *ra = &ca->ca_ra; @@ -140,6 +163,17 @@ busprint(args, obio) return (UNCONF); } +int +vmeprint(args, name) + void *args; + const char *name; +{ + register struct confargs *ca = args; + + if (name) + printf("%s at %s", ca->ca_ra.ra_name, name); + return (UNCONF); +} void obioattach(parent, self, args) @@ -154,13 +188,16 @@ obioattach(parent, self, args) register char *name; register const char *sp; const char *const *ssp; + int rlen; extern int autoconf_nzs; static const char *const special4m[] = { /* find these first */ "eeprom", "counter", +#if 0 /* Not all sun4m's have an `auxio' */ "auxio", +#endif "", /* place device to ignore here */ "interrupt", @@ -187,7 +224,7 @@ obioattach(parent, self, args) * There is only one obio bus (it is in fact one of the Sbus slots) * How about VME? */ - if (sc->sc_dev.dv_unit > 0) { + if (self->dv_unit > 0) { printf(" unsupported\n"); return; } @@ -199,8 +236,16 @@ obioattach(parent, self, args) else oca.ca_ra.ra_bp = NULL; - sc->bu.scu_sbus.sc_range = ra->ra_range; - sc->bu.scu_sbus.sc_nrange = ra->ra_nrange; + node = ra->ra_node; + rlen = getproplen(node, "ranges"); + if (rlen > 0) { + sc->bu.scu_sbus.sc_nrange = rlen / sizeof(struct rom_range); + sc->bu.scu_sbus.sc_range = + (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT); + if (sc->bu.scu_sbus.sc_range == 0) + panic("obio: PROM ranges too large: %d", rlen); + (void)getprop(node, "ranges", sc->bu.scu_sbus.sc_range, rlen); + } /* * Loop through ROM children, fixing any relative addresses @@ -218,7 +263,7 @@ obioattach(parent, self, args) sbus_translate(self, &oca); oca.ca_bustype = BUS_OBIO; - (void) config_found(&sc->sc_dev, (void *)&oca, busprint); + (void) config_found(self, (void *)&oca, busprint); } for (node = node0; node; node = nextsibling(node)) { @@ -237,7 +282,7 @@ obioattach(parent, self, args) /* Translate into parent address spaces */ sbus_translate(self, &oca); oca.ca_bustype = BUS_OBIO; - (void) config_found(&sc->sc_dev, (void *)&oca, busprint); + (void) config_found(self, (void *)&oca, busprint); } #endif } @@ -247,7 +292,8 @@ vmesattach(parent, self, args) struct device *parent, *self; void *args; { - if (CPU_ISSUN4M || self->dv_unit > 0) { + if (self->dv_unit > 0 || + (CPU_ISSUN4M && strncmp(parent->dv_xname, "vme", 3) != 0)) { printf(" unsupported\n"); return; } @@ -267,7 +313,8 @@ vmelattach(parent, self, args) struct device *parent, *self; void *args; { - if (CPU_ISSUN4M || self->dv_unit > 0) { + if (self->dv_unit > 0 || + (CPU_ISSUN4M && strncmp(parent->dv_xname, "vme", 3) != 0)) { printf(" unsupported\n"); return; } @@ -282,14 +329,116 @@ vmelattach(parent, self, args) bus_untmp(); } +void +vmeattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct vmebus_softc *sc = (struct vmebus_softc *)self; + struct confargs *ca = aux; + register struct romaux *ra = &ca->ca_ra; + int node, rlen; + struct confargs oca; + + if (!CPU_ISSUN4M || self->dv_unit > 0) { + printf(" unsupported\n"); + return; + } + + node = ra->ra_node; + + sc->sc_reg = (struct vmebusreg *) + mapdev(&ra->ra_reg[0], 0, 0, ra->ra_reg[0].rr_len); + sc->sc_vec = (struct vmebusvec *) + mapdev(&ra->ra_reg[1], 0, 0, ra->ra_reg[1].rr_len); + + /* + * Get "range" property, though we don't do anything with it yet. + */ + rlen = getproplen(node, "ranges"); + if (rlen > 0) { + sc->sc_nrange = rlen / sizeof(struct rom_range); + sc->sc_range = + (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT); + if (sc->sc_range == 0) + panic("vme: PROM ranges too large: %d", rlen); + (void)getprop(node, "ranges", sc->sc_range, rlen); + } + + vmebus_sc = sc; + printf(": version 0x%x\n", + sc->sc_reg->vmebus_cr & VMEBUS_CR_IMPL); + + if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "vme") == 0) + oca.ca_ra.ra_bp = ra->ra_bp + 1; + else + oca.ca_ra.ra_bp = NULL; + + oca.ca_ra.ra_name = "vmes"; + oca.ca_bustype = BUS_MAIN; + (void)config_found(self, (void *)&oca, vmeprint); + + oca.ca_ra.ra_name = "vmel"; + oca.ca_bustype = BUS_MAIN; + (void)config_found(self, (void *)&oca, vmeprint); +} + +void +vmebus_translate(dev, ca, bustype) + struct device *dev; + struct confargs *ca; + int bustype; +{ + struct vmebus_softc *sc = (struct vmebus_softc *)dev; + register int j; + int cspace; + + if (sc->sc_nrange == 0) + panic("vmebus: no ranges"); + + /* + * Find VMEbus modifier based on address space. + * XXX - should not be encoded in `ra_paddr' + */ + if (((u_long)ca->ca_ra.ra_paddr & 0xffff0000) == 0xffff0000) + cspace = VMEMOD_A16_D_S; + else if (((u_long)ca->ca_ra.ra_paddr & 0xff000000) == 0xff000000) + cspace = VMEMOD_A24_D_S; + else + cspace = VMEMOD_A32_D_S; + + cspace |= (bustype == BUS_VME32) ? VMEMOD_D32 : 0; + + /* Translate into parent address spaces */ + for (j = 0; j < sc->sc_nrange; j++) { + if (sc->sc_range[j].cspace == cspace) { +#if notyet + (int)ca->ca_ra.ra_paddr += + sc->sc_range[j].poffset; +#endif + (int)ca->ca_ra.ra_iospace = + sc->sc_range[j].pspace; + break; + } + } +} + +int bt2pmt[] = { + PMAP_OBIO, + PMAP_OBIO, + PMAP_VME16, + PMAP_VME32, + PMAP_OBIO +}; + int -busattach(parent, child, args, bustype) +busattach(parent, vcf, args, bustype) struct device *parent; - void *args, *child; + void *vcf, *args; int bustype; { -#if defined(SUN4) - struct cfdata *cf = child; +#if defined(SUN4) || defined(SUN4M) + register struct cfdata *cf = vcf; register struct confargs *ca = args; struct confargs oca; caddr_t tmp; @@ -309,24 +458,24 @@ busattach(parent, child, args, bustype) * XXX: We also assume that 4/[23]00 obio addresses * must be 0xZYYYYYYY, where (Z != 0) */ - if (cpumod == SUN4_100 && (cf->cf_loc[0] & 0xf0000000)) + if (cpuinfo.cpu_type == CPUTYP_4_100 && + (cf->cf_loc[0] & 0xf0000000)) return 0; - if (cpumod != SUN4_100 && !(cf->cf_loc[0] & 0xf0000000)) + if (cpuinfo.cpu_type != CPUTYP_4_100 && + !(cf->cf_loc[0] & 0xf0000000)) return 0; } - if (parent->dv_cfdata->cf_driver->cd_indirect) { - printf(" indirect devices not supported\n"); - return 0; - } - - oca.ca_ra.ra_iospace = -1; oca.ca_ra.ra_paddr = (void *)cf->cf_loc[0]; oca.ca_ra.ra_len = 0; oca.ca_ra.ra_nreg = 1; + if (CPU_ISSUN4M) + vmebus_translate(parent->dv_parent, &oca, bustype); + else + oca.ca_ra.ra_iospace = bt2pmt[bustype]; + if (oca.ca_ra.ra_paddr) - tmp = (caddr_t)bus_tmp(oca.ca_ra.ra_paddr, - bustype); + tmp = (caddr_t)mapdev(oca.ca_ra.ra_reg, TMPMAP_VA, 0, NBPG); else tmp = NULL; oca.ca_ra.ra_vaddr = tmp; @@ -364,8 +513,7 @@ busattach(parent, child, args, bustype) */ if (oca.ca_ra.ra_len) oca.ca_ra.ra_vaddr = - bus_map(oca.ca_ra.ra_reg, - oca.ca_ra.ra_len, oca.ca_bustype); + bus_map(oca.ca_ra.ra_reg, oca.ca_ra.ra_len); config_attach(parent, cf, &oca, busprint); return 1; @@ -421,18 +569,19 @@ int vmeintr(arg) void *arg; { - int level = (int)arg, vec; + int pil = (int)arg, level, vec; struct intrhand *ih; int i = 0; -#ifdef DIAGNOSTIC - if (!CPU_ISSUN4) { + level = (pil_to_vme[pil] << 1) | 1; + + if (CPU_ISSUN4) { + vec = ldcontrolb((caddr_t)(AC_VMEINTVEC | level)); + } else if (CPU_ISSUN4M) { + vec = vmebus_sc->sc_vec->vmebusvec[level]; + } else panic("vme: spurious interrupt"); - } -#endif - vec = ldcontrolb((caddr_t) - (AC_VMEINTVEC | (pil_to_vme[level] << 1) | 1)); if (vec == -1) { printf("vme: spurious interrupt\n"); return 0; @@ -451,13 +600,11 @@ vmeintr_establish(vec, level, ih) { struct intrhand *ihs; - if (!CPU_ISSUN4) { - panic("vmeintr_establish: not supported on cpu-type %d", - cputyp); - } + if (vmeints == NULL) + panic("vmeintr_establish: interrupt vector not allocated"); if (vec == -1) - panic("vmeintr_establish: uninitialized vec\n"); + panic("vmeintr_establish: uninitialized vec"); if (vmeints[vec] == NULL) vmeints[vec] = ih; @@ -489,28 +636,16 @@ vmeintr_establish(vec, level, ih) * Else, create a new mapping. */ void * -bus_map(pa, len, bustype) +bus_map(pa, len) struct rom_reg *pa; int len; - int bustype; { - u_long pf = (u_long)(pa->rr_paddr) >> PGSHIFT; - u_long va, pte; - int pgtype = -1; - - switch (bt2pmt[bustype]) { - case PMAP_OBIO: - pgtype = PG_OBIO; - break; - case PMAP_VME32: - pgtype = PG_VME32; - break; - case PMAP_VME16: - pgtype = PG_VME16; - break; - } - if (len <= NBPG) { + if (CPU_ISSUN4 && len <= NBPG) { + u_long pf = (u_long)(pa->rr_paddr) >> PGSHIFT; + int pgtype = PMAP_T2PTE_4(pa->rr_iospace); + u_long va, pte; + for (va = OLDMON_STARTVADDR; va < OLDMON_ENDVADDR; va += NBPG) { pte = getpte(va); if ((pte & PG_V) != 0 && (pte & PG_TYPE) == pgtype && @@ -520,21 +655,8 @@ bus_map(pa, len, bustype) /* note: preserve page offset */ } } - return mapiodev(pa, 0, len, bustype); -} - -void * -bus_tmp(pa, bustype) - void *pa; - int bustype; -{ - vm_offset_t addr = (vm_offset_t)pa & ~PGOFSET; - int pmtype = bt2pmt[bustype]; - pmap_enter(pmap_kernel(), TMPMAP_VA, - addr | pmtype | PMAP_NC, - VM_PROT_READ | VM_PROT_WRITE, 1); - return ((void *)(TMPMAP_VA | ((u_long) pa & PGOFSET)) ); + return mapiodev(pa, 0, len); } void diff --git a/sys/arch/sparc/dev/pfour.c b/sys/arch/sparc/dev/pfour.c index 3ed22d7df5c..c903754515a 100644 --- a/sys/arch/sparc/dev/pfour.c +++ b/sys/arch/sparc/dev/pfour.c @@ -1,4 +1,4 @@ -/* $Id: pfour.c,v 1.5 1995/12/15 13:56:26 deraadt Exp $ */ +/* $OpenBSD: pfour.c,v 1.6 1997/08/08 08:25:20 downsj Exp $ */ /* * Copyright (c) 1995 Theo de Raadt diff --git a/sys/arch/sparc/dev/pfourreg.h b/sys/arch/sparc/dev/pfourreg.h index 8ec422c2019..a0ef7094c05 100644 --- a/sys/arch/sparc/dev/pfourreg.h +++ b/sys/arch/sparc/dev/pfourreg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: pfourreg.h,v 1.4 1997/08/08 08:25:21 downsj Exp $ */ /* $NetBSD: pfourreg.h,v 1.1 1996/02/27 22:09:36 thorpej Exp $ */ /* diff --git a/sys/arch/sparc/dev/power.c b/sys/arch/sparc/dev/power.c index d083500333f..0255c25c059 100644 --- a/sys/arch/sparc/dev/power.c +++ b/sys/arch/sparc/dev/power.c @@ -1,4 +1,4 @@ -/* $OpenBSD: power.c,v 1.3 1997/06/22 22:45:34 downsj Exp $ */ +/* $OpenBSD: power.c,v 1.4 1997/08/08 08:25:22 downsj Exp $ */ /* $NetBSD: power.c,v 1.2 1996/05/16 15:56:56 abrown Exp $ */ /* @@ -91,7 +91,7 @@ powerattach(parent, self, aux) struct confargs *ca = aux; struct romaux *ra = &ca->ca_ra; - power_reg = mapdev(ra->ra_reg, 0, 0, sizeof(long), ca->ca_bustype); + power_reg = mapdev(ra->ra_reg, 0, 0, sizeof(long)); power_attached = 1; diff --git a/sys/arch/sparc/dev/rcons_font.h b/sys/arch/sparc/dev/rcons_font.h index 3cbc847ea53..292ce909ba0 100644 --- a/sys/arch/sparc/dev/rcons_font.h +++ b/sys/arch/sparc/dev/rcons_font.h @@ -1,3 +1,4 @@ +/* $OpenBSD: rcons_font.h,v 1.4 1997/08/08 08:25:25 downsj Exp $ */ /* $NetBSD: rcons_font.h,v 1.3 1995/11/29 22:03:53 pk Exp $ */ /* diff --git a/sys/arch/sparc/dev/sbus.c b/sys/arch/sparc/dev/sbus.c index 0f7ceff3bbf..aee7de7fbf8 100644 --- a/sys/arch/sparc/dev/sbus.c +++ b/sys/arch/sparc/dev/sbus.c @@ -1,4 +1,5 @@ -/* $NetBSD: sbus.c,v 1.10 1996/04/22 02:35:03 abrown Exp $ */ +/* $OpenBSD: sbus.c,v 1.5 1997/08/08 08:25:27 downsj Exp $ */ +/* $NetBSD: sbus.c,v 1.17 1997/06/01 22:10:39 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -49,8 +50,10 @@ */ #include <sys/param.h> +#include <sys/malloc.h> #include <sys/systm.h> #include <sys/device.h> +#include <vm/vm.h> #include <machine/autoconf.h> @@ -96,7 +99,7 @@ sbus_match(parent, vcf, aux) struct device *parent; void *vcf, *aux; { - struct cfdata *cf = vcf; + register struct cfdata *cf = vcf; register struct confargs *ca = aux; register struct romaux *ra = &ca->ca_ra; @@ -121,6 +124,7 @@ sbus_attach(parent, self, aux) register int node; register char *name; struct confargs oca; + int rlen; /* * XXX there is only one Sbus, for now -- do not know how to @@ -149,8 +153,15 @@ sbus_attach(parent, self, aux) else oca.ca_ra.ra_bp = NULL; - sc->sc_range = ra->ra_range; - sc->sc_nrange = ra->ra_nrange; + rlen = getproplen(node, "ranges"); + if (rlen > 0) { + sc->sc_nrange = rlen / sizeof(struct rom_range); + sc->sc_range = + (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT); + if (sc->sc_range == 0) + panic("sbus: PROM ranges too large: %d", rlen); + (void)getprop(node, "ranges", sc->sc_range, rlen); + } /* * Loop through ROM children, fixing any relative addresses @@ -183,15 +194,19 @@ sbus_translate(dev, ca) ca->ca_slot = SBUS_ABS_TO_SLOT(base); ca->ca_offset = SBUS_ABS_TO_OFFSET(base); } else { + if (!CPU_ISSUN4C) + panic("relative sbus addressing not supported"); ca->ca_slot = slot = ca->ca_ra.ra_iospace; ca->ca_offset = base; - ca->ca_ra.ra_paddr = - (void *)SBUS_ADDR(slot, base); + ca->ca_ra.ra_paddr = (void *)SBUS_ADDR(slot, base); + ca->ca_ra.ra_iospace = PMAP_OBIO; + /* Fix any remaining register banks */ for (i = 1; i < ca->ca_ra.ra_nreg; i++) { base = (int)ca->ca_ra.ra_reg[i].rr_paddr; ca->ca_ra.ra_reg[i].rr_paddr = (void *)SBUS_ADDR(slot, base); + ca->ca_ra.ra_reg[i].rr_iospace = PMAP_OBIO; } } @@ -237,12 +252,13 @@ sbus_establish(sd, dev) */ for (curdev = dev->dv_parent; ; curdev = curdev->dv_parent) { if (!curdev || !curdev->dv_xname) - panic("sbus_establish: can't find sbus parent for %s", - (sd->sd_dev->dv_xname ? sd->sd_dev->dv_xname : - "<unknown>")); + panic("sbus_establish: can't find sbus parent for %s", + sd->sd_dev->dv_xname + ? sd->sd_dev->dv_xname + : "<unknown>" ); if (strncmp(curdev->dv_xname, "sbus", 4) == 0) - break; + break; } sc = (struct sbus_softc *) curdev; diff --git a/sys/arch/sparc/dev/sbusreg.h b/sys/arch/sparc/dev/sbusreg.h index 74c0b270292..3455f5eb366 100644 --- a/sys/arch/sparc/dev/sbusreg.h +++ b/sys/arch/sparc/dev/sbusreg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: sbusreg.h,v 1.2 1997/08/08 08:25:27 downsj Exp $ */ /* $NetBSD: sbusreg.h,v 1.2 1994/11/20 20:52:26 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/dev/sbusvar.h b/sys/arch/sparc/dev/sbusvar.h index 72fa1025523..21fd61967c2 100644 --- a/sys/arch/sparc/dev/sbusvar.h +++ b/sys/arch/sparc/dev/sbusvar.h @@ -1,3 +1,4 @@ +/* $OpenBSD: sbusvar.h,v 1.4 1997/08/08 08:25:28 downsj Exp $ */ /* $NetBSD: sbusvar.h,v 1.4 1996/04/22 02:35:05 abrown Exp $ */ /* diff --git a/sys/arch/sparc/dev/si.c b/sys/arch/sparc/dev/si.c index 5aa1f4f4946..a96caafb133 100644 --- a/sys/arch/sparc/dev/si.c +++ b/sys/arch/sparc/dev/si.c @@ -1,11 +1,13 @@ -/* $NetBSD: si.c,v 1.24 1996/05/13 01:53:45 thorpej Exp $ */ +/* $OpenBSD: si.c,v 1.10 1997/08/08 08:25:29 downsj Exp $ */ +/* $NetBSD: si.c,v 1.37 1997/07/29 09:58:13 fair Exp $ */ -/* - * Copyright (c) 1995 Jason R. Thorpe - * Copyright (c) 1995 David Jones, Gordon W. Ross - * Copyright (c) 1994 Adam Glass +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. * All rights reserved. * + * This code is derived from software contributed to The NetBSD Foundation + * by Adam Glass, David Jones, Gordon W. Ross, and Jason R. Thorpe. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,23 +16,25 @@ * 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 authors 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 + * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by - * Adam Glass, David Jones, Gordon Ross, and Jason R. Thorpe + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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 SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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. */ /* @@ -108,6 +112,7 @@ #include <machine/pmap.h> #include <sparc/sparc/vaddrs.h> +#include <sparc/sparc/cpuvar.h> #ifndef DDB #define Debugger() @@ -190,7 +195,7 @@ struct si_softc { #define SI_DO_RESELECT 0x04 /* Allow disconnect/reselect */ #define SI_OPTIONS_MASK (SI_ENABLE_DMA|SI_DMA_INTR|SI_DO_RESELECT) #define SI_OPTIONS_BITS "\10\3RESELECT\2DMA_INTR\1DMA" -int si_options = 0; /* XXX SI_ENABLE_DMA when dma works */ +int si_options = SI_ENABLE_DMA; int sw_options = SI_ENABLE_DMA; /* How long to wait for DMA before declaring an error. */ @@ -201,7 +206,6 @@ static void si_attach __P((struct device *, struct device *, void *)); static int si_intr __P((void *)); static void si_reset_adapter __P((struct ncr5380_softc *)); static void si_minphys __P((struct buf *)); -static int si_print __P((void *, const char *)); void si_dma_alloc __P((struct ncr5380_softc *)); void si_dma_free __P((struct ncr5380_softc *)); @@ -259,22 +263,12 @@ struct cfdriver sw_cd = { }; static int -si_print(aux, name) - void *aux; - const char *name; -{ - if (name != NULL) - printf("%s: scsibus ", name); - return UNCONF; -} - -static int -si_match(parent, vcf, args) +si_match(parent, vcf, aux) struct device *parent; - void *vcf, *args; + void *vcf, *aux; { - struct cfdata *cf = vcf; - struct confargs *ca = args; + struct cfdata *cf = vcf; + struct confargs *ca = aux; struct romaux *ra = &ca->ca_ra; /* Are we looking for the right thing? */ @@ -296,13 +290,15 @@ si_match(parent, vcf, args) switch (ca->ca_bustype) { case BUS_VME16: /* AFAIK, the `si' can only exist on the vmes. */ - if (strcmp(ra->ra_name, "si") || cpumod == SUN4_100) + if (strcmp(ra->ra_name, "si") || + cpuinfo.cpu_type == CPUTYP_4_100) return (0); break; case BUS_OBIO: /* AFAIK, an `sw' can only exist on the obio. */ - if (strcmp(ra->ra_name, "sw") || cpumod != SUN4_100) + if (strcmp(ra->ra_name, "sw") || + cpuinfo.cpu_type != CPUTYP_4_100) return (0); break; @@ -341,17 +337,20 @@ si_attach(parent, self, args) struct bootpath *bp; int i; - /* Pull in the options flags. */ - if (ca->ca_bustype == BUS_OBIO) - sc->sc_options = sw_options; + /* + * Pull in the options flags. Allow the user to completely + * override the default values. + */ + if ((ncr_sc->sc_dev.dv_cfdata->cf_flags & SI_OPTIONS_MASK) != 0) + sc->sc_options = + (ncr_sc->sc_dev.dv_cfdata->cf_flags & SI_OPTIONS_MASK); else - sc->sc_options = si_options; - sc->sc_options |= - (ncr_sc->sc_dev.dv_cfdata->cf_flags & SI_OPTIONS_MASK); + sc->sc_options = + (ca->ca_bustype == BUS_OBIO) ? sw_options : si_options; /* Map the controller registers. */ - regs = (struct si_regs *)mapiodev(ra->ra_reg, 0, - sizeof(struct si_regs), ca->ca_bustype); + regs = (struct si_regs *) + mapiodev(ra->ra_reg, 0, sizeof(struct si_regs)); /* * Fill in the prototype scsi_link. @@ -413,7 +412,7 @@ si_attach(parent, self, args) } ncr_sc->sc_flags = 0; - if (sc->sc_options & SI_DO_RESELECT) + if ((sc->sc_options & SI_DO_RESELECT) == 0) ncr_sc->sc_flags |= NCR5380_PERMIT_RESELECT; if ((sc->sc_options & SI_DMA_INTR) == 0) ncr_sc->sc_flags |= NCR5380_FORCE_POLLING; @@ -494,7 +493,7 @@ si_attach(parent, self, args) bootpath_store(1, bp + 1); /* Configure sub-devices */ - config_found(self, &(ncr_sc->sc_link), si_print); + config_found(self, &(ncr_sc->sc_link), scsiprint); bootpath_store(1, NULL); } @@ -505,7 +504,7 @@ si_minphys(struct buf *bp) if (bp->b_bcount > MAX_DMA_LEN) { #ifdef DEBUG if (si_debug) { - printf("si_minphys len = %x.\n", MAX_DMA_LEN); + printf("si_minphys len = 0x%x.\n", MAX_DMA_LEN); Debugger(); } #endif @@ -658,21 +657,6 @@ si_dma_alloc(ncr_sc) if (xlen < MIN_DMA_LEN) panic("si_dma_alloc: xlen=0x%x\n", xlen); - /* - * XXX SUN4 doesn't have this limitation? - * Never attempt single transfers of more than 63k, because - * our count register may be only 16 bits (an OBIO adapter). - * This should never happen since already bounded by minphys(). - * XXX - Should just segment these... - */ - if (xlen > MAX_DMA_LEN) { - printf("si_dma_alloc: excessive xlen=0x%x\n", xlen); -#ifdef DEBUG - Debugger(); -#endif - ncr_sc->sc_datalen = xlen = MAX_DMA_LEN; - } - /* Find free DMA handle. Guaranteed to find one since we have as many DMA handles as the driver has processes. */ for (i = 0; i < SCI_OPENINGS; i++) { @@ -701,7 +685,7 @@ found: dh->dh_dvma = (long)kdvma_mapin((caddr_t)addr, xlen, 0); if (dh->dh_dvma == 0) { /* Can't remap segment */ - printf("si_dma_alloc: can't remap %p/%x, doing PIO\n", + printf("si_dma_alloc: can't remap %p/0x%x, doing PIO\n", dh->dh_addr, dh->dh_maplen); dh->dh_flags = 0; return; diff --git a/sys/arch/sparc/dev/sireg.h b/sys/arch/sparc/dev/sireg.h index 8f2ab6e40e3..d17fc344b74 100644 --- a/sys/arch/sparc/dev/sireg.h +++ b/sys/arch/sparc/dev/sireg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: sireg.h,v 1.3 1997/08/08 08:25:30 downsj Exp $ */ /* $NetBSD: sireg.h,v 1.3 1996/01/01 22:40:58 thorpej Exp $ */ /* diff --git a/sys/arch/sparc/dev/tcx.c b/sys/arch/sparc/dev/tcx.c new file mode 100644 index 00000000000..608fb4e64c0 --- /dev/null +++ b/sys/arch/sparc/dev/tcx.c @@ -0,0 +1,496 @@ +/* $OpenBSD: tcx.c,v 1.1 1997/08/08 08:25:31 downsj Exp $ */ +/* $NetBSD: tcx.c,v 1.8 1997/07/29 09:58:14 fair Exp $ */ + +/* + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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. + */ + +/* + * color display (TCX) driver. + * + * Does not handle interrupts, even though they can occur. + * + * XXX should defer colormap updates to vertical retrace interrupts + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <machine/fbio.h> +#include <sys/ioctl.h> +#include <sys/malloc.h> +#include <sys/mman.h> +#include <sys/tty.h> +#include <sys/conf.h> + +#ifdef DEBUG +#include <sys/proc.h> +#include <sys/syslog.h> +#endif + +#include <vm/vm.h> + +#include <machine/autoconf.h> +#include <machine/pmap.h> +#include <machine/fbvar.h> +#include <machine/cpu.h> +#include <machine/conf.h> + +#include <sparc/dev/btreg.h> +#include <sparc/dev/btvar.h> +#include <sparc/dev/tcxreg.h> +#include <sparc/dev/sbusvar.h> + +#if 0 +union cursor_cmap { /* colormap, like bt_cmap, but tiny */ + u_char cm_map[2][3]; /* 2 R/G/B entries */ + u_int cm_chip[2]; /* 2 chip equivalents */ +}; + +struct tcx_cursor { /* tcx hardware cursor status */ + short cc_enable; /* cursor is enabled */ + struct fbcurpos cc_pos; /* position */ + struct fbcurpos cc_hot; /* hot-spot */ + struct fbcurpos cc_size; /* size of mask & image fields */ + u_int cc_bits[2][32]; /* space for mask & image bits */ + union cursor_cmap cc_color; /* cursor colormap */ +}; +#endif + +/* per-display variables */ +struct tcx_softc { + struct device sc_dev; /* base device */ + struct sbusdev sc_sd; /* sbus device */ + struct fbdevice sc_fb; /* frame buffer device */ + struct rom_reg sc_physadr[TCX_NREG]; /* phys addr of h/w */ + int sc_bustype; /* type of bus we live on */ + volatile struct bt_regs *sc_bt; /* Brooktree registers */ + volatile struct tcx_thc *sc_thc; /* THC registers */ + short sc_blanked; /* true if blanked */ + union bt_cmap sc_cmap; /* Brooktree color map */ +}; + +/* autoconfiguration driver */ +static void tcxattach __P((struct device *, struct device *, void *)); +static int tcxmatch __P((struct device *, void *, void *)); +static void tcx_unblank __P((struct device *)); + +/* cdevsw prototypes */ +cdev_decl(tcx); + +struct cfattach tcx_ca = { + sizeof(struct tcx_softc), tcxmatch, tcxattach +}; + +struct cfdriver tcx_cd = { + NULL, "tcx", DV_DULL +}; + +/* frame buffer generic driver */ +static struct fbdriver tcx_fbdriver = { + tcx_unblank, tcxopen, tcxclose, tcxioctl, tcxmmap +}; + +extern int fbnode; + +static void tcx_reset __P((struct tcx_softc *)); +static void tcx_loadcmap __P((struct tcx_softc *, int, int)); + +#define OBPNAME "SUNW,tcx" +/* + * Match a tcx. + */ +int +tcxmatch(parent, vcf, aux) + struct device *parent; + void *vcf, *aux; +{ + struct cfdata *cf = vcf; + struct confargs *ca = aux; + struct romaux *ra = &ca->ca_ra; + + if (strcmp(ra->ra_name, OBPNAME)) + return (0); + + /* + * Mask out invalid flags from the user. + */ + cf->cf_flags &= FB_USERMASK; + + if (ca->ca_bustype == BUS_SBUS) + return (1); + + return (0); +} + +/* + * Attach a display. + */ +void +tcxattach(parent, self, args) + struct device *parent, *self; + void *args; +{ + register struct tcx_softc *sc = (struct tcx_softc *)self; + register struct confargs *ca = args; + register int node = 0, ramsize, i; + register volatile struct bt_regs *bt; + struct fbdevice *fb = &sc->sc_fb; + int isconsole = 0, sbus = 1; + extern struct tty *fbconstty; + + fb->fb_driver = &tcx_fbdriver; + fb->fb_device = &sc->sc_dev; + fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags; + + /* + * XXX - should be set to FBTYPE_TCX. + * XXX For CG3 emulation to work in current (96/6) X11 servers, + * XXX `fbtype' must point to an "unregocnised" entry. + */ + fb->fb_type.fb_type = FBTYPE_RESERVED3; + + if (ca->ca_ra.ra_nreg != TCX_NREG) + panic("tcx: oops"); + + /* Copy register address spaces */ + for (i = 0; i < TCX_NREG; i++) + sc->sc_physadr[i] = ca->ca_ra.ra_reg[i]; + + /* XXX - fix THC and TEC offsets */ + sc->sc_physadr[TCX_REG_TEC].rr_paddr += 0x1000; + sc->sc_physadr[TCX_REG_THC].rr_paddr += 0x1000; + + sc->sc_bt = bt = (volatile struct bt_regs *) + mapiodev(&ca->ca_ra.ra_reg[TCX_REG_CMAP], 0, sizeof *sc->sc_bt); + sc->sc_thc = (volatile struct tcx_thc *) + mapiodev(&ca->ca_ra.ra_reg[TCX_REG_THC], 0, sizeof *sc->sc_thc); + + switch (ca->ca_bustype) { + case BUS_SBUS: + node = ca->ca_ra.ra_node; + break; + + case BUS_OBIO: + default: + printf("TCX on bus 0x%x?\n", ca->ca_bustype); + return; + } + + fb->fb_type.fb_depth = node_has_property(node, "tcx-24-bit") + ? 24 + : (node_has_property(node, "tcx-8-bit") + ? 8 + : 8); + + fb_setsize(fb, fb->fb_type.fb_depth, 1152, 900, + node, ca->ca_bustype); + + ramsize = fb->fb_type.fb_height * fb->fb_linebytes; + fb->fb_type.fb_cmsize = 256; + fb->fb_type.fb_size = ramsize; + printf(": %s, %d x %d", OBPNAME, + fb->fb_type.fb_width, + fb->fb_type.fb_height); + + isconsole = node == fbnode && fbconstty != NULL; + + printf(", id %d, rev %d, sense %d", + (sc->sc_thc->thc_config & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT, + (sc->sc_thc->thc_config & THC_CFG_REV) >> THC_CFG_REV_SHIFT, + (sc->sc_thc->thc_config & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT + ); + + /* reset cursor & frame buffer controls */ + tcx_reset(sc); + + /* grab initial (current) color map (DOES THIS WORK?) */ + bt->bt_addr = 0; + for (i = 0; i < 256 * 3; i++) + ((char *)&sc->sc_cmap)[i] = bt->bt_cmap >> 24; + + /* enable video */ + sc->sc_thc->thc_hcmisc |= THC_MISC_VIDEN; + + if (isconsole) { + printf(" (console)\n"); + } else + printf("\n"); + + if (sbus) + sbus_establish(&sc->sc_sd, &sc->sc_dev); + if (node == fbnode) + fb_attach(&sc->sc_fb, isconsole); +} + +int +tcxopen(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; +{ + int unit = minor(dev); + + if (unit >= tcx_cd.cd_ndevs || tcx_cd.cd_devs[unit] == NULL) + return (ENXIO); + return (0); +} + +int +tcxclose(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; +{ + struct tcx_softc *sc = tcx_cd.cd_devs[minor(dev)]; + + tcx_reset(sc); + return (0); +} + +int +tcxioctl(dev, cmd, data, flags, p) + dev_t dev; + u_long cmd; + register caddr_t data; + int flags; + struct proc *p; +{ + register struct tcx_softc *sc = tcx_cd.cd_devs[minor(dev)]; + int error; + + switch (cmd) { + + case FBIOGTYPE: + *(struct fbtype *)data = sc->sc_fb.fb_type; + break; + + case FBIOGATTR: +#define fba ((struct fbgattr *)data) + fba->real_type = sc->sc_fb.fb_type.fb_type; + fba->owner = 0; /* XXX ??? */ + fba->fbtype = sc->sc_fb.fb_type; + fba->sattr.flags = 0; + fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; + fba->sattr.dev_specific[0] = -1; + fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; + fba->emu_types[1] = FBTYPE_SUN3COLOR; + fba->emu_types[2] = -1; +#undef fba + break; + + case FBIOGETCMAP: + return (bt_getcmap((struct fbcmap *)data, &sc->sc_cmap, 256)); + + case FBIOPUTCMAP: + /* copy to software map */ +#define p ((struct fbcmap *)data) + error = bt_putcmap(p, &sc->sc_cmap, 256); + if (error) + return (error); + /* now blast them into the chip */ + /* XXX should use retrace interrupt */ + tcx_loadcmap(sc, p->index, p->count); +#undef p + break; + + case FBIOGVIDEO: + *(int *)data = sc->sc_blanked; + break; + + case FBIOSVIDEO: + if (*(int *)data) + tcx_unblank(&sc->sc_dev); + else if (!sc->sc_blanked) { + sc->sc_blanked = 1; + sc->sc_thc->thc_hcmisc &= ~THC_MISC_VIDEN; + /* Put monitor in `power-saving mode' */ + sc->sc_thc->thc_hcmisc |= THC_MISC_VSYNC_DISABLE; + sc->sc_thc->thc_hcmisc |= THC_MISC_HSYNC_DISABLE; + } + break; + + default: +#ifdef DEBUG + log(LOG_NOTICE, "tcxioctl(0x%lx) (%s[%d])\n", cmd, + p->p_comm, p->p_pid); +#endif + return (ENOTTY); + } + return (0); +} + +/* + * Clean up hardware state (e.g., after bootup or after X crashes). + */ +static void +tcx_reset(sc) + register struct tcx_softc *sc; +{ + register volatile struct bt_regs *bt; + + /* Enable cursor in Brooktree DAC. */ + bt = sc->sc_bt; + bt->bt_addr = 0x06 << 24; + bt->bt_ctrl |= 0x03 << 24; +} + +/* + * Load a subset of the current (new) colormap into the color DAC. + */ +static void +tcx_loadcmap(sc, start, ncolors) + register struct tcx_softc *sc; + register int start, ncolors; +{ + register volatile struct bt_regs *bt; + register u_int *ip, i; + register int count; + + ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ + count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; + bt = sc->sc_bt; + bt->bt_addr = BT_D4M4(start) << 24; + while (--count >= 0) { + i = *ip++; + /* hardware that makes one want to pound boards with hammers */ + bt->bt_cmap = i; + bt->bt_cmap = i << 8; + bt->bt_cmap = i << 16; + bt->bt_cmap = i << 24; + } +} + +static void +tcx_unblank(dev) + struct device *dev; +{ + struct tcx_softc *sc = (struct tcx_softc *)dev; + + if (sc->sc_blanked) { + sc->sc_blanked = 0; + sc->sc_thc->thc_hcmisc &= ~THC_MISC_VSYNC_DISABLE; + sc->sc_thc->thc_hcmisc &= ~THC_MISC_HSYNC_DISABLE; + sc->sc_thc->thc_hcmisc |= THC_MISC_VIDEN; + } +} + +/* + * Base addresses at which users can mmap() the various pieces of a tcx. + */ +#define TCX_USER_RAM 0x00000000 +#define TCX_USER_RAM24 0x01000000 +#define TCX_USER_RAM_COMPAT 0x04000000 /* cg3 emulation */ +#define TCX_USER_STIP 0x10000000 +#define TCX_USER_BLIT 0x20000000 +#define TCX_USER_RDFB32 0x28000000 +#define TCX_USER_RSTIP 0x30000000 +#define TCX_USER_RBLIT 0x38000000 +#define TCX_USER_TEC 0x70001000 +#define TCX_USER_BTREGS 0x70002000 +#define TCX_USER_THC 0x70004000 +#define TCX_USER_DHC 0x70008000 +#define TCX_USER_ALT 0x7000a000 +#define TCX_USER_UART 0x7000c000 +#define TCX_USER_VRT 0x7000e000 +#define TCX_USER_ROM 0x70010000 + +struct mmo { + u_int mo_uaddr; /* user (virtual) address */ + u_int mo_size; /* size, or 0 for video ram size */ + u_int mo_bank; /* register bank number */ +}; + +/* + * Return the address that would map the given device at the given + * offset, allowing for the given protection, or return -1 for error. + * + * XXX needs testing against `demanding' applications (e.g., aviator) + */ +int +tcxmmap(dev, off, prot) + dev_t dev; + int off, prot; +{ + register struct tcx_softc *sc = tcx_cd.cd_devs[minor(dev)]; + register struct mmo *mo; + register u_int u, sz; + static struct mmo mmo[] = { + { TCX_USER_RAM, 0, TCX_REG_DFB8 }, + { TCX_USER_RAM24, 0, TCX_REG_DFB24 }, + { TCX_USER_RAM_COMPAT, 0, TCX_REG_DFB8 }, + + { TCX_USER_STIP, 1, TCX_REG_STIP }, + { TCX_USER_BLIT, 1, TCX_REG_BLIT }, + { TCX_USER_RDFB32, 1, TCX_REG_RDFB32 }, + { TCX_USER_RSTIP, 1, TCX_REG_RSTIP }, + { TCX_USER_RBLIT, 1, TCX_REG_RBLIT }, + { TCX_USER_TEC, 1, TCX_REG_TEC }, + { TCX_USER_BTREGS, 8192 /* XXX */, TCX_REG_CMAP }, + { TCX_USER_THC, sizeof(struct tcx_thc), TCX_REG_THC }, + { TCX_USER_DHC, 1, TCX_REG_DHC }, + { TCX_USER_ALT, 1, TCX_REG_ALT }, + { TCX_USER_ROM, 65536, TCX_REG_ROM }, + }; +#define NMMO (sizeof mmo / sizeof *mmo) + + if (off & PGOFSET) + panic("tcxmmap"); + + /* + * Entries with size 0 map video RAM (i.e., the size in fb data). + * + * Since we work in pages, the fact that the map offset table's + * sizes are sometimes bizarre (e.g., 1) is effectively ignored: + * one byte is as good as one page. + */ + for (mo = mmo; mo < &mmo[NMMO]; mo++) { + if ((u_int)off < mo->mo_uaddr) + continue; + u = off - mo->mo_uaddr; + sz = mo->mo_size ? mo->mo_size : sc->sc_fb.fb_type.fb_size; + if (u < sz) + return (REG2PHYS(&sc->sc_physadr[mo->mo_bank], u) | + PMAP_NC); + } +#ifdef DEBUG + { + register struct proc *p = curproc; /* XXX */ + log(LOG_NOTICE, "tcxmmap(0x%x) (%s[%d])\n", off, p->p_comm, p->p_pid); + } +#endif + return (-1); /* not a user-map offset */ +} diff --git a/sys/arch/sparc/dev/tcxreg.h b/sys/arch/sparc/dev/tcxreg.h new file mode 100644 index 00000000000..ef48a21955c --- /dev/null +++ b/sys/arch/sparc/dev/tcxreg.h @@ -0,0 +1,151 @@ +/* $OpenBSD: tcxreg.h,v 1.1 1997/08/08 08:25:32 downsj Exp $ */ +/* $NetBSD: tcxreg.h,v 1.1 1996/06/19 13:17:35 pk Exp $ */ +/* + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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. + */ + +/* + * A TCX is composed of numerous groups of control registers, all with TLAs: + * DHC - ??? + * TEC - transform engine control? + * THC - TEC Hardware Configuration + * ROM - a 128Kbyte ROM with who knows what in it. + * STIP - ??? + * RSTIP - Raw ??? + * BLIT - ??? + * RBLIT - Raw ??? + * ALT - ??? + * colormap - see below + * frame buffer memory (video RAM) + * possible other stuff + * + */ +#define TCX_REG_DFB8 0 +#define TCX_REG_DFB24 1 +#define TCX_REG_STIP 2 +#define TCX_REG_BLIT 3 +#define TCX_REG_RDFB32 4 +#define TCX_REG_RSTIP 5 +#define TCX_REG_RBLIT 6 +#define TCX_REG_TEC 7 +#define TCX_REG_CMAP 8 +#define TCX_REG_THC 9 +#define TCX_REG_ROM 10 +#define TCX_REG_DHC 11 +#define TCX_REG_ALT 12 + +#define TCX_NREG 13 + + +/* + * The layout of the THC. + */ +struct tcx_thc { + u_int thc_config; + u_int thc_xxx1[31]; + u_int thc_sensebus; + u_int thc_xxx2[3]; + u_int thc_delay; + u_int thc_strapping; + u_int thc_xxx3[1]; + u_int thc_linecount; + u_int thc_xxx4[478]; + u_int thc_hcmisc; + u_int thc_xxx5[56]; + u_int thc_cursoraddr; + u_int thc_cursorAdata[32]; + u_int thc_cursorBdata[32]; + +}; +/* bits in thc_config ??? */ +#define THC_CFG_FBID 0xf0000000 /* id mask */ +#define THC_CFG_FBID_SHIFT 28 +#define THC_CFG_SENSE 0x07000000 /* sense mask */ +#define THC_CFG_SENSE_SHIFT 24 +#define THC_CFG_REV 0x00f00000 /* revision mask */ +#define THC_CFG_REV_SHIFT 20 +#define THC_CFG_RST 0x00008000 /* reset */ + +/* bits in thc_hcmisc */ +#define THC_MISC_OPENFLG 0x80000000 /* open flag (what's that?) */ +#define THC_MISC_SWERR_EN 0x20000000 /* enable SW error interrupt */ +#define THC_MISC_VSYNC_LEVEL 0x08000000 /* vsync level when disabled */ +#define THC_MISC_HSYNC_LEVEL 0x04000000 /* hsync level when disabled */ +#define THC_MISC_VSYNC_DISABLE 0x02000000 /* vsync disable */ +#define THC_MISC_HSYNC_DISABLE 0x01000000 /* hsync disable */ +#define THC_MISC_XXX1 0x00ffe000 /* unused */ +#define THC_MISC_RESET 0x00001000 /* ??? */ +#define THC_MISC_XXX2 0x00000800 /* unused */ +#define THC_MISC_VIDEN 0x00000400 /* video enable */ +#define THC_MISC_SYNC 0x00000200 /* not sure what ... */ +#define THC_MISC_VSYNC 0x00000100 /* ... these really are */ +#define THC_MISC_SYNCEN 0x00000080 /* sync enable */ +#define THC_MISC_CURSRES 0x00000040 /* cursor resolution */ +#define THC_MISC_INTEN 0x00000020 /* v.retrace intr enable */ +#define THC_MISC_INTR 0x00000010 /* intr pending / ack bit */ +#define THC_MISC_DACWAIT 0x0000000f /* ??? */ + +/* + * Partial description of TEC. + */ +struct tcx_tec { + u_int tec_config; /* what's in it? */ + u_int tec_xxx0[35]; + u_int tec_delay; /* */ +#define TEC_DELAY_SYNC 0x00000f00 +#define TEC_DELAY_WR_F 0x000000c0 +#define TEC_DELAY_WR_R 0x00000030 +#define TEC_DELAY_SOE_F 0x0000000c +#define TEC_DELAY_SOE_S 0x00000003 + u_int tec_strapping; /* */ +#define TEC_STRAP_FIFO_LIMIT 0x00f00000 +#define TEC_STRAP_CACHE_EN 0x00010000 +#define TEC_STRAP_ZERO_OFFSET 0x00008000 +#define TEC_STRAP_REFRSH_DIS 0x00004000 +#define TEC_STRAP_REF_LOAD 0x00001000 +#define TEC_STRAP_REFRSH_PERIOD 0x000003ff + u_int tec_hcmisc; /* */ + u_int tec_linecount; /* */ + u_int tec_hss; /* */ + u_int tec_hse; /* */ + u_int tec_hds; /* */ + u_int tec_hsedvs; /* */ + u_int tec_hde; /* */ + u_int tec_vss; /* */ + u_int tec_vse; /* */ + u_int tec_vds; /* */ + u_int tec_vde; /* */ +}; + diff --git a/sys/arch/sparc/dev/vmereg.h b/sys/arch/sparc/dev/vmereg.h new file mode 100644 index 00000000000..5e7eb708ea4 --- /dev/null +++ b/sys/arch/sparc/dev/vmereg.h @@ -0,0 +1,75 @@ +/* $OpenBSD: vmereg.h,v 1.1 1997/08/08 08:25:32 downsj Exp $ */ +/* $NetBSD: vmereg.h,v 1.2 1997/06/07 19:10:57 pk Exp $ */ + +/* + * Copyright (c) 1997 Paul Kranenburg + * + * 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 Paul Kranenburg. + * 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. + * + */ + +struct vmebusreg { + u_int32_t vmebus_cr; /* VMEbus control register */ + u_int32_t vmebus_afar; /* VMEbus async fault address */ + u_int32_t vmebus_afsr; /* VMEbus async fault status */ +}; + +/* Control Register bits */ +#define VMEBUS_CR_C 0x80000000 /* I/O cache enable */ +#define VMEBUS_CR_S 0x40000000 /* VME slave enable */ +#define VMEBUS_CR_L 0x20000000 /* Loopback enable (diagnostic) */ +#define VMEBUS_CR_R 0x10000000 /* VMEbus reset */ +#define VMEBUS_CR_RSVD 0x0ffffff0 /* reserved */ +#define VMEBUS_CR_IMPL 0x0000000f /* VMEbus interface implementation */ + +/* Asynchronous Fault Status bits */ +#define VMEBUS_AFSR_SZ 0xe0000000 /* Error transaction size */ +#define VMEBUS_AFSR_SZ4 0 /* 4 byte */ +#define VMEBUS_AFSR_SZ1 1 /* 1 byte */ +#define VMEBUS_AFSR_SZ2 2 /* 2 byte */ +#define VMEBUS_AFSR_SZ32 5 /* 32 byte */ +#define VMEBUS_AFSR_TO 0x10000000 /* VME master access time-out */ +#define VMEBUS_AFSR_BERR 0x08000000 /* VME master got BERR */ +#define VMEBUS_AFSR_WB 0x04000000 /* IOC write-back error (if SZ == 32) */ + /* Non-IOC write error (id SZ != 32) */ +#define VMEBUS_AFSR_ERR 0x02000000 /* Error summary bit */ +#define VMEBUS_AFSR_S 0x01000000 /* MVME error in supervisor space */ +#define VMEBUS_AFSR_ME 0x00800000 /* Multiple error */ +#define VMEBUS_AFSR_RSVD 0x007fffff /* reserved */ + +struct vmebusvec { + volatile u_int8_t vmebusvec[16]; +}; + +/* VME address modifiers */ +#define VMEMOD_A16_D_S 0x2d /* 16-bit address, data, supervisor */ +#define VMEMOD_A24_D_S 0x3d /* 24-bit address, data, supervisor */ +#define VMEMOD_A32_D_S 0x0d /* 32-bit address, data, supervisor */ + +#define VMEMOD_D32 0x40 /* 32-bit access */ + diff --git a/sys/arch/sparc/dev/xd.c b/sys/arch/sparc/dev/xd.c index 70caf5e3e48..5bf36fe6db2 100644 --- a/sys/arch/sparc/dev/xd.c +++ b/sys/arch/sparc/dev/xd.c @@ -1,4 +1,5 @@ -/* $NetBSD: xd.c,v 1.25 1996/04/22 02:42:06 christos Exp $ */ +/* $OpenBSD: xd.c,v 1.10 1997/08/08 08:25:35 downsj Exp $ */ +/* $NetBSD: xd.c,v 1.37 1997/07/29 09:58:16 fair Exp $ */ /* * @@ -36,7 +37,7 @@ * x d . c x y l o g i c s 7 5 3 / 7 0 5 3 v m e / s m d d r i v e r * * author: Chuck Cranor <chuck@ccrc.wustl.edu> - * id: $NetBSD: xd.c,v 1.25 1996/04/22 02:42:06 christos Exp $ + * id: $NetBSD: xd.c,v 1.37 1997/07/29 09:58:16 fair Exp $ * started: 27-Feb-95 * references: [1] Xylogics Model 753 User's Manual * part number: 166-753-001, Revision B, May 21, 1988. @@ -85,6 +86,7 @@ #include <sparc/dev/xdvar.h> #include <sparc/dev/xio.h> #include <sparc/sparc/vaddrs.h> +#include <sparc/sparc/cpuvar.h> /* * macros @@ -346,11 +348,11 @@ xdgetdisklabel(xd, b) * soft reset to detect the xdc. */ -int xdcmatch(parent, match, aux) +int xdcmatch(parent, vcf, aux) struct device *parent; - void *match, *aux; + void *vcf, *aux; { - struct cfdata *cf = match; + struct cfdata *cf = vcf; struct confargs *ca = aux; struct romaux *ra = &ca->ca_ra; struct xdc *xdc; @@ -359,7 +361,13 @@ int xdcmatch(parent, match, aux) if (strcmp(cf->cf_driver->cd_name, ra->ra_name)) return (0); - if (CPU_ISSUN4) { + switch (ca->ca_bustype) { + case BUS_OBIO: + case BUS_SBUS: + case BUS_VME16: + default: + return (0); + case BUS_VME32: xdc = (struct xdc *) ra->ra_vaddr; if (probeget((caddr_t) &xdc->xdc_csr, 1) == -1) return (0); @@ -367,8 +375,8 @@ int xdcmatch(parent, match, aux) XDC_WAIT(xdc, del, XDC_RESETUSEC, XDC_RESET); if (del <= 0) return (0); + return (1); } - return (1); } /* @@ -389,8 +397,7 @@ xdcattach(parent, self, aux) /* get addressing and intr level stuff from autoconfig and load it * into our xdc_softc. */ - ca->ca_ra.ra_vaddr = mapiodev(ca->ca_ra.ra_reg, 0, - sizeof(struct xdc), ca->ca_bustype); + ca->ca_ra.ra_vaddr = mapiodev(ca->ca_ra.ra_reg, 0, sizeof(struct xdc)); xdc->xdc = (struct xdc *) ca->ca_ra.ra_vaddr; pri = ca->ca_ra.ra_intr[0].int_pri; @@ -463,7 +470,7 @@ xdcattach(parent, self, aux) XDC_DONE(xdc, rqno, err); return; } - printf(": Xylogics 753/7053, PROM=%x.%02x.%02x\n", + printf(": Xylogics 753/7053, PROM=0x%x.%02x.%02x\n", ctl->eprom_partno, ctl->eprom_lvl, ctl->eprom_rev); XDC_DONE(xdc, rqno, err); @@ -514,12 +521,11 @@ xdcattach(parent, self, aux) * call xdattach!). */ int -xdmatch(parent, match, aux) +xdmatch(parent, vcf, aux) struct device *parent; - void *match, *aux; - + void *vcf, *aux; { - struct cfdata *cf = match; + struct cfdata *cf = vcf; struct xdc_attach_args *xa = aux; /* looking for autoconf wildcard or exact match */ @@ -987,24 +993,28 @@ xdsize(dev) { struct xd_softc *xdsc; - int part, size; + int unit, part, size, omask; - /* valid unit? try an open */ + /* valid unit? */ + unit = DISKUNIT(dev); + if (unit >= xd_cd.cd_ndevs || (xdsc = xd_cd.cd_devs[unit]) == NULL) + return (-1); - if (xdopen(dev, 0, S_IFBLK, NULL) != 0) + part = DISKPART(dev); + omask = xdsc->sc_dk.dk_openmask & (1 << part); + + if (omask == 0 && xdopen(dev, 0, S_IFBLK, NULL) != 0) return (-1); /* do it */ - - xdsc = xd_cd.cd_devs[DISKUNIT(dev)]; - part = DISKPART(dev); if (xdsc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) size = -1; /* only give valid size for swap partitions */ else - size = xdsc->sc_dk.dk_label->d_partitions[part].p_size; - if (xdclose(dev, 0, S_IFBLK, NULL) != 0) - return -1; - return size; + size = xdsc->sc_dk.dk_label->d_partitions[part].p_size * + (xdsc->sc_dk.dk_label->d_secsize / DEV_BSIZE); + if (omask == 0 && xdclose(dev, 0, S_IFBLK, NULL) != 0) + return (-1); + return (size); } /* * xdstrategy: buffering system interface to xd. @@ -1221,7 +1231,7 @@ xdc_rqtopb(iorq, iopb, cmd, subfun) XDPC_RBC | XDPC_ECC2; ctrl->throttle = XDC_THROTTLE; #ifdef sparc - if (CPU_ISSUN4 && cpumod == SUN4_300) + if (CPU_ISSUN4 && cpuinfo.cpu_type == CPUTYP_4_300) ctrl->delay = XDC_DELAY_4_300; else ctrl->delay = XDC_DELAY_SPARC; diff --git a/sys/arch/sparc/dev/xdreg.h b/sys/arch/sparc/dev/xdreg.h index c723d018d0d..c2e19564ced 100644 --- a/sys/arch/sparc/dev/xdreg.h +++ b/sys/arch/sparc/dev/xdreg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: xdreg.h,v 1.3 1997/08/08 08:25:36 downsj Exp $ */ /* $NetBSD: xdreg.h,v 1.3 1996/03/31 22:38:54 pk Exp $ */ /* diff --git a/sys/arch/sparc/dev/xdvar.h b/sys/arch/sparc/dev/xdvar.h index 294f3a8c84b..c3e35672ba4 100644 --- a/sys/arch/sparc/dev/xdvar.h +++ b/sys/arch/sparc/dev/xdvar.h @@ -1,3 +1,4 @@ +/* $OpenBSD: xdvar.h,v 1.4 1997/08/08 08:25:37 downsj Exp $ */ /* $NetBSD: xdvar.h,v 1.5 1996/03/31 22:38:56 pk Exp $ */ /* diff --git a/sys/arch/sparc/dev/xio.h b/sys/arch/sparc/dev/xio.h index 1ad5662b6be..c55c733712e 100644 --- a/sys/arch/sparc/dev/xio.h +++ b/sys/arch/sparc/dev/xio.h @@ -1,3 +1,4 @@ +/* $OpenBSD: xio.h,v 1.3 1997/08/08 08:25:37 downsj Exp $ */ /* $NetBSD: xio.h,v 1.2 1996/03/31 22:38:58 pk Exp $ */ /* diff --git a/sys/arch/sparc/dev/xy.c b/sys/arch/sparc/dev/xy.c index 2841bd9ba84..2dc3413f2fe 100644 --- a/sys/arch/sparc/dev/xy.c +++ b/sys/arch/sparc/dev/xy.c @@ -1,4 +1,5 @@ -/* $NetBSD: xy.c,v 1.17 1996/04/22 02:42:04 christos Exp $ */ +/* $OpenBSD: xy.c,v 1.9 1997/08/08 08:25:39 downsj Exp $ */ +/* $NetBSD: xy.c,v 1.26 1997/07/19 21:43:56 pk Exp $ */ /* * @@ -36,7 +37,7 @@ * x y . c x y l o g i c s 4 5 0 / 4 5 1 s m d d r i v e r * * author: Chuck Cranor <chuck@ccrc.wustl.edu> - * id: $NetBSD: xy.c,v 1.17 1996/04/22 02:42:04 christos Exp $ + * id: $NetBSD: xy.c,v 1.26 1997/07/19 21:43:56 pk Exp $ * started: 14-Sep-95 * references: [1] Xylogics Model 753 User's Manual * part number: 166-753-001, Revision B, May 21, 1988. @@ -287,11 +288,11 @@ xygetdisklabel(xy, b) * soft reset to detect the xyc. */ -int xycmatch(parent, match, aux) +int xycmatch(parent, vcf, aux) struct device *parent; - void *match, *aux; + void *vcf, *aux; { - struct cfdata *cf = match; + struct cfdata *cf = vcf; struct confargs *ca = aux; struct romaux *ra = &ca->ca_ra; struct xyc *xyc; @@ -299,14 +300,20 @@ int xycmatch(parent, match, aux) if (strcmp(cf->cf_driver->cd_name, ra->ra_name)) return (0); - if (CPU_ISSUN4) { + switch (ca->ca_bustype) { + case BUS_OBIO: + case BUS_SBUS: + case BUS_VME32: + default: + return (0); + case BUS_VME16: xyc = (struct xyc *) ra->ra_vaddr; if (probeget((caddr_t) &xyc->xyc_rsetup, 1) == -1) return (0); if (xyc_unbusy(xyc, XYC_RESETUSEC) == XY_ERR_FAIL) return(0); + return (1); } - return (1); } /* @@ -329,8 +336,7 @@ xycattach(parent, self, aux) /* get addressing and intr level stuff from autoconfig and load it * into our xyc_softc. */ - ca->ca_ra.ra_vaddr = mapiodev(ca->ca_ra.ra_reg, 0, - sizeof(struct xyc), ca->ca_bustype); + ca->ca_ra.ra_vaddr = mapiodev(ca->ca_ra.ra_reg, 0, sizeof(struct xyc)); xyc->xyc = (struct xyc *) ca->ca_ra.ra_vaddr; pri = ca->ca_ra.ra_intr[0].int_pri; @@ -458,12 +464,11 @@ xycattach(parent, self, aux) * call xyattach!). */ int -xymatch(parent, match, aux) +xymatch(parent, vcf, aux) struct device *parent; - void *match, *aux; - + void *vcf, *aux; { - struct cfdata *cf = match; + struct cfdata *cf = vcf; struct xyc_attach_args *xa = aux; /* looking for autoconf wildcard or exact match */ @@ -951,24 +956,28 @@ xysize(dev) { struct xy_softc *xysc; - int part, size; + int unit, part, size, omask; - /* valid unit? try an open */ + /* valid unit? */ + unit = DISKUNIT(dev); + if (unit >= xy_cd.cd_ndevs || (xysc = xy_cd.cd_devs[unit]) == NULL) + return (-1); - if (xyopen(dev, 0, S_IFBLK, NULL) != 0) + part = DISKPART(dev); + omask = xysc->sc_dk.dk_openmask & (1 << part); + + if (omask == 0 && xyopen(dev, 0, S_IFBLK, NULL) != 0) return (-1); /* do it */ - - xysc = xy_cd.cd_devs[DISKUNIT(dev)]; - part = DISKPART(dev); if (xysc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) size = -1; /* only give valid size for swap partitions */ else - size = xysc->sc_dk.dk_label->d_partitions[part].p_size; - if (xyclose(dev, 0, S_IFBLK, NULL) != 0) - return -1; - return size; + size = xysc->sc_dk.dk_label->d_partitions[part].p_size * + (xysc->sc_dk.dk_label->d_secsize / DEV_BSIZE); + if (omask == 0 && xyclose(dev, 0, S_IFBLK, NULL) != 0) + return (-1); + return (size); } /* diff --git a/sys/arch/sparc/dev/xyreg.h b/sys/arch/sparc/dev/xyreg.h index 2508bb97a8e..2d8c2704685 100644 --- a/sys/arch/sparc/dev/xyreg.h +++ b/sys/arch/sparc/dev/xyreg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: xyreg.h,v 1.3 1997/08/08 08:25:40 downsj Exp $ */ /* $NetBSD: xyreg.h,v 1.3 1996/03/31 22:39:02 pk Exp $ */ /* diff --git a/sys/arch/sparc/dev/xyvar.h b/sys/arch/sparc/dev/xyvar.h index e7ec8305980..f6f80cee49d 100644 --- a/sys/arch/sparc/dev/xyvar.h +++ b/sys/arch/sparc/dev/xyvar.h @@ -1,3 +1,4 @@ +/* $OpenBSD: xyvar.h,v 1.4 1997/08/08 08:25:41 downsj Exp $ */ /* $NetBSD: xyvar.h,v 1.4 1996/03/31 22:39:04 pk Exp $ */ /* diff --git a/sys/arch/sparc/dev/zs.c b/sys/arch/sparc/dev/zs.c index c44f4aefe72..b9cb8b8eb56 100644 --- a/sys/arch/sparc/dev/zs.c +++ b/sys/arch/sparc/dev/zs.c @@ -1,5 +1,5 @@ -/* $OpenBSD: zs.c,v 1.14 1997/06/25 13:01:00 downsj Exp $ */ -/* $NetBSD: zs.c,v 1.37.4.1 1996/06/02 09:07:55 mrg Exp $ */ +/* $OpenBSD: zs.c,v 1.15 1997/08/08 08:25:43 downsj Exp $ */ +/* $NetBSD: zs.c,v 1.48 1997/07/29 09:58:18 fair Exp $ */ /* * Copyright (c) 1992, 1993 @@ -72,21 +72,18 @@ #include <machine/autoconf.h> #include <machine/conf.h> #include <machine/cpu.h> +#include <machine/kbd.h> #include <sparc/sparc/vaddrs.h> #include <sparc/sparc/auxreg.h> - - -#include <machine/kbd.h> #include <dev/ic/z8530reg.h> - #include <sparc/dev/zsvar.h> #ifdef KGDB #include <machine/remote-sl.h> #endif -#define ZSMAJOR 12 /* XXX */ +#define ZSMAJOR 12 /* XXX */ #define ZS_KBD 2 /* XXX */ #define ZS_MOUSE 3 /* XXX */ @@ -113,8 +110,8 @@ struct zs_softc { struct device sc_dev; /* base device */ volatile struct zsdevice *sc_zs; /* chip registers */ - struct evcnt sc_intrcnt; - struct zs_chanstate sc_cs[2]; /* channel A/B software state */ + struct evcnt sc_intrcnt; /* count interrupts */ + struct zs_chanstate sc_cs[2]; /* chan A/B software state */ }; /* Definition of the driver for autoconfig. */ @@ -154,10 +151,11 @@ static void zs_loadchannelregs __P((volatile struct zschan *, u_char *)); /* Console stuff. */ static struct tty *zs_ctty; /* console `struct tty *' */ static int zs_consin = -1, zs_consout = -1; +static struct zs_chanstate *zs_conscs = NULL; /*console channel state */ static void zscnputc __P((int)); /* console putc function */ static volatile struct zschan *zs_conschan; static struct tty *zs_checkcons __P((struct zs_softc *, int, - struct zs_chanstate *)); + struct zs_chanstate *)); #ifdef KGDB /* KGDB stuff. Must reboot to change zs_kgdbunit. */ @@ -176,7 +174,6 @@ static int zssint __P((struct zs_chanstate *, volatile struct zschan *)); void zsabort __P((void)); static void zsoverrun __P((int, long *, char *)); -extern void *findzs __P((int)); static volatile struct zsdevice *zsaddr[NZS]; /* XXX, but saves work */ /* @@ -272,7 +269,7 @@ zsattach(parent, dev, aux) if ((addr = zsaddr[zs]) == NULL) addr = zsaddr[zs] = (volatile struct zsdevice *)findzs(zs); - if (ca->ca_bustype == BUS_MAIN) + if (ca->ca_bustype==BUS_MAIN) if ((void *)addr != ra->ra_vaddr) panic("zsattach"); if (ra->ra_nintr != 1) { @@ -311,11 +308,12 @@ zsattach(parent, dev, aux) tp->t_dev = makedev(ZSMAJOR, unit); tp->t_oproc = zsstart; tp->t_param = zsparam; + } + cs->cs_ttyp = tp; #ifdef KGDB + if (ctp == NULL) zs_checkkgdb(unit, cs, tp); #endif - } - cs->cs_ttyp = tp; if (unit == ZS_KBD) { /* * Keyboard: tell /dev/kbd driver how to talk to us. @@ -329,14 +327,15 @@ zsattach(parent, dev, aux) if (tp != ctp) tty_attach(tp); ringsize = 4096; + if (unit == zs_consout) + zs_conscs = cs; } - cs->cs_ringmask = ringsize - 1; cs->cs_rbuf = malloc((u_long)ringsize * sizeof(*cs->cs_rbuf), M_DEVBUF, M_NOWAIT); + unit++; cs++; - cs->cs_unit = unit; cs->cs_speed = zs_getspeed(&addr->zs_chan[ZS_CHAN_B]); cs->cs_zc = &addr->zs_chan[ZS_CHAN_B]; @@ -347,11 +346,12 @@ zsattach(parent, dev, aux) tp->t_dev = makedev(ZSMAJOR, unit); tp->t_oproc = zsstart; tp->t_param = zsparam; + } + cs->cs_ttyp = tp; #ifdef KGDB + if (ctp == NULL) zs_checkkgdb(unit, cs, tp); #endif - } - cs->cs_ttyp = tp; if (unit == ZS_MOUSE) { /* * Mouse: tell /dev/mouse driver how to talk to us. @@ -364,6 +364,8 @@ zsattach(parent, dev, aux) if (tp != ctp) tty_attach(tp); ringsize = 4096; + if (unit == zs_consout) + zs_conscs = cs; } cs->cs_ringmask = ringsize - 1; cs->cs_rbuf = malloc((u_long)ringsize * sizeof(*cs->cs_rbuf), @@ -439,7 +441,7 @@ zsconsole(tp, unit, out, fnstop) v_putc = zscnputc; } else zs_consin = unit; - if(fnstop) + if (fnstop) *fnstop = &zsstop; zs_ctty = tp; } @@ -465,6 +467,24 @@ zscnputc(c) (void) splzs(); while ((zc->zc_csr & ZSRR0_TX_READY) == 0) ZS_DELAY(); + /* + * If transmitter was busy doing regular tty I/O (ZSWR1_TIE on), + * defer our output until the transmit interrupt runs. We still + * sync with TX_READY so we can get by with a single-char "queue". + */ + if (zs_conscs != NULL && (zs_conscs->cs_creg[1] & ZSWR1_TIE)) { + /* + * If previous not yet done, send it now; zsxint() + * will field the interrupt for our char, but doesn't + * care. We're running at sufficiently high spl for + * this to work. + */ + if (zs_conscs->cs_deferred_cc != 0) + zc->zc_data = zs_conscs->cs_deferred_cc; + zs_conscs->cs_deferred_cc = c; + splx(s); + return; + } zc->zc_data = c; ZS_DELAY(); splx(s); @@ -483,7 +503,7 @@ zs_checkcons(sc, unit, cs) register struct tty *tp; char *i, *o; - if ((tp = zs_ctty) == NULL) + if ((tp = zs_ctty) == NULL) /* XXX */ return (0); i = zs_consin == unit ? "input" : NULL; o = zs_consout == unit ? "output" : NULL; @@ -623,7 +643,7 @@ zsopen(dev, flags, mode, p) return (EBUSY); } error = 0; - while (1) { + for (;;) { register int rr0; /* loop, turning on the device, until carrier present */ @@ -720,6 +740,7 @@ zsread(dev, uio, flags) tp = cs->cs_ttyp; return (linesw[tp->t_line].l_read(tp, uio, flags)); + } int @@ -850,7 +871,7 @@ zshard(intrarg) raise(0, PIL_TTY); else #endif - ienab_bis(IE_ZSSOFT); + ienab_bis(IE_ZSSOFT); } return (intflags & ZSHARD_WAS_SERVICED); } @@ -860,11 +881,9 @@ zsrint(cs, zc) register struct zs_chanstate *cs; register volatile struct zschan *zc; { - register u_int c; + register u_int c = zc->zc_data; - c = zc->zc_data; ZS_DELAY(); - if (cs->cs_conk) { register struct conk_state *conk = &zsconk_state; @@ -922,6 +941,15 @@ zsxint(cs, zc) { register int i = cs->cs_tbc; + if (cs->cs_deferred_cc != 0) { + /* Handle deferred zscnputc() output first */ + zc->zc_data = cs->cs_deferred_cc; + cs->cs_deferred_cc = 0; + ZS_DELAY(); + zc->zc_csr = ZSWR0_CLR_INTR; + ZS_DELAY(); + return (0); + } if (i == 0) { zc->zc_csr = ZSWR0_RESET_TXINT; ZS_DELAY(); @@ -1145,7 +1173,7 @@ again: break; default: - log(LOG_ERR, "zs%d%c: bad ZRING_TYPE (%x)\n", + log(LOG_ERR, "zs%d%c: bad ZRING_TYPE (0x%x)\n", unit >> 1, (unit & 1) + 'a', c); break; } @@ -1166,9 +1194,9 @@ zsioctl(dev, cmd, data, flag, p) { int unit = minor(dev); struct zs_softc *sc = zs_cd.cd_devs[unit >> 1]; - register struct tty *tp = sc->sc_cs[unit & 1].cs_ttyp; - register int error, s; register struct zs_chanstate *cs = &sc->sc_cs[unit & 1]; + register struct tty *tp = cs->cs_ttyp; + register int error, s; error = linesw[tp->t_line].l_ioctl(tp, cmd, data, flag, p); if (error >= 0) @@ -1262,14 +1290,8 @@ zsioctl(dev, cmd, data, flag, p) case TIOCCDTR: zs_modem(cs, 0); break; - case TIOCMGET: - /* XXX: fixme */ - *(int *)data = TIOCM_CAR | TIOCM_CTS | TIOCM_DTR | TIOCM_RTS; - return (0); case TIOCMSET: - /* XXX: fixme */ - zs_modem(cs, *(int *)data & (TIOCM_DTR|TIOCM_RTS)); - return (0); + case TIOCMGET: case TIOCMBIS: case TIOCMBIC: default: @@ -1396,7 +1418,11 @@ zsparam(tp, t) return (0); } tmp = BPS_TO_TCONST(PCLK / 16, tmp); - if (tmp < 2) +#ifdef ALLOW_TC_EQUAL_ZERO + if (tmp < 0) +#else + if (tmp < 1) +#endif return (EINVAL); cflag = t->c_cflag; diff --git a/sys/arch/sparc/dev/zsvar.h b/sys/arch/sparc/dev/zsvar.h index 8f9274573ee..79b8c6cd2c9 100644 --- a/sys/arch/sparc/dev/zsvar.h +++ b/sys/arch/sparc/dev/zsvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: zsvar.h,v 1.9 1996/08/12 03:14:50 downsj Exp $ */ -/* $NetBSD: zsvar.h,v 1.8 1996/03/31 22:39:08 pk Exp $ */ +/* $OpenBSD: zsvar.h,v 1.10 1997/08/08 08:25:44 downsj Exp $ */ +/* $NetBSD: zsvar.h,v 1.10 1997/04/14 21:26:28 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -91,9 +91,12 @@ struct zsdevice { #define ZRING_VALUE(x) ((x) >> 8) #define ZRING_MAKE(t, v) ((t) | (v) << 8) +/* forard decl */ +struct zs_softc; + struct zs_chanstate { - struct zs_chanstate *cs_next; /* linked list for zshard() */ - struct zs_softc *cs_sc; /* points to my softc */ + struct zs_chanstate *cs_next; /* linked list for zshard() */ + struct zs_softc *cs_sc; /* pointer to softc */ volatile struct zschan *cs_zc; /* points to hardware regs */ int cs_unit; /* unit number */ struct tty *cs_ttyp; /* ### */ @@ -123,6 +126,7 @@ struct zs_chanstate { char cs_kgdb; /* enter debugger on frame char */ char cs_consio; /* port does /dev/console I/O */ char cs_xxx; /* (spare) */ + char cs_deferred_cc; /* deferred zscnputc() output */ int cs_speed; /* default baud rate (from ROM) */ /* diff --git a/sys/arch/sparc/fpu/fpu.c b/sys/arch/sparc/fpu/fpu.c index 6a502402613..742add709d2 100644 --- a/sys/arch/sparc/fpu/fpu.c +++ b/sys/arch/sparc/fpu/fpu.c @@ -1,4 +1,5 @@ -/* $NetBSD: fpu.c,v 1.3 1996/03/14 19:41:49 christos Exp $ */ +/* $OpenBSD: fpu.c,v 1.7 1997/08/08 08:25:46 downsj Exp $ */ +/* $NetBSD: fpu.c,v 1.6 1997/07/29 10:09:51 fair Exp $ */ /* * Copyright (c) 1992, 1993 @@ -143,7 +144,7 @@ fpu_cleanup(p, fs) goto out; default: - printf("fsr=%x\n", fsr); + printf("fsr=0x%x\n", fsr); panic("fpu error"); } diff --git a/sys/arch/sparc/fpu/fpu_add.c b/sys/arch/sparc/fpu/fpu_add.c index 1aa9225c01e..28ee40b9370 100644 --- a/sys/arch/sparc/fpu/fpu_add.c +++ b/sys/arch/sparc/fpu/fpu_add.c @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_add.c,v 1.3 1997/08/08 08:25:47 downsj Exp $ */ /* $NetBSD: fpu_add.c,v 1.3 1996/03/14 19:41:52 christos Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_arith.h b/sys/arch/sparc/fpu/fpu_arith.h index 572b16d7233..d222eae3a39 100644 --- a/sys/arch/sparc/fpu/fpu_arith.h +++ b/sys/arch/sparc/fpu/fpu_arith.h @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_arith.h,v 1.2 1997/08/08 08:25:48 downsj Exp $ */ /* $NetBSD: fpu_arith.h,v 1.2 1994/11/20 20:52:35 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_compare.c b/sys/arch/sparc/fpu/fpu_compare.c index 4868b535dfb..642b5497d70 100644 --- a/sys/arch/sparc/fpu/fpu_compare.c +++ b/sys/arch/sparc/fpu/fpu_compare.c @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_compare.c,v 1.2 1997/08/08 08:25:49 downsj Exp $ */ /* $NetBSD: fpu_compare.c,v 1.2 1994/11/20 20:52:37 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_div.c b/sys/arch/sparc/fpu/fpu_div.c index 0ddb592e45a..366844ec578 100644 --- a/sys/arch/sparc/fpu/fpu_div.c +++ b/sys/arch/sparc/fpu/fpu_div.c @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_div.c,v 1.2 1997/08/08 08:25:50 downsj Exp $ */ /* $NetBSD: fpu_div.c,v 1.2 1994/11/20 20:52:38 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_emu.h b/sys/arch/sparc/fpu/fpu_emu.h index 5b2b317c383..78f4dc69292 100644 --- a/sys/arch/sparc/fpu/fpu_emu.h +++ b/sys/arch/sparc/fpu/fpu_emu.h @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_emu.h,v 1.2 1997/08/08 08:25:51 downsj Exp $ */ /* $NetBSD: fpu_emu.h,v 1.2 1994/11/20 20:52:39 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_explode.c b/sys/arch/sparc/fpu/fpu_explode.c index ceaa896c02d..658ecdaf88b 100644 --- a/sys/arch/sparc/fpu/fpu_explode.c +++ b/sys/arch/sparc/fpu/fpu_explode.c @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_explode.c,v 1.3 1997/08/08 08:25:52 downsj Exp $ */ /* $NetBSD: fpu_explode.c,v 1.3 1996/03/14 19:41:54 christos Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_extern.h b/sys/arch/sparc/fpu/fpu_extern.h index 0f2ed79668d..fa7ca68daec 100644 --- a/sys/arch/sparc/fpu/fpu_extern.h +++ b/sys/arch/sparc/fpu/fpu_extern.h @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_extern.h,v 1.2 1997/08/08 08:25:53 downsj Exp $ */ /* $NetBSD: fpu_extern.h,v 1.1 1996/03/14 19:41:56 christos Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_implode.c b/sys/arch/sparc/fpu/fpu_implode.c index 753b0ba9973..5d07ac1e23b 100644 --- a/sys/arch/sparc/fpu/fpu_implode.c +++ b/sys/arch/sparc/fpu/fpu_implode.c @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_implode.c,v 1.3 1997/08/08 08:25:56 downsj Exp $ */ /* $NetBSD: fpu_implode.c,v 1.3 1996/03/14 19:41:59 christos Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_mul.c b/sys/arch/sparc/fpu/fpu_mul.c index e1439b1b354..241b0211b02 100644 --- a/sys/arch/sparc/fpu/fpu_mul.c +++ b/sys/arch/sparc/fpu/fpu_mul.c @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_mul.c,v 1.2 1997/08/08 08:25:57 downsj Exp $ */ /* $NetBSD: fpu_mul.c,v 1.2 1994/11/20 20:52:44 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_sqrt.c b/sys/arch/sparc/fpu/fpu_sqrt.c index 3fb12acd87c..e603226fc35 100644 --- a/sys/arch/sparc/fpu/fpu_sqrt.c +++ b/sys/arch/sparc/fpu/fpu_sqrt.c @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_sqrt.c,v 1.2 1997/08/08 08:25:58 downsj Exp $ */ /* $NetBSD: fpu_sqrt.c,v 1.2 1994/11/20 20:52:46 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/fpu/fpu_subr.c b/sys/arch/sparc/fpu/fpu_subr.c index 45b80c219ba..d1b5e17e53a 100644 --- a/sys/arch/sparc/fpu/fpu_subr.c +++ b/sys/arch/sparc/fpu/fpu_subr.c @@ -1,3 +1,4 @@ +/* $OpenBSD: fpu_subr.c,v 1.3 1997/08/08 08:25:59 downsj Exp $ */ /* $NetBSD: fpu_subr.c,v 1.3 1996/03/14 19:42:01 christos Exp $ */ /* diff --git a/sys/arch/sparc/include/ansi.h b/sys/arch/sparc/include/ansi.h index ecb80ec50d7..fce22059951 100644 --- a/sys/arch/sparc/include/ansi.h +++ b/sys/arch/sparc/include/ansi.h @@ -1,3 +1,4 @@ +/* $OpenBSD: ansi.h,v 1.6 1997/08/08 08:26:01 downsj Exp $ */ /* $NetBSD: ansi.h,v 1.6 1996/11/15 22:38:59 jtc Exp $ */ /*- diff --git a/sys/arch/sparc/include/asm.h b/sys/arch/sparc/include/asm.h index 4241a44caa5..d1f4082b5f0 100644 --- a/sys/arch/sparc/include/asm.h +++ b/sys/arch/sparc/include/asm.h @@ -1,4 +1,5 @@ -/* $NetBSD: asm.h,v 1.3 1994/11/20 20:52:51 deraadt Exp $ */ +/* $OpenBSD: asm.h,v 1.2 1997/08/08 08:26:02 downsj Exp $ */ +/* $NetBSD: asm.h,v 1.5 1997/07/16 15:16:43 christos Exp $ */ /* * Copyright (c) 1994 Allen Briggs @@ -83,7 +84,7 @@ #define _ENTRY(name) \ .align 4; .globl name; .proc 1; FTYPE(name); name: -#ifdef PROF +#ifdef GPROF #define _PROF_PROLOGUE \ .data; .align 4; 1: .long 0; \ .text; save %sp,-96,%sp; sethi %hi(1b),%o0; call mcount; \ @@ -99,4 +100,6 @@ #define ASMSTR .asciz +#define RCSID(name) .asciz name + #endif /* _ASM_H_ */ diff --git a/sys/arch/sparc/include/autoconf.h b/sys/arch/sparc/include/autoconf.h index 1caa73db7ab..0e56dee8093 100644 --- a/sys/arch/sparc/include/autoconf.h +++ b/sys/arch/sparc/include/autoconf.h @@ -1,4 +1,5 @@ -/* $NetBSD: autoconf.h,v 1.16 1996/04/10 20:33:38 pk Exp $ */ +/* $OpenBSD: autoconf.h,v 1.5 1997/08/08 08:26:03 downsj Exp $ */ +/* $NetBSD: autoconf.h,v 1.20 1997/05/24 20:03:03 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -60,7 +61,6 @@ #define RA_MAXVADDR 8 /* max (virtual) addresses per device */ #define RA_MAXREG 16 /* max # of register banks per device */ #define RA_MAXINTR 8 /* max interrupts per device */ -#define RA_MAXRANGE 10 /* max # of bus translations */ struct romaux { const char *ra_name; /* name from FORTH PROM */ @@ -85,18 +85,17 @@ struct romaux { } ra_intr[RA_MAXINTR]; int ra_nintr; /* number of interrupt info elements */ - struct rom_range { /* Only used on v3 PROMs */ - u_int32_t cspace; /* Client space */ - u_int32_t coffset; /* Client offset */ - u_int32_t pspace; /* Parent space */ - u_int32_t poffset; /* Parent offset */ - u_int32_t size; /* Size in bytes of this range */ - } ra_range[RA_MAXRANGE]; - int ra_nrange; - struct bootpath *ra_bp; /* used for locating boot device */ }; +struct rom_range { /* Only used on v3 PROMs */ + u_int32_t cspace; /* Client space */ + u_int32_t coffset; /* Client offset */ + u_int32_t pspace; /* Parent space */ + u_int32_t poffset; /* Parent offset */ + u_int32_t size; /* Size in bytes of this range */ +}; + struct confargs { int ca_bustype; @@ -110,8 +109,6 @@ struct confargs { #define BUS_VME32 3 #define BUS_SBUS 4 -extern int bt2pmt[]; - /* * mapiodev maps an I/O device to a virtual address, returning the address. * mapdev does the real work: you can supply a special virtual address and @@ -119,22 +116,17 @@ extern int bt2pmt[]; * you get it from ../sparc/vaddrs.h. */ void *mapdev __P((struct rom_reg *pa, int va, - int offset, int size, int bustype)); -#define mapiodev(pa, offset, size, bustype) \ - mapdev(pa, 0, offset, size, bustype) + int offset, int size)); +#define mapiodev(pa, offset, size) \ + mapdev(pa, 0, offset, size) /* * REG2PHYS is provided for drivers with a `d_mmap' function. */ -#define REG2PHYS(rr, offset, bt) \ - (((u_int)(rr)->rr_paddr + (offset)) | \ - ((CPU_ISSUN4M) \ - ? ((rr)->rr_iospace << PMAP_SHFT4M) \ - : bt2pmt[bt]) \ - ) +#define REG2PHYS(rr, offset) \ + (((u_int)(rr)->rr_paddr + (offset)) | PMAP_IOENC((rr)->rr_iospace) ) /* For VME and sun4/obio busses */ -void *bus_map __P((struct rom_reg *, int, int)); -void *bus_tmp __P((void *, int)); +void *bus_map __P((struct rom_reg *, int)); void bus_untmp __P((void)); /* @@ -142,6 +134,7 @@ void bus_untmp __P((void)); * getprop() obtains a property as a byte-sequence, and returns its * length; the others convert or make some other guarantee. */ +int getproplen __P((int node, char *name)); int getprop __P((int node, char *name, void *buf, int bufsiz)); char *getpropstring __P((int node, char *name)); int getpropint __P((int node, char *name, int deflt)); @@ -163,6 +156,7 @@ int romprop __P((struct romaux *ra, const char *name, int node)); * a romaux structure suffices, for instance). */ struct device; +struct cfdata; int matchbyname __P((struct device *, void *cf, void *aux)); /* diff --git a/sys/arch/sparc/include/bsd_audioio.h b/sys/arch/sparc/include/bsd_audioio.h index 4d8bc0aeb34..6f496e0674d 100644 --- a/sys/arch/sparc/include/bsd_audioio.h +++ b/sys/arch/sparc/include/bsd_audioio.h @@ -1,3 +1,4 @@ +/* $OpenBSD: bsd_audioio.h,v 1.2 1997/08/08 08:26:05 downsj Exp $ */ /* $NetBSD: bsd_audioio.h,v 1.3 1995/03/04 09:58:45 pk Exp $ */ /* diff --git a/sys/arch/sparc/include/bsd_openprom.h b/sys/arch/sparc/include/bsd_openprom.h index 35a9b3a7c13..4b2862dc186 100644 --- a/sys/arch/sparc/include/bsd_openprom.h +++ b/sys/arch/sparc/include/bsd_openprom.h @@ -1,3 +1,4 @@ +/* $OpenBSD: bsd_openprom.h,v 1.5 1997/08/08 08:26:06 downsj Exp $ */ /* $NetBSD: bsd_openprom.h,v 1.11 1996/05/18 12:27:43 mrg Exp $ */ /* diff --git a/sys/arch/sparc/include/cdefs.h b/sys/arch/sparc/include/cdefs.h index 36f4990a9cc..54b934c3216 100644 --- a/sys/arch/sparc/include/cdefs.h +++ b/sys/arch/sparc/include/cdefs.h @@ -1,4 +1,5 @@ -/* $NetBSD: cdefs.h,v 1.2 1995/03/23 20:10:48 jtc Exp $ */ +/* $OpenBSD: cdefs.h,v 1.4 1997/08/08 08:26:07 downsj Exp $ */ +/* $NetBSD: cdefs.h,v 1.3 1996/12/27 20:51:31 pk Exp $ */ /* * Written by J.T. Conklin <jtc@wimsey.com> 01/17/95. @@ -30,6 +31,9 @@ __asm__(".stabs msg,30,0,0,0"); \ __asm__(".stabs \"_/**/sym\",1,0,0,0") #endif +#else +#define __indr_reference(sym,alias) +#define __warn_references(sym,msg) #endif #endif /* !_MACHINE_CDEFS_H_ */ diff --git a/sys/arch/sparc/include/cgtworeg.h b/sys/arch/sparc/include/cgtworeg.h index 6a874e77cfd..4660ba7f2b6 100644 --- a/sys/arch/sparc/include/cgtworeg.h +++ b/sys/arch/sparc/include/cgtworeg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: cgtworeg.h,v 1.2 1997/08/08 08:26:09 downsj Exp $ */ /* $NetBSD: cgtworeg.h,v 1.3 1995/10/04 00:21:27 pk Exp $ */ /* diff --git a/sys/arch/sparc/include/conf.h b/sys/arch/sparc/include/conf.h index 20855735e69..cedfec5cc9b 100644 --- a/sys/arch/sparc/include/conf.h +++ b/sys/arch/sparc/include/conf.h @@ -1,5 +1,5 @@ -/* $NetBSD: conf.h,v 1.1 1996/03/30 21:17:55 christos Exp $ */ -/* $OpenBSD: conf.h,v 1.4 1997/05/06 19:07:36 kstailey Exp $ */ +/* $OpenBSD: conf.h,v 1.5 1997/08/08 08:26:10 downsj Exp $ */ +/* $NetBSD: conf.h,v 1.8 1996/12/31 07:12:43 mrg Exp $ */ /* * Copyright (c) 1996 Christos Zoulas. All rights reserved. @@ -62,6 +62,8 @@ cdev_decl(kbd); cdev_decl(bwtwo); +cdev_decl(cgtwo); + cdev_decl(cgthree); cdev_decl(cgfour); @@ -70,6 +72,10 @@ cdev_decl(cgsix); cdev_decl(cgeight); +cdev_decl(tcx); + +cdev_decl(cgfourteen); + cdev_decl(ipl); #ifdef IPFILTER #define NIPF 1 @@ -85,3 +91,6 @@ cdev_decl(xy); bdev_decl(sw); cdev_decl(sw); + +bdev_decl(rd); +cdev_decl(rd); diff --git a/sys/arch/sparc/include/cpu.h b/sys/arch/sparc/include/cpu.h index 88c05b45a98..7f743246e7a 100644 --- a/sys/arch/sparc/include/cpu.h +++ b/sys/arch/sparc/include/cpu.h @@ -1,4 +1,5 @@ -/* $NetBSD: cpu.h,v 1.21 1996/03/31 22:17:14 pk Exp $ */ +/* $OpenBSD: cpu.h,v 1.3 1997/08/08 08:26:11 downsj Exp $ */ +/* $NetBSD: cpu.h,v 1.24 1997/03/15 22:25:15 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,8 +45,8 @@ * @(#)cpu.h 8.4 (Berkeley) 1/5/94 */ -#ifndef _CPU_H_ -#define _CPU_H_ +#ifndef _SPARC_CPU_H_ +#define _SPARC_CPU_H_ /* * CTL_MACHDEP definitions. @@ -200,7 +201,7 @@ void copywords __P((const void *, void *, size_t)); void qcopy __P((const void *, void *, size_t)); void qzero __P((void *, size_t)); /* locore2.c */ -void remrq __P((struct proc *)); +void remrunqueue __P((struct proc *)); /* trap.c */ void kill_user_windows __P((struct proc *)); int rwindow_save __P((struct proc *)); @@ -229,6 +230,10 @@ void cpu_set_kpc __P((struct proc *, void (*)(struct proc *))); /* iommu.c */ void iommu_enter __P((u_int, u_int)); void iommu_remove __P((u_int, u_int)); +/* emul.c */ +struct trapframe; +int fixalign __P((struct proc *, struct trapframe *)); +int emulinstr __P((int, struct trapframe *)); /* * @@ -253,4 +258,4 @@ extern void wzero __P((void *, u_int)); extern void wcopy __P((const void *, void *, u_int)); #endif /* _KERNEL */ -#endif /* _CPU_H_ */ +#endif /* _SPARC_CPU_H_ */ diff --git a/sys/arch/sparc/include/ctlreg.h b/sys/arch/sparc/include/ctlreg.h index 1f5d8519aef..fa79810cba2 100644 --- a/sys/arch/sparc/include/ctlreg.h +++ b/sys/arch/sparc/include/ctlreg.h @@ -1,4 +1,5 @@ -/* $NetBSD: ctlreg.h,v 1.12 1996/05/16 15:57:00 abrown Exp $ */ +/* $OpenBSD: ctlreg.h,v 1.4 1997/08/08 08:26:12 downsj Exp $ */ +/* $NetBSD: ctlreg.h,v 1.15 1997/07/20 18:55:03 pk Exp $ */ /* * Copyright (c) 1996 @@ -91,11 +92,11 @@ #define ASI_ICACHEDATA 0x0d /* [4m] instruction cache data */ #define ASI_DCACHETAG 0x0e /* [4m] data cache tag */ #define ASI_DCACHEDATA 0x0f /* [4m] data cache data */ -#define ASI_IDCACHELFP 0x10 /* [4m] ms2 only: flush i&d cache line (page) */ -#define ASI_IDCACHELFS 0x11 /* [4m] ms2 only: flush i&d cache line (seg) */ -#define ASI_IDCACHELFR 0x12 /* [4m] ms2 only: flush i&d cache line (reg) */ -#define ASI_IDCACHELFC 0x13 /* [4m] ms2 only: flush i&d cache line (ctxt) */ -#define ASI_IDCACHELFU 0x14 /* [4m] ms2 only: flush i&d cache line (user) */ +#define ASI_IDCACHELFP 0x10 /* [4m] flush i&d cache line (page) */ +#define ASI_IDCACHELFS 0x11 /* [4m] flush i&d cache line (seg) */ +#define ASI_IDCACHELFR 0x12 /* [4m] flush i&d cache line (reg) */ +#define ASI_IDCACHELFC 0x13 /* [4m] flush i&d cache line (ctxt) */ +#define ASI_IDCACHELFU 0x14 /* [4m] flush i&d cache line (user) */ #define ASI_BYPASS 0x20 /* [4m] sun ref mmu bypass, ie. direct phys access */ #define ASI_ICACHECLR 0x36 /* [4m] ms1 only: I-cache flash clear */ @@ -199,37 +200,111 @@ #define SRMMU_SFADDR 0x00000400 /* Synchronous fault address reg */ #define SRMMU_AFSTAT 0x00000500 /* Asynchronous fault status reg (HS) */ #define SRMMU_AFADDR 0x00000600 /* Asynchronous fault address reg (HS)*/ +#define SRMMU_PCFG 0x00000600 /* Processor configuration reg (TURBO)*/ #define SRMMU_TLBCTRL 0x00001000 /* TLB replacement control reg */ -/* [4m] Bits in SRMMU control register */ -#define SRMMU_PCR_ME 0x00000001 /* MMU Enable */ -#define SRMMU_PCR_NF 0x00000002 /* Fault inhibit bit */ -#define SRMMU_PCR_PSO 0x00000080 /* Partial Store Ordering enable */ -#define SRMMU_PCR_CE 0x00000100 /* HS: Cache enable bit (HyperSPARC) */ -#define SRMMU_PCR_DCE 0x00000100 /* SS: Data cache enable bit */ -#define SRMMU_PCR_ICE 0x00000200 /* SS: SuperSPARC instr. cache enable */ -#define SRMMU_PCR_CM 0x00000400 /* HS: Cache mode: 1 == write-back */ -#define SRMMU_PCR_SB 0x00000400 /* SS: Store buffer enable bit */ -#define SRMMU_PCR_MR 0x00000800 /* HS: Memory reflection: 1 == on */ -#define SRMMU_PCR_MB 0x00000800 /* SS: MBus mode: 0=MXCC, 1=no MXCC */ -#define SRMMU_PCR_CS 0x00001000 /* HS: cache size: 1==256k, 0==128k */ -#define SRMMU_PCR_PE 0x00001000 /* SS: Enable memory parity checking */ -#define SRMMU_PCR_C 0x00002000 /* HS: enable cache when MMU off */ -#define SRMMU_PCR_SSBM 0x00002000 /* SS: 1 iff booting */ -#define SRMMU_PCR_HSBM 0x00004000 /* HS: 1 iff booting */ -#define SRMMU_PCR_SSSE 0x00004000 /* SS: Coherent bus snoop enable */ -#define SRMMU_PCR_AC 0x00008000 /* SS: 1=cache non-MMU accesses */ -#define SRMMU_PCR_TC 0x00010000 /* SS: 1=cache table walks */ -#define SRMMU_PCR_MID 0x00078000 /* HS: MBus module ID MID<3:0> */ -#define SRMMU_PCR_WBE 0x00080000 /* HS: Write buffer enable */ -#define SRMMU_PCR_HSSE 0x00100000 /* HS: Coherent bus snoop enable */ -#define SRMMU_PCR_CWR 0x00200000 /* HS: Cache wrap enable */ + +/* + * [4m] Bits in SRMMU control register. One set per module. + */ +#define VIKING_PCR_ME 0x00000001 /* MMU Enable */ +#define VIKING_PCR_NF 0x00000002 /* Fault inhibit bit */ +#define VIKING_PCR_PSO 0x00000080 /* Partial Store Ordering enable */ +#define VIKING_PCR_DCE 0x00000100 /* Data cache enable bit */ +#define VIKING_PCR_ICE 0x00000200 /* SuperSPARC instr. cache enable */ +#define VIKING_PCR_SB 0x00000400 /* Store buffer enable bit */ +#define VIKING_PCR_MB 0x00000800 /* MBus mode: 0=MXCC, 1=no MXCC */ +#define VIKING_PCR_PE 0x00001000 /* Enable memory parity checking */ +#define VIKING_PCR_BM 0x00002000 /* 1 iff booting */ +#define VIKING_PCR_SE 0x00004000 /* Coherent bus snoop enable */ +#define VIKING_PCR_AC 0x00008000 /* 1=cache non-MMU accesses */ +#define VIKING_PCR_TC 0x00010000 /* 1=cache table walks */ + +#define HYPERSPARC_PCR_ME 0x00000001 /* MMU Enable */ +#define HYPERSPARC_PCR_NF 0x00000002 /* Fault inhibit bit */ +#define HYPERSPARC_PCR_CE 0x00000100 /* Cache enable bit */ +#define HYPERSPARC_PCR_CM 0x00000400 /* Cache mode: 1=write-back */ +#define HYPERSPARC_PCR_MR 0x00000800 /* Memory reflection: 1 = on */ +#define HYPERSPARC_PCR_CS 0x00001000 /* cache size: 1=256k, 0=128k */ +#define HYPERSPARC_PCR_C 0x00002000 /* enable cache when MMU off */ +#define HYPERSPARC_PCR_BM 0x00004000 /* 1 iff booting */ +#define HYPERSPARC_PCR_MID 0x00078000 /* MBus module ID MID<3:0> */ +#define HYPERSPARC_PCR_WBE 0x00080000 /* Write buffer enable */ +#define HYPERSPARC_PCR_SE 0x00100000 /* Coherent bus snoop enable */ +#define HYPERSPARC_PCR_CWR 0x00200000 /* Cache wrap enable */ + +#define CYPRESS_PCR_ME 0x00000001 /* MMU Enable */ +#define CYPRESS_PCR_NF 0x00000002 /* Fault inhibit bit */ +#define CYPRESS_PCR_CE 0x00000100 /* Cache enable bit */ +#define CYPRESS_PCR_CL 0x00000200 /* Cache Lock (604 only) */ +#define CYPRESS_PCR_CM 0x00000400 /* Cache mode: 1=write-back */ +#define CYPRESS_PCR_MR 0x00000800 /* Memory reflection: 1=on (605 only) */ +#define CYPRESS_PCR_C 0x00002000 /* enable cache when MMU off */ +#define CYPRESS_PCR_BM 0x00004000 /* 1 iff booting */ +#define CYPRESS_PCR_MID 0x00078000 /* MBus module ID MID<3:0> (605 only) */ +#define CYPRESS_PCR_MV 0x00080000 /* Multichip Valid */ +#define CYPRESS_PCR_MCM 0x00300000 /* Multichip Mask */ +#define CYPRESS_PCR_MCA 0x00c00000 /* Multichip Address */ + +#define MS1_PCR_ME 0x00000001 /* MMU Enable */ +#define MS1_PCR_NF 0x00000002 /* Fault inhibit bit */ +#define MS1_PCR_DCE 0x00000100 /* Data cache enable */ +#define MS1_PCR_ICE 0x00000200 /* Instruction cache enable */ +#define MS1_PCR_RC 0x00000c00 /* DRAM Refresh control */ +#define MS1_PCR_PE 0x00001000 /* Enable memory parity checking */ +#define MS1_PCR_BM 0x00004000 /* 1 iff booting */ +#define MS1_PCR_AC 0x00008000 /* 1=cache if ME==0 (and [ID]CE on) */ +#define MS1_PCR_ID 0x00010000 /* 1=disable ITBR */ +#define MS1_PCR_PC 0x00020000 /* Parity control: 0=even,1=odd */ +#define MS1_PCR_MV 0x00100000 /* Memory data View (diag) */ +#define MS1_PCR_DV 0x00200000 /* Data View (diag) */ +#define MS1_PCR_AV 0x00400000 /* Address View (diag) */ +#define MS1_PCR_STW 0x00800000 /* Software Tablewalk enable */ + +#define SWIFT_PCR_ME 0x00000001 /* MMU Enable */ +#define SWIFT_PCR_NF 0x00000002 /* Fault inhibit bit */ +#define SWIFT_PCR_DCE 0x00000100 /* Data cache enable */ +#define SWIFT_PCR_ICE 0x00000200 /* Instruction cache enable */ +#define SWIFT_PCR_RC 0x00003c00 /* DRAM Refresh control */ +#define SWIFT_PCR_BM 0x00004000 /* 1 iff booting */ +#define SWIFT_PCR_AC 0x00008000 /* 1=cache if ME=0 (and [ID]CE on) */ +#define SWIFT_PCR_PA 0x00010000 /* TCX/SX control */ +#define SWIFT_PCR_PC 0x00020000 /* Parity control: 0=even,1=odd */ +#define SWIFT_PCR_PE 0x00040000 /* Enable memory parity checking */ +#define SWIFT_PCR_PMC 0x00180000 /* Page mode control */ +#define SWIFT_PCR_BF 0x00200000 /* Branch Folding */ +#define SWIFT_PCR_WP 0x00400000 /* Watch point enable */ +#define SWIFT_PCR_STW 0x00800000 /* Software Tablewalk enable */ + +#define TURBOSPARC_PCR_ME 0x00000001 /* MMU Enable */ +#define TURBOSPARC_PCR_NF 0x00000002 /* Fault inhibit bit */ +#define TURBOSPARC_PCR_ICS 0x00000004 /* I-cache snoop enable */ +#define TURBOSPARC_PCR_PSO 0x00000008 /* Partial Store order (ro!) */ +#define TURBOSPARC_PCR_DCE 0x00000100 /* Data cache enable */ +#define TURBOSPARC_PCR_ICE 0x00000200 /* Instruction cache enable */ +#define TURBOSPARC_PCR_RC 0x00003c00 /* DRAM Refresh control */ +#define TURBOSPARC_PCR_BM 0x00004000 /* 1 iff booting */ +#define TURBOSPARC_PCR_PC 0x00020000 /* Parity ctrl: 0=even,1=odd */ +#define TURBOSPARC_PCR_PE 0x00040000 /* Enable parity checking */ +#define TURBOSPARC_PCR_PMC 0x00180000 /* Page mode control */ + +/* The Turbosparc's Processor Configuration Register */ +#define TURBOSPARC_PCFG_SCC 0x00000007 /* e-cache config */ +#define TURBOSPARC_PCFG_SE 0x00000008 /* e-cache enable */ +#define TURBOSPARC_PCFG_US2 0x00000010 /* microsparc II compat */ +#define TURBOSPARC_PCFG_WT 0x00000020 /* write-through enable */ +#define TURBOSPARC_PCFG_SBC 0x000000c0 /* SBus Clock */ +#define TURBOSPARC_PCFG_WS 0x03800000 /* DRAM wait states */ +#define TURBOSPARC_PCFG_RAH 0x0c000000 /* DRAM Row Address Hold */ +#define TURBOSPARC_PCFG_AXC 0x30000000 /* AFX Clock */ +#define TURBOSPARC_PCFG_SNP 0x40000000 /* DVMA Snoop enable */ +#define TURBOSPARC_PCFG_IOCLK 0x80000000 /* I/O clock ratio */ + + +/* Implementation and Version fields are common to all modules */ #define SRMMU_PCR_VER 0x0f000000 /* Version of MMU implementation */ #define SRMMU_PCR_IMPL 0xf0000000 /* Implementation number of MMU */ -#ifdef notyet -#define SRMMU_PCR_INITIAL (SRMMU_PCR_ME | SRMMU_PCR_TC) -#endif /* [4m] Bits in the Synchronous Fault Status Register */ #define SFSR_EM 0x00020000 /* Error mode watchdog reset occurred */ diff --git a/sys/arch/sparc/include/db_machdep.h b/sys/arch/sparc/include/db_machdep.h index b6028854359..f47524d9e80 100644 --- a/sys/arch/sparc/include/db_machdep.h +++ b/sys/arch/sparc/include/db_machdep.h @@ -1,4 +1,5 @@ -/* $NetBSD: db_machdep.h,v 1.7 1996/03/31 22:21:28 pk Exp $ */ +/* $OpenBSD: db_machdep.h,v 1.4 1997/08/08 08:26:13 downsj Exp $ */ +/* $NetBSD: db_machdep.h,v 1.9 1997/06/26 01:27:00 thorpej Exp $ */ /* * Mach Operating System @@ -43,7 +44,7 @@ /* end of mangling */ typedef vm_offset_t db_addr_t; /* address - unsigned */ -typedef int db_expr_t; /* expression - signed */ +typedef long db_expr_t; /* expression - signed */ typedef struct { struct trapframe ddb_tf; @@ -55,7 +56,11 @@ db_regs_t ddb_regs; /* register state */ #define DDB_TF (&ddb_regs.ddb_tf) #define DDB_FR (&ddb_regs.ddb_fr) +#if defined(lint) +#define PC_REGS(regs) ((regs)->ddb_tf.tf_pc) +#else #define PC_REGS(regs) ((db_addr_t)(regs)->ddb_tf.tf_pc) +#endif #define BKPT_INST 0x91d02001 /* breakpoint instruction */ #define BKPT_SIZE (4) /* size of breakpoint inst */ @@ -78,5 +83,9 @@ db_regs_t ddb_regs; /* register state */ void db_machine_init __P((void)); int kdb_trap __P((int, struct trapframe *)); +/* + * We use a.out symbols in DDB. + */ +#define DB_AOUT_SYMBOLS #endif /* _SPARC_DB_MACHDEP_H_ */ diff --git a/sys/arch/sparc/include/eeprom.h b/sys/arch/sparc/include/eeprom.h index 298e0baef11..89603af32bf 100644 --- a/sys/arch/sparc/include/eeprom.h +++ b/sys/arch/sparc/include/eeprom.h @@ -1,8 +1,9 @@ -/* $OpenBSD: eeprom.h,v 1.6 1996/08/16 16:28:25 ccappuc Exp $ */ +/* $OpenBSD: eeprom.h,v 1.7 1997/08/08 08:26:14 downsj Exp $ */ /* * Copyright (c) 1995 Theo de Raadt * All rights reserved. + * Portions Copyright (c) 1997, Jason Downs. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -361,4 +362,30 @@ struct eeprom { #ifdef _KERNEL extern char *eeprom_va; int eeprom_uio __P((struct uio *)); + +/* + * Compatibility defines with NetBSD's eeprom.h. + * + * The goal here is to provide enough compatibility for kernel drivers to + * compile without changes; not to make userland utilities compile. Userland + * should use the native interface. + */ +#define EE_CONS_BW EED_CONS_BW +#define EE_CONS_TTYA EED_CONS_TTYA +#define EE_CONS_TTYB EED_CONS_TTYB +#define EE_CONS_COLOR EED_CONS_COLOR +#define EE_CONS_P4OPT EED_CONS_P4 + +#define EE_SCR_1152X900 EED_SCR_1152X900 +#define EE_SCR_1024X1024 EED_SCR_1024X1024 +#define EE_SCR_1600X1280 EED_SCR_1600X1280 +#define EE_SCR_1440X1440 EED_SCR_1440X1440 +#define EE_SCR_640X480 EED_SCR_640X480 +#define EE_SCR_1280X1024 EED_SCR_1280X1024 + +#define eeConsole ee_diag.eed_console +#define eeTtyRows ee_diag.eed_rowsize +#define eeTtyCols ee_diag.eed_colsize +#define eeScreenSize ee_diag.eed_scrsize + #endif /* _KERNEL */ diff --git a/sys/arch/sparc/include/endian.h b/sys/arch/sparc/include/endian.h index c536790f9ef..302cc658d93 100644 --- a/sys/arch/sparc/include/endian.h +++ b/sys/arch/sparc/include/endian.h @@ -1,5 +1,5 @@ -/* $OpenBSD: endian.h,v 1.6 1997/06/25 12:41:42 grr Exp $ */ -/* $NetBSD: endian.h,v 1.3 1996/02/13 17:04:58 christos Exp $ */ +/* $OpenBSD: endian.h,v 1.7 1997/08/08 08:26:15 downsj Exp $ */ +/* $NetBSD: endian.h,v 1.6 1996/10/11 00:43:00 christos Exp $ */ /* * Copyright (c) 1987, 1991 Regents of the University of California. @@ -87,10 +87,10 @@ __END_DECLS #else -#define NTOHL(x) (x) = ntohl((u_int32_t)x) -#define NTOHS(x) (x) = ntohs((u_int16_t)x) -#define HTONL(x) (x) = htonl((u_int32_t)x) -#define HTONS(x) (x) = htons((u_int16_t)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 /* _MACHINE_ENDIAN_H_ */ diff --git a/sys/arch/sparc/include/exec.h b/sys/arch/sparc/include/exec.h index b4c3925fd48..520345dbe10 100644 --- a/sys/arch/sparc/include/exec.h +++ b/sys/arch/sparc/include/exec.h @@ -1,3 +1,4 @@ +/* $OpenBSD: exec.h,v 1.7 1997/08/08 08:26:16 downsj Exp $ */ /* $NetBSD: exec.h,v 1.7 1994/11/20 20:53:02 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/include/fbio.h b/sys/arch/sparc/include/fbio.h index 2eddc2b5d69..babb49dea1b 100644 --- a/sys/arch/sparc/include/fbio.h +++ b/sys/arch/sparc/include/fbio.h @@ -1,4 +1,5 @@ -/* $NetBSD: fbio.h,v 1.4 1996/03/31 22:21:31 pk Exp $ */ +/* $OpenBSD: fbio.h,v 1.3 1997/08/08 08:26:17 downsj Exp $ */ +/* $NetBSD: fbio.h,v 1.5 1996/09/30 23:45:11 abrown Exp $ */ /* * Copyright (c) 1992 Regents of the University of California. @@ -66,10 +67,12 @@ #define FBTYPE_RESERVED5 15 /* reserved, do not use */ #define FBTYPE_RESERVED4 16 /* reserved, do not use */ #define FBTYPE_RESERVED3 17 /* reserved, do not use */ -#define FBTYPE_RESERVED2 18 /* reserved, do not use */ -#define FBTYPE_RESERVED1 19 /* reserved, do not use */ +#define FBTYPE_SUNGP3 17 /* cg12 running gpsi microcode */ +#define FBTYPE_SUNGT 18 /* gt graphics accelerator */ +#define FBTYPE_SUNLEO 19 /* zx graphics accelerator */ +#define FBTYPE_MDICOLOR 20 /* cgfourteen framebuffer */ -#define FBTYPE_LASTPLUSONE 20 /* max number of fbs (change as add) */ +#define FBTYPE_LASTPLUSONE 21 /* max number of fbs (change as add) */ /* * Frame buffer descriptor as returned by FBIOGTYPE. diff --git a/sys/arch/sparc/include/fbvar.h b/sys/arch/sparc/include/fbvar.h index d5f3e8855c5..75117be959c 100644 --- a/sys/arch/sparc/include/fbvar.h +++ b/sys/arch/sparc/include/fbvar.h @@ -1,4 +1,5 @@ -/* $NetBSD: fbvar.h,v 1.7 1996/02/27 22:09:39 thorpej Exp $ */ +/* $OpenBSD: fbvar.h,v 1.3 1997/08/08 08:26:18 downsj Exp $ */ +/* $NetBSD: fbvar.h,v 1.9 1997/07/07 23:31:30 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -93,7 +94,10 @@ void fb_attach __P((struct fbdevice *, int)); void fb_setsize __P((struct fbdevice *, int, int, int, int, int)); #ifdef RASTERCONSOLE void fbrcons_init __P((struct fbdevice *)); +int fbrcons_rows __P((void)); +int fbrcons_cols __P((void)); #endif + #if defined(SUN4) int fb_pfour_id __P((void *)); int fb_pfour_get_video __P((struct fbdevice *)); diff --git a/sys/arch/sparc/include/float.h b/sys/arch/sparc/include/float.h index eadcad4d141..8a724573044 100644 --- a/sys/arch/sparc/include/float.h +++ b/sys/arch/sparc/include/float.h @@ -1,4 +1,5 @@ -/* $NetBSD: float.h,v 1.5 1995/06/20 20:45:53 jtc Exp $ */ +/* $OpenBSD: float.h,v 1.3 1997/08/08 08:26:19 downsj Exp $ */ +/* $NetBSD: float.h,v 1.6 1997/07/18 05:11:52 thorpej Exp $ */ /* * Copyright (c) 1992, 1993 @@ -50,7 +51,7 @@ #include <sys/cdefs.h> __BEGIN_DECLS -int __flt_rounds __P((void)); +int __flt_rounds __P((void)); __END_DECLS #define FLT_RADIX 2 /* b */ diff --git a/sys/arch/sparc/include/frame.h b/sys/arch/sparc/include/frame.h index bc72dfff806..8313eacf8b6 100644 --- a/sys/arch/sparc/include/frame.h +++ b/sys/arch/sparc/include/frame.h @@ -1,3 +1,4 @@ +/* $OpenBSD: frame.h,v 1.2 1997/08/08 08:26:20 downsj Exp $ */ /* $NetBSD: frame.h,v 1.2 1994/11/20 20:53:07 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/include/fsr.h b/sys/arch/sparc/include/fsr.h index a1d43581015..37688a35173 100644 --- a/sys/arch/sparc/include/fsr.h +++ b/sys/arch/sparc/include/fsr.h @@ -1,3 +1,4 @@ +/* $OpenBSD: fsr.h,v 1.2 1997/08/08 08:26:21 downsj Exp $ */ /* $NetBSD: fsr.h,v 1.2 1994/11/20 20:53:08 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/include/idprom.h b/sys/arch/sparc/include/idprom.h index 6d8bbe23194..1d754cb9d42 100644 --- a/sys/arch/sparc/include/idprom.h +++ b/sys/arch/sparc/include/idprom.h @@ -1,4 +1,5 @@ -/* $NetBSD: idprom.h,v 1.4 1995/02/01 12:37:45 pk Exp $ */ +/* $OpenBSD: idprom.h,v 1.2 1997/08/08 08:26:22 downsj Exp $ */ +/* $NetBSD: idprom.h,v 1.5 1997/03/10 22:47:52 pk Exp $ */ /* * Copyright (c) 1993 Adam Glass @@ -48,4 +49,9 @@ struct idprom { char id_undef[16]; /* undefined */ }; +#define ID_SUN4_100 0x22 +#define ID_SUN4_200 0x21 +#define ID_SUN4_300 0x23 +#define ID_SUN4_400 0x24 + #define IDPROM_VERSION 1 diff --git a/sys/arch/sparc/include/ieee.h b/sys/arch/sparc/include/ieee.h index 188438c0d95..d8a2509f540 100644 --- a/sys/arch/sparc/include/ieee.h +++ b/sys/arch/sparc/include/ieee.h @@ -1,3 +1,4 @@ +/* $OpenBSD: ieee.h,v 1.2 1997/08/08 08:26:24 downsj Exp $ */ /* $NetBSD: ieee.h,v 1.2 1994/11/20 20:53:10 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/include/ieeefp.h b/sys/arch/sparc/include/ieeefp.h index a1e67846b83..eabf383ec9d 100644 --- a/sys/arch/sparc/include/ieeefp.h +++ b/sys/arch/sparc/include/ieeefp.h @@ -1,3 +1,5 @@ +/* $OpenBSD: ieeefp.h,v 1.3 1997/08/08 08:26:25 downsj Exp $ */ + /* * Written by J.T. Conklin, Apr 6, 1995 * Public domain. diff --git a/sys/arch/sparc/include/instr.h b/sys/arch/sparc/include/instr.h index 6aa7c24229d..d4b002445f3 100644 --- a/sys/arch/sparc/include/instr.h +++ b/sys/arch/sparc/include/instr.h @@ -1,4 +1,5 @@ -/* $NetBSD: instr.h,v 1.2 1994/11/20 20:53:11 deraadt Exp $ */ +/* $OpenBSD: instr.h,v 1.2 1997/08/08 08:26:26 downsj Exp $ */ +/* $NetBSD: instr.h,v 1.3 1997/03/14 23:54:07 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -244,6 +245,7 @@ union instr { u_int i_rd:5; /* destination register */ u_int i_op3:6; /* second-level decode */ u_int i_rs1:5; /* source register 1 */ + u_int i_i:1; /* immediate vs asi */ u_int i_asi:8; /* asi */ u_int i_rs2:5; /* source register 2 */ } i_asi; diff --git a/sys/arch/sparc/include/kbd.h b/sys/arch/sparc/include/kbd.h index 4cabc471287..74279bcb80d 100644 --- a/sys/arch/sparc/include/kbd.h +++ b/sys/arch/sparc/include/kbd.h @@ -1,3 +1,4 @@ +/* $OpenBSD: kbd.h,v 1.3 1997/08/08 08:26:27 downsj Exp $ */ /* $NetBSD: kbd.h,v 1.6 1996/03/31 22:21:35 pk Exp $ */ /* diff --git a/sys/arch/sparc/include/kbio.h b/sys/arch/sparc/include/kbio.h index 049bfb79fed..ff54ac3c701 100644 --- a/sys/arch/sparc/include/kbio.h +++ b/sys/arch/sparc/include/kbio.h @@ -1,3 +1,4 @@ +/* $OpenBSD: kbio.h,v 1.4 1997/08/08 08:26:28 downsj Exp $ */ /* $NetBSD: kbio.h,v 1.4 1995/05/10 16:07:27 pk Exp $ */ /* diff --git a/sys/arch/sparc/include/limits.h b/sys/arch/sparc/include/limits.h index 172e9a95d3a..d84ff6cff25 100644 --- a/sys/arch/sparc/include/limits.h +++ b/sys/arch/sparc/include/limits.h @@ -1,3 +1,4 @@ +/* $OpenBSD: limits.h,v 1.4 1997/08/08 08:26:30 downsj Exp $ */ /* $NetBSD: limits.h,v 1.7 1996/01/05 18:10:57 pk Exp $ */ /* @@ -35,9 +36,6 @@ * @(#)limits.h 8.3 (Berkeley) 1/4/94 */ -#ifndef _MACHINE_LIMITS_H_ -#define _MACHINE_LIMITS_H_ - #define CHAR_BIT 8 /* number of bits in a char */ #define MB_LEN_MAX 1 /* no multibyte characters */ @@ -87,5 +85,3 @@ #define FLT_MAX 3.40282347E+38F #define FLT_MIN 1.17549435E-38F #endif - -#endif /* _MACHINE_LIMITS_H_ */ diff --git a/sys/arch/sparc/include/oldmon.h b/sys/arch/sparc/include/oldmon.h index d18a256f05c..ce1ee9dc0b5 100644 --- a/sys/arch/sparc/include/oldmon.h +++ b/sys/arch/sparc/include/oldmon.h @@ -1,3 +1,4 @@ +/* $OpenBSD: oldmon.h,v 1.4 1997/08/08 08:26:32 downsj Exp $ */ /* $NetBSD: oldmon.h,v 1.11 1996/03/31 22:21:38 pk Exp $ */ /* diff --git a/sys/arch/sparc/include/openpromio.h b/sys/arch/sparc/include/openpromio.h index 748f0fa3cd2..fb50a2b8268 100644 --- a/sys/arch/sparc/include/openpromio.h +++ b/sys/arch/sparc/include/openpromio.h @@ -1,3 +1,4 @@ +/* $OpenBSD: openpromio.h,v 1.2 1997/08/08 08:26:35 downsj Exp $ */ /* $NetBSD: openpromio.h,v 1.2 1994/11/20 20:53:17 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/include/param.h b/sys/arch/sparc/include/param.h index 8754188b97c..34573d970f4 100644 --- a/sys/arch/sparc/include/param.h +++ b/sys/arch/sparc/include/param.h @@ -1,4 +1,5 @@ -/* $NetBSD: param.h,v 1.24 1996/05/15 02:13:48 mrg Exp $ */ +/* $OpenBSD: param.h,v 1.6 1997/08/08 08:26:36 downsj Exp $ */ +/* $NetBSD: param.h,v 1.29 1997/03/10 22:50:37 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -64,41 +65,29 @@ * Round p (pointer or byte index) up to a correctly-aligned value for * the machine's strictest data type. The result is u_int and must be * cast to any desired pointer type. + * + * ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + * */ -#define ALIGNBYTES 7 -#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) & ~ALIGNBYTES) +#define ALIGNBYTES 7 +#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) & ~ALIGNBYTES) +#define ALIGNED_POINTER(p,t) ((((u_long)(p)) & (sizeof(t)-1)) == 0) #define SUN4_PGSHIFT 13 /* for a sun4 machine */ #define SUN4CM_PGSHIFT 12 /* for a sun4c or sun4m machine */ /* - * Three possible cases: - * sun4 only 8192 bytes/page - * sun4c/sun4m only 4096 bytes/page - * sun4/sun4c/sun4m either of the above - * - * In the later case NBPG, PGOFSET, and PGSHIFT are encoded in variables - * initialized early in locore.s. Since they are variables, rather than - * simple constants, the kernel will not perform slighly worse. + * The following variables are always defined and initialized (in locore) + * so independently compiled modules (e.g. LKMs) can be used irrespective + * of the `options SUN4?' combination a particular kernel was configured with. + * See also the definitions of NBPG, PGOFSET and PGSHIFT below. */ -#if defined(SUN4) && !defined(SUN4C) && !defined(SUN4M) -#define NBPG 8192 /* bytes/page */ -#define PGOFSET (NBPG-1) /* byte offset into page */ -#define PGSHIFT SUN4_PGSHIFT /* log2(NBPG) */ -#endif -#if !defined(SUN4) && (defined(SUN4C) || defined(SUN4M)) -#define NBPG 4096 /* bytes/page */ -#define PGOFSET (NBPG-1) /* byte offset into page */ -#define PGSHIFT SUN4CM_PGSHIFT /* log2(NBPG) */ -#endif -#if defined(SUN4) && (defined(SUN4C) || defined(SUN4M)) #if defined(_KERNEL) && !defined(_LOCORE) extern int nbpg, pgofset, pgshift; #endif -#define NBPG nbpg /* bytes/page */ -#define PGOFSET pgofset /* byte offset into page */ -#define PGSHIFT pgshift /* log2(NBPG) */ -#endif #define KERNBASE 0xf8000000 /* start of kernel virtual space */ #define KERNTEXTOFF 0xf8004000 /* start of kernel text */ @@ -123,8 +112,8 @@ extern int nbpg, pgofset, pgshift; * of the hardware page size. */ #define MSIZE 128 /* size of an mbuf */ +#define MCLBYTES 2048 /* enough for whole Ethernet packet */ #define MCLSHIFT 11 /* log2(MCLBYTES) */ -#define MCLBYTES (1 << MCLSHIFT) /* enough for whole Ethernet packet */ #define MCLOFSET (MCLBYTES - 1) #ifndef NMBCLUSTERS @@ -192,8 +181,10 @@ extern void delay __P((unsigned int)); #define DELAY(n) delay(n) extern int cputyp; +#if 0 extern int cpumod; extern int mmumod; +#endif #endif /* _LOCORE */ #endif /* _KERNEL */ @@ -204,31 +195,19 @@ extern int mmumod; #define CPU_SUN4 0 #define CPU_SUN4C 1 #define CPU_SUN4M 2 -/* - * Values for cpumod (cpu model) variable. XXX currently valid only for sun4 - * or Sun4M - */ -#define SUN4_100 0x22 -#define SUN4_200 0x21 -#define SUN4_300 0x23 -#define SUN4_400 0x24 -#define SUN4M_MS 0x04 /* MicroSPARC-II */ -#define SUN4M_SS 0x40 /* Generic SuperSPARC */ -#define SUN4M_HS 0x10 /* Generic ROSS sparc product (HyperSPARC) */ -#define SUN4M_RT620 0x1f /* Ross HyperSPARC RT620 */ -#define SUN4M_STP1020N 0x41 /* TI SuperSPARC STP1020N */ -#define SUN4M_STP1020P 0x40 /* TI SuperSPARC STP1020P */ -#define SUN4M_STP1020A 0x40 /* TI SuperSPARC STP1020A */ - -/* Values for mmumod (mmu model) variable. Valid only for Sun4M */ -#define SUN4M_MMU_HS 0x1 /* ROSS HyperSparc */ -#define SUN4M_MMU_SS 0x0 /* TI SuperSPARC */ -#define SUN4M_MMU_MS1 0x4 /* MicroSPARC-I (??? XXX) */ -#define SUN4M_MMU_MS 0x0 /* MicroSPARC-II (ugh, conflicts w/SS) */ /* * Shorthand CPU-type macros. Enumerate all eight cases. * Let compiler optimize away code conditional on constants. + * + * On a sun4 machine, the page size is 8192, while on a sun4c and sun4m + * it is 4096. Therefore, in the (SUN4 && (SUN4C || SUN4M)) cases below, + * NBPG, PGOFSET and PGSHIFT are defined as variables which are initialized + * early in locore.s after the machine type has been detected. + * + * Note that whenever the macros defined below evaluate to expressions + * involving variables, the kernel will perform slighly worse due to the + * extra memory references they'll generate. */ #if defined(SUN4M) && defined(SUN4C) && defined(SUN4) # define CPU_ISSUN4M (cputyp == CPU_SUN4M) @@ -236,46 +215,70 @@ extern int mmumod; # define CPU_ISSUN4 (cputyp == CPU_SUN4) # define CPU_ISSUN4OR4C (cputyp == CPU_SUN4 || cputyp == CPU_SUN4C) # define CPU_ISSUN4COR4M (cputyp == CPU_SUN4C || cputyp == CPU_SUN4M) +# define NBPG nbpg +# define PGOFSET pgofset +# define PGSHIFT pgshift #elif defined(SUN4M) && defined(SUN4C) && !defined(SUN4) # define CPU_ISSUN4M (cputyp == CPU_SUN4M) # define CPU_ISSUN4C (cputyp == CPU_SUN4C) # define CPU_ISSUN4 (0) # define CPU_ISSUN4OR4C (cputyp == CPU_SUN4C) # define CPU_ISSUN4COR4M (cputyp == CPU_SUN4C || cputyp == CPU_SUN4M) +# define NBPG 4096 +# define PGOFSET (NBPG-1) +# define PGSHIFT SUN4CM_PGSHIFT #elif defined(SUN4M) && !defined(SUN4C) && defined(SUN4) # define CPU_ISSUN4M (cputyp == CPU_SUN4M) # define CPU_ISSUN4C (0) # define CPU_ISSUN4 (cputyp == CPU_SUN4) # define CPU_ISSUN4OR4C (cputyp == CPU_SUN4) # define CPU_ISSUN4COR4M (cputyp == CPU_SUN4M) +# define NBPG nbpg +# define PGOFSET pgofset +# define PGSHIFT pgshift #elif defined(SUN4M) && !defined(SUN4C) && !defined(SUN4) # define CPU_ISSUN4M (1) # define CPU_ISSUN4C (0) # define CPU_ISSUN4 (0) # define CPU_ISSUN4OR4C (0) # define CPU_ISSUN4COR4M (1) +# define NBPG 4096 +# define PGOFSET (NBPG-1) +# define PGSHIFT SUN4CM_PGSHIFT #elif !defined(SUN4M) && defined(SUN4C) && defined(SUN4) # define CPU_ISSUN4M (0) # define CPU_ISSUN4C (cputyp == CPU_SUN4C) # define CPU_ISSUN4 (cputyp == CPU_SUN4) # define CPU_ISSUN4OR4C (1) # define CPU_ISSUN4COR4M (cputyp == CPU_SUN4C) +# define NBPG nbpg +# define PGOFSET pgofset +# define PGSHIFT pgshift #elif !defined(SUN4M) && defined(SUN4C) && !defined(SUN4) # define CPU_ISSUN4M (0) # define CPU_ISSUN4C (1) # define CPU_ISSUN4 (0) # define CPU_ISSUN4OR4C (1) # define CPU_ISSUN4COR4M (1) +# define NBPG 4096 +# define PGOFSET (NBPG-1) +# define PGSHIFT SUN4CM_PGSHIFT #elif !defined(SUN4M) && !defined(SUN4C) && defined(SUN4) # define CPU_ISSUN4M (0) # define CPU_ISSUN4C (0) # define CPU_ISSUN4 (1) # define CPU_ISSUN4OR4C (1) # define CPU_ISSUN4COR4M (0) +# define NBPG 8192 +# define PGOFSET (NBPG-1) +# define PGSHIFT SUN4_PGSHIFT #elif !defined(SUN4M) && !defined(SUN4C) && !defined(SUN4) -# define CPU_ISSUN4M (0) -# define CPU_ISSUN4C (0) -# define CPU_ISSUN4 (0) -# define CPU_ISSUN4OR4C (0) -# define CPU_ISSUN4COR4M (0) +# define CPU_ISSUN4M (cputyp == CPU_SUN4M) +# define CPU_ISSUN4C (cputyp == CPU_SUN4C) +# define CPU_ISSUN4 (cputyp == CPU_SUN4) +# define CPU_ISSUN4OR4C (cputyp == CPU_SUN4 || cputyp == CPU_SUN4C) +# define CPU_ISSUN4COR4M (cputyp == CPU_SUN4C || cputyp == CPU_SUN4M) +# define NBPG nbpg +# define PGOFSET pgofset +# define PGSHIFT pgshift #endif diff --git a/sys/arch/sparc/include/pcb.h b/sys/arch/sparc/include/pcb.h index 3692dd17d96..e3450eabe3c 100644 --- a/sys/arch/sparc/include/pcb.h +++ b/sys/arch/sparc/include/pcb.h @@ -1,3 +1,4 @@ +/* $OpenBSD: pcb.h,v 1.2 1997/08/08 08:26:37 downsj Exp $ */ /* $NetBSD: pcb.h,v 1.4 1995/03/28 18:19:56 jtc Exp $ */ /* diff --git a/sys/arch/sparc/include/pmap.h b/sys/arch/sparc/include/pmap.h index 90e5f8d26ca..8e66fd2e655 100644 --- a/sys/arch/sparc/include/pmap.h +++ b/sys/arch/sparc/include/pmap.h @@ -1,4 +1,5 @@ -/* $NetBSD: pmap.h,v 1.22.4.1 1996/06/12 20:29:01 pk Exp $ */ +/* $OpenBSD: pmap.h,v 1.5 1997/08/08 08:26:38 downsj Exp $ */ +/* $NetBSD: pmap.h,v 1.29 1997/07/06 23:57:16 pk Exp $ */ /* * Copyright (c) 1996 @@ -138,7 +139,7 @@ TAILQ_HEAD(mmuhd,mmuentry); struct pmap { union ctxinfo *pm_ctx; /* current context, if any */ int pm_ctxnum; /* current context's number */ -#if NCPUS > 1 +#if 0 simple_lock_data_t pm_lock; /* spinlock */ #endif int pm_refcount; /* just what it says */ @@ -203,14 +204,27 @@ extern vm_offset_t vm_first_phys, vm_num_phys; #define PMAP_VME16 2 /* etc */ #define PMAP_VME32 3 /* etc */ #define PMAP_NC 4 /* tells pmap_enter to set PG_NC */ +#define PMAP_TNC_4 7 /* mask to get PG_TYPE & PG_NC */ + +#define PMAP_T2PTE_4(x) (((x) & PMAP_TNC_4) << PG_TNC_SHIFT) +#define PMAP_IOENC_4(io) (io) + +/* + * On a SRMMU machine, the iospace is encoded in bits [3-6] of the + * physical address passed to pmap_enter(). + */ +#define PMAP_TYPE_SRMMU 0x78 /* mask to get 4m page type */ +#define PMAP_PTESHFT_SRMMU 25 /* right shift to put type in pte */ +#define PMAP_SHFT_SRMMU 3 /* left shift to extract iospace */ +#define PMAP_TNC_SRMMU 127 /* mask to get PG_TYPE & PG_NC */ -#define PMAP_TYPE4M 0x78 /* mask to get 4m page type */ -#define PMAP_PTESHFT4M 25 /* right shift to put type in pte */ -#define PMAP_SHFT4M 0x3 /* left shift to extract type */ -#define PMAP_TNC \ - (CPU_ISSUN4M?127:7) /* mask to get PG_TYPE & PG_NC */ /*#define PMAP_IOC 0x00800000 -* IO cacheable, NOT shifted */ +#define PMAP_T2PTE_SRMMU(x) (((x) & PMAP_TYPE_SRMMU) << PMAP_PTESHFT_SRMMU) +#define PMAP_IOENC_SRMMU(io) ((io) << PMAP_SHFT_SRMMU) + +/* Encode IO space for pmap_enter() */ +#define PMAP_IOENC(io) (CPU_ISSUN4M ? PMAP_IOENC_SRMMU(io) : PMAP_IOENC_4(io)) #if xxx void pmap_bootstrap __P((int nmmu, int nctx, int nregion)); @@ -264,9 +278,9 @@ void pmap_redzone __P((void)); void kvm_uncache __P((caddr_t, int)); struct user; void switchexit __P((vm_map_t, struct user *, int)); -int mmu_pagein __P((struct pmap *pm, vm_offset_t, int)); +int mmu_pagein __P((struct pmap *pm, int, int)); #ifdef DEBUG -int mmu_pagein4m __P((struct pmap *pm, vm_offset_t, int)); +int mmu_pagein4m __P((struct pmap *pm, int, int)); #endif diff --git a/sys/arch/sparc/include/proc.h b/sys/arch/sparc/include/proc.h index ff2b7b5805d..dc4b3629af1 100644 --- a/sys/arch/sparc/include/proc.h +++ b/sys/arch/sparc/include/proc.h @@ -1,4 +1,5 @@ -/* $NetBSD: proc.h,v 1.2 1994/11/20 20:53:23 deraadt Exp $ */ +/* $OpenBSD: proc.h,v 1.2 1997/08/08 08:26:39 downsj Exp $ */ +/* $NetBSD: proc.h,v 1.3 1996/09/26 18:51:17 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -50,4 +51,8 @@ struct mdproc { struct trapframe *md_tf; /* trap/syscall registers */ struct fpstate *md_fpstate; /* fpu state, if any; always resident */ + u_long md_flags; }; + +/* md_flags */ +#define MDP_FIXALIGN 0x1 /* Fix unaligned memory accesses */ diff --git a/sys/arch/sparc/include/profile.h b/sys/arch/sparc/include/profile.h index 0a27b368163..13af168d2f3 100644 --- a/sys/arch/sparc/include/profile.h +++ b/sys/arch/sparc/include/profile.h @@ -1,4 +1,5 @@ -/* $NetBSD: profile.h,v 1.6 1996/04/08 20:55:36 pk Exp $ */ +/* $OpenBSD: profile.h,v 1.4 1997/08/08 08:26:40 downsj Exp $ */ +/* $NetBSD: profile.h,v 1.8 1997/02/01 20:56:40 mrg Exp $ */ /* * Copyright (c) 1992, 1993 @@ -47,26 +48,25 @@ #ifdef PIC /* Inline expansion of PICCY_SET() (see <machine/asm.h>). */ #define MCOUNT \ - asm(".global mcount");\ - asm("mcount:");\ - asm("add %o7, 8, %o1");\ - asm("1: call 2f; nop; 2:");\ - asm("add %o7,__mcount-1b, %o2");\ - asm("ld [%o2], %o2");\ - asm("jmpl %o2, %g0");\ - asm("add %i7, 8, %o0"); + __asm__(".global mcount");\ + __asm__("mcount:");\ + __asm__("add %o7, 8, %o1");\ + __asm__("1: call 2f; nop; 2:");\ + __asm__("add %o7,__mcount-1b, %o2");\ + __asm__("ld [%o2], %o2");\ + __asm__("jmpl %o2, %g0");\ + __asm__("add %i7, 8, %o0"); #else #define MCOUNT \ - asm(".global mcount");\ - asm("mcount:");\ - asm("add %i7, 8, %o0");\ - asm("sethi %hi(__mcount), %o2");\ - asm("jmpl %o2 + %lo(__mcount), %g0");\ - asm("add %o7, 8, %o1"); + __asm__(".global mcount");\ + __asm__("mcount:");\ + __asm__("add %i7, 8, %o0");\ + __asm__("sethi %hi(__mcount), %o2");\ + __asm__("jmpl %o2 + %lo(__mcount), %g0");\ + __asm__("add %o7, 8, %o1"); #endif #define _MCOUNT_DECL static void _mcount -_MCOUNT_DECL __P((unsigned long, unsigned long)); #ifdef _KERNEL /* diff --git a/sys/arch/sparc/include/psl.h b/sys/arch/sparc/include/psl.h index a93b2724348..70507bdd7ff 100644 --- a/sys/arch/sparc/include/psl.h +++ b/sys/arch/sparc/include/psl.h @@ -1,4 +1,5 @@ -/* $NetBSD: psl.h,v 1.11 1996/03/31 22:20:14 pk Exp $ */ +/* $OpenBSD: psl.h,v 1.3 1997/08/08 08:26:41 downsj Exp $ */ +/* $NetBSD: psl.h,v 1.12 1997/03/10 21:49:11 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -84,6 +85,7 @@ static __inline void setpsr __P((int)); static __inline int spl0 __P((void)); static __inline int splhigh __P((void)); static __inline void splx __P((int)); +static __inline int getmid __P((void)); /* * GCC pseudo-functions for manipulating PSR (primarily PIL field). @@ -96,6 +98,14 @@ static __inline int getpsr() return (psr); } +static __inline int getmid() +{ + int mid; + + __asm __volatile("rd %%tbr,%0" : "=r" (mid)); + return ((mid >> 20) & 0x3); +} + static __inline void setpsr(newpsr) int newpsr; { diff --git a/sys/arch/sparc/include/pte.h b/sys/arch/sparc/include/pte.h index 7418188bb85..3a7fd59a127 100644 --- a/sys/arch/sparc/include/pte.h +++ b/sys/arch/sparc/include/pte.h @@ -1,4 +1,5 @@ -/* $NetBSD: pte.h,v 1.17 1996/05/16 15:57:03 abrown Exp $ */ +/* $OpenBSD: pte.h,v 1.3 1997/08/08 08:26:42 downsj Exp $ */ +/* $NetBSD: pte.h,v 1.18 1997/05/15 22:25:45 pk Exp $ */ /* * Copyright (c) 1996 @@ -176,14 +177,10 @@ typedef u_char smeg_t; /* 8 bits needed per Sun-4 regmap entry */ * physadr = ((pte & PG_PFNUM) << PGSHIFT) | va.va_off; */ -#if defined(MMU_3L) && !defined(SUN4) +#if defined(SUN4_MMU3L) && !defined(SUN4) #error "configuration error" #endif -#if defined(MMU_3L) -extern int mmu_3l; -#endif - #define NBPRG (1 << 24) /* bytes per region */ #define RGSHIFT 24 /* log2(NBPRG) */ #define RGOFSET (NBPRG - 1) /* mask for region offset */ @@ -224,30 +221,12 @@ extern int nptesg; #define VA_ROUNDDOWNTOSEG(va) ((int)(va) & ~SGOFSET) /* virtual segment to virtual address (must sign extend on holy MMUs!) */ -#if defined(SUN4M) && !(defined(SUN4C) || defined(SUN4)) -#define VRTOVA(vr) ((int)(vr) << RGSHIFT) -#define VSTOVA(vr,vs) (((int)(vr) << RGSHIFT) + ((int)(vs) << SGSHIFT)) -#else -#if defined(MMU_3L) || defined(SUN4M) /* hairy.. */ -#if !defined(MMU_3L) -#define _PTE_HAIRY_3L_TEST (cputyp==CPU_SUN4M) -#elif !defined(SUN4M) -#define _PTE_HAIRY_3L_TEST (mmu_3l) -#else -#define _PTE_HAIRY_3L_TEST (mmu_3l || cputyp==CPU_SUN4M) -#endif -#define VRTOVA(vr) (_PTE_HAIRY_3L_TEST \ - ? ((int)(vr) << RGSHIFT) \ +#define VRTOVA(vr) ((CPU_ISSUN4M || HASSUN4_MMU3L) \ + ? ((int)(vr) << RGSHIFT) \ : (((int)(vr) << (RGSHIFT+2)) >> 2)) -#define VSTOVA(vr,vs) (_PTE_HAIRY_3L_TEST \ +#define VSTOVA(vr,vs) ((CPU_ISSUN4M || HASSUN4_MMU3L) \ ? (((int)(vr) << RGSHIFT) + ((int)(vs) << SGSHIFT)) \ : ((((int)(vr) << (RGSHIFT+2)) >> 2) + ((int)(vs) << SGSHIFT))) -#else -#define VRTOVA(vr) (((int)(vr) << (RGSHIFT+2)) >> 2) -#define VSTOVA(vr,vs) ((((int)(vr) << (RGSHIFT+2)) >> 2) + \ - ((int)(vs) << SGSHIFT)) -#endif -#endif extern int mmu_has_hole; #define VA_INHOLE(va) (mmu_has_hole \ diff --git a/sys/arch/sparc/include/ptrace.h b/sys/arch/sparc/include/ptrace.h index f01223f36bd..9253256060c 100644 --- a/sys/arch/sparc/include/ptrace.h +++ b/sys/arch/sparc/include/ptrace.h @@ -1,3 +1,4 @@ +/* $OpenBSD: ptrace.h,v 1.2 1997/08/08 08:26:43 downsj Exp $ */ /* $NetBSD: ptrace.h,v 1.4 1994/11/20 20:53:27 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/include/reg.h b/sys/arch/sparc/include/reg.h index 137d9aed411..ac6a9933849 100644 --- a/sys/arch/sparc/include/reg.h +++ b/sys/arch/sparc/include/reg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: reg.h,v 1.2 1997/08/08 08:26:44 downsj Exp $ */ /* $NetBSD: reg.h,v 1.4 1994/11/20 20:53:28 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/include/reloc.h b/sys/arch/sparc/include/reloc.h index 01c0104e932..b49b7c8a17f 100644 --- a/sys/arch/sparc/include/reloc.h +++ b/sys/arch/sparc/include/reloc.h @@ -1,3 +1,4 @@ +/* $OpenBSD: reloc.h,v 1.2 1997/08/08 08:26:45 downsj Exp $ */ /* $NetBSD: reloc.h,v 1.2 1994/11/20 20:53:30 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/include/remote-sl.h b/sys/arch/sparc/include/remote-sl.h index 3c48e6b451a..76498e57e87 100644 --- a/sys/arch/sparc/include/remote-sl.h +++ b/sys/arch/sparc/include/remote-sl.h @@ -1,3 +1,4 @@ +/* $OpenBSD: remote-sl.h,v 1.2 1997/08/08 08:26:47 downsj Exp $ */ /* $NetBSD: remote-sl.h,v 1.2 1994/11/20 20:53:31 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/include/setjmp.h b/sys/arch/sparc/include/setjmp.h index e224ce1e7c0..b9a28444183 100644 --- a/sys/arch/sparc/include/setjmp.h +++ b/sys/arch/sparc/include/setjmp.h @@ -1,3 +1,4 @@ +/* $OpenBSD: setjmp.h,v 1.2 1997/08/08 08:26:47 downsj Exp $ */ /* $NetBSD: setjmp.h,v 1.1 1994/12/20 10:37:10 cgd Exp $ */ /* diff --git a/sys/arch/sparc/include/signal.h b/sys/arch/sparc/include/signal.h index e8339c38520..7b575c569ef 100644 --- a/sys/arch/sparc/include/signal.h +++ b/sys/arch/sparc/include/signal.h @@ -1,3 +1,4 @@ +/* $OpenBSD: signal.h,v 1.3 1997/08/08 08:26:48 downsj Exp $ */ /* $NetBSD: signal.h,v 1.4 1996/02/01 22:32:35 mycroft Exp $ */ /* diff --git a/sys/arch/sparc/include/stdarg.h b/sys/arch/sparc/include/stdarg.h index aa2081597bf..311ec168f3f 100644 --- a/sys/arch/sparc/include/stdarg.h +++ b/sys/arch/sparc/include/stdarg.h @@ -1,4 +1,5 @@ -/* $NetBSD: stdarg.h,v 1.9 1995/12/29 18:53:01 mycroft Exp $ */ +/* $OpenBSD: stdarg.h,v 1.4 1997/08/08 08:26:50 downsj Exp $ */ +/* $NetBSD: stdarg.h,v 1.10 1996/12/27 20:55:28 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -49,6 +50,11 @@ #include <machine/ansi.h> +#ifdef __lint__ +#define __extension__(x) (0) +#define __builtin_classify_type(t) (0) +#endif + typedef _BSD_VA_LIST_ va_list; #define __va_size(type) \ diff --git a/sys/arch/sparc/include/svr4_machdep.h b/sys/arch/sparc/include/svr4_machdep.h index c7a5d303b74..a4984efdc72 100644 --- a/sys/arch/sparc/include/svr4_machdep.h +++ b/sys/arch/sparc/include/svr4_machdep.h @@ -1,3 +1,4 @@ +/* $OpenBSD: svr4_machdep.h,v 1.6 1997/08/08 08:26:50 downsj Exp $ */ /* $NetBSD: svr4_machdep.h,v 1.4 1996/03/31 22:21:45 pk Exp $ */ /* diff --git a/sys/arch/sparc/include/trap.h b/sys/arch/sparc/include/trap.h index b2cde2ecc25..793e3b2724e 100644 --- a/sys/arch/sparc/include/trap.h +++ b/sys/arch/sparc/include/trap.h @@ -1,3 +1,4 @@ +/* $OpenBSD: trap.h,v 1.4 1997/08/08 08:26:51 downsj Exp $ */ /* $NetBSD: trap.h,v 1.9 1996/05/16 15:57:04 abrown Exp $ */ /* diff --git a/sys/arch/sparc/include/types.h b/sys/arch/sparc/include/types.h index b9d0a0a6914..fa1d89d60e9 100644 --- a/sys/arch/sparc/include/types.h +++ b/sys/arch/sparc/include/types.h @@ -1,4 +1,5 @@ -/* $NetBSD: types.h,v 1.9 1996/03/14 00:48:30 pk Exp $ */ +/* $OpenBSD: types.h,v 1.5 1997/08/08 08:26:52 downsj Exp $ */ +/* $NetBSD: types.h,v 1.11 1996/12/10 23:19:38 pk Exp $ */ /* * Copyright (c) 1992, 1993 diff --git a/sys/arch/sparc/include/varargs.h b/sys/arch/sparc/include/varargs.h index 3585b7caa94..68ed7800c9b 100644 --- a/sys/arch/sparc/include/varargs.h +++ b/sys/arch/sparc/include/varargs.h @@ -1,3 +1,4 @@ +/* $OpenBSD: varargs.h,v 1.5 1997/08/08 08:26:53 downsj Exp $ */ /* $NetBSD: varargs.h,v 1.10 1995/12/29 18:53:02 mycroft Exp $ */ /* diff --git a/sys/arch/sparc/include/vmparam.h b/sys/arch/sparc/include/vmparam.h index fd578b1e95c..3f3ec56b5e0 100644 --- a/sys/arch/sparc/include/vmparam.h +++ b/sys/arch/sparc/include/vmparam.h @@ -1,4 +1,5 @@ -/* $NetBSD: vmparam.h,v 1.10 1996/03/14 19:49:20 christos Exp $ */ +/* $OpenBSD: vmparam.h,v 1.5 1997/08/08 08:26:54 downsj Exp $ */ +/* $NetBSD: vmparam.h,v 1.13 1997/07/12 16:20:03 perry Exp $ */ /* * Copyright (c) 1992, 1993 @@ -115,6 +116,10 @@ * 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. + * Update: memory prices have changed recently (9/96). At the current + * value of $6 per megabyte, we lend each swapped in process memory worth + * $0.15, or just admit that we don't consider it worthwhile and swap it out + * to disk which costs $0.20/MB, or just under half a cent. */ #define SAFERSS 4 /* nominal ``small'' resident set size protected against replacement */ diff --git a/sys/arch/sparc/include/vuid_event.h b/sys/arch/sparc/include/vuid_event.h index 0bb4e0015cc..7a3a5c14bab 100644 --- a/sys/arch/sparc/include/vuid_event.h +++ b/sys/arch/sparc/include/vuid_event.h @@ -1,3 +1,4 @@ +/* $OpenBSD: vuid_event.h,v 1.2 1997/08/08 08:26:55 downsj Exp $ */ /* $NetBSD: vuid_event.h,v 1.2 1994/11/20 20:53:39 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/sparc/asm.h b/sys/arch/sparc/sparc/asm.h index 1807c358050..534853ce491 100644 --- a/sys/arch/sparc/sparc/asm.h +++ b/sys/arch/sparc/sparc/asm.h @@ -1,4 +1,5 @@ -/* $NetBSD: asm.h,v 1.3 1994/11/20 20:53:55 deraadt Exp $ */ +/* $OpenBSD: asm.h,v 1.2 1997/08/08 08:26:58 downsj Exp $ */ +/* $NetBSD: asm.h,v 1.4 1996/07/01 18:01:26 abrown Exp $ */ /* * Copyright (c) 1992, 1993 @@ -102,3 +103,17 @@ __asm __volatile("sta %0,[%1]%2" : : \ "r" ((int)(value)), "r" ((int)(loc)), "n" (asi)); \ }) + +/* load 64-bit int from alternate address space */ +#define ldda(loc, asi) ({ \ + register long long _lda_v; \ + __asm __volatile("ldda [%1]%2,%0" : "=r" (_lda_v) : \ + "r" ((int)(loc)), "n" (asi)); \ + _lda_v; \ +}) + +/* store 64-bit int to alternate address space */ +#define stda(loc, asi, value) ({ \ + __asm __volatile("stda %0,[%1]%2" : : \ + "r" ((long long)(value)), "r" ((int)(loc)), "n" (asi)); \ +}) diff --git a/sys/arch/sparc/sparc/autoconf.c b/sys/arch/sparc/sparc/autoconf.c index e6b7a359b21..d645fdd3385 100644 --- a/sys/arch/sparc/sparc/autoconf.c +++ b/sys/arch/sparc/sparc/autoconf.c @@ -1,4 +1,5 @@ -/* $NetBSD: autoconf.c,v 1.58.2.2 1996/07/02 23:49:54 jtc Exp $ */ +/* $OpenBSD: autoconf.c,v 1.22 1997/08/08 08:27:01 downsj Exp $ */ +/* $NetBSD: autoconf.c,v 1.73 1997/07/29 09:41:53 fair Exp $ */ /* * Copyright (c) 1996 @@ -79,6 +80,7 @@ #include <machine/ctlreg.h> #include <machine/pmap.h> #include <sparc/sparc/asm.h> +#include <sparc/sparc/cpuvar.h> #include <sparc/sparc/timerreg.h> #ifdef DDB @@ -187,9 +189,6 @@ str2hex(str, vp) #ifdef SUN4 struct promvec promvecdat; struct om_vector *oldpvec = (struct om_vector *)PROM_BASE; - -struct idprom idprom; -void getidprom __P((struct idprom *, int size)); #endif /* @@ -200,7 +199,6 @@ void getidprom __P((struct idprom *, int size)); void bootstrap() { - int nregion = 0, nsegment = 0, ncontext = 0; extern int msgbufmapped; #if defined(SUN4) @@ -242,77 +240,16 @@ bootstrap() */ if (oldpvec->romvecVersion >= 2) *oldpvec->vector_cmd = oldmon_w_cmd; - getidprom(&idprom, sizeof(idprom)); - switch (cpumod = idprom.id_machine) { - case SUN4_100: - nsegment = 256; - ncontext = 8; - break; - case SUN4_200: - nsegment = 512; - ncontext = 16; - break; - case SUN4_300: - nsegment = 256; - ncontext = 16; - break; - case SUN4_400: - nsegment = 1024; - ncontext = 64; - nregion = 256; - mmu_3l = 1; - break; - default: - printf("bootstrap: sun4 machine type %2x unknown!\n", - idprom.id_machine); - callrom(); - } } #endif /* SUN4 */ -#if defined(SUN4C) - if (CPU_ISSUN4C) { - register int node = findroot(); - nsegment = getpropint(node, "mmu-npmg", 128); - ncontext = getpropint(node, "mmu-nctx", 8); - } -#endif /* SUN4C */ + bzero(&cpuinfo, sizeof(struct cpu_softc)); + cpuinfo.master = 1; + getcpuinfo(&cpuinfo, 0); -#if defined (SUN4M) - if (CPU_ISSUN4M) { - nsegment = 0; - cpumod = (u_int) getpsr() >> 24; - mmumod = (u_int) lda(SRMMU_PCR, ASI_SRMMU) >> 28; - /* - * We use the max. number of contexts on the micro and - * hyper SPARCs. The SuperSPARC would let us use up to 65536 - * contexts (by powers of 2), but we keep it at 4096 since - * the table must be aligned to #context*4. With 4K contexts, - * we waste at most 16K of memory. Note that the context - * table is *always* page-aligned, so there can always be - * 1024 contexts without sacrificing memory space (given - * that the chip supports 1024 contexts). - * - * Currently known limits: MS2=256, HS=4096, SS=65536 - * some old SS's=4096 - * - * XXX Should this be a tuneable parameter? - */ - switch (mmumod) { - case SUN4M_MMU_MS1: - ncontext = 64; - break; - case SUN4M_MMU_MS: - ncontext = 256; - break; - default: - ncontext = 4096; - break; - } - } -#endif /* SUN4M */ - - pmap_bootstrap(ncontext, nregion, nsegment); + pmap_bootstrap(cpuinfo.mmu_ncontext, + cpuinfo.mmu_nregion, + cpuinfo.mmu_nsegment); msgbufmapped = 1; /* enable message buffer */ #ifdef KGDB zs_kgdb_init(); /* XXX */ @@ -418,6 +355,15 @@ bootstrap() timerreg_4m = (struct timer_4m *)ra.ra_vaddrs[ra.ra_nvaddrs-1]; } #endif /* SUN4M */ + + if (CPU_ISSUN4OR4C) { + /* Map Interrupt Enable Register */ + pmap_enter(pmap_kernel(), INTRREG_VA, + INT_ENABLE_REG_PHYSADR | PMAP_NC | PMAP_OBIO, + VM_PROT_READ | VM_PROT_WRITE, 1); + /* Disable all interrupts */ + *((unsigned char *)INTRREG_VA) = 0; + } } /* @@ -617,23 +563,23 @@ bootpath_fake(bp, cp) int target, lun; - switch (cpumod) { - case SUN4_200: - case SUN4_400: + switch (cpuinfo.cpu_type) { + case CPUTYP_4_200: + case CPUTYP_4_400: BP_APPEND(bp, "vmes", -1, 0, 0); BP_APPEND(bp, "si", -1, v0val[0], 0); break; - case SUN4_100: + case CPUTYP_4_100: BP_APPEND(bp, "obio", -1, 0, 0); BP_APPEND(bp, "sw", -1, v0val[0], 0); break; - case SUN4_300: + case CPUTYP_4_300: BP_APPEND(bp, "obio", -1, 0, 0); BP_APPEND(bp, "esp", -1, v0val[0], 0); break; default: - panic("bootpath_fake: unknown cpumod %d", - cpumod); + panic("bootpath_fake: unknown system type %d", + cpuinfo.cpu_type); } /* * Deal with target/lun encodings. @@ -715,6 +661,8 @@ bootpath_fake(bp, cp) /* * print out the bootpath + * the %x isn't 0x%x because the Sun EPROMs do it this way, and + * consistency with the EPROMs is probably better here. */ static void @@ -873,21 +821,23 @@ configure() * must be 0xZYYYYYYY, where (Z != 0) * make sure we get the correct memreg cfdriver! */ - if (cpumod==SUN4_100 && (cf->cf_loc[0] & 0xf0000000)) + if (cpuinfo.cpu_type == CPUTYP_4_100 && + (cf->cf_loc[0] & 0xf0000000)) continue; - if (cpumod!=SUN4_100 && !(cf->cf_loc[0] & 0xf0000000)) + if (cpuinfo.cpu_type != CPUTYP_4_100 && + !(cf->cf_loc[0] & 0xf0000000)) continue; for (p = cf->cf_parents; memregcf==NULL && *p >= 0; p++) if (cfdata[*p].cf_driver == &obio_cd) memregcf = cf; } - if (memregcf==NULL) + if (memregcf == NULL) panic("configure: no memreg found!"); - rr.rr_iospace = BUS_OBIO; + rr.rr_iospace = PMAP_OBIO; rr.rr_paddr = (void *)memregcf->cf_loc[0]; rr.rr_len = NBPG; - par_err_reg = (u_int *)bus_map(&rr, NBPG, BUS_OBIO); + par_err_reg = (u_int *)bus_map(&rr, NBPG); if (par_err_reg == NULL) panic("configure: ROM hasn't mapped memreg!"); } @@ -911,6 +861,16 @@ configure() oca.ca_ra.ra_name = cp = "mainbus"; if (config_rootfound(cp, (void *)&oca) == NULL) panic("mainbus not configured"); + + /* Enable device interrupts */ +#if defined(SUN4M) + if (CPU_ISSUN4M) + ienab_bic(SINTR_MA); +#endif +#if defined(SUN4) || defined(SUN4C) + if (CPU_ISSUN4OR4C) + ienab_bis(IE_ALLIE); +#endif (void)spl0(); /* @@ -1067,17 +1027,6 @@ romprop(rp, cp, node) #endif } -#if defined(SUN4M) - if (CPU_ISSUN4M) { - len = getprop(node, "ranges", (void *)&rp->ra_range, - sizeof rp->ra_range); - if (len == -1) - len = 0; - rp->ra_nrange = len / sizeof(struct rom_range); - } else -#endif - rp->ra_nrange = 0; - return (1); } @@ -1110,8 +1059,8 @@ mainbus_attach(parent, dev, aux) { struct confargs oca; register const char *const *ssp, *sp = NULL; -#if defined(SUN4C) || defined(SUN4M) struct confargs *ca = aux; +#if defined(SUN4C) || defined(SUN4M) register int node0, node; const char *const *openboot_special; #define L1A_HACK /* XXX hack to allow L1-A during autoconf */ @@ -1176,8 +1125,10 @@ mainbus_attach(parent, dev, aux) #endif #if defined(SUN4M) - if (CPU_ISSUN4M) - printf(": %s", getpropstring(ca->ca_ra.ra_node, "name")); + if (CPU_ISSUN4) + printf(": SUN-4/%d series\n", cpuinfo.classlvl); + else + printf(": %s\n", getpropstring(ca->ca_ra.ra_node, "name")); #endif printf("\n"); @@ -1225,26 +1176,29 @@ mainbus_attach(parent, dev, aux) node = ca->ca_ra.ra_node; /* i.e., the root node */ /* the first early device to be configured is the cpu */ -#if defined(SUN4M) if (CPU_ISSUN4M) { /* XXX - what to do on multiprocessor machines? */ register const char *cp; for (node = firstchild(node); node; node = nextsibling(node)) { cp = getpropstring(node, "device_type"); - if (strcmp(cp, "cpu") == 0) - break; + if (strcmp(cp, "cpu") == 0) { + bzero(&oca, sizeof(oca)); + oca.ca_ra.ra_node = node; + oca.ca_ra.ra_name = "cpu"; + oca.ca_ra.ra_paddr = 0; + oca.ca_ra.ra_nreg = 0; + config_found(dev, (void *)&oca, mbprint); + } } - if (node == 0) - panic("None of the CPUs found\n"); + } else if (CPU_ISSUN4C) { + bzero(&oca, sizeof(oca)); + oca.ca_ra.ra_node = node; + oca.ca_ra.ra_name = "cpu"; + oca.ca_ra.ra_paddr = 0; + oca.ca_ra.ra_nreg = 0; + config_found(dev, (void *)&oca, mbprint); } -#endif - - oca.ca_ra.ra_node = node; - oca.ca_ra.ra_name = "cpu"; - oca.ca_ra.ra_paddr = 0; - oca.ca_ra.ra_nreg = 0; - config_found(dev, (void *)&oca, mbprint); node = ca->ca_ra.ra_node; /* re-init root node */ @@ -1303,12 +1257,6 @@ mainbus_attach(parent, dev, aux) (void) config_found(dev, (void *)&oca, mbprint); } } -#if defined(SUN4M) - if (CPU_ISSUN4M) { - /* Enable device interrupts */ - ienab_bic(SINTR_MA); - } -#endif #endif /* SUN4C || SUN4M */ } @@ -1355,9 +1303,9 @@ findzs(zs) panic("findzs: unknown zs device %d", zs); } - rr.rr_iospace = BUS_OBIO; + rr.rr_iospace = PMAP_OBIO; rr.rr_len = NBPG; - vaddr = bus_map(&rr, NBPG, BUS_OBIO); + vaddr = bus_map(&rr, NBPG); if (vaddr) return (vaddr); } @@ -1537,7 +1485,7 @@ getprop(node, name, buf, bufsiz) no = promvec->pv_nodeops; len = no->no_proplen(node, name); if (len > bufsiz) { - printf("node %x property %s length %d > %d\n", + printf("node 0x%x property %s length %d > %d\n", node, name, len, bufsiz); #ifdef DEBUG panic("getprop"); @@ -1551,6 +1499,19 @@ getprop(node, name, buf, bufsiz) } /* + * Internal form of proplen(). Returns the property length. + */ +int +getproplen(node, name) + int node; + char *name; +{ + register struct nodeops *no = promvec->pv_nodeops; + + return (no->no_proplen(node, name)); +} + +/* * Return a string property. There is a (small) limit on the length; * the string is fetched into a static buffer which is overwritten on * subsequent calls. @@ -1609,7 +1570,6 @@ nextsibling(node) return (promvec->pv_nodeops->no_nextnode(node)); } -char *strchr __P((const char *, int)); u_int hexatoi __P((const char *)); /* The following recursively searches a PROM tree for a given node */ @@ -1698,7 +1658,7 @@ romgetcursoraddr(rowp, colp) * and in some newer proms. They are local in version 2.9. The * correct cutoff point is unknown, as yet; we use 2.9 here. */ - if (promvec->pv_romvec_vers < 2 || promvec->pv_printrev < 0x00020007) + if (promvec->pv_romvec_vers < 2 || promvec->pv_printrev < 0x00020009) sprintf(buf, "' line# >body >user %lx ! ' column# >body >user %lx !", (u_long)rowp, (u_long)colp); @@ -1708,8 +1668,6 @@ romgetcursoraddr(rowp, colp) (u_long)rowp, (u_long)colp); *rowp = *colp = NULL; rominterpret(buf); - if (*rowp == *colp && *rowp != NULL) - panic("romgetcursor prom version"); return (*rowp == NULL || *colp == NULL); } #endif @@ -2163,25 +2121,6 @@ getdevunit(name, unit) return dev; } - -/* - * The $#!@$&%# kernel library doesn't have strchr or atoi. Ugh. We duplicate - * here. - */ - -char * -strchr(p, ch) /* cribbed from libc */ - register const char *p, ch; -{ - for (;; ++p) { - if (*p == ch) - return((char *)p); - if (!*p) - return((char *)NULL); - } - /* NOTREACHED */ -} - u_int hexatoi(nptr) /* atoi assuming hex, no 0x */ const char *nptr; @@ -2190,4 +2129,3 @@ hexatoi(nptr) /* atoi assuming hex, no 0x */ str2hex((char *)nptr, &retval); return retval; } - diff --git a/sys/arch/sparc/sparc/auxreg.c b/sys/arch/sparc/sparc/auxreg.c index 2a28ec0d7e5..0aa296a7ce6 100644 --- a/sys/arch/sparc/sparc/auxreg.c +++ b/sys/arch/sparc/sparc/auxreg.c @@ -120,7 +120,7 @@ auxregattach(parent, self, aux) struct confargs *ca = aux; struct romaux *ra = &ca->ca_ra; - (void)mapdev(ra->ra_reg, AUXREG_VA, 0, sizeof(long), ca->ca_bustype); + (void)mapdev(ra->ra_reg, AUXREG_VA, 0, sizeof(long)); if (CPU_ISSUN4M) { auxio_reg = AUXIO4M_REG; auxio_regval = *AUXIO4M_REG | AUXIO4M_MB1; diff --git a/sys/arch/sparc/sparc/cache.c b/sys/arch/sparc/sparc/cache.c index 1a02e82639b..aa28655e4bc 100644 --- a/sys/arch/sparc/sparc/cache.c +++ b/sys/arch/sparc/sparc/cache.c @@ -1,4 +1,5 @@ -/* $NetBSD: cache.c,v 1.8.4.1 1996/06/12 20:40:35 pk Exp $ */ +/* $OpenBSD: cache.c,v 1.4 1997/08/08 08:27:03 downsj Exp $ */ +/* $NetBSD: cache.c,v 1.33 1997/07/29 09:41:56 fair Exp $ */ /* * Copyright (c) 1996 @@ -66,169 +67,254 @@ #include <sparc/sparc/asm.h> #include <sparc/sparc/cache.h> +#include <sparc/sparc/cpuvar.h> -enum vactype vactype; struct cachestats cachestats; -#if defined(SUN4M) int cache_alias_dist; /* Cache anti-aliasing constants */ int cache_alias_bits; -#endif - -/* - * A few quick macros to allow for different ASI's between 4M/4/4C machines - */ -#define flushls_ctx(p) do { \ - CPU_ISSUN4M \ - ? sta(p, ASI_IDCACHELFC, 0) \ - : sta(p, ASI_FLUSHCTX, 0); \ -} while (0) -#define flushls_reg(p) do { \ - CPU_ISSUN4M \ - ? sta(p, ASI_IDCACHELFR, 0) \ - : sta(p, ASI_FLUSHREG, 0); \ -} while (0) -#define flushls_seg(p) do { \ - CPU_ISSUN4M \ - ? sta(p, ASI_IDCACHELFS, 0) \ - : sta(p, ASI_FLUSHSEG, 0); \ -} while (0) -#define flushls_pag(p) do { \ - CPU_ISSUN4M \ - ? sta(p, ASI_IDCACHELFP, 0) \ - : sta(p, ASI_FLUSHPG, 0); \ -} while (0) -#define flushls_usr(p) do { \ - if (CPU_ISSUN4M) \ - sta(p, ASI_IDCACHELFU, 0); \ -while(0) - -/* XXX: (ABB) need more generic Sun4m cache support */ -#if !defined(SUN4) && !defined(SUN4C) -#define ASI_HWFLUSHSEG 0x05 /* hardware assisted version of FLUSHSEG */ -#define ASI_HWFLUSHPG 0x06 /* hardware assisted version of FLUSHPG */ -#define ASI_HWFLUSHCTX 0x07 /* hardware assisted version of FLUSHCTX */ -#endif /* * Enable the cache. * We need to clear out the valid bits first. */ void -cache_enable() +sun4_cache_enable() { register u_int i, lim, ls, ts; - ls = cacheinfo.c_linesize; - ts = cacheinfo.c_totalsize; - - if (CPU_ISSUN4M) { - i = lda(SRMMU_PCR, ASI_SRMMU); - switch (mmumod) { - case SUN4M_MMU_HS: /* HyperSPARC */ - /* - * First we determine what type of cache we have, and - * setup the anti-aliasing constants appropriately. - */ - if (i & SRMMU_PCR_CS) { - cache_alias_bits = CACHE_ALIAS_BITS_HS256k; - cache_alias_dist = CACHE_ALIAS_DIST_HS256k; - } else { - cache_alias_bits = CACHE_ALIAS_BITS_HS128k; - cache_alias_dist = CACHE_ALIAS_DIST_HS128k; - } - /* Now reset cache tag memory */ - for (i = 0, lim = ts; i < lim; i += ls) - sta(i, ASI_DCACHETAG, 0); - - sta(SRMMU_PCR, ASI_SRMMU, /* Enable write-back cache */ - lda(SRMMU_PCR, ASI_SRMMU) | SRMMU_PCR_CE | - SRMMU_PCR_CM); - cacheinfo.c_enabled = 1; - vactype = VAC_NONE; - /* HyperSPARC uses phys. tagged cache */ - - /* XXX: should add support */ - if (cacheinfo.c_hwflush) - panic("cache_enable: can't handle 4M with hw-flush cache"); - - printf("cache enabled\n"); - break; - - case SUN4M_MMU_SS: /* SuperSPARC */ - if ((cpumod & 0xf0) != (SUN4M_SS & 0xf0)) { - printf( - "cache NOT enabled for %x/%x cpu/mmu combination\n", - cpumod, mmumod); - break; /* ugh, SS and MS have same MMU # */ - } - cache_alias_bits = CACHE_ALIAS_BITS_SS; - cache_alias_dist = CACHE_ALIAS_DIST_SS; - - /* We "flash-clear" the I/D caches. */ - sta(0x80000000, ASI_ICACHECLR, 0); /* Unlock */ - sta(0, ASI_ICACHECLR, 0); /* clear */ - sta(0x80000000, ASI_DCACHECLR, 0); - sta(0, ASI_DCACHECLR, 0); - - /* Turn on caches via MMU */ - sta(SRMMU_PCR, ASI_SRMMU, - lda(SRMMU_PCR,ASI_SRMMU) | SRMMU_PCR_DCE | - SRMMU_PCR_ICE); - cacheinfo.c_enabled = cacheinfo.dc_enabled = 1; - - /* Now try to turn on MultiCache if it exists */ - /* XXX (ABB) THIS IS BROKEN MUST FIX */ - if (0&&(lda(SRMMU_PCR, ASI_SRMMU) & SRMMU_PCR_MB) == 0 - && cacheinfo.ec_totalsize > 0) { - /* Multicache controller */ - sta(MXCC_ENABLE_ADDR, ASI_CONTROL, - lda(MXCC_ENABLE_ADDR, ASI_CONTROL) | - MXCC_ENABLE_BIT); - cacheinfo.ec_enabled = 1; - } - printf("cache enabled\n"); - break; - case SUN4M_MMU_MS1: /* MicroSPARC */ - /* We "flash-clear" the I/D caches. */ - sta(0, ASI_ICACHECLR, 0); /* clear */ - sta(0, ASI_DCACHECLR, 0); - - /* Turn on caches via MMU */ - sta(SRMMU_PCR, ASI_SRMMU, - lda(SRMMU_PCR,ASI_SRMMU) | SRMMU_PCR_DCE | - SRMMU_PCR_ICE); - cacheinfo.c_enabled = cacheinfo.dc_enabled = 1; - - printf("cache enabled\n"); - break; - - default: - printf("Unknown MMU architecture...cache disabled.\n"); - /* XXX: not HyperSPARC -- guess for now */ - cache_alias_bits = GUESS_CACHE_ALIAS_BITS; - cache_alias_dist = GUESS_CACHE_ALIAS_DIST; - } + cache_alias_bits = CPU_ISSUN4 + ? CACHE_ALIAS_BITS_SUN4 + : CACHE_ALIAS_BITS_SUN4C; + cache_alias_dist = CPU_ISSUN4 + ? CACHE_ALIAS_DIST_SUN4 + : CACHE_ALIAS_DIST_SUN4C; - } else { + ls = CACHEINFO.c_linesize; + ts = CACHEINFO.c_totalsize; - for (i = AC_CACHETAGS, lim = i + ts; i < lim; i += ls) - sta(i, ASI_CONTROL, 0); + for (i = AC_CACHETAGS, lim = i + ts; i < lim; i += ls) + sta(i, ASI_CONTROL, 0); - stba(AC_SYSENABLE, ASI_CONTROL, - lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_CACHE); - cacheinfo.c_enabled = 1; + stba(AC_SYSENABLE, ASI_CONTROL, + lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_CACHE); + CACHEINFO.c_enabled = 1; - printf("cache enabled\n"); + printf("cache enabled\n"); #ifdef notyet - if (cpumod == SUN4_400) { - stba(AC_SYSENABLE, ASI_CONTROL, - lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_IOCACHE); - printf("iocache enabled\n"); - } + if (cpuinfo.flags & SUN4_IOCACHE) { + stba(AC_SYSENABLE, ASI_CONTROL, + lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_IOCACHE); + printf("iocache enabled\n"); + } #endif +} + +void +ms1_cache_enable() +{ + u_int pcr; + + cache_alias_bits = GUESS_CACHE_ALIAS_BITS; + cache_alias_dist = GUESS_CACHE_ALIAS_DIST; + + pcr = lda(SRMMU_PCR, ASI_SRMMU); + + /* We "flash-clear" the I/D caches. */ + if ((pcr & MS1_PCR_ICE) == 0) + sta(0, ASI_ICACHECLR, 0); + if ((pcr & MS1_PCR_DCE) == 0) + sta(0, ASI_DCACHECLR, 0); + + /* Turn on caches */ + sta(SRMMU_PCR, ASI_SRMMU, pcr | MS1_PCR_DCE | MS1_PCR_ICE); + + cpuinfo.flags |= CPUFLG_CACHEPAGETABLES; + + CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1; + + printf("cache enabled\n"); +} + +void +viking_cache_enable() +{ + u_int pcr; + + cache_alias_dist = max( + CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity, + CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity); + cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET; + + pcr = lda(SRMMU_PCR, ASI_SRMMU); + + if ((pcr & VIKING_PCR_ICE) == 0) { + /* I-cache not on; "flash-clear" it now. */ + sta(0x80000000, ASI_ICACHECLR, 0); /* Unlock */ + sta(0, ASI_ICACHECLR, 0); /* clear */ + } + if ((pcr & VIKING_PCR_DCE) == 0) { + /* D-cache not on: "flash-clear" it. */ + sta(0x80000000, ASI_DCACHECLR, 0); + sta(0, ASI_DCACHECLR, 0); } + + /* Turn on caches via MMU */ + sta(SRMMU_PCR, ASI_SRMMU, pcr | VIKING_PCR_DCE | VIKING_PCR_ICE); + + CACHEINFO.c_enabled = CACHEINFO.dc_enabled = 1; + + /* Now turn on MultiCache if it exists */ + if (cpuinfo.mxcc && CACHEINFO.ec_totalsize > 0) { + /* Multicache controller */ + stda(MXCC_ENABLE_ADDR, ASI_CONTROL, + ldda(MXCC_ENABLE_ADDR, ASI_CONTROL) | + (u_int64_t)MXCC_ENABLE_BIT); + cpuinfo.flags |= CPUFLG_CACHEPAGETABLES; /* Ok to cache PTEs */ + CACHEINFO.ec_enabled = 1; + } + printf("cache enabled\n"); +} + +void +hypersparc_cache_enable() +{ + int i, ls, ts; + u_int pcr; + + ls = CACHEINFO.c_linesize; + ts = CACHEINFO.c_totalsize; + + pcr = lda(SRMMU_PCR, ASI_SRMMU); + + /* + * First we determine what type of cache we have, and + * setup the anti-aliasing constants appropriately. + */ + if (pcr & HYPERSPARC_PCR_CS) { + cache_alias_bits = CACHE_ALIAS_BITS_HS256k; + cache_alias_dist = CACHE_ALIAS_DIST_HS256k; + } else { + cache_alias_bits = CACHE_ALIAS_BITS_HS128k; + cache_alias_dist = CACHE_ALIAS_DIST_HS128k; + } + + /* Now reset cache tag memory if cache not yet enabled */ + if ((pcr & HYPERSPARC_PCR_CE) == 0) + for (i = 0; i < ts; i += ls) + sta(i, ASI_DCACHETAG, 0); + + /* Enable write-back cache */ + pcr |= (HYPERSPARC_PCR_CE | HYPERSPARC_PCR_CM); + sta(SRMMU_PCR, ASI_SRMMU, pcr); + CACHEINFO.c_enabled = 1; + + /* XXX: should add support */ + if (CACHEINFO.c_hwflush) + panic("cache_enable: can't handle 4M with hw-flush cache"); + + printf("cache enabled\n"); +} + +void +swift_cache_enable() +{ + int i, ls, ts; + u_int pcr; + + cache_alias_dist = max( + CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity, + CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity); + cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET; + + pcr = lda(SRMMU_PCR, ASI_SRMMU); + pcr |= (SWIFT_PCR_ICE | SWIFT_PCR_DCE); + sta(SRMMU_PCR, ASI_SRMMU, pcr); + + /* Now reset cache tag memory if cache not yet enabled */ + ls = CACHEINFO.ic_linesize; + ts = CACHEINFO.ic_totalsize; + if ((pcr & SWIFT_PCR_ICE) == 0) + for (i = 0; i < ts; i += ls) + sta(i, ASI_ICACHETAG, 0); + + ls = CACHEINFO.dc_linesize; + ts = CACHEINFO.dc_totalsize; + if ((pcr & SWIFT_PCR_DCE) == 0) + for (i = 0; i < ts; i += ls) + sta(i, ASI_DCACHETAG, 0); + + /* XXX - assume that an MS2 with ecache is really a turbo in disguise */ + if (CACHEINFO.ec_totalsize == 0) + cpuinfo.flags |= CPUFLG_CACHEPAGETABLES; /* Ok to cache PTEs */ + CACHEINFO.c_enabled = 1; + printf("cache enabled\n"); +} + +void +cypress_cache_enable() +{ + int i, ls, ts; + u_int pcr; + + cache_alias_dist = CACHEINFO.c_totalsize; + cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET; + + pcr = lda(SRMMU_PCR, ASI_SRMMU); + pcr &= ~(CYPRESS_PCR_CE | CYPRESS_PCR_CM); + + /* Now reset cache tag memory if cache not yet enabled */ + ls = CACHEINFO.c_linesize; + ts = CACHEINFO.c_totalsize; + if ((pcr & CYPRESS_PCR_CE) == 0) + for (i = 0; i < ts; i += ls) + sta(i, ASI_DCACHETAG, 0); + + pcr |= CYPRESS_PCR_CE; + /* If put in write-back mode, turn it on */ + if (CACHEINFO.c_vactype == VAC_WRITEBACK) + pcr |= CYPRESS_PCR_CM; + sta(SRMMU_PCR, ASI_SRMMU, pcr); + CACHEINFO.c_enabled = 1; + printf("cache enabled\n"); +} + +void +turbosparc_cache_enable() +{ + int i, ls, ts; + u_int pcr, pcf; + + cache_alias_dist = max( + CACHEINFO.ic_totalsize / CACHEINFO.ic_associativity, + CACHEINFO.dc_totalsize / CACHEINFO.dc_associativity); + cache_alias_bits = (cache_alias_dist - 1) & ~PGOFSET; + + pcr = lda(SRMMU_PCR, ASI_SRMMU); + + /* Now reset cache tag memory if cache not yet enabled */ + ls = CACHEINFO.ic_linesize; + ts = CACHEINFO.ic_totalsize; + if ((pcr & TURBOSPARC_PCR_ICE) == 0) + for (i = 0; i < ts; i += ls) + sta(i, ASI_ICACHETAG, 0); + + ls = CACHEINFO.dc_linesize; + ts = CACHEINFO.dc_totalsize; + if ((pcr & TURBOSPARC_PCR_DCE) == 0) + for (i = 0; i < ts; i += ls) + sta(i, ASI_DCACHETAG, 0); + + pcr |= (TURBOSPARC_PCR_ICE | TURBOSPARC_PCR_DCE); + sta(SRMMU_PCR, ASI_SRMMU, pcr); + + pcf = lda(SRMMU_PCFG, ASI_SRMMU); + if (pcf & TURBOSPARC_PCFG_SNP) + printf("DVMA coherent "); + + CACHEINFO.c_enabled = 1; + printf("cache enabled\n"); } /* @@ -239,27 +325,26 @@ cache_enable() * hardware flush space, for all cache pages). */ void -cache_flush_context() +sun4_vcache_flush_context() { register char *p; register int i, ls; cachestats.cs_ncxflush++; p = (char *)0; /* addresses 0..cacheinfo.c_totalsize will do fine */ - if (cacheinfo.c_hwflush) { + if (CACHEINFO.c_hwflush) { ls = NBPG; - i = cacheinfo.c_totalsize >> PGSHIFT; + i = CACHEINFO.c_totalsize >> PGSHIFT; for (; --i >= 0; p += ls) sta(p, ASI_HWFLUSHCTX, 0); } else { - ls = cacheinfo.c_linesize; - i = cacheinfo.c_totalsize >> cacheinfo.c_l2linesize; + ls = CACHEINFO.c_linesize; + i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize; for (; --i >= 0; p += ls) - flushls_ctx(p); + sta(p, ASI_FLUSHCTX, 0); } } -#if defined(SUN4) || defined(SUN4M) /* * Flush the given virtual region from the cache. * @@ -267,11 +352,11 @@ cache_flush_context() * now the addresses must include the virtual region number, and * we use the `flush region' space. * - * This function is only called on sun4m's or sun4's with 3-level MMUs; there's + * This function is only called on sun4's with 3-level MMUs; there's * no hw-flush space. */ void -cache_flush_region(vreg) +sun4_vcache_flush_region(vreg) register int vreg; { register int i, ls; @@ -279,12 +364,11 @@ cache_flush_region(vreg) cachestats.cs_nrgflush++; p = (char *)VRTOVA(vreg); /* reg..reg+sz rather than 0..sz */ - ls = cacheinfo.c_linesize; - i = cacheinfo.c_totalsize >> cacheinfo.c_l2linesize; + ls = CACHEINFO.c_linesize; + i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize; for (; --i >= 0; p += ls) - flushls_reg(p); + sta(p, ASI_FLUSHREG, 0); } -#endif /* * Flush the given virtual segment from the cache. @@ -296,7 +380,7 @@ cache_flush_region(vreg) * Again, for hardware, we just write each page (in hw-flush space). */ void -cache_flush_segment(vreg, vseg) +sun4_vcache_flush_segment(vreg, vseg) register int vreg, vseg; { register int i, ls; @@ -304,16 +388,16 @@ cache_flush_segment(vreg, vseg) cachestats.cs_nsgflush++; p = (char *)VSTOVA(vreg, vseg); /* seg..seg+sz rather than 0..sz */ - if (cacheinfo.c_hwflush) { + if (CACHEINFO.c_hwflush) { ls = NBPG; - i = cacheinfo.c_totalsize >> PGSHIFT; + i = CACHEINFO.c_totalsize >> PGSHIFT; for (; --i >= 0; p += ls) sta(p, ASI_HWFLUSHSEG, 0); } else { - ls = cacheinfo.c_linesize; - i = cacheinfo.c_totalsize >> cacheinfo.c_l2linesize; + ls = CACHEINFO.c_linesize; + i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize; for (; --i >= 0; p += ls) - flushls_seg(p); + sta(p, ASI_FLUSHSEG, 0); } } @@ -323,7 +407,7 @@ cache_flush_segment(vreg, vseg) * Again we write to each cache line. */ void -cache_flush_page(va) +sun4_vcache_flush_page(va) int va; { register int i, ls; @@ -331,18 +415,18 @@ cache_flush_page(va) #ifdef DEBUG if (va & PGOFSET) - panic("cache_flush_page: asked to flush misaligned va %x",va); + panic("cache_flush_page: asked to flush misaligned va 0x%x",va); #endif cachestats.cs_npgflush++; p = (char *)va; - if (cacheinfo.c_hwflush) + if (CACHEINFO.c_hwflush) sta(p, ASI_HWFLUSHPG, 0); else { - ls = cacheinfo.c_linesize; - i = NBPG >> cacheinfo.c_l2linesize; + ls = CACHEINFO.c_linesize; + i = NBPG >> CACHEINFO.c_l2linesize; for (; --i >= 0; p += ls) - flushls_pag(p); + sta(p, ASI_FLUSHPG, 0); } } @@ -354,37 +438,187 @@ cache_flush_page(va) * We choose the best of (context,segment,page) here. */ -#define CACHE_FLUSH_MAGIC (cacheinfo.c_totalsize / NBPG) +#define CACHE_FLUSH_MAGIC (CACHEINFO.c_totalsize / NBPG) void -cache_flush(base, len) +sun4_cache_flush(base, len) caddr_t base; register u_int len; { register int i, ls, baseoff; register char *p; -#if defined(SUN4) - extern int mmu_3l; -#endif -#if defined(SUN4M) + if (CACHEINFO.c_vactype == VAC_NONE) + return; + /* - * Although physically tagged, we still need to flush the - * data cache after (if we have a write-through cache) or before - * (in case of write-back caches) DMA operations. + * Figure out how much must be flushed. * - * SS10s and 20s (supersparcs) use cached DVMA, no need to flush. + * If we need to do CACHE_FLUSH_MAGIC pages, we can do a segment + * in the same number of loop iterations. We can also do the whole + * region. If we need to do between 2 and NSEGRG, do the region. + * If we need to do two or more regions, just go ahead and do the + * whole context. This might not be ideal (e.g., fsck likes to do + * 65536-byte reads, which might not necessarily be aligned). + * + * We could try to be sneaky here and use the direct mapping + * to avoid flushing things `below' the start and `above' the + * ending address (rather than rounding to whole pages and + * segments), but I did not want to debug that now and it is + * not clear it would help much. + * + * (XXX the magic number 16 is now wrong, must review policy) */ - if (CPU_ISSUN4M && mmumod != SUN4M_MMU_SS) { - /* XXX (ABB) - Need more generic cache interface */ - /* XXX above test conflicts on MicroSPARC (SUN4M_MMU_MS=_SS) */ - sta(0, ASI_DCACHECLR, 0); + baseoff = (int)base & PGOFSET; + i = (baseoff + len + PGOFSET) >> PGSHIFT; + + cachestats.cs_nraflush++; +#ifdef notyet + cachestats.cs_ra[min(i, MAXCACHERANGE)]++; +#endif + + if (i < CACHE_FLUSH_MAGIC) { + /* cache_flush_page, for i pages */ + p = (char *)((int)base & ~baseoff); + if (CACHEINFO.c_hwflush) { + for (; --i >= 0; p += NBPG) + sta(p, ASI_HWFLUSHPG, 0); + } else { + ls = CACHEINFO.c_linesize; + i <<= PGSHIFT - CACHEINFO.c_l2linesize; + for (; --i >= 0; p += ls) + sta(p, ASI_FLUSHPG, 0); + } return; } + baseoff = (u_int)base & SGOFSET; + i = (baseoff + len + SGOFSET) >> SGSHIFT; + if (i == 1) + sun4_vcache_flush_segment(VA_VREG(base), VA_VSEG(base)); + else { + if (HASSUN4_MMU3L) { + baseoff = (u_int)base & RGOFSET; + i = (baseoff + len + RGOFSET) >> RGSHIFT; + if (i == 1) + sun4_vcache_flush_region(VA_VREG(base)); + else + sun4_vcache_flush_context(); + } else + sun4_vcache_flush_context(); + } +} + + +#if defined(SUN4M) +/* + * Flush the current context from the cache. + * + * This is done by writing to each cache line in the `flush context' + * address space (or, for hardware flush, once to each page in the + * hardware flush space, for all cache pages). + */ +void +srmmu_vcache_flush_context() +{ + register char *p; + register int i, ls; + + cachestats.cs_ncxflush++; + p = (char *)0; /* addresses 0..cacheinfo.c_totalsize will do fine */ + ls = CACHEINFO.c_linesize; + i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize; + for (; --i >= 0; p += ls) + sta(p, ASI_IDCACHELFC, 0); +} + +/* + * Flush the given virtual region from the cache. + * + * This is also done by writing to each cache line, except that + * now the addresses must include the virtual region number, and + * we use the `flush region' space. + */ +void +srmmu_vcache_flush_region(vreg) + register int vreg; +{ + register int i, ls; + register char *p; + + cachestats.cs_nrgflush++; + p = (char *)VRTOVA(vreg); /* reg..reg+sz rather than 0..sz */ + ls = CACHEINFO.c_linesize; + i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize; + for (; --i >= 0; p += ls) + sta(p, ASI_IDCACHELFR, 0); +} + +/* + * Flush the given virtual segment from the cache. + * + * This is also done by writing to each cache line, except that + * now the addresses must include the virtual segment number, and + * we use the `flush segment' space. + * + * Again, for hardware, we just write each page (in hw-flush space). + */ +void +srmmu_vcache_flush_segment(vreg, vseg) + register int vreg, vseg; +{ + register int i, ls; + register char *p; + + cachestats.cs_nsgflush++; + p = (char *)VSTOVA(vreg, vseg); /* seg..seg+sz rather than 0..sz */ + ls = CACHEINFO.c_linesize; + i = CACHEINFO.c_totalsize >> CACHEINFO.c_l2linesize; + for (; --i >= 0; p += ls) + sta(p, ASI_IDCACHELFS, 0); +} + +/* + * Flush the given virtual page from the cache. + * (va is the actual address, and must be aligned on a page boundary.) + * Again we write to each cache line. + */ +void +srmmu_vcache_flush_page(va) + int va; +{ + register int i, ls; + register char *p; + +#ifdef DEBUG + if (va & PGOFSET) + panic("cache_flush_page: asked to flush misaligned va 0x%x",va); #endif - if (vactype == VAC_NONE) - return; + cachestats.cs_npgflush++; + p = (char *)va; + ls = CACHEINFO.c_linesize; + i = NBPG >> CACHEINFO.c_l2linesize; + for (; --i >= 0; p += ls) + sta(p, ASI_IDCACHELFP, 0); +} + +/* + * Flush a range of virtual addresses (in the current context). + * The first byte is at (base&~PGOFSET) and the last one is just + * before byte (base+len). + * + * We choose the best of (context,segment,page) here. + */ + +#define CACHE_FLUSH_MAGIC (CACHEINFO.c_totalsize / NBPG) + +void +srmmu_cache_flush(base, len) + caddr_t base; + register u_int len; +{ + register int i, ls, baseoff; + register char *p; /* * Figure out how much must be flushed. @@ -415,37 +649,121 @@ cache_flush(base, len) if (i < CACHE_FLUSH_MAGIC) { /* cache_flush_page, for i pages */ p = (char *)((int)base & ~baseoff); - if (cacheinfo.c_hwflush) { - for (; --i >= 0; p += NBPG) - sta(p, ASI_HWFLUSHPG, 0); - } else { - ls = cacheinfo.c_linesize; - i <<= PGSHIFT - cacheinfo.c_l2linesize; - for (; --i >= 0; p += ls) - flushls_pag(p); - } + ls = CACHEINFO.c_linesize; + i <<= PGSHIFT - CACHEINFO.c_l2linesize; + for (; --i >= 0; p += ls) + sta(p, ASI_IDCACHELFP, 0); return; } baseoff = (u_int)base & SGOFSET; i = (baseoff + len + SGOFSET) >> SGSHIFT; if (i == 1) - cache_flush_segment(VA_VREG(base), VA_VSEG(base)); + srmmu_vcache_flush_segment(VA_VREG(base), VA_VSEG(base)); else { -#if defined(SUN4) || defined(SUN4M) baseoff = (u_int)base & RGOFSET; i = (baseoff + len + RGOFSET) >> RGSHIFT; - if (i == 1 -#if !defined(SUN4) - && CPU_ISSUN4M -#elif !defined(SUN4M) - && mmu_3l -#else - && (CPU_ISSUN4M || mmu_3l) -#endif - ) - cache_flush_region(VA_VREG(base)); + if (i == 1) + srmmu_vcache_flush_region(VA_VREG(base)); else -#endif - cache_flush_context(); + srmmu_vcache_flush_context(); } } + +void +ms1_cache_flush(base, len) + caddr_t base; + register u_int len; +{ + /* + * Although physically tagged, we still need to flush the + * data cache after (if we have a write-through cache) or before + * (in case of write-back caches) DMA operations. + */ + + /* XXX investigate other methods instead of blowing the entire cache */ + sta(0, ASI_DCACHECLR, 0); +} + +void +viking_cache_flush(base, len) + caddr_t base; + register u_int len; +{ + /* + * Although physically tagged, we still need to flush the + * data cache after (if we have a write-through cache) or before + * (in case of write-back caches) DMA operations. + */ + +} + +void +viking_pcache_flush_line(va, pa) + int va; + int pa; +{ + /* + * Flush cache line corresponding to virtual address `va' + * which is mapped at physical address `pa'. + */ + extern char etext[]; + static char *base; + int i; + char *v; + + /* + * Construct a virtual address that hits the same cache line + * as PA, then read from 2*ASSOCIATIVITY-1 different physical + * locations (all different from PA). + */ + +#if 0 + if (base == 0) { + cshift = CACHEINFO.ic_l2linesize; + csize = CACHEINFO.ic_nlines << cshift; + cmask = csize - 1; + base = (char *)roundup((int)etext, csize); + } + + v = base + (((va & cmask) >> cshift) << cshift); + i = CACHEINFO.dc_associativity * 2 - 1; + + while (i--) { + (*(volatile int *)v); + v += csize; + } +#else +#define cshift 5 /* CACHEINFO.ic_l2linesize */ +#define csize (128 << cshift) /* CACHEINFO.ic_nlines << cshift */ +#define cmask (csize - 1) +#define cass 4 /* CACHEINFO.dc_associativity */ + + if (base == 0) + base = (char *)roundup((int)etext, csize); + + v = base + (((pa & cmask) >> cshift) << cshift); + i = 2 * cass - 1; + + while (i--) { + (*(volatile int *)v); + v += csize; + } +#undef cass +#undef cmask +#undef csize +#undef cshift +#endif +} + +void +srmmu_pcache_flush_line(va, pa) + int va; + int pa; +{ + /* + * Flush cache line corresponding to virtual address `va' + * which is mapped at physical address `pa'. + */ + sta(va, ASI_IDCACHELFP, 0); +} +#endif /* SUN4M */ diff --git a/sys/arch/sparc/sparc/cache.h b/sys/arch/sparc/sparc/cache.h index 6076ee314b6..1eef90e5d67 100644 --- a/sys/arch/sparc/sparc/cache.h +++ b/sys/arch/sparc/sparc/cache.h @@ -1,4 +1,5 @@ -/* $NetBSD: cache.h,v 1.7.4.1 1996/06/12 20:41:22 pk Exp $ */ +/* $OpenBSD: cache.h,v 1.3 1997/08/08 08:27:04 downsj Exp $ */ +/* $NetBSD: cache.h,v 1.16 1997/07/06 21:15:14 pk Exp $ */ /* * Copyright (c) 1996 @@ -43,6 +44,9 @@ * @(#)cache.h 8.1 (Berkeley) 6/11/93 */ +#ifndef SPARC_CACHE_H +#define SPARC_CACHE_H + /* * Sun-4 and Sun-4c virtual address cache. * @@ -50,14 +54,8 @@ * and write-back (Sun-4). The write-back caches are much faster * but require a bit more care. * - * VAC_NONE is not actually used now, but if someone builds a physical - * cache Sun-4 (or, more likely, a virtual index/physical tag cache) - * everything will work (after pulling out the #ifdef notdef's: grep - * for VAC_NONE to find them). */ -enum vactype { VAC_NONE, VAC_WRITETHROUGH, VAC_WRITEBACK }; - -extern enum vactype vactype; /* XXX move into cacheinfo struct */ +enum vactype { VAC_UNKNOWN, VAC_NONE, VAC_WRITETHROUGH, VAC_WRITEBACK }; /* * Cache tags can be written in control space, and must be set to 0 @@ -120,35 +118,29 @@ extern enum vactype vactype; /* XXX move into cacheinfo struct */ #define CACHE_ALIAS_DIST_HS256k 0x40000 #define CACHE_ALIAS_BITS_HS256k 0x3f000 -#define CACHE_ALIAS_DIST_SS 0x0 -#define CACHE_ALIAS_BITS_SS 0x0 - -#define CACHE_ALIAS_DIST_MS GUESS_CACHE_ALIAS_DIST /* fix! */ -#define CACHE_ALIAS_BITS_MS GUESS_CACHE_ALIAS_BITS /* %%% */ - /* * Assuming a tag format where the least significant bits are the byte offset * into the cache line, and the next-most significant bits are the line id, * we can calculate the appropriate aliasing constants. We also assume that * the linesize and total cache size are powers of 2. */ -#define GUESS_CACHE_ALIAS_BITS ((cacheinfo.c_totalsize - 1) & ~PGOFSET) -#define GUESS_CACHE_ALIAS_DIST (cacheinfo.c_totalsize) +#define GUESS_CACHE_ALIAS_BITS ((cpuinfo.cacheinfo.c_totalsize - 1) & ~PGOFSET) +#define GUESS_CACHE_ALIAS_DIST (cpuinfo.cacheinfo.c_totalsize) -extern int cache_alias_dist; /* If `guessed' */ +extern int cache_alias_dist; /* */ extern int cache_alias_bits; -#define CACHE_ALIAS_DIST (CPU_ISSUN4M \ - ? cache_alias_dist \ - : (CPU_ISSUN4C \ - ? CACHE_ALIAS_DIST_SUN4C \ - : CACHE_ALIAS_DIST_SUN4)) - -#define CACHE_ALIAS_BITS (CPU_ISSUN4M \ - ? cache_alias_bits \ - : (CPU_ISSUN4C \ - ? CACHE_ALIAS_BITS_SUN4C \ - : CACHE_ALIAS_BITS_SUN4)) +/* Optimize cache alias macros on single architecture kernels */ +#if defined(SUN4) && !defined(SUN4C) && !defined(SUN4M) +#define CACHE_ALIAS_DIST CACHE_ALIAS_DIST_SUN4 +#define CACHE_ALIAS_BITS CACHE_ALIAS_BITS_SUN4 +#elif !defined(SUN4) && defined(SUN4C) && !defined(SUN4M) +#define CACHE_ALIAS_DIST CACHE_ALIAS_DIST_SUN4C +#define CACHE_ALIAS_BITS CACHE_ALIAS_BITS_SUN4C +#else +#define CACHE_ALIAS_DIST cache_alias_dist +#define CACHE_ALIAS_BITS cache_alias_bits +#endif /* * True iff a1 and a2 are `bad' aliases (will cause cache duplication). @@ -158,12 +150,51 @@ extern int cache_alias_bits; /* * Routines for dealing with the cache. */ -void cache_enable __P((void)); /* turn it on */ -void cache_flush_context __P((void)); /* flush current context */ -void cache_flush_region __P((int)); /* flush region in cur ctx */ -void cache_flush_segment __P((int, int)); /* flush seg in cur ctx */ -void cache_flush_page __P((int va)); /* flush page in cur ctx */ -void cache_flush __P((caddr_t, u_int)); /* flush region */ +void sun4_cache_enable __P((void)); /* turn it on */ +void ms1_cache_enable __P((void)); /* turn it on */ +void viking_cache_enable __P((void)); /* turn it on */ +void hypersparc_cache_enable __P((void)); /* turn it on */ +void swift_cache_enable __P((void)); /* turn it on */ +void cypress_cache_enable __P((void)); /* turn it on */ +void turbosparc_cache_enable __P((void)); /* turn it on */ + +void sun4_vcache_flush_context __P((void)); /* flush current context */ +void sun4_vcache_flush_region __P((int)); /* flush region in cur ctx */ +void sun4_vcache_flush_segment __P((int, int));/* flush seg in cur ctx */ +void sun4_vcache_flush_page __P((int va)); /* flush page in cur ctx */ +void sun4_cache_flush __P((caddr_t, u_int));/* flush region */ + +void srmmu_vcache_flush_context __P((void)); /* flush current context */ +void srmmu_vcache_flush_region __P((int)); /* flush region in cur ctx */ +void srmmu_vcache_flush_segment __P((int, int));/* flush seg in cur ctx */ +void srmmu_vcache_flush_page __P((int va)); /* flush page in cur ctx */ +void srmmu_cache_flush __P((caddr_t, u_int));/* flush region */ + +void ms1_cache_flush __P((caddr_t, u_int)); +void viking_cache_flush __P((caddr_t, u_int)); +void viking_pcache_flush_line __P((int, int)); +void srmmu_pcache_flush_line __P((int, int)); + +extern void sparc_noop __P((void)); + +#define noop_vcache_flush_context \ + (void (*)__P((void))) sparc_noop +#define noop_vcache_flush_region \ + (void (*)__P((int))) sparc_noop +#define noop_vcache_flush_segment \ + (void (*)__P((int,int))) sparc_noop +#define noop_vcache_flush_page \ + (void (*)__P((int))) sparc_noop +#define noop_cache_flush \ + (void (*)__P((caddr_t, u_int))) sparc_noop +#define noop_pcache_flush_line \ + (void (*)__P((int, int))) sparc_noop + + +#define cache_flush_page(va) cpuinfo.vcache_flush_page(va) +#define cache_flush_segment(vr,vs) cpuinfo.vcache_flush_segment(vr,vs) +#define cache_flush_region(vr) cpuinfo.vcache_flush_region(vr) +#define cache_flush_context() cpuinfo.vcache_flush_context() /* * Cache control information. @@ -175,22 +206,37 @@ struct cacheinfo { int c_hwflush; /* true => have hardware flush */ int c_linesize; /* line size, in bytes */ int c_l2linesize; /* log2(linesize) */ - int c_physical; /* true => cache is physical */ + int c_nlines; /* number of cache lines */ + int c_physical; /* true => cache has physical + address tags */ + int c_associativity; /* # of "buckets" in cache line */ int c_split; /* true => cache is split */ + int ic_totalsize; /* instruction cache */ int ic_enabled; int ic_linesize; int ic_l2linesize; + int ic_nlines; + int ic_associativity; + int dc_totalsize; /* data cache */ int dc_enabled; int dc_linesize; int dc_l2linesize; + int dc_nlines; + int dc_associativity; + int ec_totalsize; /* external cache info */ int ec_enabled; int ec_linesize; int ec_l2linesize; + int ec_nlines; + int ec_associativity; + + enum vactype c_vactype; }; -extern struct cacheinfo cacheinfo; + +#define CACHEINFO cpuinfo.cacheinfo /* * Cache control statistics. @@ -205,3 +251,4 @@ struct cachestats { int cs_ra[65]; /* pages/range */ #endif }; +#endif /* SPARC_CACHE_H */ diff --git a/sys/arch/sparc/sparc/clock.c b/sys/arch/sparc/sparc/clock.c index d8606c7b21d..04027d5d670 100644 --- a/sys/arch/sparc/sparc/clock.c +++ b/sys/arch/sparc/sparc/clock.c @@ -1,4 +1,5 @@ -/* $NetBSD: clock.c,v 1.44 1996/05/16 15:57:12 abrown Exp $ */ +/* $OpenBSD: clock.c,v 1.8 1997/08/08 08:27:05 downsj Exp $ */ +/* $NetBSD: clock.c,v 1.52 1997/05/24 20:16:05 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -77,10 +78,10 @@ #include <machine/cpu.h> #include <sparc/sparc/vaddrs.h> +#include <sparc/sparc/cpuvar.h> #include <sparc/sparc/clockreg.h> #include <sparc/sparc/intreg.h> #include <sparc/sparc/timerreg.h> -#include <sparc/sparc/cache.h> /* * Statistics clock interval and variance, in usec. Variance must be a @@ -95,7 +96,8 @@ int statvar = 8192; int statmin; /* statclock interval - 1/2*variance */ int timerok; -#include <sparc/sparc/intersil7170.h> +#include <dev/ic/intersil7170.h> + extern struct idprom idprom; #define intersil_command(run, interrupt) \ @@ -120,11 +122,11 @@ static int oldclk = 0; struct intersil7170 *i7; static long oclk_get_secs __P((void)); -static void oclk_get_dt __P((struct date_time *)); -static void dt_to_gmt __P((struct date_time *, long *)); -static void oclk_set_dt __P((struct date_time *)); +static void oclk_get_dt __P((struct intersil_dt *)); +static void dt_to_gmt __P((struct intersil_dt *, long *)); +static void oclk_set_dt __P((struct intersil_dt *)); static void oclk_set_secs __P((long)); -static void gmt_to_dt __P((long *, struct date_time *)); +static void gmt_to_dt __P((long *, struct intersil_dt *)); #endif static int oclockmatch __P((struct device *, void *, void *)); @@ -208,12 +210,14 @@ int timerblurb = 10; /* Guess a value; used before clock is attached */ static int oclockmatch(parent, vcf, aux) struct device *parent; - void *aux, *vcf; + void *vcf, *aux; { register struct confargs *ca = aux; /* Only these sun4s have oclock */ - if (!CPU_ISSUN4 || (cpumod != SUN4_100 && cpumod != SUN4_200)) + if (!CPU_ISSUN4 || + (cpuinfo.cpu_type != CPUTYP_4_100 && + cpuinfo.cpu_type != CPUTYP_4_200)) return (0); /* Check configuration name */ @@ -241,8 +245,7 @@ oclockattach(parent, self, aux) oldclk = 1; /* we've got an oldie! */ - i7 = (struct intersil7170 *) - mapiodev(ra->ra_reg, 0, sizeof(*i7), ca->ca_bustype); + i7 = (struct intersil7170 *) mapiodev(ra->ra_reg, 0, sizeof(*i7)); idp = &idprom; h = idp->id_machine << 24; @@ -287,7 +290,7 @@ oclockattach(parent, self, aux) static int eeprom_match(parent, vcf, aux) struct device *parent; - void *aux, *vcf; + void *vcf, *aux; { struct cfdata *cf = vcf; struct confargs *ca = aux; @@ -298,7 +301,8 @@ eeprom_match(parent, vcf, aux) if (cf->cf_unit != 0) return (0); - if (cpumod != SUN4_100 && cpumod != SUN4_200) + if (cpuinfo.cpu_type != CPUTYP_4_100 && + cpuinfo.cpu_type != CPUTYP_4_200) return (0); if (strcmp(eeprom_cd.cd_name, ca->ca_ra.ra_name) != 0) @@ -327,7 +331,7 @@ eeprom_attach(parent, self, aux) printf("\n"); - eeprom_va = (char *)mapiodev(ra->ra_reg, 0, EEPROM_SIZE, ca->ca_bustype); + eeprom_va = (char *)mapiodev(ra->ra_reg, 0, EEPROM_SIZE); eeprom_nvram = 0; #endif /* SUN4 */ @@ -340,13 +344,14 @@ eeprom_attach(parent, self, aux) static int clockmatch(parent, vcf, aux) struct device *parent; - void *aux, *vcf; + void *vcf, *aux; { register struct confargs *ca = aux; if (CPU_ISSUN4) { /* Only these sun4s have "clock" (others have "oclock") */ - if (cpumod != SUN4_300 && cpumod != SUN4_400) + if (cpuinfo.cpu_type != CPUTYP_4_300 && + cpuinfo.cpu_type != CPUTYP_4_400) return (0); if (strcmp(clock_cd.cd_name, ca->ca_ra.ra_name) != 0) @@ -399,8 +404,7 @@ clockattach(parent, self, aux) /* * the MK48T08 is 8K */ - cl = (struct clockreg *)mapiodev(ra->ra_reg, 0, 8192, - ca->ca_bustype); + cl = (struct clockreg *)mapiodev(ra->ra_reg, 0, 8192); pmap_changeprot(pmap_kernel(), (vm_offset_t)cl, VM_PROT_READ, 1); pmap_changeprot(pmap_kernel(), (vm_offset_t)cl + 4096, VM_PROT_READ, 1); @@ -410,8 +414,7 @@ clockattach(parent, self, aux) * the MK48T02 is 2K */ cl = (struct clockreg *)mapiodev(ra->ra_reg, 0, - sizeof *clockreg, - ca->ca_bustype); + sizeof *clockreg); pmap_changeprot(pmap_kernel(), (vm_offset_t)cl, VM_PROT_READ, 1); } idp = &cl->cl_idprom; @@ -420,7 +423,8 @@ clockattach(parent, self, aux) if (CPU_ISSUN4) { idp = &idprom; - if (cpumod == SUN4_300 || cpumod == SUN4_400) { + if (cpuinfo.cpu_type == CPUTYP_4_300 || + cpuinfo.cpu_type == CPUTYP_4_400) { eeprom_va = (char *)cl->cl_nvram; eeprom_nvram = 1; } @@ -441,12 +445,13 @@ clockattach(parent, self, aux) static int timermatch(parent, vcf, aux) struct device *parent; - void *aux, *vcf; + void *vcf, *aux; { register struct confargs *ca = aux; if (CPU_ISSUN4) { - if (cpumod != SUN4_300 && cpumod != SUN4_400) + if (cpuinfo.cpu_type != CPUTYP_4_300 && + cpuinfo.cpu_type != CPUTYP_4_400) return (0); if (strcmp("timer", ca->ca_ra.ra_name) != 0) @@ -483,9 +488,9 @@ timerattach(parent, self, aux) if (CPU_ISSUN4M) { (void)mapdev(&ra->ra_reg[ra->ra_nreg-1], TIMERREG_VA, 0, - sizeof(struct timer_4m), ca->ca_bustype); + sizeof(struct timer_4m)); (void)mapdev(&ra->ra_reg[0], COUNTERREG_VA, 0, - sizeof(struct counter_4m), ca->ca_bustype); + sizeof(struct counter_4m)); timerreg_4m = (struct timer_4m *)TIMERREG_VA; counterreg_4m = (struct counter_4m *)COUNTERREG_VA; @@ -503,7 +508,7 @@ timerattach(parent, self, aux) * microtime() faster (in SUN4/SUN4C kernel only). */ (void)mapdev(ra->ra_reg, TIMERREG_VA, 0, - sizeof(struct timerreg_4), ca->ca_bustype); + sizeof(struct timerreg_4)); cnt = &timerreg4->t_c14.t_counter; lim = &timerreg4->t_c14.t_limit; @@ -641,8 +646,8 @@ cpu_initclocks() statvar >>= 1; if (CPU_ISSUN4M) { - timerreg_4m->t_limit = tmr_ustolim(tick); - counterreg_4m->t_limit = tmr_ustolim(statint); + timerreg_4m->t_limit = tmr_ustolim4m(tick); + counterreg_4m->t_limit = tmr_ustolim4m(statint); } if (CPU_ISSUN4OR4C) { @@ -768,7 +773,7 @@ statintr(cap) newint = statmin + r; if (CPU_ISSUN4M) { - counterreg_4m->t_limit = tmr_ustolim(newint); + counterreg_4m->t_limit = tmr_ustolim4m(newint); } if (CPU_ISSUN4OR4C) { @@ -990,7 +995,7 @@ resettodr() static long oclk_get_secs() { - struct date_time dt; + struct intersil_dt dt; long gmt; oclk_get_dt(&dt); @@ -1002,7 +1007,7 @@ static void oclk_set_secs(secs) long secs; { - struct date_time dt; + struct intersil_dt dt; long gmt; gmt = secs; @@ -1017,7 +1022,7 @@ oclk_set_secs(secs) */ static void oclk_get_dt(dt) - struct date_time *dt; + struct intersil_dt *dt; { int s; register volatile char *src, *dst; @@ -1041,7 +1046,7 @@ oclk_get_dt(dt) static void oclk_set_dt(dt) - struct date_time *dt; + struct intersil_dt *dt; { int s; register volatile char *src, *dst; @@ -1085,7 +1090,7 @@ static int month_days[12] = { static void gmt_to_dt(tp, dt) long *tp; - struct date_time *dt; + struct intersil_dt *dt; { register int i; register long days, secs; @@ -1126,7 +1131,7 @@ gmt_to_dt(tp, dt) static void dt_to_gmt(dt, tp) - struct date_time *dt; + struct intersil_dt *dt; long *tp; { register int i; diff --git a/sys/arch/sparc/sparc/clockreg.h b/sys/arch/sparc/sparc/clockreg.h index e2222446f1c..a1769a69d6d 100644 --- a/sys/arch/sparc/sparc/clockreg.h +++ b/sys/arch/sparc/sparc/clockreg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: clockreg.h,v 1.2 1997/08/08 08:27:07 downsj Exp $ */ /* $NetBSD: clockreg.h,v 1.5 1994/11/20 20:54:07 deraadt Exp $ */ /* diff --git a/sys/arch/sparc/sparc/conf.c b/sys/arch/sparc/sparc/conf.c index 9147630566e..a62696e300d 100644 --- a/sys/arch/sparc/sparc/conf.c +++ b/sys/arch/sparc/sparc/conf.c @@ -1,3 +1,4 @@ +/* $OpenBSD: conf.c,v 1.14 1997/08/08 08:27:08 downsj Exp $ */ /* $NetBSD: conf.c,v 1.40 1996/04/11 19:20:03 thorpej Exp $ */ /* @@ -71,10 +72,13 @@ #include "zs.h" #include "fdc.h" /* has NFDC and NFD; see files.sparc */ #include "bwtwo.h" +#include "cgtwo.h" #include "cgthree.h" #include "cgfour.h" #include "cgsix.h" #include "cgeight.h" +#include "tcx.h" +#include "cgfourteen.h" #include "xd.h" #include "xy.h" @@ -141,7 +145,7 @@ struct cdevsw cdevsw[] = cdev_notdef(), /* 28 */ cdev_gen_init(1,kbd), /* 29: /dev/kbd */ cdev_notdef(), /* 30 */ - cdev_notdef(), /* 31: should be /dev/cgtwo */ + cdev_fb_init(NCGTWO,cgtwo), /* 31: /dev/cgtwo */ cdev_notdef(), /* 32: should be /dev/gpone */ cdev_notdef(), /* 33 */ cdev_notdef(), /* 34 */ @@ -209,7 +213,7 @@ struct cdevsw cdevsw[] = cdev_notdef(), /* 96 */ cdev_notdef(), /* 97 */ cdev_notdef(), /* 98 */ - cdev_notdef(), /* 99 */ + cdev_fb_init(NCGFOURTEEN,cgfourteen), /* 99: /dev/cgfourteen */ cdev_notdef(), /* 100 */ cdev_notdef(), /* 101 */ cdev_notdef(), /* 102 */ @@ -219,7 +223,7 @@ struct cdevsw cdevsw[] = cdev_disk_init(NRD,rd), /* 106: ram disk driver */ cdev_notdef(), /* 107 */ cdev_notdef(), /* 108 */ - cdev_notdef(), /* 109 */ + cdev_fb_init(NTCX,tcx), /* 109: /dev/tcx */ cdev_disk_init(NVND,vnd), /* 110: vnode disk driver */ cdev_bpftun_init(NTUN,tun), /* 111: network tunnel */ cdev_lkm_init(NLKM,lkm), /* 112: loadable module driver */ diff --git a/sys/arch/sparc/sparc/cpu.c b/sys/arch/sparc/sparc/cpu.c index f9c5af8c424..8826a84ae33 100644 --- a/sys/arch/sparc/sparc/cpu.c +++ b/sys/arch/sparc/sparc/cpu.c @@ -1,4 +1,5 @@ -/* $NetBSD: cpu.c,v 1.22.4.1 1996/06/12 20:39:45 pk Exp $ */ +/* $OpenBSD: cpu.c,v 1.7 1997/08/08 08:27:10 downsj Exp $ */ +/* $NetBSD: cpu.c,v 1.52 1997/07/29 09:41:58 fair Exp $ */ /* * Copyright (c) 1996 @@ -64,14 +65,16 @@ #include <machine/trap.h> #include <machine/pmap.h> +#include <machine/oldmon.h> +#include <machine/idprom.h> + #include <sparc/sparc/cache.h> #include <sparc/sparc/asm.h> - -/* This is declared here so that you must include a CPU for the cache code. */ -struct cacheinfo cacheinfo; +#include <sparc/sparc/cpuvar.h> /* The following are used externally (sysctl_hw). */ -char machine[] = "sparc"; +char machine[] = MACHINE; /* from <machine/param.h> */ +char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ char cpu_model[100]; /* The CPU configuration driver. */ @@ -79,24 +82,24 @@ static void cpu_attach __P((struct device *, struct device *, void *)); int cpu_match __P((struct device *, void *, void *)); struct cfattach cpu_ca = { - sizeof(struct device), cpu_match, cpu_attach + sizeof(struct cpu_softc), cpu_match, cpu_attach }; struct cfdriver cpu_cd = { NULL, "cpu", DV_CPU }; -#if defined(SUN4C) || defined(SUN4M) -static char *psrtoname __P((int, int, int, char *)); -#endif static char *fsrtoname __P((int, int, int, char *)); +void cache_print __P((struct cpu_softc *)); +void cpu_spinup __P((struct cpu_softc *)); +void fpu_init __P((struct cpu_softc *)); #define IU_IMPL(psr) ((u_int)(psr) >> 28) #define IU_VERS(psr) (((psr) >> 24) & 0xf) -#if defined(SUN4M) + #define SRMMU_IMPL(mmusr) ((u_int)(mmusr) >> 28) #define SRMMU_VERS(mmusr) (((mmusr) >> 24) & 0xf) -#endif + #ifdef notdef /* @@ -140,9 +143,9 @@ static char *iu_vendor[16] = { int cpu_match(parent, vcf, aux) struct device *parent; - void *aux, *vcf; + void *vcf, *aux; { - struct cfdata *cf = vcf; + register struct cfdata *cf = vcf; register struct confargs *ca = aux; return (strcmp(cf->cf_driver->cd_name, ca->ca_ra.ra_name) == 0); @@ -154,271 +157,965 @@ cpu_match(parent, vcf, aux) * (slightly funny place to do it, but this is where it is to be found). */ static void -cpu_attach(parent, dev, aux) +cpu_attach(parent, self, aux) struct device *parent; - struct device *dev; + struct device *self; void *aux; { - register int node, clk, bug = 0, i; - register int impl, vers, fver; + struct cpu_softc *sc = (struct cpu_softc *)self; + register int node; register char *fpuname; struct confargs *ca = aux; - struct fpstate fpstate; - char *sep; char fpbuf[40]; -#if defined(SUN4C) || defined(SUN4M) - register int l; - char iubuf[40]; + + sc->node = node = ca->ca_ra.ra_node; + + /* + * First, find out if we're attaching the boot CPU. + */ + if (node == 0) + sc->master = 1; + else { + sc->mid = getpropint(node, "mid", 0); + if (sc->mid == 0 || sc->mid == getmid() + 8 /*XXX*/) + sc->master = 1; + } + + if (sc->master) { + /* + * Gross, but some things in cpuinfo may already have + * been setup by early routines like pmap_bootstrap(). + */ + bcopy(&sc->dv, &cpuinfo, sizeof(sc->dv)); + bcopy(&cpuinfo, sc, sizeof(cpuinfo)); + } + + getcpuinfo(sc, node); + + fpuname = "no"; + if (sc->master) { + if (sc->hotfix) + sc->hotfix(sc); + + fpu_init(sc); + if (foundfpu) + fpuname = fsrtoname(sc->cpu_impl, sc->cpu_vers, + sc->fpuvers, fpbuf); + } + /* XXX - multi-processor: take care of `cpu_model' and `foundfpu' */ + + sprintf(cpu_model, "%s @ %s MHz, %s FPU", + sc->cpu_name, + clockfreq(sc->hz), fpuname); + printf(": %s\n", cpu_model); + + if (sc->cacheinfo.c_totalsize != 0) + cache_print(sc); + + if (sc->master) { + bcopy(sc, &cpuinfo, sizeof(cpuinfo)); + /* Enable the cache */ + sc->cache_enable(); + return; + } + + /* Now start this CPU */ +} + +#if 0 +void +cpu_(sc) + struct cpu_softc *sc; +{ + if (sc->hotfix) + sc->hotfix(sc); + + /* Initialize FPU */ + fpu_init(sc); + + /* Enable the cache */ + sc->cache_enable(); +} #endif +void +cpu_spinup(sc) + struct cpu_softc *sc; +{ +#if 0 + pmap_cpusetup(); +#endif +} + +void +fpu_init(sc) + struct cpu_softc *sc; +{ + struct fpstate fpstate; + /* * Get the FSR and clear any exceptions. If we do not unload * the queue here and it is left over from a previous crash, we - * will panic in the first loadfpstate(), due to a sequence error, - * so we need to dump the whole state anyway. + * will panic in the first loadfpstate(), due to a sequence + * error, so we need to dump the whole state anyway. * * If there is no FPU, trap.c will advance over all the stores, * so we initialize fs_fsr here. */ - fpstate.fs_fsr = 7 << FSR_VER_SHIFT; /* 7 is reserved for "none" */ + + /* 7 is reserved for "none" */ + fpstate.fs_fsr = 7 << FSR_VER_SHIFT; savefpstate(&fpstate); - fver = (fpstate.fs_fsr >> FSR_VER_SHIFT) & (FSR_VER >> FSR_VER_SHIFT); - i = getpsr(); - impl = IU_IMPL(i); - vers = IU_VERS(i); - if (fver != 7) { + sc->fpuvers = + (fpstate.fs_fsr >> FSR_VER_SHIFT) & (FSR_VER >> FSR_VER_SHIFT); + + if (sc->fpuvers != 7) foundfpu = 1; - fpuname = fsrtoname(impl, vers, fver, fpbuf); - } else - fpuname = "no"; - - /* tell them what we have */ - node = ca->ca_ra.ra_node; - -#ifdef SUN4 - if (CPU_ISSUN4) { - clk = 0; - vactype = VAC_WRITEBACK; - switch (cpumod) { - case SUN4_100: - sprintf(cpu_model, "SUN-4/100 series (%s FPU)", fpuname); - vactype = VAC_NONE; - cacheinfo.c_totalsize = 0; - cacheinfo.c_hwflush = 0; - cacheinfo.c_linesize = 0; - cacheinfo.c_l2linesize = 0; - break; - case SUN4_200: - sprintf(cpu_model, "SUN-4/200 series (%s FPU)", fpuname); - cacheinfo.c_totalsize = 128*1024; - cacheinfo.c_hwflush = 0; - cacheinfo.c_linesize = 16; - cacheinfo.c_l2linesize = 4; - break; - case SUN4_300: - sprintf(cpu_model, "SUN-4/300 series (%s FPU)", fpuname); - bug = 1; - vactype = VAC_WRITETHROUGH; - cacheinfo.c_totalsize = 128*1024; - cacheinfo.c_hwflush = 0; - cacheinfo.c_linesize = 16; - cacheinfo.c_l2linesize = 4; - break; - case SUN4_400: - sprintf(cpu_model, "SUN-4/400 series (%s FPU)", fpuname); - cacheinfo.c_totalsize = 128 * 1024; - cacheinfo.c_hwflush = 0; - cacheinfo.c_linesize = 32; - cacheinfo.c_l2linesize = 5; - break; +} + +void +cache_print(sc) + struct cpu_softc *sc; +{ + struct cacheinfo *ci = &sc->cacheinfo; + char *sep; + + printf("%s:", sc->dv.dv_xname); + + sep = " "; + if (ci->c_split) { + printf("%s", (ci->c_physical ? " physical" : "")); + if (ci->ic_totalsize > 0) { + printf("%s%dK instruction (%d b/l)", sep, + ci->ic_totalsize/1024, ci->ic_linesize); + sep = ", "; } - printf(": %s\n", cpu_model); + if (ci->dc_totalsize > 0) { + printf("%s%dK data (%d b/l)", sep, + ci->dc_totalsize/1024, ci->dc_linesize); + sep = ", "; + } + printf(" "); + } else if (ci->c_physical) { + /* combined, physical */ + printf(" physical %dK combined cache (%d bytes/line) ", + ci->c_totalsize/1024, ci->c_linesize); + } else { + /* combined, virtual */ + printf(" %d byte write-%s, %d bytes/line, %cw flush ", + ci->c_totalsize, + (ci->c_vactype == VAC_WRITETHROUGH) ? "through" : "back", + ci->c_linesize, + ci->c_hwflush ? 'h' : 's'); + } + + if (ci->ec_totalsize > 0) { + printf(", %dK external (%d b/l)", + ci->ec_totalsize/1024, ci->ec_linesize); + } +} + + +/*------------*/ + + +void cpumatch_unknown __P((struct cpu_softc *, struct module_info *, int)); +void cpumatch_sun4 __P((struct cpu_softc *, struct module_info *, int)); +void cpumatch_sun4c __P((struct cpu_softc *, struct module_info *, int)); +void cpumatch_viking __P((struct cpu_softc *, struct module_info *, int)); +void cpumatch_hypersparc __P((struct cpu_softc *, struct module_info *, int)); +void cpumatch_turbosparc __P((struct cpu_softc *, struct module_info *, int)); + +void getcacheinfo_sun4 __P((struct cpu_softc *, int node)); +void getcacheinfo_sun4c __P((struct cpu_softc *, int node)); +void getcacheinfo_obp __P((struct cpu_softc *, int node)); + +void sun4_hotfix __P((struct cpu_softc *)); +void viking_hotfix __P((struct cpu_softc *)); +void turbosparc_hotfix __P((struct cpu_softc *)); + +void ms1_mmu_enable __P((void)); +void viking_mmu_enable __P((void)); +void swift_mmu_enable __P((void)); +void hypersparc_mmu_enable __P((void)); + +void srmmu_get_fltstatus __P((void)); +void ms1_get_fltstatus __P((void)); +void viking_get_fltstatus __P((void)); +void swift_get_fltstatus __P((void)); +void turbosparc_get_fltstatus __P((void)); +void hypersparc_get_fltstatus __P((void)); +void cypress_get_fltstatus __P((void)); + +struct module_info module_unknown = { + CPUTYP_UNKNOWN, + VAC_UNKNOWN, + cpumatch_unknown +}; + + +void +cpumatch_unknown(sc, mp, node) + struct cpu_softc *sc; + struct module_info *mp; + int node; +{ + panic("Unknown CPU type: " + "cpu: impl %d, vers %d; mmu: impl %d, vers %d", + sc->cpu_impl, sc->cpu_vers, + sc->mmu_impl, sc->mmu_vers); +} + +#if defined(SUN4) +struct module_info module_sun4 = { + CPUTYP_UNKNOWN, + VAC_WRITETHROUGH, + cpumatch_sun4, + getcacheinfo_sun4, + sun4_hotfix, + 0, + sun4_cache_enable, + 0, /* ncontext set in `match' function */ + 0, /* get fault regs: unused */ + sun4_cache_flush, + sun4_vcache_flush_page, + sun4_vcache_flush_segment, + sun4_vcache_flush_region, + sun4_vcache_flush_context, + noop_pcache_flush_line +}; + +void +getcacheinfo_sun4(sc, node) + struct cpu_softc *sc; + int node; +{ + struct cacheinfo *ci = &sc->cacheinfo; + + switch (sc->cpu_type) { + case CPUTYP_4_100: + ci->c_vactype = VAC_NONE; + ci->c_totalsize = 0; + ci->c_hwflush = 0; + ci->c_linesize = 0; + ci->c_l2linesize = 0; + ci->c_split = 0; + ci->c_nlines = 0; + + /* Override cache flush functions */ + sc->cache_flush = noop_cache_flush; + sc->vcache_flush_page = noop_vcache_flush_page; + sc->vcache_flush_segment = noop_vcache_flush_segment; + sc->vcache_flush_region = noop_vcache_flush_region; + sc->vcache_flush_context = noop_vcache_flush_context; + break; + case CPUTYP_4_200: + ci->c_vactype = VAC_WRITEBACK; + ci->c_totalsize = 128*1024; + ci->c_hwflush = 0; + ci->c_linesize = 16; + ci->c_l2linesize = 4; + ci->c_split = 0; + ci->c_nlines = ci->c_totalsize << ci->c_l2linesize; + break; + case CPUTYP_4_300: + ci->c_vactype = VAC_WRITEBACK; + ci->c_totalsize = 128*1024; + ci->c_hwflush = 0; + ci->c_linesize = 16; + ci->c_l2linesize = 4; + ci->c_split = 0; + ci->c_nlines = ci->c_totalsize << ci->c_l2linesize; + sc->flags |= CPUFLG_SUN4CACHEBUG; + break; + case CPUTYP_4_400: + ci->c_vactype = VAC_WRITEBACK; + ci->c_totalsize = 128 * 1024; + ci->c_hwflush = 0; + ci->c_linesize = 32; + ci->c_l2linesize = 5; + ci->c_split = 0; + ci->c_nlines = ci->c_totalsize << ci->c_l2linesize; + break; } +} + +struct idprom idprom; +void getidprom __P((struct idprom *, int size)); + +void +cpumatch_sun4(sc, mp, node) + struct cpu_softc *sc; + struct module_info *mp; + int node; +{ + + getidprom(&idprom, sizeof(idprom)); + switch (idprom.id_machine) { + /* XXX: don't know about Sun4 types */ + case ID_SUN4_100: + sc->cpu_type = CPUTYP_4_100; + sc->classlvl = 100; + sc->mmu_ncontext = 8; + sc->mmu_nsegment = 256; +/*XXX*/ sc->hz = 0; + break; + case ID_SUN4_200: + sc->cpu_type = CPUTYP_4_200; + sc->classlvl = 200; + sc->mmu_nsegment = 512; + sc->mmu_ncontext = 16; +/*XXX*/ sc->hz = 0; + break; + case ID_SUN4_300: + sc->cpu_type = CPUTYP_4_300; + sc->classlvl = 300; + sc->mmu_nsegment = 256; + sc->mmu_ncontext = 16; +/*XXX*/ sc->hz = 0; + break; + case ID_SUN4_400: + sc->cpu_type = CPUTYP_4_400; + sc->classlvl = 400; + sc->mmu_nsegment = 1024; + sc->mmu_ncontext = 64; + sc->mmu_nregion = 256; +/*XXX*/ sc->hz = 0; + sc->sun4_mmu3l = 1; + break; + } + +} #endif /* SUN4 */ -#if defined(SUN4C) || defined(SUN4M) - if (CPU_ISSUN4C || CPU_ISSUN4M) { - clk = getpropint(node, "clock-frequency", 0); - if (clk == 0) { - /* - * Try to find it in the OpenPROM root... - */ - clk = getpropint(findroot(), "clock-frequency", 0); - } - if (CPU_ISSUN4C) - sprintf(cpu_model, "%s (%s @ %s MHz, %s FPU)", - getpropstring(node, "name"), - psrtoname(impl, vers, fver, iubuf), - clockfreq(clk), fpuname); - else - /* On sun4m, the "name" property identifies CPU */ - sprintf(cpu_model, "%s @ %s MHz, %s FPU", - getpropstring(node, "name"), - clockfreq(clk), fpuname); - printf(": %s\n", cpu_model); +#if defined(SUN4C) +struct module_info module_sun4c = { + CPUTYP_UNKNOWN, + VAC_WRITETHROUGH, + cpumatch_sun4c, + getcacheinfo_sun4c, + sun4_hotfix, + 0, + sun4_cache_enable, + 0, /* ncontext set in `match' function */ + 0, + sun4_cache_flush, + sun4_vcache_flush_page, + sun4_vcache_flush_segment, + sun4_vcache_flush_region, + sun4_vcache_flush_context, + noop_pcache_flush_line +}; + +void +cpumatch_sun4c(sc, mp, node) + struct cpu_softc *sc; + struct module_info *mp; + int node; +{ + int rnode; + + rnode = findroot(); + sc->mmu_npmeg = sc->mmu_nsegment = + getpropint(rnode, "mmu-npmg", 128); + sc->mmu_ncontext = getpropint(rnode, "mmu-nctx", 8); + + /* Get clock frequency */ + sc->hz = getpropint(rnode, "clock-frequency", 0); +} + +void +getcacheinfo_sun4c(sc, node) + struct cpu_softc *sc; + int node; +{ + struct cacheinfo *ci = &sc->cacheinfo; + int i, l; + if (node == 0) + /* Bootstrapping */ + return; + + /* Sun4c's have only virtually-addressed caches */ + ci->c_physical = 0; + ci->c_totalsize = getpropint(node, "vac-size", 65536); + /* + * Note: vac-hwflush is spelled with an underscore + * on the 4/75s. + */ + ci->c_hwflush = + getpropint(node, "vac_hwflush", 0) | + getpropint(node, "vac-hwflush", 0); + + ci->c_linesize = l = getpropint(node, "vac-linesize", 16); + for (i = 0; (1 << i) < l; i++) + /* void */; + if ((1 << i) != l) + panic("bad cache line size %d", l); + ci->c_l2linesize = i; + ci->c_associativity = 1; + ci->c_nlines = ci->c_totalsize << i; + + ci->c_vactype = VAC_WRITETHROUGH; + + /* + * Machines with "buserr-type" 1 have a bug in the cache + * chip that affects traps. (I wish I knew more about this + * mysterious buserr-type variable....) + */ + if (getpropint(node, "buserr-type", 0) == 1) + sc->flags |= CPUFLG_SUN4CACHEBUG; +} +#endif /* SUN4C */ + +void +sun4_hotfix(sc) + struct cpu_softc *sc; +{ + if ((sc->flags & CPUFLG_SUN4CACHEBUG) != 0) { + kvm_uncache((caddr_t)trapbase, 1); + printf("cache chip bug; trap page uncached "); + } + +} + +#if defined(SUN4M) +void +getcacheinfo_obp(sc, node) + struct cpu_softc *sc; + int node; +{ + struct cacheinfo *ci = &sc->cacheinfo; + int i, l; + + if (node == 0) + /* Bootstrapping */ + return; + + /* + * Determine the Sun4m cache organization. + */ + ci->c_physical = node_has_property(node, "cache-physical?"); + + if (getpropint(node, "ncaches", 1) == 2) + ci->c_split = 1; + else + ci->c_split = 0; + + /* hwflush is used only by sun4/4c code */ + ci->c_hwflush = 0; + + if (node_has_property(node, "icache-nlines") && + node_has_property(node, "dcache-nlines") && + ci->c_split) { + /* Harvard architecture: get I and D cache sizes */ + ci->ic_nlines = getpropint(node, "icache-nlines", 0); + ci->ic_linesize = l = + getpropint(node, "icache-line-size", 0); + for (i = 0; (1 << i) < l && l; i++) + /* void */; + if ((1 << i) != l && l) + panic("bad icache line size %d", l); + ci->ic_l2linesize = i; + ci->ic_associativity = + getpropint(node, "icache-associativity", 1); + ci->ic_totalsize = l * ci->ic_nlines * ci->ic_associativity; + + ci->dc_nlines = getpropint(node, "dcache-nlines", 0); + ci->dc_linesize = l = + getpropint(node, "dcache-line-size",0); + for (i = 0; (1 << i) < l && l; i++) + /* void */; + if ((1 << i) != l && l) + panic("bad dcache line size %d", l); + ci->dc_l2linesize = i; + ci->dc_associativity = + getpropint(node, "dcache-associativity", 1); + ci->dc_totalsize = l * ci->dc_nlines * ci->dc_associativity; + + ci->c_l2linesize = min(ci->ic_l2linesize, ci->dc_l2linesize); + ci->c_linesize = min(ci->ic_linesize, ci->dc_linesize); + ci->c_totalsize = ci->ic_totalsize + ci->dc_totalsize; + } else { + /* unified I/D cache */ + ci->c_nlines = getpropint(node, "cache-nlines", 128); + ci->c_linesize = l = + getpropint(node, "cache-line-size", 0); + for (i = 0; (1 << i) < l && l; i++) + /* void */; + if ((1 << i) != l && l) + panic("bad cache line size %d", l); + ci->c_l2linesize = i; + ci->c_totalsize = l * + ci->c_nlines * + getpropint(node, "cache-associativity", 1); + } + + if (node_has_property(node, "ecache-nlines")) { + /* we have a L2 "e"xternal cache */ + ci->ec_nlines = getpropint(node, "ecache-nlines", 32768); + ci->ec_linesize = l = getpropint(node, "ecache-line-size", 0); + for (i = 0; (1 << i) < l && l; i++) + /* void */; + if ((1 << i) != l && l) + panic("bad ecache line size %d", l); + ci->ec_l2linesize = i; + ci->ec_associativity = + getpropint(node, "ecache-associativity", 1); + ci->ec_totalsize = l * ci->ec_nlines * ci->ec_associativity; + } + if (ci->c_totalsize == 0) + printf("warning: couldn't identify cache\n"); +} + +/* + * We use the max. number of contexts on the micro and + * hyper SPARCs. The SuperSPARC would let us use up to 65536 + * contexts (by powers of 2), but we keep it at 4096 since + * the table must be aligned to #context*4. With 4K contexts, + * we waste at most 16K of memory. Note that the context + * table is *always* page-aligned, so there can always be + * 1024 contexts without sacrificing memory space (given + * that the chip supports 1024 contexts). + * + * Currently known limits: MS1=64, MS2=256, HS=4096, SS=65536 + * some old SS's=4096 + */ + +/* TI Microsparc I */ +struct module_info module_ms1 = { + CPUTYP_MS1, + VAC_NONE, + 0, + getcacheinfo_obp, + 0, + ms1_mmu_enable, + ms1_cache_enable, + 64, + ms1_get_fltstatus, + ms1_cache_flush, + noop_vcache_flush_page, + noop_vcache_flush_segment, + noop_vcache_flush_region, + noop_vcache_flush_context, + noop_pcache_flush_line +}; + +void +ms1_mmu_enable() +{ +} + +/* TI Microsparc II */ +struct module_info module_ms2 = { /* UNTESTED */ + CPUTYP_MS2, + VAC_WRITETHROUGH, + 0, + getcacheinfo_obp, + 0, + 0, + swift_cache_enable, + 256, + srmmu_get_fltstatus, + srmmu_cache_flush, + srmmu_vcache_flush_page, + srmmu_vcache_flush_segment, + srmmu_vcache_flush_region, + srmmu_vcache_flush_context, + noop_pcache_flush_line +}; + + +struct module_info module_swift = { /* UNTESTED */ + CPUTYP_MS2, + VAC_WRITETHROUGH, + 0, + getcacheinfo_obp, + 0, + 0, + swift_cache_enable, + 256, + swift_get_fltstatus, + srmmu_cache_flush, + srmmu_vcache_flush_page, + srmmu_vcache_flush_segment, + srmmu_vcache_flush_region, + srmmu_vcache_flush_context, + srmmu_pcache_flush_line +}; + +void +swift_mmu_enable() +{ +} + +struct module_info module_viking = { /* UNTESTED */ + CPUTYP_UNKNOWN, /* set in cpumatch() */ + VAC_NONE, + cpumatch_viking, + getcacheinfo_obp, + viking_hotfix, + viking_mmu_enable, + viking_cache_enable, + 4096, + viking_get_fltstatus, + /* supersparcs use cached DVMA, no need to flush */ + noop_cache_flush, + noop_vcache_flush_page, + noop_vcache_flush_segment, + noop_vcache_flush_region, + noop_vcache_flush_context, + noop_pcache_flush_line +}; + +void +cpumatch_viking(sc, mp, node) + struct cpu_softc *sc; + struct module_info *mp; + int node; +{ + if (node == 0) + viking_hotfix(sc); +} + +void +viking_hotfix(sc) + struct cpu_softc *sc; +{ + /* Test if we're directly on the MBus */ + if (!(lda(SRMMU_PCR, ASI_SRMMU) & VIKING_PCR_MB)) { + sc->mxcc = 1; + sc->flags |= CPUFLG_CACHE_MANDATORY; /* - * Fill in the cache info. Note, vac-hwflush is spelled - * with an underscore on 4/75s. + * Ok to cache PTEs; set the flag here, so we don't + * uncache in pmap_bootstrap(). */ - /*bzero(&cacheinfo, sizeof(cacheinfo));*/ + sc->flags |= CPUFLG_CACHEPAGETABLES; + } else { + sc->cache_flush = viking_cache_flush; + sc->pcache_flush_line = viking_pcache_flush_line; + } + + /* XXX! */ + if (sc->mxcc) + sc->cpu_type = CPUTYP_SS1_MBUS_MXCC; + else + sc->cpu_type = CPUTYP_SS1_MBUS_NOMXCC; +} + +void +viking_mmu_enable() +{ + int pcr; + + pcr = lda(SRMMU_PCR, ASI_SRMMU); + + if (cpuinfo.mxcc) + pcr |= VIKING_PCR_TC; + else + pcr &= ~VIKING_PCR_TC; + sta(SRMMU_PCR, ASI_SRMMU, pcr); +} + + +/* ROSS Hypersparc */ +struct module_info module_hypersparc = { /* UNTESTED */ + CPUTYP_UNKNOWN, + VAC_NONE, + cpumatch_hypersparc, + getcacheinfo_obp, + 0, + hypersparc_mmu_enable, + hypersparc_cache_enable, + 4096, + hypersparc_get_fltstatus, + srmmu_cache_flush, + srmmu_vcache_flush_page, + srmmu_vcache_flush_segment, + srmmu_vcache_flush_region, + srmmu_vcache_flush_context, + noop_pcache_flush_line +}; + +void +cpumatch_hypersparc(sc, mp, node) + struct cpu_softc *sc; + struct module_info *mp; + int node; +{ + sc->cpu_type = CPUTYP_HS_MBUS;/*XXX*/ +} + +void +hypersparc_mmu_enable() +{ + int pcr; + + pcr = lda(SRMMU_PCR, ASI_SRMMU); + pcr |= HYPERSPARC_PCR_C; + pcr &= ~HYPERSPARC_PCR_CE; + + sta(SRMMU_PCR, ASI_SRMMU, pcr); +} + +/* Cypress 605 */ +struct module_info module_cypress = { /* UNTESTED */ + CPUTYP_CYPRESS, + VAC_WRITEBACK, + 0, + getcacheinfo_obp, + 0, + 0, + cypress_cache_enable, + 4096, + cypress_get_fltstatus, + srmmu_cache_flush, + srmmu_vcache_flush_page, + srmmu_vcache_flush_segment, + srmmu_vcache_flush_region, + srmmu_vcache_flush_context, + srmmu_pcache_flush_line +}; + +/* Fujitsu Turbosparc */ +struct module_info module_turbosparc = { /* UNTESTED */ + CPUTYP_MS2, + VAC_WRITEBACK, + cpumatch_turbosparc, + getcacheinfo_obp, + turbosparc_hotfix, + 0, + turbosparc_cache_enable, + 256, + turbosparc_get_fltstatus, + srmmu_cache_flush, + srmmu_vcache_flush_page, + srmmu_vcache_flush_segment, + srmmu_vcache_flush_region, + srmmu_vcache_flush_context, + srmmu_pcache_flush_line +}; + +void +cpumatch_turbosparc(sc, mp, node) + struct cpu_softc *sc; + struct module_info *mp; + int node; +{ + int i; + + if (node == 0 || sc->master == 0) + return; + + i = getpsr(); + if (sc->cpu_vers == IU_VERS(i)) + return; + + /* + * A cloaked Turbosparc: clear any items in cpuinfo that + * might have been set to uS2 versions during bootstrap. + */ + sc->cpu_name = 0; + sc->mmu_ncontext = 0; + sc->cpu_type = 0; + sc->cacheinfo.c_vactype = 0; + sc->hotfix = 0; + sc->mmu_enable = 0; + sc->cache_enable = 0; + sc->get_faultstatus = 0; + sc->cache_flush = 0; + sc->vcache_flush_page = 0; + sc->vcache_flush_segment = 0; + sc->vcache_flush_region = 0; + sc->vcache_flush_context = 0; + sc->pcache_flush_line = 0; +} + +void +turbosparc_hotfix(sc) + struct cpu_softc *sc; +{ + int pcf; + + pcf = lda(SRMMU_PCFG, ASI_SRMMU); + if (pcf & TURBOSPARC_PCFG_US2) { + /* Turn off uS2 emulation bit */ + pcf &= ~TURBOSPARC_PCFG_US2; + sta(SRMMU_PCFG, ASI_SRMMU, pcf); + } +} +#endif /* SUN4M */ + + +#define ANY -1 /* match any version */ + +struct cpu_conf { + int arch; + int cpu_impl; + int cpu_vers; + int mmu_impl; + int mmu_vers; + char *name; + struct module_info *minfo; +} cpu_conf[] = { +#if defined(SUN4) + { CPU_SUN4, 0, 0, ANY, ANY, "MB86900/1A or L64801", &module_sun4 }, + { CPU_SUN4, 1, 0, ANY, ANY, "L64811", &module_sun4 }, + { CPU_SUN4, 1, 1, ANY, ANY, "CY7C601", &module_sun4 }, +#endif + +#if defined(SUN4C) + { CPU_SUN4C, 0, 0, ANY, ANY, "MB86900/1A or L64801", &module_sun4c }, + { CPU_SUN4C, 1, 0, ANY, ANY, "L64811", &module_sun4c }, + { CPU_SUN4C, 1, 1, ANY, ANY, "CY7C601", &module_sun4c }, + { CPU_SUN4C, 9, 0, ANY, ANY, "W8601/8701 or MB86903", &module_sun4c }, +#endif + #if defined(SUN4M) + { CPU_SUN4M, 0, 4, 0, 4, "MB86904", &module_swift }, + { CPU_SUN4M, 0, 5, 0, 5, "MB86907", &module_turbosparc }, + { CPU_SUN4M, 1, 1, 1, 0, "CY7C601/604", &module_cypress }, + { CPU_SUN4M, 1, 1, 1, 0xb, "CY7C601/605 (v.b)", &module_cypress }, + { CPU_SUN4M, 1, 1, 1, 0xc, "CY7C601/605 (v.c)", &module_cypress }, + { CPU_SUN4M, 1, 1, 1, 0xf, "CY7C601/605 (v.f)", &module_cypress }, + { CPU_SUN4M, 1, 3, 1, ANY, "CY7C611", &module_cypress }, + { CPU_SUN4M, 1, 0xf, 1, 1, "RT620/625", &module_hypersparc }, + { CPU_SUN4M, 4, 0, 0, ANY, "TMS390Z50 v0 or TMS390Z55", &module_viking }, + { CPU_SUN4M, 4, 1, 0, ANY, "TMS390Z50 v1", &module_viking }, + { CPU_SUN4M, 4, 1, 4, ANY, "TMS390S10", &module_ms1 }, + { CPU_SUN4M, 4, 2, 0, ANY, "TI_MS2", &module_ms2 }, + { CPU_SUN4M, 4, 3, ANY, ANY, "TI_4_3", &module_viking }, + { CPU_SUN4M, 4, 4, ANY, ANY, "TI_4_4", &module_viking }, +#endif + + { ANY, ANY, ANY, ANY, ANY, "Unknown", &module_unknown } +}; + +void +getcpuinfo(sc, node) + struct cpu_softc *sc; + int node; +{ + struct cpu_conf *mp; + int i; + int cpu_impl, cpu_vers; + int mmu_impl, mmu_vers; + + /* + * Set up main criteria for selection from the CPU configuration + * table: the CPU implementation/version fields from the PSR + * register, and -- on sun4m machines -- the MMU + * implementation/version from the SCR register. + */ + if (sc->master) { + i = getpsr(); + if (node == 0 || + (cpu_impl = + getpropint(node, "psr-implementation", -1)) == -1) + cpu_impl = IU_IMPL(i); + + if (node == 0 || + (cpu_vers = getpropint(node, "psr-version", -1)) == -1) + cpu_vers = IU_VERS(i); + if (CPU_ISSUN4M) { - cacheinfo.c_physical = 1; - vactype = node_has_property(node, "cache-physical?") - ? VAC_NONE - : VAC_WRITETHROUGH; /* ??? */ - /* - * Sun4m physical caches are nice since we never - * have to flush them. Unfortunately it is a pain - * to determine what size they are, since they may - * be split... - */ - switch (mmumod) { - case SUN4M_MMU_SS: - case SUN4M_MMU_MS1: - cacheinfo.c_split = 1; - cacheinfo.ic_linesize = l = - getpropint(node, "icache-line-size", 0); - for (i = 0; (1 << i) < l && l; i++) - /* void */; - if ((1 << i) != l && l) - panic("bad icache line size %d", l); - cacheinfo.ic_l2linesize = i; - cacheinfo.ic_totalsize = l * - getpropint(node, "icache-nlines", 64) * - getpropint(node, "icache-associativity", 1); - - cacheinfo.dc_linesize = l = - getpropint(node, "dcache-line-size",0); - for (i = 0; (1 << i) < l && l; i++) - /* void */; - if ((1 << i) != l && l) - panic("bad dcache line size %d", l); - cacheinfo.dc_l2linesize = i; - cacheinfo.dc_totalsize = l * - getpropint(node, "dcache-nlines", 128) * - getpropint(node, "dcache-associativity", 1); - - cacheinfo.ec_linesize = l = - getpropint(node, "ecache-line-size", 0); - for (i = 0; (1 << i) < l && l; i++) - /* void */; - if ((1 << i) != l && l) - panic("bad ecache line size %d", l); - cacheinfo.ec_l2linesize = i; - cacheinfo.ec_totalsize = l * - getpropint(node, "ecache-nlines", 32768) * - getpropint(node, "ecache-associativity", 1); + i = lda(SRMMU_PCR, ASI_SRMMU); + if (node == 0 || + (mmu_impl = + getpropint(node, "implementation", -1)) == -1) + mmu_impl = SRMMU_IMPL(i); - /* - * XXX - The following will have to do until - * we have per-cpu cache handling. - */ - cacheinfo.c_l2linesize = - min(cacheinfo.ic_l2linesize, - cacheinfo.dc_l2linesize); - cacheinfo.c_linesize = - min(cacheinfo.ic_linesize, - cacheinfo.dc_linesize); - cacheinfo.c_totalsize = - cacheinfo.ic_totalsize + - cacheinfo.dc_totalsize; - break; - case SUN4M_MMU_HS: - printf("Warning, guessing on HyperSPARC cache...\n"); - cacheinfo.c_split = 0; - i = lda(SRMMU_PCR, ASI_SRMMU); - if (i & SRMMU_PCR_CS) - cacheinfo.c_totalsize = 256 * 1024; - else - cacheinfo.c_totalsize = 128 * 1024; - /* manual says it has 4096 lines */ - cacheinfo.c_linesize = l = - cacheinfo.c_totalsize / 4096; - for (i = 0; (1 << i) < l; i++) - /* void */; - if ((1 << i) != l) - panic("bad cache line size %d", l); - cacheinfo.c_l2linesize = i; - break; - default: - printf("warning: couldn't identify cache\n"); - cacheinfo.c_totalsize = 0; - } - } else -#endif /* SUN4M */ - { - cacheinfo.c_physical = 0; - cacheinfo.c_totalsize = - getpropint(node, "vac-size", 65536); - cacheinfo.c_hwflush = - getpropint(node, "vac_hwflush", 0) | - getpropint(node, "vac-hwflush", 0); - cacheinfo.c_linesize = l = - getpropint(node, "vac-linesize", 16); - for (i = 0; (1 << i) < l; i++) - /* void */; - if ((1 << i) != l) - panic("bad cache line size %d", l); - cacheinfo.c_l2linesize = i; - vactype = VAC_WRITETHROUGH; + if (node == 0 || + (mmu_vers = getpropint(node, "version", -1)) == -1) + mmu_vers = SRMMU_VERS(i); + } else { + mmu_impl = ANY; + mmu_vers = ANY; } - + } else { /* - * Machines with "buserr-type" 1 have a bug in the cache - * chip that affects traps. (I wish I knew more about this - * mysterious buserr-type variable....) + * Get CPU version/implementation from ROM. If not + * available, assume same as boot CPU. */ - bug = (getpropint(node, "buserr-type", 0) == 1); - } -#endif /* SUN4C || SUN4M */ + cpu_impl = getpropint(node, "psr-implementation", -1); + if (cpu_impl == -1) + cpu_impl = cpuinfo.cpu_impl; + cpu_vers = getpropint(node, "psr-version", -1); + if (cpu_vers == -1) + cpu_vers = cpuinfo.cpu_vers; - if (bug) { - kvm_uncache((caddr_t)trapbase, 1); - printf("%s: cache chip bug; trap page uncached\n", - dev->dv_xname); + /* Get MMU version/implementation from ROM always */ + mmu_impl = getpropint(node, "implementation", -1); + mmu_vers = getpropint(node, "version", -1); } - if (cacheinfo.c_totalsize == 0) - return; + for (mp = cpu_conf; ; mp++) { + if (mp->arch != cputyp && mp->arch != ANY) + continue; - if (!cacheinfo.c_physical) { - printf("%s: %d byte write-%s, %d bytes/line, %cw flush ", - dev->dv_xname, cacheinfo.c_totalsize, - (vactype == VAC_WRITETHROUGH) ? "through" : "back", - cacheinfo.c_linesize, - cacheinfo.c_hwflush ? 'h' : 's'); - cache_enable(); - } else { - sep = " "; - if (cacheinfo.c_split) { - printf("%s: physical", dev->dv_xname); - if (cacheinfo.ic_totalsize > 0) { - printf("%s%dK instruction (%d b/l)", sep, - cacheinfo.ic_totalsize/1024, - cacheinfo.ic_linesize); - sep = ", "; - } - if (cacheinfo.dc_totalsize > 0) { - printf("%s%dK data (%d b/l)", sep, - cacheinfo.dc_totalsize/1024, - cacheinfo.dc_linesize); - sep = ", "; - } - if (cacheinfo.ec_totalsize > 0) { - printf("%s%dK external (%d b/l)", sep, - cacheinfo.ec_totalsize/1024, - cacheinfo.ec_linesize); +#define MATCH(x) (mp->x == x || mp->x == ANY) + if (!MATCH(cpu_impl) || + !MATCH(cpu_vers) || + !MATCH(mmu_impl) || + !MATCH(mmu_vers)) + continue; +#undef MATCH + + /* + * Got CPU type. + */ + sc->cpu_impl = cpu_impl; + sc->cpu_vers = cpu_vers; + sc->mmu_impl = mmu_impl; + sc->mmu_vers = mmu_vers; + + if (mp->minfo->cpu_match) { + /* Additional fixups */ + mp->minfo->cpu_match(sc, mp->minfo, node); + } + if (sc->cpu_name == 0) + sc->cpu_name = mp->name; + + if (sc->mmu_ncontext == 0) + sc->mmu_ncontext = mp->minfo->ncontext; + + if (sc->cpu_type == 0) + sc->cpu_type = mp->minfo->cpu_type; + + if (sc->cacheinfo.c_vactype == VAC_UNKNOWN) + sc->cacheinfo.c_vactype = mp->minfo->vactype; + + mp->minfo->getcacheinfo(sc, node); + + if (node && sc->hz == 0 && !CPU_ISSUN4/*XXX*/) { + sc->hz = getpropint(node, "clock-frequency", 0); + if (sc->hz == 0) { + /* + * Try to find it in the OpenPROM root... + */ + sc->hz = getpropint(findroot(), + "clock-frequency", 0); } - printf(" "); - } else - printf("%s: physical %dK combined cache (%d bytes/" - "line) ", dev->dv_xname, - cacheinfo.c_totalsize/1024, - cacheinfo.c_linesize); - cache_enable(); + } + + /* + * Copy CPU/MMU/Cache specific routines into cpu_softc. + */ +#define MPCOPY(x) if (sc->x == 0) sc->x = mp->minfo->x; + MPCOPY(hotfix); + MPCOPY(mmu_enable); + MPCOPY(cache_enable); + MPCOPY(get_faultstatus); + MPCOPY(cache_flush); + MPCOPY(vcache_flush_page); + MPCOPY(vcache_flush_segment); + MPCOPY(vcache_flush_region); + MPCOPY(vcache_flush_context); + MPCOPY(pcache_flush_line); +#undef MPCOPY + return; } + panic("Out of CPUs"); } /* @@ -431,50 +1128,13 @@ cpu_attach(parent, dev, aux) * */ struct info { - u_char valid; - u_char iu_impl; - u_char iu_vers; - u_char fpu_vers; + int valid; + int iu_impl; + int iu_vers; + int fpu_vers; char *name; }; -#define ANY 0xff /* match any FPU version (or, later, IU version) */ - -#if defined(SUN4C) || defined(SUN4M) -static struct info iu_types[] = { - { 1, 0x0, 0x4, 4, "MB86904" }, - { 1, 0x0, 0x0, ANY, "MB86900/1A or L64801" }, - { 1, 0x1, 0x0, ANY, "RT601 or L64811 v1" }, - { 1, 0x1, 0x1, ANY, "RT601 or L64811 v2" }, - { 1, 0x1, 0x3, ANY, "RT611" }, - { 1, 0x1, 0xf, ANY, "RT620" }, - { 1, 0x2, 0x0, ANY, "B5010" }, - { 1, 0x4, 0x0, 0, "TMS390Z50 v0 or TMS390Z55" }, - { 1, 0x4, 0x1, 0, "TMS390Z50 v1" }, - { 1, 0x4, 0x1, 4, "TMS390S10" }, - { 1, 0x5, 0x0, ANY, "MN10501" }, - { 1, 0x9, 0x0, ANY, "W8601/8701 or MB86903" }, - { 0 } -}; - -static char * -psrtoname(impl, vers, fver, buf) - register int impl, vers, fver; - char *buf; -{ - register struct info *p; - - for (p = iu_types; p->valid; p++) - if (p->iu_impl == impl && p->iu_vers == vers && - (p->fpu_vers == fver || p->fpu_vers == ANY)) - return (p->name); - - /* Not found. */ - sprintf(buf, "IU impl 0x%x vers 0x%x", impl, vers); - return (buf); -} -#endif /* SUN4C || SUN4M */ - /* NB: table order matters here; specific numbers must appear before ANY. */ static struct info fpu_types[] = { /* @@ -485,6 +1145,7 @@ static struct info fpu_types[] = { { 1, 0x0, ANY, 2, "L64802 or ACT8847" }, { 1, 0x0, ANY, 3, "WTL3170/2" }, { 1, 0x0, 4, 4, "on-chip" }, /* Swift */ + { 1, 0x0, 5, 5, "on-chip" }, /* TurboSparc */ { 1, 0x0, ANY, 4, "L64804" }, /* @@ -532,6 +1193,6 @@ fsrtoname(impl, vers, fver, buf) (p->iu_vers == vers || p->iu_vers == ANY) && (p->fpu_vers == fver)) return (p->name); - sprintf(buf, "version %x", fver); + sprintf(buf, "version 0x%x", fver); return (buf); } diff --git a/sys/arch/sparc/sparc/db_disasm.c b/sys/arch/sparc/sparc/db_disasm.c index 901597194d3..344a557cc7e 100644 --- a/sys/arch/sparc/sparc/db_disasm.c +++ b/sys/arch/sparc/sparc/db_disasm.c @@ -1,3 +1,4 @@ +/* $OpenBSD: db_disasm.c,v 1.3 1997/08/08 08:27:11 downsj Exp $ */ /* $NetBSD: db_disasm.c,v 1.9 1996/03/31 23:45:07 pk Exp $ */ /* diff --git a/sys/arch/sparc/sparc/db_interface.c b/sys/arch/sparc/sparc/db_interface.c index 013e80a046f..0414ca1af53 100644 --- a/sys/arch/sparc/sparc/db_interface.c +++ b/sys/arch/sparc/sparc/db_interface.c @@ -1,4 +1,5 @@ -/* $NetBSD: db_interface.c,v 1.12 1996/05/18 12:27:45 mrg Exp $ */ +/* $OpenBSD: db_interface.c,v 1.5 1997/08/08 08:27:12 downsj Exp $ */ +/* $NetBSD: db_interface.c,v 1.15 1997/02/05 00:01:50 pk Exp $ */ /* * Mach Operating System diff --git a/sys/arch/sparc/sparc/db_trace.c b/sys/arch/sparc/sparc/db_trace.c index 8da02ce3082..3fc0c8e56eb 100644 --- a/sys/arch/sparc/sparc/db_trace.c +++ b/sys/arch/sparc/sparc/db_trace.c @@ -1,4 +1,5 @@ -/* $NetBSD: db_trace.c,v 1.8 1996/04/04 23:25:35 pk Exp $ */ +/* $OpenBSD: db_trace.c,v 1.3 1997/08/08 08:27:13 downsj Exp $ */ +/* $NetBSD: db_trace.c,v 1.9 1997/07/29 09:42:00 fair Exp $ */ /* * Mach Operating System @@ -90,8 +91,8 @@ db_stack_trace_cmd(addr, have_addr, count, modif) * actual arguments somewhat... */ for (i=0; i < 5; i++) - db_printf("%x, ", frame->fr_arg[i]); - db_printf("%x) at ", frame->fr_arg[i]); + db_printf("0x%x, ", frame->fr_arg[i]); + db_printf("0x%x) at ", frame->fr_arg[i]); db_printsym(pc, DB_STGY_PROC); db_printf("\n"); diff --git a/sys/arch/sparc/sparc/genassym.cf b/sys/arch/sparc/sparc/genassym.cf index 338ff4b89b0..68951337bdb 100644 --- a/sys/arch/sparc/sparc/genassym.cf +++ b/sys/arch/sparc/sparc/genassym.cf @@ -1,5 +1,8 @@ -# $OpenBSD: genassym.cf,v 1.1 1997/06/25 14:47:12 downsj Exp $ +# $OpenBSD: genassym.cf,v 1.2 1997/08/08 08:27:14 downsj Exp $ +# $NetBSD: genassym.cf,v 1.2 1997/06/28 19:59:04 pk Exp $ + # +# Copyright (c) 1997 Christos Zoulas. All rights reserved. # Copyright (c) 1992, 1993 # The Regents of the University of California. All rights reserved. # @@ -62,10 +65,13 @@ include <machine/cpu.h> include <machine/oldmon.h> include <machine/bsd_openprom.h> +include <sparc/sparc/cpuvar.h> + ifdef notyet include <sparc/dev/zsreg.h> include <sparc/dev/zsvar.h> endif + include <dev/ic/am7930reg.h> include <sparc/dev/amd7930var.h> @@ -86,22 +92,25 @@ define P_VMSPACE offsetof(struct proc, p_vmspace) define SRUN SRUN # VM structure fields -define VM_PMAP offsetof(struct vmspace, vm_pmap) -define VM_PMAP_CTX offsetof(struct vmspace, vm_pmap.pm_ctx) -define VM_PMAP_CTXNUM offsetof(struct vmspace, vm_pmap.pm_ctxnum) +define VM_PMAP offsetof(struct vmspace, vm_map.pmap) +define PMAP_CTX offsetof(struct pmap, pm_ctx) +define PMAP_CTXNUM offsetof(struct pmap, pm_ctxnum) # interrupt/fault metering define V_SWTCH offsetof(struct vmmeter, v_swtch) define V_INTR offsetof(struct vmmeter, v_intr) define V_FAULTS offsetof(struct vmmeter, v_faults) +# CPU info structure +define CPUINFO_FAULTSTATUS offsetof(struct cpu_softc, get_faultstatus) + # PTE bits and related information define PG_W PG_W define PG_VSHIFT PG_VSHIFT define PG_PROTSHIFT PG_PROTSHIFT define PG_PROTUREAD PG_PROTUREAD define PG_PROTUWRITE PG_PROTUWRITE -ifdef SUN4M +if defined(SUN4M) define SRMMU_TETYPE SRMMU_TETYPE define SRMMU_TEPTE SRMMU_TEPTE define SRMMU_PROT_MASK SRMMU_PROT_MASK @@ -138,13 +147,13 @@ define PCB_UW offsetof(struct pcb, pcb_uw) define PCB_WIM offsetof(struct pcb, pcb_wim) # interrupt enable register PTE -define IE_REG_PTE_PG PG_V | PG_W | PG_S | PG_NC | PG_OBIO +define IE_REG_PTE_PG (PG_V | PG_W | PG_S | PG_NC | PG_OBIO) ifdef notyet # ZSCC interrupt fields define ZSC_A offsetof(struct zs_softc, sc_a) define ZSC_B offsetof(struct zs_softc, sc_b) -# define ZL_WREG offsetof(struct zs_line, zl_wreg) +define ZL_WREG offsetof(struct zs_line, zl_wreg) define ZL_TBC offsetof(struct zs_line, zl_tbc) define ZL_TBA offsetof(struct zs_line, zl_tba) define ZL_RBPUT offsetof(struct zs_line, zl_rbput) diff --git a/sys/arch/sparc/sparc/in_cksum.c b/sys/arch/sparc/sparc/in_cksum.c index 991dd17cc18..a6e0a86371a 100644 --- a/sys/arch/sparc/sparc/in_cksum.c +++ b/sys/arch/sparc/sparc/in_cksum.c @@ -1,9 +1,9 @@ -/* $NetBSD: in_cksum.c,v 1.3 1995/04/26 13:30:03 pk Exp $ */ +/* $OpenBSD: in_cksum.c,v 1.8 1997/08/08 08:27:15 downsj Exp $ */ +/* $NetBSD: in_cksum.c,v 1.7 1996/10/05 23:44:34 mrg Exp $ */ /* * Copyright (c) 1995 Zubin Dittia. - * Copyright (c) 1995 Theo de Raadt. - * Copyright (c) 1995 Matthew Green. + * Copyright (c) 1995 Matthew R. Green. * Copyright (c) 1994 Charles Hannum. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -46,7 +46,6 @@ #include <sys/param.h> #include <sys/mbuf.h> - #include <netinet/in.h> /* @@ -74,8 +73,8 @@ * Another possible optimization is to replace a pair of 32-bit loads * with a single 64-bit load (ldd) instruction, but I found that although * this improves performance somewhat on Sun4c machines, it actually - * reduces performance considerably on Sun4m machines (because of their - * superscaler architecture). So I chose to leave it out. + * reduces performance considerably on Sun4m machines (I don't know why). + * So I chose to leave it out. * * Zubin Dittia (zubin@dworkin.wustl.edu) */ @@ -150,7 +149,8 @@ in_cksum(m, len) * allow the compiler to pick which specific machine registers to * use, instead of hard-coding this in the asm code above. */ - register u_int tmp1, tmp2; + /* XXX - initialized because of gcc's `-Wuninitialized' ! */ + register u_int tmp1 = 0, tmp2 = 0; for (; m && len; m = m->m_next) { if (m->m_len == 0) @@ -160,7 +160,7 @@ in_cksum(m, len) if (len < mlen) mlen = len; len -= mlen; - + /* * Ensure that we're aligned on a word boundary here so * that we can do 32 bit operations below. diff --git a/sys/arch/sparc/sparc/intersil7170.h b/sys/arch/sparc/sparc/intersil7170.h deleted file mode 100644 index b91f526e62e..00000000000 --- a/sys/arch/sparc/sparc/intersil7170.h +++ /dev/null @@ -1,90 +0,0 @@ -/* $NetBSD: intersil7170.h,v 1.3 1996/05/02 18:17:40 pk 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. - */ - -/* - * Driver support for the intersil7170 used in sun[34]s to provide - * real time clock and time-of-day support. - * - * Derived from: datasheet "ICM7170 a uP-Compatible Real-Time Clock" - * document #301680-005, Dec 85 - */ - -struct date_time { /* from p. 7 of 10 */ - volatile unsigned char dt_csec; - volatile unsigned char dt_hour; - volatile unsigned char dt_min; - volatile unsigned char dt_sec; - volatile unsigned char dt_month; - volatile unsigned char dt_day; - volatile unsigned char dt_year; - volatile unsigned char dt_dow; -}; - -struct intersil7170 { - struct date_time counters; - struct date_time clk_ram; /* should be ok as both are word aligned */ - volatile unsigned char clk_intr_reg; - volatile unsigned char clk_cmd_reg; -}; - -/* bit assignments for command register, p. 6 of 10, write-only */ -#define INTERSIL_CMD_FREQ_32K 0x0 -#define INTERSIL_CMD_FREQ_1M 0x1 -#define INTERSIL_CMD_FREQ_2M 0x2 -#define INTERSIL_CMD_FREQ_4M 0x3 - -#define INTERSIL_CMD_12HR_MODE 0x0 -#define INTERSIL_CMD_24HR_MODE 0x4 - -#define INTERSIL_CMD_STOP 0x0 -#define INTERSIL_CMD_RUN 0x8 - -#define INTERSIL_CMD_IDISABLE 0x0 -#define INTERSIL_CMD_IENABLE 0x10 - -#define INTERSIL_CMD_TEST_MODE 0x20 -#define INTERSIL_CMD_NORMAL_MODE 0x0 - -/* bit assignments for interrupt register r/w, p 7 of 10*/ - -#define INTERSIL_INTER_ALARM 0x1 /* r/w */ -#define INTERSIL_INTER_CSECONDS 0x2 /* r/w */ -#define INTERSIL_INTER_DSECONDS 0x4 /* r/w */ -#define INTERSIL_INTER_SECONDS 0x8 /* r/w */ -#define INTERSIL_INTER_MINUTES 0x10 /* r/w */ -#define INTERSIL_INTER_HOURS 0x20 /* r/w */ -#define INTERSIL_INTER_DAYS 0x40 /* r/w */ -#define INTERSIL_INTER_PENDING 0x80 /* read-only */ - -#define INTERSIL_INTER_BITS "\20\10PENDING\7DAYS\6HRS\5MIN\4SCDS\3DSEC\2CSEC\1ALARM" - diff --git a/sys/arch/sparc/sparc/intr.c b/sys/arch/sparc/sparc/intr.c index e4ca57141b4..7ca610c248e 100644 --- a/sys/arch/sparc/sparc/intr.c +++ b/sys/arch/sparc/sparc/intr.c @@ -1,4 +1,4 @@ -/* $NetBSD: intr.c,v 1.13 1996/03/31 23:35:20 pk Exp $ */ +/* $NetBSD: intr.c,v 1.20 1997/07/29 09:42:03 fair Exp $ */ /* * Copyright (c) 1992, 1993 @@ -44,8 +44,6 @@ * @(#)intr.c 8.3 (Berkeley) 11/11/93 */ -#include "ppp.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -68,9 +66,6 @@ #include <netinet/if_ether.h> #include <netinet/ip_var.h> #endif -#ifdef NETATALK -#include <netatalk/at_extern.h> -#endif #ifdef NS #include <netns/ns_var.h> #endif @@ -78,6 +73,9 @@ #include <netiso/iso.h> #include <netiso/clnp.h> #endif +#ifdef NETATALK +#include <netatalk/at_extern.h> +#endif #include "ppp.h" #if NPPP > 0 #include <net/ppp_defs.h> @@ -98,7 +96,7 @@ strayintr(fp) static int straytime, nstray; int timesince; - printf("stray interrupt ipl %x pc=%x npc=%x psr=%b\n", + printf("stray interrupt ipl 0x%x pc=0x%x npc=0x%x psr=%b\n", fp->ipl, fp->pc, fp->npc, fp->psr, PSR_BITS); timesince = time.tv_sec - straytime; if (timesince <= 10) { @@ -160,6 +158,10 @@ soft01intr(fp) if (n & (1 << NETISR_ISO)) clnlintr(); #endif +#ifdef NATM + if (n & (1 << NETISR_NATM)) + natmintr(); +#endif #if NPPP > 0 if (n & (1 << NETISR_PPP)) pppintr(); @@ -236,7 +238,7 @@ intr_establish(level, ih) if (tv->tv_instr[0] != I_MOVi(I_L3, level) || tv->tv_instr[1] != I_BA(0, displ) || tv->tv_instr[2] != I_RDPSR(I_L0)) - panic("intr_establish(%d, %p)\n%x %x %x != %x %x %x", + panic("intr_establish(%d, %p)\n0x%x 0x%x 0x%x != 0x%x 0x%x 0x%x", level, ih, tv->tv_instr[0], tv->tv_instr[1], tv->tv_instr[2], I_MOVi(I_L3, level), I_BA(0, displ), I_RDPSR(I_L0)); @@ -285,7 +287,7 @@ intr_fasttrap(level, vec) if (tv->tv_instr[0] != I_MOVi(I_L3, level) || tv->tv_instr[1] != I_BA(0, displ) || tv->tv_instr[2] != I_RDPSR(I_L0)) - panic("intr_fasttrap(%d, %p)\n%x %x %x != %x %x %x", + panic("intr_fasttrap(%d, %p)\n0x%x 0x%x 0x%x != 0x%x 0x%x 0x%x", level, vec, tv->tv_instr[0], tv->tv_instr[1], tv->tv_instr[2], I_MOVi(I_L3, level), I_BA(0, displ), I_RDPSR(I_L0)); diff --git a/sys/arch/sparc/sparc/intreg.h b/sys/arch/sparc/sparc/intreg.h index 5abbb8342f1..e74859f6327 100644 --- a/sys/arch/sparc/sparc/intreg.h +++ b/sys/arch/sparc/sparc/intreg.h @@ -1,4 +1,5 @@ -/* $NetBSD: intreg.h,v 1.5 1996/03/31 23:03:39 pk Exp $ */ +/* $OpenBSD: intreg.h,v 1.3 1997/08/08 08:27:19 downsj Exp $ */ +/* $NetBSD: intreg.h,v 1.6 1997/07/22 20:19:10 pk Exp $ */ /* * Copyright (c) 1992, 1993 @@ -121,18 +122,20 @@ void ienab_bic __P((int bic)); /* clear given bits */ #define SINTR_ME 0x40000000 /* Module Error (async) */ #define SINTR_I 0x20000000 /* MSI (MBus-SBus) */ #define SINTR_M 0x10000000 /* ECC Memory controller */ -#define SINTR_RSVD2 0x0f800000 +#define SINTR_V 0x08000000 /* VME Async error */ +#define SINTR_RSVD2 0x07800000 #define SINTR_F 0x00400000 /* Floppy */ -#define SINTR_RSVD3 0x00200000 -#define SINTR_V 0x00100000 /* Video (Supersparc only) */ +#define SINTR_MI 0x00200000 /* Module interrupt */ +#define SINTR_VI 0x00100000 /* Video (Supersparc only) */ #define SINTR_T 0x00080000 /* Level 10 counter */ #define SINTR_SC 0x00040000 /* SCSI */ -#define SINTR_RSVD4 0x00020000 +#define SINTR_A 0x00020000 /* Audio/ISDN */ #define SINTR_E 0x00010000 /* Ethernet */ #define SINTR_S 0x00008000 /* Serial port */ #define SINTR_K 0x00004000 /* Keyboard/mouse */ #define SINTR_SBUSMASK 0x00003f80 /* SBus */ -#define SINTR_SBUS(n) (((n) << 7) & 0x00003f80) -#define SINTR_RSVD5 0x0000007f +#define SINTR_SBUS(n) (1 << (7+(n)-1)) +#define SINTR_VMEMASK 0x0000007f /* VME */ +#define SINTR_VME(n) (1 << ((n)-1)) #endif diff --git a/sys/arch/sparc/sparc/iommu.c b/sys/arch/sparc/sparc/iommu.c index 765bca78d17..91d125afae4 100644 --- a/sys/arch/sparc/sparc/iommu.c +++ b/sys/arch/sparc/sparc/iommu.c @@ -1,4 +1,5 @@ -/* $NetBSD: iommu.c,v 1.4 1996/05/21 07:25:07 pk Exp $ */ +/* $OpenBSD: iommu.c,v 1.3 1997/08/08 08:27:20 downsj Exp $ */ +/* $NetBSD: iommu.c,v 1.13 1997/07/29 09:42:04 fair Exp $ */ /* * Copyright (c) 1996 @@ -45,6 +46,7 @@ #include <machine/ctlreg.h> #include <sparc/sparc/asm.h> #include <sparc/sparc/vaddrs.h> +#include <sparc/sparc/cpuvar.h> #include <sparc/sparc/iommureg.h> struct iommu_softc { @@ -96,7 +98,7 @@ iommu_match(parent, vcf, aux) struct device *parent; void *vcf, *aux; { - struct cfdata *cf = vcf; + register struct cfdata *cf = vcf; register struct confargs *ca = aux; register struct romaux *ra = &ca->ca_ra; @@ -121,12 +123,12 @@ iommu_attach(parent, self, aux) register int node; register char *name; register u_int pbase, pa; - register int i, mmupcrsav, s, wierdviking = 0; + register int i, mmupcrsave, s; register iopte_t *tpte_p; extern u_int *kernel_iopte_table; extern u_int kernel_iopte_table_pa; -/*XXX-GCC!*/mmupcrsav=0; +/*XXX-GCC!*/mmupcrsave=0; iommu_sc = sc; /* * XXX there is only one iommu, for now -- do not know how to @@ -151,10 +153,12 @@ iommu_attach(parent, self, aux) * other fields for? */ sc->sc_reg = (struct iommureg *) - mapdev(ra->ra_reg, 0, 0, ra->ra_len, ra->ra_iospace); + mapiodev(ra->ra_reg, 0, ra->ra_len); #endif sc->sc_hasiocache = node_has_property(node, "cache-coherence?"); + if (CACHEINFO.c_enabled == 0) /* XXX - is this correct? */ + sc->sc_hasiocache = 0; has_iocache = sc->sc_hasiocache; /* Set global flag */ sc->sc_pagesize = getpropint(node, "page-size", NBPG), @@ -191,10 +195,10 @@ iommu_attach(parent, self, aux) * * XXX: PGOFSET, NBPG assume same page size as SRMMU */ - if ((getpsr() & 0x40000000) && (!(lda(SRMMU_PCR,ASI_SRMMU) & 0x800))) { - wierdviking = 1; - sta(SRMMU_PCR, ASI_SRMMU, /* set MMU AC bit */ - ((mmupcrsav = lda(SRMMU_PCR,ASI_SRMMU)) | SRMMU_PCR_AC)); + if (cpuinfo.cpu_vers == 4 && cpuinfo.mxcc) { + /* set MMU AC bit */ + sta(SRMMU_PCR, ASI_SRMMU, + ((mmupcrsave = lda(SRMMU_PCR, ASI_SRMMU)) | VIKING_PCR_AC)); } for (tpte_p = &sc->sc_ptes[((0 - DVMA4M_BASE)/NBPG) - 1], @@ -207,8 +211,9 @@ iommu_attach(parent, self, aux) (tpte_p - &sc->sc_ptes[0])*NBPG + DVMA4M_BASE); *tpte_p = lda(pa, ASI_BYPASS); } - if (wierdviking) { /* restore mmu after bug-avoidance */ - sta(SRMMU_PCR, ASI_SRMMU, mmupcrsav); + if (cpuinfo.cpu_vers == 4 && cpuinfo.mxcc) { + /* restore mmu after bug-avoidance */ + sta(SRMMU_PCR, ASI_SRMMU, mmupcrsave); } /* @@ -232,7 +237,7 @@ iommu_attach(parent, self, aux) IOMMU_FLUSHALL(sc); splx(s); - printf(": version %x/%x, page-size %d, range %dMB\n", + printf(": version 0x%x/0x%x, page-size %d, range %dMB\n", (sc->sc_reg->io_cr & IOMMU_CTL_VER) >> 24, (sc->sc_reg->io_cr & IOMMU_CTL_IMPL) >> 28, sc->sc_pagesize, @@ -299,7 +304,6 @@ iommu_remove(va, len) #endif #endif sc->sc_ptes[atop(va - sc->sc_dvmabase)] = 0; - sta(sc->sc_ptes + atop(va - sc->sc_dvmabase), ASI_BYPASS, 0); IOMMU_FLUSHPAGE(sc, va); len -= sc->sc_pagesize; va += sc->sc_pagesize; @@ -313,8 +317,8 @@ iommu_error() struct iommu_softc *sc = X; struct iommureg *iop = sc->sc_reg; - printf("iommu: afsr %x, afar %x\n", iop->io_afsr, iop->io_afar); - printf("iommu: mfsr %x, mfar %x\n", iop->io_mfsr, iop->io_mfar); + printf("iommu: afsr 0x%x, afar 0x%x\n", iop->io_afsr, iop->io_afar); + printf("iommu: mfsr 0x%x, mfar 0x%x\n", iop->io_mfsr, iop->io_mfar); } int iommu_alloc(va, len) diff --git a/sys/arch/sparc/sparc/iommureg.h b/sys/arch/sparc/sparc/iommureg.h index 24c5ac9f8cf..021e32f09e0 100644 --- a/sys/arch/sparc/sparc/iommureg.h +++ b/sys/arch/sparc/sparc/iommureg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: iommureg.h,v 1.2 1997/08/08 08:27:22 downsj Exp $ */ /* $NetBSD: iommureg.h,v 1.2 1996/05/16 15:57:18 abrown Exp $ */ /* diff --git a/sys/arch/sparc/sparc/kgdb_proto.h b/sys/arch/sparc/sparc/kgdb_proto.h index 8d1869a3a47..bc2c777ddea 100644 --- a/sys/arch/sparc/sparc/kgdb_proto.h +++ b/sys/arch/sparc/sparc/kgdb_proto.h @@ -1,3 +1,4 @@ +/* $OpenBSD: kgdb_proto.h,v 1.3 1997/08/08 08:27:23 downsj Exp $ */ /* $NetBSD: kgdb_proto.h,v 1.4 1996/05/16 15:57:19 abrown Exp $ */ /* diff --git a/sys/arch/sparc/sparc/kgdb_stub.c b/sys/arch/sparc/sparc/kgdb_stub.c index 3ba0c5e9975..15f3f2b9d35 100644 --- a/sys/arch/sparc/sparc/kgdb_stub.c +++ b/sys/arch/sparc/sparc/kgdb_stub.c @@ -1,4 +1,5 @@ -/* $NetBSD: kgdb_stub.c,v 1.8 1996/05/16 15:57:20 abrown Exp $ */ +/* $OpenBSD: kgdb_stub.c,v 1.3 1997/08/08 08:27:24 downsj Exp $ */ +/* $NetBSD: kgdb_stub.c,v 1.10 1996/10/13 03:00:36 christos Exp $ */ /* * Copyright (c) 1992, 1993 diff --git a/sys/arch/sparc/sparc/locore.s b/sys/arch/sparc/sparc/locore.s index 4826e06aa56..8878d8048bc 100644 --- a/sys/arch/sparc/sparc/locore.s +++ b/sys/arch/sparc/sparc/locore.s @@ -1,3 +1,6 @@ +/* $OpenBSD: locore.s,v 1.17 1997/08/08 08:27:27 downsj Exp $ */ +/* $NetBSD: locore.s,v 1.72 1997/07/07 20:06:42 pk Exp $ */ + /* * Copyright (c) 1996 Paul Kranenburg * Copyright (c) 1996 @@ -64,7 +67,6 @@ #include <compat/svr4/svr4_syscall.h> #endif - /* * GNU assembler does not understand `.empty' directive; Sun assembler * gripes about labels without it. To allow cross-compilation using @@ -270,19 +272,6 @@ sun4_notsup: _msgbuf = KERNBASE /* - * We need to map the interrupt enable register very early on in the - * boot process, so that we can handle NMIs (parity errors) halfway - * sensibly during boot. We use virtual address f8002000 (`page 2') - * for this, wasting a page of physical memory. - * - * This doesn't work for the Sun4M, which can have 5 or more pages of - * registers, a system register and one for each processor. Thus we use - * a reserved piece of the virtual address space, set up in bootstrap(). - */ - -IE_reg_addr = INTRREG_VA ! KERNBASE + 8192 - points to IEreg - -/* * Each trap has room for four instructions, of which one perforce must * be a branch. On entry the hardware has copied pc and npc to %l1 and * %l2 respectively. We use two more to read the psr into %l0, and to @@ -1156,7 +1145,7 @@ trapbase_sun4m: * need to .skip 4096 to pad to page size iff. the number of trap tables * defined above is odd. */ -#if defined(SUN4) + defined(SUN4C) + defined(SUN4M) - 2 == 0 +#if (defined(SUN4) + defined(SUN4C) + defined(SUN4M)) % 2 == 1 .skip 4096 #endif @@ -1294,47 +1283,44 @@ Lpanic_red: #endif /* 4m */ #if defined(SUN4M) && !(defined(SUN4C) || defined(SUN4)) -#define PTE_OF_ADDR PTE_OF_ADDR4M -#define CMP_PTE_USER_WRITE(pte,tmp) CMP_PTE_USER_WRITE4M(pte) -#define CMP_PTE_USER_READ(pte,tmp) CMP_PTE_USER_READ4M(pte) + +#define PTE_OF_ADDR(addr, pte, bad, page_offset, label) \ + PTE_OF_ADDR4M(addr, pte, bad, page_offset) +#define CMP_PTE_USER_WRITE(pte, tmp, label) CMP_PTE_USER_WRITE4M(pte) +#define CMP_PTE_USER_READ(pte, tmp, label) CMP_PTE_USER_READ4M(pte) + #elif (defined(SUN4C) || defined(SUN4)) && !defined(SUN4M) -#define PTE_OF_ADDR PTE_OF_ADDR4_4C -#define CMP_PTE_USER_WRITE(pte,tmp) CMP_PTE_USER_WRITE4_4C(pte) -#define CMP_PTE_USER_READ(pte,tmp) CMP_PTE_USER_READ4_4C(pte) + +#define PTE_OF_ADDR(addr, pte, bad, page_offset,label) \ + PTE_OF_ADDR4_4C(addr, pte, bad, page_offset) +#define CMP_PTE_USER_WRITE(pte, tmp, label) CMP_PTE_USER_WRITE4_4C(pte) +#define CMP_PTE_USER_READ(pte, tmp, label) CMP_PTE_USER_READ4_4C(pte) + #else /* both defined, ugh */ -#define PTE_OF_ADDR(addr, pte, bad, page_offset) \ - sethi %hi(_cputyp), pte; \ - ld [pte + %lo(_cputyp)], pte; \ - cmp pte, CPU_SUN4M; \ - bne 2f; nop; \ + +#define PTE_OF_ADDR(addr, pte, bad, page_offset, label) \ +label: b,a 2f; \ PTE_OF_ADDR4M(addr, pte, bad, page_offset); \ b,a 3f; \ 2: \ PTE_OF_ADDR4_4C(addr, pte, bad, page_offset); \ 3: -#define CMP_PTE_USER_READ(pte, tmp) \ - sethi %hi(_cputyp), tmp; \ - ld [tmp + %lo(_cputyp)], tmp; \ - cmp tmp, CPU_SUN4M; \ - bne 1f; nop; \ +#define CMP_PTE_USER_READ(pte, tmp, label) \ +label: b,a 1f; \ CMP_PTE_USER_READ4M(pte); \ b,a 2f; \ 1: \ CMP_PTE_USER_READ4_4C(pte); \ 2: -#define CMP_PTE_USER_WRITE(pte, tmp) \ - sethi %hi(_cputyp), tmp; \ - ld [tmp + %lo(_cputyp)], tmp; \ - cmp tmp, CPU_SUN4M; \ - bne 1f; nop; \ +#define CMP_PTE_USER_WRITE(pte, tmp, label) \ +label: b,a 1f; \ CMP_PTE_USER_WRITE4M(pte); \ b,a 2f; \ 1: \ CMP_PTE_USER_WRITE4_4C(pte); \ 2: - #endif @@ -1605,8 +1591,8 @@ ctw_user: sethi %hi(_pgofset), %g6 ! trash %g6=curpcb ld [%g6 + %lo(_pgofset)], %g6 - PTE_OF_ADDR(%sp, %g7, ctw_invalid, %g6) - CMP_PTE_USER_WRITE(%g7, %g5) ! likewise if not writable + PTE_OF_ADDR(%sp, %g7, ctw_invalid, %g6, NOP_ON_4M_1) + CMP_PTE_USER_WRITE(%g7, %g5, NOP_ON_4M_2) ! likewise if not writable bne ctw_invalid EMPTY /* Note side-effect of SLT_IF_1PAGE_RW: decrements %g6 by 62 */ @@ -1615,8 +1601,8 @@ ctw_user: std %l0, [%sp] add %sp, 7*8, %g5 ! check last addr too add %g6, 62, %g6 ! restore %g6 to `pgofset' - PTE_OF_ADDR(%g5, %g7, ctw_invalid, %g6) - CMP_PTE_USER_WRITE(%g7, %g6) + PTE_OF_ADDR(%g5, %g7, ctw_invalid, %g6, NOP_ON_4M_3) + CMP_PTE_USER_WRITE(%g7, %g6, NOP_ON_4M_4) be,a ctw_merge ! all ok: store <l0,l1> and merge std %l0, [%sp] @@ -1828,10 +1814,10 @@ memfault_sun4c: * This code is essentially the same as that at `nmi' below, * but the register usage is different and we cannot merge. */ - sethi %hi(IE_reg_addr), %l5 ! ienab_bic(IE_ALLIE); - ldub [%l5 + %lo(IE_reg_addr)], %o0 + sethi %hi(INTRREG_VA), %l5 ! ienab_bic(IE_ALLIE); + ldub [%l5 + %lo(INTRREG_VA)], %o0 andn %o0, IE_ALLIE, %o0 - stb %o0, [%l5 + %lo(IE_reg_addr)] + stb %o0, [%l5 + %lo(INTRREG_VA)] /* * Now reenable traps and call C code. @@ -1848,9 +1834,9 @@ memfault_sun4c: ldd [%sp + CCFSZ + 32], %g4 ldd [%sp + CCFSZ + 40], %g6 /* now safe to set IE_ALLIE again */ - ldub [%l5 + %lo(IE_reg_addr)], %o1 + ldub [%l5 + %lo(INTRREG_VA)], %o1 or %o1, IE_ALLIE, %o1 - stb %o1, [%l5 + %lo(IE_reg_addr)] + stb %o1, [%l5 + %lo(INTRREG_VA)] b return_from_trap wr %l4, 0, %y ! restore y @@ -1880,29 +1866,15 @@ memfault_sun4m: st %g1, [%sp + CCFSZ + 20] ! save g1 rd %y, %l4 ! save y - set SRMMU_SFADDR, %o0 std %g2, [%sp + CCFSZ + 24] ! save g2, g3 - lda [%o0] ASI_SRMMU, %o2 ! sync virt addr; must be read first - set SRMMU_SFSTAT, %o0 - lda [%o0] ASI_SRMMU, %o1 ! get sync fault status register - std %g4, [%sp + CCFSZ + 32] ! (sneak g4,g5 in here) + std %g4, [%sp + CCFSZ + 32] ! save g4, g5 - /* Now test for a HyperSPARC. If we have one, get the async status */ - sethi %hi(_mmumod), %o3 ! get MMU model - ld [%o3 + %lo(_mmumod)], %o3 - cmp %o3, SUN4M_MMU_HS ! is it hypersparc? - std %g6, [%sp + CCFSZ + 40] ! sneak in g6, g7 - be 1f ! yup, skip ahead + ! get fault status/address + set CPUINFO_VA+CPUINFO_FAULTSTATUS, %o0 + ld [%o0], %o0 + jmpl %o0, %o7 + std %g6, [%sp + CCFSZ + 40] ! sneak in g6, g7 - clr %o3 ! clear %o3 and %o4, not hypersparc - b 2f - clr %o4 -1: - set SRMMU_AFSTAT, %o3 ! must read status before fault on HS - lda [%o3] ASI_SRMMU, %o3 ! get async fault status - set SRMMU_AFADDR, %o4 - lda [%o4] ASI_SRMMU, %o4 ! get async fault address -2: wr %l0, PSR_ET, %psr ! reenable traps /* Finish stackframe, call C trap handler */ @@ -2329,10 +2301,10 @@ return_from_syscall: */ .comm _intrhand, 15 * 8 ! intrhand[0..14]; 0 => error softintr_sun44c: - sethi %hi(IE_reg_addr), %l6 - ldub [%l6 + %lo(IE_reg_addr)], %l5 + sethi %hi(INTRREG_VA), %l6 + ldub [%l6 + %lo(INTRREG_VA)], %l5 andn %l5, %l4, %l5 - stb %l5, [%l6 + %lo(IE_reg_addr)] + stb %l5, [%l6 + %lo(INTRREG_VA)] softintr_common: INTR_SETUP(-CCFSZ-80) @@ -2498,10 +2470,10 @@ nmi_sun4: * Level 15 interrupts are nonmaskable, so with traps off, * disable all interrupts to prevent recursion. */ - sethi %hi(IE_reg_addr), %o0 - ldub [%o0 + %lo(IE_reg_addr)], %o1 + sethi %hi(INTRREG_VA), %o0 + ldub [%o0 + %lo(INTRREG_VA)], %o1 andn %o0, IE_ALLIE, %o1 - stb %o1, [%o0 + %lo(IE_reg_addr)] + stb %o1, [%o0 + %lo(INTRREG_VA)] wr %l0, PSR_ET, %psr ! okay, turn traps on again std %g2, [%sp + CCFSZ + 0] ! save g2, g3 @@ -2524,10 +2496,10 @@ nmi_sun4c: * Level 15 interrupts are nonmaskable, so with traps off, * disable all interrupts to prevent recursion. */ - sethi %hi(IE_reg_addr), %o0 - ldub [%o0 + %lo(IE_reg_addr)], %o1 + sethi %hi(INTRREG_VA), %o0 + ldub [%o0 + %lo(INTRREG_VA)], %o1 andn %o0, IE_ALLIE, %o1 - stb %o1, [%o0 + %lo(IE_reg_addr)] + stb %o1, [%o0 + %lo(INTRREG_VA)] wr %l0, PSR_ET, %psr ! okay, turn traps on again std %g2, [%sp + CCFSZ + 0] ! save g2, g3 @@ -2564,10 +2536,10 @@ nmi_common: mov %l7, %g7 ! set IE_ALLIE again (safe, we disabled traps again above) - sethi %hi(IE_reg_addr), %o0 - ldub [%o0 + %lo(IE_reg_addr)], %o1 + sethi %hi(INTRREG_VA), %o0 + ldub [%o0 + %lo(INTRREG_VA)], %o1 or %o1, IE_ALLIE, %o1 - stb %o1, [%o0 + %lo(IE_reg_addr)] + stb %o1, [%o0 + %lo(INTRREG_VA)] b return_from_trap wr %l4, 0, %y ! restore y @@ -2595,28 +2567,11 @@ nmi_sun4m: rd %y, %l4 ! save y ! now read sync error registers - set SRMMU_SFADDR, %o0 - lda [%o0] ASI_SRMMU, %o2 ! sync virt addr - set SRMMU_SFSTAT, %o0 - lda [%o0] ASI_SRMMU, %o1 ! sync err reg - std %g4, [%sp + CCFSZ + 8] ! save g4,g5 - - /* Now test for a HyperSPARC. If we have one, get the async status */ - - sethi %hi(_mmumod), %o3 ! get MMU model - ld [%o3 + %lo(_mmumod)], %o3 - cmp %o3, SUN4M_MMU_HS ! is it hypersparc? - be 1f ! yup, skip ahead + set CPUINFO_VA+CPUINFO_FAULTSTATUS, %o0 + ld [%o0], %o0 + jmpl %o0, %o7 + std %g4, [%sp + CCFSZ + 8] ! save g4,g5 - clr %o3 ! clear %o3 and %o4, not hypersparc - b 2f - clr %o4 -1: - set SRMMU_AFSTAT, %o3 ! read status first on hypersparc - lda [%o3] ASI_SRMMU, %o3 ! get async fault status - set SRMMU_AFADDR, %o4 - lda [%o4] ASI_SRMMU, %o4 ! get async fault address -2: /* Finish stackframe, call C trap handler */ mov %g1, %l5 ! save g1,g6,g7 mov %g6, %l6 @@ -2822,8 +2777,8 @@ winuf_user: sethi %hi(_pgofset), %l4 ld [%l4 + %lo(_pgofset)], %l4 - PTE_OF_ADDR(%sp, %l7, winuf_invalid, %l4) - CMP_PTE_USER_READ(%l7, %l5) ! if first page not readable, + PTE_OF_ADDR(%sp, %l7, winuf_invalid, %l4, NOP_ON_4M_5) + CMP_PTE_USER_READ(%l7, %l5, NOP_ON_4M_6) ! if first page not readable, bne winuf_invalid ! it is invalid EMPTY SLT_IF_1PAGE_RW(%sp, %l7, %l4) ! first page is readable @@ -2831,8 +2786,8 @@ winuf_user: restore %g0, 1, %l1 ! and goto ok, & set %l1 to 1 add %sp, 7*8, %l5 add %l4, 62, %l4 - PTE_OF_ADDR(%l5, %l7, winuf_invalid, %l4) - CMP_PTE_USER_READ(%l7, %l5) ! check second page too + PTE_OF_ADDR(%l5, %l7, winuf_invalid, %l4, NOP_ON_4M_7) + CMP_PTE_USER_READ(%l7, %l5, NOP_ON_4M_8) ! check second page too be,a winuf_ok ! enter window X and goto ok restore %g0, 1, %l1 ! (and then set %l1 to 1) @@ -3046,8 +3001,8 @@ rft_user: sethi %hi(_pgofset), %l3 ld [%l3 + %lo(_pgofset)], %l3 - PTE_OF_ADDR(%fp, %l7, rft_invalid, %l3) - CMP_PTE_USER_READ(%l7, %l5) ! try first page + PTE_OF_ADDR(%fp, %l7, rft_invalid, %l3, NOP_ON_4M_9) + CMP_PTE_USER_READ(%l7, %l5, NOP_ON_4M_10) ! try first page bne rft_invalid ! no good EMPTY SLT_IF_1PAGE_RW(%fp, %l7, %l3) @@ -3055,8 +3010,8 @@ rft_user: wr %g0, 0, %wim add %fp, 7*8, %l5 add %l3, 62, %l3 - PTE_OF_ADDR(%l5, %l7, rft_invalid, %l3) - CMP_PTE_USER_READ(%l7, %l5) ! check 2nd page too + PTE_OF_ADDR(%l5, %l7, rft_invalid, %l3, NOP_ON_4M_11) + CMP_PTE_USER_READ(%l7, %l5, NOP_ON_4M_12) ! check 2nd page too be,a rft_user_ok wr %g0, 0, %wim @@ -3446,6 +3401,7 @@ start_havetype: blu 0b ! no, loop add %l3, %l0, %l0 ! (and lowva += segsz) +#if 0 /* moved to autoconf */ /* * Now map the interrupt enable register and clear any interrupts, * enabling NMIs. Note that we will not take NMIs until we change @@ -3462,6 +3418,7 @@ start_havetype: mov IE_ALLIE, %l1 nop; nop ! paranoia stb %l1, [%l0] +#endif b startmap_done nop 1: @@ -3493,6 +3450,7 @@ no_3mmu: remap_done: +#if 0 /* moved to autoconf */ /* * Now map the interrupt enable register and clear any interrupts, * enabling NMIs. Note that we will not take NMIs until we change @@ -3509,6 +3467,7 @@ remap_done: mov IE_ALLIE, %l1 nop; nop ! paranoia stb %l1, [%l0] +#endif b,a startmap_done 2: #endif /* SUN4 */ @@ -3682,6 +3641,50 @@ noplab: nop 1: #endif +#if ((defined(SUN4) || defined(SUN4C)) && defined(SUN4M)) + + /* + * Patch instructions at specified labels that start + * per-architecture code-paths. + */ +Lgandul: nop + +#define MUNGE(label) \ + sethi %hi(label), %o0; \ + st %l0, [%o0 + %lo(label)] + + sethi %hi(Lgandul), %o0 + ld [%o0 + %lo(Lgandul)], %l0 ! %l0 = NOP + + cmp %g4, CPU_SUN4M + bne,a 1f + nop + + ! this should be automated! + MUNGE(NOP_ON_4M_1) + MUNGE(NOP_ON_4M_2) + MUNGE(NOP_ON_4M_3) + MUNGE(NOP_ON_4M_4) + MUNGE(NOP_ON_4M_5) + MUNGE(NOP_ON_4M_6) + MUNGE(NOP_ON_4M_7) + MUNGE(NOP_ON_4M_8) + MUNGE(NOP_ON_4M_9) + MUNGE(NOP_ON_4M_10) + MUNGE(NOP_ON_4M_11) + MUNGE(NOP_ON_4M_12) + MUNGE(NOP_ON_4M_13) + MUNGE(NOP_ON_4M_14) + b,a 2f + +1: + MUNGE(NOP_ON_4_4C_1) + +2: + +#undef MUNGE +#endif + /* * Step 4: change the trap base register, now that our trap handlers * will function (they need the tables we just set up). @@ -3705,6 +3708,7 @@ noplab: nop clr %o0 ! our frame arg is ignored /*NOTREACHED*/ + /* * The following code is copied to the top of the user stack when each * process is exec'ed, and signals are `trampolined' off it. @@ -3976,6 +3980,13 @@ _svr4_esigcode: #define ALTENTRY(x) .globl _/**/x; _/**/x: /* + * General-purpose NULL routine. + */ +ENTRY(sparc_noop) + retl + nop + +/* * getfp() - get stack frame pointer */ ENTRY(getfp) @@ -4576,15 +4587,17 @@ Lsw_load: * zero so it is safe to have interrupts going here.) */ ld [%g3 + P_VMSPACE], %o3 ! vm = p->p_vmspace; - ld [%o3 + VM_PMAP_CTX], %o0! if (vm->vm_pmap.pm_ctx != NULL) + ld [%o3 + VM_PMAP], %o3 ! pm = vm->vm_map.vm_pmap; + ld [%o3 + PMAP_CTX], %o0 ! if (pm->pm_ctx != NULL) tst %o0 bnz,a Lsw_havectx ! goto havecontext; - ld [%o3 + VM_PMAP_CTXNUM], %o0 ! load context number + ld [%o3 + PMAP_CTXNUM], %o0 ! load context number /* p does not have a context: call ctx_alloc to get one */ save %sp, -CCFSZ, %sp - call _ctx_alloc ! ctx_alloc(&vm->vm_pmap); - add %i3, VM_PMAP, %o0 + call _ctx_alloc ! ctx_alloc(pm); + mov %i3, %o0 + ret restore @@ -4626,7 +4639,7 @@ Lsw_sameproc: * Only used just before a crash dump. */ ENTRY(snapshot) - st %o6, [%o0 + PCB_SP] ! save sp + std %o6, [%o0 + PCB_SP] ! save sp rd %psr, %o1 ! save psr st %o1, [%o0 + PCB_PSR] @@ -5408,20 +5421,14 @@ ENTRY(loadfpstate) #if defined(SUN4M) && (defined(SUN4) || defined(SUN4C)) ENTRY(ienab_bis) - sethi %hi(_cputyp), %o1 - ld [%o1 + %lo(_cputyp)], %o1 - cmp %o1, CPU_SUN4M - be,a _ienab_bis_4m - nop - b,a _ienab_bis_4c +NOP_ON_4M_13: + b,a _ienab_bis_4_4c + b,a _ienab_bis_4m ENTRY(ienab_bic) - sethi %hi(_cputyp), %o1 - ld [%o1 + %lo(_cputyp)], %o1 - cmp %o1, CPU_SUN4M - be,a _ienab_bic_4m - nop - b,a _ienab_bic_4c +NOP_ON_4M_14: + b,a _ienab_bic_4_4c + b,a _ienab_bic_4m #endif #if defined(SUN4) || defined(SUN4C) @@ -5430,7 +5437,7 @@ ENTRY(ienab_bic) * and one of the interrupts is nonmaskable, we must disable traps. */ #if defined(SUN4M) -ENTRY(ienab_bis_4c) +ENTRY(ienab_bis_4_4c) #else ENTRY(ienab_bis) #endif @@ -5438,17 +5445,17 @@ ENTRY(ienab_bis) rd %psr, %o2 wr %o2, PSR_ET, %psr ! disable traps nop; nop ! 3-instr delay until ET turns off - sethi %hi(IE_reg_addr), %o3 - ldub [%o3 + %lo(IE_reg_addr)], %o4 - or %o4, %o0, %o4 ! *IE_reg_addr |= bis; - stb %o4, [%o3 + %lo(IE_reg_addr)] + sethi %hi(INTRREG_VA), %o3 + ldub [%o3 + %lo(INTRREG_VA)], %o4 + or %o4, %o0, %o4 ! *INTRREG_VA |= bis; + stb %o4, [%o3 + %lo(INTRREG_VA)] wr %o2, 0, %psr ! reenable traps nop retl nop #if defined(SUN4M) -ENTRY(ienab_bic_4c) +ENTRY(ienab_bic_4_4c) #else ENTRY(ienab_bic) #endif @@ -5456,10 +5463,10 @@ ENTRY(ienab_bic) rd %psr, %o2 wr %o2, PSR_ET, %psr ! disable traps nop; nop - sethi %hi(IE_reg_addr), %o3 - ldub [%o3 + %lo(IE_reg_addr)], %o4 - andn %o4, %o0, %o4 ! *IE_reg_addr &=~ bic; - stb %o4, [%o3 + %lo(IE_reg_addr)] + sethi %hi(INTRREG_VA), %o3 + ldub [%o3 + %lo(INTRREG_VA)], %o4 + andn %o4, %o0, %o4 ! *INTRREG_VA &=~ bic; + stb %o4, [%o3 + %lo(INTRREG_VA)] wr %o2, 0, %psr ! reenable traps nop retl @@ -5504,6 +5511,84 @@ ENTRY(raise) retl st %o2, [%o1] + +/* + * Read Fault Status registers. + * On entry: %l1 == PC, %l3 == fault type + * On exit: %o1 == sync fault status, %o2 == sync fault address + * %o3 == async fault status, %o4 == async fault address + */ +ALTENTRY(srmmu_get_fltstatus) + set SRMMU_SFADDR, %o2 + lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first + set SRMMU_SFSTAT, %o1 + lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register + + clr %o3 ! clear %o3 and %o4 + retl + clr %o4 + +ALTENTRY(viking_get_fltstatus) + cmp %l3, T_TEXTFAULT + be,a 1f + mov %l1, %o2 ! use PC if type == T_TEXTFAULT + + set SRMMU_SFADDR, %o2 + lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first +1: + set SRMMU_SFSTAT, %o1 + lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register + + clr %o3 ! clear %o3 and %o4 + retl + clr %o4 + +ALTENTRY(ms1_get_fltstatus) +ALTENTRY(swift_get_fltstatus) +ALTENTRY(turbosparc_get_fltstatus) + cmp %l3, T_TEXTFAULT + be,a 1f + mov %l1, %o2 ! use PC if type == T_TEXTFAULT + + set SRMMU_SFADDR, %o2 + lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first +1: + set SRMMU_SFSTAT, %o1 + lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register + + clr %o3 ! clear %o3 and %o4 + retl + clr %o4 + +ALTENTRY(cypress_get_fltstatus) + cmp %l3, T_TEXTFAULT + be,a 1f + mov %l1, %o2 ! use PC if type == T_TEXTFAULT + + set SRMMU_SFADDR, %o2 + lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first +1: + set SRMMU_SFSTAT, %o1 + lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register + + set SRMMU_AFSTAT, %o3 ! must read status before fault on HS + lda [%o3] ASI_SRMMU, %o3 ! get async fault status + set SRMMU_AFADDR, %o4 + retl + lda [%o4] ASI_SRMMU, %o4 ! get async fault address + +ALTENTRY(hypersparc_get_fltstatus) + set SRMMU_SFADDR, %o2 + lda [%o2] ASI_SRMMU, %o2 ! sync virt addr; must be read first + set SRMMU_SFSTAT, %o1 + lda [%o1] ASI_SRMMU, %o1 ! get sync fault status register + + set SRMMU_AFSTAT, %o3 ! must read status before fault on HS + lda [%o3] ASI_SRMMU, %o3 ! get async fault status + set SRMMU_AFADDR, %o4 + retl + lda [%o4] ASI_SRMMU, %o4 ! get async fault address + #endif /* SUN4M */ /* @@ -5644,26 +5729,23 @@ ENTRY(lo_microtime) ENTRY(microtime) #endif sethi %hi(_time), %g2 - sethi %hi(TIMERREG_VA), %g3 -/* blech, sun4m has microsecond counter at a different location */ -#if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M) -#define r_aardvark %lo(TIMERREG_VA) -#elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M) -#define r_aardvark %lo(TIMERREG_VA) + 4 +#if defined(SUN4M) && !(defined(SUN4C) || defined(SUN4)) + sethi %hi(TIMERREG_VA+4), %g3 + or %g3, %lo(TIMERREG_VA+4), %g3 +#elif (defined(SUN4C) || defined(SUN4)) && !defined(SUN4M) + sethi %hi(TIMERREG_VA), %g3 + or %g3, %lo(TIMERREG_VA), %g3 #else - sethi %hi(_cputyp), %g4 - ld [%g4 + %lo(_cputyp)], %g4 + sethi %hi(TIMERREG_VA), %g3 or %g3, %lo(TIMERREG_VA), %g3 - cmp %g4, CPU_SUN4M - be,a 1f +NOP_ON_4_4C_1: add %g3, 4, %g3 -1: -#define r_aardvark 0 #endif + 2: ldd [%g2+%lo(_time)], %o2 ! time.tv_sec & time.tv_usec - ld [%g3+r_aardvark], %o4 ! usec counter + ld [%g3], %o4 ! usec counter ldd [%g2+%lo(_time)], %g4 ! see if time values changed cmp %g4, %o2 bne 2b ! if time.tv_sec changed diff --git a/sys/arch/sparc/sparc/locore2.c b/sys/arch/sparc/sparc/locore2.c index 7e28fb8f265..75299008f41 100644 --- a/sys/arch/sparc/sparc/locore2.c +++ b/sys/arch/sparc/sparc/locore2.c @@ -1,4 +1,5 @@ -/* $NetBSD: locore2.c,v 1.6 1996/03/14 21:09:15 christos Exp $ */ +/* $OpenBSD: locore2.c,v 1.4 1997/08/08 08:27:29 downsj Exp $ */ +/* $NetBSD: locore2.c,v 1.7 1996/11/06 20:19:53 cgd Exp $ */ /* * Copyright (c) 1992, 1993 diff --git a/sys/arch/sparc/sparc/machdep.c b/sys/arch/sparc/sparc/machdep.c index cb2d1b8f5e8..02fb423eec4 100644 --- a/sys/arch/sparc/sparc/machdep.c +++ b/sys/arch/sparc/sparc/machdep.c @@ -1,5 +1,5 @@ -/* $OpenBSD: machdep.c,v 1.26 1997/07/01 21:32:02 grr Exp $ */ -/* $NetBSD: machdep.c,v 1.64 1996/05/19 04:12:56 mrg Exp $ */ +/* $OpenBSD: machdep.c,v 1.27 1997/08/08 08:27:30 downsj Exp $ */ +/* $NetBSD: machdep.c,v 1.83 1997/07/29 10:04:44 fair Exp $ */ /* * Copyright (c) 1992, 1993 @@ -280,6 +280,14 @@ cpu_startup() configure(); /* + * Re-zero proc0's user area, to nullify the effect of the + * stack running into it during auto-configuration. + * XXX - should fix stack usage. + * XXX - there's a race here, as interrupts are enabled + */ + bzero(proc0paddr, sizeof(struct user)); + + /* * fix message buffer mapping, note phys addr of msgbuf is 0 */ @@ -384,6 +392,9 @@ setregs(p, pack, stack, retval) register struct fpstate *fs; register int psr; + /* Don't allow misaligned code by default */ + p->p_md.md_flags &= ~MDP_FIXALIGN; + /* * The syscall will ``return'' to npc or %g7 or %g2; set them all. * Set the rest of the registers to 0 except for %o6 (stack pointer, @@ -662,13 +673,11 @@ boot(howto) fb_unblank(); boothowto = howto; if ((howto & RB_NOSYNC) == 0 && waittime < 0) { -#if 1 extern struct proc proc0; - /* protect against curproc->p_stats.foo refs in sync() XXX */ + /* XXX protect against curproc->p_stats.foo refs in sync() */ if (curproc == NULL) curproc = &proc0; -#endif waittime = 0; vfs_shutdown(); @@ -732,7 +741,7 @@ dumpconf() /* No usable dump device */ return; - nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); + nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); dumpblks = ctod(physmem) + ctod(pmap_dumpsize()); if (dumpblks > (nblks - ctod(1))) @@ -746,7 +755,7 @@ dumpconf() /* Put the dump at the end of the partition */ dumplo = nblks - dumpblks; - /* + /* * savecore(8) expects dumpsize to be the number of pages * of actual core dumped (i.e. excluding the MMU stuff). */ @@ -799,7 +808,7 @@ dumpsys() if (dumplo <= 0) return; printf("\ndumping to dev(%d,%d), at offset %ld blocks\n", - major(dumpdev), minor(dumpdev), dumplo); + major(dumpdev), minor(dumpdev), dumplo); psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); printf("dump "); @@ -891,7 +900,7 @@ stackdump() printf("Frame pointer is at %p\n", fp); printf("Call traceback:\n"); while (fp && ((u_long)fp >> PGSHIFT) == ((u_long)sfp >> PGSHIFT)) { - printf(" pc = %x args = (%x, %x, %x, %x, %x, %x, %x) fp = %p\n", + printf(" pc = 0x%x args = (0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) fp = %p\n", fp->fr_pc, fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3], fp->fr_arg[4], fp->fr_arg[5], fp->fr_arg[6], fp->fr_fp); @@ -899,27 +908,18 @@ stackdump() } } -int bt2pmt[] = { - PMAP_OBIO, - PMAP_OBIO, - PMAP_VME16, - PMAP_VME32, - PMAP_OBIO -}; - /* * Map an I/O device given physical address and size in bytes, e.g., * * mydev = (struct mydev *)mapdev(myioaddr, 0, - * 0, sizeof(struct mydev), pmtype); + * 0, sizeof(struct mydev)); * * See also machine/autoconf.h. */ void * -mapdev(phys, virt, offset, size, bustype) +mapdev(phys, virt, offset, size) register struct rom_reg *phys; register int offset, virt, size; - register int bustype; { register vm_offset_t v; register vm_offset_t pa; @@ -945,9 +945,7 @@ mapdev(phys, virt, offset, size, bustype) /* note: preserve page offset */ pa = trunc_page(phys->rr_paddr + offset); - pmtype = (CPU_ISSUN4M) - ? (phys->rr_iospace << PMAP_SHFT4M) - : bt2pmt[bustype]; + pmtype = PMAP_IOENC(phys->rr_iospace); do { pmap_enter(pmap_kernel(), v, pa | pmtype | PMAP_NC, @@ -993,12 +991,12 @@ oldmon_w_trace(va) #define round_up(x) (( (x) + (NBPG-1) ) & (~(NBPG-1)) ) - printf("\nstack trace with sp = %lx\n", va); + printf("\nstack trace with sp = 0x%lx\n", va); stop = round_up(va); - printf("stop at %lx\n", stop); + printf("stop at 0x%lx\n", stop); fp = (struct frame *) va; while (round_up((u_long) fp) == stop) { - printf(" %x(%x, %x, %x, %x, %x, %x, %x) fp %p\n", fp->fr_pc, + printf(" 0x%x(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) fp %p\n", fp->fr_pc, fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3], fp->fr_arg[4], fp->fr_arg[5], fp->fr_arg[6], fp->fr_fp); fp = fp->fr_fp; diff --git a/sys/arch/sparc/sparc/mem.c b/sys/arch/sparc/sparc/mem.c index ff531dca56f..cd594c505a2 100644 --- a/sys/arch/sparc/sparc/mem.c +++ b/sys/arch/sparc/sparc/mem.c @@ -1,3 +1,4 @@ +/* $OpenBSD: mem.c,v 1.3 1997/08/08 08:27:31 downsj Exp $ */ /* $NetBSD: mem.c,v 1.13 1996/03/30 21:12:16 christos Exp $ */ /* diff --git a/sys/arch/sparc/sparc/memreg.c b/sys/arch/sparc/sparc/memreg.c index a2b5bf67ddc..26974d3dcb7 100644 --- a/sys/arch/sparc/sparc/memreg.c +++ b/sys/arch/sparc/sparc/memreg.c @@ -1,4 +1,5 @@ -/* $NetBSD: memreg.c,v 1.13 1996/03/31 22:52:08 pk Exp $ */ +/* $OpenBSD: memreg.c,v 1.5 1997/08/08 08:27:32 downsj Exp $ */ +/* $NetBSD: memreg.c,v 1.21 1997/07/29 09:42:08 fair Exp $ */ /* * Copyright (c) 1992, 1993 @@ -56,6 +57,7 @@ #include <sparc/sparc/memreg.h> #include <sparc/sparc/vaddrs.h> #include <sparc/sparc/asm.h> +#include <sparc/sparc/cpuvar.h> #include <machine/reg.h> /* for trapframe */ #include <machine/trap.h> /* for trap types */ @@ -82,9 +84,9 @@ static void hardmemerr4m __P((int, u_int, u_int)); static int memregmatch(parent, vcf, aux) struct device *parent; - void *aux, *vcf; + void *vcf, *aux; { - struct cfdata *cf = vcf; + register struct cfdata *cf; register struct confargs *ca = aux; if (CPU_ISSUN4) { @@ -111,8 +113,7 @@ memregattach(parent, self, aux) ra->ra_vaddr = (caddr_t)par_err_reg; } else { par_err_reg = ra->ra_vaddr ? (volatile u_int *)ra->ra_vaddr : - (volatile u_int *)mapiodev(ra->ra_reg, 0, sizeof(int), - ca->ca_bustype); + (volatile u_int *)mapiodev(ra->ra_reg, 0, sizeof(int)); } printf("\n"); } @@ -129,13 +130,13 @@ memerr(issync, ser, sva, aer, ava) int issync; u_int ser, sva, aer, ava; { - /* XXX Ugh! Clean up this switch and all the ifdefs! */ switch (cputyp) { #if defined(SUN4) case CPU_SUN4: if (par_err_reg) { - printf("mem err: ser=%b sva=%x\n", ser, SER_BITS, sva); + printf("mem err: ser=%b sva=0x%x\n", + ser, SER_BITS, sva); printf("parity error register = %b\n", *par_err_reg, PER_BITS); } else { @@ -152,12 +153,12 @@ memerr(issync, ser, sva, aer, ava) #if defined(SUN4C) case CPU_SUN4C: - printf("%ssync mem err: ser=%b sva=%x aer=%b ava=%x\n", - issync ? "" : "a", ser, SER_BITS, - sva, aer & 0xff, AER_BITS, ava); + printf("%ssync mem arr: ser=%b sva=0x%x ", + issync ? "" : "a", ser, SER_BITS, sva); + printf("aer=%b ava=0x%x\n", aer & 0xff, AER_BITS, ava); if (par_err_reg) printf("parity error register = %b\n", - *par_err_reg, PER_BITS); + *par_err_reg, PER_BITS); #ifdef DEBUG callrom(); #else @@ -196,22 +197,24 @@ hardmemerr4m(issync, fsr, faddr) case 1: if ((fsr & SFSR_FT) == SFSR_FT_NONE) return; - panic("mem err: sfsr=%b sfaddr=%x", fsr, SFSR_BITS, faddr); + printf("mem err: sfsr=%b sfaddr=0x%x\n", fsr, SFSR_BITS, faddr); break; case 0: if (!(fsr & AFSR_AFO)) return; - panic("async (HS) mem err: afsr=%b afaddr=%x physaddr=%x%x", + printf("async (HS) mem err: afsr=%b afaddr=0x%x physaddr=0x%x%x\n", fsr, AFSR_BITS, faddr, (fsr & AFSR_AFA) >> AFSR_AFA_RSHIFT, faddr); break; default: /* unknown; print both decodings*/ - panic("Unknown mem err: if sync, fsr=%b fva=%x; if async, fsr" - "=%b fa=%x pa=%x%x", fsr, SFSR_BITS, faddr, fsr, - AFSR_BITS, faddr, (fsr & AFSR_AFA) >> AFSR_AFA_RSHIFT, - faddr); + printf("unknown mem err: if sync, fsr=%b fva=0x%x; ", + fsr, SFSR_BITS, faddr); + printf("if async, fsr=%b fa=0x%x pa=0x%x%x", fsr, + AFSR_BITS, faddr, (fsr & AFSR_AFA) >> AFSR_AFA_RSHIFT, + faddr); break; } + panic("hard memory error"); } /* @@ -248,9 +251,12 @@ memerr4m(type, sfsr, sfva, afsr, afva, tf) addrold = afva; addroldtop = afsr & AFSR_AFA; - } else if (type == T_STOREBUFFAULT) { - /* We try to reenable the store buffers to force a retry */ + } else if (type == T_STOREBUFFAULT && cpuinfo.cpu_vers == 4) { + /* + * On Supersparc, we try to reenable the store buffers + * to force a retry. + */ printf("store buffer copy-back failure at 0x%x. Retrying...\n", sfva); @@ -261,8 +267,9 @@ memerr4m(type, sfsr, sfva, afsr, afva, tf) oldtype = T_STOREBUFFAULT; addrold = sfva; - sta(SRMMU_PCR, ASI_SRMMU, lda(SRMMU_PCR, ASI_SRMMU) | - SRMMU_PCR_SB); /* reenable store buffer */ + /* reenable store buffer */ + sta(SRMMU_PCR, ASI_SRMMU, + lda(SRMMU_PCR, ASI_SRMMU) | VIKING_PCR_SB); } else if (type == T_DATAFAULT && !(sfsr & SFSR_FAV)) { /* bizarre */ /* XXX: Should handle better. See SuperSPARC manual pg. 9-35 */ @@ -276,9 +283,10 @@ memerr4m(type, sfsr, sfva, afsr, afva, tf) oldtype = T_DATAFAULT; } else if (type == 0) { /* NMI */ - printf("ERROR: got NMI with sfsr=0x%b, sfva=0x%x, afsr=0x%b, " - "afaddr=0x%x. Retrying...\n", - sfsr,SFSR_BITS,sfva,afsr, AFSR_BITS,afva); + printf("ERROR: got NMI with sfsr=0x%b, sfva=0x%x, ", + sfsr, SFSR_BITS, sfva); + printf("afsr=0x%b, afaddr=0x%x. Retrying...\n", + afsr, AFSR_BITS, afva); if (oldtype == 0 || addrold == sfva) hardmemerr4m(1, sfsr, sfva); /* XXX: async? */ /* NOTREACHED */ @@ -286,9 +294,10 @@ memerr4m(type, sfsr, sfva, afsr, afva, tf) oldtype = 0; addrold = sfva; } else /* something we don't know about?!? */ { - panic("memerr4m: unknown fatal memory error. type=%d, sfsr=%b," - " sfva=%x, afsr=%b, afaddr=%x", - type, sfsr, SFSR_BITS, sfva, afsr, AFSR_BITS, afva); + printf("unknown fatal memory error, type=%d, sfsr=%b, sfva=0x%x", + type, sfsr, SFSR_BITS, sfva); + printf(", afsr=%b, afaddr=0x%x\n", afsr, AFSR_BITS, afva); + panic("memerr4m"); } return; diff --git a/sys/arch/sparc/sparc/memreg.h b/sys/arch/sparc/sparc/memreg.h index be25a8f76c0..f27a5197621 100644 --- a/sys/arch/sparc/sparc/memreg.h +++ b/sys/arch/sparc/sparc/memreg.h @@ -1,3 +1,4 @@ +/* $OpenBSD: memreg.h,v 1.3 1997/08/08 08:27:33 downsj Exp $ */ /* $NetBSD: memreg.h,v 1.4 1996/03/31 22:52:13 pk Exp $ */ /* diff --git a/sys/arch/sparc/sparc/openprom.c b/sys/arch/sparc/sparc/openprom.c index 15c9ac1293f..ed362afe3cd 100644 --- a/sys/arch/sparc/sparc/openprom.c +++ b/sys/arch/sparc/sparc/openprom.c @@ -1,3 +1,4 @@ +/* $OpenBSD: openprom.c,v 1.3 1997/08/08 08:27:34 downsj Exp $ */ /* $NetBSD: openprom.c,v 1.8 1996/03/31 23:45:34 pk Exp $ */ /* diff --git a/sys/arch/sparc/sparc/pmap.c b/sys/arch/sparc/sparc/pmap.c index 9aca4e3a4b5..789619a78bc 100644 --- a/sys/arch/sparc/sparc/pmap.c +++ b/sys/arch/sparc/sparc/pmap.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pmap.c,v 1.16 1997/07/07 07:45:32 grr Exp $ */ -/* $NetBSD: pmap.c,v 1.60.4.1 1996/06/12 20:36:30 pk Exp $ */ +/* $OpenBSD: pmap.c,v 1.17 1997/08/08 08:27:36 downsj Exp $ */ +/* $NetBSD: pmap.c,v 1.91 1997/07/29 09:42:11 fair Exp $ */ /* * Copyright (c) 1996 @@ -63,14 +63,15 @@ #include <sys/proc.h> #include <sys/queue.h> #include <sys/malloc.h> -#include <sys/kcore.h> +#include <sys/exec.h> #include <sys/core.h> -#include <sys/exec_aout.h> +#include <sys/kcore.h> #include <vm/vm.h> #include <vm/vm_kern.h> #include <vm/vm_prot.h> #include <vm/vm_page.h> +#include <vm/lock.h> #include <machine/autoconf.h> #include <machine/bsd_openprom.h> @@ -82,6 +83,7 @@ #include <sparc/sparc/asm.h> #include <sparc/sparc/cache.h> #include <sparc/sparc/vaddrs.h> +#include <sparc/sparc/cpuvar.h> #ifdef DEBUG #define PTE_BITS "\20\40V\37W\36S\35NC\33IO\32U\31M" @@ -132,6 +134,9 @@ struct pmap_stats { int ps_useless_changewire; /* useless wiring changes */ int ps_npg_prot_all; /* # of active pages protected */ int ps_npg_prot_actual; /* # pages actually affected */ + int ps_npmeg_free; /* # of free pmegs */ + int ps_npmeg_locked; /* # of pmegs on locked list */ + int ps_npmeg_lru; /* # of pmegs on lru list */ } pmap_stats; #ifdef DEBUG @@ -140,6 +145,7 @@ struct pmap_stats { #define PDB_REMOVE 0x0004 #define PDB_CHANGEPROT 0x0008 #define PDB_ENTER 0x0010 +#define PDB_FOLLOW 0x0020 #define PDB_MMU_ALLOC 0x0100 #define PDB_MMU_STEAL 0x0200 @@ -148,6 +154,8 @@ struct pmap_stats { #define PDB_MMUREG_ALLOC 0x1000 #define PDB_MMUREG_STEAL 0x2000 #define PDB_CACHESTUFF 0x4000 +#define PDB_SWITCHMAP 0x8000 +#define PDB_SANITYCHK 0x10000 int pmapdebug = 0; #endif @@ -175,10 +183,10 @@ vm_offset_t vm_first_phys, vm_num_phys; * THIS SHOULD BE PART OF THE CORE MAP */ struct pvlist { - struct pvlist *pv_next; /* next pvlist, if any */ - struct pmap *pv_pmap; /* pmap of this va */ - vm_offset_t pv_va; /* virtual address */ - int pv_flags; /* flags (below) */ + struct pvlist *pv_next; /* next pvlist, if any */ + struct pmap *pv_pmap; /* pmap of this va */ + vm_offset_t pv_va; /* virtual address */ + int pv_flags; /* flags (below) */ }; /* @@ -249,6 +257,13 @@ struct pvlist *pv_table; /* array of entries, one per physical page */ * If a virtual segment is valid, its entries will be in both parallel lists. * If it is not valid, then its entry in the kernel tables will be zero, and * its entry in the MMU tables will either be nonexistent or zero as well. + * + * The Reference MMU generally uses a Translation Look-aside Buffer (TLB) + * to cache the result of recently executed page table walks. When + * manipulating page tables, we need to ensure consistency of the + * in-memory and TLB copies of the page table entries. This is handled + * by flushing (and invalidating) a TLB entry when appropriate before + * altering an in-memory page table entry. */ struct mmuentry { TAILQ_ENTRY(mmuentry) me_list; /* usage list link */ @@ -264,10 +279,8 @@ struct mmuentry *mmuregions; /* allocated in pmap_bootstrap */ struct mmuhd segm_freelist, segm_lru, segm_locked; struct mmuhd region_freelist, region_lru, region_locked; -int seginval; /* the invalid segment number */ -#ifdef MMU_3L -int reginval; /* the invalid region number */ -#endif +int seginval; /* [4/4c] the invalid segment number */ +int reginval; /* [4/3mmu] the invalid region number */ /* * (sun4/4c) @@ -290,36 +303,39 @@ union ctxinfo { union ctxinfo *c_nextfree; /* free list (if free) */ struct pmap *c_pmap; /* pmap (if busy) */ }; + +#define ncontext (cpuinfo.mmu_ncontext) +#define ctx_kick (cpuinfo.ctx_kick) +#define ctx_kickdir (cpuinfo.ctx_kickdir) +#define ctx_freelist (cpuinfo.ctx_freelist) + +#if 0 union ctxinfo *ctxinfo; /* allocated at in pmap_bootstrap */ -int ncontext; union ctxinfo *ctx_freelist; /* context free list */ int ctx_kick; /* allocation rover when none free */ int ctx_kickdir; /* ctx_kick roves both directions */ -char *ctxbusyvector; /* [4m] tells what contexts are busy */ -int *ctx_phys_tbl; /* [4m] SRMMU-edible context table */ +char *ctxbusyvector; /* [4m] tells what contexts are busy (XXX)*/ +#endif caddr_t vpage[2]; /* two reserved MD virtual pages */ caddr_t vmmap; /* one reserved MI vpage for /dev/mem */ caddr_t vdumppages; /* 32KB worth of reserved dump pages */ -#ifdef MMU_3L -smeg_t tregion; -#endif +smeg_t tregion; /* [4/3mmu] Region for temporary mappings */ + struct pmap kernel_pmap_store; /* the kernel's pmap */ struct regmap kernel_regmap_store[NKREG]; /* the kernel's regmap */ struct segmap kernel_segmap_store[NKREG*NSEGRG];/* the kernel's segmaps */ -#ifdef SUN4M +#if defined(SUN4M) u_int *kernel_regtable_store; /* 1k of storage to map the kernel */ u_int *kernel_segtable_store; /* 2k of storage to map the kernel */ u_int *kernel_pagtable_store; /* 128k of storage to map the kernel */ u_int *kernel_iopte_table; /* 64k of storage for iommu */ u_int kernel_iopte_table_pa; - -static int cant_cache_pagetables = 0; /* 1 if page tables are uncachable */ #endif #define MA_SIZE 32 /* size of memory descriptor arrays */ @@ -330,18 +346,10 @@ int cpmemarr; /* pmap_next_page() state */ /*static*/ vm_offset_t avail_end; /* last free physical page */ /*static*/ vm_offset_t avail_next; /* pmap_next_page() state: next free physical page */ +/*static*/ vm_offset_t unavail_start; /* first stolen free physical page */ +/*static*/ vm_offset_t unavail_end; /* last stolen free physical page */ /*static*/ vm_offset_t virtual_avail; /* first free virtual page number */ /*static*/ vm_offset_t virtual_end; /* last free virtual page number */ -#ifdef SUN4M -#if 0 /* not needed anymore */ -static void * pmap_bootstrap_malloc __P((unsigned long, int, int)); - -caddr_t minipool_start; -caddr_t minipool_current; -#define MINIPOOL_SIZE 8192 /* number of bytes to reserve for early malloc */ - /* (must be multiple of pagesize) */ -#endif -#endif int mmu_has_hole; @@ -373,12 +381,17 @@ static u_long segfixmask = 0xffffffff; /* all bits valid to start */ /* * pseudo-functions for mnemonic value */ +#define getcontext4() lduba(AC_CONTEXT, ASI_CONTROL) +#define getcontext4m() lda(SRMMU_CXR, ASI_SRMMU) #define getcontext() (CPU_ISSUN4M \ - ? lda(SRMMU_CXR, ASI_SRMMU) \ - : lduba(AC_CONTEXT, ASI_CONTROL)) + ? getcontext4m() \ + : getcontext4() ) + +#define setcontext4(c) stba(AC_CONTEXT, ASI_CONTROL, c) +#define setcontext4m(c) sta(SRMMU_CXR, ASI_SRMMU, c) #define setcontext(c) (CPU_ISSUN4M \ - ? sta(SRMMU_CXR, ASI_SRMMU, c) \ - : stba(AC_CONTEXT, ASI_CONTROL, c)) + ? setcontext4m(c) \ + : setcontext4(c) ) #define getsegmap(va) (CPU_ISSUN4C \ ? lduba(va, ASI_SEGMAP) \ @@ -394,6 +407,7 @@ static u_long segfixmask = 0xffffffff; /* all bits valid to start */ #if defined(SUN4M) #define getpte4m(va) lda((va & 0xFFFFF000) | ASI_SRMMUFP_L3, \ ASI_SRMMUFP) +void setpgt4m __P((int *ptep, int pte)); void setpte4m __P((vm_offset_t va, int pte)); void setptesw4m __P((struct pmap *pm, vm_offset_t va, int pte)); u_int getptesw4m __P((struct pmap *pm, vm_offset_t va)); @@ -418,11 +432,10 @@ u_int getptesw4m __P((struct pmap *pm, vm_offset_t va)); */ #if defined(SUN4M) -static void mmu_setup4m_L1 __P((int, caddr_t, struct pmap *, caddr_t *)); -static void mmu_setup4m_L2 __P((int, caddr_t, struct regmap *, caddr_t *, - struct segmap *)); -static int mmu_setup4m_L3 __P((int, caddr_t)); -/*static*/ void mmu_reservemon4m __P((struct pmap *, caddr_t *)); +static void mmu_setup4m_L1 __P((int, struct pmap *)); +static void mmu_setup4m_L2 __P((int, struct regmap *)); +static void mmu_setup4m_L3 __P((int, struct segmap *)); +/*static*/ void mmu_reservemon4m __P((struct pmap *)); /*static*/ void pmap_rmk4m __P((struct pmap *, vm_offset_t, vm_offset_t, int, int)); @@ -585,6 +598,16 @@ getptesw4m(pm, va) /* Assumes L3 mapping! */ return (sm->sg_pte[VA_SUN4M_VPG(va)]); /* return pte */ } +__inline void +setpgt4m(ptep, pte) + int *ptep; + int pte; +{ + *ptep = pte; + if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) + cpuinfo.pcache_flush_line((int)ptep, VA2PA((caddr_t)ptep)); +} + /* * Set the page table entry for va to pte. Only affects software MMU page- * tables (the in-core pagetables read by the MMU). Ignores TLB, and @@ -604,15 +627,15 @@ setptesw4m(pm, va, pte) #ifdef DEBUG if (pm->pm_regmap == NULL || rm == NULL) - panic("setpte4m: no regmap entry"); + panic("setptesw4m: no regmap entry"); #endif sm = &rm->rg_segmap[VA_VSEG(va)]; #ifdef DEBUG if (rm->rg_segmap == NULL || sm == NULL || sm->sg_pte == NULL) - panic("setpte4m: no segmap for va %p", (caddr_t)va); + panic("setptesw4m: no segmap for va %p", (caddr_t)va); #endif - sm->sg_pte[VA_SUN4M_VPG(va)] = pte; /* set new pte */ + setpgt4m(sm->sg_pte + VA_SUN4M_VPG(va), pte); } /* Set the page table entry for va to pte. Flushes cache. */ @@ -626,19 +649,20 @@ setpte4m(va, pte) register struct segmap *sm; register union ctxinfo *c; - if (vactype != VAC_NONE) - cache_flush_page(va); + cache_flush_page(va); /* * Now walk tables to find pte. We use ctxinfo to locate the pmap * from the current context */ +#if 0 #ifdef DEBUG - if (ctxbusyvector[getcontext()] == 0) + if (ctxbusyvector[getcontext4m()] == 0) panic("setpte4m: no pmap for current context (%d)", - getcontext()); + getcontext4m()); #endif - c = &ctxinfo[getcontext()]; +#endif + c = &cpuinfo.ctxinfo[getcontext4m()]; pm = c->c_pmap; /* Note: inline version of setptesw4m() */ @@ -654,17 +678,21 @@ setpte4m(va, pte) panic("setpte4m: no segmap for va %p", (caddr_t)va); #endif tlb_flush_page(va); - sm->sg_pte[VA_SUN4M_VPG(va)] = pte; /* set new pte */ + setpgt4m(sm->sg_pte + VA_SUN4M_VPG(va), pte); } + #endif /* 4m only */ /*----------------------------------------------------------------*/ -#if defined(MMU_3L) -#define CTX_USABLE(pm,rp) (CPU_ISSUN4M \ - ? ((pm)->pm_ctx != NULL ) \ - : ((pm)->pm_ctx != NULL && \ - (!mmu_3l || (rp)->rg_smeg != reginval))) +/* + * The following three macros are to be used in sun4/sun4c code only. + */ +#if defined(SUN4_MMU3L) +#define CTX_USABLE(pm,rp) ( \ + ((pm)->pm_ctx != NULL && \ + (!HASSUN4_MMU3L || (rp)->rg_smeg != reginval)) \ +) #else #define CTX_USABLE(pm,rp) ((pm)->pm_ctx != NULL ) #endif @@ -688,6 +716,7 @@ setpte4m(va, pte) } \ } while (0) + static void sortm __P((struct memarr *, int)); void ctx_alloc __P((struct pmap *)); void ctx_free __P((struct pmap *)); @@ -789,7 +818,8 @@ pmap_next_page(paddr) if (++cpmemarr == npmemarr) return FALSE; avail_next = pmemarr[cpmemarr].addr; - } + } else if (avail_next == unavail_start) + avail_next = unavail_end; #ifdef DIAGNOSTIC /* Any available memory remaining? */ @@ -872,16 +902,16 @@ void mmu_reservemon4_4c(nrp, nsp) register int *nrp, *nsp; { - register vm_offset_t va = 0, eva = 0; + register u_int va = 0, eva = 0; register int mmuseg, i, nr, ns, vr, lastvr; -#ifdef MMU_3L +#if defined(SUN4_MMU3L) register int mmureg; #endif register struct regmap *rp; #if defined(SUN4M) if (CPU_ISSUN4M) { - panic("mmu_reservemon called on Sun4M machine"); + panic("mmu_reservemon4_4c called on Sun4M machine"); return; } #endif @@ -905,8 +935,8 @@ mmu_reservemon4_4c(nrp, nsp) vr = VA_VREG(va); rp = &pmap_kernel()->pm_regmap[vr]; -#ifdef MMU_3L - if (mmu_3l && vr != lastvr) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L && vr != lastvr) { lastvr = vr; mmureg = getregmap(va); if (mmureg < nr) @@ -922,9 +952,8 @@ mmu_reservemon4_4c(nrp, nsp) mmuseg = getsegmap(va); if (mmuseg < ns) ns = mmuseg; -#ifdef MMU_3L - if (!mmu_3l) -#endif + + if (!HASSUN4_MMU3L) for (i = ncontext; --i > 0;) (*promvec->pv_setctxt)(i, (caddr_t)va, mmuseg); @@ -963,24 +992,20 @@ mmu_reservemon4_4c(nrp, nsp) /* * mmu_reservemon4m(): Copies the existing (ROM) page tables to kernel space, * converting any L1/L2 PTEs to L3 PTEs. Does *not* copy the L1 entry mapping - * the kernel at 0xf8000000 (KERNBASE) since we don't want to map 16M of + * the kernel at KERNBASE (0xf8000000) since we don't want to map 16M of * physical memory for the kernel. Thus the kernel must be installed later! * Also installs ROM mappings into the kernel pmap. * NOTE: This also revokes all user-mode access to the mapped regions. - * NOTE ALSO: Must set up kernel pmap as all invalid before this is called. */ void -mmu_reservemon4m(kpmap, kmemtop) +mmu_reservemon4m(kpmap) struct pmap *kpmap; - register caddr_t *kmemtop; /* Note: this is a *virtual* address! */ { - unsigned int ctxtblptr; - int wierdviking = 0; + unsigned int rom_ctxtbl; register int te; - register caddr_t tableptr; - unsigned int mmupcrsav; + unsigned int mmupcrsave; -/*XXX-GCC!*/mmupcrsav = 0; +/*XXX-GCC!*/mmupcrsave = 0; /* * XXX: although the Sun4M can handle 36 bits of physical @@ -993,36 +1018,24 @@ mmu_reservemon4m(kpmap, kmemtop) * physical memory. */ - ctxtblptr = (lda(SRMMU_CXTPTR,ASI_SRMMU) << SRMMU_PPNPASHIFT); + rom_ctxtbl = (lda(SRMMU_CXTPTR,ASI_SRMMU) << SRMMU_PPNPASHIFT); /* We're going to have to use MMU passthrough. If we're on a * Viking MicroSparc without an mbus, we need to turn off traps * and set the AC bit at 0x8000 in the MMU's control register. Ugh. * XXX: Once we've done this, can we still access kernel vm? */ - if ((getpsr() & 0x40000000) && (!(lda(SRMMU_PCR,ASI_SRMMU) & 0x800))) { - wierdviking = 1; + if (cpuinfo.cpu_vers == 4 && cpuinfo.mxcc) { sta(SRMMU_PCR, ASI_SRMMU, /* set MMU AC bit */ - ((mmupcrsav = lda(SRMMU_PCR,ASI_SRMMU)) | SRMMU_PCR_AC)); - } - if (ncontext < 1024) { - /* to keep supersparc happy, still align on 4K boundary */ - ctx_phys_tbl = (int *)roundup((u_int) *kmemtop, 4096); - *kmemtop = (caddr_t)((u_int)ctx_phys_tbl + 4096); - qzero(ctx_phys_tbl, 4096); - } else { - ctx_phys_tbl = (int *)roundup((u_int) *kmemtop, - ncontext * sizeof(int)); - *kmemtop = (caddr_t)((u_int)ctx_phys_tbl + - (ncontext * sizeof(int))); - qzero(ctx_phys_tbl, ncontext * sizeof(int)); + ((mmupcrsave = lda(SRMMU_PCR,ASI_SRMMU)) | VIKING_PCR_AC)); } - te = lda(ctxtblptr, ASI_BYPASS); + te = lda(rom_ctxtbl, ASI_BYPASS); /* i.e. context 0 */ switch (te & SRMMU_TETYPE) { case SRMMU_TEINVALID: - ctx_phys_tbl[0] = SRMMU_TEINVALID; - panic("mmu_reservemon4m: no existing L0 mapping! (How are we running?"); + cpuinfo.ctx_tbl[0] = SRMMU_TEINVALID; + panic("mmu_reservemon4m: no existing L0 mapping! " + "(How are we running?"); break; case SRMMU_TEPTE: #ifdef DEBUG @@ -1032,93 +1045,68 @@ mmu_reservemon4m(kpmap, kmemtop) /* XXX: Should make this work, however stupid it is */ break; case SRMMU_TEPTD: - tableptr = (caddr_t) roundup((u_int) *kmemtop, - SRMMU_L1SIZE * sizeof(long)); - *kmemtop = tableptr + (SRMMU_L1SIZE * sizeof(long)); - bzero(tableptr, *kmemtop - tableptr); - ctx_phys_tbl[0] = (VA2PA(tableptr) >> SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; - kpmap->pm_reg_ptps = (int *)tableptr; - kpmap->pm_reg_ptps_pa = VA2PA(tableptr); - mmu_setup4m_L1(te, tableptr, kpmap, kmemtop); + mmu_setup4m_L1(te, kpmap); break; default: panic("mmu_reservemon4m: unknown pagetable entry type"); } - if (wierdviking == 1) { - sta(SRMMU_PCR, ASI_SRMMU, mmupcrsav); + if (cpuinfo.cpu_vers == 4 && cpuinfo.mxcc) { + sta(SRMMU_PCR, ASI_SRMMU, mmupcrsave); } } void -mmu_setup4m_L1(regtblptd, newtableptr, kpmap, kmemtop) +mmu_setup4m_L1(regtblptd, kpmap) int regtblptd; /* PTD for region table to be remapped */ - caddr_t newtableptr; /* Virtual ptr to new region table */ struct pmap *kpmap; - register caddr_t *kmemtop; { register unsigned int regtblrover; register int i; unsigned int te; - caddr_t segtblptr; - register caddr_t pagtblptr; - struct regmap *thisregmap = NULL; - struct segmap *segmaps; + struct regmap *rp; int j, k; - /* Here we scan the region table to copy any entries which appear. + /* + * Here we scan the region table to copy any entries which appear. * We are only concerned with regions in kernel space and above * (i.e. regions 0xf8 to 0xff). We also ignore region 0xf8, since * that is the 16MB L1 mapping that the ROM used to map the kernel * in initially. Later, we will rebuild a new L3 mapping for the * kernel and install it before switching to the new pagetables. */ - regtblrover = ((regtblptd & ~SRMMU_TETYPE) << SRMMU_PPNPASHIFT) + - (VA_VREG(KERNBASE)+1) * sizeof(long); /* kernel only */ + regtblrover = + ((regtblptd & ~SRMMU_TETYPE) << SRMMU_PPNPASHIFT) + + (VA_VREG(KERNBASE)+1) * sizeof(long); /* kernel only */ for (i = VA_VREG(KERNBASE) + 1; i < SRMMU_L1SIZE; i++, regtblrover += sizeof(long)) { + + /* The region we're dealing with */ + rp = &kpmap->pm_regmap[i]; + te = lda(regtblrover, ASI_BYPASS); switch(te & SRMMU_TETYPE) { case SRMMU_TEINVALID: - ((int *)newtableptr)[i] = SRMMU_TEINVALID; break; + case SRMMU_TEPTE: #ifdef DEBUG - printf("mmu_reservemon4m: converting region 0x%x from L1->L3\n",i); + printf("mmu_setup4m_L1: " + "converting region 0x%x from L1->L3\n", i); #endif - /* We must build segment and page tables, then - * fill them in + /* + * This region entry covers 64MB of memory -- or + * (NSEGRG * NPTESG) pages -- which we must convert + * into a 3-level description. */ - thisregmap = &kpmap->pm_regmap[i]; - bzero(thisregmap, sizeof(struct regmap)); - segmaps = &kernel_segmap_store[(i-VA_VREG(KERNBASE))*NSEGRG]; - segtblptr = (caddr_t) roundup((u_int) *kmemtop, - SRMMU_L2SIZE * sizeof(long)); - *kmemtop = segtblptr + (SRMMU_L2SIZE * sizeof(long)); - bzero(segtblptr, *kmemtop - segtblptr); - bzero(segmaps, NSEGRG * sizeof(struct segmap)); - thisregmap->rg_segmap = segmaps; - thisregmap->rg_seg_ptps = (int *)segtblptr; - ((int *)newtableptr)[i] = (VA2PA(segtblptr) >> - SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; + for (j = 0; j < SRMMU_L2SIZE; j++) { - thisregmap->rg_nsegmap++; - pagtblptr = (caddr_t) roundup((u_int) *kmemtop, - SRMMU_L3SIZE * sizeof(int)); - *kmemtop = segtblptr + (SRMMU_L3SIZE * - sizeof(long)); - bzero(pagtblptr, *kmemtop - pagtblptr); - ((int *)segtblptr)[j] = (VA2PA(pagtblptr) >> - SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; - segmaps[j].sg_pte = (int *)pagtblptr; + struct segmap *sp = &rp->rg_segmap[j]; for (k = 0; k < SRMMU_L3SIZE; k++) { - segmaps[j].sg_npte++; - ((int *)pagtblptr)[k] = + sp->sg_npte++; + (sp->sg_pte)[k] = (te & SRMMU_L1PPNMASK) | (j << SRMMU_L2PPNSHFT) | (k << SRMMU_L3PPNSHFT) | @@ -1129,22 +1117,11 @@ mmu_setup4m_L1(regtblptd, newtableptr, kpmap, kmemtop) } } break; + case SRMMU_TEPTD: - thisregmap = &kpmap->pm_regmap[i]; - bzero(thisregmap, sizeof(struct regmap)); - segtblptr = (caddr_t) roundup((u_int)*kmemtop, - SRMMU_L2SIZE * sizeof(long)); - *kmemtop = segtblptr + (SRMMU_L2SIZE * sizeof(long)); - segmaps = &kernel_segmap_store[(i-(KERNBASE >> RGSHIFT))*NSEGRG]; - bzero(segtblptr, *kmemtop - segtblptr); - bzero(segmaps, NSEGRG * sizeof(struct segmap)); - thisregmap->rg_segmap = segmaps; - thisregmap->rg_seg_ptps = (int *)segtblptr; - ((int *)newtableptr)[i] = (VA2PA(segtblptr) >> - SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; - mmu_setup4m_L2(te, segtblptr, thisregmap, kmemtop, segmaps); + mmu_setup4m_L2(te, rp); break; + default: panic("mmu_setup4m_L1: unknown pagetable entry type"); } @@ -1152,45 +1129,37 @@ mmu_setup4m_L1(regtblptd, newtableptr, kpmap, kmemtop) } void -mmu_setup4m_L2(segtblptd, newtableptr, pregmap, kmemtop, segmaps) +mmu_setup4m_L2(segtblptd, rp) int segtblptd; - caddr_t newtableptr; - struct regmap *pregmap; - register caddr_t *kmemtop; - struct segmap *segmaps; + struct regmap *rp; { register unsigned int segtblrover; register int i, k; unsigned int te; - register caddr_t pagtblptr; - struct segmap *thissegmap = NULL; + struct segmap *sp; segtblrover = (segtblptd & ~SRMMU_TETYPE) << SRMMU_PPNPASHIFT; for (i = 0; i < SRMMU_L2SIZE; i++, segtblrover += sizeof(long)) { + + sp = &rp->rg_segmap[i]; + te = lda(segtblrover, ASI_BYPASS); switch(te & SRMMU_TETYPE) { case SRMMU_TEINVALID: - ((int *)newtableptr)[i] = SRMMU_TEINVALID; break; + case SRMMU_TEPTE: #ifdef DEBUG - printf("mmu_reservemon4m: converting L2 entry at segment 0x%x to L3\n",i); -#endif - pregmap->rg_nsegmap++; - /* We must build page tables and fill them in */ - pagtblptr = (caddr_t) roundup((u_int) *kmemtop, - SRMMU_L3SIZE*sizeof(int)); - *kmemtop = pagtblptr + (SRMMU_L3SIZE * - sizeof(int)); - bzero(pagtblptr, *kmemtop - pagtblptr); - ((int *)newtableptr)[i] = (VA2PA(pagtblptr) >> - SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; - segmaps[i].sg_pte = (int *) pagtblptr; - + printf("mmu_setup4m_L2: converting L2 entry at segment 0x%x to L3\n",i); +#endif + /* + * This segment entry covers 256KB of memory -- or + * (NPTESG) pages -- which we must convert + * into a 3-level description. + */ for (k = 0; k < SRMMU_L3SIZE; k++) { - segmaps[i].sg_npte++; - ((int *)pagtblptr)[k] = + sp->sg_npte++; + (sp->sg_pte)[k] = (te & SRMMU_L1PPNMASK) | (te & SRMMU_L2PPNMASK) | (k << SRMMU_L3PPNSHFT) | @@ -1200,32 +1169,24 @@ mmu_setup4m_L2(segtblptd, newtableptr, pregmap, kmemtop, segmaps) SRMMU_TEPTE; } break; + case SRMMU_TEPTD: - pregmap->rg_nsegmap++; - thissegmap = &segmaps[i]; - pagtblptr = (caddr_t) roundup((u_int) *kmemtop, - SRMMU_L3SIZE*sizeof(int)); - *kmemtop = pagtblptr + (SRMMU_L3SIZE * sizeof(int)); - bzero(pagtblptr, *kmemtop - pagtblptr); - ((int *)newtableptr)[i] = (VA2PA(pagtblptr) >> - SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; - thissegmap->sg_pte = (int *) pagtblptr; - thissegmap->sg_npte += mmu_setup4m_L3(te, pagtblptr); + mmu_setup4m_L3(te, sp); break; + default: panic("mmu_setup4m_L2: unknown pagetable entry type"); } } } -int -mmu_setup4m_L3(pagtblptd, newtableptr) +void +mmu_setup4m_L3(pagtblptd, sp) register int pagtblptd; - register caddr_t newtableptr; + struct segmap *sp; { register unsigned int pagtblrover; - register int i, n = 0; + register int i; register unsigned int te; pagtblrover = (pagtblptd & ~SRMMU_TETYPE) << SRMMU_PPNPASHIFT; @@ -1233,11 +1194,10 @@ mmu_setup4m_L3(pagtblptd, newtableptr) te = lda(pagtblrover, ASI_BYPASS); switch(te & SRMMU_TETYPE) { case SRMMU_TEINVALID: - ((int *)newtableptr)[i] = SRMMU_TEINVALID; break; case SRMMU_TEPTE: - ((int *)newtableptr)[i] = te | PPROT_U2S_OMASK; - n++; + sp->sg_npte++; + sp->sg_pte[i] = te | PPROT_U2S_OMASK; break; case SRMMU_TEPTD: panic("mmu_setup4m_L3: PTD found in L3 page table"); @@ -1245,15 +1205,9 @@ mmu_setup4m_L3(pagtblptd, newtableptr) panic("mmu_setup4m_L3: unknown pagetable entry type"); } } - return n; } #endif /* defined SUN4M */ -/* - * TODO: agree with the ROM on physical pages by taking them away - * from the page list, rather than having a dinky BTSIZE above. - */ - /*----------------------------------------------------------------*/ /* @@ -1316,6 +1270,13 @@ me_alloc(mh, newpm, newvreg, newvseg) /* onto on pmap chain; pmap is already locked, if needed */ TAILQ_INSERT_TAIL(&newpm->pm_seglist, me, me_pmchain); +#ifdef DIAGNOSTIC + pmap_stats.ps_npmeg_free--; + if (mh == &segm_locked) + pmap_stats.ps_npmeg_locked++; + else + pmap_stats.ps_npmeg_lru++; +#endif /* into pmap segment table, with backpointers */ newpm->pm_regmap[newvreg].rg_segmap[newvseg].sg_pmeg = me->me_cookie; @@ -1337,7 +1298,7 @@ me_alloc(mh, newpm, newvreg, newvseg) panic("me_alloc: stealing from kernel"); #ifdef DEBUG if (pmapdebug & (PDB_MMU_ALLOC | PDB_MMU_STEAL)) - printf("me_alloc: stealing pmeg %x from pmap %p\n", + printf("me_alloc: stealing pmeg 0x%x from pmap %p\n", me->me_cookie, pm); #endif /* @@ -1347,6 +1308,13 @@ me_alloc(mh, newpm, newvreg, newvseg) TAILQ_REMOVE(&segm_lru, me, me_list); TAILQ_INSERT_TAIL(mh, me, me_list); +#ifdef DIAGNOSTIC + if (mh == &segm_locked) { + pmap_stats.ps_npmeg_lru--; + pmap_stats.ps_npmeg_locked++; + } +#endif + rp = &pm->pm_regmap[me->me_vreg]; if (rp->rg_segmap == NULL) panic("me_alloc: LRU entry's pmap has no segments"); @@ -1366,18 +1334,15 @@ me_alloc(mh, newpm, newvreg, newvseg) * XXX for ncpus>1 must use per-cpu VA? * XXX do not have to flush cache immediately */ - ctx = getcontext(); + ctx = getcontext4(); if (CTX_USABLE(pm,rp)) { CHANGE_CONTEXTS(ctx, pm->pm_ctxnum); - if (vactype != VAC_NONE) - cache_flush_segment(me->me_vreg, me->me_vseg); + cache_flush_segment(me->me_vreg, me->me_vseg); va = VSTOVA(me->me_vreg,me->me_vseg); } else { CHANGE_CONTEXTS(ctx, 0); -#ifdef MMU_3L - if (mmu_3l) + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, me->me_cookie); /* * No cache flush needed: it happened earlier when @@ -1412,7 +1377,7 @@ me_alloc(mh, newpm, newvreg, newvseg) /* off old pmap chain */ TAILQ_REMOVE(&pm->pm_seglist, me, me_pmchain); simple_unlock(&pm->pm_lock); - setcontext(ctx); /* done with old context */ + setcontext4(ctx); /* done with old context */ /* onto new pmap chain; new pmap is already locked, if needed */ TAILQ_INSERT_TAIL(&newpm->pm_seglist, me, me_pmchain); @@ -1465,12 +1430,10 @@ me_free(pm, pmeg) va = VSTOVA(vr,me->me_vseg); } else { #ifdef DEBUG -if (getcontext() != 0) panic("me_free: ctx != 0"); +if (getcontext4() != 0) panic("me_free: ctx != 0"); #endif -#ifdef MMU_3L - if (mmu_3l) + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, me->me_cookie); va = 0; } @@ -1495,16 +1458,25 @@ if (getcontext() != 0) panic("me_free: ctx != 0"); /* off LRU or lock chain */ if (pm == pmap_kernel()) { TAILQ_REMOVE(&segm_locked, me, me_list); +#ifdef DIAGNOSTIC + pmap_stats.ps_npmeg_locked--; +#endif } else { TAILQ_REMOVE(&segm_lru, me, me_list); +#ifdef DIAGNOSTIC + pmap_stats.ps_npmeg_lru--; +#endif } /* no associated pmap; on free list */ me->me_pmap = NULL; TAILQ_INSERT_TAIL(&segm_freelist, me, me_list); +#ifdef DIAGNOSTIC + pmap_stats.ps_npmeg_free++; +#endif } -#ifdef MMU_3L +#if defined(SUN4_MMU3L) /* XXX - Merge with segm_alloc/segm_free ? */ @@ -1526,7 +1498,7 @@ region_alloc(mh, newpm, newvr) if (me->me_pmap != NULL) panic("region_alloc: freelist entry has pmap"); if (pmapdebug & PDB_MMUREG_ALLOC) - printf("region_alloc: got smeg %x\n", me->me_cookie); + printf("region_alloc: got smeg 0x%x\n", me->me_cookie); #endif TAILQ_INSERT_TAIL(mh, me, me_list); @@ -1552,7 +1524,7 @@ region_alloc(mh, newpm, newvr) panic("region_alloc: stealing from kernel"); #ifdef DEBUG if (pmapdebug & (PDB_MMUREG_ALLOC | PDB_MMUREG_STEAL)) - printf("region_alloc: stealing smeg %x from pmap %p\n", + printf("region_alloc: stealing smeg 0x%x from pmap %p\n", me->me_cookie, pm); #endif /* @@ -1563,11 +1535,10 @@ region_alloc(mh, newpm, newvr) TAILQ_INSERT_TAIL(mh, me, me_list); rp = &pm->pm_regmap[me->me_vreg]; - ctx = getcontext(); + ctx = getcontext4(); if (pm->pm_ctx) { CHANGE_CONTEXTS(ctx, pm->pm_ctxnum); - if (vactype != VAC_NONE) - cache_flush_region(me->me_vreg); + cache_flush_region(me->me_vreg); } /* update region tables */ @@ -1579,7 +1550,7 @@ region_alloc(mh, newpm, newvr) /* off old pmap chain */ TAILQ_REMOVE(&pm->pm_reglist, me, me_pmchain); simple_unlock(&pm->pm_lock); - setcontext(ctx); /* done with old context */ + setcontext4(ctx); /* done with old context */ /* onto new pmap chain; new pmap is already locked, if needed */ TAILQ_INSERT_TAIL(&newpm->pm_reglist, me, me_pmchain); @@ -1610,7 +1581,7 @@ region_free(pm, smeg) #ifdef DEBUG if (pmapdebug & PDB_MMUREG_ALLOC) - printf("region_free: freeing smeg %x from pmap %p\n", + printf("region_free: freeing smeg 0x%x from pmap %p\n", me->me_cookie, pm); if (me->me_cookie != smeg) panic("region_free: wrong mmuentry"); @@ -1619,8 +1590,7 @@ region_free(pm, smeg) #endif if (pm->pm_ctx) - if (vactype != VAC_NONE) - cache_flush_region(me->me_vreg); + cache_flush_region(me->me_vreg); /* take mmu entry off pmap chain */ TAILQ_REMOVE(&pm->pm_reglist, me, me_pmchain); @@ -1650,8 +1620,7 @@ region_free(pm, smeg) int mmu_pagein(pm, va, prot) register struct pmap *pm; - register vm_offset_t va; - vm_prot_t prot; + register int va, prot; { register int *pte; register int vr, vs, pmeg, i, s, bits; @@ -1668,14 +1637,14 @@ mmu_pagein(pm, va, prot) rp = &pm->pm_regmap[vr]; #ifdef DEBUG if (pm == pmap_kernel()) -printf("mmu_pagein: kernel wants map at va %x, vr %d, vs %d\n", va, vr, vs); +printf("mmu_pagein: kernel wants map at va 0x%x, vr %d, vs %d\n", va, vr, vs); #endif /* return 0 if we have no PMEGs to load */ if (rp->rg_segmap == NULL) return (0); -#ifdef MMU_3L - if (mmu_3l && rp->rg_smeg == reginval) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L && rp->rg_smeg == reginval) { smeg_t smeg; unsigned int tva = VA_ROUNDDOWNTOREG(va); struct segmap *sp = rp->rg_segmap; @@ -1716,56 +1685,6 @@ printf("mmu_pagein: kernel wants map at va %x, vr %d, vs %d\n", va, vr, vs); } #endif /* defined SUN4 or SUN4C */ -#if defined(DEBUG) && defined(SUN4M) -/* - * `Page in' (load or inspect) an MMU entry; called on page faults. - * Returns -1 if the desired page was marked valid (in which case the - * fault must be a bus error or something), or 0 (segment loaded but - * PTE not valid, or segment not loaded at all). - * - * The SRMMU does not have the concept of `loading PMEGs into the MMU'. - * For now, we use it to debug certain sporadic and strange memory - * fault traps. - */ -int -mmu_pagein4m(pm, va, prot) - register struct pmap *pm; - register vm_offset_t va; - register int prot; -{ - register int pte; - register int bits; - - pte = getpte4m(va); - if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) - /* pte not found == not valid */ - return 0; - - /* - * If pte has "correct" protection (according to bits), then - * something bizarre has happened, so we return -1 to generate - * a fault. Otherwise, we return 0 and let the VM code reload - * the page. - * XXX: Does this actually work, or will it cause a loop? - */ - - if (prot != VM_PROT_NONE) - bits = ((prot & VM_PROT_WRITE) ? PPROT_RWX_RWX : PPROT_RX_RX); - else - bits = 0; - /* If we're in kernelland, mask out user RWX */ -/* if (getcontext() == 0) - bits |= PPROT_S; -*/ - if (bits && (pte & bits) == bits) { - printf("pagein4m(%s[%d]): OOPS: prot=%x, va=%x, pte=%x, bits=%x\n", - curproc->p_comm, curproc->p_pid, prot, va, pte, bits); - return -1; - } - return 0; -} -#endif - /* * Allocate a context. If necessary, steal one from someone else. * Changes hardware context number and loads segment map. @@ -1798,7 +1717,7 @@ ctx_alloc(pm) s = splpmap(); if ((c = ctx_freelist) != NULL) { ctx_freelist = c->c_nextfree; - cnum = c - ctxinfo; + cnum = c - cpuinfo.ctxinfo; doflush = 0; } else { if ((ctx_kick += ctx_kickdir) >= ncontext) { @@ -1808,7 +1727,7 @@ ctx_alloc(pm) ctx_kick = 1; ctx_kickdir = 1; } - c = &ctxinfo[cnum = ctx_kick]; + c = &cpuinfo.ctxinfo[cnum = ctx_kick]; #ifdef DEBUG if (c->c_pmap == NULL) panic("ctx_alloc cu_pmap"); @@ -1817,7 +1736,7 @@ ctx_alloc(pm) cnum, c->c_pmap); #endif c->c_pmap->pm_ctx = NULL; - doflush = (vactype != VAC_NONE); + doflush = (CACHEINFO.c_vactype != VAC_NONE); if (CPU_ISSUN4OR4C) { if (gap_start < c->c_pmap->pm_gap_start) gap_start = c->c_pmap->pm_gap_start; @@ -1851,7 +1770,7 @@ ctx_alloc(pm) * disjuction of the new and the previous map. */ - setcontext(cnum); + setcontext4(cnum); splx(s); if (doflush) cache_flush_context(); @@ -1867,13 +1786,10 @@ ctx_alloc(pm) /* mustn't re-enter this branch */ gap_start = NUREG; } -#ifdef MMU_3L - if (mmu_3l) { + if (HASSUN4_MMU3L) { setregmap(va, rp++->rg_smeg); va += NBPRG; - } else -#endif - { + } else { register int j; register struct segmap *sp = rp->rg_segmap; for (j = NSEGRG; --j >= 0; va += NBPSG) @@ -1885,6 +1801,7 @@ ctx_alloc(pm) } else if (CPU_ISSUN4M) { +#if defined(SUN4M) /* * Reload page and context tables to activate the page tables * for this context. @@ -1906,38 +1823,20 @@ ctx_alloc(pm) * XXX: Do we have to flush cache after reloading ctx tbl? */ - /* - * We install kernel mappings into the pmap here, since when - * the kernel expands it only propagates the expansion to pmaps - * corresponding to valid contexts. Thus it is possible (and - * it has happened!) that a pmap is created just before - * the kernel expands, but the pmap gets a context *after* - * the kernel expands, thus missing getting mappings. - */ - qcopy(&pmap_kernel()->pm_reg_ptps[VA_VREG(KERNBASE)], - &pm->pm_reg_ptps[VA_VREG(KERNBASE)], - NKREG * sizeof(int)); - /* - * We must also install the regmap/segmap/etc stuff for - * kernel maps. - */ - qcopy(&pmap_kernel()->pm_regmap[VA_VREG(KERNBASE)], - &pm->pm_regmap[VA_VREG(KERNBASE)], - NKREG * sizeof(struct regmap)); - - ctxbusyvector[cnum] = 1; /* mark context as busy */ #ifdef DEBUG +#if 0 + ctxbusyvector[cnum] = 1; /* mark context as busy */ +#endif if (pm->pm_reg_ptps_pa == 0) panic("ctx_alloc: no region table in current pmap"); #endif /*setcontext(0); * paranoia? can we modify curr. ctx? */ - ctx_phys_tbl[cnum] = - (pm->pm_reg_ptps_pa >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD; + setpgt4m(&cpuinfo.ctx_tbl[cnum], + (pm->pm_reg_ptps_pa >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD); - setcontext(cnum); + setcontext4m(cnum); if (doflush) cache_flush_context(); -#if defined(SUN4M) tlb_flush_context(); /* remove any remnant garbage from tlb */ #endif splx(s); @@ -1959,7 +1858,7 @@ ctx_free(pm) pm->pm_ctx = NULL; oldc = getcontext(); - if (vactype != VAC_NONE) { + if (CACHEINFO.c_vactype != VAC_NONE) { newc = pm->pm_ctxnum; CHANGE_CONTEXTS(oldc, newc); cache_flush_context(); @@ -1970,23 +1869,28 @@ ctx_free(pm) setcontext(0); } else { #if defined(SUN4M) - if (CPU_ISSUN4M) + if (CPU_ISSUN4M) { + newc = pm->pm_ctxnum; + CHANGE_CONTEXTS(oldc, newc); tlb_flush_context(); + } #endif CHANGE_CONTEXTS(oldc, 0); } c->c_nextfree = ctx_freelist; ctx_freelist = c; +#if 0 #if defined(SUN4M) if (CPU_ISSUN4M) { /* Map kernel back into unused context */ newc = pm->pm_ctxnum; - ctx_phys_tbl[newc] = ctx_phys_tbl[0]; + cpuinfo.ctx_tbl[newc] = cpuinfo.ctx_tbl[0]; if (newc) ctxbusyvector[newc] = 0; /* mark as free */ } #endif +#endif } @@ -2020,8 +1924,7 @@ pv_changepte4_4c(pv0, bis, bic) register int *pte; register struct pvlist *pv; register struct pmap *pm; - register vm_offset_t va; - register int vr, vs, flags; + register int va, vr, vs, flags; int ctx, s; struct regmap *rp; struct segmap *sp; @@ -2033,11 +1936,14 @@ pv_changepte4_4c(pv0, bis, bic) splx(s); return; } - ctx = getcontext(); + ctx = getcontext4(); flags = pv0->pv_flags; for (pv = pv0; pv != NULL; pv = pv->pv_next) { pm = pv->pv_pmap; -if(pm==NULL)panic("pv_changepte 1"); +#ifdef DIAGNOSTIC + if(pm == NULL) + panic("pv_changepte: pm == NULL"); +#endif va = pv->pv_va; vr = VA_VREG(va); vs = VA_VSEG(va); @@ -2051,7 +1957,7 @@ if(pm==NULL)panic("pv_changepte 1"); if (sp->sg_pmeg == seginval) { /* not in hardware: just fix software copy */ if (pte == NULL) - panic("pv_changepte 2"); + panic("pv_changepte: pte == NULL"); pte += VA_VPG(va); *pte = (*pte | bis) & ~bic; } else { @@ -2071,24 +1977,26 @@ if(pm==NULL)panic("pv_changepte 1"); if (bic == PG_NC && va >= DVMA_BASE && va < DVMA_END) continue; - setcontext(pm->pm_ctxnum); + setcontext4(pm->pm_ctxnum); /* XXX should flush only when necessary */ tpte = getpte4(va); - if (vactype != VAC_NONE && (tpte & PG_M)) - cache_flush_page(va); + /* + * XXX: always flush cache; conservative, but + * needed to invalidate cache tag protection + * bits and when disabling caching. + */ + cache_flush_page(va); } else { /* XXX per-cpu va? */ - setcontext(0); -#ifdef MMU_3L - if (mmu_3l) + setcontext4(0); + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, sp->sg_pmeg); va = VA_VPG(va) << PGSHIFT; tpte = getpte4(va); } if (tpte & PG_V) - flags |= (tpte >> PG_M_SHIFT) & (PV_MOD|PV_REF); + flags |= MR4_4C(tpte); tpte = (tpte | bis) & ~bic; setpte4(va, tpte); if (pte != NULL) /* update software copy */ @@ -2096,7 +2004,7 @@ if(pm==NULL)panic("pv_changepte 1"); } } pv0->pv_flags = flags; - setcontext(ctx); + setcontext4(ctx); splx(s); } @@ -2125,7 +2033,7 @@ pv_syncflags4_4c(pv0) splx(s); return (0); } - ctx = getcontext(); + ctx = getcontext4(); flags = pv0->pv_flags; for (pv = pv0; pv != NULL; pv = pv->pv_next) { pm = pv->pv_pmap; @@ -2141,31 +2049,28 @@ pv_syncflags4_4c(pv0) continue; if (CTX_USABLE(pm,rp)) { - setcontext(pm->pm_ctxnum); + setcontext4(pm->pm_ctxnum); /* XXX should flush only when necessary */ tpte = getpte4(va); - if (vactype != VAC_NONE && (tpte & PG_M)) + if (tpte & PG_M) cache_flush_page(va); } else { /* XXX per-cpu va? */ - setcontext(0); -#ifdef MMU_3L - if (mmu_3l) + setcontext4(0); + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, pmeg); va = VA_VPG(va) << PGSHIFT; tpte = getpte4(va); } if (tpte & (PG_M|PG_U) && tpte & PG_V) { - flags |= (tpte >> PG_M_SHIFT) & - (PV_MOD|PV_REF); + flags |= MR4_4C(tpte); tpte &= ~(PG_M|PG_U); setpte4(va, tpte); } } pv0->pv_flags = flags; - setcontext(ctx); + setcontext4(ctx); splx(s); return (flags); } @@ -2190,10 +2095,8 @@ pv_unlink4_4c(pv, pm, va) register struct pvlist *npv; #ifdef DIAGNOSTIC - if (pv == NULL) - panic("pv_unlink: pv==NULL"); if (pv->pv_pmap == NULL) - panic("pv_unlink: pv->pv_pmap==NULL"); + panic("pv_unlink0"); #endif /* * First entry is special (sigh). @@ -2205,9 +2108,10 @@ pv_unlink4_4c(pv, pm, va) pv->pv_next = npv->pv_next; pv->pv_pmap = npv->pv_pmap; pv->pv_va = npv->pv_va; - free(npv, M_VMPVENT); + FREE(npv, M_VMPVENT); } else { pv->pv_pmap = NULL; + pv->pv_flags &= ~PV_NC; return; } } else { @@ -2216,12 +2120,12 @@ pv_unlink4_4c(pv, pm, va) for (prev = pv;; prev = npv, npv = npv->pv_next) { pmap_stats.ps_unlink_pvsearch++; if (npv == NULL) - panic("pv_unlink: npv==NULL"); + panic("pv_unlink"); if (npv->pv_pmap == pm && npv->pv_va == va) break; } prev->pv_next = npv->pv_next; - free(npv, M_VMPVENT); + FREE(npv, M_VMPVENT); } if (pv->pv_flags & PV_NC) { /* @@ -2273,10 +2177,12 @@ pv_link4_4c(pv, pm, va) for (npv = pv; npv != NULL; npv = npv->pv_next) { if (BADALIAS(va, npv->pv_va)) { #ifdef DEBUG - if (pmapdebug) printf( - "pv_link: badalias: pid %d, %lx<=>%x, pa %lx\n", - curproc?curproc->p_pid:-1, va, npv->pv_va, - vm_first_phys + (pv-pv_table)*NBPG); + if (pmapdebug & PDB_CACHESTUFF) + printf( + "pv_link: badalias: pid %d, 0x%lx<=>0x%lx, pa 0x%lx\n", + curproc ? curproc->p_pid : -1, + va, npv->pv_va, + vm_first_phys + (pv-pv_table)*NBPG); #endif pv->pv_flags |= PV_NC; pv_changepte4_4c(pv, ret = PG_NC, 0); @@ -2284,7 +2190,7 @@ pv_link4_4c(pv, pm, va) } } } - npv = (struct pvlist *)malloc(sizeof *npv, M_VMPVENT, M_WAITOK); + MALLOC(npv, struct pvlist *, sizeof *npv, M_VMPVENT, M_WAITOK); npv->pv_next = pv->pv_next; npv->pv_pmap = pm; npv->pv_va = va; @@ -2315,10 +2221,10 @@ pv_changepte4m(pv0, bis, bic) { register struct pvlist *pv; register struct pmap *pm; - register vm_offset_t va; - register int vr, flags; + register int va, vr, flags; int ctx, s; struct regmap *rp; + struct segmap *sp; write_user_windows(); /* paranoid? */ @@ -2327,20 +2233,24 @@ pv_changepte4m(pv0, bis, bic) splx(s); return; } - ctx = getcontext(); + ctx = getcontext4m(); flags = pv0->pv_flags; for (pv = pv0; pv != NULL; pv = pv->pv_next) { register int tpte; pm = pv->pv_pmap; +#ifdef DIAGNOSTIC if (pm == NULL) - panic("pv_changepte 1"); + panic("pv_changepte: pm == NULL"); +#endif va = pv->pv_va; vr = VA_VREG(va); rp = &pm->pm_regmap[vr]; if (rp->rg_segmap == NULL) panic("pv_changepte: no segments"); - if (CTX_USABLE(pm,rp)) { + sp = &rp->rg_segmap[VA_VSEG(va)]; + + if (pm->pm_ctx) { extern vm_offset_t pager_sva, pager_eva; /* @@ -2353,27 +2263,34 @@ pv_changepte4m(pv0, bis, bic) if ((bis & SRMMU_PG_C) && va >= DVMA_BASE && va < DVMA_END) continue; - setcontext(pm->pm_ctxnum); - /* %%%: Do we need to always flush? */ - tpte = getpte4m(va); - if (vactype != VAC_NONE && (tpte & SRMMU_PG_M)) - cache_flush_page(va); - } else { - /* PTE that we want has no context. Use sw getpte*/ - tpte = getptesw4m(pm, va); + + setcontext4m(pm->pm_ctxnum); + + /* + * XXX: always flush cache; conservative, but + * needed to invalidate cache tag protection + * bits and when disabling caching. + */ + cache_flush_page(va); + + /* Flush TLB so memory copy is up-to-date */ + tlb_flush_page(va); + + } + + tpte = sp->sg_pte[VA_SUN4M_VPG(va)]; + if ((tpte & SRMMU_TETYPE) != SRMMU_TEPTE) { + printf("pv_changepte: invalid PTE for 0x%x\n", va); + continue; } - if ((tpte & SRMMU_TETYPE) == SRMMU_TEPTE) /* i.e. if valid pte */ - flags |= (tpte >> PG_M_SHIFT4M) & (PV_MOD4M|PV_REF4M|PV_C4M); + flags |= (tpte >> PG_M_SHIFT4M) & (PV_MOD4M|PV_REF4M|PV_C4M); tpte = (tpte | bis) & ~bic; - if (CTX_USABLE(pm,rp)) - setpte4m(va, tpte); - else - setptesw4m(pm, va, tpte); + setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], tpte); } pv0->pv_flags = flags; - setcontext(ctx); + setcontext4m(ctx); splx(s); } @@ -2401,7 +2318,7 @@ pv_syncflags4m(pv0) splx(s); return (0); } - ctx = getcontext(); + ctx = getcontext4m(); flags = pv0->pv_flags; for (pv = pv0; pv != NULL; pv = pv->pv_next) { pm = pv->pv_pmap; @@ -2420,26 +2337,30 @@ pv_syncflags4m(pv0) * We need the PTE from memory as the TLB version will * always have the SRMMU_PG_R bit on. */ - if (CTX_USABLE(pm,rp)) { - setcontext(pm->pm_ctxnum); + if (pm->pm_ctx) { + setcontext4m(pm->pm_ctxnum); tlb_flush_page(va); } - tpte = getptesw4m(pm, va); + tpte = sp->sg_pte[VA_SUN4M_VPG(va)]; if ((tpte & SRMMU_TETYPE) == SRMMU_TEPTE && /* if valid pte */ (tpte & (SRMMU_PG_M|SRMMU_PG_R))) { /* and mod/refd */ + flags |= (tpte >> PG_M_SHIFT4M) & (PV_MOD4M|PV_REF4M|PV_C4M); - tpte &= ~(SRMMU_PG_M | SRMMU_PG_R); - /* TLB has been invalidated, so just update memory */ - setptesw4m(pm, va, tpte); - if (vactype != VAC_NONE && - CTX_USABLE(pm,rp) && (tpte & SRMMU_PG_M)) + + if (pm->pm_ctx && (tpte & SRMMU_PG_M)) { cache_flush_page(va); /* XXX: do we need this?*/ + tlb_flush_page(va); /* paranoid? */ + } + + /* Clear mod/ref bits from PTE and write it back */ + tpte &= ~(SRMMU_PG_M | SRMMU_PG_R); + setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], tpte); } } pv0->pv_flags = flags; - setcontext(ctx); + setcontext4m(ctx); splx(s); return (flags); } @@ -2453,10 +2374,8 @@ pv_unlink4m(pv, pm, va) register struct pvlist *npv; #ifdef DIAGNOSTIC - if (pv == NULL) - panic("pv_unlink: pv==NULL"); if (pv->pv_pmap == NULL) - panic("pv_unlink: pv->pv_pmap==NULL"); + panic("pv_unlink0"); #endif /* * First entry is special (sigh). @@ -2468,9 +2387,10 @@ pv_unlink4m(pv, pm, va) pv->pv_next = npv->pv_next; pv->pv_pmap = npv->pv_pmap; pv->pv_va = npv->pv_va; - free(npv, M_VMPVENT); + FREE(npv, M_VMPVENT); } else { pv->pv_pmap = NULL; + pv->pv_flags |= PV_C4M; return; } } else { @@ -2479,12 +2399,12 @@ pv_unlink4m(pv, pm, va) for (prev = pv;; prev = npv, npv = npv->pv_next) { pmap_stats.ps_unlink_pvsearch++; if (npv == NULL) - panic("pv_unlink: npv==NULL"); + panic("pv_unlink"); if (npv->pv_pmap == pm && npv->pv_va == va) break; } prev->pv_next = npv->pv_next; - free(npv, M_VMPVENT); + FREE(npv, M_VMPVENT); } if (!(pv->pv_flags & PV_C4M)) { /* @@ -2536,10 +2456,12 @@ pv_link4m(pv, pm, va) for (npv = pv; npv != NULL; npv = npv->pv_next) { if (BADALIAS(va, npv->pv_va)) { #ifdef DEBUG - if (pmapdebug & PDB_CACHESTUFF) printf( - "pv_link: badalias: pid %d, %lx<=>%x, pa %lx\n", - curproc?curproc->p_pid:-1, va, npv->pv_va, - vm_first_phys + (pv-pv_table)*NBPG); + if (pmapdebug & PDB_CACHESTUFF) + printf( + "pv_link: badalias: pid %d, 0x%lx<=>0x%lx, pa 0x%lx\n", + curproc ? curproc->p_pid : -1, + va, npv->pv_va, + vm_first_phys + (pv-pv_table)*NBPG); #endif pv->pv_flags &= ~PV_C4M; pv_changepte4m(pv, 0, ret = SRMMU_PG_C); @@ -2548,7 +2470,7 @@ pv_link4m(pv, pm, va) } } } - npv = (struct pvlist *)malloc(sizeof *npv, M_VMPVENT, M_WAITOK); + MALLOC(npv, struct pvlist *, sizeof *npv, M_VMPVENT, M_WAITOK); npv->pv_next = pv->pv_next; npv->pv_pmap = pm; npv->pv_va = va; @@ -2626,7 +2548,9 @@ pmap_bootstrap(nctx, nregion, nsegment) nptesg = (NBPSG >> pgshift); #endif +#if 0 ncontext = nctx; +#endif #if defined(SUN4M) if (CPU_ISSUN4M) { @@ -2649,7 +2573,7 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) { register union ctxinfo *ci; register struct mmuentry *mmuseg; -#ifdef MMU_3L +#if defined(SUN4_MMU3L) register struct mmuentry *mmureg; #endif struct regmap *rp; @@ -2663,7 +2587,6 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) extern char end[]; #ifdef DDB extern char *esym; - char *theend = end; #endif switch (cputyp) { @@ -2671,7 +2594,7 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) mmu_has_hole = 1; break; case CPU_SUN4: - if (cpumod != SUN4_400) { + if (cpuinfo.cpu_type != CPUTYP_4_400) { mmu_has_hole = 1; break; } @@ -2716,8 +2639,8 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) */ seginval = --nsegment; -#ifdef MMU_3L - if (mmu_3l) +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L) reginval = --nregion; #endif @@ -2727,14 +2650,14 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) /* kernel_pmap_store.pm_ctxnum = 0; */ simple_lock_init(kernel_pmap_store.pm_lock); kernel_pmap_store.pm_refcount = 1; -#ifdef MMU_3L +#if defined(SUN4_MMU3L) TAILQ_INIT(&kernel_pmap_store.pm_reglist); #endif TAILQ_INIT(&kernel_pmap_store.pm_seglist); kernel_pmap_store.pm_regmap = &kernel_regmap_store[-NUREG]; for (i = NKREG; --i >= 0;) { -#ifdef MMU_3L +#if defined(SUN4_MMU3L) kernel_regmap_store[i].rg_smeg = reginval; #endif kernel_regmap_store[i].rg_segmap = @@ -2752,7 +2675,7 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) mmu_reservemon4_4c(&nregion, &nsegment); -#ifdef MMU_3L +#if defined(SUN4_MMU3L) /* Reserve one region for temporary mappings */ tregion = --nregion; #endif @@ -2763,24 +2686,22 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) p = end; #ifdef DDB if (esym != 0) - theend = p = esym; + p = esym; #endif -#ifdef MMU_3L +#if defined(SUN4_MMU3L) mmuregions = mmureg = (struct mmuentry *)p; p += nregion * sizeof(struct mmuentry); + bzero(mmuregions, nregion * sizeof(struct mmuentry)); #endif mmusegments = mmuseg = (struct mmuentry *)p; p += nsegment * sizeof(struct mmuentry); - pmap_kernel()->pm_ctx = ctxinfo = ci = (union ctxinfo *)p; + bzero(mmusegments, nsegment * sizeof(struct mmuentry)); + + pmap_kernel()->pm_ctx = cpuinfo.ctxinfo = ci = (union ctxinfo *)p; p += nctx * sizeof *ci; -#ifdef DDB - bzero(theend, p - theend); -#else - bzero(end, p - end); -#endif /* Initialize MMU resource queues */ -#ifdef MMU_3L +#if defined(SUN4_MMU3L) TAILQ_INIT(®ion_freelist); TAILQ_INIT(®ion_lru); TAILQ_INIT(®ion_locked); @@ -2890,8 +2811,8 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) #endif vr++, rp++; } -#ifdef MMU_3L - if (mmu_3l) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L) { for (i = 1; i < nctx; i++) rom_setmap(i, p, rcookie); @@ -2909,8 +2830,8 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) #endif } -#ifdef MMU_3L - if (!mmu_3l) +#if defined(SUN4_MMU3L) + if (!HASSUN4_MMU3L) #endif for (i = 1; i < nctx; i++) rom_setmap(i, p, scookie); @@ -2918,6 +2839,7 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) /* set up the mmu entry */ TAILQ_INSERT_TAIL(&segm_locked, mmuseg, me_list); TAILQ_INSERT_TAIL(&pmap_kernel()->pm_seglist, mmuseg, me_pmchain); + pmap_stats.ps_npmeg_locked++; mmuseg->me_cookie = scookie; mmuseg->me_pmap = pmap_kernel(); mmuseg->me_vreg = vr; @@ -2940,8 +2862,8 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) for (p += npte << PGSHIFT; npte < NPTESG; npte++, p += NBPG) setpte4(p, 0); -#ifdef MMU_3L - if (mmu_3l) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L) { /* * Unmap the segments, if any, that are not part of * the final region. @@ -2953,8 +2875,8 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) break; } -#ifdef MMU_3L - if (mmu_3l) +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L) for (; rcookie < nregion; rcookie++, mmureg++) { mmureg->me_cookie = rcookie; TAILQ_INSERT_TAIL(®ion_freelist, mmureg, me_list); @@ -2964,17 +2886,16 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) for (; scookie < nsegment; scookie++, mmuseg++) { mmuseg->me_cookie = scookie; TAILQ_INSERT_TAIL(&segm_freelist, mmuseg, me_list); + pmap_stats.ps_npmeg_free++; } /* Erase all spurious user-space segmaps */ for (i = 1; i < ncontext; i++) { - setcontext(i); -#ifdef MMU_3L - if (mmu_3l) + setcontext4(i); + if (HASSUN4_MMU3L) for (p = 0, j = NUREG; --j >= 0; p += NBPRG) setregmap(p, reginval); else -#endif for (p = 0, vr = 0; vr < NUREG; vr++) { if (VA_INHOLE(p)) { p = (caddr_t)MMU_HOLE_END; @@ -2984,7 +2905,7 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) setsegmap(p, seginval); } } - setcontext(0); + setcontext4(0); /* * write protect & encache kernel text; @@ -3014,25 +2935,19 @@ static void pmap_bootstrap4m(void) { register int i, j; - caddr_t p, p2; + caddr_t p; register caddr_t q; register union ctxinfo *ci; register struct memarr *mp; - struct regmap *rmapp = NULL; - struct segmap *smapp = NULL; register int reg, seg; -#if 0 - int nkreg, nkseg, nkpag, kernsize, newpgs; -#endif - caddr_t kphyssegtbl, kphyspagtbl = NULL; - int deadfill, deadspace; + unsigned int ctxtblsize; + caddr_t pagetables_start, pagetables_end; extern char end[]; extern char etext[]; + extern caddr_t reserve_dumppages(caddr_t); #ifdef DDB extern char *esym; - char *theend = end; #endif - extern caddr_t reserve_dumppages(caddr_t); #if defined(SUN4) || defined(SUN4C) /* setup 4M fn. ptrs for dual-arch kernel */ pmap_clear_modify_p = pmap_clear_modify4m; @@ -3054,9 +2969,11 @@ pmap_bootstrap4m(void) * Intialize the kernel pmap. */ /* kernel_pmap_store.pm_ctxnum = 0; */ - simple_lock_init(kernel_pmap_store.pm_lock); + simple_lock_init(&kernel_pmap_store.pm_lock); kernel_pmap_store.pm_refcount = 1; - /* Set up pm_regmap for kernel to point NUREG *below* the beginning + + /* + * Set up pm_regmap for kernel to point NUREG *below* the beginning * of kernel regmap storage. Since the kernel only uses regions * above NUREG, we save storage space and can index kernel and * user regions in the same way @@ -3077,85 +2994,87 @@ pmap_bootstrap4m(void) p = end; /* p points to top of kernel mem */ #ifdef DDB if (esym != 0) - theend = p = esym; + p = esym; #endif - /* - * Preserve the monitor ROM's reserved VM region, so that - * we can use L1-A or the monitor's debugger. - */ - - mmu_reservemon4m(&kernel_pmap_store, &p); - pmap_kernel()->pm_ctx = ctxinfo = ci = (union ctxinfo *)p; + /* Allocate context administration */ + pmap_kernel()->pm_ctx = cpuinfo.ctxinfo = ci = (union ctxinfo *)p; p += ncontext * sizeof *ci; - bzero((caddr_t)ctxinfo, (u_int)p - (u_int)ctxinfo); + bzero((caddr_t)ci, (u_int)p - (u_int)ci); +#if 0 ctxbusyvector = p; p += ncontext; bzero(ctxbusyvector, ncontext); ctxbusyvector[0] = 1; /* context 0 is always in use */ +#endif + + + /* + * Set up the `constants' for the call to vm_init() + * in main(). All pages beginning at p (rounded up to + * the next whole page) and continuing through the number + * of available pages are free. + */ + p = (caddr_t)(((u_int)p + NBPG - 1) & ~PGOFSET); + avail_start = (int)p - KERNBASE; + /* + * Grab physical memory list use it to compute `physmem' and + * `avail_end'. The latter is used in conjuction with + * `avail_start' and `avail_next' to dispatch left-over + * physical pages to the VM system. + */ + npmemarr = makememarr(pmemarr, MA_SIZE, MEMARR_AVAILPHYS); + sortm(pmemarr, npmemarr); + if (pmemarr[0].addr != 0) { + printf("pmap_bootstrap: no kernel memory?!\n"); + callrom(); + } + avail_end = pmemarr[npmemarr-1].addr + pmemarr[npmemarr-1].len; + avail_next = avail_start; + for (physmem = 0, mp = pmemarr, j = npmemarr; --j >= 0; mp++) + physmem += btoc(mp->len); /* - * reserve memory for I/O pagetables. This takes 64k of memory + * Reserve memory for MMU pagetables. Some of these have severe + * alignment restrictions. We allocate in a sequence that + * minimizes alignment gaps. + * The amount of physical memory that becomes unavailable for + * general VM use is marked by [unavail_start, unavail_end>. + */ + + /* + * Reserve memory for I/O pagetables. This takes 64k of memory * since we want to have 64M of dvma space (this actually depends - * on the definition of DVMA4M_BASE...we may drop it back to 32M) - * but since the table must be aligned, we might end up using - * as much as 128K. (note 1024 = NBPG / sizeof(iopte_t)) - * - * We optimize with some space saving song and dance to - * squeeze other pagetables in the dead space. + * on the definition of DVMA4M_BASE...we may drop it back to 32M). + * The table must be aligned on a (-DVMA4M_BASE/NBPG) boundary + * (i.e. 64K for 64M of dvma space). */ #ifdef DEBUG if ((0 - DVMA4M_BASE) % (16*1024*1024)) - panic("pmap_bootstrap4m: invalid DVMA4M_BASE of 0x%x",DVMA4M_BASE); -#endif - - deadfill = 0; - p = (caddr_t) roundup((u_int) p, max(SRMMU_L1SIZE * sizeof(long), - max(SRMMU_L2SIZE * sizeof(long), - SRMMU_L3SIZE * sizeof(long)))); - - deadspace = (int) (((caddr_t)roundup((u_int)p, - (0 - DVMA4M_BASE) / 1024)) - p); - - if (deadspace >= SRMMU_L3SIZE * sizeof(long) * NKREG * NSEGRG) { - p = (caddr_t) roundup((u_int)p, SRMMU_L3SIZE * sizeof(long)); - kernel_pagtable_store = (u_int *)p; - p += ((SRMMU_L3SIZE * sizeof(long)) * NKREG) * NSEGRG; - bzero(kernel_pagtable_store, - p - (caddr_t) kernel_pagtable_store); - deadfill |= 4; - deadspace -= (int)(p - (caddr_t) kernel_pagtable_store); - } - if (deadspace >= SRMMU_L2SIZE * sizeof(long) * NKREG) { - p = (caddr_t) roundup((u_int)p, SRMMU_L2SIZE * sizeof(long)); - kernel_segtable_store = (u_int *)p; - p += (SRMMU_L2SIZE * sizeof(long)) * NKREG; - bzero(kernel_segtable_store, - p - (caddr_t) kernel_segtable_store); - deadfill |= 2; - deadspace -= (int)(p - (caddr_t) kernel_segtable_store); - } - if (deadspace >= SRMMU_L1SIZE * sizeof(long)) { - p = (caddr_t) roundup((u_int)p, SRMMU_L1SIZE * sizeof(long)); - kernel_regtable_store = (u_int *)p; - p += SRMMU_L1SIZE * sizeof(long); - bzero(kernel_regtable_store, - p - (caddr_t) kernel_regtable_store); - deadfill |= 1; - deadspace -= (int)(p - (caddr_t) kernel_regtable_store); - } - if (deadspace < 0) - printf("pmap_bootstrap4m: botch in memory-saver\n"); + panic("pmap_bootstrap4m: invalid DVMA4M_BASE of 0x%x", DVMA4M_BASE); +#endif p = (caddr_t) roundup((u_int)p, (0 - DVMA4M_BASE) / 1024); + unavail_start = (int)p - KERNBASE; + kernel_iopte_table = (u_int *)p; kernel_iopte_table_pa = VA2PA((caddr_t)kernel_iopte_table); p += (0 - DVMA4M_BASE) / 1024; bzero(kernel_iopte_table, p - (caddr_t) kernel_iopte_table); + pagetables_start = p; + /* + * Allocate context table. + * To keep supersparc happy, minimum aligment is on a 4K boundary. + */ + ctxtblsize = max(ncontext,1024) * sizeof(int); + cpuinfo.ctx_tbl = (int *)roundup((u_int)p, ctxtblsize); + p = (caddr_t)((u_int)cpuinfo.ctx_tbl + ctxtblsize); + qzero(cpuinfo.ctx_tbl, ctxtblsize); + /* - * reserve memory for segment and page tables needed to map the entire + * Reserve memory for segment and page tables needed to map the entire * kernel (from regions 0xf8 -> 0xff). This takes 130k of space, but * unfortunately is necessary since pmap_enk *must* be able to enter * a kernel mapping without resorting to malloc, or else the @@ -3164,87 +3083,103 @@ pmap_bootstrap4m(void) * pmap_enk4m to enter the new malloc'd page; pmap_enk4m needs to * malloc a page table to enter _that_ mapping; malloc deadlocks since * it is already allocating that object). - * - * We only do this if it wasn't done above... */ - if (!(deadfill & 2)) { - p = (caddr_t) roundup((u_int)p, SRMMU_L2SIZE * sizeof(long)); - kernel_segtable_store = (u_int *)p; - p += (SRMMU_L2SIZE * sizeof(long)) * NKREG; - bzero(kernel_segtable_store, - p - (caddr_t) kernel_segtable_store); - } - if (!(deadfill & 4)) { - p = (caddr_t) roundup((u_int)p, SRMMU_L3SIZE * sizeof(long)); - kernel_pagtable_store = (u_int *)p; - p += ((SRMMU_L3SIZE * sizeof(long)) * NKREG) * NSEGRG; - bzero(kernel_pagtable_store, - p - (caddr_t) kernel_pagtable_store); - } - if (!(deadfill & 1)) { - p = (caddr_t) roundup((u_int)p, SRMMU_L1SIZE * sizeof(long)); - kernel_regtable_store = (u_int *)p; - p += SRMMU_L1SIZE * sizeof(long); - bzero(kernel_regtable_store, - p - (caddr_t) kernel_regtable_store); - } + p = (caddr_t) roundup((u_int)p, SRMMU_L1SIZE * sizeof(long)); + kernel_regtable_store = (u_int *)p; + p += SRMMU_L1SIZE * sizeof(long); + bzero(kernel_regtable_store, + p - (caddr_t) kernel_regtable_store); + + p = (caddr_t) roundup((u_int)p, SRMMU_L2SIZE * sizeof(long)); + kernel_segtable_store = (u_int *)p; + p += (SRMMU_L2SIZE * sizeof(long)) * NKREG; + bzero(kernel_segtable_store, + p - (caddr_t) kernel_segtable_store); + + p = (caddr_t) roundup((u_int)p, SRMMU_L3SIZE * sizeof(long)); + kernel_pagtable_store = (u_int *)p; + p += ((SRMMU_L3SIZE * sizeof(long)) * NKREG) * NSEGRG; + bzero(kernel_pagtable_store, + p - (caddr_t) kernel_pagtable_store); + + /* Round to next page and mark end of stolen pages */ + p = (caddr_t)(((u_int)p + NBPG - 1) & ~PGOFSET); + pagetables_end = p; + unavail_end = (int)p - KERNBASE; -#if 0 - /* At this point, "p" is the highest location of kernel memory that - * we need to lock in/map initially. We now need to calculate the - * size of this kernel image and allocate memory for its page tables, - * which we won't set up until the end of this function. After this - * point, it is NOT POSSIBLE to allocate kernel physical memory - * by bumping up p!!! + /* + * Since we've statically allocated space to map the entire kernel, + * we might as well pre-wire the mappings to save time in pmap_enter. + * This also gets around nasty problems with caching of L1/L2 ptp's. + * + * XXX WHY DO WE HAVE THIS CACHING PROBLEM WITH L1/L2 PTPS????? %%% */ - p = (caddr_t) roundup((u_int)p,SRMMU_L1SIZE * sizeof(long)); - kernsize = (u_int)p - KERNBASE; - /* We keep adding pages until the number of added pages is sufficient - * to hold the map for both the kernel and the new pages. This - * converges since it takes at most about 1152 bytes to map one page. - */ - newpgs = 0; - do { - newpgs++; - nkreg = (kernsize + (newpgs * NBPG) + NBPRG - 1) / NBPRG; - nkseg = (kernsize + (newpgs * NBPG) + NBPSG - 1) / NBPSG; - nkpag = (kernsize + NBPG - 1) / NBPG + newpgs; - } while (((SRMMU_L1SIZE + (nkreg * SRMMU_L2SIZE) + - (nkseg * SRMMU_L3SIZE) + (nkpag)) * sizeof(long)) > - newpgs * NBPG); + pmap_kernel()->pm_reg_ptps = (int *) kernel_regtable_store; + pmap_kernel()->pm_reg_ptps_pa = + VA2PA((caddr_t)pmap_kernel()->pm_reg_ptps); - kernsize += newpgs * NBPG; - p2 = p; /* Page tables go from p2 to p. */ - p += newpgs * NBPG; /* p is now the _real_ top of kernel mem. */ -#endif + /* Install L1 table in context 0 */ + setpgt4m(&cpuinfo.ctx_tbl[0], + (pmap_kernel()->pm_reg_ptps_pa >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD); + + /* XXX:rethink - Store pointer to region table address */ + cpuinfo.L1_ptps = pmap_kernel()->pm_reg_ptps; + + for (reg = VA_VREG(KERNBASE); reg < NKREG+VA_VREG(KERNBASE); reg++) { + struct regmap *rp; + caddr_t kphyssegtbl; + + /* + * Entering new region; install & build segtbl + */ + int kregnum = reg - VA_VREG(KERNBASE); + + rp = &pmap_kernel()->pm_regmap[reg]; + + kphyssegtbl = (caddr_t) + &kernel_segtable_store[kregnum * SRMMU_L2SIZE]; + + setpgt4m(&pmap_kernel()->pm_reg_ptps[reg], + (VA2PA(kphyssegtbl) >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD); + + rp->rg_seg_ptps = (int *)kphyssegtbl; + + if (rp->rg_segmap == NULL) { + printf("rp->rg_segmap == NULL!\n"); + rp->rg_segmap = &kernel_segmap_store[kregnum * NSEGRG]; + } + + for (seg = 0; seg < NSEGRG; seg++) { + struct segmap *sp; + caddr_t kphyspagtbl; + + rp->rg_nsegmap++; + + sp = &rp->rg_segmap[seg]; + kphyspagtbl = (caddr_t) + &kernel_pagtable_store + [((kregnum * NSEGRG) + seg) * SRMMU_L3SIZE]; + + setpgt4m(&rp->rg_seg_ptps[seg], + (VA2PA(kphyspagtbl) >> SRMMU_PPNPASHIFT) | + SRMMU_TEPTD); + sp->sg_pte = (int *) kphyspagtbl; + } + } /* - * Set up the `constants' for the call to vm_init() - * in main(). All pages beginning at p (rounded up to - * the next whole page) and continuing through the number - * of available pages are free, but they start at a higher - * virtual address. This gives us two mappable MD pages - * for pmap_zero_page and pmap_copy_page, and one MI page - * for /dev/mem, all with no associated physical memory. + * Preserve the monitor ROM's reserved VM region, so that + * we can use L1-A or the monitor's debugger. */ - p = (caddr_t)(((u_int)p + NBPG - 1) & ~PGOFSET); - avail_start = (int)p - KERNBASE; + mmu_reservemon4m(&kernel_pmap_store); + /* - * Grab physical memory list, so pmap_next_page() can do its bit. + * Reserve virtual address space for two mappable MD pages + * for pmap_zero_page and pmap_copy_page, one MI page + * for /dev/mem, and some more for dumpsys(). */ - npmemarr = makememarr(pmemarr, MA_SIZE, MEMARR_AVAILPHYS); - sortm(pmemarr, npmemarr); - if (pmemarr[0].addr != 0) { - printf("pmap_bootstrap: no kernel memory?!\n"); - callrom(); - } - avail_end = pmemarr[npmemarr-1].addr + pmemarr[npmemarr-1].len; - avail_next = avail_start; - for (physmem = 0, mp = pmemarr, j = npmemarr; --j >= 0; mp++) - physmem += btoc(mp->len); - - i = (int)p; + q = p; vpage[0] = p, p += NBPG; vpage[1] = p, p += NBPG; vmmap = p, p += NBPG; @@ -3260,9 +3195,10 @@ pmap_bootstrap4m(void) virtual_avail = (vm_offset_t)p; virtual_end = VM_MAX_KERNEL_ADDRESS; - p = (caddr_t)i; /* retract to first free phys */ + p = q; /* retract to first free phys */ - /* Set up the ctxinfo structures (freelist of contexts) + /* + * Set up the ctxinfo structures (freelist of contexts) */ ci->c_pmap = pmap_kernel(); ctx_freelist = ci + 1; @@ -3274,148 +3210,49 @@ pmap_bootstrap4m(void) ctx_kick = 0; ctx_kickdir = -1; - /* Now map the kernel into our new set of page tables, then + /* + * Now map the kernel into our new set of page tables, then * (finally) switch over to our running page tables. * We map from KERNBASE to p into context 0's page tables (and * the kernel pmap). */ #ifdef DEBUG /* Sanity checks */ if ((u_int)p % NBPG != 0) - panic("pmap_bootstrap4m: p misaligned?!?"); + panic("pmap_bootstrap4m: p misaligned?!?"); if (KERNBASE % NBPRG != 0) - panic("pmap_bootstrap4m: KERNBASE not region-aligned"); + panic("pmap_bootstrap4m: KERNBASE not region-aligned"); #endif - if (pmap_kernel()->pm_reg_ptps == NULL) { -#ifdef DEBUG - printf("pmap_bootstrap4m: no kernel regiontable; creating.\n"); -#endif - pmap_kernel()->pm_reg_ptps = (int *) kernel_regtable_store; - pmap_kernel()->pm_reg_ptps_pa = - VA2PA((caddr_t)pmap_kernel()->pm_reg_ptps); - p2 = (caddr_t) pmap_kernel()->pm_reg_ptps + - (SRMMU_L1SIZE * sizeof(int)); - bzero(pmap_kernel()->pm_reg_ptps, SRMMU_L1SIZE * sizeof(long)); - } - reg = -1; - seg = -1; + for (q = (caddr_t) KERNBASE; q < p; q += NBPG) { - if ((VA_VSEG(q) % NSEGRG == 0) && VA_VREG(q) != reg) { - /* entering new region; install & build segtbl - * XXX: WE TRASH ANY EXISTING MAPPINGS IN THE KERNEL - * REGION. SHOULD BE FIXED! - */ - reg = VA_VREG(q); - rmapp = &(pmap_kernel()->pm_regmap[reg]); - kphyssegtbl = (caddr_t) - &kernel_segtable_store[(reg - VA_VREG(KERNBASE)) * - SRMMU_L2SIZE]; - bzero(kphyssegtbl, SRMMU_L2SIZE * sizeof(long)); - - ((int *)pmap_kernel()->pm_reg_ptps)[VA_VREG(q)] = - (VA2PA(kphyssegtbl) >> SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; - - rmapp->rg_seg_ptps = (int *)kphyssegtbl; - - if (rmapp->rg_segmap == NULL) - rmapp->rg_segmap = &kernel_segmap_store[(reg - - VA_VREG(KERNBASE)) * NSEGRG]; - } - if (((VA_VPG(q) % NPTESG) == 0) && VA_VSEG(q) != seg) { - rmapp->rg_nsegmap++; - /* Entering new segment. XXX: trashes existing maps */ - seg = VA_VSEG(q); - smapp = &(rmapp->rg_segmap[seg]); - kphyspagtbl = (caddr_t) - &kernel_pagtable_store[(((reg-VA_VREG(KERNBASE))* - NSEGRG) + seg)*SRMMU_L3SIZE]; - bzero(kphyspagtbl, SRMMU_L3SIZE * sizeof(long)); - - rmapp->rg_seg_ptps[VA_VSEG(q)] = - (VA2PA(kphyspagtbl) >> SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; - smapp->sg_pte = (int *) kphyspagtbl; - } - /* Now install entry for current page. Cache and write-protect - * kernel text. - */ - smapp->sg_npte++; - if (q == (caddr_t) KERNBASE) { - /* Must map in message buffer in low page. */ - ((int *)kphyspagtbl)[VA_VPG(q)] = PPROT_N_RWX | - SRMMU_PG_C | SRMMU_TEPTE; + struct regmap *rp; + struct segmap *sp; + int pte; + + if ((int)q >= KERNBASE + avail_start && + (int)q < KERNBASE + unavail_start) + /* This gap is part of VM-managed pages */ continue; - } - else if (q < (caddr_t) (KERNBASE+0x4000)) { - /* Special case: retain interrupt register mapping */ - ((int *)kphyspagtbl)[VA_VPG(q)] = - getpte4m((vm_offset_t)q); - } - if (q >= (caddr_t) trapbase && q < etext) - ((int *)kphyspagtbl)[VA_VPG(q)] = - (VA2PA(q) >> SRMMU_PPNPASHIFT) | - PPROT_N_RX | SRMMU_PG_C | SRMMU_TEPTE; - else - ((int *)kphyspagtbl)[VA_VPG(q)] = - (VA2PA(q) >> SRMMU_PPNPASHIFT) | - PPROT_N_RWX | SRMMU_PG_C | SRMMU_TEPTE; - } - /* - * We must also create a segment table for region 0xfe and any - * needed page tables necessary to map the special (important) - * devices that get mapped at the beginning of this I/O segment. - * This is necessary since we have to map the interrupt registers - * at the start of region 0xfe in bootstrap(). - * - * Since we've statically allocated space to map the entire kernel, - * we might as well pre-wire the mappings to save time in pmap_enter. - * This also gets around nasty problems with caching of L1/L2 ptp's. - * - * XXX WHY DO WE HAVE THIS CACHING PROBLEM WITH L1/L2 PTPS????? %%% - */ - for (reg = VA_VREG(KERNBASE); reg < NKREG+VA_VREG(KERNBASE); reg++) { - rmapp = &(pmap_kernel()->pm_regmap[reg]); - - if (((int *)pmap_kernel()->pm_reg_ptps)[reg] == NULL) { - kphyssegtbl = (caddr_t) - &kernel_segtable_store[(reg - VA_VREG(KERNBASE)) * - SRMMU_L2SIZE]; - bzero(kphyssegtbl, SRMMU_L2SIZE * sizeof(long)); - ((int *)pmap_kernel()->pm_reg_ptps)[reg] = - (VA2PA(kphyssegtbl) >> SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; - - rmapp->rg_seg_ptps = (int *)kphyssegtbl; - - if (rmapp->rg_segmap == NULL) - rmapp->rg_segmap = &kernel_segmap_store - [(reg - VA_VREG(KERNBASE)) * NSEGRG]; - } - for (seg = 0; seg < NSEGRG; seg++) { - if (rmapp->rg_seg_ptps[seg] == NULL) { - rmapp->rg_nsegmap++; - - smapp = &(rmapp->rg_segmap[seg]); - kphyspagtbl = (caddr_t) - &kernel_pagtable_store[(((reg- - VA_VREG(KERNBASE))* - NSEGRG) + seg)* - SRMMU_L3SIZE]; - bzero(kphyspagtbl, - SRMMU_L3SIZE * sizeof(long)); - - rmapp->rg_seg_ptps[seg] = - (VA2PA(kphyspagtbl) >> SRMMU_PPNPASHIFT) | - SRMMU_TEPTD; - smapp->sg_pte = (int *) kphyspagtbl; - } - } + /* + * Now install entry for current page. + */ + rp = &pmap_kernel()->pm_regmap[VA_VREG(q)]; + sp = &rp->rg_segmap[VA_VSEG(q)]; + sp->sg_npte++; + + pte = ((int)q - KERNBASE) >> SRMMU_PPNPASHIFT; + pte |= PPROT_N_RX | SRMMU_PG_C | SRMMU_TEPTE; + /* write-protect kernel text */ + if (q < (caddr_t) trapbase || q >= etext) + pte |= PPROT_WRITE; + + setpgt4m(&sp->sg_pte[VA_VPG(q)], pte); } +#if 0 /* * We also install the kernel mapping into all other contexts by - * copying the context 0 L1 PTP from ctx_phys_tbl[0] into the + * copying the context 0 L1 PTP from cpuinfo.ctx_tbl[0] into the * remainder of the context table (i.e. we share the kernel page- * tables). Each user pmap automatically gets the kernel mapped * into it when it is created, but we do this extra step early on @@ -3423,98 +3260,110 @@ pmap_bootstrap4m(void) * pmap associated with it. */ for (i = 1; i < ncontext; i++) - ctx_phys_tbl[i] = ctx_phys_tbl[0]; + cpuinfo.ctx_tbl[i] = cpuinfo.ctx_tbl[0]; +#endif /* * Now switch to kernel pagetables (finally!) */ + mmu_install_tables(&cpuinfo); + + /* Mark all MMU tables uncacheable, if required */ + if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) + kvm_uncache(pagetables_start, + (pagetables_end - pagetables_start) >> PGSHIFT); + +} + +void +mmu_install_tables(sc) + struct cpu_softc *sc; +{ + #ifdef DEBUG printf("pmap_bootstrap: installing kernel page tables..."); #endif - setcontext(0); /* paranoia? %%%: Make 0x3 a define! below */ + setcontext4m(0); /* paranoia? %%%: Make 0x3 a define! below */ /* Enable MMU tablewalk caching, flush TLB */ - - i = lda(SRMMU_PCR, ASI_SRMMU); - switch(mmumod) { -/* case SUN4M_MMU_MS: */ /* These have the same model # as SS */ - case SUN4M_MMU_SS: - if ((cpumod & 0xf0) == (SUN4M_SS & 0xf0)) - sta(SRMMU_PCR, ASI_SRMMU, (i | SRMMU_PCR_TC)); - else /* microsparc */ - printf("(if this doesn't work, " - "fix pmap_bootstrap4m in pmap.c)"); - break; - case SUN4M_MMU_HS: - printf("(if this doesn't work, fix pmap_bootstrap4m in pmap.c)"); - sta(SRMMU_PCR, ASI_SRMMU, (i | SRMMU_PCR_C) & ~SRMMU_PCR_CE); - /* above: CHECKFIX %%% below: add microsparc*/ - break; - case SUN4M_MMU_MS1: - printf("(if this doesn't work, fix pmap_bootstrap4m in pmap.c)"); - break; - default: - panic("Unimplemented MMU architecture %d",mmumod); - } + if (sc->mmu_enable != 0) + sc->mmu_enable(); tlb_flush_all(); sta(SRMMU_CXTPTR, ASI_SRMMU, - (VA2PA((caddr_t)ctx_phys_tbl) >> SRMMU_PPNPASHIFT) & ~0x3); + (VA2PA((caddr_t)sc->ctx_tbl) >> SRMMU_PPNPASHIFT) & ~0x3); tlb_flush_all(); #ifdef DEBUG printf("done.\n"); #endif +} + +/* + * Allocate per-CPU page tables. + * Note: this routine is called in the context of the boot CPU + * during autoconfig. + */ +void +pmap_alloc_cpu(sc) + struct cpu_softc *sc; +{ + caddr_t cpustore; + int *ctxtable; + int *regtable; + int *segtable; + int *pagtable; + int vr, vs, vpg; + struct regmap *rp; + struct segmap *sp; + + /* Allocate properly aligned and physically contiguous memory here */ + cpustore = 0; + ctxtable = 0; + regtable = 0; + segtable = 0; + pagtable = 0; + + vr = VA_VREG(CPUINFO_VA); + vs = VA_VSEG(CPUINFO_VA); + vpg = VA_VPG(CPUINFO_VA); + rp = &pmap_kernel()->pm_regmap[vr]; + sp = &rp->rg_segmap[vs]; /* - * On SuperSPARC machines without a MXCC, we *cannot* cache the - * page tables. - * XXX: this needs to be cleaned up with the cpu_softc stuff... + * Copy page tables, then modify entry for CPUINFO_VA so that + * it points at the per-CPU pages. */ - if (mmumod == SUN4M_MMU_SS && - (lda(SRMMU_PCR, ASI_SRMMU) & SRMMU_PCR_MB)) { + bcopy(cpuinfo.L1_ptps, regtable, SRMMU_L1SIZE * sizeof(int)); + regtable[vr] = + (VA2PA((caddr_t)segtable) >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD; - int bytes, numpages; - cant_cache_pagetables = 1; + bcopy(rp->rg_seg_ptps, segtable, SRMMU_L2SIZE * sizeof(int)); + segtable[vs] = + (VA2PA((caddr_t)pagtable) >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD; -#define DO_THE_MATH(math) \ - bytes = (math); \ - numpages = (bytes >> PGSHIFT) + (bytes % NBPG ? 1 : 0); + bcopy(sp->sg_pte, pagtable, SRMMU_L3SIZE * sizeof(int)); + pagtable[vpg] = + (VA2PA((caddr_t)cpustore) >> SRMMU_PPNPASHIFT) | + (SRMMU_TEPTE | PPROT_RWX_RWX | SRMMU_PG_C); - DO_THE_MATH(SRMMU_L3SIZE * sizeof(long) * NKREG * NSEGRG); -#ifdef DEBUG - printf("pmap_bootstrap4m: uncaching %d PT pages at 0x%lx\n", - numpages, (long)kernel_pagtable_store); -#endif - kvm_uncache((caddr_t)kernel_pagtable_store, numpages); - - DO_THE_MATH(SRMMU_L2SIZE * sizeof(long) * NKREG); -#ifdef DEBUG - printf("pmap_bootstrap4m: uncaching %d ST pages at 0x%lx\n", - numpages, (long)kernel_segtable_store); -#endif - kvm_uncache((caddr_t)kernel_segtable_store, numpages); + /* Install L1 table in context 0 */ + ctxtable[0] = ((u_int)regtable >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD; - DO_THE_MATH(SRMMU_L1SIZE * sizeof(long)); -#ifdef DEBUG - printf("pmap_bootstrap4m: uncaching %d RT pages at 0x%lx\n", - numpages, (long)kernel_regtable_store); -#endif - kvm_uncache((caddr_t)kernel_regtable_store, numpages); + sc->ctx_tbl = ctxtable; + sc->L1_ptps = regtable; -#undef DO_THE_MATH +#if 0 + if ((sc->flags & CPUFLG_CACHEPAGETABLES) == 0) { + kvm_uncache((caddr_t)0, 1); } - -#ifdef DEBUG - printf("\n"); /* Might as well make it pretty... */ #endif - - /* All done! */ } #endif /* defined sun4m */ + void pmap_init() { @@ -3560,16 +3409,10 @@ pass2: sva = trunc_page(va); if (sva < eva) { -#if defined(DEBUG) && !defined(SUN4M) - /* - * crowded chunks are normal on SS20s; don't clutter - * screen with messages - */ - printf("note: crowded chunk at 0x%x\n", mp->addr); -#endif + /* This chunk overlaps the previous in pv_table[] */ sva += PAGE_SIZE; if (sva < eva) - panic("pmap_init: sva(%lx) < eva(%lx)", + panic("pmap_init: sva(0x%lx) < eva(0x%lx)", sva, eva); } eva = round_page(va + len); @@ -3667,29 +3510,35 @@ pmap_pinit(pm) if (CPU_ISSUN4OR4C) { TAILQ_INIT(&pm->pm_seglist); -#ifdef MMU_3L +#if defined(SUN4_MMU3L) TAILQ_INIT(&pm->pm_reglist); - if (mmu_3l) - for (i = NUREG; --i >= 0;) - pm->pm_regmap[i].rg_smeg = reginval; + if (HASSUN4_MMU3L) { + int i; + for (i = NUREG; --i >= 0;) + pm->pm_regmap[i].rg_smeg = reginval; + } #endif } #if defined(SUN4M) else { + int i; + /* * We must allocate and initialize hardware-readable (MMU) * pagetables. We must also map the kernel regions into this * pmap's pagetables, so that we can access the kernel from - * user mode! + * this user context. * * Note: pm->pm_regmap's have been zeroed already, so we don't * need to explicitly mark them as invalid (a null * rg_seg_ptps pointer indicates invalid for the 4m) */ urp = malloc(SRMMU_L1SIZE * sizeof(int), M_VMPMAP, M_WAITOK); - if (cant_cache_pagetables) +#if 0 + if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) kvm_uncache(urp, ((SRMMU_L1SIZE*sizeof(int))+NBPG-1)/NBPG); +#endif #ifdef DEBUG if ((u_int) urp % (SRMMU_L1SIZE * sizeof(int))) @@ -3697,8 +3546,14 @@ pmap_pinit(pm) #endif pm->pm_reg_ptps = urp; pm->pm_reg_ptps_pa = VA2PA(urp); - qzero(urp, SRMMU_L1SIZE * sizeof(int)); + for (i = 0; i < NUREG; i++) + setpgt4m(&pm->pm_reg_ptps[i], SRMMU_TEINVALID); + /* Copy kernel regions */ + for (i = 0; i < NKREG; i++) { + setpgt4m(&pm->pm_reg_ptps[VA_VREG(KERNBASE) + i], + cpuinfo.L1_ptps[VA_VREG(KERNBASE) + i]); + } } #endif @@ -3749,7 +3604,7 @@ pmap_release(pm) #endif if (CPU_ISSUN4OR4C) { -#ifdef MMU_3L +#if defined(SUN4_MMU3L) if (pm->pm_reglist.tqh_first) panic("pmap_release: region list not empty"); #endif @@ -3840,7 +3695,7 @@ pmap_remove(pm, va, endva) #ifdef DEBUG if (pmapdebug & PDB_REMOVE) - printf("pmap_remove(%p, %lx, %lx)\n", pm, va, endva); + printf("pmap_remove(%p, 0x%lx, 0x%lx)\n", pm, va, endva); #endif if (pm == pmap_kernel()) { @@ -3866,7 +3721,8 @@ pmap_remove(pm, va, endva) nva = VSTOVA(vr, vs + 1); if (nva == 0 || nva > endva) nva = endva; - (*rm)(pm, va, nva, vr, vs); + if (pm->pm_regmap[vr].rg_nsegmap != 0) + (*rm)(pm, va, nva, vr, vs); } simple_unlock(&pm->pm_lock); splx(s); @@ -3932,17 +3788,16 @@ pmap_rmk4_4c(pm, va, endva, vr, vs) panic("pmap_rmk: lost context"); #endif - setcontext(0); + setcontext4(0); /* decide how to flush cache */ npg = (endva - va) >> PGSHIFT; if (npg > PMAP_RMK_MAGIC) { /* flush the whole segment */ perpage = 0; - if (vactype != VAC_NONE) - cache_flush_segment(vr, vs); + cache_flush_segment(vr, vs); } else { /* flush each page individually; some never need flushing */ - perpage = (vactype != VAC_NONE); + perpage = (CACHEINFO.c_vactype != VAC_NONE); } while (va < endva) { tpte = getpte4(va); @@ -3972,21 +3827,21 @@ pmap_rmk4_4c(pm, va, endva, vr, vs) */ if ((sp->sg_npte = nleft) == 0) { va = VSTOVA(vr,vs); /* retract */ -#ifdef MMU_3L - if (mmu_3l) +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L) setsegmap(va, seginval); else #endif for (i = ncontext; --i >= 0;) { - setcontext(i); + setcontext4(i); setsegmap(va, seginval); } me_free(pm, pmeg); if (--rp->rg_nsegmap == 0) { -#ifdef MMU_3L - if (mmu_3l) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L) { for (i = ncontext; --i >= 0;) { - setcontext(i); + setcontext4(i); setregmap(va, reginval); } /* note: context is 0 */ @@ -4034,28 +3889,34 @@ pmap_rmk4m(pm, va, endva, vr, vs) panic("pmap_rmk: lost context"); #endif - setcontext(0); + setcontext4m(0); /* decide how to flush cache */ npg = (endva - va) >> PGSHIFT; if (npg > PMAP_RMK_MAGIC) { /* flush the whole segment */ perpage = 0; - if (vactype != VAC_NONE) + if (CACHEINFO.c_vactype != VAC_NONE) cache_flush_segment(vr, vs); } else { /* flush each page individually; some never need flushing */ - perpage = (vactype != VAC_NONE); + perpage = (CACHEINFO.c_vactype != VAC_NONE); } while (va < endva) { - tpte = getpte4m(va); + tpte = sp->sg_pte[VA_SUN4M_VPG(va)]; if ((tpte & SRMMU_TETYPE) != SRMMU_TEPTE) { +#ifdef DEBUG + if ((pmapdebug & PDB_SANITYCHK) && + (getpte4m(va) & SRMMU_TETYPE) == SRMMU_TEPTE) + panic("pmap_rmk: Spurious kTLB entry for 0x%lx", + va); +#endif va += NBPG; continue; } if ((tpte & SRMMU_PGTYPE) == PG_SUN4M_OBMEM) { /* if cacheable, flush page as needed */ if (perpage && (tpte & SRMMU_PG_C)) - cache_flush_page(va); + cache_flush_page(va); i = ptoa((tpte & SRMMU_PPNMASK) >> SRMMU_PPNSHIFT); if (managed(i)) { pv = pvhead(i); @@ -4064,7 +3925,8 @@ pmap_rmk4m(pm, va, endva, vr, vs) } } nleft--; - setpte4m(va, SRMMU_TEINVALID); + tlb_flush_page(va); + setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], SRMMU_TEINVALID); va += NBPG; } @@ -4163,13 +4025,13 @@ pmap_rmu4_4c(pm, va, endva, vr, vs) if (--rp->rg_nsegmap == 0) { free(rp->rg_segmap, M_VMPMAP); rp->rg_segmap = NULL; -#ifdef MMU_3L - if (mmu_3l && rp->rg_smeg != reginval) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L && rp->rg_smeg != reginval) { if (pm->pm_ctx) { - setcontext(pm->pm_ctxnum); + setcontext4(pm->pm_ctxnum); setregmap(va, reginval); } else - setcontext(0); + setcontext4(0); region_free(pm, rp->rg_smeg); } #endif @@ -4185,21 +4047,18 @@ pmap_rmu4_4c(pm, va, endva, vr, vs) if (CTX_USABLE(pm,rp)) { /* process has a context, must flush cache */ npg = (endva - va) >> PGSHIFT; - setcontext(pm->pm_ctxnum); + setcontext4(pm->pm_ctxnum); if (npg > PMAP_RMU_MAGIC) { perpage = 0; /* flush the whole segment */ - if (vactype != VAC_NONE) - cache_flush_segment(vr, vs); + cache_flush_segment(vr, vs); } else - perpage = (vactype != VAC_NONE); + perpage = (CACHEINFO.c_vactype != VAC_NONE); pteva = va; } else { /* no context, use context 0; cache flush unnecessary */ - setcontext(0); -#ifdef MMU_3L - if (mmu_3l) + setcontext4(0); + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif /* XXX use per-cpu pteva? */ setsegmap(0, pmeg); pteva = VA_VPG(va) << PGSHIFT; @@ -4222,10 +4081,7 @@ pmap_rmu4_4c(pm, va, endva, vr, vs) } nleft--; setpte4(pteva, 0); -#define PMAP_PTESYNC -#ifdef PMAP_PTESYNC pte0[VA_VPG(pteva)] = 0; -#endif } /* @@ -4241,13 +4097,11 @@ if (pm->pm_ctx == NULL) { va = VSTOVA(vr,vs); /* retract */ if (CTX_USABLE(pm,rp)) setsegmap(va, seginval); -#ifdef MMU_3L - else if (mmu_3l && rp->rg_smeg != reginval) { + else if (HASSUN4_MMU3L && rp->rg_smeg != reginval) { /* note: context already set earlier */ setregmap(0, rp->rg_smeg); setsegmap(vs << SGSHIFT, seginval); } -#endif free(pte0, M_VMPMAP); sp->sg_pte = NULL; me_free(pm, pmeg); @@ -4257,8 +4111,8 @@ if (pm->pm_ctx == NULL) { rp->rg_segmap = NULL; GAP_WIDEN(pm,vr); -#ifdef MMU_3L - if (mmu_3l && rp->rg_smeg != reginval) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L && rp->rg_smeg != reginval) { /* note: context already set */ if (pm->pm_ctx) setregmap(va, reginval); @@ -4280,7 +4134,7 @@ pmap_rmu4m(pm, va, endva, vr, vs) register vm_offset_t va, endva; register int vr, vs; { - register int *pte0, i, tpte, perpage, npg; + register int *pte0, i, perpage, npg; register struct pvlist *pv; register int nleft; struct regmap *rp; @@ -4295,6 +4149,7 @@ pmap_rmu4m(pm, va, endva, vr, vs) sp = &rp->rg_segmap[vs]; if ((nleft = sp->sg_npte) == 0) return; + if (sp->sg_pte == NULL) panic("pmap_rmu: no pages"); @@ -4303,10 +4158,10 @@ pmap_rmu4m(pm, va, endva, vr, vs) /* * Invalidate PTE in MMU pagetables. Flush cache if necessary. */ - if (CTX_USABLE(pm,rp)) { + if (pm->pm_ctx) { /* process has a context, must flush cache */ - setcontext(pm->pm_ctxnum); - if (vactype != VAC_NONE) { + setcontext4m(pm->pm_ctxnum); + if (CACHEINFO.c_vactype != VAC_NONE) { npg = (endva - va) >> PGSHIFT; if (npg > PMAP_RMU_MAGIC) { perpage = 0; /* flush the whole segment */ @@ -4320,16 +4175,20 @@ pmap_rmu4m(pm, va, endva, vr, vs) perpage = 0; } for (; va < endva; va += NBPG) { - /* Note: we use sw pagetables here since pages have been - * flushed already. This avoids over-zealous cache flushing. - */ - if (CTX_USABLE(pm,rp)) { /* %%% XXX: Performance hit? */ - tpte = getpte4m(va); /* should we just flush seg? */ - tlb_flush_page(va); - } else - tpte = getptesw4m(pm, va); - if ((tpte & SRMMU_TETYPE) != SRMMU_TEPTE) + + int tpte = pte0[VA_SUN4M_VPG(va)]; + + if ((tpte & SRMMU_TETYPE) != SRMMU_TEPTE) { +#ifdef DEBUG + if ((pmapdebug & PDB_SANITYCHK) && + pm->pm_ctx && + (getpte4m(va) & SRMMU_TEPTE) == SRMMU_TEPTE) + panic("pmap_rmu: Spurious uTLB entry for 0x%lx", + va); +#endif continue; + } + if ((tpte & SRMMU_PGTYPE) == PG_SUN4M_OBMEM) { /* if cacheable, flush page as needed */ if (perpage && (tpte & SRMMU_PG_C)) @@ -4342,14 +4201,16 @@ pmap_rmu4m(pm, va, endva, vr, vs) } } nleft--; - setptesw4m(pm, va, SRMMU_TEINVALID); /* Update pagetables */ + if (pm->pm_ctx) + tlb_flush_page(va); + setpgt4m(&pte0[VA_SUN4M_VPG(va)], SRMMU_TEINVALID); } /* * If the segment is all gone, and the context is loaded, give * the segment back. */ - if ((sp->sg_npte = nleft) == 0 /* ??? && pm->pm_ctx != NULL*/) { + if ((sp->sg_npte = nleft) == 0) { #ifdef DEBUG if (pm->pm_ctx == NULL) { printf("pmap_rmu: no context here..."); @@ -4357,17 +4218,19 @@ pmap_rmu4m(pm, va, endva, vr, vs) #endif va = VSTOVA(vr,vs); /* retract */ - tlb_flush_segment(vr, vs); /* Paranoia? */ - rp->rg_seg_ptps[vs] = SRMMU_TEINVALID; + if (pm->pm_ctx) + tlb_flush_segment(vr, vs); /* Paranoia? */ + setpgt4m(&rp->rg_seg_ptps[vs], SRMMU_TEINVALID); free(pte0, M_VMPMAP); sp->sg_pte = NULL; if (--rp->rg_nsegmap == 0) { + if (pm->pm_ctx) + tlb_flush_context(); /* Paranoia? */ + setpgt4m(&pm->pm_reg_ptps[vr], SRMMU_TEINVALID); free(rp->rg_segmap, M_VMPMAP); rp->rg_segmap = NULL; free(rp->rg_seg_ptps, M_VMPMAP); - pm->pm_reg_ptps[vr] = SRMMU_TEINVALID; - GAP_WIDEN(pm,vr); } } } @@ -4390,24 +4253,23 @@ pmap_page_protect4_4c(pa, prot) { register struct pvlist *pv, *pv0, *npv; register struct pmap *pm; - register vm_offset_t va; - register int vr, vs, pteva, tpte; + register int va, vr, vs, pteva, tpte; register int flags, nleft, i, s, ctx; struct regmap *rp; struct segmap *sp; #ifdef DEBUG if (!pmap_pa_exists(pa)) - panic("pmap_page_protect: no such address: %lx", pa); + panic("pmap_page_protect: no such address: 0x%lx", pa); if ((pmapdebug & PDB_CHANGEPROT) || (pmapdebug & PDB_REMOVE && prot == VM_PROT_NONE)) - printf("pmap_page_protect(%lx, %x)\n", pa, prot); + printf("pmap_page_protect(0x%lx, 0x%x)\n", pa, prot); #endif /* * Skip unmanaged pages, or operations that do not take * away write permission. */ - if ((pa & (PMAP_TNC & ~PMAP_NC)) || + if ((pa & (PMAP_TNC_4 & ~PMAP_NC)) || !managed(pa) || prot & VM_PROT_WRITE) return; write_user_windows(); /* paranoia */ @@ -4428,7 +4290,7 @@ pmap_page_protect4_4c(pa, prot) splx(s); return; } - ctx = getcontext(); + ctx = getcontext4(); pv0 = pv; flags = pv->pv_flags & ~PV_NC; for (;; pm = pv->pv_pmap) { @@ -4455,13 +4317,13 @@ pmap_page_protect4_4c(pa, prot) free(rp->rg_segmap, M_VMPMAP); rp->rg_segmap = NULL; GAP_WIDEN(pm,vr); -#ifdef MMU_3L - if (mmu_3l && rp->rg_smeg != reginval) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L && rp->rg_smeg != reginval) { if (pm->pm_ctx) { - setcontext(pm->pm_ctxnum); + setcontext4(pm->pm_ctxnum); setregmap(va, reginval); } else - setcontext(0); + setcontext4(0); region_free(pm, rp->rg_smeg); } #endif @@ -4469,94 +4331,96 @@ pmap_page_protect4_4c(pa, prot) } goto nextpv; } + if (CTX_USABLE(pm,rp)) { - setcontext(pm->pm_ctxnum); + setcontext4(pm->pm_ctxnum); pteva = va; - if (vactype != VAC_NONE) - cache_flush_page(va); + cache_flush_page(va); } else { - setcontext(0); + setcontext4(0); /* XXX use per-cpu pteva? */ -#ifdef MMU_3L - if (mmu_3l) + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, sp->sg_pmeg); pteva = VA_VPG(va) << PGSHIFT; } tpte = getpte4(pteva); if ((tpte & PG_V) == 0) - panic("pmap_page_protect !PG_V"); + panic("pmap_page_protect !PG_V: ctx %d, va 0x%x, pte 0x%x", + pm->pm_ctxnum, va, tpte); flags |= MR4_4C(tpte); if (nleft) { setpte4(pteva, 0); -#ifdef PMAP_PTESYNC if (sp->sg_pte != NULL) sp->sg_pte[VA_VPG(pteva)] = 0; + goto nextpv; + } + + /* Entire segment is gone */ + if (pm == pmap_kernel()) { +#if defined(SUN4_MMU3L) + if (!HASSUN4_MMU3L) #endif - } else { - if (pm == pmap_kernel()) { -#ifdef MMU_3L - if (!mmu_3l) -#endif + for (i = ncontext; --i >= 0;) { + setcontext4(i); + setsegmap(va, seginval); + } + me_free(pm, sp->sg_pmeg); + if (--rp->rg_nsegmap == 0) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L) { for (i = ncontext; --i >= 0;) { - setcontext(i); - setsegmap(va, seginval); - } - me_free(pm, sp->sg_pmeg); - if (--rp->rg_nsegmap == 0) { -#ifdef MMU_3L - if (mmu_3l) { - for (i = ncontext; --i >= 0;) { - setcontext(i); - setregmap(va, reginval); - } - region_free(pm, rp->rg_smeg); + setcontext4(i); + setregmap(va, reginval); } -#endif - } - } else { - if (CTX_USABLE(pm,rp)) - /* `pteva'; we might be using tregion */ - setsegmap(pteva, seginval); -#ifdef MMU_3L - else if (mmu_3l && rp->rg_smeg != reginval) { - /* note: context already set earlier */ - setregmap(0, rp->rg_smeg); - setsegmap(vs << SGSHIFT, seginval); + region_free(pm, rp->rg_smeg); } #endif - free(sp->sg_pte, M_VMPMAP); - sp->sg_pte = NULL; - me_free(pm, sp->sg_pmeg); - - if (--rp->rg_nsegmap == 0) { -#ifdef MMU_3L - if (mmu_3l && rp->rg_smeg != reginval) { - if (pm->pm_ctx) - setregmap(va, reginval); - region_free(pm, rp->rg_smeg); - } + } + } else { + if (CTX_USABLE(pm,rp)) + /* `pteva'; we might be using tregion */ + setsegmap(pteva, seginval); +#if defined(SUN4_MMU3L) + else if (HASSUN4_MMU3L && + rp->rg_smeg != reginval) { + /* note: context already set earlier */ + setregmap(0, rp->rg_smeg); + setsegmap(vs << SGSHIFT, seginval); + } #endif - free(rp->rg_segmap, M_VMPMAP); - rp->rg_segmap = NULL; - GAP_WIDEN(pm,vr); + free(sp->sg_pte, M_VMPMAP); + sp->sg_pte = NULL; + me_free(pm, sp->sg_pmeg); + + if (--rp->rg_nsegmap == 0) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L && + rp->rg_smeg != reginval) { + if (pm->pm_ctx) + setregmap(va, reginval); + region_free(pm, rp->rg_smeg); } +#endif + free(rp->rg_segmap, M_VMPMAP); + rp->rg_segmap = NULL; + GAP_WIDEN(pm,vr); } } + nextpv: npv = pv->pv_next; if (pv != pv0) - free(pv, M_VMPVENT); + FREE(pv, M_VMPVENT); if ((pv = npv) == NULL) break; } pv0->pv_pmap = NULL; pv0->pv_next = NULL; /* ? */ pv0->pv_flags = flags; - setcontext(ctx); + setcontext4(ctx); splx(s); } @@ -4575,8 +4439,7 @@ pmap_protect4_4c(pm, sva, eva, prot) vm_offset_t sva, eva; vm_prot_t prot; { - register vm_offset_t va, nva; - register int vr, vs; + register int va, nva, vr, vs; register int s, ctx; struct regmap *rp; struct segmap *sp; @@ -4590,7 +4453,7 @@ pmap_protect4_4c(pm, sva, eva, prot) } write_user_windows(); - ctx = getcontext(); + ctx = getcontext4(); s = splpmap(); simple_lock(&pm->pm_lock); @@ -4635,15 +4498,14 @@ if (nva == 0) panic("pmap_protect: last segment"); /* cannot happen */ * tags are updated. This is really only * needed for PTEs that lose PG_W. */ - setcontext(pm->pm_ctxnum); + setcontext4(pm->pm_ctxnum); for (; va < nva; va += NBPG) { tpte = getpte4(va); pmap_stats.ps_npg_prot_all++; if ((tpte & (PG_W|PG_TYPE)) == (PG_W|PG_OBMEM)) { pmap_stats.ps_npg_prot_actual++; - if (vactype != VAC_NONE) - cache_flush_page(va); + cache_flush_page(va); setpte4(va, tpte & ~PG_W); } } @@ -4654,12 +4516,10 @@ if (nva == 0) panic("pmap_protect: last segment"); /* cannot happen */ * No context, hence not cached; * just update PTEs. */ - setcontext(0); + setcontext4(0); /* XXX use per-cpu pteva? */ -#ifdef MMU_3L - if (mmu_3l) + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, sp->sg_pmeg); pteva = VA_VPG(va) << PGSHIFT; for (; va < nva; pteva += NBPG, va += NBPG) @@ -4669,7 +4529,7 @@ if (nva == 0) panic("pmap_protect: last segment"); /* cannot happen */ } simple_unlock(&pm->pm_lock); splx(s); - setcontext(ctx); + setcontext4(ctx); } /* @@ -4690,7 +4550,7 @@ pmap_changeprot4_4c(pm, va, prot, wired) #ifdef DEBUG if (pmapdebug & PDB_CHANGEPROT) - printf("pmap_changeprot(%p, %lx, %x, %x)\n", + printf("pmap_changeprot(%p, 0x%lx, 0x%x, 0x%x)\n", pm, va, prot, wired); #endif @@ -4732,42 +4592,37 @@ pmap_changeprot4_4c(pm, va, prot, wired) *pte = (*pte & ~PG_PROT) | newprot; } else { /* update in hardware */ - ctx = getcontext(); + ctx = getcontext4(); if (CTX_USABLE(pm,rp)) { - /* use current context; flush writeback cache */ - setcontext(pm->pm_ctxnum); + /* + * Use current context. + * Flush cache if page has been referenced to + * avoid stale protection bits in the cache tags. + */ + setcontext4(pm->pm_ctxnum); tpte = getpte4(va); if ((tpte & PG_PROT) == newprot) { - setcontext(ctx); + setcontext4(ctx); goto useless; } - - /* - * the latter check deals with a writethrough cache - * problem on the 4/300 - */ - if ((vactype==VAC_WRITEBACK || - (vactype==VAC_WRITETHROUGH && cputyp==CPU_SUN4)) && - (tpte & (PG_U|PG_NC|PG_TYPE)) == (PG_U|PG_OBMEM)) + if ((tpte & (PG_U|PG_NC|PG_TYPE)) == (PG_U|PG_OBMEM)) cache_flush_page((int)va); } else { - setcontext(0); + setcontext4(0); /* XXX use per-cpu va? */ -#ifdef MMU_3L - if (mmu_3l) + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, sp->sg_pmeg); va = VA_VPG(va) << PGSHIFT; tpte = getpte4(va); if ((tpte & PG_PROT) == newprot) { - setcontext(ctx); + setcontext4(ctx); goto useless; } } tpte = (tpte & ~PG_PROT) | newprot; setpte4(va, tpte); - setcontext(ctx); + setcontext4(ctx); } splx(s); return; @@ -4796,8 +4651,7 @@ pmap_page_protect4m(pa, prot) { register struct pvlist *pv, *pv0, *npv; register struct pmap *pm; - register vm_offset_t va; - register int vr, vs, tpte; + register int va, vr, vs, tpte; register int flags, nleft, s, ctx; struct regmap *rp; struct segmap *sp; @@ -4807,7 +4661,7 @@ pmap_page_protect4m(pa, prot) panic("pmap_page_protect: no such address: 0x%lx", pa); if ((pmapdebug & PDB_CHANGEPROT) || (pmapdebug & PDB_REMOVE && prot == VM_PROT_NONE)) - printf("pmap_page_protect(%lx, %x)\n", pa, prot); + printf("pmap_page_protect(0x%lx, 0x%x)\n", pa, prot); #endif /* * Skip unmanaged pages, or operations that do not take @@ -4833,7 +4687,7 @@ pmap_page_protect4m(pa, prot) splx(s); return; } - ctx = getcontext(); + ctx = getcontext4m(); pv0 = pv; flags = pv->pv_flags /*| PV_C4M*/; /* %%%: ???? */ for (;; pm = pv->pv_pmap) { @@ -4850,63 +4704,71 @@ pmap_page_protect4m(pa, prot) sp->sg_npte = nleft; /* Invalidate PTE in MMU pagetables. Flush cache if necessary */ - if (CTX_USABLE(pm,rp)) { /* Must flush */ - setcontext(pm->pm_ctxnum); - tpte = getpte4m(va); - if (vactype != VAC_NONE) - cache_flush_page(va); + if (pm->pm_ctx) { + setcontext4m(pm->pm_ctxnum); + cache_flush_page(va); tlb_flush_page(va); - } else - tpte = getptesw4m(pm, va); + } + + tpte = sp->sg_pte[VA_SUN4M_VPG(va)]; if ((tpte & SRMMU_TETYPE) != SRMMU_TEPTE) panic("pmap_page_protect !PG_V"); + flags |= MR4M(tpte); - if (nleft) - setptesw4m(pm, va, SRMMU_TEINVALID); - else { - if (pm == pmap_kernel()) { - tlb_flush_segment(vr, vs); /* Paranoid? */ - if (va < virtual_avail) { + if (nleft) { + setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], SRMMU_TEINVALID); + goto nextpv; + } + + /* Entire segment is gone */ + if (pm == pmap_kernel()) { + tlb_flush_segment(vr, vs); /* Paranoid? */ + setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], SRMMU_TEINVALID); + if (va < virtual_avail) { #ifdef DEBUG - printf("pmap_rmk4m: attempt to free " - "base kernel allocation\n"); + printf( + "pmap_page_protect: attempt to free" + " base kernel allocation\n"); +#endif + goto nextpv; + } +#if 0 /* no need for this */ + /* no need to free the table; it is static */ + qzero(sp->sg_pte, SRMMU_L3SIZE * sizeof(int)); #endif - goto nextpv; - } - /* no need to free the table; it is static */ - qzero(sp->sg_pte, SRMMU_L3SIZE * sizeof(int)); - /* if we're done with a region, leave it */ + /* if we're done with a region, leave it */ - } else { /* User mode mapping */ - if (CTX_USABLE(pm,rp)) - tlb_flush_segment(vr, vs); - rp->rg_seg_ptps[vs] = SRMMU_TEINVALID; - free(sp->sg_pte, M_VMPMAP); - sp->sg_pte = NULL; + } else { /* User mode mapping */ + if (pm->pm_ctx) + tlb_flush_segment(vr, vs); + setpgt4m(&rp->rg_seg_ptps[vs], SRMMU_TEINVALID); + free(sp->sg_pte, M_VMPMAP); + sp->sg_pte = NULL; - if (--rp->rg_nsegmap == 0) { - free(rp->rg_segmap, M_VMPMAP); - rp->rg_segmap = NULL; - free(rp->rg_seg_ptps, M_VMPMAP); - pm->pm_reg_ptps[vr] = SRMMU_TEINVALID; - GAP_WIDEN(pm,vr); - } + if (--rp->rg_nsegmap == 0) { + if (pm->pm_ctx) + tlb_flush_context(); + setpgt4m(&pm->pm_reg_ptps[vr], SRMMU_TEINVALID); + free(rp->rg_segmap, M_VMPMAP); + rp->rg_segmap = NULL; + free(rp->rg_seg_ptps, M_VMPMAP); } } + nextpv: npv = pv->pv_next; if (pv != pv0) - free(pv, M_VMPVENT); + FREE(pv, M_VMPVENT); if ((pv = npv) == NULL) break; } pv0->pv_pmap = NULL; pv0->pv_next = NULL; /* ? */ pv0->pv_flags = flags; - setcontext(ctx); + setcontext4m(ctx); splx(s); } @@ -4925,8 +4787,7 @@ pmap_protect4m(pm, sva, eva, prot) vm_offset_t sva, eva; vm_prot_t prot; { - register vm_offset_t va, nva; - register int vr, vs; + register int va, nva, vr, vs; register int s, ctx; struct regmap *rp; struct segmap *sp; @@ -4940,7 +4801,7 @@ pmap_protect4m(pm, sva, eva, prot) } write_user_windows(); - ctx = getcontext(); + ctx = getcontext4m(); s = splpmap(); simple_lock(&pm->pm_lock); @@ -4970,43 +4831,34 @@ pmap_protect4m(pm, sva, eva, prot) if (sp->sg_pte == NULL) panic("pmap_protect: no pages"); #endif - /* in MMU: take away write bits from MMU PTEs */ - if (CTX_USABLE(pm,rp)) { + /* pages loaded: take away write bits from MMU PTEs */ + if (pm->pm_ctx) + setcontext4m(pm->pm_ctxnum); + + pmap_stats.ps_npg_prot_all = (nva - va) >> PGSHIFT; + for (; va < nva; va += NBPG) { + int tpte; + tpte = sp->sg_pte[VA_SUN4M_VPG(va)]; /* * Flush cache so that any existing cache * tags are updated. This is really only * needed for PTEs that lose PG_W. */ - setcontext(pm->pm_ctxnum); - for (; va < nva; va += NBPG) { - register int tpte = getpte4m(va); - pmap_stats.ps_npg_prot_all++; - if ((tpte & (PPROT_WRITE|SRMMU_PGTYPE)) == - (PPROT_WRITE|PG_SUN4M_OBMEM)) { - pmap_stats.ps_npg_prot_actual++; - if (vactype != VAC_NONE) - cache_flush_page(va); - setpte4m(va, tpte & ~PPROT_WRITE); + if ((tpte & (PPROT_WRITE|SRMMU_PGTYPE)) == + (PPROT_WRITE|PG_SUN4M_OBMEM)) { + pmap_stats.ps_npg_prot_actual++; + if (pm->pm_ctx) { + cache_flush_page(va); + tlb_flush_page(va); } - } - } else { - /* - * No context, hence not cached; - * just update PTEs. - */ - setcontext(0); - for (; va < nva; va += NBPG) { - register int tpte = getptesw4m(pm, va); - pmap_stats.ps_npg_prot_all++; - if ((tpte & (PPROT_WRITE))) - pmap_stats.ps_npg_prot_actual++; - setptesw4m(pm, va, tpte & ~PPROT_WRITE); + setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], + tpte & ~PPROT_WRITE); } } } simple_unlock(&pm->pm_lock); splx(s); - setcontext(ctx); + setcontext4m(ctx); } /* @@ -5025,7 +4877,7 @@ pmap_changeprot4m(pm, va, prot, wired) #ifdef DEBUG if (pmapdebug & PDB_CHANGEPROT) - printf("pmap_changeprot(%p, %lx, %x, %x)\n", + printf("pmap_changeprot(%p, 0x%lx, 0x%x, 0x%x)\n", pm, va, prot, wired); #endif @@ -5040,31 +4892,33 @@ pmap_changeprot4m(pm, va, prot, wired) pmap_stats.ps_changeprots++; s = splpmap(); /* conservative */ - ctx = getcontext(); + ctx = getcontext4m(); if (pm->pm_ctx) { - setcontext(pm->pm_ctxnum); + /* + * Use current context. + * Flush cache if page has been referenced to + * avoid stale protection bits in the cache tags. + */ + setcontext4m(pm->pm_ctxnum); tpte = getpte4m(va); - if (vactype == VAC_WRITEBACK && - (tpte & SRMMU_PGTYPE) == PG_SUN4M_OBMEM) - cache_flush_page(va); /* XXX: paranoia? */ + if ((tpte & (SRMMU_PG_C|SRMMU_PGTYPE)) == + (SRMMU_PG_C|PG_SUN4M_OBMEM)) + cache_flush_page(va); } else { tpte = getptesw4m(pm, va); } if ((tpte & SRMMU_PROT_MASK) == newprot) { - setcontext(ctx); - goto useless; + /* only wiring changed, and we ignore wiring */ + pmap_stats.ps_useless_changeprots++; + goto out; } if (pm->pm_ctx) setpte4m(va, (tpte & ~SRMMU_PROT_MASK) | newprot); else setptesw4m(pm, va, (tpte & ~SRMMU_PROT_MASK) | newprot); - setcontext(ctx); - splx(s); - return; -useless: - /* only wiring changed, and we ignore wiring */ - pmap_stats.ps_useless_changeprots++; +out: + setcontext4m(ctx); splx(s); } #endif /* 4m */ @@ -5099,7 +4953,7 @@ pmap_enter4_4c(pm, va, pa, prot, wired) if (VA_INHOLE(va)) { #ifdef DEBUG - printf("pmap_enter: pm %p, va %lx, pa %lx: in MMU hole\n", + printf("pmap_enter: pm %p, va 0x%lx, pa 0x%lx: in MMU hole\n", pm, va, pa); #endif return; @@ -5107,12 +4961,12 @@ pmap_enter4_4c(pm, va, pa, prot, wired) #ifdef DEBUG if (pmapdebug & PDB_ENTER) - printf("pmap_enter(%p, %lx, %lx, %x, %x)\n", + printf("pmap_enter(%p, 0x%lx, 0x%lx, 0x%x, 0x%x)\n", pm, va, pa, prot, wired); #endif - pteproto = PG_V | ((pa & PMAP_TNC) << PG_TNC_SHIFT); - pa &= ~PMAP_TNC; + pteproto = PG_V | PMAP_T2PTE_4(pa); + pa &= ~PMAP_TNC_4; /* * Set up prototype for new PTE. Cannot set PG_NC from PV_NC yet * since the pvlist no-cache bit might change as a result of the @@ -5121,7 +4975,7 @@ pmap_enter4_4c(pm, va, pa, prot, wired) if ((pteproto & PG_TYPE) == PG_OBMEM && managed(pa)) { #ifdef DIAGNOSTIC if (!pmap_pa_exists(pa)) - panic("pmap_enter: no such address: %lx", pa); + panic("pmap_enter: no such address: 0x%lx", pa); #endif pv = pvhead(pa); } else { @@ -5131,12 +4985,12 @@ pmap_enter4_4c(pm, va, pa, prot, wired) if (prot & VM_PROT_WRITE) pteproto |= PG_W; - ctx = getcontext(); + ctx = getcontext4(); if (pm == pmap_kernel()) pmap_enk4_4c(pm, va, prot, wired, pv, pteproto | PG_S); else pmap_enu4_4c(pm, va, prot, wired, pv, pteproto); - setcontext(ctx); + setcontext4(ctx); } /* enter new (or change existing) kernel mapping */ @@ -5159,13 +5013,13 @@ pmap_enk4_4c(pm, va, prot, wired, pv, pteproto) sp = &rp->rg_segmap[vs]; s = splpmap(); /* XXX way too conservative */ -#ifdef MMU_3L - if (mmu_3l && rp->rg_smeg == reginval) { +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L && rp->rg_smeg == reginval) { vm_offset_t tva; rp->rg_smeg = region_alloc(®ion_locked, pm, vr)->me_cookie; i = ncontext - 1; do { - setcontext(i); + setcontext4(i); setregmap(va, rp->rg_smeg); } while (--i >= 0); @@ -5185,13 +5039,13 @@ pmap_enk4_4c(pm, va, prot, wired, pv, pteproto) (pteproto & (PG_PFNUM|PG_TYPE))) { /* just changing protection and/or wiring */ splx(s); - pmap_changeprot(pm, va, prot, wired); + pmap_changeprot4_4c(pm, va, prot, wired); return; } if ((tpte & PG_TYPE) == PG_OBMEM) { #ifdef DEBUG -printf("pmap_enk: changing existing va=>pa entry: va %lx, pteproto %x\n", +printf("pmap_enk: changing existing va=>pa entry: va 0x%lx, pteproto 0x%x\n", va, pteproto); #endif /* @@ -5203,9 +5057,8 @@ printf("pmap_enk: changing existing va=>pa entry: va %lx, pteproto %x\n", if (managed(addr)) pv_unlink4_4c(pvhead(addr), pm, va); if ((tpte & PG_NC) == 0) { - setcontext(0); /* ??? */ - if (vactype != VAC_NONE) - cache_flush_page((int)va); + setcontext4(0); /* ??? */ + cache_flush_page((int)va); } } } else { @@ -5237,15 +5090,15 @@ printf("pmap_enk: changing existing va=>pa entry: va %lx, pteproto %x\n", sp->sg_pmeg = me_alloc(&segm_locked, pm, vr, vs)->me_cookie; rp->rg_nsegmap++; -#ifdef MMU_3L - if (mmu_3l) +#if defined(SUN4_MMU3L) + if (HASSUN4_MMU3L) setsegmap(va, sp->sg_pmeg); else #endif { i = ncontext - 1; do { - setcontext(i); + setcontext4(i); setsegmap(va, sp->sg_pmeg); } while (--i >= 0); } @@ -5297,7 +5150,7 @@ pmap_enu4_4c(pm, va, prot, wired, pv, pteproto) #ifdef DEBUG if (pm->pm_gap_end < pm->pm_gap_start) { - printf("pmap_enu: gap_start %x, gap_end %x", + printf("pmap_enu: gap_start 0x%x, gap_end 0x%x", pm->pm_gap_start, pm->pm_gap_end); panic("pmap_enu: gap botch"); } @@ -5352,16 +5205,14 @@ printf("pmap_enter: pte filled during sleep\n"); /* can this happen? */ } else { /* hardware pte */ if (CTX_USABLE(pm,rp)) { - setcontext(pm->pm_ctxnum); + setcontext4(pm->pm_ctxnum); tpte = getpte4(va); - doflush = 1; + doflush = CACHEINFO.c_vactype != VAC_NONE; } else { - setcontext(0); + setcontext4(0); /* XXX use per-cpu pteva? */ -#ifdef MMU_3L - if (mmu_3l) + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, pmeg); tpte = getpte4(VA_VPG(va) << PGSHIFT); } @@ -5387,14 +5238,15 @@ printf("pmap_enter: pte filled during sleep\n"); /* can this happen? */ * If old pa was managed, remove from pvlist. * If old page was cached, flush cache. */ -/*printf("%s[%d]: pmap_enu: changing existing va(%x)=>pa entry\n", -curproc->p_comm, curproc->p_pid, va);*/ +#if 0 +printf("%s[%d]: pmap_enu: changing existing va(0x%x)=>pa entry\n", + curproc->p_comm, curproc->p_pid, va); +#endif if ((tpte & PG_TYPE) == PG_OBMEM) { addr = ptoa(tpte & PG_PFNUM); if (managed(addr)) pv_unlink4_4c(pvhead(addr), pm, va); - if (vactype != VAC_NONE && - doflush && (tpte & PG_NC) == 0) + if (doflush && (tpte & PG_NC) == 0) cache_flush_page((int)va); } } else { @@ -5416,16 +5268,14 @@ curproc->p_comm, curproc->p_pid, va);*/ * Update hardware & software PTEs. */ if ((pmeg = sp->sg_pmeg) != seginval) { - /* ptes are in hardare */ + /* ptes are in hardware */ if (CTX_USABLE(pm,rp)) - setcontext(pm->pm_ctxnum); + setcontext4(pm->pm_ctxnum); else { - setcontext(0); + setcontext4(0); /* XXX use per-cpu pteva? */ -#ifdef MMU_3L - if (mmu_3l) + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, pmeg); va = VA_VPG(va) << PGSHIFT; } @@ -5469,24 +5319,26 @@ pmap_enter4m(pm, va, pa, prot, wired) #ifdef DEBUG if (pmapdebug & PDB_ENTER) - printf("pmap_enter(%p, %lx, %lx, %x, %x)\n", + printf("pmap_enter(%p, 0x%lx, 0x%lx, 0x%x, 0x%x)\n", pm, va, pa, prot, wired); #endif /* Initialise pteproto with cache bit */ pteproto = (pa & PMAP_NC) == 0 ? SRMMU_PG_C : 0; - if (pa & PMAP_TYPE4M) { /* this page goes in an iospace */ - if (cpumod == SUN4M_MS) +#ifdef DEBUG + if (pa & PMAP_TYPE_SRMMU) { /* this page goes in an iospace */ + if (cpuinfo.cpu_type == CPUTYP_MS1) panic("pmap_enter4m: attempt to use 36-bit iospace on" " MicroSPARC"); - pteproto |= (pa & PMAP_TYPE4M) << PMAP_PTESHFT4M; } +#endif + pteproto |= PMAP_T2PTE_SRMMU(pa); /* Make sure we get a pte with appropriate perms! */ pteproto |= SRMMU_TEPTE | PPROT_RX_RX; - pa &= ~PMAP_TNC; + pa &= ~PMAP_TNC_SRMMU; /* * Set up prototype for new PTE. Cannot set PG_NC from PV_NC yet * since the pvlist no-cache bit might change as a result of the @@ -5495,7 +5347,7 @@ pmap_enter4m(pm, va, pa, prot, wired) if ((pteproto & SRMMU_PGTYPE) == PG_SUN4M_OBMEM && managed(pa)) { #ifdef DIAGNOSTIC if (!pmap_pa_exists(pa)) - panic("pmap_enter: no such address: %lx", pa); + panic("pmap_enter: no such address: 0x%lx", pa); #endif pv = pvhead(pa); } else { @@ -5506,14 +5358,14 @@ pmap_enter4m(pm, va, pa, prot, wired) if (prot & VM_PROT_WRITE) pteproto |= PPROT_WRITE; - ctx = getcontext(); + ctx = getcontext4m(); if (pm == pmap_kernel()) pmap_enk4m(pm, va, prot, wired, pv, pteproto | PPROT_S); else pmap_enu4m(pm, va, prot, wired, pv, pteproto); - setcontext(ctx); + setcontext4m(ctx); } /* enter new (or change existing) kernel mapping */ @@ -5532,7 +5384,7 @@ pmap_enk4m(pm, va, prot, wired, pv, pteproto) #ifdef DEBUG if (va < KERNBASE) - panic("pmap_enk4m: can't enter va 0x%lx below KERNBASE",va); + panic("pmap_enk4m: can't enter va 0x%lx below KERNBASE", va); #endif vr = VA_VREG(va); vs = VA_VSEG(va); @@ -5542,9 +5394,10 @@ pmap_enk4m(pm, va, prot, wired, pv, pteproto) s = splpmap(); /* XXX way too conservative */ if (rp->rg_seg_ptps == NULL) /* enter new region */ - panic("pmap_enk4m: missing kernel region table for va %lx",va); + panic("pmap_enk4m: missing kernel region table for va 0x%lx",va); - if (((tpte = getpte4m(va)) & SRMMU_TETYPE) == SRMMU_TEPTE) { + tpte = sp->sg_pte[VA_SUN4M_VPG(va)]; + if ((tpte & SRMMU_TETYPE) == SRMMU_TEPTE) { register int addr; /* old mapping exists, and is of the same pa type */ @@ -5552,14 +5405,14 @@ pmap_enk4m(pm, va, prot, wired, pv, pteproto) if ((tpte & SRMMU_PPNMASK) == (pteproto & SRMMU_PPNMASK)) { /* just changing protection and/or wiring */ splx(s); - pmap_changeprot(pm, va, prot, wired); + pmap_changeprot4m(pm, va, prot, wired); return; } if ((tpte & SRMMU_PGTYPE) == PG_SUN4M_OBMEM) { #ifdef DEBUG -printf("pmap_enk4m: changing existing va=>pa entry: va %lx, pteproto %x, " - "oldpte %x\n", va, pteproto, tpte); +printf("pmap_enk4m: changing existing va=>pa entry: va 0x%lx, pteproto 0x%x, " + "oldpte 0x%x\n", va, pteproto, tpte); #endif /* * Switcheroo: changing pa for this va. @@ -5570,9 +5423,8 @@ printf("pmap_enk4m: changing existing va=>pa entry: va %lx, pteproto %x, " if (managed(addr)) pv_unlink4m(pvhead(addr), pm, va); if (tpte & SRMMU_PG_C) { - setcontext(0); /* ??? */ - if (vactype != VAC_NONE) - cache_flush_page((int)va); + setcontext4m(0); /* ??? */ + cache_flush_page((int)va); } } } else { @@ -5588,11 +5440,13 @@ printf("pmap_enk4m: changing existing va=>pa entry: va %lx, pteproto %x, " if (pv != NULL) pteproto &= ~(pv_link4m(pv, pm, va)); +#ifdef DEBUG if (sp->sg_pte == NULL) /* If no existing pagetable */ panic("pmap_enk4m: missing segment table for va 0x%lx",va); +#endif - /* ptes kept in hardware only */ - setpte4m(va, pteproto); + tlb_flush_page(va); + setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], pteproto); splx(s); } @@ -5607,24 +5461,21 @@ pmap_enu4m(pm, va, prot, wired, pv, pteproto) register struct pvlist *pv; register int pteproto; { - register int vr, vs, *pte, tpte, s, doflush; + register int vr, vs, *pte, tpte, s; struct regmap *rp; struct segmap *sp; +#ifdef DEBUG + if (KERNBASE < va) + panic("pmap_enu4m: can't enter va 0x%lx above KERNBASE", va); +#endif + write_user_windows(); /* XXX conservative */ vr = VA_VREG(va); vs = VA_VSEG(va); rp = &pm->pm_regmap[vr]; s = splpmap(); /* XXX conservative */ -#ifdef DEBUG - if (pm->pm_gap_end < pm->pm_gap_start) { - printf("pmap_enu: gap_start %x, gap_end %x", - pm->pm_gap_start, pm->pm_gap_end); - panic("pmap_enu: gap botch"); - } -#endif - rretry: if (rp->rg_segmap == NULL) { /* definitely a new mapping */ @@ -5646,24 +5497,27 @@ printf("pmap_enu4m: segment filled during sleep\n"); /* can this happen? */ rgretry: if (rp->rg_seg_ptps == NULL) { /* Need a segment table */ - register int size; - register caddr_t tblp; + int size, i, *ptd; + size = SRMMU_L2SIZE * sizeof(long); - tblp = malloc(size, M_VMPMAP, M_WAITOK); + ptd = (int *)malloc(size, M_VMPMAP, M_WAITOK); if (rp->rg_seg_ptps != NULL) { #ifdef DEBUG printf("pmap_enu4m: bizarre segment table fill during sleep\n"); #endif - free(tblp,M_VMPMAP); + free(ptd, M_VMPMAP); goto rgretry; } - if (cant_cache_pagetables) - kvm_uncache(tblp, (size+NBPG-1)/NBPG); +#if 0 + if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) + kvm_uncache((char *)ptd, (size+NBPG-1)/NBPG); +#endif - rp->rg_seg_ptps = (int *)tblp; - qzero(tblp, size); - pm->pm_reg_ptps[vr] = - (VA2PA(tblp) >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD; + rp->rg_seg_ptps = ptd; + for (i = 0; i < SRMMU_L2SIZE; i++) + setpgt4m(&ptd[i], SRMMU_TEINVALID); + setpgt4m(&pm->pm_reg_ptps[vr], + (VA2PA((caddr_t)ptd) >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD); } sp = &rp->rg_segmap[vs]; @@ -5671,7 +5525,7 @@ printf("pmap_enu4m: bizarre segment table fill during sleep\n"); sretry: if ((pte = sp->sg_pte) == NULL) { /* definitely a new mapping */ - register int size = SRMMU_L3SIZE * sizeof(*pte); + int i, size = SRMMU_L3SIZE * sizeof(*pte); pte = (int *)malloc((u_long)size, M_VMPMAP, M_WAITOK); if (sp->sg_pte != NULL) { @@ -5679,26 +5533,26 @@ printf("pmap_enter: pte filled during sleep\n"); /* can this happen? */ free(pte, M_VMPMAP); goto sretry; } - if (cant_cache_pagetables) +#if 0 + if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) kvm_uncache((caddr_t)pte, (size+NBPG-1)/NBPG); +#endif - qzero((caddr_t)pte, size); sp->sg_pte = pte; sp->sg_npte = 1; rp->rg_nsegmap++; - rp->rg_seg_ptps[vs] = - (VA2PA((caddr_t)pte) >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD; + for (i = 0; i < SRMMU_L3SIZE; i++) + setpgt4m(&pte[i], SRMMU_TEINVALID); + setpgt4m(&rp->rg_seg_ptps[vs], + (VA2PA((caddr_t)pte) >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD); } else { - /* might be a change: fetch old pte */ - doflush = 0; + /* + * Might be a change: fetch old pte + * Note we're only interested in the PTE's page frame + * number and type bits, so the memory copy will do. + */ + tpte = pte[VA_SUN4M_VPG(va)]; - if (CTX_USABLE(pm,rp)) { - setcontext(pm->pm_ctxnum); - tpte = getpte4m(va); - doflush = 1; - } else { - tpte = getptesw4m(pm, va); - } if ((tpte & SRMMU_TETYPE) == SRMMU_TEPTE) { register int addr; @@ -5721,17 +5575,16 @@ printf("pmap_enter: pte filled during sleep\n"); /* can this happen? */ * If old page was cached, flush cache. */ #ifdef DEBUG -if (pmapdebug & PDB_ENTER) -printf("%s[%d]: pmap_enu: changing existing va(%x)=>pa(pte=%x) entry\n", -curproc->p_comm, curproc->p_pid, (int)va, (int)pte); +if (pmapdebug & PDB_SWITCHMAP) +printf("%s[%d]: pmap_enu: changing existing va(0x%x)=>pa(pte=0x%x) entry\n", + curproc->p_comm, curproc->p_pid, (int)va, (int)pte); #endif if ((tpte & SRMMU_PGTYPE) == PG_SUN4M_OBMEM) { addr = ptoa( (tpte & SRMMU_PPNMASK) >> SRMMU_PPNSHIFT); if (managed(addr)) pv_unlink4m(pvhead(addr), pm, va); - if (vactype != VAC_NONE && - doflush && (tpte & SRMMU_PG_C)) + if (pm->pm_ctx && (tpte & SRMMU_PG_C)) cache_flush_page((int)va); } } else { @@ -5749,14 +5602,13 @@ curproc->p_comm, curproc->p_pid, (int)va, (int)pte); pteproto &= ~(pv_link4m(pv, pm, va)); /* - * Update hardware & software PTEs. + * Update PTEs, flush TLB as necessary. */ - if (CTX_USABLE(pm,rp)) { - setcontext(pm->pm_ctxnum); - setpte4m(va, pteproto); - } else - setptesw4m(pm, va, pteproto); - /* XXX: restore previous context here? */ + if (pm->pm_ctx) { + setcontext4m(pm->pm_ctxnum); + tlb_flush_page(va); + } + setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)], pteproto); splx(s); } @@ -5794,45 +5646,55 @@ pmap_extract4_4c(pm, va) struct segmap *sp; if (pm == NULL) { - printf("pmap_extract: null pmap\n"); +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_extract: null pmap\n"); +#endif return (0); } vr = VA_VREG(va); vs = VA_VSEG(va); rp = &pm->pm_regmap[vr]; if (rp->rg_segmap == NULL) { - printf("pmap_extract: invalid segment (%d)\n", vr); +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_extract: invalid segment (%d)\n", vr); +#endif return (0); } sp = &rp->rg_segmap[vs]; if (sp->sg_pmeg != seginval) { - register int ctx = getcontext(); + register int ctx = getcontext4(); if (CTX_USABLE(pm,rp)) { CHANGE_CONTEXTS(ctx, pm->pm_ctxnum); tpte = getpte4(va); } else { CHANGE_CONTEXTS(ctx, 0); -#ifdef MMU_3L - if (mmu_3l) + if (HASSUN4_MMU3L) setregmap(0, tregion); -#endif setsegmap(0, sp->sg_pmeg); tpte = getpte4(VA_VPG(va) << PGSHIFT); } - setcontext(ctx); + setcontext4(ctx); } else { register int *pte = sp->sg_pte; if (pte == NULL) { - printf("pmap_extract: invalid segment\n"); +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_extract: invalid segment\n"); +#endif return (0); } tpte = pte[VA_VPG(va)]; } if ((tpte & PG_V) == 0) { - printf("pmap_extract: invalid pte\n"); +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_extract: invalid pte\n"); +#endif return (0); } tpte &= PG_PFNUM; @@ -5852,30 +5714,46 @@ pmap_extract4m(pm, va) register struct pmap *pm; vm_offset_t va; { - register int tpte, ctx; + struct regmap *rm; + struct segmap *sm; + int pte; if (pm == NULL) { - printf("pmap_extract: null pmap\n"); +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_extract: null pmap\n"); +#endif return (0); } - if (pm->pm_ctx) { - ctx = getcontext(); - CHANGE_CONTEXTS(ctx, pm->pm_ctxnum); - tpte = getpte4m(va); + rm = &pm->pm_regmap[VA_VREG(va)]; + if (rm == NULL) { #ifdef DEBUG - if ((tpte & SRMMU_TETYPE) != SRMMU_TEPTE) { - printf("pmap_extract: invalid pte of type %d\n", - tpte & SRMMU_TETYPE); - return (0); - } + if (pmapdebug & PDB_FOLLOW) + printf("getptesw4m: no regmap entry"); #endif - setcontext(ctx); - } else - tpte = getptesw4m(pm, va); + return (0); + } + sm = &rm->rg_segmap[VA_VSEG(va)]; + if (sm == NULL) { +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + panic("getptesw4m: no segmap"); +#endif + return (0); + } + pte = sm->sg_pte[VA_SUN4M_VPG(va)]; + if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) { +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) + printf("pmap_extract: invalid pte of type %d\n", + pte & SRMMU_TETYPE); +#endif + return (0); + } - return (ptoa((tpte & SRMMU_PPNMASK) >> SRMMU_PPNSHIFT) | VA_OFF(va)); + return (ptoa((pte & SRMMU_PPNMASK) >> SRMMU_PPNSHIFT) | VA_OFF(va)); } #endif /* sun4m */ @@ -5954,7 +5832,7 @@ pmap_clear_modify4_4c(pa) { register struct pvlist *pv; - if ((pa & (PMAP_TNC & ~PMAP_NC)) == 0 && managed(pa)) { + if ((pa & (PMAP_TNC_4 & ~PMAP_NC)) == 0 && managed(pa)) { pv = pvhead(pa); (void) pv_syncflags4_4c(pv); pv->pv_flags &= ~PV_MOD; @@ -5970,7 +5848,7 @@ pmap_is_modified4_4c(pa) { register struct pvlist *pv; - if ((pa & (PMAP_TNC & ~PMAP_NC)) == 0 && managed(pa)) { + if ((pa & (PMAP_TNC_4 & ~PMAP_NC)) == 0 && managed(pa)) { pv = pvhead(pa); if (pv->pv_flags & PV_MOD || pv_syncflags4_4c(pv) & PV_MOD) return (1); @@ -5987,7 +5865,7 @@ pmap_clear_reference4_4c(pa) { register struct pvlist *pv; - if ((pa & (PMAP_TNC & ~PMAP_NC)) == 0 && managed(pa)) { + if ((pa & (PMAP_TNC_4 & ~PMAP_NC)) == 0 && managed(pa)) { pv = pvhead(pa); (void) pv_syncflags4_4c(pv); pv->pv_flags &= ~PV_REF; @@ -6003,7 +5881,7 @@ pmap_is_referenced4_4c(pa) { register struct pvlist *pv; - if ((pa & (PMAP_TNC & ~PMAP_NC)) == 0 && managed(pa)) { + if ((pa & (PMAP_TNC_4 & ~PMAP_NC)) == 0 && managed(pa)) { pv = pvhead(pa); if (pv->pv_flags & PV_REF || pv_syncflags4_4c(pv) & PV_REF) return (1); @@ -6032,7 +5910,7 @@ pmap_clear_modify4m(pa) /* XXX %%%: Should service from swpagetbl for 4m */ { register struct pvlist *pv; - if ((pa & (PMAP_TNC & ~PMAP_NC)) == 0 && managed(pa)) { + if ((pa & (PMAP_TNC_SRMMU & ~PMAP_NC)) == 0 && managed(pa)) { pv = pvhead(pa); (void) pv_syncflags4m(pv); pv->pv_flags &= ~PV_MOD4M; @@ -6048,7 +5926,7 @@ pmap_is_modified4m(pa) /* Test performance with SUN4M && SUN4/4C. XXX */ { register struct pvlist *pv; - if ((pa & (PMAP_TNC & ~PMAP_NC)) == 0 && managed(pa)) { + if ((pa & (PMAP_TNC_SRMMU & ~PMAP_NC)) == 0 && managed(pa)) { pv = pvhead(pa); if (pv->pv_flags & PV_MOD4M || pv_syncflags4m(pv) & PV_MOD4M) return(1); @@ -6065,7 +5943,7 @@ pmap_clear_reference4m(pa) { register struct pvlist *pv; - if ((pa & (PMAP_TNC & ~PMAP_NC)) == 0 && managed(pa)) { + if ((pa & (PMAP_TNC_SRMMU & ~PMAP_NC)) == 0 && managed(pa)) { pv = pvhead(pa); (void) pv_syncflags4m(pv); pv->pv_flags &= ~PV_REF4M; @@ -6081,7 +5959,7 @@ pmap_is_referenced4m(pa) { register struct pvlist *pv; - if ((pa & (PMAP_TNC & ~PMAP_NC)) == 0 && managed(pa)) { + if ((pa & (PMAP_TNC_SRMMU & ~PMAP_NC)) == 0 && managed(pa)) { pv = pvhead(pa); if (pv->pv_flags & PV_REF4M || pv_syncflags4m(pv) & PV_REF4M) return(1); @@ -6125,14 +6003,13 @@ pmap_zero_page4_4c(pa) register caddr_t va; register int pte; - if (((pa & (PMAP_TNC & ~PMAP_NC)) == 0) && managed(pa)) { + if (((pa & (PMAP_TNC_4 & ~PMAP_NC)) == 0) && managed(pa)) { /* * The following might not be necessary since the page * is being cleared because it is about to be allocated, * i.e., is in use by no one. */ - if (vactype != VAC_NONE) - pv_flushcache(pvhead(pa)); + pv_flushcache(pvhead(pa)); } pte = PG_V | PG_S | PG_W | PG_NC | (atop(pa) & PG_PFNUM); @@ -6159,14 +6036,14 @@ pmap_copy_page4_4c(src, dst) register int spte, dpte; if (managed(src)) { - if (vactype == VAC_WRITEBACK) + if (CACHEINFO.c_vactype == VAC_WRITEBACK) pv_flushcache(pvhead(src)); } spte = PG_V | PG_S | (atop(src) & PG_PFNUM); if (managed(dst)) { /* similar `might not be necessary' comment applies */ - if (vactype != VAC_NONE) + if (CACHEINFO.c_vactype != VAC_NONE) pv_flushcache(pvhead(dst)); } dpte = PG_V | PG_S | PG_W | PG_NC | (atop(dst) & PG_PFNUM); @@ -6176,8 +6053,7 @@ pmap_copy_page4_4c(src, dst) setpte4(sva, spte); setpte4(dva, dpte); qcopy(sva, dva, NBPG); /* loads cache, so we must ... */ - if (vactype != VAC_NONE) - cache_flush_page((int)sva); + cache_flush_page((int)sva); setpte4(sva, 0); setpte4(dva, 0); } @@ -6196,28 +6072,32 @@ pmap_zero_page4m(pa) { register caddr_t va; register int pte; + int ctx; - if (((pa & (PMAP_TNC & ~PMAP_NC)) == 0) && managed(pa)) { + if (((pa & (PMAP_TNC_SRMMU & ~PMAP_NC)) == 0) && managed(pa)) { /* * The following might not be necessary since the page * is being cleared because it is about to be allocated, * i.e., is in use by no one. */ - if (vactype != VAC_NONE) + if (CACHEINFO.c_vactype != VAC_NONE) pv_flushcache(pvhead(pa)); } - /* - * there really needs to be a conditional ecache flush here, but - * making the page cacheable avoids problems with potentially - * leaving dirty cache lines pending in the e-cache while the page - * is marked non-cachable. Per Chris Torek and Aaron Brown... - */ - pte = SRMMU_PG_C | (SRMMU_TEPTE | PPROT_S | PPROT_WRITE | - (atop(pa) << SRMMU_PPNSHIFT)); + pte = (SRMMU_TEPTE | PPROT_S | PPROT_WRITE | + (atop(pa) << SRMMU_PPNSHIFT)); + if (cpuinfo.flags & CPUFLG_CACHE_MANDATORY) + pte |= SRMMU_PG_C; + else + pte &= ~SRMMU_PG_C; + + /* XXX - must use context 0 or else setpte4m() will fail */ + ctx = getcontext4m(); + setcontext4m(0); va = vpage[0]; setpte4m((vm_offset_t) va, pte); qzero(va, NBPG); setpte4m((vm_offset_t) va, SRMMU_TEINVALID); + setcontext4m(ctx); } /* @@ -6235,9 +6115,10 @@ pmap_copy_page4m(src, dst) { register caddr_t sva, dva; register int spte, dpte; + int ctx; if (managed(src)) { - if (vactype == VAC_WRITEBACK) + if (CACHEINFO.c_vactype == VAC_WRITEBACK) pv_flushcache(pvhead(src)); } spte = SRMMU_TEPTE | SRMMU_PG_C | PPROT_S | @@ -6245,27 +6126,28 @@ pmap_copy_page4m(src, dst) if (managed(dst)) { /* similar `might not be necessary' comment applies */ - if (vactype != VAC_NONE) + if (CACHEINFO.c_vactype != VAC_NONE) pv_flushcache(pvhead(dst)); } - /* - * there really needs to be a conditional ecache flush here, but - * making the page cacheable avoids problems with potentially - * leaving dirty cache lines pending in the e-cache while the page - * is marked non-cachable. Per Chris Torek and Aaron Brown... - */ - dpte = SRMMU_PG_C | (SRMMU_TEPTE | PPROT_S | PPROT_WRITE | - (atop(dst) << SRMMU_PPNSHIFT)); + dpte = (SRMMU_TEPTE | PPROT_S | PPROT_WRITE | + (atop(dst) << SRMMU_PPNSHIFT)); + if (cpuinfo.flags & CPUFLG_CACHE_MANDATORY) + dpte |= SRMMU_PG_C; + else + dpte &= ~SRMMU_PG_C; + /* XXX - must use context 0 or else setpte4m() will fail */ + ctx = getcontext4m(); + setcontext4m(0); sva = vpage[0]; dva = vpage[1]; setpte4m((vm_offset_t) sva, spte); setpte4m((vm_offset_t) dva, dpte); qcopy(sva, dva, NBPG); /* loads cache, so we must ... */ - if (vactype != VAC_NONE) - cache_flush_page((int)sva); + cache_flush_page((int)sva); setpte4m((vm_offset_t) sva, SRMMU_TEINVALID); setpte4m((vm_offset_t) dva, SRMMU_TEINVALID); + setcontext4m(ctx); } #endif /* Sun4M */ @@ -6294,6 +6176,7 @@ kvm_uncache(va, npages) register int npages; { register int pte; + if (CPU_ISSUN4M) { #if defined(SUN4M) for (; --npages >= 0; va += NBPG) { @@ -6302,7 +6185,7 @@ kvm_uncache(va, npages) panic("kvm_uncache: table entry not pte"); pte &= ~SRMMU_PG_C; setpte4m((vm_offset_t) va, pte); - if (vactype != VAC_NONE && (pte & PG_TYPE) == PG_OBMEM) + if ((pte & SRMMU_PGTYPE) == PG_SUN4M_OBMEM) cache_flush_page((int)va); } #endif @@ -6314,7 +6197,7 @@ kvm_uncache(va, npages) panic("kvm_uncache !pg_v"); pte |= PG_NC; setpte4(va, pte); - if (vactype != VAC_NONE && (pte & PG_TYPE) == PG_OBMEM) + if ((pte & PG_TYPE) == PG_OBMEM) cache_flush_page((int)va); } #endif @@ -6437,20 +6320,21 @@ pm_check_u(s, pm) int n, vs, vr, j, m, *pte; if (pm->pm_regmap == NULL) - panic("%s: CHK(pmap %p): no region mapping", s, pm); + panic("%s: CHK(pmap %p): no region mapping", s, pm); #if defined(SUN4M) if (CPU_ISSUN4M && (pm->pm_reg_ptps == NULL || pm->pm_reg_ptps_pa != VA2PA((caddr_t)pm->pm_reg_ptps))) - panic("%s: CHK(pmap %p): no SRMMU region table or bad pa: tblva=%p, tblpa=0x%x", - s, pm, pm->pm_reg_ptps, pm->pm_reg_ptps_pa); + panic("%s: CHK(pmap %p): no SRMMU region table or bad pa: " + "tblva=%p, tblpa=0x%x", + s, pm, pm->pm_reg_ptps, pm->pm_reg_ptps_pa); if (CPU_ISSUN4M && pm->pm_ctx != NULL && - (ctx_phys_tbl[pm->pm_ctxnum] != ((VA2PA((caddr_t)pm->pm_reg_ptps) + (cpuinfo.ctx_tbl[pm->pm_ctxnum] != ((VA2PA((caddr_t)pm->pm_reg_ptps) >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD))) - panic("%s: CHK(pmap %p): SRMMU region table at %x not installed " + panic("%s: CHK(pmap %p): SRMMU region table at 0x%x not installed " "for context %d", s, pm, pm->pm_reg_ptps_pa, pm->pm_ctxnum); #endif @@ -6529,13 +6413,13 @@ pm_check_k(s, pm) /* Note: not as extensive as pm_check_u. */ if (CPU_ISSUN4M && (pm->pm_reg_ptps == NULL || pm->pm_reg_ptps_pa != VA2PA((caddr_t)pm->pm_reg_ptps))) - panic("%s: CHK(pmap %p): no SRMMU region table or bad pa: tblva=%p, tblpa=%x", + panic("%s: CHK(pmap %p): no SRMMU region table or bad pa: tblva=%p, tblpa=0x%x", s, pm, pm->pm_reg_ptps, pm->pm_reg_ptps_pa); if (CPU_ISSUN4M && - (ctx_phys_tbl[0] != ((VA2PA((caddr_t)pm->pm_reg_ptps) >> + (cpuinfo.ctx_tbl[0] != ((VA2PA((caddr_t)pm->pm_reg_ptps) >> SRMMU_PPNPASHIFT) | SRMMU_TEPTD))) - panic("%s: CHK(pmap %p): SRMMU region table at %x not installed " + panic("%s: CHK(pmap %p): SRMMU region table at 0x%x not installed " "for context %d", s, pm, pm->pm_reg_ptps_pa, 0); #endif for (vr = NUREG; vr < NUREG+NKREG; vr++) { @@ -6554,10 +6438,13 @@ pm_check_k(s, pm) /* Note: not as extensive as pm_check_u. */ SRMMU_PPNPASHIFT) | SRMMU_TEPTD)) panic("%s: CHK(vr %d): SRMMU segtbl not installed",s,vr); #endif - n = 0; - for (vs = 0; vs < NSEGRG; vs++) { - if (rp->rg_segmap[vs].sg_npte) - n++; + if (CPU_ISSUN4M) { + n = NSEGRG; + } else { + for (n = 0, vs = 0; vs < NSEGRG; vs++) { + if (rp->rg_segmap[vs].sg_npte) + n++; + } } if (n != rp->rg_nsegmap) printf("%s: kernel CHK(vr %d): inconsistent " @@ -6588,10 +6475,9 @@ pmap_dumpsize() } /* - * Write the dump header and memory mapping information at the front - * of the dumpfile to make life easy for savecore and libkvm. Also - * dump the MMU contents for Sun 4/4c systems since they don't have - * a separate incore copy of the kernel memory mappings. + * Write the mmu contents to the dump device. + * This gets appended to the end of a crash dump since + * there is no in-core copy of kernel memory mappings on a 4/4c machine. */ int pmap_dumpmmu(dump, blkno) @@ -6601,9 +6487,9 @@ pmap_dumpmmu(dump, blkno) kcore_seg_t *ksegp; cpu_kcore_hdr_t *kcpup; phys_ram_seg_t memseg; - register int error = 0; + register int error = 0; register int i, memsegoffset, pmegoffset; - int buffer[dbtob(1) / sizeof(int)]; + int buffer[dbtob(1) / sizeof(int)]; int *bp, *ep; #if defined(SUN4C) || defined(SUN4) register int pmeg; @@ -6622,7 +6508,7 @@ pmap_dumpmmu(dump, blkno) ++blkno; \ bp = buffer; \ } \ - sz -= sizeof *sp; \ + sz -= 4; \ } \ } while (0) @@ -6653,7 +6539,7 @@ pmap_dumpmmu(dump, blkno) /* Align storage for upcoming quad-aligned segment array */ while (bp != (int *)ALIGN(bp)) { int dummy = 0; - EXPEDITE(&dummy, sizeof dummy); + EXPEDITE(&dummy, 4); } for (i = 0; i < npmemarr; i++) { memseg.start = pmemarr[i].addr; @@ -6679,7 +6565,7 @@ pmap_dumpmmu(dump, blkno) * Go through the pmegs and dump each one. */ for (pmeg = 0; pmeg <= seginval; ++pmeg) { - register vm_offset_t va = 0; + register int va = 0; setsegmap(va, pmeg); i = NPTESG; @@ -6712,7 +6598,7 @@ debug_pagetables() printf("\nncontext=%d. ",ncontext); printf("Context table is at va 0x%x. Level 0 PTP: 0x%x\n", - ctx_phys_tbl, ctx_phys_tbl[0]); + cpuinfo.ctx_tbl, cpuinfo.ctx_tbl[0]); printf("Context 0 region table is at va 0x%x, pa 0x%x. Contents:\n", pmap_kernel()->pm_reg_ptps, pmap_kernel()->pm_reg_ptps_pa); @@ -6761,7 +6647,7 @@ VA2PAsw(ctx, addr, pte) printf("Looking up addr 0x%x in context 0x%x\n",addr,ctx); #endif /* L0 */ - *pte = curpte = ctx_phys_tbl[ctx]; + *pte = curpte = cpuinfo.ctx_tbl[ctx]; #ifdef EXTREME_EXTREME_DEBUG printf("Got L0 pte 0x%x\n",pte); #endif @@ -6866,7 +6752,7 @@ void print_fe_map(void) for (i = 0xfe000000; i < 0xff000000; i+=4096) { if (((pte = getpte4m(i)) & SRMMU_TETYPE) != SRMMU_TEPTE) continue; - printf("0x%x -> 0x%x%x (pte %x)\n", i, pte >> 28, + printf("0x%x -> 0x%x%x (pte 0x%x)\n", i, pte >> 28, (pte & ~0xff) << 4, pte); } printf("done\n"); diff --git a/sys/arch/sparc/sparc/process_machdep.c b/sys/arch/sparc/sparc/process_machdep.c index 3ea7669ede6..afaa37a2342 100644 --- a/sys/arch/sparc/sparc/process_machdep.c +++ b/sys/arch/sparc/sparc/process_machdep.c @@ -1,3 +1,4 @@ +/* $OpenBSD: process_machdep.c,v 1.3 1997/08/08 08:27:39 downsj Exp $ */ /* $NetBSD: process_machdep.c,v 1.6 1996/03/14 21:09:26 christos Exp $ */ /* diff --git a/sys/arch/sparc/sparc/rd_root.c b/sys/arch/sparc/sparc/rd_root.c index 6474f0d2188..7cffb24430f 100644 --- a/sys/arch/sparc/sparc/rd_root.c +++ b/sys/arch/sparc/sparc/rd_root.c @@ -1,3 +1,4 @@ +/* $OpenBSD: rd_root.c,v 1.2 1997/08/08 08:27:40 downsj Exp $ */ /* $NetBSD: rd_root.c,v 1.2 1996/03/27 16:38:33 perry Exp $ */ /* diff --git a/sys/arch/sparc/sparc/sunos_machdep.c b/sys/arch/sparc/sparc/sunos_machdep.c index 1a572199112..d013f076741 100644 --- a/sys/arch/sparc/sparc/sunos_machdep.c +++ b/sys/arch/sparc/sparc/sunos_machdep.c @@ -1,7 +1,8 @@ -/* $NetBSD: sunos_machdep.c,v 1.3 1995/10/07 06:26:08 mycroft Exp $ */ +/* $OpenBSD: sunos_machdep.c,v 1.2 1997/08/08 08:27:41 downsj Exp $ */ +/* $NetBSD: sunos_machdep.c,v 1.4 1996/10/05 23:44:33 mrg Exp $ */ /* - * Copyright (c) 1995 Matthew Green + * Copyright (c) 1995 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -12,18 +13,27 @@ * 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 + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Matthew R. Green for + * the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ diff --git a/sys/arch/sparc/sparc/svr4_machdep.c b/sys/arch/sparc/sparc/svr4_machdep.c index 0100d8bf9bb..92bb3522029 100644 --- a/sys/arch/sparc/sparc/svr4_machdep.c +++ b/sys/arch/sparc/sparc/svr4_machdep.c @@ -1,4 +1,5 @@ -/* $NetBSD: svr4_machdep.c,v 1.17.4.1 1996/06/11 01:46:42 jtc Exp $ */ +/* $OpenBSD: svr4_machdep.c,v 1.9 1997/08/08 08:27:42 downsj Exp $ */ +/* $NetBSD: svr4_machdep.c,v 1.24 1997/07/29 10:04:45 fair Exp $ */ /* * Copyright (c) 1994 Christos Zoulas @@ -40,6 +41,7 @@ #include <sys/signalvar.h> #include <sys/malloc.h> #include <sys/buf.h> +#include <sys/exec.h> #include <sys/syscallargs.h> #include <compat/svr4/svr4_types.h> @@ -77,31 +79,31 @@ svr4_printcontext(fun, uc) printf("%s at %p\n", fun, uc); printf("Regs: "); - printf("PSR = %x ", r[SVR4_SPARC_PSR]); - printf("PC = %x ", r[SVR4_SPARC_PC]); - printf("nPC = %x ", r[SVR4_SPARC_nPC]); - printf("Y = %x ", r[SVR4_SPARC_Y]); - printf("G1 = %x ", r[SVR4_SPARC_G1]); - printf("G2 = %x ", r[SVR4_SPARC_G2]); - printf("G3 = %x ", r[SVR4_SPARC_G3]); - printf("G4 = %x ", r[SVR4_SPARC_G4]); - printf("G5 = %x ", r[SVR4_SPARC_G5]); - printf("G6 = %x ", r[SVR4_SPARC_G6]); - printf("G7 = %x ", r[SVR4_SPARC_G7]); - printf("O0 = %x ", r[SVR4_SPARC_O0]); - printf("O1 = %x ", r[SVR4_SPARC_O1]); - printf("O2 = %x ", r[SVR4_SPARC_O2]); - printf("O3 = %x ", r[SVR4_SPARC_O3]); - printf("O4 = %x ", r[SVR4_SPARC_O4]); - printf("O5 = %x ", r[SVR4_SPARC_O5]); - printf("O6 = %x ", r[SVR4_SPARC_O6]); - printf("O7 = %x ", r[SVR4_SPARC_O7]); + printf("PSR = 0x%x ", r[SVR4_SPARC_PSR]); + printf("PC = 0x%x ", r[SVR4_SPARC_PC]); + printf("nPC = 0x%x ", r[SVR4_SPARC_nPC]); + printf("Y = 0x%x ", r[SVR4_SPARC_Y]); + printf("G1 = 0x%x ", r[SVR4_SPARC_G1]); + printf("G2 = 0x%x ", r[SVR4_SPARC_G2]); + printf("G3 = 0x%x ", r[SVR4_SPARC_G3]); + printf("G4 = 0x%x ", r[SVR4_SPARC_G4]); + printf("G5 = 0x%x ", r[SVR4_SPARC_G5]); + printf("G6 = 0x%x ", r[SVR4_SPARC_G6]); + printf("G7 = 0x%x ", r[SVR4_SPARC_G7]); + printf("O0 = 0x%x ", r[SVR4_SPARC_O0]); + printf("O1 = 0x%x ", r[SVR4_SPARC_O1]); + printf("O2 = 0x%x ", r[SVR4_SPARC_O2]); + printf("O3 = 0x%x ", r[SVR4_SPARC_O3]); + printf("O4 = 0x%x ", r[SVR4_SPARC_O4]); + printf("O5 = 0x%x ", r[SVR4_SPARC_O5]); + printf("O6 = 0x%x ", r[SVR4_SPARC_O6]); + printf("O7 = 0x%x ", r[SVR4_SPARC_O7]); printf("\n"); - printf("Signal Stack: sp %p, size %d, flags %x\n", - s->ss_sp, s->ss_size, s->ss_flags); + printf("Signal Stack: sp %p, size %d, flags 0x%x\n", + s->ss_sp, s->ss_size, s->ss_flags); - printf("Flags: %lx\n", uc->uc_flags); + printf("Flags: 0x%lx\n", uc->uc_flags); } #endif @@ -167,7 +169,7 @@ svr4_getcontext(p, uc, mask, oonstack) if (copyout(fps->fs_queue, f->fp_q, sz) != 0) { #ifdef DIAGNOSTIC printf("getcontext: copy of fp_queue failed %d\n", - error); + error); #endif return; } diff --git a/sys/arch/sparc/sparc/sys_machdep.c b/sys/arch/sparc/sparc/sys_machdep.c index e83270eaf3b..80dd232bb53 100644 --- a/sys/arch/sparc/sparc/sys_machdep.c +++ b/sys/arch/sparc/sparc/sys_machdep.c @@ -1,3 +1,4 @@ +/* $OpenBSD: sys_machdep.c,v 1.3 1997/08/08 08:27:44 downsj Exp $ */ /* $NetBSD: sys_machdep.c,v 1.7 1996/03/14 21:09:33 christos Exp $ */ /* diff --git a/sys/arch/sparc/sparc/timerreg.h b/sys/arch/sparc/sparc/timerreg.h index 26bc2a57ca3..b6f41dcf1f3 100644 --- a/sys/arch/sparc/sparc/timerreg.h +++ b/sys/arch/sparc/sparc/timerreg.h @@ -1,4 +1,5 @@ -/* $NetBSD: timerreg.h,v 1.5 1996/05/02 18:17:33 pk Exp $ */ +/* $OpenBSD: timerreg.h,v 1.3 1997/08/08 08:27:44 downsj Exp $ */ +/* $NetBSD: timerreg.h,v 1.6 1996/10/28 00:20:32 abrown Exp $ */ /* * Copyright (c) 1992, 1993 @@ -74,12 +75,6 @@ * they count in 500ns increments (bit 9 being the least * significant bit). * - * Note that we still use the `sun4c' masks and shifts to compute - * the bit pattern, given the tick period in microseconds, resulting - * in a limit value that is 1 too high. This means that (with HZ=100) - * the clock will err on the slow side by 500ns/10ms (or 0.00005 %). - * We dont bother. - * */ #ifndef _LOCORE struct timer_4 { @@ -118,8 +113,18 @@ struct counter_4m { /* counter that interrupts at ipl 14 */ #define TMR_SHIFT 10 /* shift to obtain microseconds */ #define TMR_MASK 0x1fffff /* 21 bits */ -/* Compute a limit that causes the timer to fire every n microseconds. */ +/* + * Compute a limit that causes the timer to fire every n microseconds. + * The Sun4c requires that the timer register be initialized for n+1 + * microseconds, while the Sun4m requires it be initialized for n. Thus + * the two versions of this function. + * + * Note that the manual for the chipset used in the Sun4m suggests that + * the timer be set at n+0.5 microseconds; in practice, this produces + * a 50 ppm clock skew, which means that the 0.5 should not be there... + */ #define tmr_ustolim(n) (((n) + 1) << TMR_SHIFT) /*efine TMR_SHIFT4M 9 -* shift to obtain microseconds */ -/*efine tmr_ustolim(n) (((2*(n)) + 1) << TMR_SHIFT4M)*/ +/*efine tmr_ustolim4m(n) (((2*(n)) + 1) << TMR_SHIFT4M)*/ +#define tmr_ustolim4m(n) ((n) << TMR_SHIFT) diff --git a/sys/arch/sparc/sparc/trap.c b/sys/arch/sparc/sparc/trap.c index f23f537381e..34c2f049c2a 100644 --- a/sys/arch/sparc/sparc/trap.c +++ b/sys/arch/sparc/sparc/trap.c @@ -1,4 +1,5 @@ -/* $NetBSD: trap.c,v 1.42.4.2 1996/07/03 00:06:40 jtc Exp $ */ +/* $OpenBSD: trap.c,v 1.11 1997/08/08 08:27:46 downsj Exp $ */ +/* $NetBSD: trap.c,v 1.57 1997/07/29 09:42:15 fair Exp $ */ /* * Copyright (c) 1996 @@ -84,6 +85,7 @@ #include <sparc/fpu/fpu_extern.h> #include <sparc/sparc/memreg.h> +#include <sparc/sparc/cpuvar.h> #define offsetof(s, f) ((int)&((s *)0)->f) @@ -201,6 +203,8 @@ void mem_access_fault __P((unsigned, int, u_int, int, int, struct trapframe *)); void mem_access_fault4m __P((unsigned, u_int, u_int, u_int, u_int, struct trapframe *)); void syscall __P((register_t, struct trapframe *, register_t)); +int ignore_bogus_traps = 0; + /* * Define the code needed before returning to user mode, for * trap, mem_access_fault, and syscall. @@ -318,7 +322,11 @@ trap(type, psr, pc, tf) ADVANCE; return; } - goto dopanic; + dopanic: + printf("trap type 0x%x: pc=0x%x npc=0x%x psr=%b\n", + type, pc, tf->tf_npc, psr, PSR_BITS); + panic(type < N_TRAP_TYPES ? trap_type[type] : T); + /* NOTREACHED */ } if ((p = curproc) == NULL) p = &proc0; @@ -329,25 +337,21 @@ trap(type, psr, pc, tf) switch (type) { default: -#if defined(SUN4M) - if (type == 0x29) - /* Mysterious trap 29.. for now print&signal process */ - goto badtrap; -#endif if (type < 0x80) { -dopanic: - printf("trap type 0x%x: pc=%x npc=%x psr=%b\n", + if (!ignore_bogus_traps) + goto dopanic; + printf("trap type 0x%x: pc=0x%x npc=0x%x psr=%b\n", type, pc, tf->tf_npc, psr, PSR_BITS); - panic(type < N_TRAP_TYPES ? trap_type[type] : T); - /* NOTREACHED */ + trapsignal(p, SIGILL, type, ILL_ILLOPC, (caddr_t)pc); + break; } -#if defined(COMPAT_SVR4) || defined(SUN4M) +#if defined(COMPAT_SVR4) badtrap: #endif /* the following message is gratuitous */ /* ... but leave it in until we find anything */ printf("%s[%d]: unimplemented software trap 0x%x\n", - p->p_comm, p->p_pid, type); + p->p_comm, p->p_pid, type); trapsignal(p, SIGILL, type, ILL_ILLOPC, (caddr_t)pc); break; @@ -368,6 +372,10 @@ badtrap: break; /* the work is all in userret() */ case T_ILLINST: + if ((n = emulinstr(pc, tf)) == 0) { + ADVANCE; + break; + } trapsignal(p, SIGILL, 0, ILL_ILLOPC, (caddr_t)pc); break; @@ -435,7 +443,7 @@ badtrap: panic("trap T_RWRET 1"); #ifdef DEBUG if (rwindow_debug) - printf("%s[%d]: rwindow: pcb<-stack: %x\n", + printf("%s[%d]: rwindow: pcb<-stack: 0x%x\n", p->p_comm, p->p_pid, tf->tf_out[6]); #endif if (read_rw(tf->tf_out[6], &pcb->pcb_rw[0])) @@ -457,7 +465,7 @@ badtrap: */ #ifdef DEBUG if (rwindow_debug) - printf("%s[%d]: rwindow: T_WINUF 0: pcb<-stack: %x\n", + printf("%s[%d]: rwindow: T_WINUF 0: pcb<-stack: 0x%x\n", p->p_comm, p->p_pid, tf->tf_out[6]); #endif write_user_windows(); @@ -465,7 +473,7 @@ badtrap: sigexit(p, SIGILL); #ifdef DEBUG if (rwindow_debug) - printf("%s[%d]: rwindow: T_WINUF 1: pcb<-stack: %x\n", + printf("%s[%d]: rwindow: T_WINUF 1: pcb<-stack: 0x%x\n", p->p_comm, p->p_pid, pcb->pcb_rw[0].rw_in[6]); #endif if (read_rw(pcb->pcb_rw[0].rw_in[6], &pcb->pcb_rw[1])) @@ -476,6 +484,11 @@ badtrap: break; case T_ALIGN: + if ((p->p_md.md_flags & MDP_FIXALIGN) != 0 && + fixalign(p, tf) == 0) { + ADVANCE; + break; + } trapsignal(p, SIGBUS, 0, BUS_ADRALN, (caddr_t)pc); break; @@ -514,6 +527,7 @@ badtrap: break; case T_DIV0: + case T_IDIV0: ADVANCE; trapsignal(p, SIGFPE, 0, FPE_INTDIV, (caddr_t)pc); break; @@ -539,7 +553,11 @@ badtrap: break; case T_FIXALIGN: - uprintf("T_FIXALIGN\n"); /* XXX */ +#ifdef DEBUG_ALIGN + uprintf("T_FIXALIGN\n"); +#endif + /* User wants us to fix alignment faults */ + p->p_md.md_flags |= MDP_FIXALIGN; ADVANCE; break; @@ -585,7 +603,7 @@ rwindow_save(p) do { #ifdef DEBUG if (rwindow_debug) - printf(" %x", rw[1].rw_in[6]); + printf(" 0x%x", rw[1].rw_in[6]); #endif if (copyout((caddr_t)rw, (caddr_t)rw[1].rw_in[6], sizeof *rw)) @@ -666,8 +684,8 @@ mem_access_fault(type, ser, v, pc, psr, tf) extern char Lfsbail[]; if (type == T_TEXTFAULT) { (void) splhigh(); - printf("text fault: pc=%x ser=%b\n", pc, - ser, SER_BITS); + printf("text fault: pc=0x%x ser=%b\n", pc, + ser, SER_BITS); panic("kernel fault"); /* NOTREACHED */ } @@ -699,7 +717,7 @@ mem_access_fault(type, ser, v, pc, psr, tf) * that got bumped out via LRU replacement. */ vm = p->p_vmspace; - rv = mmu_pagein(&vm->vm_pmap, va, + rv = mmu_pagein(vm->vm_map.pmap, va, ser & SER_WRITE ? VM_PROT_WRITE : VM_PROT_READ); if (rv < 0) goto fault; @@ -731,7 +749,7 @@ mem_access_fault(type, ser, v, pc, psr, tf) * entries for `wired' pages). Instead, we call * mmu_pagein here to make sure the new PTE gets installed. */ - (void) mmu_pagein(&vm->vm_pmap, va, VM_PROT_NONE); + (void) mmu_pagein(vm->vm_map.pmap, va, VM_PROT_NONE); } else { /* * Pagein failed. If doing copyin/out, return to onfault @@ -745,8 +763,8 @@ kfault: (int)p->p_addr->u_pcb.pcb_onfault : 0; if (!onfault) { (void) splhigh(); - printf("data fault: pc=%x addr=%x ser=%b\n", - pc, v, ser, SER_BITS); + printf("data fault: pc=0x%x addr=0x%x ser=%b\n", + pc, v, ser, SER_BITS); panic("kernel fault"); /* NOTREACHED */ } @@ -790,9 +808,6 @@ mem_access_fault4m(type, sfsr, sfva, afsr, afva, tf) vm_prot_t ftype, vftype; int onfault; u_quad_t sticks; -#if DEBUG -static int lastdouble; -#endif cnt.v_trap++; if ((p = curproc) == NULL) /* safety check */ @@ -819,7 +834,7 @@ static int lastdouble; memerr4m(type, sfsr, sfva, afsr, afva, tf); /* * If we get here, exit the trap handler and wait for the - * trap to reoccur + * trap to re-occur. */ goto out; } @@ -849,26 +864,12 @@ static int lastdouble; goto out; /* No fault. Why were we called? */ /* - * This next section is a mess since some chips use sfva, and others - * don't on text faults. We want to use sfva where possible, since - * we _could_ be dealing with an ASI 0x8,0x9 data access to text space, - * which would trap as a text fault, at least on a HyperSPARC. Ugh. - * XXX: Find out about MicroSPARCs. + * NOTE: the per-CPU fault status register readers (in locore) + * may already have decided to pass `pc' in `sfva', so we avoid + * testing CPU types here. + * Q: test SFSR_FAV in the locore stubs too? */ - - if (type == T_TEXTFAULT && mmumod == SUN4M_MMU_SS && - (cpumod & 0xf0) == (SUN4M_SS) && (sfsr & SFSR_FAV)) { - sfva = pc; /* can't trust fav on supersparc/text fault */ - } else if (type == T_TEXTFAULT && mmumod != SUN4M_MMU_HS) { - sfva = pc; - } else if (!(sfsr & SFSR_FAV)) { -#ifdef DEBUG - if (type != T_TEXTFAULT) - printf("mem_access_fault: got fault without valid SFVA\n"); - if (mmumod == SUN4M_MMU_HS) - printf("mem_access_fault: got fault without valid SFVA on " - "HyperSPARC!\n"); -#endif + if ((sfsr & SFSR_FAV) == 0) { if (type == T_TEXTFAULT) sfva = pc; else @@ -877,7 +878,7 @@ static int lastdouble; if ((sfsr & SFSR_FT) == SFSR_FT_TRANSERR) { /* Translation errors are always fatal, as they indicate - * a corrupt translation (page) table heirarchy. + * a corrupt translation (page) table hierarchy. */ if (tfaultaddr == sfva) /* Prevent infinite loops w/a static */ goto fault; @@ -890,41 +891,17 @@ static int lastdouble; va = trunc_page(sfva); -#ifdef DEBUG - if (lastdouble) { - printf("stacked tfault @ %x (pc %x); sfsr %x", sfva, pc, sfsr); - lastdouble = 0; - if (curproc == NULL) - printf("NULL proc\n"); - else - printf("pid %d(%s); sigmask %x, sigcatch %x\n", - curproc->p_pid, curproc->p_comm, - curproc->p_sigmask, curproc->p_sigcatch); - } -#endif if (((sfsr & SFSR_AT_TEXT) || type == T_TEXTFAULT) && !(sfsr & SFSR_AT_STORE) && (sfsr & SFSR_OW)) { if (psr & PSR_PS) /* never allow in kernel */ goto kfault; +#if 0 /* * Double text fault. The evil "case 5" from the HS manual... * Attempt to handle early fault. Ignores ASI 8,9 issue...may * do a useless VM read. * XXX: Is this really necessary? */ -#ifdef DEBUG - if (dfdebug) { - lastdouble = 1; - printf("mem_access_fault: double text fault @ %x (pc %x); sfsr %x", - sfva, pc, sfsr); - if (curproc == NULL) - printf("NULL proc\n"); - else - printf(" pid %d(%s); sigmask %x, sigcatch %x\n", - curproc->p_pid, curproc->p_comm, - curproc->p_sigmask, curproc->p_sigcatch); - } -#endif if (mmumod == SUN4M_MMU_HS) { /* On HS, we have va for both */ if (vm_fault(kernel_map, trunc_page(pc), VM_PROT_READ, 0) != KERN_SUCCESS) @@ -934,6 +911,7 @@ static int lastdouble; #endif ; } +#endif } /* Now munch on protections... */ @@ -944,7 +922,7 @@ static int lastdouble; extern char Lfsbail[]; if (sfsr & SFSR_AT_TEXT || type == T_TEXTFAULT) { (void) splhigh(); - printf("text fault: pc=%x sfsr=%b sfva=%x\n", pc, + printf("text fault: pc=0x%x sfsr=%b sfva=0x%x\n", pc, sfsr, SFSR_BITS, sfva); panic("kernel fault"); /* NOTREACHED */ @@ -972,21 +950,6 @@ static int lastdouble; p->p_md.md_tf = tf; vm = p->p_vmspace; -#ifdef DEBUG - /* - * mmu_pagein returns -1 if the page is already valid, in which - * case we have a hard fault.. now why would *that* happen? - * But it happens sporadically, and vm_fault() seems to clear it.. - */ - rv = mmu_pagein4m(&vm->vm_pmap, va, - sfsr & SFSR_AT_STORE ? VM_PROT_WRITE : VM_PROT_READ); - if (rv < 0) - printf(" sfsr=%x(FT=%x,AT=%x,LVL=%x), sfva=%x, pc=%x, psr=%x\n", - sfsr, (sfsr >> 2) & 7, (sfsr >> 5) & 7, (sfsr >> 8) & 3, - sfva, pc, psr); - if (rv > 0) - panic("mmu_pagein4m returns %d", rv); -#endif /* alas! must call the horrible vm code */ rv = vm_fault(&vm->vm_map, (vm_offset_t)va, ftype, FALSE); @@ -1019,8 +982,8 @@ kfault: (int)p->p_addr->u_pcb.pcb_onfault : 0; if (!onfault) { (void) splhigh(); - printf("data fault: pc=%x addr=%x sfsr=%b\n", - pc, sfva, sfsr, SFSR_BITS); + printf("data fault: pc=0x%x addr=0x%x sfsr=%b\n", + pc, sfva, sfsr, SFSR_BITS); panic("kernel fault"); /* NOTREACHED */ } diff --git a/sys/arch/sparc/sparc/vaddrs.h b/sys/arch/sparc/sparc/vaddrs.h index 0beedac2545..66ebb45b094 100644 --- a/sys/arch/sparc/sparc/vaddrs.h +++ b/sys/arch/sparc/sparc/vaddrs.h @@ -1,4 +1,5 @@ -/* $NetBSD: vaddrs.h,v 1.7 1996/05/16 15:57:28 abrown Exp $ */ +/* $OpenBSD: vaddrs.h,v 1.4 1997/08/08 08:27:47 downsj Exp $ */ +/* $NetBSD: vaddrs.h,v 1.8 1997/03/10 23:54:41 pk Exp $ */ /* * Copyright (c) 1996 @@ -68,16 +69,12 @@ * use one of the two `wasted' pages at KERNBASE+_MAXNBPG (see locore.s). */ - #ifndef IODEV_0 #define IODEV_0 0xfe000000 /* must match VM_MAX_KERNEL_ADDRESS */ #define _MAXNBPG 8192 /* fixed VAs, independent of actual NBPG */ #define _MAXNCPU 4 /* fixed VA allocation allows 4 CPUs */ -/* [4c:] interrupt register as described above */ -#define INTRREG_VA ( KERNBASE + _MAXNBPG) /* [4c] */ - /* [4m:] interrupt and counter registers take (1 + NCPU) pages. */ #define TIMERREG_VA (IODEV_0) @@ -87,6 +84,7 @@ #define AUXREG_VA ( ZS1_VA + _MAXNBPG) #define TMPMAP_VA ( AUXREG_VA + _MAXNBPG) #define MSGBUF_VA ( TMPMAP_VA + _MAXNBPG) +#define INTRREG_VA ( MSGBUF_VA + _MAXNBPG) /* [4/4c] */ #define PI_INTR_VA ( MSGBUF_VA + _MAXNBPG) /* [4m] */ #define SI_INTR_VA ( PI_INTR_VA + _MAXNBPG*_MAXNCPU) /* [4m] */ #define IODEV_BASE ( SI_INTR_VA + _MAXNBPG) @@ -119,4 +117,9 @@ #define DVMA4M_START 0xfd000000 /* 16M of DVMA */ #define DVMA4M_END 0xfe000000 /* XXX is this enough? */ +/* + * Virtual address of the per cpu `cpu_softc' structure. + */ +#define CPUINFO_VA (KERNBASE+8192) + #endif /* IODEV_0 */ diff --git a/sys/arch/sparc/sparc/vm_machdep.c b/sys/arch/sparc/sparc/vm_machdep.c index 0a0bc838935..521588c8350 100644 --- a/sys/arch/sparc/sparc/vm_machdep.c +++ b/sys/arch/sparc/sparc/vm_machdep.c @@ -1,4 +1,5 @@ -/* $NetBSD: vm_machdep.c,v 1.27.4.1 1996/08/02 21:35:20 jtc Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.5 1997/08/08 08:27:48 downsj Exp $ */ +/* $NetBSD: vm_machdep.c,v 1.30 1997/03/10 23:55:40 pk Exp $ */ /* * Copyright (c) 1996 @@ -66,7 +67,7 @@ #include <machine/frame.h> #include <machine/trap.h> -#include <sparc/sparc/cache.h> +#include <sparc/sparc/cpuvar.h> /* * Move pages from one kernel virtual address to another. @@ -114,12 +115,20 @@ dvma_malloc(len, kaddr, flags) { vm_offset_t kva; vm_offset_t dva; +#if defined(SUN4M) + extern int has_iocache; +#endif len = round_page(len); kva = (vm_offset_t)malloc(len, M_DEVBUF, flags); if (kva == NULL) return (NULL); +#if defined(SUN4M) + if (!has_iocache) +#endif + kvm_uncache((caddr_t)kva, len >> PGSHIFT); + *(vm_offset_t *)kaddr = kva; dva = dvma_mapin(kernel_map, kva, len, (flags & M_NOWAIT) ? 0 : 1); if (dva == NULL) { @@ -155,20 +164,17 @@ dvma_mapin(map, va, len, canwait) register int npf, s; register vm_offset_t pa; long off, pn; -#if defined(SUN4M) - extern int has_iocache; -#endif + vm_offset_t ova; + int olen; + + ova = va; + olen = len; off = (int)va & PGOFSET; va -= off; len = round_page(len + off); npf = btoc(len); -#if defined(SUN4M) - if (!has_iocache) - kvm_uncache((caddr_t)va, len >> PGSHIFT); -#endif - s = splimp(); for (;;) { @@ -194,7 +200,7 @@ dvma_mapin(map, va, len, canwait) pa = trunc_page(pa); #if defined(SUN4M) - if (cputyp == CPU_SUN4M) { + if (CPU_ISSUN4M) { iommu_enter(tva, pa); } else #endif @@ -217,6 +223,13 @@ dvma_mapin(map, va, len, canwait) tva += PAGE_SIZE; va += PAGE_SIZE; } + + /* + * XXX Only have to do this on write. + */ + if (CACHEINFO.c_vactype == VAC_WRITEBACK) /* XXX */ + cpuinfo.cache_flush((caddr_t)ova, olen); /* XXX */ + return kva + off; } @@ -246,8 +259,8 @@ dvma_mapout(kva, va, len) wakeup(dvmamap); splx(s); - if (vactype != VAC_NONE) - cache_flush((caddr_t)va, len); + if (CACHEINFO.c_vactype != VAC_NONE) + cpuinfo.cache_flush((caddr_t)va, len); } /* @@ -316,8 +329,8 @@ vunmapbuf(bp, sz) kmem_free_wakeup(kernel_map, trunc_page(kva), size); bp->b_data = bp->b_saveaddr; bp->b_saveaddr = NULL; - if (vactype != VAC_NONE) - cache_flush(bp->b_un.b_addr, bp->b_bcount - bp->b_resid); + if (CACHEINFO.c_vactype != VAC_NONE) + cpuinfo.cache_flush(bp->b_un.b_addr, bp->b_bcount - bp->b_resid); } |
