diff options
42 files changed, 6559 insertions, 441 deletions
diff --git a/sys/arch/mvme88k/conf/GENERIC b/sys/arch/mvme88k/conf/GENERIC index 51b4d91c961..bccdcd6a65f 100644 --- a/sys/arch/mvme88k/conf/GENERIC +++ b/sys/arch/mvme88k/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.7 1998/12/15 06:02:54 smurph Exp $ +# $OpenBSD: GENERIC,v 1.8 1999/05/29 04:41:42 smurph Exp $ machine mvme88k @@ -17,7 +17,7 @@ config bsd swap generic mainbus0 at root # ------------------------------ mainbus devices ------------------------ #bugtty0 at mainbus0 -sram0 at mainbus0 addr 0xffe00000 +#sram0 at mainbus0 addr 0xffe00000 pcctwo0 at mainbus0 addr 0xfff00000 # ------------------------------ pcctwo devices ------------------------- clock0 at pcctwo0 ipl 5 diff --git a/sys/arch/mvme88k/conf/RAMDISK b/sys/arch/mvme88k/conf/RAMDISK index f51ea7ed1b0..21f811f6bf8 100644 --- a/sys/arch/mvme88k/conf/RAMDISK +++ b/sys/arch/mvme88k/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.1 1998/12/15 06:02:55 smurph Exp $ +# $OpenBSD: RAMDISK,v 1.2 1999/05/29 04:41:42 smurph Exp $ machine mvme88k @@ -17,7 +17,7 @@ config bsd root rd0 swap rd0 mainbus0 at root # ------------------------------ mainbus devices ------------------------ #bugtty0 at mainbus0 -sram0 at mainbus0 addr 0xffe00000 +#sram0 at mainbus0 addr 0xffe00000 pcctwo0 at mainbus0 addr 0xfff00000 # ------------------------------ pcctwo devices ------------------------- clock0 at pcctwo0 ipl 5 diff --git a/sys/arch/mvme88k/conf/files.mvme88k b/sys/arch/mvme88k/conf/files.mvme88k index 22cd80f2a4a..b739f0f14cd 100644 --- a/sys/arch/mvme88k/conf/files.mvme88k +++ b/sys/arch/mvme88k/conf/files.mvme88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.mvme88k,v 1.3 1999/02/09 06:36:24 smurph Exp $ +# $OpenBSD: files.mvme88k,v 1.4 1999/05/29 04:41:42 smurph Exp $ # maxpartitions 16 @@ -104,3 +104,16 @@ device ie: ifnet, ether attach ie at pcctwo: ifnet, ether file arch/mvme88k/dev/if_ie.c ie +device ve: ether, ifnet, ifmedia +attach ve at vmes +file arch/mvme88k/dev/if_ve.c ve + +device vx: tty +attach vx at vmes +file arch/mvme88k/dev/vx.c vx needs-count + +device vs: scsi +attach vs at vmes +file arch/mvme88k/dev/vs.c vs +file arch/mvme88k/dev/vsdma.c vs + diff --git a/sys/arch/mvme88k/dev/bugio.c b/sys/arch/mvme88k/dev/bugio.c index be68ef99c17..3a3d085dd5e 100644 --- a/sys/arch/mvme88k/dev/bugio.c +++ b/sys/arch/mvme88k/dev/bugio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bugio.c,v 1.2 1998/12/15 05:52:29 smurph Exp $ */ +/* $OpenBSD: bugio.c,v 1.3 1999/05/29 04:41:42 smurph Exp $ */ /* Copyright (c) 1998 Steve Murphree, Jr. */ #include <machine/bugio.h> @@ -10,6 +10,7 @@ #define DSKRD "0x0010" #define DSKWR "0x0011" #define DSKCFIG "0x0012" +#define NETCFG "0x001A" #define NETCTRL "0x001D" #define OUTCHR "0x0020" #define OUTSTR "0x0021" @@ -156,6 +157,15 @@ bugrtcrd(struct bugrtc *rtc) OSCTXT(); } +bugdelay(int delay) +{ + BUGCTXT(); + asm("or r2,r0,%0" : : "r" (delay)); + asm("or r9,r0, " DELAY); + asm("tb0 0,r0,0x1F0"); + OSCTXT(); +} + bugreturn(void) { BUGCTXT(); @@ -183,3 +193,47 @@ bugnetctrl(struct bugniocall *niocall) asm("tb0 0,r0,0x1F0"); /* OSCTXT();*/ } + +typedef struct netcnfgp { + unsigned int magic; + unsigned int nodemem; + unsigned int bfla; + unsigned int bfea; + unsigned int bfed; + unsigned int bfl; + unsigned int bfbo; + unsigned int tbuffer; + unsigned char cipa[4]; + unsigned char sipa[4]; + unsigned char netmask[4]; + unsigned char broadcast[4]; + unsigned char gipa[4]; + unsigned char bootp_retry; + unsigned char tftp_retry; + unsigned char bootp_ctl; + unsigned char cnfgp_ctl; + unsigned char filename[64]; + unsigned char argfname[64]; +} NETCNFGP; + +struct bugniotcall { + unsigned char clun; + unsigned char dlun; + unsigned char ci; + unsigned char cd; + NETCNFGP * netcfngp_p; + void * unused; +#define NIOT_READ (1<<0) +#define NIOT_WRITE (1<<1) +#define NIOT_NVRAM (1<<2) + unsigned long cntrlflag; +}; + +bugnetcfg(struct bugniotcall *niotcall) +{ +/* BUGCTXT();*/ + asm("or r2,r0,%0" : : "r" (niotcall)); + asm("or r9,r0, " NETCTRL); + asm("tb0 0,r0,0x1F0"); +/* OSCTXT();*/ +} diff --git a/sys/arch/mvme88k/dev/cl.c b/sys/arch/mvme88k/dev/cl.c index e568e853b99..6e738b5a4fa 100644 --- a/sys/arch/mvme88k/dev/cl.c +++ b/sys/arch/mvme88k/dev/cl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cl.c,v 1.3 1999/01/11 05:11:42 millert Exp $ */ +/* $OpenBSD: cl.c,v 1.4 1999/05/29 04:41:43 smurph Exp $ */ /* * Copyright (c) 1995 Dale Rahn. All rights reserved. @@ -42,34 +42,16 @@ #include <sys/systm.h> #include <sys/time.h> #include <sys/device.h> -/* #include <sys/queue.h> */ #include <machine/cpu.h> #include <machine/autoconf.h> #include <dev/cons.h> -#if defined(MVME187) #include <mvme88k/dev/clreg.h> -#else -#include <mvme68k/dev/clreg.h> -#endif #include <sys/syslog.h> #include "cl.h" - #include "pcctwo.h" - -#if NPCCTWO > 0 -#if defined(MVME187) #include <mvme88k/dev/pcctworeg.h> -#else -#include <mvme68k/dev/pcctworeg.h> -#endif -#endif - -#if defined(MVME187) #include <machine/psl.h> #define splcl() splx(IPL_TTY) -#else -#define splcl() spl3() -#endif /* min timeout 0xa, what is a good value */ #define CL_TIMEOUT 0x10 @@ -234,7 +216,8 @@ struct tty * cltty(dev) return sc->sc_cl[channel].tty; } -int clprobe(parent, self, aux) +int +clprobe(parent, self, aux) struct device *parent; void *self; void *aux; @@ -277,14 +260,14 @@ clattach(parent, self, aux) if ((u_char *)ca->ca_paddr == (u_char *)cl_cons.cl_paddr) { /* if this device is configured as console, * line cl_cons.channel is the console */ - sc->sc_cl[cl_cons.channel].cl_consio = 1; - printf(" console"); + sc->sc_cl[0].cl_consio = 1; + printf(" console "); } else { /* reset chip only if we are not console device */ /* wait for GFRCR */ } /* allow chip to settle before continuing */ - delay(100); + delay(800); /* set up global registers */ sc->cl_reg->cl_tpr = CL_TIMEOUT; @@ -357,25 +340,18 @@ clattach(parent, self, aux) sc->sc_ih_r.ih_arg = sc; sc->sc_ih_r.ih_ipl = ca->ca_ipl; sc->sc_ih_r.ih_wantframe = 0; - switch (ca->ca_bustype) { - case BUS_PCCTWO: - dopoll = 0; - intr_establish(PCC2_VECT + SRXEIRQ, &sc->sc_ih_e); - intr_establish(PCC2_VECT + SMOIRQ, &sc->sc_ih_m); - intr_establish(PCC2_VECT + STxIRQ, &sc->sc_ih_t); - intr_establish(PCC2_VECT + SRxIRQ, &sc->sc_ih_r); - sc->sc_pcctwo = ca->ca_master; - sc->sc_pcctwo->pcc2_sccerr = 0x01; /* clear errors */ - - /* enable all interrupts at ca_ipl */ - sc->sc_pcctwo->pcc2_sccirq = 0x10 | (ca->ca_ipl & 0x7); - sc->sc_pcctwo->pcc2_scctx = 0x10 | (ca->ca_ipl & 0x7); - sc->sc_pcctwo->pcc2_sccrx = 0x10 | (ca->ca_ipl & 0x7); - break; - default: - /* oops */ - panic ("cl driver on unknown bus"); - } + dopoll = 0; + intr_establish(PCC2_VECT + SRXEIRQ, &sc->sc_ih_e); + intr_establish(PCC2_VECT + SMOIRQ, &sc->sc_ih_m); + intr_establish(PCC2_VECT + STxIRQ, &sc->sc_ih_t); + intr_establish(PCC2_VECT + SRxIRQ, &sc->sc_ih_r); + sc->sc_pcctwo = ca->ca_master; + sc->sc_pcctwo->pcc2_sccerr = 0x01; /* clear errors */ + + /* enable all interrupts at ca_ipl */ + sc->sc_pcctwo->pcc2_sccirq = 0x10 | (ca->ca_ipl & 0x7); + sc->sc_pcctwo->pcc2_scctx = 0x10 | (ca->ca_ipl & 0x7); + sc->sc_pcctwo->pcc2_sccrx = 0x10 | (ca->ca_ipl & 0x7); evcnt_attach(&sc->sc_dev, "intr", &sc->sc_txintrcnt); evcnt_attach(&sc->sc_dev, "intr", &sc->sc_rxintrcnt); diff --git a/sys/arch/mvme88k/dev/clock.c b/sys/arch/mvme88k/dev/clock.c index 3535f83d231..80a022fc263 100644 --- a/sys/arch/mvme88k/dev/clock.c +++ b/sys/arch/mvme88k/dev/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.4 1998/12/15 05:52:29 smurph Exp $ */ +/* $OpenBSD: clock.c,v 1.5 1999/05/29 04:41:43 smurph Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -89,10 +89,13 @@ #include <machine/psl.h> #include <machine/autoconf.h> +#include <machine/bugio.h> #include <machine/cpu.h> #include <mvme88k/dev/pcctworeg.h> +#include <mvme88k/dev/vme.h> #include "pcctwo.h" +extern struct vme2reg *sys_vme2; /* * Statistics clock interval and variance, in usec. Variance must be a @@ -104,7 +107,7 @@ */ int statvar = 8192; int statmin; /* statclock interval - 1/2*variance */ -int timerok; +int timerok = 0; u_long delay_factor = 1; @@ -203,6 +206,7 @@ clockintr(arg) #if NBUGTTY > 0 bugtty_chkinput(); #endif /* NBUGTTY */ + timerok = 1; return (1); } @@ -287,18 +291,30 @@ statintr(cap) return (1); } + delay(us) register int us; { volatile register int c; - + unsigned long st; /* - * XXX MVME167 doesn't have a 3rd free-running timer, - * so we use a stupid loop. Fix the code to watch t1: - * the profiling timer. + * We use the vme system controller for the delay clock. + * Do not go to the real timer until vme device is present */ - c = 4 * us; - while (--c > 0) - ; - return (0); + if (sys_vme2 == NULL) { + c = 5 * us; + while (--c > 0); + return(0); + } + sys_vme2->vme2_irql1 |= (0 << VME2_IRQL1_TIC1SHIFT); + sys_vme2->vme2_t1count = 0; + sys_vme2->vme2_tctl |= (VME2_TCTL1_CEN | VME2_TCTL1_COVF); + + while (sys_vme2->vme2_t1count < us) + ; + sys_vme2->vme2_tctl &= ~(VME2_TCTL1_CEN | VME2_TCTL1_COVF); + return (0); } + + + diff --git a/sys/arch/mvme88k/dev/if_ie.c b/sys/arch/mvme88k/dev/if_ie.c index d3a5127976e..e8041125a1c 100644 --- a/sys/arch/mvme88k/dev/if_ie.c +++ b/sys/arch/mvme88k/dev/if_ie.c @@ -1,4 +1,4 @@ -/* $Id: if_ie.c,v 1.4 1999/03/03 22:10:32 jason Exp $ */ +/* $Id: if_ie.c,v 1.5 1999/05/29 04:41:43 smurph Exp $ */ /*- * Copyright (c) 1998 Steve Murphree, Jr. @@ -139,23 +139,8 @@ Mode of operation: #include <machine/autoconf.h> #include <machine/cpu.h> #include <machine/pmap.h> - -#if !defined(MVME187) -#include "mc.h" -#endif #include "pcctwo.h" - -#if NMC > 0 -#include <mvme68k/dev/mcreg.h> -#endif -#if NPCCTWO > 0 -#if defined(MVME187) #include <mvme88k/dev/pcctworeg.h> -#else -#include <mvme68k/dev/pcctworeg.h> -#endif -#endif - #include <mvme88k/dev/if_ie.h> #include <mvme88k/dev/i82586.h> #include <machine/board.h> @@ -285,12 +270,7 @@ struct ie_softc { #ifdef IEDEBUG int sc_debug; #endif -#if NMC > 0 - struct mcreg *sc_mc; -#endif -#if NPCCTWO > 0 struct pcctworeg *sc_pcc2; -#endif }; static void ie_obreset __P((struct ie_softc *)); @@ -391,7 +371,6 @@ iematch(parent, vcf, args) int ret; if ((ret = badvaddr(IIOV(ca->ca_vaddr), 1)) <=0){ - printf("==> ie: failed address check returning %ld.\n", ret); return(0); } return (1); @@ -462,14 +441,16 @@ ieattach(parent, self, aux) sc->sc_msize = etherlen; sc->sc_reg = ca->ca_vaddr; ieo = (volatile struct ieob *) sc->sc_reg; - - /* Are we the boot device? */ - if (ca->ca_paddr == bootaddr) - bootdv = self; - + + /* Are we the boot device? */ + if (ca->ca_paddr == bootaddr) + bootdv = self; + + /* get the first avaliable etherbuf */ sc->sc_maddr = etherbuf; /* maddr = vaddr */ + if (sc->sc_maddr == NULL) panic("ie: too many ethernet boards"); pa = pmap_extract(pmap_kernel(), (vm_offset_t)sc->sc_maddr); - if (pa == 0) panic("ie pmap_extract"); + if (pa == 0) panic("ie: pmap_extract"); sc->sc_iobase = (caddr_t)pa; /* iobase = paddr (24 bit) */ /*printf("maddrP %x iobaseV %x\n", sc->sc_maddr, sc->sc_iobase);*/ @@ -531,29 +512,13 @@ ieattach(parent, self, aux) sc->sc_failih.ih_arg = sc; sc->sc_failih.ih_ipl = pri; - switch (sc->sc_bustype) { -#if NMC > 0 - case BUS_MC: - mcintr_establish(MCV_IE, &sc->sc_ih); - sc->sc_mc = (struct mcreg *)ca->ca_master; - sc->sc_mc->mc_ieirq = pri | MC_SC_SNOOP | MC_IRQ_IEN | - MC_IRQ_ICLR; - mcintr_establish(MCV_IEFAIL, &sc->sc_failih); - sc->sc_mc->mc_iefailirq = pri | MC_IRQ_IEN | MC_IRQ_ICLR; - break; -#endif -#if NPCCTWO > 0 - case BUS_PCCTWO: - pcctwointr_establish(PCC2V_IE, &sc->sc_ih); - sc->sc_pcc2 = (struct pcctworeg *)ca->ca_master; - sc->sc_pcc2->pcc2_ieirq = pri | PCC2_SC_SNOOP | - PCC2_IRQ_IEN | PCC2_IRQ_ICLR; - pcctwointr_establish(PCC2V_IEFAIL, &sc->sc_failih); - sc->sc_pcc2->pcc2_iefailirq = pri | PCC2_IRQ_IEN | - PCC2_IRQ_ICLR; - break; -#endif - } + pcctwointr_establish(PCC2V_IE, &sc->sc_ih); + sc->sc_pcc2 = (struct pcctworeg *)ca->ca_master; + sc->sc_pcc2->pcc2_ieirq = pri | PCC2_SC_SNOOP | + PCC2_IRQ_IEN | PCC2_IRQ_ICLR; + pcctwointr_establish(PCC2V_IEFAIL, &sc->sc_failih); + sc->sc_pcc2->pcc2_iefailirq = pri | PCC2_IRQ_IEN | + PCC2_IRQ_ICLR; evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt); } @@ -580,22 +545,9 @@ void *v; { struct ie_softc *sc = v; - switch (sc->sc_bustype) { -#if NMC > 0 - case BUS_MC: - sc->sc_mc->mc_ieirq |= MC_IRQ_ICLR; /* safe: clear irq */ - sc->sc_mc->mc_iefailirq |= MC_IRQ_ICLR; /* clear failure */ - sc->sc_mc->mc_ieerr = MC_IEERR_SCLR; /* reset error */ - break; -#endif -#if NPCCTWO > 0 - case BUS_PCCTWO: - sc->sc_pcc2->pcc2_ieirq |= PCC2_IRQ_ICLR; /* safe: clear irq */ - sc->sc_pcc2->pcc2_iefailirq |= PCC2_IRQ_ICLR; /* clear failure */ - sc->sc_pcc2->pcc2_ieerr = PCC2_IEERR_SCLR; /* reset error */ - break; -#endif - } + sc->sc_pcc2->pcc2_ieirq |= PCC2_IRQ_ICLR; /* safe: clear irq */ + sc->sc_pcc2->pcc2_iefailirq |= PCC2_IRQ_ICLR; /* clear failure */ + sc->sc_pcc2->pcc2_ieerr = PCC2_IEERR_SCLR; /* reset error */ iereset(sc); return (1); @@ -617,18 +569,7 @@ void *v; loop: /* Ack interrupts FIRST in case we receive more during the ISR. */ ie_ack(sc, IE_ST_WHENCE & status); - switch (sc->sc_bustype) { -#if NMC > 0 - case BUS_MC: - sc->sc_mc->mc_ieirq |= MC_IRQ_ICLR; /* clear irq */ - break; -#endif -#if NPCCTWO > 0 - case BUS_PCCTWO: - sc->sc_pcc2->pcc2_ieirq |= PCC2_IRQ_ICLR; /* clear irq */ - break; -#endif - } + sc->sc_pcc2->pcc2_ieirq |= PCC2_IRQ_ICLR; /* clear irq */ if (status & (IE_ST_RECV | IE_ST_RNR)) { #ifdef IEDEBUG diff --git a/sys/arch/mvme88k/dev/if_ve.c b/sys/arch/mvme88k/dev/if_ve.c new file mode 100644 index 00000000000..502be8e6143 --- /dev/null +++ b/sys/arch/mvme88k/dev/if_ve.c @@ -0,0 +1,1345 @@ +/* $OpenBSD: if_ve.c,v 1.1 1999/05/29 04:41:43 smurph Exp $ */ +/*- + * Copyright (c) 1999 Steve Murphree, Jr. + * Copyright (c) 1982, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* if_ve.c - Motorola MVME376 vme bus ethernet driver. Based on if_le.c */ + +#include "bpfilter.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/syslog.h> +#include <sys/socket.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/ioctl.h> +#include <sys/errno.h> + +#include <net/if.h> +#include <net/if_media.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/if_ether.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#endif + +#include <net/if_media.h> + +#if NBPFILTER > 0 +#include <net/bpf.h> +#include <net/bpfdesc.h> +#endif + +#include <vm/vm.h> +#include <vm/vm_map.h> +#include <vm/vm_kern.h> + +#include <machine/autoconf.h> +#include <machine/cpu.h> +#include <machine/bugio.h> + +#include <mvme88k/dev/if_vereg.h> +#include <mvme88k/dev/if_vevar.h> +#include <mvme88k/dev/pcctworeg.h> +#include <mvme88k/dev/vme.h> + +#define LEDEBUG 1 + + +#ifdef LEDEBUG +void ve_recv_print __P((struct vam7990_softc *, int)); +void ve_xmit_print __P((struct vam7990_softc *, int)); +#endif + +integrate void ve_rint __P((struct vam7990_softc *)); +integrate void ve_tint __P((struct vam7990_softc *)); + +integrate int ve_put __P((struct vam7990_softc *, int, struct mbuf *)); +integrate struct mbuf *ve_get __P((struct vam7990_softc *, int, int)); +integrate void ve_read __P((struct vam7990_softc *, int, int)); + +hide void ve_shutdown __P((void *)); + +#define ifp (&sc->sc_arpcom.ac_if) +#ifndef ETHER_CMP +#define ETHER_CMP(a, b) bcmp((a), (b), ETHER_ADDR_LEN) +#endif +#define LANCE_REVC_BUG 1 +/* + * 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. + * This structure contains the output queue for the interface, its address, ... + */ +struct ve_softc { + struct vam7990_softc sc_am7990; /* glue to MI code */ + struct intrhand sc_ih; /* interrupt vectoring */ + struct vereg1 *sc_r1; /* LANCE registers */ + u_short csr; /* Control/Status reg image */ + u_long board_addr; + struct evcnt sc_intrcnt; + struct evcnt sc_errcnt; + struct vme2reg *sc_vme2; + u_char sc_ipl; + u_char sc_vec; + int sc_flags; +}; + +struct cfdriver ve_cd = { + NULL, "ve", DV_IFNET +}; + + +/* autoconfiguration driver */ +void veattach(struct device *, struct device *, void *); +int vematch(struct device *, void *, void *); +void veetheraddr(struct vam7990_softc *sc); + +struct cfattach ve_ca = { + sizeof(struct ve_softc), vematch, veattach +}; + +hide void vewrcsr __P((struct vam7990_softc *, u_int16_t, u_int16_t)); +hide u_int16_t verdcsr __P((struct vam7990_softc *, u_int16_t)); + +/* send command to the nvram controller */ +nvram_cmd(sc, cmd, addr ) +struct vam7990_softc *sc; +u_char cmd; +u_short addr; +{ + int i; + u_char rcmd = 0; + u_char rcmd2= 0; + struct vereg1 *reg1 = ((struct ve_softc *)sc)->sc_r1; + + rcmd = addr; + rcmd = rcmd << 3; + rcmd |= cmd; + for(i=0;i<8;i++){ + reg1->ver1_ear=((cmd|(addr<<1))>>i); + CDELAY; + } +} + +/* read nvram one bit at a time */ +u_int16_t +nvram_read(sc, nvram_addr) +struct vam7990_softc *sc; +u_char nvram_addr; +{ + u_short val = 0, mask = 0x04000; + u_int16_t wbit; + /* these used by macros DO NOT CHANGE!*/ + int i; + struct vereg1 *reg1 = ((struct ve_softc *)sc)->sc_r1; + sc->csr = 0x4f; + ENABLE_NVRAM; + nvram_cmd(sc, NVRAM_RCL, 0); + DISABLE_NVRAM; + CDELAY; + ENABLE_NVRAM; + nvram_cmd(sc, NVRAM_READ, nvram_addr); + for (wbit=0; wbit<15; wbit++) { + (reg1->ver1_ear & 0x01) ? (val = (val | mask)) : (val = (val & (~mask))); + mask = mask>>1; + CDELAY; + } + (reg1->ver1_ear & 0x01) ? (val = (val | 0x8000)) : (val = (val & 0x7FFF)); + CDELAY; + DISABLE_NVRAM; + return (val); +} + +hide void +vewrcsr(sc, port, val) + struct vam7990_softc *sc; + u_int16_t port, val; +{ + register struct vereg1 *ve1 = ((struct ve_softc *)sc)->sc_r1; + + ve1->ver1_rap = port; + ve1->ver1_rdp = val; +} + +hide u_int16_t +verdcsr(sc, port) + struct vam7990_softc *sc; + u_int16_t port; +{ + register struct vereg1 *ve1 = ((struct ve_softc *)sc)->sc_r1; + u_int16_t val; + + ve1->ver1_rap = port; + val = ve1->ver1_rdp; + return (val); +} + +/* reset MVME376, set ipl and vec */ +void +vereset(sc) + struct vam7990_softc *sc; +{ + register struct vereg1 *reg1 = ((struct ve_softc *)sc)->sc_r1; + u_char vec = ((struct ve_softc *)sc)->sc_vec; + u_char ipl = ((struct ve_softc *)sc)->sc_ipl; + sc->csr = 0x4f; + WRITE_CSR_AND( ~ipl ); + SET_VEC(vec); + return; +} + +/* ack the intrrupt by reenableling interrupts */ +void +ve_ackint(sc) +struct vam7990_softc *sc; +{ + register struct vereg1 *reg1 = ((struct ve_softc *)sc)->sc_r1; + ENABLE_INTR; +} + +int +vematch(parent, vcf, args) + struct device *parent; + void *vcf, *args; +{ + + struct confargs *ca = args; + if (!badvaddr(ca->ca_vaddr, 1)) { + if (ca->ca_vec & 0x03) { + printf("ve: bad vector 0x%x\n", ca->ca_vec); + return (0); + } + return(1); + } else { + return (0); + } +} + +/* + * Interface exists: make available by filling in network interface + * record. System will initialize the interface when it is ready + * to accept packets. + */ +void +veattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + register struct ve_softc *lesc = (struct ve_softc *)self; + struct vam7990_softc *sc = &lesc->sc_am7990; + struct confargs *ca = aux; + register int a; + int pri = ca->ca_ipl; + caddr_t addr; + + char *cp; + int i, ipl; + + addr = ca->ca_vaddr; + + if (addr == 0) { + printf("\n%s: can't map LANCE registers\n", + sc->sc_dev.dv_xname); + return; + } + + /* Are we the boot device? */ + if (ca->ca_paddr == bootaddr) + bootdv = self; + + lesc->sc_r1 = (struct vereg1 *)ca->ca_vaddr; + lesc->sc_ipl = ca->ca_ipl; + lesc->sc_vec = ca->ca_vec; + + /* get the first avaliable etherbuf */ + switch ((int)ca->ca_paddr) { + case 0xFFFF1200: + addr = (caddr_t)0xFD6C0000; + break; + case 0xFFFF1400: + addr = (caddr_t)0xFD700000; + break; + case 0xFFFF1600: + addr = (caddr_t)0xFD740000; + break; + default: + panic("ve: invalid address"); + } + sc->sc_mem = (void *)mapiodev(addr, LEMEMSIZE); + if (sc->sc_mem == NULL) panic("ve: no more memory in external I/O map"); + sc->sc_memsize = LEMEMSIZE; + sc->sc_conf3 = LE_C3_BSWP; + sc->sc_addr = kvtop(sc->sc_mem); + + /* get ether address via bug call */ + veetheraddr(sc); + + evcnt_attach(&sc->sc_dev, "intr", &lesc->sc_intrcnt); + evcnt_attach(&sc->sc_dev, "errs", &lesc->sc_errcnt); + + sc->sc_copytodesc = ve_copytobuf_contig; + sc->sc_copyfromdesc = ve_copyfrombuf_contig; + sc->sc_copytobuf = ve_copytobuf_contig; + sc->sc_copyfrombuf = ve_copyfrombuf_contig; + sc->sc_zerobuf = ve_zerobuf_contig; + + sc->sc_rdcsr = verdcsr; + sc->sc_wrcsr = vewrcsr; + sc->sc_hwreset = vereset; + sc->sc_hwinit = NULL; + vereset(sc); + + ve_config(sc); + + /* connect the interrupt */ + lesc->sc_ih.ih_fn = ve_intr; + lesc->sc_ih.ih_arg = sc; + lesc->sc_ih.ih_ipl = pri; + vmeintr_establish(ca->ca_vec + 0, &lesc->sc_ih); +} + +void +veetheraddr(sc) +struct vam7990_softc *sc; +{ + u_char * cp = sc->sc_arpcom.ac_enaddr; + u_int16_t ival[3]; + u_char i; + + for (i=0; i<3; i++) { + ival[i] = nvram_read(sc, i); + } + memcpy(cp, &ival[0], 6); +} + +void +ve_config(sc) + struct vam7990_softc *sc; +{ + int mem; + + /* Make sure the chip is stopped. */ + ve_stop(sc); + + /* Initialize ifnet structure. */ + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; + ifp->if_start = ve_start; + ifp->if_ioctl = ve_ioctl; + ifp->if_watchdog = ve_watchdog; + ifp->if_flags = + IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; +#ifdef LANCE_REVC_BUG + ifp->if_flags &= ~IFF_MULTICAST; +#endif + + /* Attach the interface. */ + if_attach(ifp); + ether_ifattach(ifp); + +#if NBPFILTER > 0 + bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); +#endif + + if (sc->sc_memsize > 262144) + sc->sc_memsize = 262144; + + switch (sc->sc_memsize) { + case 8192: + sc->sc_nrbuf = 4; + sc->sc_ntbuf = 1; + break; + case 16384: + sc->sc_nrbuf = 8; + sc->sc_ntbuf = 2; + break; + case 32768: + sc->sc_nrbuf = 16; + sc->sc_ntbuf = 4; + break; + case 65536: + sc->sc_nrbuf = 32; + sc->sc_ntbuf = 8; + break; + case 131072: + sc->sc_nrbuf = 64; + sc->sc_ntbuf = 16; + break; + case 262144: + sc->sc_nrbuf = 128; + sc->sc_ntbuf = 32; + break; + default: + panic("ve_config: weird memory size %d", sc->sc_memsize); + } + + printf("\n%s: address %s\n", sc->sc_dev.dv_xname, + ether_sprintf(sc->sc_arpcom.ac_enaddr)); + printf("%s: %d receive buffers, %d transmit buffers\n", + sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf); + + sc->sc_sh = shutdownhook_establish(ve_shutdown, sc); + if (sc->sc_sh == NULL) + panic("ve_config: can't establish shutdownhook"); + + mem = 0; + sc->sc_initaddr = mem; + mem += sizeof(struct veinit); + sc->sc_rmdaddr = mem; + mem += sizeof(struct vermd) * sc->sc_nrbuf; + sc->sc_tmdaddr = mem; + mem += sizeof(struct vetmd) * sc->sc_ntbuf; + sc->sc_rbufaddr = mem; + mem += LEBLEN * sc->sc_nrbuf; + sc->sc_tbufaddr = mem; + mem += LEBLEN * sc->sc_ntbuf; +#ifdef notyet + if (mem > ...) + panic(...); +#endif +} + +void +ve_reset(sc) + struct vam7990_softc *sc; +{ + int s; + + s = splimp(); + ve_init(sc); + splx(s); +} + +/* + * Set up the initialization block and the descriptor rings. + */ +void +ve_meminit(sc) + register struct vam7990_softc *sc; +{ + u_long a; + int bix; + struct veinit init; + struct vermd rmd; + struct vetmd tmd; + +#if NBPFILTER > 0 + if (ifp->if_flags & IFF_PROMISC) + init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM; + else +#endif + init.init_mode = LE_MODE_NORMAL; + init.init_padr[0] = + (sc->sc_arpcom.ac_enaddr[1] << 8) | sc->sc_arpcom.ac_enaddr[0]; + init.init_padr[1] = + (sc->sc_arpcom.ac_enaddr[3] << 8) | sc->sc_arpcom.ac_enaddr[2]; + init.init_padr[2] = + (sc->sc_arpcom.ac_enaddr[5] << 8) | sc->sc_arpcom.ac_enaddr[4]; + ve_setladrf(&sc->sc_arpcom, init.init_ladrf); + + sc->sc_last_rd = 0; + sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; + + a = sc->sc_addr + LE_RMDADDR(sc, 0); + init.init_rdra = a; + init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13); + + a = sc->sc_addr + LE_TMDADDR(sc, 0); + init.init_tdra = a; + init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13); + + (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); + + /* + * Set up receive ring descriptors. + */ + for (bix = 0; bix < sc->sc_nrbuf; bix++) { + a = sc->sc_addr + LE_RBUFADDR(sc, bix); + rmd.rmd0 = a; + rmd.rmd1_hadr = a >> 16; + rmd.rmd1_bits = LE_R1_OWN; + rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; + rmd.rmd3 = 0; + (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), + sizeof(rmd)); + } + + /* + * Set up transmit ring descriptors. + */ + for (bix = 0; bix < sc->sc_ntbuf; bix++) { + a = sc->sc_addr + LE_TBUFADDR(sc, bix); + tmd.tmd0 = a; + tmd.tmd1_hadr = a >> 16; + tmd.tmd1_bits = 0; + tmd.tmd2 = 0 | LE_XMD2_ONES; + tmd.tmd3 = 0; + (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), + sizeof(tmd)); + } +} + +void +ve_stop(sc) + struct vam7990_softc *sc; +{ + + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); +} + +/* + * Initialization of interface; set up initialization block + * and transmit/receive descriptor rings. + */ +void +ve_init(sc) + register struct vam7990_softc *sc; +{ + register int timo; + u_long a; + + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); + DELAY(100); + + /* Newer LANCE chips have a reset register */ + if (sc->sc_hwreset) + (*sc->sc_hwreset)(sc); + + /* Set the correct byte swapping mode, etc. */ + (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3); + + /* Set up LANCE init block. */ + ve_meminit(sc); + + /* Give LANCE the physical address of its init block. */ + a = sc->sc_addr + LE_INITADDR(sc); + (*sc->sc_wrcsr)(sc, LE_CSR1, a); + (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16); + + /* Try to initialize the LANCE. */ + DELAY(100); + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT); + + /* Wait for initialization to finish. */ + for (timo = 100000; timo; timo--) + if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) + break; + + if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) { + /* Start the LANCE. */ + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT | + LE_C0_IDON); + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + ifp->if_timer = 0; + ve_start(ifp); + } else + printf("%s: controller failed to initialize\n", sc->sc_dev.dv_xname); + if (sc->sc_hwinit) + (*sc->sc_hwinit)(sc); +} + +/* + * Routine to copy from mbuf chain to transmit buffer in + * network buffer memory. + */ +integrate int +ve_put(sc, boff, m) + struct vam7990_softc *sc; + int boff; + register struct mbuf *m; +{ + register struct mbuf *n; + register int len, tlen = 0; + + for (; m; m = n) { + len = m->m_len; + if (len == 0) { + MFREE(m, n); + continue; + } + (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len); + boff += len; + tlen += len; + MFREE(m, n); + } + if (tlen < LEMINSIZE) { + (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen); + tlen = LEMINSIZE; + } + return (tlen); +} + +/* + * Pull data off an interface. + * Len is length of data, with local net header stripped. + * We copy the data into mbufs. When full cluster sized units are present + * we copy into clusters. + */ +integrate struct mbuf * +ve_get(sc, boff, totlen) + struct vam7990_softc *sc; + int boff, totlen; +{ + register struct mbuf *m; + struct mbuf *top, **mp; + int len, pad; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) + return (0); + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header); + m->m_data += pad; + len = MHLEN - pad; + top = 0; + mp = ⊤ + + while (totlen > 0) { + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + return 0; + } + len = MLEN; + } + if (top && totlen >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + len = MCLBYTES; + } + m->m_len = len = min(totlen, len); + (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len); + boff += len; + totlen -= len; + *mp = m; + mp = &m->m_next; + } + + return (top); +} + +/* + * Pass a packet to the higher levels. + */ +integrate void +ve_read(sc, boff, len) + register struct vam7990_softc *sc; + int boff, len; +{ + struct mbuf *m; + struct ether_header *eh; + + if (len <= sizeof(struct ether_header) || + len > ETHERMTU + sizeof(struct ether_header)) { +#ifdef LEDEBUG + printf("%s: invalid packet size %d; dropping\n", + sc->sc_dev.dv_xname, len); +#endif + ifp->if_ierrors++; + return; + } + + /* Pull packet off interface. */ + m = ve_get(sc, boff, len); + if (m == 0) { + ifp->if_ierrors++; + return; + } + + ifp->if_ipackets++; + + /* We assume that the header fit entirely in one mbuf. */ + eh = mtod(m, struct ether_header *); + +#if NBPFILTER > 0 + /* + * Check if there's a BPF listener on this interface. + * If so, hand off the raw packet to BPF. + */ + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m); +#endif + +#ifdef LANCE_REVC_BUG + /* + * The old LANCE (Rev. C) chips have a bug which causes + * garbage to be inserted in front of the received packet. + * The work-around is to ignore packets with an invalid + * destination address (garbage will usually not match). + * Of course, this precludes multicast support... + */ + if (ETHER_CMP(eh->ether_dhost, sc->sc_arpcom.ac_enaddr) && + ETHER_CMP(eh->ether_dhost, etherbroadcastaddr)) { + m_freem(m); + return; + } +#endif + + /* Pass the packet up, with the ether header sort-of removed. */ + m_adj(m, sizeof(struct ether_header)); + ether_input(ifp, eh, m); +} + +integrate void +ve_rint(sc) + struct vam7990_softc *sc; +{ + register int bix; + int rp; + struct vermd rmd; + + bix = sc->sc_last_rd; + + /* Process all buffers with valid data. */ + for (;;) { + rp = LE_RMDADDR(sc, bix); + (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); + + if (rmd.rmd1_bits & LE_R1_OWN) + break; + + if (rmd.rmd1_bits & LE_R1_ERR) { + if (rmd.rmd1_bits & LE_R1_ENP) { +#ifdef LEDEBUG + if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) { + if (rmd.rmd1_bits & LE_R1_FRAM) + printf("%s: framing error\n", + sc->sc_dev.dv_xname); + if (rmd.rmd1_bits & LE_R1_CRC) + printf("%s: crc mismatch\n", + sc->sc_dev.dv_xname); + } +#endif + } else { + if (rmd.rmd1_bits & LE_R1_OFLO) + printf("%s: overflow\n", + sc->sc_dev.dv_xname); + } + if (rmd.rmd1_bits & LE_R1_BUFF) + printf("%s: receive buffer error\n", + sc->sc_dev.dv_xname); + ifp->if_ierrors++; + } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) != + (LE_R1_STP | LE_R1_ENP)) { + printf("%s: dropping chained buffer\n", + sc->sc_dev.dv_xname); + ifp->if_ierrors++; + } else { +#ifdef LEDEBUG + if (sc->sc_debug) + ve_recv_print(sc, sc->sc_last_rd); +#endif + ve_read(sc, LE_RBUFADDR(sc, bix), + (int)rmd.rmd3 - 4); + } + + rmd.rmd1_bits = LE_R1_OWN; + rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; + rmd.rmd3 = 0; + (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); + +#ifdef LEDEBUG + if (sc->sc_debug) + printf("sc->sc_last_rd = %x, rmd: " + "ladr %04x, hadr %02x, flags %02x, " + "bcnt %04x, mcnt %04x\n", + sc->sc_last_rd, + rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, + rmd.rmd2, rmd.rmd3); +#endif + + if (++bix == sc->sc_nrbuf) + bix = 0; + } + + sc->sc_last_rd = bix; +} + +integrate void +ve_tint(sc) + register struct vam7990_softc *sc; +{ + register int bix; + struct vetmd tmd; + + bix = sc->sc_first_td; + + for (;;) { + if (sc->sc_no_td <= 0) + break; + + (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), + sizeof(tmd)); + +#ifdef LEDEBUG + if (sc->sc_debug) + printf("trans tmd: " + "ladr %04x, hadr %02x, flags %02x, " + "bcnt %04x, mcnt %04x\n", + tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, + tmd.tmd2, tmd.tmd3); +#endif + + if (tmd.tmd1_bits & LE_T1_OWN) + break; + + ifp->if_flags &= ~IFF_OACTIVE; + + if (tmd.tmd1_bits & LE_T1_ERR) { + if (tmd.tmd3 & LE_T3_BUFF) + printf("%s: transmit buffer error\n", + sc->sc_dev.dv_xname); + else if (tmd.tmd3 & LE_T3_UFLO) + printf("%s: underflow\n", sc->sc_dev.dv_xname); + if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) { + ve_reset(sc); + return; + } + if (tmd.tmd3 & LE_T3_LCAR) { + if (sc->sc_nocarrier) + (*sc->sc_nocarrier)(sc); + else + printf("%s: lost carrier\n", + sc->sc_dev.dv_xname); + } + if (tmd.tmd3 & LE_T3_LCOL) + ifp->if_collisions++; + if (tmd.tmd3 & LE_T3_RTRY) { + printf("%s: excessive collisions, tdr %d\n", + sc->sc_dev.dv_xname, + tmd.tmd3 & LE_T3_TDR_MASK); + ifp->if_collisions += 16; + } + ifp->if_oerrors++; + } else { + if (tmd.tmd1_bits & LE_T1_ONE) + ifp->if_collisions++; + else if (tmd.tmd1_bits & LE_T1_MORE) + /* Real number is unknown. */ + ifp->if_collisions += 2; + ifp->if_opackets++; + } + + if (++bix == sc->sc_ntbuf) + bix = 0; + + --sc->sc_no_td; + } + + sc->sc_first_td = bix; + + ve_start(ifp); + + if (sc->sc_no_td == 0) + ifp->if_timer = 0; +} + +/* + * Controller interrupt. + */ +int +ve_intr(arg) + register void *arg; +{ + register struct vam7990_softc *sc = arg; + register u_int16_t isr; + + isr = (*sc->sc_rdcsr)(sc, LE_CSR0); +#ifdef LEDEBUG + if (sc->sc_debug) + printf("%s: ve_intr entering with isr=%04x\n", + sc->sc_dev.dv_xname, isr); +#endif + if ((isr & LE_C0_INTR) == 0) + return (0); + + /* clear the interrupting condition */ + (*sc->sc_wrcsr)(sc, LE_CSR0, + isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR | + LE_C0_RINT | LE_C0_TINT | LE_C0_IDON)); + if (isr & LE_C0_ERR) { + if (isr & LE_C0_BABL) { +#ifdef LEDEBUG + printf("%s: babble\n", sc->sc_dev.dv_xname); +#endif + ifp->if_oerrors++; + } +#if 0 + if (isr & LE_C0_CERR) { + printf("%s: collision error\n", sc->sc_dev.dv_xname); + ifp->if_collisions++; + } +#endif + if (isr & LE_C0_MISS) { +#ifdef LEDEBUG + printf("%s: missed packet\n", sc->sc_dev.dv_xname); +#endif + ifp->if_ierrors++; + } + if (isr & LE_C0_MERR) { + printf("%s: memory error\n", sc->sc_dev.dv_xname); + ve_reset(sc); + return (1); + } + } + + if ((isr & LE_C0_RXON) == 0) { + printf("%s: receiver disabled\n", sc->sc_dev.dv_xname); + ifp->if_ierrors++; + ve_reset(sc); + return (1); + } + if ((isr & LE_C0_TXON) == 0) { + printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname); + ifp->if_oerrors++; + ve_reset(sc); + return (1); + } + + if (isr & LE_C0_RINT) + ve_rint(sc); + if (isr & LE_C0_TINT) + ve_tint(sc); + ve_ackint(sc); + return (1); +} + +#undef ifp + +void +ve_watchdog(ifp) + struct ifnet *ifp; +{ + struct vam7990_softc *sc = ifp->if_softc; + + log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); + ++ifp->if_oerrors; + + ve_reset(sc); +} + +/* + * Setup output on interface. + * Get another datagram to send off of the interface queue, and map it to the + * interface before starting the output. + * Called only at splimp or interrupt level. + */ +void +ve_start(ifp) + register struct ifnet *ifp; +{ + register struct vam7990_softc *sc = ifp->if_softc; + register int bix; + register struct mbuf *m; + struct vetmd tmd; + int rp; + int len; + + if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) + return; + + bix = sc->sc_last_td; + + for (;;) { + rp = LE_TMDADDR(sc, bix); + (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); + + if (tmd.tmd1_bits & LE_T1_OWN) { + ifp->if_flags |= IFF_OACTIVE; + printf("missing buffer, no_td = %d, last_td = %d\n", + sc->sc_no_td, sc->sc_last_td); + } + + IF_DEQUEUE(&ifp->if_snd, m); + if (m == 0) + break; + +#if NBPFILTER > 0 + /* + * If BPF is listening on this interface, let it see the packet + * before we commit it to the wire. + */ + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m); +#endif + + /* + * Copy the mbuf chain into the transmit buffer. + */ + len = ve_put(sc, LE_TBUFADDR(sc, bix), m); + +#ifdef LEDEBUG + if (len > ETHERMTU + sizeof(struct ether_header)) + printf("packet length %d\n", len); +#endif + + ifp->if_timer = 5; + + /* + * Init transmit registers, and set transmit start flag. + */ + tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP; + tmd.tmd2 = -len | LE_XMD2_ONES; + tmd.tmd3 = 0; + + (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); + +#ifdef LEDEBUG + if (sc->sc_debug) + ve_xmit_print(sc, sc->sc_last_td); +#endif + + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); + + if (++bix == sc->sc_ntbuf) + bix = 0; + + if (++sc->sc_no_td == sc->sc_ntbuf) { + ifp->if_flags |= IFF_OACTIVE; + break; + } + + } + + sc->sc_last_td = bix; +} + +/* + * Process an ioctl request. + */ +int +ve_ioctl(ifp, cmd, data) + register struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ + register struct vam7990_softc *sc = ifp->if_softc; + struct ifaddr *ifa = (struct ifaddr *)data; + struct ifreq *ifr = (struct ifreq *)data; + int s, error = 0; + + s = splimp(); + + if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) { + splx(s); + return error; + } + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + ve_init(sc); + arp_ifinit(&sc->sc_arpcom, ifa); + break; +#endif + default: + ve_init(sc); + break; + } + break; + + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && + (ifp->if_flags & IFF_RUNNING) != 0) { + /* + * If interface is marked down and it is running, then + * stop it. + */ + ve_stop(sc); + ifp->if_flags &= ~IFF_RUNNING; + } else if ((ifp->if_flags & IFF_UP) != 0 && + (ifp->if_flags & IFF_RUNNING) == 0) { + /* + * If interface is marked up and it is stopped, then + * start it. + */ + ve_init(sc); + } else { + /* + * Reset the interface to pick up changes in any other + * flags that affect hardware registers. + */ + /*ve_stop(sc);*/ + ve_init(sc); + } +#ifdef LEDEBUG + if (ifp->if_flags & IFF_DEBUG) + sc->sc_debug = 1; + else + sc->sc_debug = 0; +#endif + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + error = (cmd == SIOCADDMULTI) ? + ether_addmulti(ifr, &sc->sc_arpcom) : + ether_delmulti(ifr, &sc->sc_arpcom); + + if (error == ENETRESET) { + /* + * Multicast list has changed; set the hardware filter + * accordingly. + */ + ve_reset(sc); + error = 0; + } + break; + + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + if (sc->sc_hasifmedia) + error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd); + else + error = EINVAL; + break; + + default: + error = EINVAL; + break; + } + + splx(s); + return (error); +} + +hide void +ve_shutdown(arg) + void *arg; +{ + + ve_stop((struct vam7990_softc *)arg); +} + +#ifdef LEDEBUG +void +ve_recv_print(sc, no) + struct vam7990_softc *sc; + int no; +{ + struct vermd rmd; + u_int16_t len; + struct ether_header eh; + + (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); + len = rmd.rmd3; + printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no, + len); + printf("%s: status %04x\n", sc->sc_dev.dv_xname, + (*sc->sc_rdcsr)(sc, LE_CSR0)); + printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", + sc->sc_dev.dv_xname, + rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3); + if (len >= sizeof(eh)) { + (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); + printf("%s: dst %s", sc->sc_dev.dv_xname, + ether_sprintf(eh.ether_dhost)); + printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), + ntohs(eh.ether_type)); + } +} + +void +ve_xmit_print(sc, no) + struct vam7990_softc *sc; + int no; +{ + struct vetmd tmd; + u_int16_t len; + struct ether_header eh; + + (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); + len = -tmd.tmd2; + printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no, + len); + printf("%s: status %04x\n", sc->sc_dev.dv_xname, + (*sc->sc_rdcsr)(sc, LE_CSR0)); + printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", + sc->sc_dev.dv_xname, + tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3); + if (len >= sizeof(eh)) { + (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); + printf("%s: dst %s", sc->sc_dev.dv_xname, + ether_sprintf(eh.ether_dhost)); + printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), + ntohs(eh.ether_type)); + } +} +#endif /* LEDEBUG */ + +/* + * Set up the logical address filter. + */ +void +ve_setladrf(ac, af) + struct arpcom *ac; + u_int16_t *af; +{ + struct ifnet *ifp = &ac->ac_if; + struct ether_multi *enm; + register u_char *cp, c; + register u_int32_t crc; + register int i, len; + struct ether_multistep step; + + /* + * Set up multicast address filter by passing all multicast addresses + * through a crc generator, and then using the high order 6 bits as an + * index into the 64 bit logical address filter. The high order bit + * selects the word, while the rest of the bits select the bit within + * the word. + */ + + if (ifp->if_flags & IFF_PROMISC) + goto allmulti; + + af[0] = af[1] = af[2] = af[3] = 0x0000; + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) { + /* + * We must listen to a range of multicast addresses. + * For now, just accept all multicasts, rather than + * trying to set only those filter bits needed to match + * the range. (At this time, the only use of address + * ranges is for IP multicast routing, for which the + * range is big enough to require all bits set.) + */ + goto allmulti; + } + + cp = enm->enm_addrlo; + crc = 0xffffffff; + for (len = sizeof(enm->enm_addrlo); --len >= 0;) { + c = *cp++; + for (i = 8; --i >= 0;) { + if ((crc & 0x01) ^ (c & 0x01)) { + crc >>= 1; + crc ^= 0xedb88320; + } else + crc >>= 1; + c >>= 1; + } + } + /* Just want the 6 most significant bits. */ + crc >>= 26; + + /* Set the corresponding bit in the filter. */ + af[crc >> 4] |= 1 << (crc & 0xf); + + ETHER_NEXT_MULTI(step, enm); + } + ifp->if_flags &= ~IFF_ALLMULTI; + return; + +allmulti: + ifp->if_flags |= IFF_ALLMULTI; + af[0] = af[1] = af[2] = af[3] = 0xffff; +} + + +/* + * Routines for accessing the transmit and receive buffers. + * The various CPU and adapter configurations supported by this + * driver require three different access methods for buffers + * and descriptors: + * (1) contig (contiguous data; no padding), + * (2) gap2 (two bytes of data followed by two bytes of padding), + * (3) gap16 (16 bytes of data followed by 16 bytes of padding). + */ + +/* + * contig: contiguous data with no padding. + * + * Buffers may have any alignment. + */ + +void +ve_copytobuf_contig(sc, from, boff, len) + struct vam7990_softc *sc; + void *from; + int boff, len; +{ + volatile caddr_t buf = sc->sc_mem; + + /* + * Just call bcopy() to do the work. + */ + bcopy(from, buf + boff, len); +} + +void +ve_copyfrombuf_contig(sc, to, boff, len) + struct vam7990_softc *sc; + void *to; + int boff, len; +{ + volatile caddr_t buf = sc->sc_mem; + + /* + * Just call bcopy() to do the work. + */ + bcopy(buf + boff, to, len); +} + +void +ve_zerobuf_contig(sc, boff, len) + struct vam7990_softc *sc; + int boff, len; +{ + volatile caddr_t buf = sc->sc_mem; + + /* + * Just let bzero() do the work + */ + bzero(buf + boff, len); +} + + diff --git a/sys/arch/mvme88k/dev/if_vereg.h b/sys/arch/mvme88k/dev/if_vereg.h new file mode 100644 index 00000000000..9b29b2b95d6 --- /dev/null +++ b/sys/arch/mvme88k/dev/if_vereg.h @@ -0,0 +1,218 @@ +/* $OpenBSD: if_vereg.h,v 1.1 1999/05/29 04:41:43 smurph Exp $ */ + +/*- + * Copyright (c) 1982, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_lereg.h 8.2 (Berkeley) 10/30/93 + */ + +#define LEMEMSIZE 0x40000 + +/* + * LANCE registers. + */ +struct vereg1 { + volatile u_int16_t ver1_csr; /* board control/status register */ + volatile u_int16_t ver1_vec; /* interupt vector register */ + volatile u_int16_t ver1_rdp; /* data port */ + volatile u_int16_t ver1_rap; /* register select port */ + volatile u_int16_t ver1_ear; /* ethernet address register */ +}; + +#define NVRAM_EN 0x0008 /* NVRAM enable bit */ +#define INTR_EN 0x0010 /* Interrupt enable bit */ +#define PARITYB 0x0020 /* Parity clear bit */ +#define HW_RS 0x0040 /* Hardware reset bit */ +#define SYSFAILB 0x0080 /* SYSFAIL bit */ +#define NVRAM_RWEL 0xE0 /* Reset write enable latch */ +#define NVRAM_STO 0x60 /* Store ram to eeprom */ +#define NVRAM_SLP 0xA0 /* Novram into low power mode */ +#define NVRAM_WRITE 0x20 /* Writes word from location x */ +#define NVRAM_SWEL 0xC0 /* Set write enable latch */ +#define NVRAM_RCL 0x40 /* Recall eeprom data into ram */ +#define NVRAM_READ 0x00 /* Reads word from location x */ + +#define CDELAY delay(10000) +#define WRITE_CSR_OR(x) reg1->ver1_csr=sc->csr|=x +#define WRITE_CSR_AND(x) reg1->ver1_csr=sc->csr&=x +#define ENABLE_NVRAM WRITE_CSR_AND(~NVRAM_EN) +#define DISABLE_NVRAM WRITE_CSR_OR(NVRAM_EN) +#define ENABLE_INTR WRITE_CSR_AND(~INTR_EN) +#define DISABLE_INTR WRITE_CSR_OR(INTR_EN) +#define RESET_HW WRITE_CSR_AND(~0xFF00);WRITE_CSR_AND(~HW_RS);CDELAY +#define SET_IPL(x) WRITE_CSR_AND(~x) +#define SET_VEC(x) reg1->ver1_vec=0;reg1->ver1_vec |=x; +#define PARITY_CL WRITE_CSR_AND(~PARITYB) +#define SYSFAIL_CL WRITE_CSR_AND(~SYSFAILB) +#define NVRAM_CMD(c,a) for(i=0;i<8;i++){ \ + reg1->ver1_ear=((c|(a<<1))>>i); \ + CDELAY; \ + } \ + CDELAY; + +#define LEBLEN 1536 /* ETHERMTU + header + CRC */ +#define LEMINSIZE 60 /* should be 64 if mode DTCR is set */ + +/* + * Receive message descriptor + */ +struct vermd { + u_int16_t rmd0; +#if BYTE_ORDER == BIG_ENDIAN + u_int8_t rmd1_bits; + u_int8_t rmd1_hadr; +#else + u_int8_t rmd1_hadr; + u_int8_t rmd1_bits; +#endif + int16_t rmd2; + u_int16_t rmd3; +}; + +/* + * Transmit message descriptor + */ +struct vetmd { + u_int16_t tmd0; +#if BYTE_ORDER == BIG_ENDIAN + u_int8_t tmd1_bits; + u_int8_t tmd1_hadr; +#else + u_int8_t tmd1_hadr; + u_int8_t tmd1_bits; +#endif + int16_t tmd2; + u_int16_t tmd3; +}; + +/* + * Initialization block + */ +struct veinit { + u_int16_t init_mode; /* +0x0000 */ + u_int16_t init_padr[3]; /* +0x0002 */ + u_int16_t init_ladrf[4]; /* +0x0008 */ + u_int16_t init_rdra; /* +0x0010 */ + u_int16_t init_rlen; /* +0x0012 */ + u_int16_t init_tdra; /* +0x0014 */ + u_int16_t init_tlen; /* +0x0016 */ + int16_t pad0[4]; /* Pad to 16 shorts */ +}; + +#define LE_INITADDR(sc) (sc->sc_initaddr) +#define LE_RMDADDR(sc, bix) (sc->sc_rmdaddr + sizeof(struct vermd) * (bix)) +#define LE_TMDADDR(sc, bix) (sc->sc_tmdaddr + sizeof(struct vetmd) * (bix)) +#define LE_RBUFADDR(sc, bix) (sc->sc_rbufaddr + LEBLEN * (bix)) +#define LE_TBUFADDR(sc, bix) (sc->sc_tbufaddr + LEBLEN * (bix)) + +/* register addresses */ +#define LE_CSR0 0x0000 /* Control and status register */ +#define LE_CSR1 0x0001 /* low address of init block */ +#define LE_CSR2 0x0002 /* high address of init block */ +#define LE_CSR3 0x0003 /* Bus master and control */ + +/* Control and status register 0 (csr0) */ +#define LE_C0_ERR 0x8000 /* error summary */ +#define LE_C0_BABL 0x4000 /* transmitter timeout error */ +#define LE_C0_CERR 0x2000 /* collision */ +#define LE_C0_MISS 0x1000 /* missed a packet */ +#define LE_C0_MERR 0x0800 /* memory error */ +#define LE_C0_RINT 0x0400 /* receiver interrupt */ +#define LE_C0_TINT 0x0200 /* transmitter interrupt */ +#define LE_C0_IDON 0x0100 /* initalization done */ +#define LE_C0_INTR 0x0080 /* interrupt condition */ +#define LE_C0_INEA 0x0040 /* interrupt enable */ +#define LE_C0_RXON 0x0020 /* receiver on */ +#define LE_C0_TXON 0x0010 /* transmitter on */ +#define LE_C0_TDMD 0x0008 /* transmit demand */ +#define LE_C0_STOP 0x0004 /* disable all external activity */ +#define LE_C0_STRT 0x0002 /* enable external activity */ +#define LE_C0_INIT 0x0001 /* begin initalization */ + +#define LE_C0_BITS \ + "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\ +\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT" + +/* Control and status register 3 (csr3) */ +#define LE_C3_BSWP 0x0004 /* byte swap */ +#define LE_C3_ACON 0x0002 /* ALE control, eh? */ +#define LE_C3_BCON 0x0001 /* byte control */ + +/* Initialzation block (mode) */ +#define LE_MODE_PROM 0x8000 /* promiscuous mode */ +/* 0x7f80 reserved, must be zero */ +#define LE_MODE_INTL 0x0040 /* internal loopback */ +#define LE_MODE_DRTY 0x0020 /* disable retry */ +#define LE_MODE_COLL 0x0010 /* force a collision */ +#define LE_MODE_DTCR 0x0008 /* disable transmit CRC */ +#define LE_MODE_LOOP 0x0004 /* loopback mode */ +#define LE_MODE_DTX 0x0002 /* disable transmitter */ +#define LE_MODE_DRX 0x0001 /* disable receiver */ +#define LE_MODE_NORMAL 0 /* none of the above */ + +/* Receive message descriptor 1 (rmd1_bits) */ +#define LE_R1_OWN 0x80 /* LANCE owns the packet */ +#define LE_R1_ERR 0x40 /* error summary */ +#define LE_R1_FRAM 0x20 /* framing error */ +#define LE_R1_OFLO 0x10 /* overflow error */ +#define LE_R1_CRC 0x08 /* CRC error */ +#define LE_R1_BUFF 0x04 /* buffer error */ +#define LE_R1_STP 0x02 /* start of packet */ +#define LE_R1_ENP 0x01 /* end of packet */ + +#define LE_R1_BITS \ + "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP" + +/* Transmit message descriptor 1 (tmd1_bits) */ +#define LE_T1_OWN 0x80 /* LANCE owns the packet */ +#define LE_T1_ERR 0x40 /* error summary */ +#define LE_T1_MORE 0x10 /* multiple collisions */ +#define LE_T1_ONE 0x08 /* single collision */ +#define LE_T1_DEF 0x04 /* defferred transmit */ +#define LE_T1_STP 0x02 /* start of packet */ +#define LE_T1_ENP 0x01 /* end of packet */ + +#define LE_T1_BITS \ + "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP" + +/* Transmit message descriptor 3 (tmd3) */ +#define LE_T3_BUFF 0x8000 /* buffer error */ +#define LE_T3_UFLO 0x4000 /* underflow error */ +#define LE_T3_LCOL 0x1000 /* late collision */ +#define LE_T3_LCAR 0x0800 /* loss of carrier */ +#define LE_T3_RTRY 0x0400 /* retry error */ +#define LE_T3_TDR_MASK 0x03ff /* time domain reflectometry counter */ + +#define LE_XMD2_ONES 0xf000 + +#define LE_T3_BITS \ + "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY" diff --git a/sys/arch/mvme88k/dev/if_vevar.h b/sys/arch/mvme88k/dev/if_vevar.h new file mode 100644 index 00000000000..4c7de6d0571 --- /dev/null +++ b/sys/arch/mvme88k/dev/if_vevar.h @@ -0,0 +1,146 @@ +/* $OpenBSD: if_vevar.h,v 1.1 1999/05/29 04:41:43 smurph Exp $ */ + +/* + * Copyright (c) 1995 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. + */ + +#define LEDEBUG 1 + +#ifdef DDB +#define integrate +#define hide +#else +#define integrate static __inline +#define hide static +#endif + +/* + * Ethernet software status per device. + * + * Each interface is referenced by a network interface structure, + * arpcom.ac_if, which the routing code uses to locate the interface. + * This structure contains the output queue for the interface, its address, ... + * + * NOTE: this structure MUST be the first element in machine-dependent + * le_softc structures! This is designed SPECIFICALLY to make it possible + * to simply cast a "void *" to "struct le_softc *" or to + * "struct ve_softc *". Among other things, this saves a lot of hair + * in the interrupt handlers. + */ +struct vam7990_softc { + struct device sc_dev; /* base device glue */ + struct arpcom sc_arpcom; /* Ethernet common part */ + + /* + * Memory functions: + * + * copy to/from descriptor + * copy to/from buffer + * zero bytes in buffer + */ + void (*sc_copytodesc) + __P((struct vam7990_softc *, void *, int, int)); + void (*sc_copyfromdesc) + __P((struct vam7990_softc *, void *, int, int)); + void (*sc_copytobuf) + __P((struct vam7990_softc *, void *, int, int)); + void (*sc_copyfrombuf) + __P((struct vam7990_softc *, void *, int, int)); + void (*sc_zerobuf) + __P((struct vam7990_softc *, int, int)); + + /* + * Machine-dependent functions: + * + * read/write CSR + * hardware reset hook - may be NULL + * hardware init hook - may be NULL + * no carrier hook - may be NULL + */ + u_int16_t (*sc_rdcsr) + __P((struct vam7990_softc *, u_int16_t)); + void (*sc_wrcsr) + __P((struct vam7990_softc *, u_int16_t, u_int16_t)); + void (*sc_hwreset) __P((struct vam7990_softc *)); + void (*sc_hwinit) __P((struct vam7990_softc *)); + void (*sc_nocarrier) __P((struct vam7990_softc *)); + + int sc_hasifmedia; + struct ifmedia sc_ifmedia; + + void *sc_sh; /* shutdownhook cookie */ + + u_int16_t sc_conf3; /* CSR3 value */ + + void *sc_mem; /* base address of RAM -- CPU's view */ + u_long sc_addr; /* base address of RAM -- LANCE's view */ + + u_long sc_memsize; /* size of RAM */ + + int sc_nrbuf; /* number of receive buffers */ + int sc_ntbuf; /* number of transmit buffers */ + int sc_last_rd; + int sc_first_td, sc_last_td, sc_no_td; + + int sc_initaddr; + int sc_rmdaddr; + int sc_tmdaddr; + int sc_rbufaddr; + int sc_tbufaddr; + unsigned short csr; +#ifdef LEDEBUG + int sc_debug; +#endif +}; + +/* Export this to machine-dependent drivers. */ +extern struct cfdriver ve_cd; + +void ve_config __P((struct vam7990_softc *)); +void ve_init __P((struct vam7990_softc *)); +int ve_ioctl __P((struct ifnet *, u_long, caddr_t)); +void ve_meminit __P((struct vam7990_softc *)); +void ve_reset __P((struct vam7990_softc *)); +void ve_setladrf __P((struct arpcom *, u_int16_t *)); +void ve_start __P((struct ifnet *)); +void ve_stop __P((struct vam7990_softc *)); +void ve_watchdog __P((struct ifnet *)); +int ve_intr __P((void *)); + +/* + * The following functions are only useful on certain cpu/bus + * combinations. They should be written in assembly language for + * maximum efficiency, but machine-independent versions are provided + * for drivers that have not yet been optimized. + */ +void ve_copytobuf_contig __P((struct vam7990_softc *, void *, int, int)); +void ve_copyfrombuf_contig __P((struct vam7990_softc *, void *, int, int)); +void ve_zerobuf_contig __P((struct vam7990_softc *, int, int)); + + + diff --git a/sys/arch/mvme88k/dev/mainbus.c b/sys/arch/mvme88k/dev/mainbus.c index 49e002f1075..2892a076d48 100644 --- a/sys/arch/mvme88k/dev/mainbus.c +++ b/sys/arch/mvme88k/dev/mainbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mainbus.c,v 1.2 1998/12/15 05:52:30 smurph Exp $ */ +/* $OpenBSD: mainbus.c,v 1.3 1999/05/29 04:41:44 smurph Exp $ */ /* Copyright (c) 1998 Steve Murphree, Jr. */ #include <sys/param.h> #include <sys/systm.h> @@ -67,7 +67,7 @@ mainbus_attach(parent, self, args) struct device *parent, *self; void *args; { - printf (" machine type %x\n", cputyp); + printf (" machine type MVME%x\n", cputyp); /* XXX * should have a please-attach-first list for mainbus, diff --git a/sys/arch/mvme88k/dev/memc.c b/sys/arch/mvme88k/dev/memc.c index f07337d3aec..5805f1e42c9 100644 --- a/sys/arch/mvme88k/dev/memc.c +++ b/sys/arch/mvme88k/dev/memc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: memc.c,v 1.2 1998/12/15 05:52:30 smurph Exp $ */ +/* $OpenBSD: memc.c,v 1.3 1999/05/29 04:41:44 smurph Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -84,7 +84,7 @@ memcmatch(parent, vcf, args) struct confargs *ca = args; struct memcreg *memc = (struct memcreg *)ca->ca_vaddr; - if (badvaddr(memc, 1)) + if (badvaddr(memc, 4)) return (0); if (memc->memc_chipid==MEMC_CHIPID || memc->memc_chipid==MCECC_CHIPID) return (1); diff --git a/sys/arch/mvme88k/dev/pcctwo.c b/sys/arch/mvme88k/dev/pcctwo.c index 4156a8f440e..415c8aae3b4 100644 --- a/sys/arch/mvme88k/dev/pcctwo.c +++ b/sys/arch/mvme88k/dev/pcctwo.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pcctwo.c,v 1.5 1998/12/15 05:52:30 smurph Exp $ */ +/* $OpenBSD: pcctwo.c,v 1.6 1999/05/29 04:41:44 smurph Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -87,7 +87,7 @@ pcctwomatch(parent, vcf, args) struct pcctworeg *pcc2; /* Bomb if wrong cpu */ - if (cputyp != CPU_187){ + if (!(cputyp == CPU_187 || cputyp == CPU_188)){ printf("==> pcctwo: wrong CPU type %x.\n", cputyp); return (0); } diff --git a/sys/arch/mvme88k/dev/siop.c b/sys/arch/mvme88k/dev/siop.c index ba95e2bd449..4fbb54c51e3 100644 --- a/sys/arch/mvme88k/dev/siop.c +++ b/sys/arch/mvme88k/dev/siop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: siop.c,v 1.2 1998/12/15 05:52:31 smurph Exp $ */ +/* $OpenBSD: siop.c,v 1.3 1999/05/29 04:41:44 smurph Exp $ */ /* * Copyright (c) 1994 Michael L. Hitch @@ -184,6 +184,19 @@ void siop_dump_trace __P((void)); int kludge_city = 1; /* + * dummy routine to debug while loops + */ +void +wdummy(void) +{ + static int wcount; + wcount++; + if (wcount > 400000) { + wcount = 0; + } +} + +/* * default minphys routine for siop based controllers */ void @@ -213,8 +226,9 @@ siop_scsicmd(xs) slp = xs->sc_link; sc = slp->adapter_softc; flags = xs->flags; - - /* XXXX ?? */ + xs->error = XS_NOERROR; + + /* XXXX ?? */ if (flags & SCSI_DATA_UIO) panic("siop: scsi data uio requested"); @@ -921,7 +935,9 @@ siop_checkintr(sc, istat, dstat, sstat0, status) * Flush DMA and SCSI FIFOs. */ rp->siop_ctest8 |= SIOP_CTEST8_CLF; - while ((rp->siop_ctest1 & SIOP_CTEST1_FMT) != SIOP_CTEST1_FMT) + while ((rp->siop_ctest1 & SIOP_CTEST1_FMT) != SIOP_CTEST1_FMT){ + wdummy(); + } ; rp->siop_ctest8 &= ~SIOP_CTEST8_CLF; #ifdef DEBUG diff --git a/sys/arch/mvme88k/dev/vme.c b/sys/arch/mvme88k/dev/vme.c index 7e8b14fe3c9..958077067a1 100644 --- a/sys/arch/mvme88k/dev/vme.c +++ b/sys/arch/mvme88k/dev/vme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vme.c,v 1.2 1998/12/15 05:52:31 smurph Exp $ */ +/* $OpenBSD: vme.c,v 1.3 1999/05/29 04:41:44 smurph Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -43,9 +43,13 @@ #include <sys/syslog.h> #include <sys/fcntl.h> #include <sys/device.h> -#include <machine/autoconf.h> -#include <machine/cpu.h> -#include <machine/frame.h> +#include <vm/vm.h> +#include <vm/vm_map.h> +#include <vm/vm_kern.h> +#include "machine/autoconf.h" +#include "machine/cpu.h" +#include "machine/frame.h" +#include "machine/pmap.h" #include "pcctwo.h" @@ -60,6 +64,11 @@ u_long vme2chip_map __P((u_long base, int len, int dwidth)); int vme2abort __P((struct frame *frame)); static int vmebustype; +volatile vm_offset_t master1va; +volatile vm_offset_t master2va; +volatile vm_offset_t master3va; +volatile vm_offset_t master4va; +struct vme2reg *sys_vme2 = NULL; struct cfattach vme_ca = { sizeof(struct vmesoftc), vmematch, vmeattach @@ -86,9 +95,9 @@ vmematch(parent, cf, args) } #endif return (1); - } +} -#if defined(MVME162) || defined(MVME167) || defined(MVME177) || defined (MVME187) +#ifndef BUGMAP /* * make local addresses 1G-2G correspond to VME addresses 3G-4G, * as D32 @@ -104,8 +113,31 @@ vmematch(parent, cf, args) */ #define VME2_D16STARTPHYS (3*1024*1024*1024UL) #define VME2_D16ENDPHYS (3*1024*1024*1024UL + 768*1024*1024UL) + +#else + +/* + * make local addresses 1G-2G correspond to VME addresses 3G-4G, + * as D32 + */ + +#define VME2_D32STARTPHYS (1*1024*1024*1024UL) +#define VME2_D32ENDPHYS (2*1024*1024*1024UL) +#define VME2_D32STARTVME (3*1024*1024*1024UL) +#define VME2_D32BITSVME (3*1024*1024*1024UL) + +/* + * make local addresses 3G-3.75G correspond to VME addresses 3G-3.75G, + * as D16 + */ +#define VME2_D16STARTPHYS (3*1024*1024*1024UL) +#define VME2_D16ENDPHYS (3*1024*1024*1024UL + 768*1024*1024UL) +#define VME2_A32D16STARTPHYS (0xFF000000UL) +#define VME2_A32D16ENDPHYS (0xFF7FFFFFUL) + #endif + /* * Returns a physical address mapping for a VME address & length. * Note: on some hardware it is not possible to create certain @@ -161,34 +193,24 @@ vmepmap(sc, vmeaddr, len, bustype) case BUS_MC: case BUS_PCCTWO: switch (bustype) { - case BUS_VMES: - /*printf("base %x len %d\n", base, len);*/ - if (base > VME2_A16BASE && - (base+len-VME2_A16BASE) < VME2_A16D16LEN) { - /* XXX busted? */ - base = base - VME2_A16BASE + VME2_A16D16BASE; - } else if (base > VME2_A24BASE && - (base+len-VME2_A24BASE) < VME2_A24D16LEN) { - base = base - VME2_A24BASE + VME2_D16STARTPHYS; - } else if ((base+len) < VME2_A32D16LEN) { - /* XXX busted? */ - base = base + VME2_A32D16BASE; - } else { - printf("vme2chip_map\n"); - base = vme2chip_map(base, len, 16); - if (base == NULL) - return (NULL); + case BUS_VMES: /* D16 VME Transfers */ + /*printf("base 0x%8x/0x%8x len 0x%x\n", vmeaddr, base, len);*/ + base = vme2chip_map(base, len, 16); + if (base == NULL){ + printf("%s: cannot map pa 0x%x len 0x%x\n", + sc->sc_dev.dv_xname, base, len); + return (NULL); } break; - case BUS_VMEL: -#if 0 - if (base > VME2_A16BASE && - (base+len-VME2_A16BASE) < VME2_A16D32LEN) - base = base - VME2_A16BASE + VME2_A16D32BASE; -#endif + case BUS_VMEL: /* D32 VME Transfers */ + printf("base 0x%8x/0x%8x len 0x%x\n", + vmeaddr, base, len); base = vme2chip_map(base, len, 32); - if (base == NULL) + if (base == NULL){ + printf("%s: cannot map pa 0x%x len 0x%x\n", + sc->sc_dev.dv_xname, base, len); return (NULL); + } break; } break; @@ -271,6 +293,7 @@ vmeprint(args, bus) struct confargs *ca = args; printf(" addr 0x%x", ca->ca_offset); + printf(" vaddr 0x%x", ca->ca_vaddr); if (ca->ca_vec > 0) printf(" vec 0x%x", ca->ca_vec); if (ca->ca_ipl > 0) @@ -345,7 +368,7 @@ vmeattach(parent, self, args) case BUS_PCC: vme1 = (struct vme1reg *)sc->sc_vaddr; scon = (vme1->vme1_scon & VME1_SCON_SWITCH); - printf(": %sscon\n", scon ? "" : "not "); + printf(": %ssystem controller\n", scon ? "" : "not "); vme1chip_init(sc); break; #endif @@ -354,7 +377,8 @@ vmeattach(parent, self, args) case BUS_PCCTWO: vme2 = (struct vme2reg *)sc->sc_vaddr; scon = (vme2->vme2_tctl & VME2_TCTL_SCON); - printf(": %sscon\n", scon ? "" : "not "); + printf(": %ssystem controller\n", scon ? "" : "not "); + if (scon) sys_vme2 = vme2; vme2chip_init(sc); break; #endif @@ -424,7 +448,7 @@ vme1chip_init(sc) #endif -#if defined(MVME162) || defined(MVME167) || defined(MVME177) || defined (MVME187) +#ifndef BUGMAP /* * XXX what AM bits should be used for the D32/D16 mappings? @@ -444,7 +468,7 @@ vme2chip_init(sc) /* unused decoders 1 */ vme2->vme2_master1 = 0; ctl &= ~(VME2_MASTERCTL_ALL << VME2_MASTERCTL_1SHIFT); - printf("%s: 1phys 0x%08x-0x%08x to VMExxx 0x%08x-0x%08x\n", + printf("%s: 1phys 0x%08x-0x%08x to VME 0x%08x-0x%08x\n", sc->sc_dev.dv_xname, vme2->vme2_master1 << 16, vme2->vme2_master1 & 0xffff0000, vme2->vme2_master1 << 16, vme2->vme2_master1 & 0xffff0000); @@ -452,7 +476,7 @@ vme2chip_init(sc) /* unused decoders 2 */ vme2->vme2_master2 = 0; ctl &= ~(VME2_MASTERCTL_ALL << VME2_MASTERCTL_2SHIFT); - printf("%s: 2phys 0x%08x-0x%08x to VMExxx 0x%08x-0x%08x\n", + printf("%s: 2phys 0x%08x-0x%08x to VME 0x%08x-0x%08x\n", sc->sc_dev.dv_xname, vme2->vme2_master2 << 16, vme2->vme2_master2 & 0xffff0000, vme2->vme2_master2 << 16, vme2->vme2_master2 & 0xffff0000); @@ -463,7 +487,7 @@ vme2chip_init(sc) ctl &= ~(VME2_MASTERCTL_ALL << VME2_MASTERCTL_3SHIFT); ctl |= (VME2_MASTERCTL_D16 | VME2_MASTERCTL_AM24UD) << VME2_MASTERCTL_3SHIFT; - printf("%s: 3phys 0x%08x-0x%08x to VMED16 0x%08x-0x%08x\n", + printf("%s: 3phys 0x%08x-0x%08x to VME 0x%08x-0x%08x\n", sc->sc_dev.dv_xname, vme2->vme2_master3 << 16, vme2->vme2_master3 & 0xffff0000, vme2->vme2_master3 << 16, vme2->vme2_master3 & 0xffff0000); @@ -476,7 +500,7 @@ vme2chip_init(sc) ctl &= ~(VME2_MASTERCTL_ALL << VME2_MASTERCTL_4SHIFT); ctl |= (VME2_MASTERCTL_AM32UD) << VME2_MASTERCTL_4SHIFT; - printf("%s: 4phys 0x%08x-0x%08x to VMED32 0x%08x-0x%08x\n", + printf("%s: 4phys 0x%08x-0x%08x to VME 0x%08x-0x%08x\n", sc->sc_dev.dv_xname, vme2->vme2_master4 << 16, vme2->vme2_master4 & 0xffff0000, vme2->vme2_master4 << 16, vme2->vme2_master4 & 0xffff0000); @@ -513,6 +537,71 @@ vme2chip_init(sc) vme2->vme2_irql4); #if NPCCTWO > 0 + if (vmebustype == BUS_PCCTWO) { + sc->sc_abih.ih_fn = vme2abort; + sc->sc_abih.ih_arg = 0; + sc->sc_abih.ih_ipl = 7; + sc->sc_abih.ih_wantframe = 1; + + intr_establish(110, &sc->sc_abih); /* XXX 110 */ + vme2->vme2_irqen |= VME2_IRQ_AB; + } +#endif + vme2->vme2_irqen = vme2->vme2_irqen | VME2_IRQ_ACF; +} + +#else /* BUGMAP */ + +int +vme2chip_init(sc) + struct vmesoftc *sc; +{ + struct vme2reg *vme2 = (struct vme2reg *)sc->sc_vaddr; + u_long ctl, addr, vasize; + + /* turn off SYSFAIL LED */ + vme2->vme2_tctl &= ~VME2_TCTL_SYSFAIL; + + ctl = vme2->vme2_masterctl; + printf("%s: using BUG parameters\n", sc->sc_dev.dv_xname); + /* setup a A32D16 space */ + printf("%s: 1phys 0x%08x-0x%08x to VME 0x%08x-0x%08x\n", + sc->sc_dev.dv_xname, + vme2->vme2_master1 << 16, vme2->vme2_master1 & 0xffff0000, + vme2->vme2_master1 << 16, vme2->vme2_master1 & 0xffff0000); + + /* setup a A32D32 space */ + printf("%s: 2phys 0x%08x-0x%08x to VME 0x%08x-0x%08x\n", + sc->sc_dev.dv_xname, + vme2->vme2_master2 << 16, vme2->vme2_master2 & 0xffff0000, + vme2->vme2_master2 << 16, vme2->vme2_master2 & 0xffff0000); + + /* setup a A24D16 space */ + printf("%s: 3phys 0x%08x-0x%08x to VME 0x%08x-0x%08x\n", + sc->sc_dev.dv_xname, + vme2->vme2_master3 << 16, vme2->vme2_master3 & 0xffff0000, + vme2->vme2_master3 << 16, vme2->vme2_master3 & 0xffff0000); + + /* setup a XXXXXX space */ + printf("%s: 4phys 0x%08x-0x%08x to VME 0x%08x-0x%08x\n", + sc->sc_dev.dv_xname, + vme2->vme2_master4 << 16, vme2->vme2_master4 & 0xffff0000, + vme2->vme2_master4 << 16 + vme2->vme2_master4mod << 16, + vme2->vme2_master4 & 0xffff0000 + vme2->vme2_master4 & 0xffff0000); + /* + * Map the VME irq levels to the cpu levels 1:1. + * This is rather inflexible, but much easier. + */ + vme2->vme2_irql4 = (7 << VME2_IRQL4_VME7SHIFT) | + (6 << VME2_IRQL4_VME6SHIFT) | (5 << VME2_IRQL4_VME5SHIFT) | + (4 << VME2_IRQL4_VME4SHIFT) | (3 << VME2_IRQL4_VME3SHIFT) | + (2 << VME2_IRQL4_VME2SHIFT) | (1 << VME2_IRQL4_VME1SHIFT); + printf("%s: vme to cpu irq level 1:1\n",sc->sc_dev.dv_xname); + /* + printf("%s: vme2_irql4 = 0x%08x\n", sc->sc_dev.dv_xname, + vme2->vme2_irql4); + */ +#if NPCCTWO > 0 if (vmebustype == BUS_PCCTWO){ /* * pseudo driver, abort interrupt handler @@ -530,6 +619,9 @@ vme2chip_init(sc) #endif vme2->vme2_irqen = vme2->vme2_irqen | VME2_IRQ_ACF; } +#endif /* BUGMAP */ + +#if defined(MVME162) || defined(MVME167) || defined(MVME177) || defined (MVME187) || defined (MVME188) /* * A32 accesses on the MVME1[678]x require setting up mappings in @@ -544,14 +636,12 @@ vme2chip_map(base, len, dwidth) { switch (dwidth) { case 16: - if (base < VME2_D16STARTPHYS || - base + (u_long)len > VME2_D16ENDPHYS) - return (NULL); return (base); case 32: - if (base < VME2_D32STARTVME) + if (base < VME2_D32STARTPHYS || + base + (u_long)len > VME2_D32ENDPHYS) return (NULL); - return (base - VME2_D32STARTVME + VME2_D32STARTPHYS); + return (base); } } @@ -573,3 +663,5 @@ vme2abort(frame) } #endif #endif /* MVME1[678]x */ + + diff --git a/sys/arch/mvme88k/dev/vme.h b/sys/arch/mvme88k/dev/vme.h index f0663440e3d..d143d53f791 100644 --- a/sys/arch/mvme88k/dev/vme.h +++ b/sys/arch/mvme88k/dev/vme.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vme.h,v 1.2 1998/12/15 05:52:31 smurph Exp $ */ +/* $OpenBSD: vme.h,v 1.3 1999/05/29 04:41:44 smurph Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -188,8 +188,8 @@ struct vme2reg { #define VME2_MASTERCTL_AM24UB 0x3b /* A24 Non-priv. Block Transfer */ #define VME2_MASTERCTL_AM24UP 0x3a /* A24 Non-priv. Program Access */ #define VME2_MASTERCTL_AM24UD 0x39 /* A24 Non-priv. Data Access */ -#define VME2_MASTERCTL_AM16S 0x2d /* A16 Supervisory Access */ -#define VME2_MASTERCTL_AM16U 0x29 /* A16 Non-priv. Access */ +#define VME2_MASTERCTL_AM16S 0x2d /* A16 Supervisory Access */ +#define VME2_MASTERCTL_AM16U 0x29 /* A16 Non-priv. Access */ #define VME2_MASTERCTL_AM32SB 0x0f /* A32 Supervisory Block Transfer */ #define VME2_MASTERCTL_AM32SP 0x0e /* A32 Supervisory Program Access */ #define VME2_MASTERCTL_AM32SD 0x0d /* A32 Supervisory Data Access */ @@ -228,6 +228,10 @@ struct vme2reg { /*58*/ volatile u_long vme2_t2cmp; /*5c*/ volatile u_long vme2_t2count; /*60*/ volatile u_long vme2_tctl; +#define VME2_TCTL1_CEN 0x01 +#define VME2_TCTL1_COC 0x02 +#define VME2_TCTL1_COVF 0x04 +#define VME2_TCTL1_OVF 0xf0 #define VME2_TCTL_SCON 0x40000000 /* we are SCON */ #define VME2_TCTL_SYSFAIL 0x20000000 /* light SYSFAIL led */ #define VME2_TCTL_SRST 0x00800000 /* system reset */ @@ -306,6 +310,7 @@ struct vme2reg { #define VME2_IRQL4_VME2SHIFT 4 #define VME2_IRQL4_VME1SHIFT 0 /*88*/ volatile u_long vme2_vbr; +#define VME2_SYSFAIL (1 << 22) #define VME2_VBR_0SHIFT 28 #define VME2_VBR_1SHIFT 24 #define VME2_VBR_GPOXXXX 0x00ffffff diff --git a/sys/arch/mvme88k/dev/vs.c b/sys/arch/mvme88k/dev/vs.c new file mode 100644 index 00000000000..a92f1bf6211 --- /dev/null +++ b/sys/arch/mvme88k/dev/vs.c @@ -0,0 +1,758 @@ +/* $OpenBSD: vs.c,v 1.1 1999/05/29 04:41:44 smurph Exp $ */ + +/* + * Copyright (c) 1999 Steve Murphree, Jr. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of 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. + */ + +/* + * MVME328 scsi adaptor driver + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/disklabel.h> +#include <sys/dkstat.h> +#include <sys/buf.h> +#include <sys/malloc.h> +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> +#include <machine/autoconf.h> +#include <machine/param.h> +#if defined(MVME187) +#include <mvme88k/dev/vsreg.h> +#include <mvme88k/dev/vsvar.h> +#include "machine/mmu.h" +#else +#include <mvme68k/dev/vsreg.h> +#include <mvme68k/dev/vsvar.h> +#endif /* MVME187 */ + +int vs_checkintr __P((struct vs_softc *, struct scsi_xfer *, int *)); +int vs_chksense __P((struct scsi_xfer *)); +void vs_reset __P((struct vs_softc *)); +void vs_resync __P((struct vs_softc *)); +void vs_initialize __P((struct vs_softc *)); +int vs_intr __P((struct vs_softc *)); +int vs_poll __P((struct vs_softc *, struct scsi_xfer *)); +void vs_scsidone __P((struct scsi_xfer *, int)); +M328_CQE * vs_getcqe __P((struct vs_softc *)); +M328_IOPB * vs_getiopb __P((struct vs_softc *)); + +extern int cold; +extern u_int kvtop(); + +/* + * default minphys routine for MVME328 based controllers + */ +void +vs_minphys(bp) + struct buf *bp; +{ + /* + * No max transfer at this level. + */ + minphys(bp); +} + +int do_vspoll(sc, to) + struct vs_softc *sc; + int to; +{ + int i; + if (to <= 0 ) to = 50000; + /* use cmd_wait values? */ + i = 50000; + /*spl0();*/ + while(!(CRSW & (M_CRSW_CRBV | M_CRSW_CC))){ + if (--i <= 0) { +#ifdef DEBUG + printf ("waiting: timeout %d crsw 0x%x\n", to, CRSW); +#endif + i = 50000; + --to; + if (to <= 0) { + /*splx(s);*/ + vs_reset(sc); + vs_resync(sc); + printf ("timed out: timeout %d crsw 0x%x\n", to, CRSW); + return 1; + } + } + } + return 0; +} + +int +vs_poll(sc, xs) + struct vs_softc *sc; + struct scsi_xfer *xs; +{ + M328_CIB *cib = (M328_CIB *)&sc->sc_vsreg->sh_CIB; + M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE; + M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB; + M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB; + M328_IOPB *miopb = (M328_IOPB *)&sc->sc_vsreg->sh_MCE_IOPB; + M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB; + M328_CQE *cqep; + M328_IOPB *iopb; + int i; + int status; + int s; + int to; + + /*s = splbio();*/ + to = xs->timeout / 1000; + for (;;) { + if (do_vspoll(sc, to)) break; + if (vs_checkintr(sc, xs, &status)) { + vs_scsidone(xs, status); + } + if (CRSW & M_CRSW_ER) + CRB_CLR_ER(CRSW); + CRB_CLR_DONE(CRSW); + if (xs->flags & ITSDONE) break; + } + return (COMPLETE); +} + +void thaw_queue(sc, target) + struct vs_softc *sc; + u_int8_t target; +{ + u_short t; + t = target << 8; + t |= 0x0001; + THAW_REG = t; + /* loop until thawed */ + while (THAW_REG & 0x01); +} + +void +vs_scsidone (xs, stat) +struct scsi_xfer *xs; +int stat; +{ + struct scsi_link *slp = xs->sc_link; + struct vs_softc *sc = slp->adapter_softc; + M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB; + xs->status = stat; + while (xs->status == SCSI_CHECK) { + vs_chksense(xs); + thaw_queue(sc, slp->target + 1); + } + xs->flags |= ITSDONE; + /*sc->sc_tinfo[slp->target].cmds++;*/ + if (CRSW & M_CRSW_ER) + CRB_CLR_ER(CRSW); + CRB_CLR_DONE(CRSW); + thaw_queue(sc, slp->target + 1); + bzero(riopb, sizeof(M328_IOPB)); + scsi_done(xs); +} + +int +vs_scsicmd(xs) + struct scsi_xfer *xs; +{ + struct scsi_link *slp = xs->sc_link; + struct vs_softc *sc = slp->adapter_softc; + int flags, s, i; + unsigned long buf, len; + u_short iopb_len; + M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE; + M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB; + M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB; + M328_IOPB *miopb = (M328_IOPB *)&sc->sc_vsreg->sh_MCE_IOPB; + M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB; + M328_CQE *cqep; + M328_IOPB *iopb; + + /* If the target doesn't exist, abort */ + if (!sc->sc_tinfo[slp->target].avail) { + xs->error = XS_SELTIMEOUT; + xs->status = -1; + xs->flags |= ITSDONE; + scsi_done(xs); + } + + slp->quirks |= SDEV_NOLUNS; + flags = xs->flags; +#ifdef SDEBUG + printf("scsi_cmd() "); + if (xs->cmd->opcode == 0){ + printf("TEST_UNIT_READY "); + } else if (xs->cmd->opcode == REQUEST_SENSE) { + printf("REQUEST_SENSE "); + } else if (xs->cmd->opcode == INQUIRY) { + printf("INQUIRY "); + } else if (xs->cmd->opcode == MODE_SELECT) { + printf("MODE_SELECT "); + } else if (xs->cmd->opcode == MODE_SENSE) { + printf("MODE_SENSE "); + } else if (xs->cmd->opcode == START_STOP) { + printf("START_STOP "); + } else if (xs->cmd->opcode == RESERVE) { + printf("RESERVE "); + } else if (xs->cmd->opcode == RELEASE) { + printf("RELEASE "); + } else if (xs->cmd->opcode == PREVENT_ALLOW) { + printf("PREVENT_ALLOW "); + } else if (xs->cmd->opcode == POSITION_TO_ELEMENT) { + printf("POSITION_TO_EL "); + } else if (xs->cmd->opcode == CHANGE_DEFINITION) { + printf("CHANGE_DEF "); + } else if (xs->cmd->opcode == MODE_SENSE_BIG) { + printf("MODE_SENSE_BIG "); + } else if (xs->cmd->opcode == MODE_SELECT_BIG) { + printf("MODE_SELECT_BIG "); + } else if (xs->cmd->opcode == 0x25) { + printf("READ_CAPACITY "); + } else if (xs->cmd->opcode == 0x08) { + printf("READ_COMMAND "); + } +#endif + if (flags & SCSI_POLL){ + cqep = mc; + iopb = miopb; + }else{ + cqep = vs_getcqe(sc); + iopb = vs_getiopb(sc); + } + if (cqep == NULL) { + xs->error = XS_DRIVER_STUFFUP; + return(TRY_AGAIN_LATER); + } + +/* s = splbio();*/ + iopb_len = sizeof(M328_short_IOPB) + xs->cmdlen; + bzero(iopb, sizeof(M328_IOPB)); + + bcopy(xs->cmd, &iopb->iopb_SCSI[0], xs->cmdlen); + iopb->iopb_CMD = IOPB_SCSI; + LV(iopb->iopb_BUFF, kvtop(xs->data)); + LV(iopb->iopb_LENGTH, xs->datalen); + iopb->iopb_UNIT = slp->lun << 3; + iopb->iopb_UNIT |= slp->target; + iopb->iopb_NVCT = (u_char)sc->sc_nvec; + iopb->iopb_EVCT = (u_char)sc->sc_evec; + + /* + * Since the 187 doesn't support cache snooping, we have + * to flush the cache for a write and flush with inval for + * a read, prior to starting the IO. + */ + if (xs->flags & SCSI_DATA_IN) { /* read */ +#if defined(MVME187) + dma_cachectl((vm_offset_t)xs->data, xs->datalen, + DMA_CACHE_SYNC_INVAL); +#endif + iopb->iopb_OPTION |= OPT_READ; + } else { /* write */ +#if defined(MVME187) + dma_cachectl((vm_offset_t)xs->data, xs->datalen, + DMA_CACHE_SYNC); +#endif + iopb->iopb_OPTION |= OPT_WRITE; + } + + if (flags & SCSI_POLL) { + iopb->iopb_OPTION |= OPT_INTDIS; + iopb->iopb_LEVEL = 0; + } else { + iopb->iopb_OPTION |= OPT_INTEN; + iopb->iopb_LEVEL = sc->sc_ipl; + } + iopb->iopb_ADDR = ADDR_MOD; + + /* + * Wait until we can use the command queue entry. + * Should only have to wait if the master command + * queue entry is busy. + */ + while(cqep->cqe_QECR & M_QECR_GO); + + cqep->cqe_IOPB_ADDR = OFF(iopb); + cqep->cqe_IOPB_LENGTH = iopb_len; + if (flags & SCSI_POLL){ + cqep->cqe_WORK_QUEUE = slp->target + 1; + }else{ + cqep->cqe_WORK_QUEUE = slp->target + 1; + } + LV(cqep->cqe_CTAG, xs); + + if (crb->crb_CRSW & M_CRSW_AQ) { + cqep->cqe_QECR = M_QECR_AA; + } + VL(buf, iopb->iopb_BUFF); + VL(len, iopb->iopb_LENGTH); +#ifdef SDEBUG + printf("tgt %d lun %d buf %x len %d wqn %d ipl %d\n", slp->target, + slp->lun, buf, len, cqep->cqe_WORK_QUEUE, iopb->iopb_LEVEL); +#endif + cqep->cqe_QECR |= M_QECR_GO; + + if (flags & SCSI_POLL){ + /* poll for the command to complete */ +/* splx(s);*/ + vs_poll(sc, xs); + return (COMPLETE); + } +/* splx(s);*/ + return(SUCCESSFULLY_QUEUED); +} + +int +vs_chksense(xs) + struct scsi_xfer *xs; +{ + int flags, s, i; + struct scsi_link *slp = xs->sc_link; + struct vs_softc *sc = slp->adapter_softc; + struct scsi_sense *ss; + M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE; + M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB; + M328_IOPB *miopb = (M328_IOPB *)&sc->sc_vsreg->sh_MCE_IOPB; + + /* ack and clear the error */ + CRB_CLR_DONE(CRSW); + CRB_CLR_ER(CRSW); + xs->status = 0; + + bzero(miopb, sizeof(M328_IOPB)); + /* This is a command, so point to it */ + ss = (void *)&miopb->iopb_SCSI[0]; + bzero(ss, sizeof(*ss)); + ss->opcode = REQUEST_SENSE; + ss->byte2 = slp->lun << 5; + ss->length = sizeof(struct scsi_sense_data); + + miopb->iopb_CMD = IOPB_SCSI; + miopb->iopb_OPTION = OPT_READ; + miopb->iopb_NVCT = (u_char)sc->sc_nvec; + miopb->iopb_EVCT = (u_char)sc->sc_evec; + miopb->iopb_LEVEL = 0; /*sc->sc_ipl;*/ + miopb->iopb_ADDR = ADDR_MOD; + LV(miopb->iopb_BUFF, kvtop(&xs->sense)); + LV(miopb->iopb_LENGTH, sizeof(struct scsi_sense_data)); + + bzero(mc, sizeof(M328_CQE)); + mc->cqe_IOPB_ADDR = OFF(miopb); + mc->cqe_IOPB_LENGTH = sizeof(M328_short_IOPB) + sizeof(struct scsi_sense); + mc->cqe_WORK_QUEUE = 0; + mc->cqe_QECR = M_QECR_GO; + /* poll for the command to complete */ + s = splbio(); + do_vspoll(sc, 0); + /* + if (xs->cmd->opcode != PREVENT_ALLOW) { + xs->error = XS_SENSE; + } + */ + xs->status = riopb->iopb_STATUS >> 8; +#ifdef SDEBUG + scsi_print_sense(xs, 2); +#endif + splx(s); +} + +M328_CQE * +vs_getcqe(sc) + struct vs_softc *sc; +{ + M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB; + M328_CQE *cqep; + + cqep = (M328_CQE *)&sc->sc_vsreg->sh_CQE[mcsb->mcsb_QHDP]; + + if (cqep->cqe_QECR & M_QECR_GO) + return NULL; /* Hopefully, this will never happen */ + mcsb->mcsb_QHDP++; + if (mcsb->mcsb_QHDP == NUM_CQE) mcsb->mcsb_QHDP = 0; + bzero(cqep, sizeof(M328_CQE)); + return cqep; +} + +M328_IOPB * +vs_getiopb(sc) + struct vs_softc *sc; +{ + M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB; + M328_IOPB *iopb; + int slot; + + if (mcsb->mcsb_QHDP == 0) { + slot = NUM_CQE; + } else { + slot = mcsb->mcsb_QHDP - 1; + } + iopb = (M328_IOPB *)&sc->sc_vsreg->sh_IOPB[slot]; + bzero(iopb, sizeof(M328_IOPB)); + return iopb; +} + +void +vs_initialize(sc) + struct vs_softc *sc; +{ + M328_CIB *cib = (M328_CIB *)&sc->sc_vsreg->sh_CIB; + M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE; + M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB; + M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB; + M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB; + M328_IOPB *iopb; + M328_WQCF *wiopb = (M328_WQCF *)&sc->sc_vsreg->sh_MCE_IOPB; + u_short i, crsw; + int failed = 0; + + bzero(cib, sizeof(M328_CIB)); + mcsb->mcsb_QHDP = 0; + sc->sc_qhp = 0; + cib->cib_NCQE = 10; + cib->cib_BURST = 0; + cib->cib_NVECT = sc->sc_ipl << 8; + cib->cib_NVECT |= sc->sc_nvec; + cib->cib_EVECT = sc->sc_ipl << 8; + cib->cib_EVECT |= sc->sc_evec; + cib->cib_PID = 0x07; + cib->cib_SID = 0x00; + cib->cib_CRBO = OFF(crb); + cib->cib_SELECT_msw = HI(SELECTION_TIMEOUT); + cib->cib_SELECT_lsw = LO(SELECTION_TIMEOUT); + cib->cib_WQ0TIMO_msw = HI(4); + cib->cib_WQ0TIMO_lsw = LO(4); + cib->cib_VMETIMO_msw = 0; /*HI(VME_BUS_TIMEOUT);*/ + cib->cib_VMETIMO_lsw = 0; /*LO(VME_BUS_TIMEOUT);*/ + cib->cib_SBRIV = sc->sc_ipl << 8; + cib->cib_SBRIV |= sc->sc_evec; + cib->cib_SOF0 = 0x15; + cib->cib_SRATE0 = 100/4; + cib->cib_SOF1 = 0x0; + cib->cib_SRATE1 = 0x0; + + iopb = (M328_IOPB *)&sc->sc_vsreg->sh_MCE_IOPB; + bzero(iopb, sizeof(M328_IOPB)); + iopb->iopb_CMD = CNTR_INIT; + iopb->iopb_OPTION = 0; + iopb->iopb_NVCT = (u_char)sc->sc_nvec; + iopb->iopb_EVCT = (u_char)sc->sc_evec; + iopb->iopb_LEVEL = 0; /*sc->sc_ipl;*/ + iopb->iopb_ADDR = SHIO_MOD; + LV(iopb->iopb_BUFF, OFF(cib)); + LV(iopb->iopb_LENGTH, sizeof(M328_CIB)); + + bzero(mc, sizeof(M328_CQE)); + mc->cqe_IOPB_ADDR = OFF(iopb); + mc->cqe_IOPB_LENGTH = sizeof(M328_IOPB); + mc->cqe_WORK_QUEUE = 0; + mc->cqe_QECR = M_QECR_GO; + /* poll for the command to complete */ + do_vspoll(sc, 0); + CRB_CLR_DONE(CRSW); + + /* initialize work queues */ + for (i=1; i<8; i++) { + bzero(wiopb, sizeof(M328_IOPB)); + wiopb->wqcf_CMD = CNTR_INIT_WORKQ; + wiopb->wqcf_OPTION = 0; + wiopb->wqcf_NVCT = (u_char)sc->sc_nvec; + wiopb->wqcf_EVCT = (u_char)sc->sc_evec; + wiopb->wqcf_ILVL = 0; /*sc->sc_ipl;*/ + wiopb->wqcf_WORKQ = i; + wiopb->wqcf_WOPT = (WQO_FOE | WQO_INIT); + wiopb->wqcf_SLOTS = JAGUAR_MAX_Q_SIZ; + LV(wiopb->wqcf_CMDTO, 2); + + bzero(mc, sizeof(M328_CQE)); + mc->cqe_IOPB_ADDR = OFF(wiopb); + mc->cqe_IOPB_LENGTH = sizeof(M328_IOPB); + mc->cqe_WORK_QUEUE = 0; + mc->cqe_QECR = M_QECR_GO; + /* poll for the command to complete */ + do_vspoll(sc, 0); + if (CRSW & M_CRSW_ER) { + printf("error: queue %d status = 0x%x\n", i, riopb->iopb_STATUS); + /*failed = 1;*/ + CRB_CLR_ER(CRSW); + } + CRB_CLR_DONE(CRSW); + delay(1000); + } + /* start queue mode */ + CRSW = 0; + mcsb->mcsb_MCR |= M_MCR_SQM; + crsw = CRSW; + do_vspoll(sc, 0); + if (CRSW & M_CRSW_ER) { + printf("error: status = 0x%x\n", riopb->iopb_STATUS); + CRB_CLR_ER(CRSW); + } + CRB_CLR_DONE(CRSW); + + if (failed) { + printf(": failed!\n"); + return; + } + /* reset SCSI bus */ + vs_reset(sc); + /* sync all devices */ + vs_resync(sc); + printf(": target %d\n", sc->sc_link.adapter_target); +} + +void +vs_resync(sc) + struct vs_softc *sc; +{ + M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE; + M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB; + M328_DRCF *devreset = (M328_DRCF *)&sc->sc_vsreg->sh_MCE_IOPB; + u_short i; + + for (i=0; i<7; i++) { + bzero(devreset, sizeof(M328_DRCF)); + devreset->drcf_CMD = CNTR_DEV_REINIT; + devreset->drcf_OPTION = 0x00; /* no interrupts yet... */ + devreset->drcf_NVCT = sc->sc_nvec; + devreset->drcf_EVCT = sc->sc_evec; + devreset->drcf_ILVL = 0; + devreset->drcf_UNIT = i; + + bzero(mc, sizeof(M328_CQE)); + mc->cqe_IOPB_ADDR = OFF(devreset); + mc->cqe_IOPB_LENGTH = sizeof(M328_DRCF); + mc->cqe_WORK_QUEUE = 0; + mc->cqe_QECR = M_QECR_GO; + /* poll for the command to complete */ + do_vspoll(sc, 0); + if (riopb->iopb_STATUS) { + sc->sc_tinfo[i].avail = 0; + } else { + sc->sc_tinfo[i].avail = 1; + } + if (CRSW & M_CRSW_ER) { + CRB_CLR_ER(CRSW); + } + CRB_CLR_DONE(CRSW); + } +} + +void +vs_reset(sc) + struct vs_softc *sc; +{ + struct vsreg * rp; + u_int s; + u_char i; + struct iopb_reset* iopr; + struct cqe *cqep; + struct iopb_scsi *iopbs; + struct scsi_sense *ss; + M328_CIB *cib = (M328_CIB *)&sc->sc_vsreg->sh_CIB; + M328_CQE *mc = (M328_CQE*)&sc->sc_vsreg->sh_MCE; + M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB; + M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB; + M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB; + M328_SRCF *reset = (M328_SRCF *)&sc->sc_vsreg->sh_MCE_IOPB; + M328_IOPB *iopb; + + bzero(reset, sizeof(M328_SRCF)); + reset->srcf_CMD = IOPB_RESET; + reset->srcf_OPTION = 0x00; /* no interrupts yet... */ + reset->srcf_NVCT = sc->sc_nvec; + reset->srcf_EVCT = sc->sc_evec; + reset->srcf_ILVL = 0; + reset->srcf_BUSID = 0; + s = splbio(); + + bzero(mc, sizeof(M328_CQE)); + mc->cqe_IOPB_ADDR = OFF(reset); + mc->cqe_IOPB_LENGTH = sizeof(M328_SRCF); + mc->cqe_WORK_QUEUE = 0; + mc->cqe_QECR = M_QECR_GO; + /* poll for the command to complete */ + while(1){ + do_vspoll(sc, 0); + /* ack & clear scsi error condition cause by reset */ + if (CRSW & M_CRSW_ER) { + CRB_CLR_ER(CRSW); + CRB_CLR_DONE(CRSW); + riopb->iopb_STATUS = 0; + break; + } + CRB_CLR_DONE(CRSW); + } + /* thaw all work queues */ + thaw_queue(sc, 0xFF); + splx (s); +} + + +/* + * Process an interrupt from the MVME328 + * We'll generally update: xs->{flags,resid,error,sense,status} and + * occasionally xs->retries. + */ + +int +vs_checkintr(sc, xs, status) + struct vs_softc *sc; + struct scsi_xfer *xs; + int *status; +{ + struct vsreg * rp = sc->sc_vsreg; + int target = -1; + int lun = -1; + M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB; + M328_IOPB *riopb = (M328_IOPB *)&sc->sc_vsreg->sh_RET_IOPB; + struct scsi_generic *cmd; + u_long buf; + u_long len; + u_char error; + + target = xs->sc_link->target; + lun = xs->sc_link->lun; + cmd = (struct scsi_generic *)&riopb->iopb_SCSI[0]; + + VL(buf, riopb->iopb_BUFF); + VL(len, riopb->iopb_LENGTH); + *status = riopb->iopb_STATUS >> 8; + error = riopb->iopb_STATUS & 0xFF; + +#ifdef SDEBUG + printf("scsi_chk() "); + + if (xs->cmd->opcode == 0){ + printf("TEST_UNIT_READY "); + } else if (xs->cmd->opcode == REQUEST_SENSE) { + printf("REQUEST_SENSE "); + } else if (xs->cmd->opcode == INQUIRY) { + printf("INQUIRY "); + } else if (xs->cmd->opcode == MODE_SELECT) { + printf("MODE_SELECT "); + } else if (xs->cmd->opcode == MODE_SENSE) { + printf("MODE_SENSE "); + } else if (xs->cmd->opcode == START_STOP) { + printf("START_STOP "); + } else if (xs->cmd->opcode == RESERVE) { + printf("RESERVE "); + } else if (xs->cmd->opcode == RELEASE) { + printf("RELEASE "); + } else if (xs->cmd->opcode == PREVENT_ALLOW) { + printf("PREVENT_ALLOW "); + } else if (xs->cmd->opcode == POSITION_TO_ELEMENT) { + printf("POSITION_TO_EL "); + } else if (xs->cmd->opcode == CHANGE_DEFINITION) { + printf("CHANGE_DEF "); + } else if (xs->cmd->opcode == MODE_SENSE_BIG) { + printf("MODE_SENSE_BIG "); + } else if (xs->cmd->opcode == MODE_SELECT_BIG) { + printf("MODE_SELECT_BIG "); + } else if (xs->cmd->opcode == 0x25) { + printf("READ_CAPACITY "); + } else if (xs->cmd->opcode == 0x08) { + printf("READ_COMMAND "); + } + + printf("tgt %d lun %d buf %x len %d status %x ", target, lun, buf, len, riopb->iopb_STATUS); + + if (CRSW & M_CRSW_EX) { + printf("[ex]"); + } + if (CRSW & M_CRSW_QMS) { + printf("[qms]"); + } + if (CRSW & M_CRSW_SC) { + printf("[sc]"); + } + if (CRSW & M_CRSW_SE) { + printf("[se]"); + } + if (CRSW & M_CRSW_AQ) { + printf("[aq]"); + } + if (CRSW & M_CRSW_ER) { + printf("[er]"); + } + printf("\n"); +#endif + if (len != xs->datalen) { + xs->resid = xs->datalen - len; + } else { + xs->resid = 0; + } + + if (error == SCSI_SELECTION_TO) { + xs->error = XS_SELTIMEOUT; + xs->status = -1; + *status = -1; + } + return 1; +} + +int +vs_intr (sc) + register struct vs_softc *sc; +{ + M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB; + struct scsi_xfer *xs; + unsigned long loc; + int status; + int s; + s = splbio(); + /* Got a valid interrupt on this device */ + + VL(loc, crb->crb_CTAG); +#ifdef SDEBUG + printf("Interrupt!!! "); + printf("loc == 0x%x\n", loc); +#endif + /* + * If this is a controller error, there won't be a scsi_xfer + * pointer in the CTAG feild. Bad things happen if you try + * to point to address 0. Controller error should be handeled + * in m328dma.c I'll change this soon - steve. + */ + if (loc) { + xs = (struct scsi_xfer *)loc; + if (vs_checkintr (sc, xs, &status)) { + vs_scsidone(xs, status); + } + } + splx(s); +} + + diff --git a/sys/arch/mvme88k/dev/vsdma.c b/sys/arch/mvme88k/dev/vsdma.c new file mode 100644 index 00000000000..c8a3186d0ab --- /dev/null +++ b/sys/arch/mvme88k/dev/vsdma.c @@ -0,0 +1,197 @@ +/* $OpenBSD: vsdma.c,v 1.1 1999/05/29 04:41:44 smurph Exp $ */ +/* + * Copyright (c) 1999 Steve Murphree, Jr. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vsdma.c + */ + +/* + * MVME328 scsi adaptor driver + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> +#include <machine/autoconf.h> + +#if defined(MVME187) +#include <machine/board.h> +#include <mvme88k/dev/vsreg.h> +#include <mvme88k/dev/vsvar.h> +#include <mvme88k/dev/vme.h> +#include "machine/mmu.h" +#else +#include <mvme68k/dev/vsreg.h> +#include <mvme68k/dev/vsvar.h> +#include <mvme68k/dev/vme.h> +#endif /* defined(MVME187) */ + +int vsmatch __P((struct device *, void *, void *)); +void vsattach __P((struct device *, struct device *, void *)); +int vsprint __P((void *auxp, char *)); +void vs_initialize __P((struct vs_softc *)); +int vs_intr __P((struct vs_softc *)); +int vs_nintr __P((struct vs_softc *)); +int vs_eintr __P((struct vs_softc *)); + +struct scsi_adapter vs_scsiswitch = { + vs_scsicmd, + vs_minphys, + 0, /* no lun support */ + 0, /* no lun support */ +}; + +struct scsi_device vs_scsidev = { + NULL, /* use default error handler */ + NULL, /* do not have a start function */ + NULL, /* have no async handler */ + NULL, /* Use default done routine */ +}; + +struct cfattach vs_ca = { + sizeof(struct vs_softc), vsmatch, vsattach, +}; + +struct cfdriver vs_cd = { + NULL, "vs", DV_DULL, 0 +}; + +int +vsmatch(pdp, vcf, args) + struct device *pdp; + void *vcf, *args; +{ + struct cfdata *cf = vcf; + struct confargs *ca = args; + if (!badvaddr(ca->ca_vaddr, 1)) { + if (ca->ca_vec & 0x03) { + printf("vs: bad vector 0x%x\n", ca->ca_vec); + return (0); + } + return(1); + } else { + return (0); + } +} + +void +vsattach(parent, self, auxp) + struct device *parent, *self; + void *auxp; +{ + struct vs_softc *sc = (struct vs_softc *)self; + struct confargs *ca = auxp; + struct vsreg * rp; + int tmp; + extern int cpuspeed; + + sc->sc_vsreg = rp = ca->ca_vaddr; + + sc->sc_ipl = ca->ca_ipl; + sc->sc_nvec = ca->ca_vec + 0; + sc->sc_evec = ca->ca_vec + 1; + sc->sc_link.adapter_softc = sc; + sc->sc_link.adapter_target = 7; + sc->sc_link.adapter = &vs_scsiswitch; + sc->sc_link.device = &vs_scsidev; + sc->sc_link.openings = 1; + + sc->sc_ih_n.ih_fn = vs_nintr; + sc->sc_ih_n.ih_arg = sc; + sc->sc_ih_n.ih_ipl = ca->ca_ipl; + + + sc->sc_ih_e.ih_fn = vs_eintr; + sc->sc_ih_e.ih_arg = sc; + sc->sc_ih_e.ih_ipl = ca->ca_ipl; + + vs_initialize(sc); + + vmeintr_establish(sc->sc_nvec, &sc->sc_ih_n); + vmeintr_establish(sc->sc_evec, &sc->sc_ih_e); + evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt_n); + evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt_e); + + /* + * attach all scsi units on us, watching for boot device + * (see dk_establish). + */ + tmp = bootpart; + if (ca->ca_paddr != bootaddr) + bootpart = -1; /* invalid flag to dk_establish */ + config_found(self, &sc->sc_link, scsiprint); + bootpart = tmp; /* restore old value */ +} + +/* + * print diag if pnp is NULL else just extra + */ +int +vsprint(auxp, pnp) + void *auxp; + char *pnp; +{ + if (pnp == NULL) + return (UNCONF); + return (QUIET); +} + +/* normal interrupt function */ +int +vs_nintr(sc) + struct vs_softc *sc; +{ +#ifdef SDEBUG + printf("Normal Interrupt!!!\n"); +#endif + vs_intr(sc); + sc->sc_intrcnt_n.ev_count++; + return (1); +} + +/* error interrupt function */ +int +vs_eintr(sc) + struct vs_softc *sc; +{ +#ifdef SDEBUG + printf("Error Interrupt!!!\n"); +#endif + vs_intr(sc); + sc->sc_intrcnt_e.ev_count++; + return (1); +} + + diff --git a/sys/arch/mvme88k/dev/vsreg.h b/sys/arch/mvme88k/dev/vsreg.h new file mode 100644 index 00000000000..d722d62e7ea --- /dev/null +++ b/sys/arch/mvme88k/dev/vsreg.h @@ -0,0 +1,695 @@ +/* $OpenBSD: vsreg.h,v 1.1 1999/05/29 04:41:44 smurph Exp $ */ +/* + * Copyright (c) 1999 Steve Murphree, Jr. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from source contributed by Mark Bellon. + * + * 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. + */ + +#if !defined(_M328REG_H_) +#define _M328REG_H_ + +typedef struct LONGV +{ + u_short msw; + u_short lsw; +} LONGV; + +#define MSW(x) ((x).msw) +#define LSW(x) ((x).lsw) + +/* + * macro to convert a unsigned long to a LONGV + */ + +#define LV( a, b) \ +{ \ + MSW( a ) = ( (( (unsigned long)(b) ) >> 16) & 0xffff ); \ + LSW( a ) = ( ( (unsigned long)(b) ) & 0xffff); \ +} + +/* + * macro to convert a LONGV to a unsigned long + */ + +#define VL( a, b) \ +{ \ + a = ( (((unsigned long) MSW(b)) << 16 ) | (((unsigned long) LSW(b)) & 0x0ffff) ); \ +} + +#define COUGAR 0x4220 /* board type (config. status area) */ +#define JAGUAR 0 + +/* + * JAGUAR specific device limits. + */ + +#define JAGUAR_MIN_Q_SIZ 2 /* got'a have at least one! */ +#define JAGUAR_MAX_Q_SIZ 2 /* can't have more */ +#define JAGUAR_MAX_CTLR_CMDS 80 /* Interphase says so */ + +/* + * COUGAR specific device limits. + */ + +#define COUGAR_MIN_Q_SIZ 2 /* got'a have at least one! */ +#define COUGAR_CMDS_PER_256K 42 /* Interphase says so */ + +/* + * Structures + */ + +#define NUM_CQE 10 +#define MAX_IOPB 64 +#define NUM_IOPB NUM_CQE +#define S_IOPB_RES (MAX_IOPB - sizeof(M328_short_IOPB)) +#define S_SHORTIO 2048 +#define S_IOPB sizeof(M328_IOPB) +#define S_CIB sizeof(M328_CIB) +#define S_MCSB sizeof(M328_MCSB) +#define S_MCE sizeof(M328_CQE) +#define S_CQE (sizeof(M328_CQE) * NUM_CQE) +#define S_HIOPB (sizeof(M328_IOPB) * NUM_IOPB) +#define S_HSB sizeof(M328_HSB) +#define S_CRB sizeof(M328_CRB) +#define S_CSS sizeof(M328_CSB) +#define S_NOT_HOST (S_MCSB + S_MCE + S_CQE + S_HIOPB + S_IOPB + \ + S_CIB + S_HSB + S_CRB + S_IOPB + S_CSS) +#define S_HUS_FREE (S_SHORTIO - S_NOT_HOST) + +#define S_WQCF sizeof(M328_WQCF) + +#define HOST_ID 0x4321 + + +/**************** Master Control Status Block (MCSB) *******************/ + +/* + * defines for Master Status Register + */ + +#define M_MSR_QFC 0x0004 /* queue flush complete */ +#define M_MSR_BOK 0x0002 /* board OK */ +#define M_MSR_CNA 0x0001 /* controller not available */ + +/* + * defines for Master Control Register + */ + +#define M_MCR_SFEN 0x2000 /* sysfail enable */ +#define M_MCR_RES 0x1000 /* reset controller */ +#define M_MCR_FLQ 0x0800 /* flush queue */ +#define M_MCR_FLQR 0x0004 /* flush queue and report */ +#define M_MCR_SQM 0x0001 /* start queue mode */ + +/* + * defines for Interrupt on Queue Available Register + */ + +#define M_IQAR_IQEA 0x8000 /* interrupt on queue entry avail */ +#define M_IQAR_IQEH 0x4000 /* interrupt on queue half empty */ +#define M_IQAR_ILVL 0x0700 /* interrupt lvl on queue avaliable */ +#define M_IQAR_IVCT 0x00FF /* interrupt vector on queue avail */ + +/* + * defines for Thaw Work Queue Register + */ + +#define M_THAW_TWQN 0xff00 /* thaw work queue number */ +#define M_THAW_TWQE 0x0001 /* thaw work queue enable */ + +typedef struct mcsb +{ /* Master control/Status Block */ + volatile u_short mcsb_MSR; /* Master status register */ + volatile u_short mcsb_MCR; /* Master Control register */ + volatile u_short mcsb_IQAR; /* Interrupt on Queue Available Reg */ + volatile u_short mcsb_QHDP; /* Queue head pointer */ + volatile u_short mcsb_THAW; /* Thaw work Queue */ + volatile u_short mcsb_RES0; /* Reserved word 0 */ + volatile u_short mcsb_RES1; /* Reserved word 1 */ + volatile u_short mcsb_RES2; /* Reserved word 2 */ +} M328_MCSB; + +/**************** END Master Control Status Block (MCSB) *******************/ + + +/**************** Host Semaphore Block (HSB) *******************/ + +typedef struct hsb +{ /* Host Semaphore Block */ + volatile u_short hsb_INITQ; /* Init MCE Flag */ + volatile u_short hsb_WORKQ; /* Work Queue number */ + volatile u_short hsb_MAGIC; /* Magic word */ + volatile u_short hsb_RES0; /* Reserved word */ +} M328_HSB; + +/**************** END Host Semaphore Block (HSB) *******************/ + +/**************** Perform Diagnostics Command Format *******************/ + +typedef struct pdcf +{ /* Perform Diagnostics Cmd Format */ + volatile u_short pdcf_CMD; /* Command normally 0x40 */ + volatile u_short pdcf_RES0; /* Reserved word */ + volatile u_short pdcf_STATUS; /* Return Status */ + volatile u_short pdcf_RES1; /* Reserved Word */ + volatile u_short pdcf_ROM; /* ROM Test Results */ + volatile u_short pdcf_BUFRAM; /* Buffer RAM results */ + volatile u_short pdcf_EVENT_RAM; /* Event Ram test Results */ + volatile u_short pdcf_SCSI_PRI_PORT; /* SCSI Primary Port Reg test */ + volatile u_short pdcf_SCSI_SEC_PORT; /* SCSI Secondary Port Reg test */ +} M328_PDCF; + +#define PDCF_SUCCESS 0xFFFF + +/**************** END Perform Diagnostics Command Format *******************/ + +/*************** Controller Initialization Block (CIB) *****************/ + +/* + * defines for Interrupt Vectors + */ + +#define M_VECT_ILVL 0x0700 /* Interrupt Level */ +#define M_VECT_IVCT 0x00FF /* Interrupt Vector */ + +/* + * defines for SCSI Bus ID Registers + */ + +#define M_PSID_DFT 0x0008 /* default ID enable */ +#define M_PSID_ID 0x0007 /* Primary/Secondary SCSI ID */ + +/* + * Error recovery flags. + */ + +#define M_ERRFLGS_FOSR 0x0001 /* Freeze on SCSI bus reset */ +#define M_ERRFLGS_RIN 0x0002 /* SCSI bus reset interrupt */ +#define M_ERRFLGS_RSE 0x0004 /* Report COUGAR SCSI errors */ + +/* + * Controller Initialization Block + */ + +typedef struct cib +{ + volatile u_short cib_NCQE; /* Number of Command Queue Entries */ + volatile u_short cib_BURST; /* DMA Burst count */ + volatile u_short cib_NVECT; /* Normal Completion Vector */ + volatile u_short cib_EVECT; /* Error Completion Vector */ + volatile u_short cib_PID; /* Primary SCSI Bus ID */ + volatile u_short cib_SID; /* Secondary SCSI Bus ID */ + volatile u_short cib_CRBO; /* Command Response Block Offset */ + volatile u_short cib_SELECT_msw;/* Selection timeout in milli_second */ + volatile u_short cib_SELECT_lsw;/* Selection timeout in milli_second */ + volatile u_short cib_WQ0TIMO_msw;/* Work Q - timeout in 256 ms */ + volatile u_short cib_WQ0TIMO_lsw;/* Work Q - timeout in 256 ms */ + volatile u_short cib_VMETIMO_msw;/* VME Time out in 32 ms */ + volatile u_short cib_VMETIMO_lsw;/* VME Time out in 32 ms */ + volatile u_short cib_RES0[2]; /* Reserved words */ + volatile u_short cib_OBMT; /* offbrd CRB mtype/xfer type/ad mod */ + volatile u_short cib_OBADDR_msw;/* host mem address for offboard CRB */ + volatile u_short cib_OBADDR_lsw;/* host mem address for offboard CRB */ + volatile u_short cib_ERR_FLGS; /* error recovery flags */ + volatile u_short cib_RES1; /* reserved word */ + volatile u_short cib_RES2; /* reserved word */ + volatile u_short cib_SBRIV; /* SCSI Bus Reset Interrupt Vector */ + volatile u_char cib_SOF0; /* Synchronous offset (Bus 0) */ + volatile u_char cib_SRATE0; /* Sync negotiation rate (Bus 0) */ + volatile u_char cib_SOF1; /* Synchronous offset (Bus 1) */ + volatile u_char cib_SRATE1; /* Sync negotiation rate (Bus 1) */ +} M328_CIB; + +/**************** END Controller Initialization Block (CIB) *****************/ + +/**************** Command Queue Entry (CQE) *******************/ + +/* + * defines for Queue Entry Control Register + */ + +#define M_QECR_IOPB 0x0F00 /* IOPB type (must be zero) */ +#define M_QECR_HPC 0x0004 /* High Priority command */ +#define M_QECR_AA 0x0002 /* abort acknowledge */ +#define M_QECR_GO 0x0001 /* Go/Busy */ + +#define CQE_GO(qecr) ((qecr) |= M_QECR_GO) +#define CQE_AA_GO(qecr) ((qecr) |= (M_QECR_GO + M_QECR_AA)) + +typedef struct cqe +{ /* Command Queue Entry */ + volatile u_short cqe_QECR; /* Queue Entry Control Register */ + volatile u_short cqe_IOPB_ADDR; /* IOPB Address */ + volatile LONGV cqe_CTAG; /* Command Tag */ + volatile u_char cqe_IOPB_LENGTH;/* IOPB Length */ + volatile u_char cqe_WORK_QUEUE; /* Work Queue Number */ + volatile u_short cqe_RES0; /* Reserved word */ +} M328_CQE; + +/**************** END Command Queue Entry (CQE) *******************/ + +/**************** Command Response Block (CRB) *******************/ + +/* + * defines for Command Response Status Word + */ + +#define M_CRSW_SE 0x0800 /* SCSI error (COUGAR) */ +#define M_CRSW_RST 0x0400 /* SCSI Bus reset (COUGAR) */ +#define M_CRSW_SC 0x0080 /* status change */ +#define M_CRSW_CQA 0x0040 /* Command queue entry available */ +#define M_CRSW_QMS 0x0020 /* queue mode started */ +#define M_CRSW_AQ 0x0010 /* abort queue */ +#define M_CRSW_EX 0x0008 /* exception */ +#define M_CRSW_ER 0x0004 /* error */ +#define M_CRSW_CC 0x0002 /* command complete */ +#define M_CRSW_CRBV 0x0001 /* cmd response block valid/clear */ + +#define CRB_CLR_DONE(crsw) ((crsw) = 0) +#define CRB_CLR_ER(crsw) ((crsw) &= ~M_CRSW_ER) + +typedef struct crb +{ /* Command Response Block */ + volatile u_short crb_CRSW; /* Command Response Status Word */ + volatile u_short crb_RES0; /* Reserved word */ + volatile LONGV crb_CTAG; /* Command Tag */ + volatile u_char crb_IOPB_LENGTH;/* IOPB Length */ + volatile u_char crb_WORK_QUEUE; /* Work Queue Number */ + volatile u_short crb_RES1; /* Reserved word */ +} M328_CRB; + +/**************** END Command Response Block (CRB) *******************/ + +/*********** Controller Error Vector Status Block (CEVSB) **************/ + +typedef struct cevsb +{ /* Command Response Block */ + volatile u_short cevsb_CRSW; /* Command Response Status Word */ + volatile u_char cevsb_TYPE; /* IOPB type */ + volatile u_char cevsb_RES0; /* Reserved byte */ + volatile LONGV cevsb_CTAG; /* Command Tag */ + volatile u_char cevsb_IOPB_LENGTH;/* IOPB Length */ + volatile u_char cevsb_WORK_QUEUE;/* Work Queue Number */ + volatile u_short cevsb_RES1; /* Reserved word */ + volatile u_char cevsb_RES2; /* Reserved byte */ + volatile u_char cevsb_ERROR; /* error code */ + volatile u_short cevsb_AUXERR; /* COUGAR error code */ +} M328_CEVSB; + +/*********** END Controller Error Vector Status Block (CEVSB) **************/ + +/**************** Configuration Status Block (CSB) *******************/ + +typedef struct csb +{ /* Configuration Status Blk */ + volatile u_short csb_TYPE; /* 0x0=JAGUAR, 0x4220=COUGAR */ + volatile u_char csb_RES1; /* Reserved byte */ + volatile u_char csb_PCODE[3]; /* Product Code */ + volatile u_short csb_RES2; /* Reserved word */ + volatile u_char csb_RES3; /* Reserved byte */ + volatile u_char csb_PVAR; /* Product Variation */ + volatile u_short csb_RES4; /* Reserved word */ + volatile u_char csb_RES5; /* Reserved byte */ + volatile u_char csb_FREV[3]; /* Firmware Revision level */ + volatile u_short csb_RES6; /* Reserved word */ + volatile u_char csb_FDATE[8]; /* Firmware Release date */ + volatile u_short csb_SSIZE; /* System memory size in Kbytes */ + volatile u_short csb_BSIZE; /* Buffer memory size in Kbytes */ + volatile u_short csb_RES8; /* Reserved word */ + volatile u_char csb_PFECID; /* Primary Bus FEC ID */ + volatile u_char csb_SFECID; /* Secondard Bus FEC ID */ + volatile u_char csb_PID; /* Primary Bus ID */ + volatile u_char csb_SID; /* Secondary Bus ID */ + volatile u_char csb_LPDS; /* Last Primary Device Selected */ + volatile u_char csb_LSDS; /* Last Secondary Device Selected */ + volatile u_char csb_PPS; /* Primary Phase Sense */ + volatile u_char csb_SPS; /* Secondary Phase Sense */ + volatile u_char csb_RES10; /* Reserved byte */ + volatile u_char csb_DBID; /* Daughter Board ID */ + volatile u_char csb_RES11; /* Reserved byte */ + volatile u_char csb_SDS; /* Software DIP Switch */ + volatile u_short csb_RES12; /* Reserved word */ + volatile u_short csb_FWQR; /* Frozen Work Queues Register */ + volatile u_char csb_RES13[72]; /* Reserved bytes */ +} M328_CSB; + +/**************** END Configuration Status Block (CSB) *******************/ + +/**************** IOPB Format (IOPB) *******************/ + +/* + * defines for IOPB Option Word + */ + +#define M_OPT_HEAD_TAG 0x3000 /* head of queue command queue tag */ +#define M_OPT_ORDERED_TAG 0x2000 /* order command queue tag */ +#define M_OPT_SIMPLE_TAG 0x1000 /* simple command queue tag */ +#define M_OPT_GO_WIDE 0x0800 /* use WIDE transfers */ +#define M_OPT_DIR 0x0100 /* VME direction bit */ +#define M_OPT_SG_BLOCK 0x0008 /* scatter/gather in 512 byte blocks */ +#define M_OPT_SS 0x0004 /* Suppress synchronous transfer */ +#define M_OPT_SG 0x0002 /* scatter/gather bit */ +#define M_OPT_IE 0x0001 /* Interrupt enable */ + +/* + * defines for IOPB Address Type and Modifier + */ + +#define M_ADR_TRANS 0x0C00 /* transfer type */ +#define M_ADR_MEMT 0x0300 /* memory type */ +#define M_ADR_MOD 0x00FF /* VME address modifier */ + +/* + * defines for IOPB Unit Address on SCSI Bus + */ + +#define M_UNIT_EXT_LUN 0xFF00 /* Extended Address */ +#define M_UNIT_EXT 0x0080 /* Extended Address Enable */ +#define M_UNIT_BUS 0x0040 /* SCSI Bus Selection */ +#define M_UNIT_LUN 0x0038 /* Logical Unit Number */ +#define M_UNIT_ID 0x0007 /* SCSI Device ID */ + +typedef struct short_iopb +{ + volatile u_short iopb_CMD; /* IOPB Command code */ + volatile u_short iopb_OPTION; /* IOPB Option word */ + volatile u_short iopb_STATUS; /* IOPB Return Status word */ + volatile u_short iopb_RES0; /* IOPB Reserved word */ + volatile u_char iopb_NVCT; /* IOPB Normal completion Vector */ + volatile u_char iopb_EVCT; /* IOPB Error completion Vector */ + volatile u_short iopb_LEVEL; /* IOPB Interrupt Level */ + volatile u_short iopb_RES1; /* IOPB Reserved word */ + volatile u_short iopb_ADDR; /* IOPB Address type and modifer */ + volatile LONGV iopb_BUFF; /* IOPB Buffer Address */ + volatile LONGV iopb_LENGTH; /* IOPB Max-Transfer Length */ + volatile u_short iopb_RES2; /* IOPB Reserved word */ + volatile u_short iopb_RES3; /* IOPB Reserved word */ + volatile u_short iopb_RES4; /* IOPB Reserved word */ + volatile u_short iopb_UNIT; /* IOPB Unit address on SCSI bus */ +} M328_short_IOPB; + +typedef struct iopb +{ + volatile u_short iopb_CMD; /* IOPB Command code */ + volatile u_short iopb_OPTION; /* IOPB Option word */ + volatile u_short iopb_STATUS; /* IOPB Return Status word */ + volatile u_short iopb_RES0; /* IOPB Reserved word */ + volatile u_char iopb_NVCT; /* IOPB Normal completion Vector */ + volatile u_char iopb_EVCT; /* IOPB Error completion Vector */ + volatile u_short iopb_LEVEL; /* IOPB Interrupt Level */ + volatile u_short iopb_RES1; /* IOPB Reserved word */ + volatile u_short iopb_ADDR; /* IOPB Address type and modifer */ + volatile LONGV iopb_BUFF; /* IOPB Buffer Address */ + volatile LONGV iopb_LENGTH; /* IOPB Max-Transfer Length */ + volatile u_short iopb_RES2; /* IOPB Reserved word */ + volatile u_short iopb_RES3; /* IOPB Reserved word */ + volatile u_short iopb_RES4; /* IOPB Reserved word */ + volatile u_short iopb_UNIT; /* IOPB Unit address on SCSI bus */ + u_short iopb_SCSI[S_IOPB_RES/2]; /* IOPB SCSI words for pass thru */ +} M328_IOPB; + +/**************** END IOPB Format (IOPB) *******************/ + +/**************** Initialize Work Queue Command Format (WQCF) ***********/ + +#define M_WOPT_IWQ 0x8000 /* initialize work queue */ +#define M_WOPT_PE 0x0008 /* parity check enable */ +#define M_WOPT_FE 0x0004 /* freeze on error enable */ +#define M_WOPT_TM 0x0002 /* target mode enable */ +#define M_WOPT_AE 0x0001 /* abort enable */ + +typedef struct wqcf +{ /* Initialize Work Queue Cmd Format*/ + volatile u_short wqcf_CMD; /* Command Normally (0x42) */ + volatile u_short wqcf_OPTION; /* Command Options */ + volatile u_short wqcf_STATUS; /* Return Status */ + volatile u_short wqcf_RES0; /* Reserved word */ + volatile u_char wqcf_NVCT; /* Normal Completion Vector */ + volatile u_char wqcf_EVCT; /* Error Completion Vector */ + volatile u_short wqcf_ILVL; /* Interrupt Level */ + volatile u_short wqcf_RES1[8]; /* Reserved words */ + volatile u_short wqcf_WORKQ; /* Work Queue Number */ + volatile u_short wqcf_WOPT; /* Work Queue Options */ + volatile u_short wqcf_SLOTS; /* Number of slots in Work Queues */ + volatile u_short wqcf_RES2; /* Reserved word */ + volatile LONGV wqcf_CMDTO; /* Command timeout */ + volatile u_short wqcf_RES3; /* Reserved word */ +} M328_WQCF; + +/**************** END Initialize Work Queue Command Format (WQCF) ***********/ + +/**************** SCSI Reset Command Format (SRCF) ***********/ + +typedef struct srcf +{ /* SCSI Reset Cmd Format*/ + volatile u_short srcf_CMD; /* Command Normally (0x22) */ + volatile u_short srcf_OPTION; /* Command Options */ + volatile u_short srcf_STATUS; /* Return Status */ + volatile u_short srcf_RES0; /* Reserved word */ + volatile u_char srcf_NVCT; /* Normal Completion Vector */ + volatile u_char srcf_EVCT; /* Error Completion Vector */ + volatile u_short srcf_ILVL; /* Interrupt Level */ + volatile u_short srcf_RES1[8]; /* Reserved words */ + volatile u_short srcf_BUSID; /* SCSI bus ID to reset */ +} M328_SRCF; + +/**************** END SCSI Reset Command Format (SRCF) ***********/ + +/**************** Device Reinitialize Command Format (DRCF) ***********/ + +typedef struct drcf +{ /* Device Reinitialize Cmd Format*/ + volatile u_short drcf_CMD; /* Command Normally (0x4C) */ + volatile u_short drcf_OPTION; /* Command Options */ + volatile u_short drcf_STATUS; /* Return Status */ + volatile u_short drcf_RES0; /* Reserved word */ + volatile u_char drcf_NVCT; /* Normal Completion Vector */ + volatile u_char drcf_EVCT; /* Error Completion Vector */ + volatile u_short drcf_ILVL; /* Interrupt Level */ + volatile u_short drcf_RES1[9]; /* Reserved words */ + volatile u_short drcf_UNIT; /* Unit Address */ +} M328_DRCF; + +/**************** END SCSI Reset Command Format (SRCF) ***********/ + +/**************** Host Down Loadable Firmware (HDLF) ***********/ + +typedef struct hdlf +{ /* Host Down Loadable Firmware cmd */ + volatile u_short hdlf_CMD; /* Command Normally (0x4F) */ + volatile u_short hdlf_OPTION; /* Command Options */ + volatile u_short hdlf_STATUS; /* Return Status */ + volatile u_short hdlf_RES0; /* Reserved word */ + volatile u_char hdlf_NVCT; /* Normal Completion Vector */ + volatile u_char hdlf_EVCT; /* Error Completion Vector */ + volatile u_short hdlf_ILVL; /* Interrupt Level */ + volatile u_short hdlf_RES1; /* Reserved word */ + volatile u_short hdlf_ADDR; /* Address type and modifer */ + volatile LONGV hdlf_BUFF; /* Buffer Address */ + volatile LONGV hdlf_LENGTH; /* Max-Transfer Length */ + volatile LONGV hdlf_CSUM; /* Checksum */ + volatile u_short hdlf_RES2; /* Reserved word */ + volatile u_short hdlf_SEQ; /* Sequence number */ + volatile u_short hdlf_RES3[6]; /* Reserved words */ +} M328_HDLF; + +#define M328_INITIALIZE_DOWNLOAD 0x0010 +#define M328_TRANSFER_PACKET 0x0020 +#define M328_PROGRAM_FLASH 0x0040 +#define M328_MOTOROLA_S_RECORDS 0x1000 + +/**************** END SCSI Reset Command Format (SRCF) ***********/ + +/**************** Short I/O Format *******************/ + +struct vsreg +{ + M328_MCSB sh_MCSB; /* Master Control / Status Block */ + M328_CQE sh_MCE; /* Master Command Entry */ + M328_CQE sh_CQE[NUM_CQE]; /* Command Queue Entry */ + M328_IOPB sh_IOPB[NUM_IOPB]; /* Host IOPB Space */ + M328_IOPB sh_MCE_IOPB; /* Host MCE IOPB Space */ + M328_CIB sh_CIB; /* Controller Initialization Block */ + volatile u_char sh_HUS[S_HUS_FREE];/* Host Usable Space */ + M328_HSB sh_HSB; /* Host Semaphore Block */ + M328_CRB sh_CRB; /* Command Response Block */ + M328_IOPB sh_RET_IOPB; /* Returned IOPB */ + M328_CSB sh_CSS; /* Controller Specific Space/Block */ +}; + +#define CRSW sc->sc_vsreg->sh_CRB.crb_CRSW +#define THAW_REG sc->sc_vsreg->sh_MCSB.mcsb_THAW +#define THAW(x) THAW_REG=((u_char)x << 8);THAW_REG |= M_THAW_TWQE +#define QUEUE_FZN(x) (sc->sc_vsreg->sh_CSS.csb_FWQR & (1 << x)) +#define SELECTION_TIMEOUT 250 /* milliseconds */ +#define VME_BUS_TIMEOUT 0xF /* units of 30ms */ +#define M328_INFINITE_TIMEOUT 0 /* wait forever */ + +/**************** END Short I/O Format *******************/ + +/* + * Scatter gather structure + */ + +typedef struct ipsg +{ + volatile u_short sg_count; /* byte/entry count */ + volatile u_short sg_addrhi; /* datablock/entry address high */ + volatile u_short sg_addrlo; /* datablock/entry address low */ + volatile u_short sg_meminfo; /* memory information */ +}IPSG; + +#define MACSI_SG 256 /* number of MACSI scat/gat entries */ +#define S_MACSI_SG (MACSI_SG * sizeof(IPSG)) +#define MACSI_SG_RSIZE 65535 /* max len of each scatter/gather entry */ + +/* + * SCSI IOPB definitions + */ + +#define IOPB_PASS_THRU 0x20 /* SCSI Pass Through commands */ +#define IOPB_PASS_THRU_EXT 0x21 /* SCSI Pass Through Extended commands */ +#define IOPB_RESET 0x22 /* SCSI Reset bus */ + +/* + * SCSI Control IOPB's + */ + +#define CNTR_DIAG 0x40 /* Perform Diagnostics */ +#define CNTR_INIT 0x41 /* Initialize Controller */ +#define CNTR_INIT_WORKQ 0x42 /* Initialize Work Queue */ +#define CNTR_DUMP_INIT 0x43 /* Dump Initialization Parameters */ +#define CNTR_DUMP_WORDQ 0x44 /* Dump work Queue Parameters */ +#define CNTR_CANCEL_IOPB 0x48 /* Cancel command tag */ +#define CNTR_FLUSH_WORKQ 0x49 /* Flush Work Queue */ +#define CNTR_DEV_REINIT 0x4C /* Reinitialize Device */ +#define CNTR_ISSUE_ABORT 0x4E /* An abort has been issued */ +#define CNTR_DOWNLOAD_FIRMWARE 0x4F /* Download firmware (COUGAR) */ + +/* + * Memory types + */ + +#define MEMT_16BIT 1 /* 16 Bit Memory type */ +#define MEMT_32BIT 2 /* 32 Bit Memory type */ +#define MEMT_SHIO 3 /* Short I/O Memory type */ +#define MEMTYPE MEMT_32BIT /* do 32-bit transfers */ + +/* + * Transfer types + */ + +#define TT_NORMAL 0 /* Normal Mode Tranfers */ +#define TT_BLOCK 1 /* block Mode Tranfers */ +#define TT_DISABLE_INC_ADDR 2 /* Disable Incrementing Addresses */ +#define TT_D64 3 /* D64 Mode Transfers */ + +/* + * Error codes. + */ + +#define MACSI_GOOD_STATUS 0x00 /* Good status */ +#define MACSI_QUEUE_FULL 0x01 /* The work queue is full */ +#define MACSI_CMD_CODE_ERR 0x04 /* The IOPB command field is invalid */ +#define MACSI_QUEUE_NUMBER_ERR 0x05 /* Invalid queue number */ + +#define RESET_BUS_STATUS 0x11 /* SCSI bus reset IOPB forced this */ +#define NO_SECONDARY_PORT 0x12 /* second SCSI bus not available */ +#define SCSI_DEVICE_IS_RESET 0x14 /* device has been reset */ +#define CMD_ABORT_BY_RESET 0x15 /* device has been reset */ + +#define VME_BUS_ERROR 0x20 /* There was a VME BUS error */ +#define VME_BUS_ACC_TIMEOUT 0x21 +#define VME_BUS_BAD_ADDR 0x23 +#define VME_BUS_BAD_MEM_TYPE 0x24 +#define VME_BUS_BAD_COUNT 0x25 +#define VME_BUS_FETCH_ERROR 0x26 +#define VME_BUS_FETCH_TIMEOUT 0x27 +#define VME_BUS_POST_ERROR 0x28 +#define VME_BUS_POST_TIMEOUT 0x29 +#define VME_BUS_BAD_FETCH_ADDR 0x2A +#define VME_BUS_BAD_POST_ADDR 0x2B +#define VME_BUS_SG_FETCH 0x2C +#define VME_BUS_SG_TIMEOUT 0x2D +#define VME_BUS_SG_COUNT 0x2E + +#define SCSI_SELECTION_TO 0x30 /* select time out */ +#define SCSI_DISCONNECT_TIMEOUT 0x31 /* disconnect timeout */ +#define SCSI_ABNORMAL_SEQ 0x32 /* abnormal sequence */ +#define SCSI_DISCONNECT_ERR 0x33 /* disconnect error */ +#define SCSI_XFER_EXCEPTION 0x34 /* transfer cnt exception */ +#define SCSI_PARITY_ERROR 0x35 /* parity error */ + +#define DEVICE_NO_IOPB 0x82 /* IOPB no available */ +#define IOPB_CTLR_EHX 0x83 /* IOPB counter exhausted */ +#define IOPB_DIR_ERROR 0x84 /* IOPB direction wrong */ +#define COUGAR_ERROR 0x86 /* COUGAR unrecoverable error */ +#define MACSI_INCORRECT_HARDWARE 0x90 /* Insufficient memory */ +#define MACSI_ILGL_IOPB_VAL 0x92 /* Invalid field in the IOPB */ +#define MACSI_ILLEGAL_IMAGE 0x9C /* Submitted fails reuested action */ +#define IOPB_TYPE_ERR 0xC0 /* IOPB type not 0 */ +#define IOPB_TIMEOUT 0xC1 /* IOPB timed out */ + +#define COUGAR_PANIC 0xFF /* COUGAR paniced */ + +#define MACSI_INVALID_TIMEOUT 0x843 /* The SCSI byte to byte timer expired */ + +/* + * Handy vector macro. + */ + +#define VEC(c, vec) (((c) -> mc_ipl << 8) + (vec)) + +/* + * VME addressing modes + */ + +#define ADRM_STD_S_P 0x3E /* Standard Supervisory Program */ +#define ADRM_STD_S_D 0x3D /* Standard Supervisory Data */ +#define ADRM_STD_N_P 0x3A /* Standard Normal Program */ +#define ADRM_STD_N_D 0x39 /* Standard Normal Data */ +#define ADRM_SHT_S_IO 0x2D /* Short Supervisory IO */ +#define ADRM_SHT_N_IO 0x29 /* Short Normal IO */ +#define ADRM_EXT_S_P 0x0E /* Extended Supervisory Program */ +#define ADRM_EXT_S_D 0x0D /* Extended Supervisory Data */ +#define ADRM_EXT_N_P 0x0A /* Extended Normal Program */ +#define ADRM_EXT_N_D 0x09 /* Extended Normal Data */ +#define ADRM_EXT_S_BM 0x0F /* Extended Supervisory Block Mode */ +#define ADRM_EXT_S_D64 0x0C /* Extended Supervisory D64 Mode */ + +#define ADDR_MOD ( (TT_NORMAL << 10) | (MEMTYPE << 8) | ADRM_EXT_S_D ) +#define BLOCK_MOD ( (TT_BLOCK << 10) | (MEMTYPE << 8) | ADRM_EXT_S_BM ) +#define D64_MOD ( (TT_D64 << 10) | (MEMTYPE << 8) | ADRM_EXT_S_D64 ) +#define SHIO_MOD ( (TT_NORMAL << 10) | (MEMT_SHIO << 8) | ADRM_SHT_N_IO) + +#endif /* _M328REG_H_ */ diff --git a/sys/arch/mvme88k/dev/vsvar.h b/sys/arch/mvme88k/dev/vsvar.h new file mode 100644 index 00000000000..e645971095c --- /dev/null +++ b/sys/arch/mvme88k/dev/vsvar.h @@ -0,0 +1,132 @@ +/* $OpenBSD: vsvar.h,v 1.1 1999/05/29 04:41:44 smurph Exp $ */ +/* + * Copyright (c) 1999 Steve Murphree, Jr. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of 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. + */ +#ifndef _VSVAR_H_ +#define _VSVAR_H_ + +/* + * The largest single request will be MAXPHYS bytes which will require + * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of + * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the + * buffer is not page aligned (+1). + */ +#define DMAMAXIO (MAXPHYS/NBPG+1) +#define LO(x) (u_short)((unsigned long)x & 0x0000FFFF) +#define HI(x) (u_short)((unsigned long)x >> 16) +#define OFF(x) (u_short)((long)kvtop(x) - (long)kvtop(sc->sc_vsreg)) + +struct vs_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; + u_char period; /* Period suggestion */ + u_char offset; /* Offset suggestion */ + int avail; /* Is there a device there */ +} tinfo_t; + +struct vs_softc { + struct device sc_dev; + struct intrhand sc_ih_e; + struct intrhand sc_ih_n; + struct evcnt sc_intrcnt_e; + struct evcnt sc_intrcnt_n; + u_short sc_ipl; + u_short sc_evec; + u_short sc_nvec; + struct scsi_link sc_link; /* proto for sub devices */ + u_long sc_chnl; /* channel 0 or 1 for dual bus cards */ + u_long sc_qhp; /* Command queue head pointer */ + struct vsreg *sc_vsreg; +#define SIOP_NACB 8 + struct vs_tinfo sc_tinfo[8]; + u_char sc_flags; + u_char sc_sien; + u_char sc_dien; + u_char sc_minsync; + struct map *hus_map; + /* one for each target */ + struct syncpar { + u_char state; + u_char sxfer; + u_char sbcl; + } sc_sync[8]; +}; + +/* sync states */ +#define SYNC_START 0 /* no sync handshake started */ +#define SYNC_SENT 1 /* we sent sync request, no answer yet */ +#define SYNC_DONE 2 /* target accepted our (or inferior) settings, + or it rejected the request and we stay async */ + +#define IOPB_SCSI 0x20 +#define IOPB_RESET 0x22 +#define IOPB_INIT 0x41 +#define IOPB_WQINIT 0x42 +#define IOPB_DEV_RESET 0x4D + +#define OPT_INTEN 0x0001 +#define OPT_INTDIS 0x0000 +#define OPT_SG 0x0002 +#define OPT_SST 0x0004 +#define OPT_SIT 0x0040 +#define OPT_READ 0x0000 +#define OPT_WRITE 0x0100 + +#define AM_S32 0x01 +#define AM_S16 0x05 +#define AM_16 0x0100 +#define AM_32 0x0200 +#define AM_SHORT 0x0300 +#define AM_NORMAL 0x0000 +#define AM_BLOCK 0x0400 +#define AM_D64BLOCK 0x0C00 + +#define WQO_AE 0x0001 /* abort enable bit */ +#define WQO_FOE 0x0004 /* freeze on error */ +#define WQO_PE 0x0008 /* parity enable bit */ +#define WQO_ARE 0x0010 /* autosense recovery enable bit */ +#define WQO_RFWQ 0x0020 /* report frozen work queue bit */ +#define WQO_INIT 0x8000 /* work queue init bit */ + +void vs_minphys __P((struct buf *bp)); +int vs_scsicmd __P((struct scsi_xfer *)); + +#endif /* _M328VAR_H */ diff --git a/sys/arch/mvme88k/dev/vx.c b/sys/arch/mvme88k/dev/vx.c new file mode 100644 index 00000000000..60aba6197ad --- /dev/null +++ b/sys/arch/mvme88k/dev/vx.c @@ -0,0 +1,1691 @@ +/* $OpenBSD: vx.c,v 1.1 1999/05/29 04:41:45 smurph Exp $ */ +/* + * Copyright (c) 1999 Steve Murphree, Jr. + * 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 Dale Rahn. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/callout.h> +#include <sys/conf.h> +#include <sys/ioctl.h> +#include <sys/proc.h> +#include <sys/tty.h> +#include <sys/uio.h> +#include <sys/systm.h> +#include <sys/time.h> +#include <sys/device.h> +#include <machine/cpu.h> +#include <machine/autoconf.h> +#include <dev/cons.h> +#include <mvme88k/dev/vxreg.h> +#include <sys/syslog.h> +#include "pcctwo.h" +#if NPCCTWO > 0 + #include <mvme88k/dev/pcctworeg.h> + #include <mvme88k/dev/vme.h> +#endif + +#include <machine/psl.h> +#define splvx() spltty() + +#ifdef DEBUG + #undef DEBUG +#endif +#define DEBUG_KERN 1 + +struct vx_info { + struct tty *tty; + u_char vx_swflags; + int vx_linestatus; + int open; + int waiting; + u_char vx_consio; + u_char vx_speed; + u_char read_pending; + struct wring *wringp; + struct rring *rringp; +}; + +struct vxsoftc { + struct device sc_dev; + struct evcnt sc_intrcnt; + struct evcnt sc_sintrcnt; + struct vx_info sc_info[9]; + struct vxreg *vx_reg; + unsigned int board_addr; + struct channel *channel; + char channel_number; + struct packet sc_bppwait_pkt; + void *sc_bppwait_pktp; + struct intrhand sc_ih_c; + struct intrhand sc_ih_s; + struct vme2reg *sc_vme2; + int sc_ipl; + int sc_vec; + int sc_flags; + struct envelope *elist_head, *elist_tail; + struct packet *plist_head, *plist_tail; +}; + +extern int cold; /* var in autoconf.c that is set in machdep.c when booting */ + +/* prototypes */ + +void *get_next_envelope __P((struct envelope *thisenv)); +struct envelope *get_status_head __P((struct vxsoftc *sc)); +void set_status_head __P((struct vxsoftc *sc, void *envp)); +struct packet *get_packet __P((struct vxsoftc *sc, struct envelope *thisenv)); +struct envelope *find_status_packet __P((struct vxsoftc *sc, struct packet * pktp)); + +void read_wakeup __P((struct vxsoftc *sc, int port)); +int bpp_send __P((struct vxsoftc *sc, void *pkt, int wait_flag)); + +int create_channels __P((struct vxsoftc *sc)); +void *memcpy2 __P((void *dest, const void *src, size_t size)); +void *get_free_envelope __P((struct vxsoftc *sc)); +void put_free_envelope __P((struct vxsoftc *sc, void *envp)); +void *get_free_packet __P((struct vxsoftc *sc)); +void put_free_packet __P((struct vxsoftc *sc, void *pktp)); + +int vx_init __P((struct vxsoftc *sc)); +int vx_event __P((struct vxsoftc *sc, struct packet *evntp)); + +void vx_unblock __P((struct tty *tp)); +int vx_ccparam __P((struct vxsoftc *sc, struct termios *par, int port)); + +int vx_param __P((struct tty *tp, struct termios *t)); +int vx_intr __P((struct vxsoftc *sc)); +int vx_sintr __P((struct vxsoftc *sc)); +int vx_poll __P((struct vxsoftc *sc, struct packet *wpktp)); +void vx_overflow __P((struct vxsoftc *sc, int port, long *ptime, u_char *msg)); +void vx_frame __P((struct vxsoftc *sc, int port)); +void vx_break __P(( struct vxsoftc *sc, int port)); +int vx_mctl __P((dev_t dev, int bits, int how)); + +int vxmatch __P((struct device *parent, void *self, void *aux)); +void vxattach __P((struct device *parent, struct device *self, void *aux)); + +int vxopen __P((dev_t dev, int flag, int mode, struct proc *p)); +int vxclose __P((dev_t dev, int flag, int mode, struct proc *p)); +int vxread __P((dev_t dev, struct uio *uio, int flag)); +int vxwrite __P((dev_t dev, struct uio *uio, int flag)); +int vxioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)); +void vxstart __P((struct tty *tp)); +int vxstop __P((struct tty *tp, int flag)); + +static void vxputc __P((struct vxsoftc *sc, int port, u_char c)); +static u_char vxgetc __P((struct vxsoftc *sc, int *port)); + +struct cfattach vx_ca = { + sizeof(struct vxsoftc), vxmatch, vxattach +}; + +struct cfdriver vx_cd = { + NULL, "vx", DV_TTY, 0 +}; + +#define VX_UNIT(x) (int)(minor(x) / 9) +#define VX_PORT(x) (int)(minor(x) % 9) + +extern int cputyp; +struct envelope *bpp_wait; +unsigned int board_addr; + +struct tty * vxtty(dev) +dev_t dev; +{ + int unit, port; + struct vxsoftc *sc; + unit = VX_UNIT(dev); + if (unit >= vx_cd.cd_ndevs || + (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) { + return (NULL); + } + port = VX_PORT(dev); + return sc->sc_info[port].tty; +} + +int +vxmatch(parent, self, aux) +struct device *parent; +void *self; +void *aux; +{ + struct vxreg *vx_reg; + struct vxsoftc *sc = self; + struct confargs *ca = aux; + int ret; + if (cputyp != CPU_187) + return 0; +#ifdef OLD_MAPPINGS + ca->ca_vaddr = ca->ca_paddr; +#endif + ca->ca_len = 0x10000; /* we know this. */ + ca->ca_ipl = 3; /* we need interrupts for this board to work */ + + vx_reg = (struct vxreg *)ca->ca_vaddr; + board_addr = (unsigned int)ca->ca_vaddr; + if (!badvaddr(&vx_reg->ipc_cr, 1)){ + if (ca->ca_vec & 0x03) { + printf("xvt: bad vector 0x%x\n", ca->ca_vec); + return (0); + } + return (1); + } else { + return (0); + } +} + +void +vxattach(parent, self, aux) +struct device *parent; +struct device *self; +void *aux; +{ + struct vxsoftc *sc = (struct vxsoftc *)self; + struct confargs *ca = aux; + int i; + + /* set up dual port memory and registers and init*/ + sc->vx_reg = (struct vxreg *)ca->ca_vaddr; + sc->channel = (struct channel *)(ca->ca_vaddr + 0x0100); + sc->sc_vme2 = ca->ca_master; + sc->sc_ipl = ca->ca_ipl; + sc->sc_vec = ca->ca_vec; + sc->board_addr = (unsigned int)ca->ca_vaddr; + + printf("\n"); + + if (create_channels(sc)) { + printf("%s: failed to create channel %d\n", sc->sc_dev.dv_xname, + sc->channel->channel_number); + return; + } + if (vx_init(sc)){ + printf("%s: failed to initialize\n", sc->sc_dev.dv_xname); + return; + } + + /* enable interrupts */ + sc->sc_ih_c.ih_fn = vx_intr; + sc->sc_ih_c.ih_arg = sc; + sc->sc_ih_c.ih_ipl = ca->ca_ipl; + sc->sc_ih_c.ih_wantframe = 0; + + vmeintr_establish(ca->ca_vec, &sc->sc_ih_c); + evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt); +} + +int vxtdefaultrate = TTYDEF_SPEED; + +dtr_ctl(sc, port, on) + struct vxsoftc *sc; + int port; + int on; +{ + struct packet pkt; + bzero(&pkt, sizeof(struct packet)); + pkt.command = CMD_IOCTL; + pkt.ioctl_cmd_l = IOCTL_TCXONC; + pkt.command_pipe_number = sc->channel_number; + pkt.status_pipe_number = sc->channel_number; + pkt.device_number = port; + if (on) { + pkt.ioctl_arg_l = 6; /* assert DTR */ + } else { + pkt.ioctl_arg_l = 7; /* negate DTR */ + } + bpp_send(sc, &pkt, NOWAIT); + return (pkt.error_l); +} + +rts_ctl(sc, port, on) + struct vxsoftc *sc; + int port; + int on; +{ + struct packet pkt; + bzero(&pkt, sizeof(struct packet)); + pkt.command = CMD_IOCTL; + pkt.ioctl_cmd_l = IOCTL_TCXONC; + pkt.command_pipe_number = sc->channel_number; + pkt.status_pipe_number = sc->channel_number; + pkt.device_number = port; + if (on) { + pkt.ioctl_arg_l = 4; /* assert RTS */ + } else { + pkt.ioctl_arg_l = 5; /* negate RTS */ + } + bpp_send(sc, &pkt, NOWAIT); + return (pkt.error_l); +} + +flush_ctl(sc, port, which) + struct vxsoftc *sc; + int port; + int which; +{ + struct packet pkt; + bzero(&pkt, sizeof(struct packet)); + pkt.command = CMD_IOCTL; + pkt.ioctl_cmd_l = IOCTL_TCFLSH; + pkt.command_pipe_number = sc->channel_number; + pkt.status_pipe_number = sc->channel_number; + pkt.device_number = port; + pkt.ioctl_arg_l = which; /* 0=input, 1=output, 2=both */ + bpp_send(sc, &pkt, NOWAIT); + return (pkt.error_l); +} + +int vx_mctl (dev, bits, how) +dev_t dev; +int bits; +int how; +{ + int s, unit, port; + int vxbits; + struct vxsoftc *sc; + struct vx_info *vxt; + u_char msvr; + + unit = VX_UNIT(dev); + port = VX_PORT(dev); + sc = (struct vxsoftc *) vx_cd.cd_devs[unit]; + vxt = &sc->sc_info[port]; + + s = splvx(); + switch (how) { + case DMSET: + if( bits & TIOCM_RTS) { + rts_ctl(sc, port, 1); + vxt->vx_linestatus |= TIOCM_RTS; + } else { + rts_ctl(sc, port, 0); + + vxt->vx_linestatus &= ~TIOCM_RTS; + } + if( bits & TIOCM_DTR) { + dtr_ctl(sc, port, 1); + vxt->vx_linestatus |= TIOCM_DTR; + } else { + dtr_ctl(sc, port, 0); + vxt->vx_linestatus &= ~TIOCM_DTR; + } + break; + case DMBIC: + if ( bits & TIOCM_RTS) { + rts_ctl(sc, port, 0); + vxt->vx_linestatus &= ~TIOCM_RTS; + } + if ( bits & TIOCM_DTR) { + dtr_ctl(sc, port, 0); + vxt->vx_linestatus &= ~TIOCM_DTR; + } + break; + + case DMBIS: + if ( bits & TIOCM_RTS) { + rts_ctl(sc, port, 1); + vxt->vx_linestatus |= TIOCM_RTS; + } + if ( bits & TIOCM_DTR) { + dtr_ctl(sc, port, 1); + vxt->vx_linestatus |= TIOCM_DTR; + } + break; + + case DMGET: + bits = 0; + msvr = vxt->vx_linestatus; + if( msvr & TIOCM_DSR) { + bits |= TIOCM_DSR; + } + if( msvr & TIOCM_CD) { + bits |= TIOCM_CD; + } + if( msvr & TIOCM_CTS) { + bits |= TIOCM_CTS; + } + if( msvr & TIOCM_DTR) { + bits |= TIOCM_DTR; + } + if( msvr & TIOCM_RTS) { + bits |= TIOCM_RTS; + } + break; + } + + splx(s); + bits = 0; + bits |= TIOCM_DTR; + bits |= TIOCM_RTS; + bits |= TIOCM_CTS; + bits |= TIOCM_CD; + bits |= TIOCM_DSR; + return (bits); +} + +int vxopen (dev, flag, mode, p) +dev_t dev; +int flag; +int mode; +struct proc *p; +{ + int s, unit, port; + struct vx_info *vxt; + struct vxsoftc *sc; + struct tty *tp; + struct open_packet opkt; + u_short code; + + unit = VX_UNIT(dev); + port = VX_PORT(dev); + + if (unit >= vx_cd.cd_ndevs || + (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) { + return (ENODEV); + } + + /*flush_ctl(sc, port, 2);*/ + + bzero(&opkt, sizeof(struct packet)); + opkt.eye_catcher[0] = 0x33; + opkt.eye_catcher[1] = 0x33; + opkt.eye_catcher[2] = 0x33; + opkt.eye_catcher[3] = 0x33; + opkt.command_pipe_number = sc->channel_number; + opkt.status_pipe_number = sc->channel_number; + opkt.command = CMD_OPEN; + opkt.device_number = port; + + bpp_send(sc, &opkt, WAIT_POLL); + + if (opkt.error_l) { +#ifdef DEBUG_VXT + printf("unit %d, port %d, ", unit, port); + printf("error = %d\n", opkt.error_l); +#endif + return (ENODEV); + } + + code = opkt.event_code; + s = splvx(); + + vxt = &sc->sc_info[port]; + if (vxt->tty) { + tp = vxt->tty; + } else { + tp = vxt->tty = ttymalloc(); + } + + /* set line status */ + tp->t_state |= TS_CARR_ON; + if (code & E_DCD) { + tp->t_state |= TS_CARR_ON; + vxt->vx_linestatus |= TIOCM_CD; + } + if (code & E_DSR) { + vxt->vx_linestatus |= TIOCM_DSR; + } + if (code & E_CTS) { + vxt->vx_linestatus |= TIOCM_CTS; + } + + tp->t_oproc = vxstart; + tp->t_param = vx_param; + tp->t_dev = dev; + + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_WOPEN; + ttychars(tp); + if (tp->t_ispeed == 0) { + /* + * only when cleared do we reset to defaults. + */ + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = vxtdefaultrate; + tp->t_cflag = TTYDEF_CFLAG; + } + /* + * do these all the time + */ + if (vxt->vx_swflags & TIOCFLAG_CLOCAL) + tp->t_cflag |= CLOCAL; + if (vxt->vx_swflags & TIOCFLAG_CRTSCTS) + tp->t_cflag |= CRTSCTS; + if (vxt->vx_swflags & TIOCFLAG_MDMBUF) + tp->t_cflag |= MDMBUF; + vx_param(tp, &tp->t_termios); + ttsetwater(tp); + + (void)vx_mctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET); + + tp->t_state |= TS_CARR_ON; + } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { + splx(s); + return (EBUSY); + } + + /* + * Reset the tty pointer, as there could have been a dialout + * use of the tty with a dialin open waiting. + */ + tp->t_dev = dev; + sc->sc_info[port].open = 1; + read_wakeup(sc, port); + splx(s); + return ((*linesw[tp->t_line].l_open)(dev, tp)); +} + +int +vx_param(tp, t) +struct tty *tp; +struct termios *t; +{ + int unit, port; + struct vxsoftc *sc; + int s; + dev_t dev; + + dev = tp->t_dev; + unit = VX_UNIT(dev); + if (unit >= vx_cd.cd_ndevs || + (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) { + return (ENODEV); + } + port = VX_PORT(dev); + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = t->c_cflag; + vx_ccparam(sc, t, port); + vx_unblock(tp); + return 0; +} + +int +vxclose (dev, flag, mode, p) +dev_t dev; +int flag; +int mode; +struct proc *p; +{ + int unit, port; + struct tty *tp; + struct vx_info *vxt; + struct vxsoftc *sc; + int s; + struct close_packet cpkt; + unit = VX_UNIT(dev); + if (unit >= vx_cd.cd_ndevs || + (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) { + return (ENODEV); + } + port = VX_PORT(dev); +/* flush_ctl(sc, port, 2); flush both input and output */ + + vxt = &sc->sc_info[port]; + tp = vxt->tty; + (*linesw[tp->t_line].l_close)(tp, flag); + + if((tp->t_cflag & HUPCL) != 0) { + rts_ctl(sc, port, 0); + dtr_ctl(sc, port, 0); + } + + s = splvx(); + + bzero(&cpkt, sizeof(struct packet)); + cpkt.eye_catcher[0] = 0x55; + cpkt.eye_catcher[1] = 0x55; + cpkt.eye_catcher[2] = 0x55; + cpkt.eye_catcher[3] = 0x55; + cpkt.command_pipe_number = sc->channel_number; + cpkt.status_pipe_number = sc->channel_number; + cpkt.command = CMD_CLOSE; + cpkt.device_number = port; + + bpp_send(sc, &cpkt, NOWAIT); + splx(s); + ttyclose(tp); + sc->sc_info[port].open = 0; + return (0); +} + +void +read_wakeup(sc, port) +struct vxsoftc *sc; +int port; +{ + struct rring *rp; + struct read_wakeup_packet rwp; + volatile struct vx_info *vxt; + vxt = &sc->sc_info[port]; + /* + * If we already have a read_wakeup paket + * for this port, do nothing. + */ + if (vxt->read_pending) { + return; + } else { + vxt->read_pending = 1; + } + + bzero(&rwp, sizeof(struct packet)); + rwp.eye_catcher[0] = 0x11; + rwp.eye_catcher[1] = 0x11; + rwp.eye_catcher[2] = 0x11; + rwp.eye_catcher[3] = 0x11; + rwp.command_pipe_number = sc->channel_number; + rwp.status_pipe_number = sc->channel_number; + rwp.command = CMD_READW; + rwp.device_number = port; + + /* + * Do not wait. Characters will be transfered + * to (*linesw[tp->t_line].l_rint)(c,tp); by + * vx_intr() (IPC will notify via interrupt) + */ + bpp_send(sc, &rwp, NOWAIT); +} + +int +vxread (dev, uio, flag) +dev_t dev; +struct uio *uio; +int flag; +{ + int unit, port; + struct tty *tp; + volatile struct vx_info *vxt; + volatile struct vxsoftc *sc; + + unit = VX_UNIT(dev); + if (unit >= vx_cd.cd_ndevs || + (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) { + return (ENODEV); + } + port = VX_PORT(dev); + vxt = &sc->sc_info[port]; + tp = vxt->tty; + if (!tp) return ENXIO; + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +vxwrite (dev, uio, flag) +dev_t dev; +struct uio *uio; +int flag; +{ + int unit, port; + struct tty *tp; + struct vx_info *vxt; + struct vxsoftc *sc; + struct wring *wp; + struct write_wakeup_packet wwp; + u_short get, put; + int i, cnt, s; + + unit = VX_UNIT(dev); + if (unit >= vx_cd.cd_ndevs || + (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) { + return (ENODEV); + } + + port = VX_PORT(dev); + vxt = &sc->sc_info[port]; + tp = vxt->tty; + if (!tp) return ENXIO; + + wp = sc->sc_info[port].wringp; + get = wp->get; + put = wp->put; + + if ((put + 1) == get) { + bzero(&wwp, sizeof(struct packet)); + wwp.eye_catcher[0] = 0x22; + wwp.eye_catcher[1] = 0x22; + wwp.eye_catcher[2] = 0x22; + wwp.eye_catcher[3] = 0x22; + wwp.command_pipe_number = sc->channel_number; + wwp.status_pipe_number = sc->channel_number; + wwp.command = CMD_WRITEW; + wwp.device_number = port; + + bpp_send(sc, &wwp, WAIT_POLL); + + if (wwp.error_l) { + return (ENXIO); + } + } + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +int +vxioctl (dev, cmd, data, flag, p) +dev_t dev; +int cmd; +caddr_t data; +int flag; +struct proc *p; +{ + int error; + int unit, port; + struct tty *tp; + struct vx_info *vxt; + struct vxsoftc *sc; + unit = VX_UNIT(dev); + if (unit >= vx_cd.cd_ndevs || + (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) { + return (ENODEV); + } + port = VX_PORT(dev); + vxt = &sc->sc_info[port]; + tp = vxt->tty; + if (!tp) + return ENXIO; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + + switch (cmd) { + case TIOCSBRK: + /* */ + break; + + case TIOCCBRK: + /* */ + break; + + case TIOCSDTR: + (void) vx_mctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS); + break; + + case TIOCCDTR: + (void) vx_mctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC); + break; + + case TIOCMSET: + (void) vx_mctl(dev, *(int *) data, DMSET); + break; + + case TIOCMBIS: + (void) vx_mctl(dev, *(int *) data, DMBIS); + break; + + case TIOCMBIC: + (void) vx_mctl(dev, *(int *) data, DMBIC); + break; + + case TIOCMGET: + *(int *)data = vx_mctl(dev, 0, DMGET); + break; + + case TIOCGFLAGS: + *(int *)data = vxt->vx_swflags; + break; + + case TIOCSFLAGS: + error = suser(p->p_ucred, &p->p_acflag); + if (error != 0) + return(EPERM); + + vxt->vx_swflags = *(int *)data; + vxt->vx_swflags &= /* only allow valid flags */ + (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS); + break; + + default: + return (ENOTTY); + } + return 0; +} + +int +vxstop(tp, flag) +struct tty *tp; +int flag; +{ + int s; + + s = splvx(); + if (tp->t_state & TS_BUSY) { + if ((tp->t_state & TS_TTSTOP) == 0) + tp->t_state |= TS_FLUSH; + } + splx(s); + return 0; +} + +static u_char +vxgetc(sc, port) +struct vxsoftc *sc; +int *port; +{ + return 0; +} + +static void +vxputc(sc, port, c) +struct vxsoftc *sc; +int port; +u_char c; +{ + struct wring *wp; + + wp = sc->sc_info[port].wringp; + wp->data[wp->put++ & (WRING_BUF_SIZE-1)] = c; + wp->put &= (WRING_BUF_SIZE-1); + return; +} + +u_short vxtspeed(speed) +int speed; +{ + switch (speed) { + case B0: + return VB0; + break; + case B50: + return VB50; + break; + case B75: + return VB75; + break; + case B110: + return VB110; + break; + case B134: + return VB134; + break; + case B150: + return VB150; + break; + case B200: + return VB200; + break; + case B300: + return VB300; + break; + case B600: + return VB600; + break; + case B1200: + return VB1200; + break; + case B1800: + return VB1800; + break; + case B2400: + return VB2400; + break; + case B4800: + return VB4800; + break; + case B9600: + return VB9600; + break; + case B19200: + return VB19200; + break; + case B38400: + return VB38400; + break; + default: + return VB9600; + break; + } +} + +int +vx_ccparam(sc, par, port) +struct vxsoftc *sc; +struct termios *par; +int port; +{ + struct termio tio; + int imask=0, ints, s; + int cflag, iflag, oflag, lflag; + struct ioctl_a_packet pkt; + bzero(&pkt, sizeof(struct packet)); + + if (par->c_ospeed == 0) { + s = splvx(); + /* dont kill the console */ + if(sc->sc_info[port].vx_consio == 0) { + /* disconnect, drop RTS DTR stop reciever */ + rts_ctl(sc, port, 0); + dtr_ctl(sc, port, 0); + } + splx(s); + return (0xff); + } + + pkt.command = CMD_IOCTL; + pkt.ioctl_cmd_l = IOCTL_TCGETA; + pkt.command_pipe_number = sc->channel_number; + pkt.status_pipe_number = sc->channel_number; + pkt.device_number = port; + bpp_send(sc, &pkt, WAIT_POLL); + + cflag = pkt.c_cflag; + cflag |= vxtspeed(par->c_ospeed); + + switch (par->c_cflag & CSIZE) { + case CS5: + cflag |= VCS5; + imask = 0x1F; + break; + case CS6: + cflag |= VCS6; + imask = 0x3F; + break; + case CS7: + cflag |= VCS7; + imask = 0x7F; + break; + default: + cflag |= VCS8; + imask = 0xFF; + } + + if (par->c_cflag & PARENB) cflag |= VPARENB; else cflag &= ~VPARENB; + if (par->c_cflag & PARODD) cflag |= VPARODD; else cflag &= ~VPARODD; + if (par->c_cflag & CREAD) cflag |= VCREAD; else cflag &= ~VCREAD; + if (par->c_cflag & CLOCAL) cflag |= VCLOCAL; else cflag &= ~VCLOCAL; + if (par->c_cflag & HUPCL) cflag |= VHUPCL; else cflag &= ~VHUPCL; + /* + if (par->c_iflag & BRKINT) iflag |= VBRKINT; else iflag &= ~VBRKINT; + if (par->c_iflag & ISTRIP) iflag |= VISTRIP; else iflag &= ~VISTRIP; + if (par->c_iflag & ICRNL) iflag |= VICRNL; else iflag &= ~VICRNL; + if (par->c_iflag & IXON) iflag |= VIXON; else iflag &= ~VIXON; + if (par->c_iflag & IXANY) iflag |= VIXANY; else iflag &= ~VIXANY; + if (par->c_oflag & OPOST) oflag |= VOPOST; else oflag &= ~VOPOST; + if (par->c_oflag & ONLCR) oflag |= VONLCR; else oflag &= ~VONLCR; + if (par->c_oflag & OXTABS) oflag |= VOXTABS; else oflag &= ~VOXTABS; + if (par->c_lflag & ECHO) lflag |= VECHO; else lflag &= ~VECHO; + if (par->c_lflag & ECHOE) lflag |= VECHOE; else lflag &= ~VECHOE; + if (par->c_lflag & ICANON) lflag |= VICANON; else lflag &= ~VICANON; + if (par->c_lflag & ISIG) lflag |= VISIG; else lflag &= ~VISIG; + */ + pkt.command = CMD_IOCTL; + pkt.ioctl_cmd_l = IOCTL_TCSETA; + pkt.command_pipe_number = sc->channel_number; + pkt.status_pipe_number = sc->channel_number; + pkt.device_number = port; + pkt.c_cflag = cflag; +/* + pkt.c_iflag = iflag; + pkt.c_oflag = oflag; + pkt.c_lflag = lflag; + */ + + bpp_send(sc, &pkt, WAIT_POLL); + return imask; +} + +void +vx_unblock(tp) +struct tty *tp; +{ + tp->t_state &= ~TS_FLUSH; + if (tp->t_outq.c_cc != 0) + vxstart(tp); +} + +void +vxstart(tp) +struct tty *tp; +{ + dev_t dev; + u_char cbuf; + struct vxsoftc *sc; + struct wring *wp; + int cc, port, unit, s, cnt, i; + u_short get, put; + char buffer[WRING_BUF_SIZE]; + char *wrdp; + + dev = tp->t_dev; + port = VX_PORT(dev); + unit = VX_UNIT(dev); + if (unit >= vx_cd.cd_ndevs || + (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) { + return; + } + + if ((tp->t_state & TS_ISOPEN) == 0) + return; + + s = splvx(); + if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_FLUSH)) == 0) { + tp->t_state |= TS_BUSY; + wp = sc->sc_info[port].wringp; + get = wp->get; + put = wp->put; + cc = tp->t_outq.c_cc; + while (cc > 0) { + cnt = min(WRING_BUF_SIZE, cc); + cnt = q_to_b(&tp->t_outq, buffer, cnt); + buffer[cnt] = 0; + for (i=0; i<cnt; i++) { + vxputc(sc, port, buffer[i]); + } + cc -= cnt; + } + tp->t_state &= ~TS_BUSY; + } + splx(s); + return; +} + +void +read_chars(sc, port) +struct vxsoftc *sc; +int port; +{ + /* + * This routine is called by vx_intr() when there are + * characters in the read ring. It will process one + * cooked line, put the chars in the line disipline ring, + * and then return. The characters may then + * be read by vxread. + */ + struct vx_info *vxt; + struct rring *rp; + struct read_wakeup_packet rwp; + struct tty *tp; + u_short get, put; + int frame_count, i, pc = 0, open; + char c; + + vxt = &sc->sc_info[port]; + tp = vxt->tty; + rp = vxt->rringp; + open = vxt->open; + get = rp->get; + put = rp->put; +#ifdef DEBUG_VXT + printf("read_chars() get=%d, put=%d ", get, put); + printf("open = %d ring at 0x%x\n", open, rp); +#endif + while (get != put) { + frame_count = rp->data[rp->get++ & (RRING_BUF_SIZE - 1)]; + rp->get &= (RRING_BUF_SIZE - 1); + for (i=0; i<frame_count; i++) { + c = rp->data[rp->get++ & (RRING_BUF_SIZE - 1)]; + rp->get &= (RRING_BUF_SIZE - 1); + if (open) + (*linesw[tp->t_line].l_rint)(c,tp); + } + c = rp->data[rp->get++ & (RRING_BUF_SIZE - 1)]; + rp->get &= (RRING_BUF_SIZE - 1); + if (!(c & DELIMITER)) { + vx_frame (sc, port); + break; + } else { + break; + } + get = rp->get; + put = rp->put; + } + vxt->read_pending = 0; + read_wakeup(sc, port); + return; +} + +ccode(sc, port, c) +struct vxsoftc *sc; +int port; +char c; +{ + struct vx_info *vxt; + struct tty *tp; + tp = vxt->tty; + vxt = &sc->sc_info[port]; + tp = vxt->tty; + (*linesw[tp->t_line].l_rint)(c,tp); +} + +int +vx_intr(sc) +struct vxsoftc *sc; +{ + struct envelope *envp, *next_envp; + struct envelope env; + struct packet *pktp, pkt; + int valid, i; + short cmd; + u_char port; + struct vme2reg *vme2 = (struct vme2reg *)sc->sc_vme2; + + if (vme2->vme2_vbr & VME2_SYSFAIL){ + /* do something... print_dump(sc); */ + } + if (!cold) sc->sc_intrcnt.ev_count++; + + while (env_isvalid(get_status_head(sc))) { + pktp = get_packet(sc, get_status_head(sc)); + valid = env_isvalid(get_status_head(sc)); + cmd = pktp->command; + port = pktp->device_number; + /* if we are waiting on this packet, strore the info so bpp_send + can process the packet */ + if (sc->sc_bppwait_pktp == pktp) + memcpy2(&sc->sc_bppwait_pkt, pktp, sizeof(struct packet)); + + memcpy2(&pkt, pktp, sizeof(struct packet)); + next_envp = get_next_envelope(get_status_head(sc)); + envp = get_status_head(sc); + /* return envelope and packet to the free queues */ + put_free_envelope(sc, envp); + put_free_packet(sc, pktp); + /* mark new status pipe head pointer */ + set_status_head(sc, next_envp); + /* if it was valid, process packet */ + switch (cmd) { + case CMD_READW: +#ifdef DEBUG_VXT + printf("READW Packet\n"); +#endif + read_chars(sc, port); + return 1; + break; + case CMD_WRITEW: +#ifdef DEBUG_VXT + printf("WRITEW Packet\n"); /* Still don't know XXXsmurph */ +#endif + return 1; + break; + case CMD_EVENT: +#ifdef DEBUG_VXT + printf("EVENT Packet\n"); +#endif + vx_event(sc, &pkt); + return 1; + break; + case CMD_PROCCESED: +#ifdef DEBUG_VXT + printf("CMD_PROCCESED Packet\n"); +#endif + return 1; + break; + default: +#ifdef DEBUG_VXT + printf("Other packet 0x%x\n", cmd); +#endif + return 1; + break; + } + } + return 1; +} + +int +vx_event(sc, evntp) +struct vxsoftc *sc; +struct packet *evntp; +{ + u_short code = evntp->event_code; + struct event_packet evnt; + struct vx_info *vxt; + + vxt = &sc->sc_info[evntp->device_number]; + + if (code & E_INTR) { + ccode(sc, evntp->device_number, CINTR); + } + if (code & E_QUIT) { + ccode(sc, evntp->device_number, CQUIT); + } + if (code & E_HUP) { + rts_ctl(sc, evntp->device_number, 0); + dtr_ctl(sc, evntp->device_number, 0); + } + if (code & E_DCD) { + vxt->vx_linestatus |= TIOCM_CD; + } + if (code & E_DSR) { + vxt->vx_linestatus |= TIOCM_DSR; + } + if (code & E_CTS) { + vxt->vx_linestatus |= TIOCM_CTS; + } + if (code & E_LOST_DCD) { + vxt->vx_linestatus &= ~TIOCM_CD; + } + if (code & E_LOST_DSR) { + vxt->vx_linestatus &= ~TIOCM_DSR; + } + if (code & E_LOST_CTS) { + vxt->vx_linestatus &= ~TIOCM_CTS; + } + if (code & E_PR_FAULT) { + /* do something... */ + } + if (code & E_PR_POUT) { + /* do something... */ + } + if (code & E_PR_SELECT) { + /* do something... */ + } + if (code & E_SWITCH) { + /* do something... */ + } + if (code & E_BREAK) { + vx_break (sc, evntp->device_number); + } + + /* send and event packet backe to the device */ + bzero(&evnt, sizeof(struct event_packet)); + evnt.command = CMD_EVENT; + evnt.device_number = evntp->device_number; + evnt.command_pipe_number = sc->channel_number; + /* return status on same channel */ + evnt.status_pipe_number = sc->channel_number; + /* send packet to the firmware */ + bpp_send(sc, &evnt, NOWAIT); + return 1; +} + +void +vx_overflow (sc, port, ptime, msg) +struct vxsoftc *sc; +int port; +long *ptime; +u_char *msg; +{ + log(LOG_WARNING, "%s port %d: overrun\n", sc->sc_dev.dv_xname, port); + return; +} + +void +vx_frame (sc, port) +struct vxsoftc *sc; +int port; +{ + log(LOG_WARNING, "%s port %d: frame error\n", sc->sc_dev.dv_xname, port); + return; +} + +void +vx_break (sc, port) +struct vxsoftc *sc; +int port; +{ +#ifdef DEBUG_KERN + Debugger(); +#else + log(LOG_WARNING, "%s port %d: break detected\n", sc->sc_dev.dv_xname, port); +#endif + return; +} + +/* + * Initialization and Buffered Pipe Protocol (BPP) code + */ + +/* special function for 16 bit data transfer */ +/* Not needed now that I figured out VME bus */ +/* mappings and address modifiers, but I don't */ +/* want to change them :) */ +void * +memcpy2(void *dest, const void *src, size_t size) +{ + int i; + short *d, *s; + d = (short*) dest; + s = (short*) src; + for (i=0; i<(size/2); i++) { + *d = *s; + d++; + s++; + } +} + +void +wzero(void *addr, size_t size) +{ + int i; + short *d; + d = (short*) addr; + for (i=0; i<(size/2); i++) { + *d = 0; + d++; + } +} + +int +create_free_queue(sc) +struct vxsoftc *sc; +{ + int i; + struct envelope *envp; + struct envelope env; + struct packet *pktp; + struct packet pkt; + + envp = (struct envelope *)ENVELOPE_AREA; + sc->elist_head = envp; + for (i=0; i < NENVELOPES; i++) { + bzero(envp, sizeof(struct envelope)); + if (i==(NENVELOPES - 1)) { + envp->link = NULL; + } else { + envp->link = (u_long)envp + sizeof(struct envelope); + } + envp->packet_ptr = NULL; + envp->valid_flag = 0; + envp++; + } + sc->elist_tail = --envp; + + pktp = (struct packet *)PACKET_AREA; + sc->plist_head = pktp; + for (i=0; i < NPACKETS; i++) { + bzero(pktp, sizeof(struct packet)); + if (i==(NPACKETS - 1)) { + pktp->link = NULL; + } else { + pktp->link = (u_long)pktp + sizeof(struct packet); + } + pktp++; + } + sc->plist_tail = --pktp; + return 0; /* no error */ +} + +void * +get_free_envelope(sc) +struct vxsoftc *sc; +{ + void *envp; + + envp = sc->elist_head; + sc->elist_head = (struct envelope *)sc->elist_head->link; + bzero(envp, sizeof(struct envelope)); + return envp; +} + +void +put_free_envelope(sc, ep) +struct vxsoftc *sc; +void * ep; +{ + struct envelope *envp = (struct envelope *)ep; + bzero(envp, sizeof(struct envelope)); + sc->elist_tail->link = (ulong)envp; + envp->link = NULL; + sc->elist_tail = envp; +} + +void* +get_free_packet(sc) +struct vxsoftc *sc; +{ + struct packet *pktp; + + pktp = sc->plist_head; + sc->plist_head = (struct packet *)sc->plist_head->link; + bzero(pktp, sizeof(struct packet)); + return pktp; +} + +void +put_free_packet(sc, pp) +struct vxsoftc *sc; +void *pp; +{ + struct packet *pktp = (struct packet *)pp; + /*bzero(pktp, sizeof(struct packet));*/ + pktp->command = CMD_PROCCESED; + sc->plist_tail->link = (u_long)pktp; + pktp->link = NULL; + sc->plist_tail = pktp; +} + +/* + * This is the nitty gritty. All the rest if this code + * was hell to come by. Getting this right from the + * Moto manual took *time*! + */ +int +create_channels(sc) +struct vxsoftc *sc; +{ + struct envelope *envp; + struct envelope env; + struct packet *pktp; + u_char valid; + u_short status; + u_short tas, csr; + struct vxreg *ipc_csr; + + ipc_csr = sc->vx_reg; + /* wait for busy bit to clear */ + while ((ipc_csr->ipc_cr & IPC_CR_BUSY)); + create_free_queue(sc); + /* set up channel header. we only want one */ + tas = ipc_csr->ipc_tas; + while (!(tas & IPC_TAS_VALID_STATUS)) { + envp = get_free_envelope(sc); + sc->channel->command_pipe_head_ptr_h = HI(envp); + sc->channel->command_pipe_head_ptr_l = LO(envp); + sc->channel->command_pipe_tail_ptr_h = sc->channel->command_pipe_head_ptr_h; + sc->channel->command_pipe_tail_ptr_l = sc->channel->command_pipe_head_ptr_l; + envp = get_free_envelope(sc); + sc->channel->status_pipe_head_ptr_h = HI(envp); + sc->channel->status_pipe_head_ptr_l = LO(envp); + sc->channel->status_pipe_tail_ptr_h = sc->channel->status_pipe_head_ptr_h; + sc->channel->status_pipe_tail_ptr_l = sc->channel->status_pipe_head_ptr_l; + sc->channel->interrupt_level = sc->sc_ipl; + sc->channel->interrupt_vec = sc->sc_vec; + sc->channel->channel_priority = 0; + sc->channel->channel_number = 0; + sc->channel->valid = 1; + sc->channel->address_modifier = 0x8D; /* A32/D16 supervisor data access */ + sc->channel->datasize = 0; /* 32 bit data mode */ + + /* loop until TAS bit is zero */ + while ((ipc_csr->ipc_tas & IPC_TAS_TAS)); + ipc_csr->ipc_tas |= IPC_TAS_TAS; + /* load address of channel header */ + ipc_csr->ipc_addrh = HI(sc->channel); + ipc_csr->ipc_addrl = LO(sc->channel); + /* load address modifier reg (supervisor data access) */ + ipc_csr->ipc_amr = 0x8D; + /* load tas with create channel command */ + ipc_csr->ipc_tas |= IPC_CSR_CREATE; + /* set vaild command bit */ + ipc_csr->ipc_tas |= IPC_TAS_VALID_CMD; + /* notify IPC of the CSR command */ + ipc_csr->ipc_cr |= IPC_CR_ATTEN; + /* loop until IPC sets vaild status bit */ + delay(5000); + tas = ipc_csr->ipc_tas; + } + + /* save the status */ + status = ipc_csr->ipc_sr; + /* set COMMAND COMPLETE bit */ + ipc_csr->ipc_tas |= IPC_TAS_COMPLETE; + /* notify IPC that we are through */ + ipc_csr->ipc_cr |= IPC_CR_ATTEN; + /* check and see if the channel was created */ + if (!status && sc->channel->valid) { + sc->channel_number = sc->channel->channel_number; + printf("%s: created channel %d\n", sc->sc_dev.dv_xname, + sc->channel->channel_number); + return 0; + } else { + switch (status) { + case 0x0000: + printf("%s: channel not valid\n", + sc->sc_dev.dv_xname); + break; + case 0xFFFF: + printf("%s: invalid CSR command\n", + sc->sc_dev.dv_xname); + break; + case 0xC000: + printf("%s: could not read channel structure\n", + sc->sc_dev.dv_xname); + break; + case 0x8000: + printf("%s: could not write channel structure\n", + sc->sc_dev.dv_xname); + break; + default: + printf("%s: unknown IPC CSR command error 0x%x\n", + sc->sc_dev.dv_xname, status); + break; + } + return status; /* error */ + } +} + +void +print_dump(sc) +struct vxsoftc *sc; +{ + char *dump_area, *end_dump, *dumpp; + char dump[209]; + char dump2[209]; + bzero(&dump, 209); + + dump_area = (char *)0xff780030; + memcpy2(&dump, dump_area, 208); + + printf("%s", dump); +} + +void * +get_next_envelope(thisenv) +struct envelope *thisenv; +{ + return ((void *)thisenv->link); +} + +int +env_isvalid(thisenv) +struct envelope *thisenv; +{ + return thisenv->valid_flag; +} + +struct envelope * +get_cmd_tail(sc) +struct vxsoftc *sc; +{ + unsigned long retaddr; + retaddr = (unsigned long)sc->vx_reg; + retaddr += sc->channel->command_pipe_tail_ptr_l; + return ((struct envelope *)retaddr); +} + +struct envelope * +get_status_head(sc) +struct vxsoftc *sc; +{ + unsigned long retaddr; + retaddr = (unsigned long)sc->vx_reg; + retaddr += sc->channel->status_pipe_head_ptr_l; + return ((struct envelope *)retaddr); +} + +void +set_status_head(sc, envp) +struct vxsoftc *sc; +void *envp; +{ + sc->channel->status_pipe_head_ptr_h = HI(envp); + sc->channel->status_pipe_head_ptr_l = LO(envp); + return; +} + +struct packet * +get_packet(sc, thisenv) +struct vxsoftc *sc; +struct envelope *thisenv; +{ + struct envelope env; + unsigned long baseaddr; + + if (thisenv == NULL) return NULL; + baseaddr = (unsigned long)sc->vx_reg; + /* + * packet ptr returned on status pipe is only last two bytes + * so we must supply the full address based on the board address. + * This also works for all envelopes because every address is an + * offset to the board address + */ + baseaddr |= thisenv->packet_ptr; + return ((void*)baseaddr); +} + +/* + * Send a command via BPP + */ +int +bpp_send(struct vxsoftc *sc, void *pkt, int wait_flag) +{ + struct envelope *envp; + struct init_packet init, *initp; + struct packet *wpktp, *pktp, *testpktp; + struct vme2reg *vme2 = (struct vme2reg *)sc->sc_vme2; + unsigned long newenv; + int i, s; + + + /* load up packet in dual port mem */ + pktp = get_free_packet(sc); + memcpy2(pktp, pkt, sizeof(struct packet)); + + envp = get_cmd_tail(sc); + newenv = (unsigned long)get_free_envelope(sc); /* put a NULL env on the tail */ + envp->link = newenv; + sc->channel->command_pipe_tail_ptr_h = HI(newenv); + sc->channel->command_pipe_tail_ptr_l = LO(newenv); + envp->packet_ptr = (u_long)pktp; /* add the command packet */ + envp->valid_flag = 1; /* set valid command flag */ + + sc->vx_reg->ipc_cr |= IPC_CR_ATTEN; + if (wait_flag) { /* wait for a packet to return */ + while (pktp->command != CMD_PROCCESED) { +#ifdef DEBUG_VXT + printf("Polling for packet 0x%x in envelope 0x%x...\n", pktp, envp); +#endif + vx_intr(sc); + delay(5000); + } + memcpy2(pkt, pktp, sizeof(struct packet)); + return 0; + } + return 0; /* no error */ +} + +/* + * BPP commands + */ +int +vx_init(sc) +struct vxsoftc *sc; +{ + int i; + struct init_info *infp, inf; + struct wring *wringp; + struct rring *rringp; + struct termio def_termio; + struct init_packet init; + struct event_packet evnt; + + bzero(&def_termio, sizeof(struct termio)); + /* init wait queue */ + bzero(&sc->sc_bppwait_pkt, sizeof(struct packet)); + sc->sc_bppwait_pktp = NULL; + /* set up init_info array */ + wringp = (struct wring *)WRING_AREA; + rringp = (struct rring *)RRING_AREA; + infp = (struct init_info *)INIT_INFO_AREA; + for (i=0; i<9; i++) { + bzero(&inf, sizeof(struct init_info)); + infp->write_ring_ptr_h = HI(wringp); + infp->write_ring_ptr_l = LO(wringp); + sc->sc_info[i].wringp = wringp; + infp->read_ring_ptr_h = HI(rringp); + infp->read_ring_ptr_l = LO(rringp); + sc->sc_info[i].rringp = rringp; +#ifdef DEBUG_VXT + printf("write at 0x%8x, read at 0x%8x\n", wringp, rringp); +#endif + infp->write_ring_size = WRING_DATA_SIZE; + infp->read_ring_size = RRING_DATA_SIZE; + infp->def_termio.c_iflag = VBRKINT; + infp->def_termio.c_oflag = 0; + infp->def_termio.c_cflag = (VB9600 | VCS8); + + infp->def_termio.c_lflag = VISIG; /* enable signal processing */ + infp->def_termio.c_line = 1; /* raw line disipline, we want to control it! */ + infp->def_termio.c_cc[0] = CINTR; + infp->def_termio.c_cc[1] = CQUIT; + infp->def_termio.c_cc[2] = CERASE; + infp->def_termio.c_cc[3] = CKILL; + infp->def_termio.c_cc[4] = 20; + infp->def_termio.c_cc[5] = 2; + infp->reserved1 = 0; /* Must be Zero */ + infp->reserved2 = 0; + infp->reserved3 = 0; + infp->reserved4 = 0; + wringp++; rringp++; infp++; + } + /* set up init_packet */ + bzero(&init, sizeof(struct init_packet)); + init.eye_catcher[0] = 0x12; + init.eye_catcher[1] = 0x34; + init.eye_catcher[2] = 0x56; + init.eye_catcher[3] = 0x78; + init.command = CMD_INIT; + init.command_pipe_number = sc->channel_number; + /* return status on the same channel */ + init.status_pipe_number = sc->channel_number; + init.interrupt_level = sc->sc_ipl; + init.interrupt_vec = sc->sc_vec; + init.init_info_ptr_h = HI(INIT_INFO_AREA); + init.init_info_ptr_l = LO(INIT_INFO_AREA); + + /* send packet to the firmware and wait for completion */ + bpp_send(sc, &init, WAIT_POLL); + + /* check for error */ + if (init.error_l !=0) { + return init.error_l; + } else { + /* send one event packet to each device; */ + for (i=0; i<9; i++) { + bzero(&evnt, sizeof(struct event_packet)); + evnt.command = CMD_EVENT; + evnt.device_number = i; + evnt.command_pipe_number = sc->channel_number; + /* return status on same channel */ + evnt.status_pipe_number = sc->channel_number; + /* send packet to the firmware */ + bpp_send(sc, &evnt, NOWAIT); + } + return 0; + } +} + + diff --git a/sys/arch/mvme88k/dev/vxreg.h b/sys/arch/mvme88k/dev/vxreg.h new file mode 100644 index 00000000000..f328b9dcdd9 --- /dev/null +++ b/sys/arch/mvme88k/dev/vxreg.h @@ -0,0 +1,530 @@ +/* $OpenBSD: vxreg.h,v 1.1 1999/05/29 04:41:45 smurph Exp $ */ + +/* + * Copyright (c) 1999 Steve Murphree, Jr. 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 Dale Rahn. + * 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. + */ + +/* IPC - Intelligent Peripheral Controller */ + +struct vxreg { +/*0x0*/volatile u_short ipc_addrh; /* IPC addr reg, most significant */ +/*0x2*/volatile u_short ipc_addrl; /* IPC addr reg, least significant */ +/*0x4*/volatile u_char ipc_amr; /* IPC address modifier reg */ +/*0x5*/volatile u_char unused1; +/*0x6*/volatile u_short ipc_cr; /* IPC control ceg */ +/*0x8*/volatile u_short ipc_sr; /* IPC status reg */ +/*0xA*/volatile u_char ipc_mdbp; /* IPC model data byte pointer */ +/*0xB*/volatile u_char reserved3; +/*0xC*/volatile u_char ipc_avrp; /* IPC abort vector reg pointer */ +/*0xD*/volatile u_char unused2; +/*0xE*/volatile u_short ipc_tas; /* IPC test and set reg */ +}; + +#define NOWAIT 0 +#define WAIT 1 +#define WAIT_POLL 2 + +#define IPC_CR_SYSFI 0x1000 /* inhibit sysfail */ +#define IPC_CR_ATTEN 0x2000 /* attention bit */ +#define IPC_CR_RESET 0x4000 /* reset bit */ +#define IPC_CR_BUSY 0x8000 /* busy bit */ + +#define IPC_SR_BUSERROR 0x4000 /* bus error */ +#define IPC_SR_ERROR 0x8000 /* general error */ +#define IPC_SR_INVAL 0xFFFF /* invalid command */ + +#define IPC_TAS_COMPLETE 0x1000 +#define IPC_TAS_VALID_STATUS 0x2000 +#define IPC_TAS_VALID_CMD 0x4000 +#define IPC_TAS_TAS 0x8000 + +#define IPC_CSR_CREATE 0x0001 +#define IPC_CSR_DELETE 0x0002 + +#define CSW_OFFSET 0x0010 + +#define CMD_INIT 0x0000 +#define CMD_READW 0x0001 +#define CMD_WRITEW 0x0002 +#define CMD_OPEN 0x0003 +#define CMD_IOCTL 0x0004 +#define CMD_CLOSE 0x0005 +#define CMD_EVENT 0x0006 +#define CMD_PROCCESED 0x00FF + +#define IOCTL_LDOPEN 0x4400 +#define IOCTL_LDCLOSE 0x4401 +#define IOCTL_LDCHG 0x4402 +#define IOCTL_LDGETT 0x4408 +#define IOCTL_LDSETT 0x4409 +#define IOCTL_TCGETA 0x5401 /* get dev termio struct */ +#define IOCTL_TCSETA 0x5402 /* set dev termio struct */ +#define IOCTL_TCSETAW 0x5403 /* set dev termio struct - wait */ +#define IOCTL_TCSETAF 0x5404 /* set dev termio struct - wait - flush */ +#define IOCTL_TCSBRK 0x5405 /* transmit a break seq */ +#define IOCTL_TCXONC 0x5406 /* sus or res, xon or xoff, RTS or DTR */ +#define IOCTL_TCFLSH 0x5407 /* Flush */ +#define IOCTL_TCSETHW 0x5440 /* enable/disable HW handshake */ +#define IOCTL_TCGETHW 0x5441 /* get current HW handshake info */ +#define IOCTL_TCGETDL 0x5442 /* get daownloadable addr and mem size */ +#define IOCTL_TCDLOAD 0x5443 /* download code/data to mem */ +#define IOCTL_TCLINE 0x5444 /* copy line discipline */ +#define IOCTL_TCEXEC 0x5445 /* exec code in local mem */ +#define IOCTL_TCGETVR 0x5446 /* get version and revison of firmware */ +#define IOCTL_TCGETDF 0x5447 /* get default termio stuct */ +#define IOCTL_TCSETDF 0x5448 /* set default termio stuct */ +#define IOCTL_TCGETSYM 0x5449 /* get firmware symbol table */ +#define IOCTL_TCWHAT 0x544A /* get all SCSI IDs of FW files */ +#define IOCTL_TIOGETP 0x7408 /* get devs curr termio struct by sgttyb */ +#define IOCTL_TIOSETP 0x7409 /* set devs curr termio struct by sgttyb */ + +#define IPC_EIO 5 /* I/O error */ +#define IPC_ENXIO 6 /* no such device or address */ +#define IPC_ENOMEM 12 /* not enough space */ +#define IPC_EEXIST 17 /* device or address exists */ +#define IPC_EINVAL 22 /* invalid caommand argument */ + +/* + * Index into c_cc[VNCC]; + */ +#define VVINTR 0 /* ISIG */ +#define VVQUIT 1 /* ISIG */ +#define VVERASE 2 /* ICANON */ +#define VVKILL 3 /* ICANON */ +#define VVEOF 4 /* ICANON */ +#define VVEOL 5 /* ICANON */ +#define VVSWTCH 6 + +/* + * Input flags - software input processing + */ +#define VIGNBRK 0000001 /* ignore BREAK condition */ +#define VBRKINT 0000002 /* map BREAK to SIGINTR */ +#define VIGNPAR 0000004 /* ignore (discard) parity errors */ +#define VPARMRK 0000010 /* mark parity and framing errors */ +#define VINPCK 0000020 /* enable checking of parity errors */ +#define VISTRIP 0000040 /* strip 8th bit off chars */ +#define VINLCR 0000100 /* map NL into CR */ +#define VIGNCR 0000200 /* ignore CR */ +#define VICRNL 0000400 /* map CR to NL (ala CRMOD) */ +#define VIUCLC 0001000 /* translate upper to lower case */ +#define VIXON 0002000 /* enable output flow control */ +#define VIXANY 0004000 /* any char will restart after stop */ +#define VIXOFF 0010000 /* enable input flow control */ + +/* + * Output flags - software output processing + */ +#define VOPOST 0000001 /* enable following output processing */ +#define VOLCUC 0000002 /* translate lower case to upper case */ +#define VONLCR 0000004 /* map NL to CR-NL (ala CRMOD) */ +#define VOCRNL 0000010 /* map CR to NL */ +#define VONOCR 0000020 /* No CR output at column 0 */ +#define VONLRET 0000040 /* NL performs the CR function */ +#define VOFILL 0000100 +#define VOFDEL 0000200 +#define VOXTABS 0014000 /* expand tabs to spaces */ + +/* + * Control flags - hardware control of terminal + */ + +#define VCBAUD 0000017 /* baud rate */ +#define VB0 0000000 /* hang up */ +#define VB50 0000001 +#define VB75 0000002 +#define VB110 0000003 +#define VB134 0000004 +#define VB150 0000005 +#define VB200 0000006 +#define VB300 0000007 +#define VB600 0000010 +#define VB1200 0000011 +#define VB1800 0000012 +#define VB2400 0000013 +#define VB4800 0000014 +#define VB9600 0000015 +#define VB19200 0000016 +#define VB38400 0000017 +#define VEXTA 0000016 +#define VEXTB 0000017 +#define VCSIZE 0000060 /* character size mask */ +#define VCS5 0000000 /* 5 bits (pseudo) */ +#define VCS6 0000020 /* 6 bits */ +#define VCS7 0000040 /* 7 bits */ +#define VCS8 0000060 /* 8 bits */ +#define VCSTOPB 0000100 /* send 2 stop bits */ +#define VCREAD 0000200 /* enable receiver */ +#define VPARENB 0000400 /* parity enable */ +#define VPARODD 0001000 /* odd parity, else even */ +#define VHUPCL 0002000 /* hang up on last close */ +#define VCLOCAL 0004000 /* ignore modem status lines */ + +/* + * "Local" flags - dumping ground for other state + * + * Warning: some flags in this structure begin with + * the letter "I" and look like they belong in the + * input flag. + */ + +#define VISIG 0000001 /* enable signals INTR, QUIT, [D]SUSP */ +#define VICANON 0000002 /* canonicalize input lines */ +#define VXCASE 0000004 /* canonical upper/lower case */ +#define VECHO 0000010 /* enable echoing */ +#define VECHOE 0000020 /* visually erase chars */ +#define VECHOK 0000040 /* echo NL after line kill */ +#define VECHONL 0000100 /* echo NL even if ECHO is off */ +#define VNOFLSH 0000200 /* don't flush after interrupt */ + + +#define VNCC 9 /* 18 bytes */ +struct termio { + volatile unsigned short c_iflag; + volatile unsigned short c_oflag; + volatile unsigned short c_cflag; + volatile unsigned short c_lflag; + volatile char c_line; + volatile unsigned char c_cc[VNCC]; +}; + +struct sgttyb { /* 6 bytes */ + volatile char sg_ispeed; + volatile char sg_ospeed; + volatile char sg_erase; + volatile char sg_kill; + volatile short sg_flags; +}; + +struct termcb { /* 6 bytes */ + volatile char st_flgs; + volatile char st_termt; + volatile char st_crow; + volatile char st_ccol; + volatile char st_vrow; + volatile char st_lrow; +}; + +struct ctdesc { + unsigned short csw, + resv; + unsigned long magic, + lcnt, + fatal, + error, + faddr, + expdata, + readdata; +}; + +struct dl_info { /* 18 bytes */ + volatile unsigned long host_addr; + volatile unsigned long ipc_addr; + volatile unsigned long count; + volatile unsigned long extra_long; + volatile unsigned short extra_short; +}; + +struct packet { /* 68 bytes */ + volatile u_long link; /* was eyecatcher */ + volatile u_char command_pipe_number; + volatile u_char status_pipe_number; + volatile char filler0[4]; + volatile short command; + volatile char filler1[1]; + volatile char command_dependent; + volatile char filler2[2]; + volatile u_char device_number; + volatile char filler3[1]; + volatile short ioctl_cmd_h; + volatile short ioctl_cmd_l; + volatile short ioctl_arg_h; + volatile short ioctl_arg_l; + volatile short ioctl_mode_h; + volatile short ioctl_mode_l; + volatile char filler4[6]; + volatile short error_h; + volatile short error_l; + volatile short event_code; + volatile char filler5[6]; + union { + struct termio tio; + struct termcb tcb; + struct sgttyb sgt; + struct dl_info dl; + long param; + } parameter_block; + short reserved; /* for alignment */ +} packet; + +struct ioctl_a_packet { /* 68 bytes */ + volatile u_long link; /* was eyecatcher */ + volatile u_char command_pipe_number; + volatile u_char status_pipe_number; + volatile char filler0[4]; + volatile short command; + volatile char filler1[1]; + volatile char command_dependent; + volatile char filler2[2]; + volatile u_char device_number; + volatile char filler3[1]; + volatile short ioctl_cmd_h; + volatile short ioctl_cmd_l; + volatile short ioctl_arg_h; + volatile short ioctl_arg_l; + volatile short ioctl_mode_h; + volatile short ioctl_mode_l; + volatile char filler4[6]; + volatile short error_h; + volatile short error_l; + volatile short event_code; + volatile char filler5[6]; + volatile unsigned short c_iflag; + volatile unsigned short c_oflag; + volatile unsigned short c_cflag; + volatile unsigned short c_lflag; + volatile char c_line; + volatile unsigned char c_cc[VNCC]; + short reserved; /* for alignment */ +}; + +struct envelope { /* 12 bytes */ + volatile u_long link; + volatile u_long packet_ptr; + volatile char valid_flag; + volatile char reserved1; + volatile char reserved[2]; +}; + +struct channel { /* 24 bytes */ + volatile short command_pipe_head_ptr_h; + volatile short command_pipe_head_ptr_l; + volatile short command_pipe_tail_ptr_h; + volatile short command_pipe_tail_ptr_l; + volatile short status_pipe_head_ptr_h; + volatile short status_pipe_head_ptr_l; + volatile short status_pipe_tail_ptr_h; + volatile short status_pipe_tail_ptr_l; + volatile char interrupt_level; + volatile char interrupt_vec; + volatile char channel_priority; + volatile char address_modifier; + volatile char channel_number; + volatile char valid; + volatile char datasize; + volatile char reserved; +}; + +#define WRING_DATA_SIZE 4096 /* for a total struct size of 4104 (4K + 6 + 2 bytes) */ +#define WRING_BUF_SIZE WRING_DATA_SIZE +struct wring { + volatile unsigned short reserved; + volatile unsigned short put; + volatile unsigned short get; + volatile char data[WRING_BUF_SIZE]; + char res[2]; /* for alignment */ +}; + +#define RRING_DATA_SIZE 2048 /* for a total struct size of 2054 (2K + 6 + 2 bytes) */ +#define RRING_BUF_SIZE RRING_DATA_SIZE +struct rring { + volatile unsigned short reserved; + volatile unsigned short put; + volatile unsigned short get; + volatile char data[RRING_BUF_SIZE]; + char res[2]; /* for alignment */ +}; + +#define EOFRAME 0xA +#define DELIMITER 0x1 + +struct init_info { /* 88 bytes */ + volatile u_short write_ring_ptr_h; + volatile u_short write_ring_ptr_l; + volatile u_short read_ring_ptr_h; + volatile u_short read_ring_ptr_l; + volatile unsigned short write_ring_size; + volatile unsigned short read_ring_size; + volatile struct termio def_termio; + volatile unsigned short reserved1; + volatile unsigned short reserved2; + volatile unsigned short reserved3; + volatile unsigned short reserved4; + volatile char init_data[56]; +}; + +struct init_packet { + volatile char eye_catcher[4]; + volatile unsigned char command_pipe_number; + volatile unsigned char status_pipe_number; + volatile char filler_0[4]; + volatile short command; + volatile char filler_1[3]; + volatile char interrupt_level; + volatile char filler_2[2]; + volatile short init_info_ptr_h; + volatile short init_info_ptr_l; + volatile char filler_3[7]; + volatile char interrupt_vec; + volatile char filler_4[6]; + volatile short error_h; + volatile short error_l; +}; + +struct event_packet { + volatile char eye_catcher[4]; + volatile unsigned char command_pipe_number; + volatile unsigned char status_pipe_number; + volatile char filler_0[4]; + volatile short command; + volatile char filler_1[4]; + volatile char device_number; + volatile char filler_2[19]; + volatile short error_h; + volatile short error_l; +#define E_INTR 0x0001 +#define E_QUIT 0x0002 +#define E_HUP 0x0004 +#define E_DCD 0x0008 +#define E_DSR 0x0010 +#define E_CTS 0x0020 +#define E_LOST_DCD 0x0040 +#define E_LOST_DSR 0x0080 +#define E_LOST_CTS 0x0100 +#define E_PR_FAULT 0x0200 +#define E_PR_POUT 0x0400 +#define E_PR_SELECT 0x0800 +#define E_SWITCH 0x4000 +#define E_BREAK 0x8000 + volatile unsigned short event_code; /* returned from IPC */ +}; + +struct open_packet { + volatile char eye_catcher[4]; + volatile unsigned char command_pipe_number; + volatile unsigned char status_pipe_number; + volatile char filler_0[4]; + volatile short command; + volatile char filler_1[4]; + volatile char device_number; + volatile char filler_2[19]; + volatile short error_h; + volatile short error_l; + volatile unsigned short event_code; /* returned from IPC */ +}; + +struct close_packet { + volatile char eye_catcher[4]; + volatile unsigned char command_pipe_number; + volatile unsigned char status_pipe_number; + volatile char filler_0[4]; + volatile short command; + volatile char filler_1[4]; + volatile char device_number; + volatile char filler_2[19]; + volatile short error_h; + volatile short error_l; + volatile unsigned short event_code; /* returned from IPC */ +}; + +struct read_wakeup_packet { + volatile char eye_catcher[4]; + volatile unsigned char command_pipe_number; + volatile unsigned char status_pipe_number; + volatile char filler_0[4]; + volatile short command; + volatile char filler_1[4]; + volatile char device_number; + volatile char filler_2[19]; + volatile short error_h; + volatile short error_l; +}; + +struct write_wakeup_packet { + volatile char eye_catcher[4]; + volatile unsigned char command_pipe_number; + volatile unsigned char status_pipe_number; + volatile char filler_0[4]; + volatile short command; + volatile char filler_1[4]; + volatile char device_number; + volatile char filler_2[19]; + volatile short error_h; + volatile short error_l; +}; + +/* + * All structures must reside in dual port user memory. + * ($FFxx0100 to $FFxxFFF0) + * All structures must be word aligned (see byte counts above) + * + * +--------------------------------+ + * | IPC Control/Status Register | $FFxx0000 + * | (16 bytes) | + * |--------------------------------| + * | Confidence Test Descriptor | $FFxx0010 + * | (32 bytes) | + * |--------------------------------| + * | Dump Area | $FFxx0030 + * | (208 bytes) | + * |--------------------------------| + * | | $FFxx0100 + * | | + * : User Space : + * : : + * : (65,264 bytes) : + * | | + * | | + * |--------------------------------| + * | Interrupt Vector Registers | $FFxxFFF0 + * | (16 bytes) | + * +--------------------------------+ + */ +#define ALIGNIT(p) (((u_int)(p) + 7) & ~7) + +#define NENVELOPES 30 +#define NPACKETS NENVELOPES +#define USER_AREA (sc->board_addr + 0x0100) +#define CHANNEL_H (sc->board_addr + 0x0100) +#define ENVELOPE_AREA (CHANNEL_H + sizeof(struct channel)) +#define ENVELOPE_AREA_SIZE (NENVELOPES * sizeof(struct envelope)) +#define PACKET_AREA (ENVELOPE_AREA + ENVELOPE_AREA_SIZE) +#define PACKET_AREA_SIZE (NPACKETS * sizeof(struct packet)) +#define INIT_INFO_AREA (PACKET_AREA + PACKET_AREA_SIZE) +#define INIT_INFO_AREA_SIZE (9 * sizeof(struct init_info)) +#define WRING_AREA ALIGNIT(INIT_INFO_AREA + INIT_INFO_AREA_SIZE) +#define WRING_AREA_SIZE (9 * sizeof(struct wring)) +#define RRING_AREA (WRING_AREA + WRING_AREA_SIZE) +#define RRING_AREA_SIZE (9 * sizeof(struct rring)) +#define USER_AREA_SIZE (RRING_AREA + RRING_AREA_SIZE - USER_AREA) + +#define LO(x) (u_short)((unsigned long)x & 0x0000FFFF) +#define HI(x) (u_short)((unsigned long)x >> 16) + + diff --git a/sys/arch/mvme88k/include/board.h b/sys/arch/mvme88k/include/board.h index 9a49db4625b..a42a6968acb 100644 --- a/sys/arch/mvme88k/include/board.h +++ b/sys/arch/mvme88k/include/board.h @@ -1,4 +1,4 @@ -/* $OpenBSD: board.h,v 1.4 1999/02/09 06:36:25 smurph Exp $ */ +/* $OpenBSD: board.h,v 1.5 1999/05/29 04:41:45 smurph Exp $ */ /* * Copyright (c) 1996 Nivas Madhur * All rights reserved. @@ -62,66 +62,50 @@ # endif #endif -#define MAX_CPUS 1 /* no. of CPUs */ +#define MAX_CPUS 1 /* no. of CPUs */ #define MAX_CMMUS 2 /* 2 CMMUs - 1 data and 1 code */ -#define SYSV_BASE U(0x00000000) /* system virtual base */ +#define SYSV_BASE U(0x00000000) /* system virtual base */ -#define MAXU_ADDR U(0x40000000) /* size of user virtual space */ -#define MAXPHYSMEM U(0x10000000) /* max physical memory */ +#define MAXU_ADDR U(0x40000000) /* size of user virtual space */ +#define MAXPHYSMEM U(0x10000000) /* max physical memory */ -#define BUGROM_START U(0xFF800000) /* start of BUG PROM */ -#define BUGROM_SIZE U(0x003FFFFF) /* size of BUG PROM */ -#define SRAM_START U(0xFFE00000) /* start of sram used by bug */ -#define SRAM_SIZE U(0x0001FFFF) /* size of sram */ -#define OBIO_START U(0xFFF00000) /* start of local IO */ -#define OBIO_SIZE U(0x000EFFFF) /* size of obio space */ +#define BUGROM_START U(0xFF800000) /* start of BUG PROM */ +#define BUGROM_SIZE U(0x003FFFFF) /* size of BUG PROM */ +#define SRAM_START U(0xFFE00000) /* start of sram used by bug */ +#define SRAM_SIZE U(0x0001FFFF) /* size of sram */ +#define OBIO_START U(0xFFF00000) /* start of local IO */ +#define OBIO_SIZE U(0x000EFFFF) /* size of obio space */ #define INT_PRI_LEVEL U(0xFFF4203E) /* interrupt priority level */ #define INT_MASK_LEVEL U(0xFFF4203F) /* interrupt mask level */ #define LOCAL_IO_DEVS U(0xFFF00000) /* local IO devices */ -#define VMEA16 U(0xFFFF0000) /* VMEbus A16 */ -#define PCC2_ADDR U(0xFFF42000) /* PCCchip2 Regs */ -#define MEM_CTLR U(0xFFF43000) /* MEMC040 mem controller */ -#define SCC_ADDR U(0xFFF45000) /* Cirrus Chip */ -#define LANCE_ADDR U(0xFFF46000) /* 82596CA */ -#define SCSI_ADDR U(0xFFF47000) /* NCR 710 address */ -#define NCR710_SIZE U(0x00000040) /* NCR 710 size */ -#define MK48T08_ADDR U(0xFFFC0000) /* BBRAM, TOD */ +#define VMEA16 U(0xFFFF0000) /* VMEbus A16 */ +#define VMEA16_SIZE U(0x0000EFFF) /* VMEbus A16 size */ +#define VMEA32D16 U(0xFF000000) /* VMEbus A32/D16 */ +#define VMEA32D16_SIZE U(0x007FFFFF) /* VMEbus A32/D16 size */ -#define TOD_CAL_CTL U(0xFFFC1FF8) /* calendar control register */ -#define TOD_CAL_SEC U(0xFFFC1FF9) /* seconds */ -#define TOD_CAL_MIN U(0xFFFC1FFA) /* minutes */ -#define TOD_CAL_HOUR U(0xFFFC1FFB) /* hours */ -#define TOD_CAL_DOW U(0xFFFC1FFC) /* Day Of the Week */ -#define TOD_CAL_DAY U(0xFFFC1FFD) /* days */ -#define TOD_CAL_MON U(0xFFFC1FFE) /* months */ -#define TOD_CAL_YEAR U(0xFFFC1FFF) /* years */ +#define PCC2_ADDR U(0xFFF42000) /* PCCchip2 Regs */ +#define MEM_CTLR U(0xFFF43000) /* MEMC040 mem controller */ +#define SCC_ADDR U(0xFFF45000) /* Cirrus Chip */ +#define LANCE_ADDR U(0xFFF46000) /* 82596CA */ +#define SCSI_ADDR U(0xFFF47000) /* NCR 710 address */ +#define NCR710_SIZE U(0x00000040) /* NCR 710 size */ +#define MK48T08_ADDR U(0xFFFC0000) /* BBRAM, TOD */ -#define CMMU_I U(0xFFF77000) /* CMMU instruction */ -#define CMMU_D U(0xFFF7F000) /* CMMU data */ -#define CMMU_SIZE 0x1000 +#define TOD_CAL_CTL U(0xFFFC1FF8) /* calendar control register */ +#define TOD_CAL_SEC U(0xFFFC1FF9) /* seconds */ +#define TOD_CAL_MIN U(0xFFFC1FFA) /* minutes */ +#define TOD_CAL_HOUR U(0xFFFC1FFB) /* hours */ +#define TOD_CAL_DOW U(0xFFFC1FFC) /* Day Of the Week */ +#define TOD_CAL_DAY U(0xFFFC1FFD) /* days */ +#define TOD_CAL_MON U(0xFFFC1FFE) /* months */ +#define TOD_CAL_YEAR U(0xFFFC1FFF) /* years */ -#if 0 -/* interrupt vectors */ - -#define PPBSY 0x50 /* printer port busy */ -#define PPPE 0x51 /* printer port PE */ -#define PPSEL 0x52 /* printer port select */ -#define PPFLT 0x53 /* printer port fault */ -#define PPACK 0x54 /* printer port ack */ -#define SCSIIRQ 0x55 /* SCSI IRQ */ -#define LANCERR 0x56 /* LANC ERR */ -#define LANCIRQ 0x57 /* LANC IRQ */ -#define TIMER2IRQ 0x58 /* Tick Timer 2 vec */ -#define TIMER1IRQ 0x59 /* Tick Timer 1 vec */ -#define GPIOIRQ 0x5A /* GPIO IRQ */ -#define SRXEXIRQ 0x5C /* Serial RX Exception IRQ */ -#define SRMIRQ 0x5D /* Serial Modem IRQ */ -#define STXIRQ 0x5E /* Serial TX IRQ */ -#define SRXIRQ 0x5F /* Serial RX IRQ */ -#endif /* 0 */ +#define CMMU_I U(0xFFF77000) /* CMMU instruction */ +#define CMMU_D U(0xFFF7F000) /* CMMU data */ +#define CMMU_SIZE 0x1000 #endif /* _MACHINE_BOARD_H */ diff --git a/sys/arch/mvme88k/include/exec.h b/sys/arch/mvme88k/include/exec.h index e02b2e8166b..f599b77eb16 100644 --- a/sys/arch/mvme88k/include/exec.h +++ b/sys/arch/mvme88k/include/exec.h @@ -1,4 +1,4 @@ -/* $OpenBSD: exec.h,v 1.6 1999/02/09 06:36:26 smurph Exp $ */ +/* $OpenBSD: exec.h,v 1.7 1999/05/29 04:41:45 smurph Exp $ */ #ifndef _MACHINE_EXEC_H_ #define _MACHINE_EXEC_H_ @@ -17,8 +17,14 @@ struct relocation_info_m88k { }; #define relocation_info relocation_info_m88k -#define _NLIST_DO_AOUT +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2MSB +#define ELF_TARG_MACH EM_88K -#define _KERN_DO_AOUT +#define _NLIST_DO_AOUT +#define _NLIST_DO_ELF + +#define _KERN_DO_AOUT +#define _KERN_DO_ELF #endif _MACHINE_EXEC_H_ diff --git a/sys/arch/mvme88k/include/param.h b/sys/arch/mvme88k/include/param.h index 34ecc00afe4..fced74b83d1 100644 --- a/sys/arch/mvme88k/include/param.h +++ b/sys/arch/mvme88k/include/param.h @@ -1,4 +1,4 @@ -/* $OpenBSD: param.h,v 1.8 1999/02/09 06:36:27 smurph Exp $ */ +/* $OpenBSD: param.h,v 1.9 1999/05/29 04:41:45 smurph Exp $ */ /* * Copyright (c) 1999 Steve Murphree, Jr. * Copyright (c) 1988 University of Utah. @@ -40,7 +40,7 @@ * from: Utah $Hdr: machparam.h 1.11 89/08/14$ * * @(#)param.h 7.8 (Berkeley) 6/28/91 - * $Id: param.h,v 1.8 1999/02/09 06:36:27 smurph Exp $ + * $Id: param.h,v 1.9 1999/05/29 04:41:45 smurph Exp $ */ #ifndef _MACHINE_PARAM_H_ #define _MACHINE_PARAM_H_ @@ -96,7 +96,7 @@ #define SINCR 1 /* increment of stack/NBPG */ #define USPACE ctob(UPAGES) -#define UPAGES 3 /* pages of u-area */ +#define UPAGES 4 /* pages of u-area */ #define UADDR 0xEEE00000 /* address of u */ #define UVPN (UADDR>>PGSHIFT)/* virtual page number of u */ #define KERNELSTACK (UADDR+UPAGES*NBPG) /* top of kernel stack */ diff --git a/sys/arch/mvme88k/include/pmap.h b/sys/arch/mvme88k/include/pmap.h index 839727e5d8d..625b3efa533 100644 --- a/sys/arch/mvme88k/include/pmap.h +++ b/sys/arch/mvme88k/include/pmap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.h,v 1.5 1999/02/09 06:36:27 smurph Exp $ */ +/* $OpenBSD: pmap.h,v 1.6 1999/05/29 04:41:45 smurph Exp $ */ /* * Mach Operating System * Copyright (c) 1991 Carnegie Mellon University @@ -95,6 +95,12 @@ void pmap_activate(pmap_t my_pmap, pcb_t); void pmap_deactivate(pmap_t pmap, pcb_t); int pmap_check_transaction(pmap_t pmap, vm_offset_t va, vm_prot_t type); +vm_offset_t pmap_map( + vm_offset_t virt, + vm_offset_t start, + vm_offset_t end, + vm_prot_t prot); + vm_offset_t pmap_map_batc( vm_offset_t virt, vm_offset_t start, diff --git a/sys/arch/mvme88k/include/proc.h b/sys/arch/mvme88k/include/proc.h index b283c4a72ff..31acf460704 100644 --- a/sys/arch/mvme88k/include/proc.h +++ b/sys/arch/mvme88k/include/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.4 1999/02/09 06:36:27 smurph Exp $ */ +/* $OpenBSD: proc.h,v 1.5 1999/05/29 04:41:45 smurph Exp $ */ /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -43,7 +43,7 @@ * @(#)proc.h 8.1 (Berkeley) 6/11/93 * * from: Header: proc.h,v 1.6 92/11/26 02:04:41 torek Exp (LBL) - * $Id: proc.h,v 1.4 1999/02/09 06:36:27 smurph Exp $ + * $Id: proc.h,v 1.5 1999/05/29 04:41:45 smurph Exp $ */ #include <machine/pcb.h> @@ -56,4 +56,6 @@ struct mdproc { struct trapframe *md_tf; /* trap/syscall registers */ struct fpstate *md_fpstate; /* fpu state, if any; always resident */ int md_upte[UPAGES]; /* ptes for mapping u page */ + int md_ss_addr; /* single step address for ptrace */ + int md_ss_instr; /* single step instruction for ptrace */ }; diff --git a/sys/arch/mvme88k/include/prom.h b/sys/arch/mvme88k/include/prom.h index 015c65a3c54..2f1650c85be 100644 --- a/sys/arch/mvme88k/include/prom.h +++ b/sys/arch/mvme88k/include/prom.h @@ -1,4 +1,4 @@ -/* $OpenBSD: prom.h,v 1.3 1999/02/09 06:36:27 smurph Exp $ */ +/* $OpenBSD: prom.h,v 1.4 1999/05/29 04:41:45 smurph Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -98,19 +98,21 @@ struct mvmeprom_brdid { u_short devtype; u_short devnum; u_long bug; - - /* - * XXX: I have seen no documentation for these! - * - * The following (appears to) exist only on the MVME162 and - * upwards. We should figure out what the other fields are. - */ - u_char xx1[16]; - u_char xx2[4]; - u_char longname[12]; - u_char xx3[16]; - u_char speed[4]; - u_char xx4[12]; + u_char version[4]; + u_char serial[12]; /* SBC serial number */ + u_char id[16]; /* SBC id */ + u_char pwa[16]; /* printed wiring assembly number */ + u_char speed[4]; /* cpu speed */ + u_char etheraddr[6]; /* mac address, all zero if no ether */ + u_char fill[2]; + u_char scsiid[2]; /* local SCSI id */ + u_char sysid[8]; /* system id - nothing on mvme187 */ + u_char brd1_pwb[8]; /* memory board 1 pwb */ + u_char brd1_serial[8]; /* memory board 1 serial */ + u_char brd2_pwb[8]; /* memory board 2 pwb */ + u_char brd2_serial[8]; /* memory board 2 serial */ + u_char reserved[153]; + u_char cksum[1]; }; struct mvmeprom_time { diff --git a/sys/arch/mvme88k/mvme88k/autoconf.c b/sys/arch/mvme88k/mvme88k/autoconf.c index 3a04a63dcfa..df5a0ba3e52 100644 --- a/sys/arch/mvme88k/mvme88k/autoconf.c +++ b/sys/arch/mvme88k/mvme88k/autoconf.c @@ -29,7 +29,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: autoconf.c,v 1.4 1998/12/15 05:11:01 smurph Exp $ + * $Id: autoconf.c,v 1.5 1999/05/29 04:41:45 smurph Exp $ */ #include <sys/param.h> #include <sys/systm.h> @@ -74,7 +74,7 @@ void configure() { bootdv = NULL; /* set by device drivers (if found) */ -/* rminit(extiomap, (long)EIOMAPSIZE, (long)1, "extio", EIOMAPSIZE/16);*/ + /*rminit(extiomap, (long)EIOMAPSIZE, (long)1, "extio", EIOMAPSIZE/16);*/ if (config_rootfound("mainbus", "mainbus") == 0) panic("no mainbus found"); @@ -124,8 +124,7 @@ swapconf() { register struct swdevt *swp; register int nblks; - - for (swp = swdevt; swp->sw_dev != NODEV; swp++) + for (swp = swdevt; swp->sw_dev != NODEV; swp++){ if (bdevsw[major(swp->sw_dev)].d_psize) { nblks = (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); @@ -133,6 +132,7 @@ swapconf() (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) swp->sw_nblks = nblks; } + } dumpconf(); } diff --git a/sys/arch/mvme88k/mvme88k/conf.c b/sys/arch/mvme88k/mvme88k/conf.c index 0fc1eb1fd62..f91962bbd7c 100644 --- a/sys/arch/mvme88k/mvme88k/conf.c +++ b/sys/arch/mvme88k/mvme88k/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.10 1999/02/09 06:36:28 smurph Exp $ */ +/* $OpenBSD: conf.c,v 1.11 1999/05/29 04:41:46 smurph Exp $ */ /*- * Copyright (c) 1991 The Regents of the University of California. @@ -107,21 +107,19 @@ cdev_decl(ctty); cdev_decl(mm); cdev_decl(sw); -#if 1 /*notyet*/ #include "sram.h" cdev_decl(sram); #include "nvram.h" cdev_decl(nvram); -#endif -#if notyet #include "vmel.h" cdev_decl(vmel); #include "vmes.h" cdev_decl(vmes); +#if notyet #include "flash.h" cdev_decl(flash); #endif /* notyet */ @@ -146,6 +144,9 @@ cdev_decl(cl); #include "bugtty.h" cdev_decl(bugtty); +#include "vx.h" +cdev_decl(vx); + /* open, close, write, ioctl */ #define cdev_lp_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ @@ -192,6 +193,12 @@ cdev_decl(tun); #define NLKM 0 #endif +#ifdef IPFILTER +#define NIPF 1 +#else +#define NIPF 0 +#endif + cdev_decl(lkm); struct cdevsw cdevsw[] = @@ -203,18 +210,10 @@ struct cdevsw cdevsw[] = cdev_tty_init(NPTY,pts), /* 4: pseudo-tty slave */ cdev_ptc_init(NPTY,ptc), /* 5: pseudo-tty master */ cdev_log_init(1,log), /* 6: /dev/klog */ -#if 1 cdev_mdev_init(NSRAM,sram), /* 7: /dev/sramX */ -#else - cdev_notdef(), /* 7: */ -#endif /* notyet */ cdev_disk_init(NSD,sd), /* 8: SCSI disk */ cdev_disk_init(NCD,cd), /* 9: SCSI CD-ROM */ -#if 1 cdev_mdev_init(NNVRAM,nvram), /* 10: /dev/nvramX */ -#else - cdev_notdef(), /* 10: */ -#endif /* notyet */ #if notyet cdev_mdev_init(NFLASH,flash), /* 11: /dev/flashX */ @@ -225,7 +224,7 @@ struct cdevsw cdevsw[] = #endif /* notyet */ cdev_tty_init(NCL,cl), /* 13: CL-CD1400 serial (tty0[0-3]) */ cdev_tty_init(NBUGTTY,bugtty), /* 14: BUGtty (ttyB) */ - cdev_notdef(), /* 15 */ + cdev_tty_init(NVX,vx), /* 15: MVME332XT serial/lpt ttyv[0-7][a-i] */ cdev_notdef(), /* 16 */ cdev_notdef(), /* 17: concatenated disk */ cdev_disk_init(NRD,rd), /* 18: ramdisk disk */ @@ -245,25 +244,20 @@ struct cdevsw cdevsw[] = #if notyet cdev_lp_init(NLP,lp), /* 28: lp */ cdev_lp_init(NLPTWO,lptwo), /* 29: lptwo */ -#else +#else cdev_notdef(), /* 28: lp */ cdev_notdef(), /* 29: lptwo */ #endif /* notyet */ cdev_notdef(), /* 30 */ -#if notyet cdev_mdev_init(NVMEL,vmel), /* 31: /dev/vmelX */ cdev_mdev_init(NVMES,vmes), /* 32: /dev/vmesX */ -#else /* notyet */ - cdev_notdef(), /* 31: /dev/vmelX */ - cdev_notdef(), /* 32: /dev/vmesX */ -#endif /* notyet */ cdev_lkm_dummy(), /* 33 */ cdev_lkm_dummy(), /* 34 */ cdev_lkm_dummy(), /* 35 */ cdev_lkm_dummy(), /* 36 */ cdev_lkm_dummy(), /* 37 */ cdev_lkm_dummy(), /* 38 */ - cdev_notdef(), /* 39 */ + cdev_gen_ipf(NIPF,ipl), /* 39: IP filter */ cdev_notdef(), /* 40 */ cdev_notdef(), /* 41 */ cdev_notdef(), /* 42 */ diff --git a/sys/arch/mvme88k/mvme88k/eh.S b/sys/arch/mvme88k/mvme88k/eh.S index 00da4a56d3d..3ba6fc8046e 100644 --- a/sys/arch/mvme88k/mvme88k/eh.S +++ b/sys/arch/mvme88k/mvme88k/eh.S @@ -1,4 +1,4 @@ -/* $OpenBSD: eh.S,v 1.6 1999/02/09 06:36:28 smurph Exp $ */ +/* $OpenBSD: eh.S,v 1.7 1999/05/29 04:41:46 smurph Exp $ */ /* * Mach Operating System * Copyright (c) 1993-1991 Carnegie Mellon University @@ -239,6 +239,8 @@ #define FLAG_FROM_KERNEL 8 /* this should be in asm.h */ +#define INTSTACK 0 /* To make interupts use their own stack */ + text align 8 @@ -1664,7 +1666,7 @@ LABEL(setup_phase_one) * If it's not the interrupt exception, enable interrupts and * take care of any data access exceptions...... * -#if notyet +#if INTSTACK * If interrupt exception, switch to interrupt stack if not * already there. Else, switch to kernel stack. #endif @@ -1673,7 +1675,7 @@ LABEL(setup_phase_one) ld r2, r31, REG_OFF(EF_EPSR) bb1 PSR_SUPERVISOR_MODE_BIT, r2, 1f /* If in kernel mode */ -#if notyet +#if INTSTACK ld r3, r31, REG_OFF(EF_VECTOR) cmp r3, r3, 1 /* is interrupt ? */ bb0 eq, r3, 2f @@ -1687,13 +1689,13 @@ LABEL(setup_phase_one) addu r31, r31, USIZE /* point at proper end */ br 3f 1: -#if notyet +#if INTSTACK ld r3, r31, REG_OFF(EF_VECTOR) cmp r3, r3, 1 /* is interrupt ? */ bb0 eq, r3, 3f /* no, we will stay on kern stack */ or.u r31, r0, hi16(_intstack_end) /* swith to int stack */ or r31, r31, lo16(_intstack_end) -#endif /* notyet */ +#endif /* INTSTACK */ /* This label is here for debugging */ exception_handler_has_ksp: global exception_handler_has_ksp 3: /* diff --git a/sys/arch/mvme88k/mvme88k/locore.S b/sys/arch/mvme88k/mvme88k/locore.S index e5e00519946..498331426a1 100644 --- a/sys/arch/mvme88k/mvme88k/locore.S +++ b/sys/arch/mvme88k/mvme88k/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.7 1999/02/09 06:36:28 smurph Exp $ */ +/* $OpenBSD: locore.S,v 1.8 1999/05/29 04:41:46 smurph Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -213,8 +213,11 @@ LABEL(_start_text) /* This is the *real* start upon poweron or reset */ set r11, r11, 1<PSR_SHADOW_FREEZE_BIT> set r11, r11, 1<PSR_FPU_DISABLE_BIT> #endif +#define PSR_MXM_DISABLE_BIT 2 + set r11, r0, 1<PSR_SUPERVISOR_MODE_BIT> set r11, r11, 1<PSR_INTERRUPT_DISABLE_BIT> + set r11, r11, 1<PSR_MXM_DISABLE_BIT> /* a cheat! for now... */ stcr r11, PSR FLUSH_PIPELINE @@ -313,7 +316,7 @@ _msgsw: global _intstack global _intstack_end _intstack: - space (4 * NBPG) /* 16K */ + space (4 * NBPG) /* 16K, just to be safe*/ _intstack_end: /* diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c index a5ced81862b..71c87315fcb 100644 --- a/sys/arch/mvme88k/mvme88k/machdep.c +++ b/sys/arch/mvme88k/mvme88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.14 1999/05/24 23:09:05 jason Exp $ */ +/* $OpenBSD: machdep.c,v 1.15 1999/05/29 04:41:46 smurph Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -128,6 +128,9 @@ volatile u_char *pcc2intr_ipl; volatile vm_offset_t bugromva; volatile vm_offset_t sramva; volatile vm_offset_t obiova; +volatile vm_offset_t extiova; +volatile vm_offset_t vmea16va; +volatile vm_offset_t vmea32d16va; int physmem; /* available physical memory, in pages */ @@ -143,7 +146,7 @@ int BugWorks = 0; */ int safepri = 0; -#if 0 /*XXX_FUTURE*/ +#if 1 /*XXX_FUTURE*/ /* * iomap stuff is for managing chunks of virtual address space that * can be allocated to IO devices. @@ -197,7 +200,7 @@ char *esym; int boothowto; /* read in kern/bootstrap */ int cputyp; -int cpuspeed = 33; /* 25 MHZ XXX should be read from NVRAM */ +int cpuspeed = 25; /* 25 MHZ XXX should be read from NVRAM */ #ifndef roundup #define roundup(value, stride) (((unsigned)(value) + (stride) - 1) & ~((stride)-1)) @@ -220,8 +223,9 @@ int no_symbols = 1; struct proc *lastproc; pcb_t curpcb; - extern struct user *proc0paddr; +extern void *etherbuf; +extern int etherlen; /* XXX this is to fake out the console routines, while booting. */ #include "bugtty.h" @@ -348,11 +352,11 @@ identifycpu() { cpuspeed = getcpuspeed(); sprintf(cpu_model, "Motorola MVME%x %dMhz", cputyp, cpuspeed); - printf("\nModel: %s\n", cpu_model); + printf("\nModel: %s\n", cpu_model); } /* The following two functions assume UPAGES == 3 */ -#if UPAGES != 3 +#if UPAGES != 4 #error "UPAGES changed?" #endif @@ -377,12 +381,12 @@ void load_u_area(struct proc *p) { pte_template_t *t; - + int i; for (i=0; i<UPAGES; i++) { t = kvtopte(UADDR + (i * NBPG)); t->bits = p->p_md.md_upte[i]; -} + } for (i=0; i<UPAGES; i++) { cmmu_flush_tlb(1, UADDR + (i * NBPG), NBPG); } @@ -477,7 +481,23 @@ cpu_startup() printf("obiova %x: OBIO not free\n", obiova); panic("bad OBIO"); } + +#if 0 + /* + * Grab the EXTIO space that we hardwired in pmap_bootstrap + */ + + extiova = IOMAP_MAP_START; + + vm_map_find(kernel_map, vm_object_allocate(IOMAP_SIZE), 0, + (vm_offset_t *)&extiova, IOMAP_SIZE, TRUE); + if (extiova != IOMAP_MAP_START) { + printf("extiova %x: EXTIO not free\n", extiova); + panic("bad EXTIO"); + } +#endif + /* * Now allocate buffers proper. They are different than the above * in that they usually occupy more virtual memory than physical. @@ -535,7 +555,7 @@ cpu_startup() panic("cpu_startup: unable to create phys_map"); } -#if 0 /*XXX_FUTURE*/ +#if 1 /*XXX_FUTURE*/ iomap_map = vm_map_create(kernel_pmap, IOMAP_MAP_START, IOMAP_MAP_START + IOMAP_SIZE, TRUE); if (iomap_map == NULL) { @@ -666,7 +686,7 @@ allocsys(v) valloc(swbuf, struct buf, nswbuf); valloc(buf, struct buf, nbuf); -#if 0 /*XXX_FUTURE*/ +#if 1 /*XXX_FUTURE*/ /* * Arbitrarily limit the number of devices mapping * the IO space at a given time to NIOPMAP (= 32, default). @@ -1760,11 +1780,13 @@ db_splx(int s) } #endif /* DDB */ + /* * Called from locore.S during boot, * this is the first C code that's run. */ + void m187_bootstrap(void) { @@ -1787,21 +1809,6 @@ m187_bootstrap(void) vm_set_page_size(); -#if 0 - esym = kflags.esym; - boothowto = kflags.bflags; - bootdev = kflags.bdev; -#endif /* 0 */ - -#if 0 - end_loaded = kflags.end_load; - if (esym != NULL) { - end = (char *)((int)(kflags.symtab)); - } else { - first_addr = (vm_offset_t)&end; - } -#endif - first_addr = m88k_round_page(first_addr); if (!no_symbols) boothowto |= RB_KDB; diff --git a/sys/arch/mvme88k/mvme88k/pmap.c b/sys/arch/mvme88k/mvme88k/pmap.c index bac606c48a9..768392fdea9 100644 --- a/sys/arch/mvme88k/mvme88k/pmap.c +++ b/sys/arch/mvme88k/mvme88k/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.6 1999/02/09 06:36:30 smurph Exp $ */ +/* $OpenBSD: pmap.c,v 1.7 1999/05/29 04:41:46 smurph Exp $ */ /* * Copyright (c) 1996 Nivas Madhur * All rights reserved. @@ -257,7 +257,7 @@ static pv_entry_t pv_head_table; /* array of entries, one per page */ #define UNLOCK_PVH(index) #define ETHERPAGES 16 -void *etherbuf; +void *etherbuf=NULL; int etherlen; /* @@ -1125,119 +1125,132 @@ pmap_bootstrap(vm_offset_t load_start, /* IN */ * the translation tree. I don't think we need to map it CACHE_INH * here... */ - if (kmapva != vaddr) { + if (kmapva != vaddr) { #ifdef DEBUG - if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) { - printf("(pmap_bootstrap) correcting vaddr\n"); - } + if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) { + printf("(pmap_bootstrap) correcting vaddr\n"); + } #endif - while (vaddr < (*virt_start - kernel_pmap_size)) - vaddr = M88K_ROUND_PAGE(vaddr + 1); - } + while (vaddr < (*virt_start - kernel_pmap_size)) + vaddr = M88K_ROUND_PAGE(vaddr + 1); + } - vaddr = PMAPER( - vaddr, - (vm_offset_t)kmap, - *phys_start, - (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_GLOBAL << 16)); + vaddr = PMAPER(vaddr,(vm_offset_t)kmap,*phys_start, + (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_GLOBAL << 16)); + + if (vaddr != *virt_start) { + #ifdef DEBUG + if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) { + printf("1:vaddr %x *virt_start %x *phys_start %x\n", vaddr, + *virt_start, *phys_start); + } + #endif + *virt_start = vaddr; + *phys_start = round_page(*phys_start); + } - etherlen = ETHERPAGES * NBPG; /* - * Get ethernet buffer - need etherlen bytes physically contiguous. + * Get ethernet buffer - need etherlen bytes physically contiguous. * 1 to 1 mapped as well???. There is actually a bug in the macros * used by the 1x7 ethernet driver. Remove this when that is fixed. * XXX -nivas */ - - if (vaddr != *virt_start) { -#ifdef DEBUG - if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) { - printf("1:vaddr %x *virt_start %x *phys_start %x\n", vaddr, - *virt_start, *phys_start); - } -#endif - *virt_start = vaddr; - *phys_start = round_page(*phys_start); - } - + etherlen = (ETHERPAGES * NBPG); *phys_start = vaddr; - + etherbuf = (void *)vaddr; - - vaddr = PMAPER( - vaddr, - *phys_start, - *phys_start + etherlen, - (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_INH << 16)); - + + vaddr = PMAPER(vaddr,*phys_start,*phys_start + etherlen, + (VM_PROT_WRITE|VM_PROT_READ)|(CACHE_INH << 16)); *virt_start += etherlen; - *phys_start += etherlen; - + *phys_start += etherlen; + if (vaddr != *virt_start) { #ifdef DEBUG - if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) { - printf("2:vaddr %x *virt_start %x *phys_start %x\n", vaddr, - *virt_start, *phys_start); - } + if ((pmap_con_dbg & (CD_BOOT | CD_FULL)) == (CD_BOOT | CD_FULL)) { + printf("2:vaddr %x *virt_start %x *phys_start %x\n", vaddr, + *virt_start, *phys_start); + } #endif - *virt_start = vaddr; - *phys_start = round_page(*phys_start); + *virt_start = vaddr; + *phys_start = round_page(*phys_start); } - *virt_start = round_page(*virt_start); - *virt_end = VM_MAX_KERNEL_ADDRESS; - /* - * Map a few more pages for phys routines and debugger. - */ + *virt_start = round_page(*virt_start); + *virt_end = VM_MAX_KERNEL_ADDRESS; - phys_map_vaddr1 = round_page(*virt_start); - phys_map_vaddr2 = phys_map_vaddr1 + PAGE_SIZE; + /* + * Map a few more pages for phys routines and debugger. + */ - /* - * To make 1:1 mapping of virt:phys, throw away a few phys pages. - * XXX what is this? nivas - */ + phys_map_vaddr1 = round_page(*virt_start); + phys_map_vaddr2 = phys_map_vaddr1 + PAGE_SIZE; + /* + * To make 1:1 mapping of virt:phys, throw away a few phys pages. + * XXX what is this? nivas + */ - *phys_start += 2 * PAGE_SIZE; - *virt_start += 2 * PAGE_SIZE; - - /* - * Map all IO space 1-to-1. Ideally, I would like to not do this - * but have va for the given IO address dynamically allocated. But - * on the 88200, 2 of the BATCs are hardwired to do map the IO space - * 1-to-1; I decided to map the rest of the IO space 1-to-1. - * And bug ROM & the SRAM need to be mapped 1-to-1 if we ever want to - * execute bug system calls after the MMU has been turned on. - * OBIO should be mapped cache inhibited. - */ + *phys_start += 2 * PAGE_SIZE; + *virt_start += 2 * PAGE_SIZE; + + /* + * Map all IO space 1-to-1. Ideally, I would like to not do this + * but have va for the given IO address dynamically allocated. But + * on the 88200, 2 of the BATCs are hardwired to do map the IO space + * 1-to-1; I decided to map the rest of the IO space 1-to-1. + * And bug ROM & the SRAM need to be mapped 1-to-1 if we ever want to + * execute bug system calls after the MMU has been turned on. + * OBIO should be mapped cache inhibited. + */ - PMAPER( + PMAPER( BUGROM_START, BUGROM_START, BUGROM_START + BUGROM_SIZE, VM_PROT_WRITE|VM_PROT_READ|(CACHE_INH << 16)); - PMAPER( + PMAPER( SRAM_START, SRAM_START, SRAM_START + SRAM_SIZE, VM_PROT_WRITE|VM_PROT_READ|(CACHE_GLOBAL << 16)); - PMAPER( + PMAPER( OBIO_START, OBIO_START, OBIO_START + OBIO_SIZE, VM_PROT_WRITE|VM_PROT_READ|(CACHE_INH << 16)); +#if 0 + PMAPER( + VMEA16, + VMEA16, + VMEA16 + VMEA16_SIZE, + VM_PROT_WRITE|VM_PROT_READ|(CACHE_INH << 16)); + + PMAPER( + VMEA32D16, + VMEA32D16, + VMEA32D16 + VMEA32D16_SIZE, + VM_PROT_WRITE|VM_PROT_READ|(CACHE_INH << 16)); + + PMAPER( + IOMAP_MAP_START, + IOMAP_MAP_START, + IOMAP_MAP_START + IOMAP_SIZE, + VM_PROT_WRITE|VM_PROT_READ|(CACHE_INH << 16)); +#endif /* 0 */ + /* * Allocate all the submaps we need. Note that SYSMAP just allocates * kernel virtual address with no physical backing memory. The idea * is physical memory will be mapped at this va before using that va. * This means that if different physcal pages are going to be mapped - * at different times, we better do a tlb flush before using it - * else we will be referencing the wrong page. + * at different times, we better do a tlb flush before using it - + * else we will be referencing the wrong page. */ #define SYSMAP(c, p, v, n) \ diff --git a/sys/arch/mvme88k/mvme88k/process_machdep.c b/sys/arch/mvme88k/mvme88k/process_machdep.c index d58e2725390..f8e66540bf8 100644 --- a/sys/arch/mvme88k/mvme88k/process_machdep.c +++ b/sys/arch/mvme88k/mvme88k/process_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: process_machdep.c,v 1.5 1999/02/09 06:36:30 smurph Exp $ */ +/* $OpenBSD: process_machdep.c,v 1.6 1999/05/29 04:41:47 smurph Exp $ */ /* * Copyright (c) 1993 The Regents of the University of California. @@ -74,16 +74,14 @@ #include <machine/frame.h> #endif #include <sys/ptrace.h> +/* NOTE: struct reg == struct trapframe */ int process_read_regs(p, regs) struct proc *p; struct reg *regs; { -#if 0 - /* NOTE: struct reg == struct trapframe */ bcopy(p->p_md.md_tf, (caddr_t)regs, sizeof(struct reg)); -#endif return (0); } @@ -92,11 +90,7 @@ process_write_regs(p, regs) struct proc *p; struct reg *regs; { -#if 0 - int psr = p->p_md.md_tf->tf_epsr & ~PSR_ICC; bcopy((caddr_t)regs, p->p_md.md_tf, sizeof(struct reg)); - p->p_md.md_tf->tf_epsr = psr | (regs->r_epsr & PSR_ICC); -#endif return (0); } @@ -104,10 +98,8 @@ int process_sstep(p, sstep) struct proc *p; { -#if 0 if (sstep) - return EINVAL; -#endif + cpu_singlestep(p); return (0); } @@ -116,10 +108,8 @@ process_set_pc(p, addr) struct proc *p; caddr_t addr; { -#if 0 - p->p_md.md_tf->tf_pc = (u_int)addr; - p->p_md.md_tf->tf_npc = (u_int)addr + 4; -#endif + p->p_md.md_tf->sxip = (u_int)addr; + p->p_md.md_tf->snip = (u_int)addr + 4; return (0); } diff --git a/sys/arch/mvme88k/mvme88k/trap.c b/sys/arch/mvme88k/mvme88k/trap.c index 53eab7da4b8..57b276fd5dc 100644 --- a/sys/arch/mvme88k/mvme88k/trap.c +++ b/sys/arch/mvme88k/mvme88k/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.6 1999/02/09 06:36:30 smurph Exp $ */ +/* $OpenBSD: trap.c,v 1.7 1999/05/29 04:41:47 smurph Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -57,12 +57,17 @@ #include <machine/m88100.h> /* DMT_VALID, etc. */ #include <machine/trap.h> #include <machine/psl.h> /* FIP_E, etc. */ +#include <machine/pcb.h> /* FIP_E, etc. */ #include <sys/systm.h> #if (DDB) #include <machine/db_machdep.h> +#else +#define PC_REGS(regs) ((regs->sxip & 2) ? regs->sxip & ~3 : \ + (regs->snip & 2 ? regs->snip & ~3 : regs->sfip & ~3)) #endif /* DDB */ +#define BREAKPOINT (0xF000D1F8U) /* Single Step Breakpoint */ #define TRAPTRACE #if defined(TRAPTRACE) @@ -191,6 +196,7 @@ trap(unsigned type, struct m88100_saved_state *frame) union sigval sv; int result; int sig = 0; + unsigned pc = PC_REGS(frame); /* get program counter (sxip) */ extern vm_map_t kernel_map; extern int fubail(), subail(); @@ -392,11 +398,12 @@ trap(unsigned type, struct m88100_saved_state *frame) case T_DATAFLT+T_USER: user_fault: - if (type == T_INSTFLT+T_USER) + if (type == T_INSTFLT+T_USER){ fault_addr = frame->sxip & XIP_ADDR; - else + }else{ fault_addr = frame->dma0; - + } + if (frame->dmt0 & (DMT_WRITE|DMT_LOCKBAR)) { ftype = VM_PROT_READ|VM_PROT_WRITE; fault_code = VM_PROT_WRITE; @@ -502,9 +509,61 @@ trap(unsigned type, struct m88100_saved_state *frame) * is executed. When this breakpoint is hit, we get the * T_STEPBPT trap. */ +#if 0 + frame->sfip = frame->snip; /* set up next FIP */ + frame->snip = frame->sxip; /* set up next NIP */ + break; +#endif + { + register unsigned va; + unsigned instr; + struct uio uio; + struct iovec iov; + + /* compute address of break instruction */ + va = pc; + + /* read break instruction */ + instr = fuiword((caddr_t)pc); +#if 1 + printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n", + p->p_comm, p->p_pid, instr, pc, + p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */ +#endif + /* check and see if we got here by accident */ +/* + if (p->p_md.md_ss_addr != pc || instr != BREAKPOINT) { + sig = SIGTRAP; + fault_type = TRAP_TRACE; + break; + } +*/ + /* restore original instruction and clear BP */ + /*sig = suiword((caddr_t)pc, p->p_md.md_ss_instr);*/ + instr = p->p_md.md_ss_instr; + if (instr == 0){ + printf("Warning: can't restore instruction at %x: %x\n", + p->p_md.md_ss_addr, p->p_md.md_ss_instr); + } else { + iov.iov_base = (caddr_t)&instr; + iov.iov_len = sizeof(int); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)pc; + uio.uio_resid = sizeof(int); + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_WRITE; + uio.uio_procp = curproc; + } + frame->sfip = frame->snip; /* set up next FIP */ frame->snip = frame->sxip; /* set up next NIP */ + frame->snip |= 2; /* set valid bit */ + p->p_md.md_ss_addr = 0; + sig = SIGTRAP; + fault_type = TRAP_BRKPT; break; + } case T_USERBPT+T_USER: /* @@ -786,3 +845,206 @@ init_sir() sir_routines[1] = softclock; next_sir = 2; } + + +/************************************\ +* User Single Step Debugging Support * +\************************************/ + +/* + * Read bytes from address space for debugger. + */ +void +ss_read_bytes(addr, size, data) + unsigned addr; + register int size; + register char *data; +{ + register char *src; + + src = (char *)addr; + + while(--size >= 0) { + *data++ = *src++; + } +} + +unsigned +ss_get_value(unsigned addr, int size, int is_signed) +{ + char data[sizeof(unsigned)]; + unsigned value, extend; + int i; + + ss_read_bytes(addr, size, data); + + value = 0; + extend = (~(db_expr_t)0) << (size * 8 - 1); + for (i = 0; i < size; i++) + value = (value << 8) + (data[i] & 0xFF); + + if (size < sizeof(unsigned) && is_signed && (value & extend)) + value |= extend; + return (value); +} + + +/* + * ss_branch_taken(instruction, program counter, func, func_data) + * + * instruction will be a control flow instruction location at address pc. + * Branch taken is supposed to return the address to which the instruction + * would jump if the branch is taken. Func can be used to get the current + * register values when invoked with a register number and func_data as + * arguments. + * + * If the instruction is not a control flow instruction, panic. + */ +unsigned +ss_branch_taken( + unsigned inst, + unsigned pc, + unsigned (*func)(unsigned int, struct trapframe *), + struct trapframe *func_data) /* 'opaque' */ +{ + + /* check if br/bsr */ + if ((inst & 0xf0000000U) == 0xc0000000U) + { + /* signed 26 bit pc relative displacement, shift left two bits */ + inst = (inst & 0x03ffffffU)<<2; + /* check if sign extension is needed */ + if (inst & 0x08000000U) + inst |= 0xf0000000U; + return pc + inst; + } + + /* check if bb0/bb1/bcnd case */ + switch ((inst & 0xf8000000U)) + { + case 0xd0000000U: /* bb0 */ + case 0xd8000000U: /* bb1 */ + case 0xe8000000U: /* bcnd */ + /* signed 16 bit pc relative displacement, shift left two bits */ + inst = (inst & 0x0000ffffU)<<2; + /* check if sign extension is needed */ + if (inst & 0x00020000U) + inst |= 0xfffc0000U; + return pc + inst; + } + + /* check jmp/jsr case */ + /* check bits 5-31, skipping 10 & 11 */ + if ((inst & 0xfffff3e0U) == 0xf400c000U) + return (*func)(inst & 0x1f, func_data); /* the register value */ + + return 0; /* keeps compiler happy */ +} + +/* + * ss_getreg_val - handed a register number and an exception frame. + * Returns the value of the register in the specified + * frame. Only makes sense for general registers. + */ +unsigned +ss_getreg_val(unsigned regno, struct trapframe *tf) +{ + if (regno == 0) + return 0; + else if (regno < 31) + return tf->r[regno]; + else { + panic("bad register number to ss_getreg_val."); + return 0;/*to make compiler happy */ + } +} + +unsigned +ss_get_next_addr(struct trapframe *regs) +{ + unsigned inst; + unsigned pc = PC_REGS(regs); + unsigned addr = 0; + + inst = ss_get_value(pc, sizeof(int), FALSE); + addr = ss_branch_taken(inst, pc, ss_getreg_val, regs); + if (addr) return(addr); + return(pc + 4); +} + +int +cpu_singlestep(p) + register struct proc *p; +{ + register unsigned va; + struct trapframe *sstf = p->p_md.md_tf; + int i; + + int bpinstr = BREAKPOINT; + int curinstr; + struct uio uio; + struct iovec iov; + + /* + * Fetch what's at the current location. + */ + iov.iov_base = (caddr_t)&curinstr; + iov.iov_len = sizeof(int); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)sstf->sxip; + uio.uio_resid = sizeof(int); + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_READ; + uio.uio_procp = curproc; + procfs_domem(curproc, p, NULL, &uio); + + /* compute next address after current location */ + if(curinstr != 0) { + va = ss_get_next_addr(sstf); + printf("SS %s (%d): next breakpoint set at %x\n", + p->p_comm, p->p_pid, va); + } + else { + va = PC_REGS(sstf) + 4; + } + if (p->p_md.md_ss_addr) { + printf("SS %s (%d): breakpoint already set at %x (va %x)\n", + p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */ + return (EFAULT); + } + + p->p_md.md_ss_addr = va; + + /* + * Fetch what's at the current location. + */ + iov.iov_base = (caddr_t)&p->p_md.md_ss_instr; + iov.iov_len = sizeof(int); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)va; + uio.uio_resid = sizeof(int); + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_READ; + uio.uio_procp = curproc; + procfs_domem(curproc, p, NULL, &uio); + + /* + * Store breakpoint instruction at the "next" location now. + */ + iov.iov_base = (caddr_t)&bpinstr; + iov.iov_len = sizeof(int); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)va; + uio.uio_resid = sizeof(int); + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_WRITE; + uio.uio_procp = curproc; + i = procfs_domem(curproc, p, NULL, &uio); + + if (i < 0) return (EFAULT); + return (0); +} + diff --git a/sys/arch/mvme88k/mvme88k/vm_machdep.c b/sys/arch/mvme88k/mvme88k/vm_machdep.c index 0c482250d07..d9f5f05d898 100644 --- a/sys/arch/mvme88k/mvme88k/vm_machdep.c +++ b/sys/arch/mvme88k/mvme88k/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.7 1999/02/09 06:36:30 smurph Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.8 1999/05/29 04:41:47 smurph Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -42,7 +42,7 @@ * from: Utah $Hdr: vm_machdep.c 1.21 91/04/06$ * from: @(#)vm_machdep.c 7.10 (Berkeley) 5/7/91 * vm_machdep.c,v 1.3 1993/07/07 07:09:32 cgd Exp - * $Id: vm_machdep.c,v 1.7 1999/02/09 06:36:30 smurph Exp $ + * $Id: vm_machdep.c,v 1.8 1999/05/29 04:41:47 smurph Exp $ */ #include <sys/param.h> @@ -61,10 +61,8 @@ #include <machine/cpu.h> #include <machine/pte.h> -#ifdef XXX_FUTURE extern struct map *iomap; -#endif -extern struct map extiomap; +extern vm_map_t iomap_map; /* * Finish a fork operation, with process p2 nearly set up. @@ -304,35 +302,48 @@ iomap_mapin(vm_offset_t pa, vm_size_t len, boolean_t canwait) if (len == 0) return NULL; - off = (u_long)pa & PGOFSET; + ppa = pa; + off = (u_long)ppa & PGOFSET; len = round_page(off + len); s = splimp(); for (;;) { - iova = rmalloc(&extiomap, len); + iova = rmalloc(iomap, len); if (iova != 0) break; if (canwait) { - (void)tsleep(&extiomap, PRIBIO+1, "iomapin", 0); + (void)tsleep(iomap, PRIBIO+1, "iomapin", 0); continue; } splx(s); return NULL; } splx(s); + + cmmu_flush_tlb(1, iova, len); - tva = iova; - pa = trunc_page(pa); + ppa = trunc_page(ppa); - while (len) { - pmap_enter(kernel_pmap, tva, pa, - VM_PROT_READ|VM_PROT_WRITE, 1); +#ifndef NEW_MAPPING + tva = iova; +#else + tva = ppa; +#endif + + while (len>0) { + pmap_enter(vm_map_pmap(iomap_map), tva, ppa, + VM_PROT_WRITE|VM_PROT_READ|(CACHE_INH << 16), 1); len -= PAGE_SIZE; tva += PAGE_SIZE; ppa += PAGE_SIZE; } +#ifndef NEW_MAPPING return (iova + off); +#else + return (pa + off); +#endif + } /* @@ -348,11 +359,11 @@ iomap_mapout(vm_offset_t kva, vm_size_t len) kva = trunc_page(kva); len = round_page(off + len); - pmap_remove(kernel_pmap, kva, kva + len); + pmap_remove(vm_map_pmap(iomap_map), kva, kva + len); s = splimp(); - rmfree(&extiomap, len, kva); - wakeup(&extiomap); + rmfree(iomap, len, kva); + wakeup(iomap); splx(s); return 1; } @@ -420,10 +431,18 @@ int badvaddr(vm_offset_t va, int size) { register int x; - - if (badaddr(va, size)) { - return -1; + int i; + int ret = 0; + + for (i=0; i<5; i++){ + ret = badaddr(va, size); + if (ret) + delay(500); + else + break; } + if (ret) + return -1; switch (size) { case 1: diff --git a/sys/arch/mvme88k/stand/bootsd/Makefile b/sys/arch/mvme88k/stand/bootsd/Makefile index a44e8916872..63dfa97be93 100644 --- a/sys/arch/mvme88k/stand/bootsd/Makefile +++ b/sys/arch/mvme88k/stand/bootsd/Makefile @@ -1,5 +1,5 @@ # from: @(#)Makefile 8.1 (Berkeley) 6/10/93 -# $OpenBSD: Makefile,v 1.4 1998/12/15 06:32:33 smurph Exp $ +# $OpenBSD: Makefile,v 1.5 1999/05/29 04:41:47 smurph Exp $ RELOC=0xCF0000 @@ -18,7 +18,7 @@ CLEANFILES+=bootsd SRCS= boot.c conf.c version.c -LIBS= ${LIBSA} ${LIBBUG} ${LIBZ} -lgcc -lc -lgcc +LIBS= ${LIBSA} ${LIBBUG} ${LIBZ} ${LIBGCC} OBJS= ${SRCS:N*.h:R:S/$/.o/g} @@ -27,10 +27,10 @@ ALL= ${BOOTS} all: ${ALL} -bootsd: ${OBJS} ${BUGCRT} ${LIBS} +bootsd: ${OBJS} ${SDCRT} ${LIBS} ${LD} ${LDFLAGS} -o $@ \ ${SDCRT} ${OBJS} ${LIBS} -#${SRTOBJ} + install: install -c -m 555 -g bin -o bin ${BOOTS} ${DESTDIR}${MDEC_DIR} diff --git a/sys/arch/mvme88k/stand/bootst/Makefile b/sys/arch/mvme88k/stand/bootst/Makefile index e704666e79e..8d765cc1766 100644 --- a/sys/arch/mvme88k/stand/bootst/Makefile +++ b/sys/arch/mvme88k/stand/bootst/Makefile @@ -1,5 +1,5 @@ # from: @(#)Makefile 8.1 (Berkeley) 6/10/93 -# $OpenBSD: Makefile,v 1.4 1998/12/15 06:09:51 smurph Exp $ +# $OpenBSD: Makefile,v 1.5 1999/05/29 04:41:47 smurph Exp $ RELOC=0xAF0000 SIZE?= size @@ -9,6 +9,7 @@ DEFS= -DSTANDALONE -DCOMPAT_NOLABEL INCPATH=-I${.CURDIR} -I${.CURDIR}/../libsa -I${.CURDIR}/../libbug \ -I${.CURDIR}/../../include -I${S} -I${S}/lib/libsa CFLAGS= -O2 ${INCPATH} ${DEFS} ${COPTS} +LDFLAGS=-s -N -T ${RELOC} CLEANFILES+=stboot bootst bootst.bug .include "${S}/arch/mvme88k/stand/wrtvid/Makefile.inc" @@ -19,7 +20,7 @@ CLEANFILES+=stboot bootst bootst.bug SRCS= boot.c conf.c dev_tape.c rawfs.c version.c -LIBS= ${LIBSA} ${LIBBUG} ${LIBZ} libgcc.a +LIBS= ${LIBSA} ${LIBBUG} ${LIBZ} OBJS= ${SRCS:N*.h:R:S/$/.o/g} @@ -29,7 +30,7 @@ ALL= ${BOOTS} all: ${ALL} bootst.bug: ${OBJS} ${BUGCRT} ${LIBS} - ${LD} -s -N -T ${RELOC} ${BUGCRT} ${OBJS} ${LIBS} -o $@ + ${LD} ${LDFLAGS} ${BUGCRT} ${OBJS} ${LIBS} -o $@ @${SIZE} bootst.bug bootst stboot: bootst.bug ${WRTVID} diff --git a/sys/arch/mvme88k/stand/bootxx/Makefile b/sys/arch/mvme88k/stand/bootxx/Makefile index d9e3b8891a1..1e04e3eaf25 100644 --- a/sys/arch/mvme88k/stand/bootxx/Makefile +++ b/sys/arch/mvme88k/stand/bootxx/Makefile @@ -1,5 +1,5 @@ # from: @(#)Makefile 8.1 (Berkeley) 6/10/93 -# $OpenBSD: Makefile,v 1.3 1998/12/15 06:32:34 smurph Exp $ +# $OpenBSD: Makefile,v 1.4 1999/05/29 04:41:48 smurph Exp $ RELOC=0xAF0000 @@ -17,7 +17,7 @@ CLEANFILES+=bootxx SRCS= bootxx.c conf.c version.c -LIBS= ${LIBSA} ${LIBBUG} ${LIBZ} -lgcc -lc -lgcc +LIBS= ${LIBSA} ${LIBBUG} ${LIBZ} ${LIBGCC} OBJS= ${SRCS:N*.h:R:S/$/.o/g} diff --git a/sys/arch/mvme88k/stand/netboot/Makefile b/sys/arch/mvme88k/stand/netboot/Makefile index ee920ad3152..10c150fe1e0 100644 --- a/sys/arch/mvme88k/stand/netboot/Makefile +++ b/sys/arch/mvme88k/stand/netboot/Makefile @@ -1,5 +1,5 @@ -# $OpenBSD: Makefile,v 1.5 1998/12/15 06:32:35 smurph Exp $ +# $OpenBSD: Makefile,v 1.6 1999/05/29 04:41:48 smurph Exp $ RELOC=0xAF0000 SIZE?= size @@ -21,7 +21,7 @@ CLEANFILES+=netboot netboot.bin SRCS= boot.c conf.c version.c devopen.c dev_net.c SRCS+= if_ie.c if_le.c OBJS= ${SRCS:S/.c/.o/g} -LIBS= ${LIBSA} ${LIBBUG} ${LIBZ} -lgcc -lc -lgcc +LIBS= ${LIBSA} ${LIBBUG} ${LIBZ} ${LIBGCC} LDFLAGS+= -s -N -T ${RELOC} #LDFLAGS+= -nostdlib -s -N -Ttext ${RELOC} diff --git a/sys/arch/mvme88k/stand/netboot/config.h b/sys/arch/mvme88k/stand/netboot/config.h index b79bd88e9ad..895f749d0f9 100644 --- a/sys/arch/mvme88k/stand/netboot/config.h +++ b/sys/arch/mvme88k/stand/netboot/config.h @@ -1,4 +1,4 @@ -/* $OpenBSD: config.h,v 1.1 1998/08/22 08:37:56 smurph Exp $ */ +/* $OpenBSD: config.h,v 1.2 1999/05/29 04:41:48 smurph Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -45,6 +45,8 @@ #define CPU_172 0x172 #define CPU_177 0x177 #define CPU_187 0x187 +#define CPU_188 0x188 +#define CPU_197 0x197 struct brdid { u_long eye_catcher; |