diff options
author | Jason Downs <downsj@cvs.openbsd.org> | 1997-08-08 08:27:49 +0000 |
---|---|---|
committer | Jason Downs <downsj@cvs.openbsd.org> | 1997-08-08 08:27:49 +0000 |
commit | c6af50ae96c114059441edde31a2879102e32d99 (patch) | |
tree | e77d44cd72b4d881fb3461d76bdd50f77adc0966 /sys/arch/sparc/dev | |
parent | c1492b0f5209b759b0ab6624db56b310c28e48e2 (diff) |
Mostly sync to NetBSD-current 970804.
GENERIC currently compiles and runs; some devices (isp) are not complete and
not yet enabled.
Diffstat (limited to 'sys/arch/sparc/dev')
63 files changed, 3683 insertions, 2993 deletions
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) */ /* |