summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/mvme88k/dev/bugio.c10
-rw-r--r--sys/arch/mvme88k/dev/busswitch.c152
-rw-r--r--sys/arch/mvme88k/dev/busswitchreg.h10
-rw-r--r--sys/arch/mvme88k/dev/cl.c27
-rw-r--r--sys/arch/mvme88k/dev/clock.c280
-rw-r--r--sys/arch/mvme88k/dev/dart.c1191
-rw-r--r--sys/arch/mvme88k/dev/dartreg.h311
-rw-r--r--sys/arch/mvme88k/dev/i82596.h310
-rw-r--r--sys/arch/mvme88k/dev/if_ie.c277
-rw-r--r--sys/arch/mvme88k/dev/if_ie.h46
-rw-r--r--sys/arch/mvme88k/dev/nvram.c110
-rw-r--r--sys/arch/mvme88k/dev/nvramreg.h17
-rw-r--r--sys/arch/mvme88k/dev/pcctwo.c37
-rw-r--r--sys/arch/mvme88k/dev/sclock.c412
-rw-r--r--sys/arch/mvme88k/dev/syscon.c250
-rw-r--r--sys/arch/mvme88k/dev/sysconreg.h61
-rw-r--r--sys/arch/mvme88k/dev/vme.c290
-rw-r--r--sys/arch/mvme88k/dev/vs.c541
-rw-r--r--sys/arch/mvme88k/dev/vsdma.c6
-rw-r--r--sys/arch/mvme88k/dev/vsreg.h71
20 files changed, 3670 insertions, 739 deletions
diff --git a/sys/arch/mvme88k/dev/bugio.c b/sys/arch/mvme88k/dev/bugio.c
index 3a3d085dd5e..aee175f7206 100644
--- a/sys/arch/mvme88k/dev/bugio.c
+++ b/sys/arch/mvme88k/dev/bugio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bugio.c,v 1.3 1999/05/29 04:41:42 smurph Exp $ */
+/* $OpenBSD: bugio.c,v 1.4 1999/09/27 18:43:21 smurph Exp $ */
/* Copyright (c) 1998 Steve Murphree, Jr. */
#include <machine/bugio.h>
@@ -64,13 +64,15 @@ buginit()
char
buginchr(void)
{
- register int cc asm("r2");
+ register int cc;
+ int ret;
BUGCTXT();
asm volatile ("or r9,r0," INCHR);
asm volatile ("tb0 0,r0,0x1F0");
asm volatile ("or %0,r0,r2" : "=r" (cc) : );
- OSCTXT();
- return ((char)cc & 0xFF);
+ ret = cc;
+ OSCTXT();
+ return ((char)ret & 0xFF);
}
bugoutchr(unsigned char c)
diff --git a/sys/arch/mvme88k/dev/busswitch.c b/sys/arch/mvme88k/dev/busswitch.c
new file mode 100644
index 00000000000..71eb44d9937
--- /dev/null
+++ b/sys/arch/mvme88k/dev/busswitch.c
@@ -0,0 +1,152 @@
+/* $OpenBSD: busswitch.c,v 1.1 1999/09/27 18:43:22 smurph Exp $ */
+
+/*
+ * Copyright (c) 1999 Steve Murphree, Jr.
+ *
+ * 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 under OpenBSD by
+ * Theo de Raadt for Willowglen Singapore.
+ * 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/kernel.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <machine/psl.h>
+#include <machine/autoconf.h>
+#include <machine/bugio.h>
+#include <machine/cpu.h>
+#include <machine/mioctl.h>
+#include <machine/vmparam.h>
+
+#include <mvme88k/dev/busswitchreg.h>
+
+struct busswitchsoftc {
+ struct device sc_dev;
+ void * sc_paddr;
+ void * sc_vaddr;
+ int sc_len;
+ struct busswitchreg * sc_busswitch;
+};
+
+void busswitchattach __P((struct device *, struct device *, void *));
+int busswitchmatch __P((struct device *, void *, void *));
+
+struct cfattach busswitch_ca = {
+ sizeof(struct busswitchsoftc), busswitchmatch, busswitchattach
+};
+
+struct cfdriver busswitch_cd = {
+ NULL, "busswitch", DV_DULL, 0
+};
+
+int
+busswitchmatch(parent, vcf, args)
+ struct device *parent;
+ void *vcf, *args;
+{
+ struct cfdata *cf = vcf;
+ struct confargs *ca = args;
+ struct busswitchreg *busswitch;
+ /* Don't match if wrong cpu */
+ if (cputyp != CPU_197) return (0);
+
+ busswitch = (struct busswitchreg *)(IIOV(ca->ca_paddr));
+ if (badvaddr(busswitch, 4) <= 0){
+ printf("==> busswitch: failed address check.\n");
+ return (0);
+ }
+ return (1);
+}
+
+void
+busswitchattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ struct confargs *ca = args;
+ struct busswitchsoftc *sc = (struct busswitchsoftc *)self;
+
+ sc->sc_paddr = ca->ca_paddr;
+ sc->sc_vaddr = ca->ca_vaddr;
+
+ /*
+ printf(": rev %d\n", sc->sc_busswitch->chiprev);
+ */
+ printf(": rev %d\n", 0);
+}
+
+int
+busswitch_print(args, bus)
+ void *args;
+ const char *bus;
+{
+ struct confargs *ca = args;
+
+ if (ca->ca_offset != -1)
+ printf(" offset 0x%x", ca->ca_offset);
+ if (ca->ca_ipl > 0)
+ printf(" ipl %d", ca->ca_ipl);
+ return (UNCONF);
+}
+
+int
+busswitch_scan(parent, child, args)
+ struct device *parent;
+ void *child, *args;
+{
+ struct cfdata *cf = child;
+ struct busswitchsoftc *sc = (struct busswitchsoftc *)parent;
+ struct confargs *ca = args;
+ struct confargs oca;
+
+ if (parent->dv_cfdata->cf_driver->cd_indirect) {
+ printf(" indirect devices not supported\n");
+ return 0;
+ }
+
+ bzero(&oca, sizeof oca);
+ oca.ca_offset = cf->cf_loc[0];
+ oca.ca_ipl = cf->cf_loc[1];
+ if ((oca.ca_offset != (void*)-1) && ISIIOVA(sc->sc_vaddr + oca.ca_offset)) {
+ oca.ca_vaddr = sc->sc_vaddr + oca.ca_offset;
+ oca.ca_paddr = sc->sc_paddr + oca.ca_offset;
+ } else {
+ oca.ca_vaddr = (void *)-1;
+ oca.ca_paddr = (void *)-1;
+ }
+ oca.ca_bustype = BUS_BUSSWITCH;
+ oca.ca_master = (void *)sc->sc_busswitch;
+ oca.ca_name = cf->cf_driver->cd_name;
+ if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0)
+ return (0);
+ config_attach(parent, cf, &oca, busswitch_print);
+ return (1);
+}
+
diff --git a/sys/arch/mvme88k/dev/busswitchreg.h b/sys/arch/mvme88k/dev/busswitchreg.h
new file mode 100644
index 00000000000..d1f95c717a2
--- /dev/null
+++ b/sys/arch/mvme88k/dev/busswitchreg.h
@@ -0,0 +1,10 @@
+/* $OpenBSD: busswitchreg.h,v 1.1 1999/09/27 18:43:22 smurph Exp $ */
+
+/*
+ * Memory map for BusSwitch chip found in mvme197 boards.
+ */
+
+struct busswitchreg {
+ unsigned start;
+};
+
diff --git a/sys/arch/mvme88k/dev/cl.c b/sys/arch/mvme88k/dev/cl.c
index 6e738b5a4fa..f00246bb230 100644
--- a/sys/arch/mvme88k/dev/cl.c
+++ b/sys/arch/mvme88k/dev/cl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cl.c,v 1.4 1999/05/29 04:41:43 smurph Exp $ */
+/* $OpenBSD: cl.c,v 1.5 1999/09/27 18:43:22 smurph Exp $ */
/*
* Copyright (c) 1995 Dale Rahn. All rights reserved.
@@ -900,16 +900,21 @@ clcnprobe(cp)
{
/* always there ? */
/* serial major */
- int maj;
-
- /* locate the major number */
- for (maj = 0; maj < nchrdev; maj++)
- if (cdevsw[maj].d_open == clopen)
- break;
- cp->cn_dev = makedev (maj, 0);
- cp->cn_pri = CN_NORMAL;
-
- return 1;
+ int maj;
+
+ /* bomb if it'a a MVME188 */
+ if (cputyp == CPU_188){
+ cp->cn_pri = CN_DEAD;
+ return 0;
+ }
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == clopen)
+ break;
+ cp->cn_dev = makedev (maj, 0);
+ cp->cn_pri = CN_NORMAL;
+
+ return 1;
}
int
diff --git a/sys/arch/mvme88k/dev/clock.c b/sys/arch/mvme88k/dev/clock.c
index 80a022fc263..2609694ac5d 100644
--- a/sys/arch/mvme88k/dev/clock.c
+++ b/sys/arch/mvme88k/dev/clock.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: clock.c,v 1.5 1999/05/29 04:41:43 smurph Exp $ */
-
+/* $OpenBSD: clock.c,v 1.6 1999/09/27 18:43:23 smurph Exp $ */
/*
+ * Copyright (c) 1999 Steve Murphree, Jr.
* Copyright (c) 1995 Theo de Raadt
*
* Redistribution and use in source and binary forms, with or without
@@ -77,10 +77,11 @@
*/
/*
- * Clock driver. Has both interval timer as well as statistics timer.
+ * interval clock driver.
*/
#include <sys/param.h>
+#include <sys/simplelock.h>
#include <sys/kernel.h>
#include <sys/device.h>
#ifdef GPROF
@@ -91,30 +92,27 @@
#include <machine/autoconf.h>
#include <machine/bugio.h>
#include <machine/cpu.h>
-
+#include "pcctwo.h"
+#if NPCCTWO > 0
#include <mvme88k/dev/pcctworeg.h>
+#endif
+#include "syscon.h"
+#if NSYSCON > 0
+#include <mvme88k/dev/sysconreg.h>
+#endif
#include <mvme88k/dev/vme.h>
-#include "pcctwo.h"
-extern struct vme2reg *sys_vme2;
-/*
- * Statistics clock interval and variance, in usec. Variance must be a
- * power of two. Since this gives us an even number, not an odd number,
- * we discard one case and compensate. That is, a variance of 4096 would
- * give us offsets in [0..4095]. Instead, we take offsets in [1..4095].
- * This is symmetric about the point 2048, or statvar/2, and thus averages
- * to that value (assuming uniform random numbers).
- */
-int statvar = 8192;
-int statmin; /* statclock interval - 1/2*variance */
+extern struct vme2reg *sys_vme2;
int timerok = 0;
u_long delay_factor = 1;
static int clockmatch __P((struct device *, void *, void *));
static void clockattach __P((struct device *, struct device *, void *));
-/*int clockintr __P((void *, void *));*/
-/*#int statintr __P((void *, void *));*/
+
+void sbc_initclock(void);
+void m188_initclock(void);
+void m188_timer_init __P((unsigned));
struct clocksoftc {
struct device sc_dev;
@@ -130,16 +128,18 @@ struct cfdriver clock_cd = {
NULL, "clock", DV_DULL, 0
};
-int clockintr __P((void *));
-int statintr __P((void *));
+int sbc_clockintr __P((void *));
+int sbc_statintr __P((void *));
+int m188_clockintr __P((void *));
+int m188_statintr __P((void *));
int clockbus;
-u_char stat_reset, prof_reset;
+u_char prof_reset;
- /*
+/*
* Every machine must have a clock tick device of some sort; for this
* platform this file manages it, no matter what form it takes.
- */
+ */
int
clockmatch(parent, vcf, args)
struct device *parent;
@@ -148,8 +148,7 @@ clockmatch(parent, vcf, args)
register struct confargs *ca = args;
register struct cfdata *cf = vcf;
- if (ca->ca_bustype != BUS_PCCTWO ||
- strcmp(cf->cf_driver->cd_name, "clock")) {
+ if (strcmp(cf->cf_driver->cd_name, "clock")) {
return (0);
}
@@ -174,67 +173,50 @@ clockattach(parent, self, args)
struct confargs *ca = args;
struct clocksoftc *sc = (struct clocksoftc *)self;
- sc->sc_profih.ih_fn = clockintr;
- sc->sc_profih.ih_arg = 0;
- sc->sc_profih.ih_wantframe = 1;
- sc->sc_profih.ih_ipl = ca->ca_ipl;
-
- sc->sc_statih.ih_fn = statintr;
- sc->sc_statih.ih_arg = 0;
- sc->sc_statih.ih_wantframe = 1;
- sc->sc_statih.ih_ipl = ca->ca_ipl;
-
clockbus = ca->ca_bustype;
- prof_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
- stat_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
- pcctwointr_establish(PCC2V_TIMER1, &sc->sc_profih);
- pcctwointr_establish(PCC2V_TIMER2, &sc->sc_statih);
-
+
+ switch (clockbus) {
+#if NPCCTWO > 0
+ case BUS_PCCTWO:
+ sc->sc_profih.ih_fn = sbc_clockintr;
+ sc->sc_profih.ih_arg = 0;
+ sc->sc_profih.ih_wantframe = 1;
+ sc->sc_profih.ih_ipl = ca->ca_ipl;
+ prof_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
+ pcctwointr_establish(PCC2V_TIMER1, &sc->sc_profih);
+ mdfp.clock_init_func = &sbc_initclock;
+ printf(": VME1x7");
+ break;
+#endif /* NPCCTWO */
+#if NSYSCON > 0
+ case BUS_SYSCON:
+ sc->sc_profih.ih_fn = m188_clockintr;
+ sc->sc_profih.ih_arg = 0;
+ sc->sc_profih.ih_wantframe = 1;
+ sc->sc_profih.ih_ipl = ca->ca_ipl;
+ sysconintr_establish(SYSCV_TIMER1, &sc->sc_profih);
+ mdfp.clock_init_func = &m188_initclock;
+ printf(": VME188");
+ break;
+#endif /* NSYSCON */
+ }
printf("\n");
}
- /*
- * clockintr: ack intr and call hardclock
- */
-int
-clockintr(arg)
- void *arg;
-{
- sys_pcc2->pcc2_t1irq = prof_reset;
- hardclock(arg);
-#include "bugtty.h"
-#if NBUGTTY > 0
- bugtty_chkinput();
-#endif /* NBUGTTY */
- timerok = 1;
- return (1);
-}
-
-/*
- * Set up real-time clock; we don't have a statistics clock at
- * present.
- */
-cpu_initclocks()
+#if NPCCTWO > 0
+void
+sbc_initclock(void)
{
register int statint, minint;
+#ifdef DEBUG
+ printf("SBC clock init\n");
+#endif
if (1000000 % hz) {
printf("cannot get %d Hz clock; using 100 Hz\n", hz);
hz = 100;
tick = 1000000 / hz;
}
- if (stathz == 0)
- stathz = hz;
- if (1000000 % stathz) {
- printf("cannot get %d Hz statclock; using 100 Hz\n", stathz);
- stathz = 100;
- }
- profhz = stathz; /* always */
-
- statint = 1000000 / stathz;
- minint = statint / 2 + 100;
- while (statvar > minint)
- statvar >>= 1;
/* profclock */
sys_pcc2->pcc2_t1ctl = 0;
@@ -244,53 +226,25 @@ cpu_initclocks()
PCC2_TCTL_COVF;
sys_pcc2->pcc2_t1irq = prof_reset;
- /* statclock */
- sys_pcc2->pcc2_t2ctl = 0;
- sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(statint);
- sys_pcc2->pcc2_t2count = 0;
- sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC |
- PCC2_TCTL_COVF;
- sys_pcc2->pcc2_t2irq = stat_reset;
-
- statmin = statint - (statvar >> 1);
-}
-
-void
-setstatclockrate(newhz)
- int newhz;
-{
}
+/*
+ * clockintr: ack intr and call hardclock
+ */
int
-statintr(cap)
- void *cap;
+sbc_clockintr(arg)
+ void *arg;
{
- register u_long newint, r, var;
-
- sys_pcc2->pcc2_t2irq = stat_reset;
-
- statclock((struct clockframe *)cap);
-
- /*
- * Compute new randomized interval. The intervals are uniformly
- * distributed on [statint - statvar / 2, statint + statvar / 2],
- * and therefore have mean statint, giving a stathz frequency clock.
- */
- var = statvar;
- do {
- r = random() & (var - 1);
- } while (r == 0);
- newint = statmin + r;
-
- sys_pcc2->pcc2_t2ctl = 0;
- sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(newint);
- sys_pcc2->pcc2_t2count = 0; /* should I? */
- sys_pcc2->pcc2_t2irq = stat_reset;
- sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC;
-
- return (1);
+ sys_pcc2->pcc2_t1irq = prof_reset;
+ hardclock(arg);
+#include "bugtty.h"
+#if NBUGTTY > 0
+ bugtty_chkinput();
+#endif /* NBUGTTY */
+ timerok = 1;
+ return (1);
}
-
+#endif /* NPCCTWO */
delay(us)
register int us;
@@ -299,10 +253,11 @@ delay(us)
unsigned long st;
/*
* We use the vme system controller for the delay clock.
- * Do not go to the real timer until vme device is present
+ * Do not go to the real timer until vme device is present.
+ * Or, in the case of MVME188, not at all.
*/
- if (sys_vme2 == NULL) {
- c = 5 * us;
+ if (sys_vme2 == NULL || cputyp == CPU_188) {
+ c = 3 * us;
while (--c > 0);
return(0);
}
@@ -311,10 +266,93 @@ delay(us)
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);
+ return (0);
+}
+
+#if NSYSCON > 0
+int counter = 0;
+
+int
+m188_clockintr(arg)
+ void *arg;
+{
+ volatile int tmp;
+ /* acknowledge the timer interrupt */
+ /* clear the counter/timer output OP3 while we program the DART */
+ *((volatile int *) DART_OPCR) = 0x00;
+
+ /* do the stop counter/timer command */
+ tmp = *((volatile int *) DART_STOPC);
+
+ /* set counter/timer to counter mode, clock/16 */
+ *((volatile int *) DART_ACR) = 0x30;
+
+ *((volatile int *) DART_CTUR) = counter / 256; /* set counter MSB */
+ *((volatile int *) DART_CTLR) = counter % 256; /* set counter LSB */
+ *((volatile int *) DART_IVR) = SYSCV_TIMER1; /* set interrupt vec */
+
+ hardclock(arg);
+#include "bugtty.h"
+#if NBUGTTY > 0
+ bugtty_chkinput();
+#endif /* NBUGTTY */
+ /* give the start counter/timer command */
+ tmp = *((volatile int *) DART_STARTC);
+ *((volatile int *) DART_OPCR) = 0x04;
+ return (1);
}
+void
+m188_initclock(void)
+{
+ register int statint, minint;
+#ifdef DEBUG
+ printf("VME188 clock init\n");
+#endif
+ if (1000000 % hz) {
+ printf("cannot get %d Hz clock; using 100 Hz\n", hz);
+ hz = 100;
+ tick = 1000000 / hz;
+ }
+ m188_timer_init(tick);
+}
+void
+m188_timer_init(unsigned period)
+{
+ int imr;
+
+ /* make sure the counter range is proper. */
+ if ( period < 9 )
+ counter = 2;
+ else if ( period > 284421 )
+ counter = 65535;
+ else
+ counter = period / 4.34;
+#ifdef DEBUG
+ printf("tick == %d, period == %d\n", tick, period);
+ printf("timer will interrupt every %d usec\n", (int) (counter * 4.34));
+#endif
+ /* clear the counter/timer output OP3 while we program the DART */
+ *((volatile int *) DART_OPCR) = 0x00;
+
+ /* do the stop counter/timer command */
+ imr = *((volatile int *) DART_STOPC);
+
+ /* set counter/timer to counter mode, clock/16 */
+ *((volatile int *) DART_ACR) = 0x30;
+
+ *((volatile int *) DART_CTUR) = counter / 256; /* set counter MSB */
+ *((volatile int *) DART_CTLR) = counter % 256; /* set counter LSB */
+ *((volatile int *) DART_IVR) = SYSCV_TIMER1; /* set interrupt vec */
+ /* give the start counter/timer command */
+ /* (yes, this is supposed to be a read) */
+ imr = *((volatile int *) DART_STARTC);
+
+ /* set the counter/timer output OP3 */
+ *((volatile int *) DART_OPCR) = 0x04;
+}
+#endif /* NSYSCON */
diff --git a/sys/arch/mvme88k/dev/dart.c b/sys/arch/mvme88k/dev/dart.c
new file mode 100644
index 00000000000..f49afd5148e
--- /dev/null
+++ b/sys/arch/mvme88k/dev/dart.c
@@ -0,0 +1,1191 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/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 <sys/simplelock.h>
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+#include <machine/cpu_number.h>
+#include <machine/asm_macro.h> /* enable/disable interrupts */
+#include <dev/cons.h>
+#include <mvme88k/dev/sysconreg.h>
+#include <mvme88k/dev/dartreg.h>
+#include <sys/syslog.h>
+#include "dart.h"
+#include <machine/psl.h>
+#define spldart() splx(IPL_TTY)
+
+#if DDB
+ #include <machine/db_machdep.h> /* for details on entering kdb */
+extern unsigned char ddb_break_mode, ddb_break_char;
+#endif
+
+#if DEBUG
+ #define dprintf(stuff) /*printf stuff*/
+#else
+ #define dprintf(stuff)
+#endif
+
+struct dart_info {
+ struct tty *tty;
+ u_char dart_swflags;
+ struct simplelock t_lock;
+};
+
+struct dartsoftc {
+ struct device sc_dev;
+ struct evcnt sc_intrcnt;
+ union dartreg *dart_reg;
+ struct dart_info sc_dart[2];
+ struct intrhand sc_ih;
+ int sc_flags;
+ int sc_ipl;
+ int sc_vec;
+};
+
+int dartmatch __P((struct device *parent, void *self, void *aux));
+void dartattach __P((struct device *parent, struct device *self, void *aux));
+
+struct cfattach dart_ca = {
+ sizeof(struct dartsoftc), dartmatch, dartattach
+};
+
+struct cfdriver dart_cd = {
+ NULL, "dart", DV_TTY, 0
+};
+
+/* prototypes */
+int dartcnprobe __P((struct consdev *cp));
+int dartcninit __P((struct consdev *cp));
+int dartcngetc __P((dev_t dev));
+int dartcnputc __P((dev_t dev, char c));
+
+int dartopen __P((dev_t dev, int flag, int mode, struct proc *p));
+int dartclose __P((dev_t dev, int flag, int mode, struct proc *p));
+int dartread __P((dev_t dev, struct uio *uio, int flag));
+int dartwrite __P((dev_t dev, struct uio *uio, int flag));
+int dartioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p));
+int dartstop __P((struct tty *tp, int flag));
+int dartintr __P((struct dartsoftc *sc));
+void dartbreak __P((dev_t dev, int state));
+
+/*
+ * Lock strategy in that driver:
+ * Use the tp->t_lock used by chario stuff as a lock
+ * when modifying the chip's registers.
+ *
+ * Should be changed if driver crashes when powering
+ * two lines.
+ */
+
+#define DART_PORT(dev) minor(dev)
+#define dart_tty darttty
+struct dart_sv_reg dart_sv_reg;
+
+/* speed tables */
+int dart_speeds[] =
+{
+ 0, /* 0 baud, special HUP condition */
+ NOBAUD, /* 50 baud, not implemented */
+ BD75, /* 75 baud */
+ BD110, /* 110 baud */
+ BD134, /* 134.5 baud */
+ BD150, /* 150 baud */
+ NOBAUD, /* 200 baud, not implemented */
+ BD300, /* 300 baud */
+ BD600, /* 600 baud */
+ BD1200, /* 1200 baud */
+ BD1800, /* 1800 baud */
+ BD2400, /* 2400 baud */
+ BD4800, /* 4800 baud */
+ BD9600, /* 9600 baud */
+ BD19200, /* 19200 baud */
+ NOBAUD /* 38400 baud, not implemented */
+};
+
+struct tty * darttty(dev)
+dev_t dev;
+{
+ int port;
+ struct dartsoftc *sc;
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ port = DART_PORT(dev);
+ return sc->sc_dart[port].tty;
+}
+
+int
+dartmatch(parent, vcf, args)
+struct device *parent;
+void *vcf, *args;
+{
+ struct cfdata *cf = vcf;
+ struct confargs *ca = args;
+ union dartreg *addr;
+
+ /* Don't match if wrong cpu */
+ if (cputyp != CPU_188) return (0);
+ ca->ca_vaddr = ca->ca_paddr; /* 1:1 */
+ addr = (union dartreg *)ca->ca_vaddr;
+ if (badvaddr(addr, 2) <= 0) {
+ printf("==> syscon: failed address check.\n");
+ return (0);
+ }
+ return (1);
+}
+
+void
+dartattach(parent, self, aux)
+struct device *parent;
+struct device *self;
+void *aux;
+{
+ struct dartsoftc *sc = (struct dartsoftc *)self;
+ struct confargs *ca = aux;
+ int i;
+ union dartreg *addr; /* pointer to DUART regs */
+ union dart_pt_io *ptaddr; /* pointer to port regs */
+ int port; /* port index */
+
+ /* set up dual port memory and registers and init*/
+ sc->dart_reg = (union dartreg *)ca->ca_vaddr;
+ sc->sc_ipl = ca->ca_ipl;
+ ca->ca_vec = SYSCV_SCC; /* hard coded vector */
+ sc->sc_vec = ca->ca_vec;
+
+ addr = sc->dart_reg;
+
+ /* save standard initialization */
+ dart_sv_reg.sv_mr1[A_PORT] = PARDIS | RXRTS | CL8;
+ dart_sv_reg.sv_mr2[A_PORT] = /* TXCTS | */ SB1;
+ dart_sv_reg.sv_csr[A_PORT] = BD9600;
+ dart_sv_reg.sv_cr[A_PORT] = TXEN | RXEN;
+
+ dart_sv_reg.sv_mr1[B_PORT] = PARDIS | RXRTS | CL8;
+ dart_sv_reg.sv_mr2[B_PORT] = /* TXCTS | */ SB1;
+ dart_sv_reg.sv_csr[B_PORT] = BD9600;
+ dart_sv_reg.sv_cr[B_PORT] = TXEN | RXEN;
+
+ dart_sv_reg.sv_acr = BDSET2 | CCLK16 | IPDCDIB | IPDCDIA;
+
+ /* Start out with Tx and RX interrupts disabled */
+ /* Enable input port change interrupt */
+ dart_sv_reg.sv_imr = IIPCHG;
+
+ dprintf(("dartattach: resetting port A\n"));
+
+ /* reset port a */
+ addr->write.wr_cra = RXRESET | TXDIS | RXDIS;
+ DELAY_CR;
+ addr->write.wr_cra = TXRESET | TXDIS | RXDIS;
+ DELAY_CR;
+ addr->write.wr_cra = ERRRESET | TXDIS | RXDIS;
+ DELAY_CR;
+ addr->write.wr_cra = BRKINTRESET | TXDIS | RXDIS;
+ DELAY_CR;
+ addr->write.wr_cra = MRRESET | TXDIS | RXDIS;
+
+ dprintf(("dartattach: resetting port B\n"));
+
+ /* reset port b */
+ addr->write.wr_crb = RXRESET | TXDIS | RXDIS;
+ DELAY_CR;
+ addr->write.wr_crb = TXRESET | TXDIS | RXDIS;
+ DELAY_CR;
+ addr->write.wr_crb = ERRRESET | TXDIS | RXDIS;
+ DELAY_CR;
+ addr->write.wr_crb = BRKINTRESET | TXDIS | RXDIS;
+ DELAY_CR;
+ addr->write.wr_crb = MRRESET | TXDIS | RXDIS;
+ DELAY_CR;
+
+ /* initialize ports */
+ for (port = 0, ptaddr = (union dart_pt_io *)addr;
+ port < MAXPORTS;
+ port++, ptaddr++) {
+ dprintf(("dartattach: init port %c\n", 'A' + port));
+ ptaddr->write.wr_mr = dart_sv_reg.sv_mr1[port];
+ ptaddr->write.wr_mr = dart_sv_reg.sv_mr2[port];
+ ptaddr->write.wr_csr = dart_sv_reg.sv_csr[port];
+ ptaddr->write.wr_cr = dart_sv_reg.sv_cr [port];
+ }
+
+ dprintf(("dartattach: init common regs\n"));
+
+ /* initialize common register of a DUART */
+ addr->write.wr_oprset = OPDTRA | OPRTSA | OPDTRB | OPRTSB;
+
+ addr->write.wr_ctur = SLCTIM>>8;
+ addr->write.wr_ctlr = SLCTIM & 0xFF;
+ addr->write.wr_acr = dart_sv_reg.sv_acr;
+ addr->write.wr_imr = dart_sv_reg.sv_imr;
+ addr->write.wr_opcr = OPSET;
+ addr->write.wr_ivr = sc->sc_vec;
+
+ /* enable interrupts */
+ sc->sc_ih.ih_fn = dartintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_ipl = ca->ca_ipl;
+ sc->sc_ih.ih_wantframe = 0;
+
+ intr_establish(ca->ca_vec, &sc->sc_ih);
+ evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
+ printf("\n");
+}
+
+/*
+ * To be called at spltty - tty already locked.
+ */
+void
+dartstart(tp)
+struct tty *tp;
+{
+ dev_t dev;
+ struct dartsoftc *sc;
+ int s, cnt;
+ union dart_pt_io *ptaddr;
+ union dartreg *addr;
+ int port;
+ int c;
+
+ dev = tp->t_dev;
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+
+ if ((tp->t_state & TS_ISOPEN) == 0)
+ return;
+
+ addr = sc->dart_reg;
+ ptaddr = (union dart_pt_io *)addr + port;
+
+ if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+ goto out;
+
+ /*
+ if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
+ ttwakeup(tp);
+ }
+ */
+
+ if (tp->t_outq.c_cc != 0) {
+
+ tp->t_state |= TS_BUSY;
+
+ /* load transmitter until it is full */
+ while (ptaddr->read.rd_sr & TXRDY) {
+ c = getc(&tp->t_outq);
+
+ if (tp->t_flags & CS8 || c <= 0177) {
+
+ dprintf(("dartstart: writing char \"%c\" (0x%02x)\n",
+ c & 0xff, c % 0xff));
+ ptaddr->write.wr_tb = c & 0xff;
+
+ dprintf(("dartstart: enabling Tx int\n"));
+ if (port == A_PORT)
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr | ITXRDYA;
+ else
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr | ITXRDYB;
+ addr -> write.wr_imr = dart_sv_reg.sv_imr;
+ } else {
+ tp->t_state &= ~TS_BUSY;
+ dprintf(("dartxint: timing out char \"%c\" (0x%02x)\n",
+ c & 0xff, c % 0xff));
+ ttrstrt(tp);
+ tp->t_state |= TS_TIMEOUT;
+ }
+ }
+ }
+
+ out:
+ return;
+}
+
+/*
+ * To be called at spltty - tty already locked.
+ */
+int
+dartstop(tp, flag)
+struct tty *tp;
+int flag;
+{
+ int s;
+
+ if (tp->t_state & TS_BUSY) {
+ if ((tp->t_state & TS_TTSTOP) == 0)
+ tp->t_state |= TS_FLUSH;
+ }
+ return 0;
+}
+
+#define HANDLE_FLAG(_FLAG_, _PORT_, _AFLAG_, _BFLAG_) \
+ if (flags & (_FLAG_)) \
+ { newflags |= ((_PORT_) == A_PORT) ? (_AFLAG_) : (_BFLAG_); \
+ flags &= ~(_FLAG_); }
+
+#define HOW2STR(_OP_) \
+ ((_OP_) == DMGET) ? "GET" : \
+ (((_OP_) == DMSET) ? "FORCE" : \
+ ((((_OP_) == DMBIS) ? "SET" : \
+ (((((_OP_) == DMBIC) ? "CLR" : "???"))))))
+
+#define FLAGSTRING \
+ "\20\1LE\2DTR\3RTS\4ST\5SR\6CTS\7CAR\10RNG\11DSR\12BRK"
+
+/*
+ * To be called at spltty - tty already locked.
+ * Returns status of carrier.
+ */
+
+int
+dartmctl (dev, flags, how)
+dev_t dev;
+int flags;
+int how;
+{
+ union dartreg *addr;
+ int port;
+ unsigned int dcdstate;
+ int newflags = 0;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ if (port = DART_PORT(dev) > 1) {
+ return (ENODEV);
+ }
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ dart = &sc->sc_dart[port];
+ addr = sc->dart_reg;
+
+ /* special case: set or clear break */
+ if (flags & TIOCSBRK) {
+ dartbreak(port, 1);
+ flags &= ~TIOCSBRK;
+ }
+ if (flags & TIOCCBRK) {
+ dartbreak(port, 0);
+ flags &= ~TIOCCBRK;
+ }
+
+ HANDLE_FLAG(TIOCM_DTR, port, OPDTRA, OPDTRB);
+ HANDLE_FLAG(TIOCM_RTS, port, OPRTSA, OPRTSB);
+
+#if 0
+ if (flags) {
+ printf("dartmctl: currently only BRK, DTR and RTS supported\n");
+ printf("dartmctl: op=%s flags left = 0x%b\n",
+ HOW2STR(how), flags, FLAGSTRING);
+ panic("dartmctl");
+ }
+#endif
+ dprintf(("dartmctl: action=%s flags=0x%x\n",
+ HOW2STR(how), newflags));
+
+ switch (how) {
+ case DMSET:
+ addr->write.wr_oprset = newflags;
+ addr->write.wr_oprreset = ~newflags;
+ break;
+ case DMBIS:
+ addr->write.wr_oprset = newflags;
+ break;
+ case DMBIC:
+ addr->write.wr_oprreset = newflags;
+ break;
+ case DMGET:
+ panic("dartmctl: DMGET not supported (yet)\n");
+ break;
+ }
+
+ /* read DCD input */
+ /* input is inverted at port */
+ dcdstate = !(addr->read.rd_ip & ((port == A_PORT) ? IPDCDA : IPDCDB));
+
+ dprintf(("dartmctl: DCD is %s\n", dcdstate ? "up" : "down"));
+
+ return dcdstate;
+}
+
+/*
+ * To be called at spltty - tty already locked.
+ */
+void
+dartbreak(dev_t dev, int state)
+{
+ union dartreg *addr;
+ union dart_pt_io *ptaddr;
+ int port;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ dprintf(("dartbreak: break %s\n", (state == 1) ? "on" : "off"));
+
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ dart = &sc->sc_dart[port];
+ addr = sc->dart_reg;
+
+ ptaddr = (union dart_pt_io *) addr + port;
+
+ if (state == 1) {
+ /* the duart must be enabled with a dummy byte,
+ to prevent the transmitter empty interrupt */
+ ptaddr->write.wr_cr = BRKSTART|TXEN;
+ ptaddr->write.wr_tb = 0;
+ } else {
+ ptaddr->write.wr_cr = BRKSTOP; /* stop a break*/
+ }
+
+ return;
+}
+
+int dartioctl (dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ int error;
+ int port;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ dart = &sc->sc_dart[port];
+ tp = dart->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) dartmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
+ break;
+
+ case TIOCCDTR:
+ (void) dartmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
+ break;
+
+ case TIOCMSET:
+ (void) dartmctl(dev, *(int *) data, DMSET);
+ break;
+
+ case TIOCMBIS:
+ (void) dartmctl(dev, *(int *) data, DMBIS);
+ break;
+
+ case TIOCMBIC:
+ (void) dartmctl(dev, *(int *) data, DMBIC);
+ break;
+
+ case TIOCMGET:
+/* *(int *)data = dartmctl(dev, 0, DMGET);*/
+ break;
+ case TIOCGFLAGS:
+ *(int *)data = dart->dart_swflags;
+ break;
+ case TIOCSFLAGS:
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error != 0)
+ return(EPERM);
+
+ dart->dart_swflags = *(int *)data;
+ dart->dart_swflags &= /* only allow valid flags */
+ (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
+ break;
+ default:
+ return(ENOTTY);
+ }
+
+ return 0;
+}
+
+/*
+ * To be called at spltty - tty already locked.
+ */
+int
+dartparam(tp, t)
+struct tty *tp;
+struct termios *t;
+{
+ union dartreg *addr;
+ union dart_pt_io *ptaddr;
+ int flags;
+ int port;
+ int speeds;
+ unsigned char mr1, mr2;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ dev_t dev;
+
+ dprintf(("dartparam: setting param for dev %d\n", dev));
+
+ dev = tp->t_dev;
+ if (port = DART_PORT(dev) > 1) {
+ return (ENODEV);
+ }
+
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ dart = &sc->sc_dart[port];
+ addr = sc->dart_reg;
+ ptaddr = (union dart_pt_io *) addr + port;
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+
+ flags = tp->t_flags;
+
+ /* Reset to make global changes*/
+ /* disable Tx and Rx */
+ dprintf(("dartparam: disabling Tx and Rx int\n"));
+
+ if (port == A_PORT)
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr & ~(ITXRDYA | IRXRDYA);
+ else
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr & ~(ITXRDYB | IRXRDYB);
+ addr -> write.wr_imr = dart_sv_reg.sv_imr;
+
+ /* hang up on zero baud rate */
+ if (tp->t_ispeed == 0) {
+ dprintf(("dartparam: ispeed == 0 -> HUP\n"));
+ dartmctl(tp, HUPCL, DMSET);
+ return;
+ } else {
+ /* set baudrate */
+ speeds = dart_speeds[(unsigned char)tp->t_ispeed];
+ if (speeds == NOBAUD)
+ speeds = dart_sv_reg.sv_csr[port];
+ ptaddr->write.wr_csr = speeds;
+ dart_sv_reg.sv_csr[port] = speeds;
+ dprintf(("dartparam: baudrate set param = %d\n", speeds));
+ }
+
+ /* get saved mode registers and clear set up parameters */
+ mr1 = dart_sv_reg.sv_mr1[port];
+ mr1 &= ~(CLMASK | PARTYPEMASK | PARMODEMASK);
+
+ mr2 = dart_sv_reg.sv_mr2[port];
+ mr2 &= ~SBMASK;
+
+ /* set up character size */
+ if (flags & CS8) {
+ mr1 |= CL8;
+ dprintf(("dartparam: PASS8\n"));
+ } else if (tp->t_ispeed == B134) {
+ mr1 |= CL6;
+ dprintf(("dartparam: CS6\n"));
+ } else {
+ mr1 |= CL7;
+ dprintf(("dartparam: CS7\n"));
+ }
+
+ /* set up stop bits */
+ if (tp->t_ospeed == B110) {
+ mr2 |= SB2;
+ dprintf(("dartparam: two stop bits\n"));
+ } else {
+ mr2 |= SB1;
+ dprintf(("dartparam: one stop bit\n"));
+ }
+
+ /* set up parity */
+ if (((flags & PARENB) != PARENB) &&
+ (flags & PARENB)) {
+ mr1 |= PAREN;
+ if (flags & PARODD) {
+ mr1 |= ODDPAR;
+ dprintf(("dartparam: odd parity\n"));
+ } else {
+ mr1 |= EVENPAR;
+ dprintf(("dartparam: even parity\n"));
+ }
+ } else {
+ mr1 |= PARDIS;
+ dprintf(("dartparam: no parity\n"));
+ }
+
+ if ((dart_sv_reg.sv_mr1[port] != mr1)
+ || (dart_sv_reg.sv_mr2[port] != mr2)) {
+ /* write mode registers to duart */
+ ptaddr->write.wr_cr = MRRESET;
+ ptaddr->write.wr_mr = mr1;
+ ptaddr->write.wr_mr = mr2;
+
+ /* save changed mode registers */
+ dart_sv_reg.sv_mr1[port] = mr1;
+ dart_sv_reg.sv_mr2[port] = mr2;
+ }
+
+ /* enable transmitter? */
+ if (tp->t_state & TS_BUSY) {
+ dprintf(("dartparam: reenabling Tx int\n"));
+
+ if (port == A_PORT)
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr | ITXRDYA;
+ else
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr | ITXRDYB;
+ addr -> write.wr_imr = dart_sv_reg.sv_imr;
+ } else {
+ dprintf(("dartparam: not enabling Tx\n"));
+ }
+
+ /* re-enable the receiver */
+ dprintf(("dartparam: reenabling Rx int\n"));
+
+ DELAY_CR;
+ if (port == A_PORT)
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr | IRXRDYA;
+ else
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr | IRXRDYB;
+ addr -> write.wr_imr = dart_sv_reg.sv_imr;
+
+ return 0;
+}
+
+void
+dartmodemtrans(sc, ip, ipcr)
+ struct dartsoftc *sc;
+ unsigned int ip;
+ unsigned int ipcr;
+{
+ unsigned int dcdstate;
+ struct tty *tp;
+ int port;
+ struct dart_info *dart;
+
+ dprintf(("dartmodemtrans: ip=0x%x ipcr=0x%x\n",
+ ip, ipcr));
+
+ /* input is inverted at port!!! */
+ if (ipcr & IPCRDCDA) {
+ port = A_PORT;
+ dcdstate = !(ip & IPDCDA);
+ } else if (ipcr & IPCRDCDB) {
+ port = B_PORT;
+ dcdstate = !(ip & IPDCDB);
+ } else {
+ printf("dartmodemtrans: unknown transition:\n");
+ printf("dartmodemtrans: ip=0x%x ipcr=0x%x\n",
+ ip, ipcr);
+ panic("dartmodemtrans");
+ }
+ dart = &sc->sc_dart[port];
+ tp = dart->tty;
+
+ dprintf(("dartmodemtrans: tp=0x%x new DCD state: %s\n",
+ tp, dcdstate ? "UP" : "DOWN"));
+ (void) ttymodem(tp, dcdstate);
+}
+
+int dartopen (dev, flag, mode, p)
+dev_t dev;
+int flag;
+int mode;
+struct proc *p;
+{
+ int s, port;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ struct tty *tp;
+
+ if (port = DART_PORT(dev) > 1) {
+ return (ENODEV);
+ }
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ dart = &sc->sc_dart[port];
+ s = spldart();
+
+ if (dart->tty) {
+ tp = dart->tty;
+ } else {
+ tp = dart->tty = ttymalloc();
+ simple_lock_init(&dart->t_lock);
+ }
+
+ simple_lock(&dart->t_lock);
+ tp->t_oproc = dartstart;
+ tp->t_param = dartparam;
+ tp->t_dev = dev;
+
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = B9600;
+ dartparam(tp, &tp->t_termios);
+ if (port == 0) {
+ /* console is 8N1 */
+ tp->t_cflag = (CREAD | CS8 | HUPCL);
+ } else {
+ tp->t_cflag = TTYDEF_CFLAG;
+ }
+ ttsetwater(tp);
+ (void)dartmctl(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);
+ simple_unlock(&dart->t_lock);
+ 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;
+ simple_unlock(&dart->t_lock);
+ splx(s);
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+int dartclose (dev, flag, mode, p)
+dev_t dev;
+int flag;
+int mode;
+struct proc *p;
+{
+ int unit, channel;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ int s, port;
+
+ if (port = DART_PORT(dev) > 1) {
+ return (ENODEV);
+ }
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ dart = &sc->sc_dart[port];
+ tp = dart->tty;
+ (*linesw[tp->t_line].l_close)(tp, flag);
+
+ s = spldart();
+ ttyclose(tp);
+ splx(s);
+ return 0;
+}
+
+int dartread (dev, uio, flag)
+dev_t dev;
+struct uio *uio;
+int flag;
+{
+ int unit, port;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ if (port = DART_PORT(dev) > 1) {
+ return (ENODEV);
+ }
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ dart = &sc->sc_dart[port];
+ tp = dart->tty;
+
+ if (!tp)
+ return ENXIO;
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int dartwrite (dev, uio, flag)
+dev_t dev;
+struct uio *uio;
+int flag;
+{
+ int port;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ if (port = DART_PORT(dev) > 1) {
+ return (ENODEV);
+ }
+ sc = (struct dartsoftc *)dart_cd.cd_devs[0];
+ dart = &sc->sc_dart[port];
+
+ tp = dart->tty;
+ if (!tp)
+ return ENXIO;
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+void
+dartrint(sc, port)
+struct dartsoftc *sc;
+int port;
+{
+ union dartreg *addr;
+ union dart_pt_io *ptaddr;
+ struct tty *tp;
+ unsigned char data, sr;
+ struct dart_info *dart;
+
+ dart = &sc->sc_dart[port];
+ addr = sc->dart_reg;
+
+ /* read status reg */
+ ptaddr = (union dart_pt_io *) addr + port;
+
+ dprintf(("dartrint: Rx int dev %d\n", dev));
+
+ tp = dart->tty;
+
+ dprintf(("dartrint: ptaddr = 0x%08x from uart at 0x%08x\n",
+ ptaddr, addr));
+
+ while ((sr = ptaddr->read.rd_sr) & RXRDY) {
+ dprintf(("dartrint: sr = 0x%08x\n", sr));
+
+ data = ptaddr->read.rd_rb; /* read data and reset receiver */
+
+ dprintf(("dartrint: read char \"%c\" (0x%02x) tp = 0x%x\n",
+ data, data, tp));
+
+ if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0){
+ return;
+ }
+
+ if (sr & RBRK) {
+ dprintf(("dartrint: BREAK detected\n"));
+ /*
+ data = tp->t_breakc;
+ ttyinput(data, tp);
+ */
+ /* clear break state */
+ ptaddr->write.wr_cr = BRKINTRESET;
+ DELAY_CR;
+ ptaddr->write.wr_cr = ERRRESET;
+
+#if DDB_XXX
+ if (ddb_break_mode & DDB_ENTER_BREAK) {
+ dprintf(("dartrint: break detected - entering debugger\n"));
+ gimmeabreak();
+ }
+#endif
+ } else {
+ if (sr & (FRERR|PERR|ROVRN)) { /* errors */
+ if (sr & ROVRN)
+ printf("dart0: receiver overrun port %c\n", 'A' + port);
+ if (sr & FRERR)
+ printf("dart0: framing error port %c\n", 'A' + port);
+ if (sr & PERR)
+ printf("dart0: parity error port %c\n", 'A' + port);
+ dprintf(("dartrint: error received\n"));
+ /* clear error state */
+ ptaddr->write.wr_cr = ERRRESET;
+ } else {
+ /* no errors */
+#if DDB_XXX
+ if ((ddb_break_mode & DDB_ENTER_CHAR) && (ddb_break_char == data)) {
+ dprintf(("dartrint: ddb_break_char detected - entering debugger\n"));
+ gimmeabreak();
+ } else
+#endif
+ {
+ if (tp->t_ispeed == B134) /* CS6 */
+ data &= 077;
+#if 0 /* XXX ??? */
+ else if (tp->t_flags & (RAW|LITOUT|PASS8)) /*CS8*/
+ ;
+#endif
+ else
+ data &= 0177; /* CS7 */
+ ttyinput(data, tp);
+ }
+ }
+ }
+ }
+ dprintf(("dartrint: ready\n"));
+}
+
+void
+dartxint(sc, port)
+struct dartsoftc *sc;
+int port;
+{
+ struct tty *tp;
+ struct dart_info *dart;
+ union dartreg *addr;
+ dev_t dev;
+
+ dart = &sc->sc_dart[port];
+ addr = sc->dart_reg;
+
+ tp = dart->tty;
+
+ simple_lock(&dart->t_lock);
+
+ if ((tp->t_state & (TS_ISOPEN|TS_WOPEN))==0)
+ goto out;
+
+ if (tp->t_state & TS_FLUSH)
+ tp->t_state &= ~TS_FLUSH;
+
+ if (tp->t_state & TS_BUSY) {
+ tp->t_state &= ~TS_BUSY;
+ dprintf(("dartxint: starting output\n"));
+ dartstart(tp);
+ if (tp->t_state & TS_BUSY) {
+ dprintf(("dartxint: ready - Tx left enabled\n"));
+ simple_unlock(&dart->t_lock);
+ return;
+ }
+ }
+ out:
+
+ /* disable transmitter */
+ if (port == 0)
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr & ~ITXRDYA;
+ else
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr & ~ITXRDYB;
+
+ addr->write.wr_imr = dart_sv_reg.sv_imr;
+
+ simple_unlock(&dart->t_lock);
+
+ dprintf(("dartxint: ready - Tx disabled\n"));
+
+ return;
+}
+
+int
+dartintr(sc)
+struct dartsoftc *sc;
+{
+ unsigned char isr;
+ unsigned char sr;
+ int port;
+ union dartreg *addr;
+
+ /* read interrupt status register and mask with imr */
+ addr = sc->dart_reg;
+
+ isr = addr->read.rd_isr;
+ isr &= dart_sv_reg.sv_imr;
+
+ if (isr) { /* interrupt from this duart */
+ if (isr & IIPCHG) {
+ unsigned int ip = addr->read.rd_ip;
+ unsigned int ipcr = addr->read.rd_ipcr;
+ dartmodemtrans(sc, ip, ipcr);
+ return 0;
+ }
+
+ if (isr & (IRXRDYA | ITXRDYA))
+ port = 0;
+ else
+ if (isr & (IRXRDYB | ITXRDYB))
+ port = 1;
+ else {
+ printf("dartintr: spurious interrupt, isr 0x%08x\n", isr);
+ panic("dartintr");
+ }
+
+ dprintf(("dartintr: interrupt from port %d, isr 0x%08x\n",
+ port, isr));
+
+ if (isr & (IRXRDYA | IRXRDYB)) {
+ dprintf(("dartintr: Rx interrupt\n"));
+ dartrint(sc, port);
+ }
+ if (isr & (ITXRDYA | ITXRDYB)) {
+ dprintf(("dartintr: Tx interrupt\n"));
+ dartxint(sc, port);
+ }
+ if (((port == A_PORT) && (isr & IBRKA))
+ || ((port == B_PORT) && (isr & IBRKB))) {
+ union dart_pt_io *ptaddr =
+ (union dart_pt_io *)addr + port;
+
+ dprintf(("dartintr: clearing end of BREAK state\n"));
+ ptaddr->write.wr_cr = BRKINTRESET;
+ }
+ }
+ dprintf(("dartintr: ready\n"));
+ return 1;
+}
+
+/*
+ * Console interface routines. Currently only dev 0 or 1
+ * supported.
+ */
+
+int
+dartcnprobe(cp)
+struct consdev *cp;
+{
+ int maj;
+
+ if (cputyp != CPU_188){
+ cp->cn_pri = CN_DEAD;
+ return 0;
+ }
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == dartopen)
+ break;
+
+ cp->cn_dev = makedev(maj, 0);
+ cp->cn_pri = CN_NORMAL;
+ return (1);
+}
+
+int
+dartcninit(cp)
+struct consdev *cp;
+{
+ /* Nothing to do */
+}
+
+int
+dartcnputc(dev, c)
+dev_t dev;
+char c;
+{
+ union dartreg *addr;
+ union dart_pt_io *ptaddr;
+ m88k_psr_type psr;
+
+ addr = (union dartreg *) MVME188_DUART;
+
+ ptaddr = (union dart_pt_io *) addr + ((dev & 1) ? 1 : 0);
+
+ psr = disable_interrupts_return_psr();
+
+ /* Assume first port initialized if we get here. */
+ /* Assume the bug initializes the port */
+
+ /* inhibit interrupts on the chip */
+ addr->write.wr_imr = dart_sv_reg.sv_imr & ~ITXRDYA;
+ /* make sure transmitter is enabled */
+ DELAY_CR;
+ ptaddr->write.wr_cr = TXEN;
+
+ /* If the character is a line feed(\n) */
+ /* then follow it with carriage return (\r) */
+ for (;;) {
+ while (!(ptaddr->read.rd_sr & TXRDY))
+ ;
+ ptaddr->write.wr_tb = c;
+ if (c != '\n')
+ break;
+ c = '\r';
+ }
+
+ /* wait for transmitter to empty */
+ while (!(ptaddr->read.rd_sr & TXEMT))
+ ;
+
+ /* restore the previous state */
+ addr->write.wr_imr = dart_sv_reg.sv_imr;
+ DELAY_CR;
+ ptaddr->write.wr_cr = dart_sv_reg.sv_cr[0];
+
+ set_psr(psr);
+
+ return;
+}
+
+int
+dartcngetc(dev)
+dev_t dev;
+{
+ union dartreg *addr; /* pointer to DUART regs */
+ union dart_pt_io *ptaddr; /* pointer to port regs */
+ unsigned char sr; /* status reg of port a/b */
+ int c; /* received character */
+ m88k_psr_type psr;
+ char buf[] = "char x";
+
+ psr = disable_interrupts_return_psr();
+
+ addr = (union dartreg *) DART_BASE;
+ ptaddr = (union dart_pt_io *) addr + ((dev & 1) ? 1 : 0);
+
+ /* enable receiver */
+ ptaddr->write.wr_cr = RXEN;
+
+ do {
+ /* read status reg */
+ sr = ptaddr->read.rd_sr;
+
+ /* receiver interrupt handler*/
+ if (sr & RXRDY) {
+ /* read character from port */
+ c = ptaddr->read.rd_rb;
+
+ /* check break condition */
+ if (sr & RBRK) {
+ /* clear break state */
+ ptaddr->write.wr_cr = BRKINTRESET;
+ DELAY_CR;
+ ptaddr->write.wr_cr = ERRRESET;
+ set_psr(psr);
+ return c;
+ }
+
+ if (sr & (FRERR|PERR|ROVRN)) {
+ /* clear error state */
+ ptaddr->write.wr_cr = ERRRESET;
+ DELAY_CR;
+ ptaddr->write.wr_cr = BRKINTRESET;
+ } else {
+ buf[5] = (char) c;
+
+ set_psr(psr);
+ return (c & 0x7f);
+ }
+ }
+ } while (-1);
+
+ set_psr(psr);
+
+ return -1;
+}
diff --git a/sys/arch/mvme88k/dev/dartreg.h b/sys/arch/mvme88k/dev/dartreg.h
new file mode 100644
index 00000000000..10d996a172d
--- /dev/null
+++ b/sys/arch/mvme88k/dev/dartreg.h
@@ -0,0 +1,311 @@
+/*
+ * Something to put append a 'U' to a long constant if it's C so that
+ * it'll be unsigned in both ANSI and traditional.
+ */
+#if defined(ASSEMBLER)
+# define U(num) num
+#else
+# if defined(__STDC__)
+# define U(num) num ## U
+# else
+# define U(num) num/**/U
+# endif
+#endif
+
+/*********************** CONFIGURATION *******************************/
+#define MAXPORTS 2 /* max count of PORTS/DUART */
+
+/*
+ * The following define is for the utputc/utgetc Console routines
+ * which have to work without any configuration.
+ */
+#define MVME188_DUART U(0xFFF82000) /* M68692 DUART chip */
+
+/*********************** DEFINITIONS *********************************/
+#define MISSING 0 /* flag, missing a configured DUART */
+#define ON 1 /* flag for modem() */
+#define OFF 0 /* flag for modem() */
+#define A_PORT 0 /* flag for port a */
+#define B_PORT 1 /* flag for port b */
+
+/*********************** MACROS ***********************************/
+/*
+ * spl priority level should always be the same.
+ */
+#define SPLCLOCK spl6 /* set clock priority level */
+#define SPLM681 splhi /* set ut driver priority level */
+
+/* the access to the same command register must be delayed,
+ because the chip has some hardware problems in this case */
+#define DELAY_CR { volatile register i; for ( i=0; i<250; ++i ); }
+
+/*********************** MC68681 DEFINITIONS ************************/
+#define PORTOFFSET 0x10 /* offset for port b address space */
+
+/* mode register 1: MR1x operations */
+#define RXRTS 0x80 /* enable receiver RTS */
+#define PAREN 0x00 /* with parity */
+#define PARDIS 0x10 /* no parity */
+#define EVENPAR 0x00 /* even parity */
+#define ODDPAR 0x04 /* odd parity */
+#define CL5 0x00 /* 5 bits per char */
+#define CL6 0x01 /* 6 bits per char */
+#define CL7 0x02 /* 7 bits per char */
+#define CL8 0x03 /* 8 bits per char */
+#define PARMODEMASK 0x18 /* parity mode mask */
+#define PARTYPEMASK 0x04 /* parity type mask */
+#define CLMASK 0x03 /* character length mask */
+
+/* mode register 2: MR2x operations */
+#define TXRTS 0x20 /* enable transmitter RTS */
+#define TXCTS 0x10 /* enable transmitter CTS */
+#define SB2 0x0f /* 2 stop bits */
+#define SB1 0x07 /* 1 stop bit */
+#define SB1L5 0x00 /* 1 stop bit at 5 bits per character */
+
+#define SBMASK 0x0f /* stop bit mask */
+
+/* clock-select register: CSRx operations */
+#define NOBAUD -1 /* 50 and 200 baud are not possible */
+/* they are not in Baud register set 2 */
+#define BD75 0x00 /* 75 baud */
+#define BD110 0x11 /* 110 baud */
+#define BD134 0x22 /* 134.5 baud */
+#define BD150 0x33 /* 150 baud */
+#define BD300 0x44 /* 300 baud */
+#define BD600 0x55 /* 600 baud */
+#define BD1200 0x66 /* 1200 baud */
+#define BD1800 0xaa /* 1800 baud */
+#define BD2400 0x88 /* 2400 baud */
+#define BD4800 0x99 /* 4800 baud */
+#define BD9600 0xbb /* 9600 baud */
+#define BD19200 0xcc /* 19200 baud */
+
+#define DEFBAUD BD9600 /* default value if baudrate is not possible */
+
+
+/* channel command register: CRx operations */
+#define MRRESET 0x10 /* reset mr pointer to mr1 */
+#define RXRESET 0x20 /* reset receiver */
+#define TXRESET 0x30 /* reset transmitter */
+#define ERRRESET 0x40 /* reset error status */
+#define BRKINTRESET 0x50 /* reset channel's break interrupt */
+#define BRKSTART 0x60 /* start break */
+#define BRKSTOP 0x70 /* stop break */
+#define TXDIS 0x08 /* disable transmitter */
+#define TXEN 0x04 /* enable transmitter */
+#define RXDIS 0x02 /* disable receiver */
+#define RXEN 0x01 /* enable receiver */
+
+/* status register: SRx status */
+#define RBRK 0x80 /* received break */
+#define FRERR 0x40 /* frame error */
+#define PERR 0x20 /* parity error */
+#define ROVRN 0x10 /* receiver overrun error */
+#define TXEMT 0x08 /* transmitter empty */
+#define TXRDY 0x04 /* transmitter ready */
+#define FFULL 0x02 /* receiver FIFO full */
+#define RXRDY 0x01 /* receiver ready */
+
+/* output port configuration register: OPCR operations */
+#define OPSET 0x00 /* set all op lines to op function */
+#define OPSETTO 0x04 /* use OP3 for timer output */
+
+/* output port register: OP operations */
+#define OPDTRB 0x20 /* DTR line output b on the VME188, 181, 141 */
+#define OPDTRA 0x04 /* DTR line output a */
+#define OPRTSB 0x02 /* RTS line output b */
+#define OPRTSA 0x01 /* RTS line output a */
+
+/* auxiliary control register: ACR operations */
+#define BDSET1 0x00 /* baudrate generator set 1 */
+#define BDSET2 0x80 /* baudrate generator set 2 */
+#define CCLK1 0x60 /* timer clock: external rate. TA */
+#define CCLK16 0x30 /* counter clock: x1 clk divided by 16 */
+#define SLCTIM 0x7800/* timer count to get 60 Hz time slice (16.6ms ticks) */
+#define IPDCDIB 0x08 /* IP3 change == DCD input on port B */
+#define IPDCDIA 0x04 /* IP2 change == DCD input on port A */
+
+/* input port change register: IPCR operations */
+#define IPCRDCDB 0x80 /* IP3 change == DCD change on port B */
+#define IPCRDCDA 0x40 /* IP2 change == DCD change on port A */
+
+/* Defines for mvme335 */
+#define IPDCDB 0x20 /* DCD line input b */
+#define IPDCDA 0x10 /* DCD line input a */
+
+#define IPDSRB 0x08 /* DSR line input b */
+#define IPDSRA 0x04 /* DSR line input a */
+#define IPCTSB 0x02 /* CTS line input b */
+#define IPCTSA 0x01 /* CTS line input a */
+
+/* interrupt status and mask register: ISR status and IMR mask */
+#define IIPCHG 0x80 /* input port change */
+#define IBRKB 0x40 /* delta break b */
+#define IRXRDYB 0x20 /* receiver ready b */
+#define ITXRDYB 0x10 /* transmitter ready b */
+#define ITIMER 0x08 /* Enable timer interrupts. */
+#define IBRKA 0x04 /* delta break a */
+#define IRXRDYA 0x02 /* receiver ready a */
+#define ITXRDYA 0x01 /* transmitter ready a */
+
+/* interrupts from port a or b */
+#define AINTPORT ( IRXRDYA | ITXRDYA )
+#define BINTPORT ( IRXRDYB | ITXRDYB )
+
+/* HW write register index for ut_wr_regs[] */
+#define MR1A 0 /* mode register 1 a */
+#define CSRA 1 /* clock-select register a*/
+#define CRA 2 /* command register a */
+#define TBA 3 /* transmitter buffer a */
+#define ACR 4 /* auxialiary control register*/
+#define IMR 5 /* interrupt mask register */
+#define CTUR 6 /* counter/timer upper reg */
+#define CTLR 7 /* counter/timer lower reg */
+#define MR1B 8 /* mode register 1 b */
+#define CSRB 9 /* clock-select register b*/
+#define CRB 10 /* command register b */
+#define TBB 11 /* transmitter buffer b */
+#define IVR 12 /* interrupt vector register */
+#define OPCR 13 /* output port config reg */
+#define OPRSET 14 /* output port: bit set cmd */
+#define OPRRESET 15 /* output port: bit reset cmd */
+#define MR2A 16 /* mode register 2 a */
+#define MR2B 17 /* mode register 2 b */
+#define MAXREG 18 /* max count of registers */
+
+/*
+ * Structure of MC68681 hardware read registers.
+ */
+struct dart_rd_reg
+{
+ volatile unsigned int rd_mra; /* mode register a */
+ volatile unsigned int rd_sra; /* status register a*/
+ volatile unsigned int dummy5; /* do not access */
+ volatile unsigned int rd_rba; /* receiver buffer a */
+ volatile unsigned int rd_ipcr; /* input port change register */
+ volatile unsigned int rd_isr; /* interrupt status register */
+ volatile unsigned int rd_cur; /* current MSB of counter */
+ volatile unsigned int rd_clr; /* current LSB of counter */
+ volatile unsigned int rd_mrb; /* mode register b */
+ volatile unsigned int rd_srb; /* status register b*/
+ volatile unsigned int dummyxb; /* do not access */
+ volatile unsigned int rd_rbb; /* receiver buffer b */
+ volatile unsigned int rd_ivr; /* interrupt vector register */
+ volatile unsigned int rd_ip; /* input port (unlatched) */
+ volatile unsigned int rd_ctstart; /* start-counter command */
+ volatile unsigned int rd_ctstop; /* stop-counter command */
+};
+
+/*
+ * Structure of MC68681 hardware write registers.
+ */
+struct dart_wr_reg
+{
+ volatile unsigned int wr_mra; /* mode register a */
+ volatile unsigned int wr_csra; /* clock-select register a*/
+ volatile unsigned int wr_cra; /* command register a */
+ volatile unsigned int wr_tba; /* transmitter buffer a */
+ volatile unsigned int wr_acr; /* auxialiary control register*/
+ volatile unsigned int wr_imr; /* interrupt mask register */
+ volatile unsigned int wr_ctur; /* counter/timer upper reg */
+ volatile unsigned int wr_ctlr; /* counter/timer lower reg */
+ volatile unsigned int wr_mrb; /* mode register b */
+ volatile unsigned int wr_csrb; /* clock-select register b*/
+ volatile unsigned int wr_crb; /* command register b */
+ volatile unsigned int wr_tbb; /* transmitter buffer b */
+ volatile unsigned int wr_ivr; /* interrupt vector register */
+ volatile unsigned int wr_opcr; /* output port config reg */
+ volatile unsigned int wr_oprset; /* output port: bit set cmd */
+ volatile unsigned int wr_oprreset;/* output port: bit reset cmd */
+};
+
+union dartreg {
+ struct dart_rd_reg read; /* read registers */
+ struct dart_wr_reg write; /* write registers */
+};
+
+/*
+ * Structure of MC68681 hardware port dependent read registers.
+ */
+struct dart_prd_reg
+{
+ volatile unsigned int rd_mr; /* mode register */
+ volatile unsigned int rd_sr; /* status register */
+ volatile unsigned int dummy5;
+ volatile unsigned int rd_rb; /* receiver buffer */
+ volatile unsigned int dummy9;
+ volatile unsigned int dummy11;
+ volatile unsigned int dummy13;
+ volatile unsigned int dummy15;
+};
+
+/*
+ * Structure of MC68681 hardware port dependent write registers.
+ */
+struct dart_pwr_reg
+{
+ volatile unsigned int wr_mr; /* mode register */
+ volatile unsigned int wr_csr; /* clock-select register */
+ volatile unsigned int wr_cr; /* command register */
+ volatile unsigned int wr_tb; /* transmitter buffer */
+ volatile unsigned int dummy9;
+ volatile unsigned int dummy11;
+ volatile unsigned int dummy13;
+ volatile unsigned int dummy15;
+};
+
+union dart_pt_io {
+ struct dart_prd_reg read; /* read registers */
+ struct dart_pwr_reg write; /* write registers */
+};
+
+/*
+ * Structure of saved registers
+ */
+struct dart_sv_reg
+{
+ volatile unsigned char sv_mr1[MAXPORTS]; /* mode register 1 a */
+ volatile unsigned char sv_mr2[MAXPORTS]; /* mode register 2 a */
+ volatile unsigned char sv_csr[MAXPORTS]; /* clock-select register a*/
+ volatile unsigned char sv_cr[MAXPORTS]; /* command register a */
+ volatile unsigned char sv_acr; /* auxialiary control register*/
+ volatile unsigned char sv_imr; /* interrupt mask register */
+ volatile unsigned char sv_ivr; /* interrupt vector register */
+};
+
+/* defines for receiver and DCD scanner */
+#define M681CSCAN 2 /* clock ticks for character scan */
+#define M681_CHAR 01 /* character arrived flag (ut_work) */
+#define M681_ACT 02 /* character in buffer flag (ut_work) */
+#define M681_DCD 04 /* DCD wait flag (ut_work) */
+
+
+/********************* SPECIAL IOCTL COMMAND DEFINITIONS ******************/
+/* HWHAND ioctls same as in MVME331 driver */
+#define MSETHWHAND (('m'<<8)+20) /* set hardware handshake */
+#define MCLEARHWHAND (('m'<<8)+21) /* clear hardware handshake */
+#define MGETHWHAND (('m'<<8)+22) /* get hardware handshake mode */
+
+#define M681STATUS (('m'<<8)+40 ) /* get status of duarts */
+#define M681GETSTAT (('m'<<8)+42 ) /* get statistics */
+
+#ifdef STATISTICS
+struct dart_stat {
+ int open_cnt; /* count of open calls */
+ int intr_cnt; /* count of interrupts */
+ int tx_cnt; /* count of transmitted characters */
+ int rx_cnt; /* count of received characters */
+ int brk_cnt; /* count of break events */
+ int rovrn_cnt; /* count of overruns */
+ int frerr_cnt; /* count of frame errors */
+ int perr_cnt; /* count of parity errors */
+ int rxoff_cnt; /* count of received XOFF chars */
+ int rxon_cnt; /* count of received XON chars */
+ int txoff_cnt; /* count of transmitted XOFF chars */
+ int txon_cnt; /* count of transmitted XON chars */
+};
+#endif
+
+
+
diff --git a/sys/arch/mvme88k/dev/i82596.h b/sys/arch/mvme88k/dev/i82596.h
new file mode 100644
index 00000000000..15ce386304f
--- /dev/null
+++ b/sys/arch/mvme88k/dev/i82596.h
@@ -0,0 +1,310 @@
+/* $OpenBSD: i82596.h,v 1.1 1999/09/27 18:43:23 smurph Exp $ */
+
+/*-
+ * Copyright (c) 1995 Theo de Raadt
+ * Copyright (c) 1992, University of Vermont and State Agricultural College.
+ * Copyright (c) 1992, Garrett A. Wollman.
+ * 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
+ * Vermont and State Agricultural College and Garrett A. Wollman.
+ * and
+ * This product includes software developed under OpenBSD by
+ * Theo de Raadt for Willowglen Singapore.
+ * 4. Neither the name of the University nor the name of the author
+ * 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 UNIVERSITY OR 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.
+ */
+
+/*
+ * Intel 82596 Ethernet chip
+ * Register, bit, and structure definitions.
+ *
+ * Written by GAW with reference to the Clarkson Packet Driver code for this
+ * chip written by Russ Nelson and others.
+ *
+ * Sun support added by Charles D. Cranor, 25-Oct-94
+ *
+ * Remade for 82596 in 32 bit mode by Per Fogelstrom.
+ */
+
+struct ie_en_addr {
+ u_char data[6];
+};
+
+/*
+ * This is the master configuration block. It tells the hardware where all
+ * the rest of the stuff is.
+ */
+struct ie_sys_conf_ptr {
+ u_char mbz1[3]; /* must be zero */
+ u_char ie_bus_use; /* true if 8-bit only */
+ u_char mbz2[4]; /* must be zero */
+ u_int ie_iscp_ptr; /* physaddr of ISCP */
+};
+
+/*
+ * The tells the hardware where all the rest of the stuff is, too.
+ * FIXME: some of these should be re-commented after we figure out their
+ * REAL function.
+ */
+struct ie_int_sys_conf_ptr {
+ u_char mbz1[1]; /* must be zero */
+ u_char ie_busy; /* zeroed after init */
+ u_short ie_mbz2; /* must be zero */
+ u_int ie_base; /* 32-bit physaddr for all vars */
+};
+
+/*
+ * This FINALLY tells the hardware what to do and where to put it.
+ */
+struct ie_sys_ctl_block {
+ u_short ie_status; /* status word */
+ u_short ie_command; /* command word */
+ u_int ie_command_list; /* 32-pointer to command block list */
+ u_int ie_recv_list; /* 32-pointer to receive frame list */
+ u_int ie_err_crc; /* CRC errors */
+ u_int ie_err_align; /* Alignment errors */
+ u_int ie_err_resource; /* Resource errors */
+ u_int ie_err_overrun; /* Overrun errors */
+ u_int ie_err_coll; /* Receive packets collision errors */
+ u_int ie_err_short; /* Short frames recived errors */
+ u_short ie_off_timer; /* Bus Throttle OFF timer */
+ u_short ie_on_timer; /* Bus Throttle ON timer */
+};
+
+/* Command values */
+#define IE_RU_COMMAND 0x0070 /* mask for RU command */
+#define IE_RU_NOP 0 /* for completeness */
+#define IE_RU_START 0x0010 /* start receive unit command */
+#define IE_RU_ENABLE 0x0020 /* enable receiver command */
+#define IE_RU_DISABLE 0x0030 /* disable receiver command */
+#define IE_RU_ABORT 0x0040 /* abort current receive operation */
+
+#define IE_CU_COMMAND 0x0700 /* mask for CU command */
+#define IE_CU_NOP 0 /* included for completeness */
+#define IE_CU_START 0x0100 /* do-command command */
+#define IE_CU_RESUME 0x0200 /* resume a suspended cmd list */
+#define IE_CU_STOP 0x0300 /* SUSPEND was already taken */
+#define IE_CU_ABORT 0x0400 /* abort current command */
+#define IE_CU_THROTTLE 0x0500 /* load new throttle valuse */
+
+#define IE_ACK_COMMAND 0xf000 /* mask for ACK command */
+#define IE_ACK_CX 0x8000 /* ack IE_ST_DONE */
+#define IE_ACK_FR 0x4000 /* ack IE_ST_RECV */
+#define IE_ACK_CNA 0x2000 /* ack IE_ST_ALLDONE */
+#define IE_ACK_RNR 0x1000 /* ack IE_ST_RNR */
+
+#define IE_ACTION_COMMAND(x) (((x) & IE_CU_COMMAND) == IE_CU_START)
+ /* is this command an action command? */
+
+/* Status values */
+#define IE_ST_WHENCE 0xf000 /* mask for cause of interrupt */
+#define IE_ST_DONE 0x8000 /* command with I bit completed */
+#define IE_ST_RECV 0x4000 /* frame received */
+#define IE_ST_ALLDONE 0x2000 /* all commands completed */
+#define IE_ST_RNR 0x1000 /* receive not ready */
+
+#define IE_CU_STATUS 0x700 /* mask for command unit status */
+#define IE_CU_ACTIVE 0x200 /* command unit is active */
+#define IE_CU_SUSPEND 0x100 /* command unit is suspended */
+
+#define IE_RU_STATUS 0x70 /* mask for receiver unit status */
+#define IE_RU_SUSPEND 0x10 /* receiver is suspended */
+#define IE_RU_NOSPACE 0x20 /* receiver has no resources */
+#define IE_RU_READY 0x40 /* reveiver is ready */
+
+/*
+ * This is filled in partially by the chip, partially by us.
+ */
+struct ie_recv_frame_desc {
+ u_short ie_fd_status; /* status for this frame */
+ u_short ie_fd_last; /* end of frame list flag */
+ u_int ie_fd_next; /* 32-pointer to next RFD */
+ u_int ie_fd_buf_desc; /* 32-pointer to list of buffer desc's */
+ u_short ie_fd_actual; /* Actual count */
+ u_short ie_fd_size; /* Size */
+ struct ie_en_addr dest; /* destination ether */
+ struct ie_en_addr src; /* source ether */
+ u_short ie_length; /* 802 length/Ether type */
+ u_short mbz; /* must be zero */
+};
+
+#define IE_FD_LAST 0x8000 /* last rfd in list */
+#define IE_FD_SUSP 0x4000 /* suspend RU after receipt */
+
+#define IE_FD_COMPLETE 0x8000 /* frame is complete */
+#define IE_FD_BUSY 0x4000 /* frame is busy */
+#define IE_FD_OK 0x2000 /* frame is bad */
+#define IE_FD_RNR 0x0200 /* receiver out of resources here */
+#define IE_FD_FLEX 0x0008 /* use flexible buffer scheeme */
+
+/*
+ * linked list of buffers...
+ */
+struct ie_recv_buf_desc {
+ u_short ie_rbd_actual; /* status for this buffer */
+ u_short ie_mbz1;
+ u_int ie_rbd_next; /* pointer to next RBD */
+ u_int ie_rbd_buffer; /* pointer to buffer for this RBD */
+ u_short ie_rbd_length; /* length of the buffer */
+ u_short mbz; /* must be zero */
+};
+
+#define IE_RBD_LAST 0x8000 /* last buffer */
+#define IE_RBD_USED 0x4000 /* this buffer has data */
+/*
+ * All commands share this in common.
+ */
+struct ie_cmd_common {
+ u_short ie_cmd_status; /* status of this command */
+ u_short ie_cmd_cmd; /* command word */
+ u_int ie_cmd_link; /* link to next command */
+};
+
+#define IE_STAT_COMPL 0x8000 /* command is completed */
+#define IE_STAT_BUSY 0x4000 /* command is running now */
+#define IE_STAT_OK 0x2000 /* command completed successfully */
+#define IE_STAT_ABORT 0x1000 /* command was aborted */
+
+
+#define IE_CMD_NOP 0x0000 /* NOP */
+#define IE_CMD_IASETUP 0x0001 /* initial address setup */
+#define IE_CMD_CONFIG 0x0002 /* configure command */
+#define IE_CMD_MCAST 0x0003 /* multicast setup command */
+#define IE_CMD_XMIT 0x0004 /* transmit command */
+#define IE_CMD_TDR 0x0005 /* time-domain reflectometer command */
+#define IE_CMD_DUMP 0x0006 /* dump command */
+#define IE_CMD_DIAGNOSE 0x0007 /* diagnostics command */
+
+#define IE_CMD_LAST 0x8000 /* this is the last command in the list */
+#define IE_CMD_SUSPEND 0x4000 /* suspend CU after this command */
+#define IE_CMD_INTR 0x2000 /* post an interrupt after completion */
+#define IE_CMD_FLEX 0x0008 /* use flexible format */
+
+/*
+ * This is the command to transmit a frame.
+ */
+struct ie_xmit_cmd {
+ struct ie_cmd_common com; /* common part */
+#define ie_xmit_status com.ie_cmd_status
+
+ u_int ie_xmit_desc; /* pointer to buffer descriptor */
+ u_short ie_xmit_count; /* Tcb count field */
+ u_short ie_mbz1;
+ struct ie_en_addr ie_xmit_addr; /* destination address */
+
+ u_short ie_xmit_length; /* 802.3 length/Ether type field */
+};
+
+#define IE_XS_MAXCOLL 0x000f /* number of collisions during transmit */
+#define IE_XS_EXCMAX 0x0020 /* exceeded maximum number of collisions */
+#define IE_XS_SQE 0x0040 /* SQE positive */
+#define IE_XS_DEFERRED 0x0080 /* transmission deferred */
+#define IE_XS_UNDERRUN 0x0100 /* DMA underrun */
+#define IE_XS_LOSTCTS 0x0200 /* Lost CTS */
+#define IE_XS_NOCARRIER 0x0400 /* No Carrier */
+
+/*
+ * This is a buffer descriptor for a frame to be transmitted.
+ */
+
+struct ie_xmit_buf {
+ u_short ie_xmit_flags; /* see below */
+ u_short mbz1; /* Must be zero */
+ u_int ie_xmit_next; /* pointer to next desc. */
+ u_int ie_xmit_buf; /* pointer to the actual buffer */
+};
+
+#define IE_XMIT_LAST 0x8000 /* this TBD is the last one */
+/* The rest of the `flags' word is actually the length. */
+
+/*
+ * Multicast setup command.
+ */
+
+#define MAXMCAST 250 /* must fit in transmit buffer */
+
+struct ie_mcast_cmd {
+ struct ie_cmd_common com; /* common part */
+#define ie_mcast_status com.ie_cmd_status
+
+ u_short ie_mcast_bytes; /* size (in bytes) of multicast addresses */
+ struct ie_en_addr ie_mcast_addrs[MAXMCAST + 1]; /* space for them */
+};
+
+/*
+ * Time Domain Reflectometer command.
+ */
+
+struct ie_tdr_cmd {
+ struct ie_cmd_common com; /* common part */
+#define ie_tdr_status com.ie_cmd_status
+
+ u_short ie_tdr_time; /* error bits and time */
+ u_short ie_mbz1;
+};
+
+#define IE_TDR_SUCCESS 0x8000 /* TDR succeeded without error */
+#define IE_TDR_XCVR 0x4000 /* detected a transceiver problem */
+#define IE_TDR_OPEN 0x2000 /* detected an open */
+#define IE_TDR_SHORT 0x1000 /* TDR detected a short */
+#define IE_TDR_TIME 0x07ff /* mask for reflection time */
+
+/*
+ * Initial Address Setup command
+ */
+struct ie_iasetup_cmd {
+ struct ie_cmd_common com;
+#define ie_iasetup_status com.ie_cmd_status
+
+ struct ie_en_addr ie_address;
+
+ u_short ie_mbz1;
+};
+
+/*
+ * Configuration command
+ */
+struct ie_config_cmd {
+ struct ie_cmd_common com; /* common part */
+#define ie_config_status com.ie_cmd_status
+
+ u_char ie_config_count; /* byte count (0x0c) */
+ u_char ie_fifo; /* fifo (8) */
+ u_char ie_save_bad; /* save bad frames (0x40) */
+ u_char ie_addr_len; /* address length (0x2e) (AL-LOC==1) */
+ u_char ie_priority; /* priority and backoff (0x0) */
+ u_char ie_ifs; /* inter-frame spacing (0x60) */
+ u_char ie_slot_low; /* slot time, LSB (0x0) */
+ u_char ie_slot_high; /* slot time, MSN, and retries (0xf2) */
+ u_char ie_promisc; /* 1 if promiscuous, else 0 */
+ u_char ie_crs_cdt; /* CSMA/CD parameters (0x0) */
+ u_char ie_min_len; /* min frame length (0x40) */
+ u_char ie_junk; /* stuff for 82596 (0xff) */
+ u_char ie_dplx;
+ u_char ie_miabf;
+};
+
diff --git a/sys/arch/mvme88k/dev/if_ie.c b/sys/arch/mvme88k/dev/if_ie.c
index e8041125a1c..10ac1ef6b4b 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.5 1999/05/29 04:41:43 smurph Exp $ */
+/* $Id: if_ie.c,v 1.6 1999/09/27 18:43:24 smurph Exp $ */
/*-
* Copyright (c) 1998 Steve Murphree, Jr.
@@ -50,7 +50,7 @@
*/
/*
- * Intel 82586 Ethernet chip
+ * Intel 82596 Ethernet chip
* Register, bit, and structure definitions.
*
* Original StarLAN driver written by Garrett Wollman with reference to the
@@ -73,11 +73,11 @@ extern int etherlen;
/*
Mode of operation:
- We run the 82586 in a standard Ethernet mode. We keep NFRAMES
+ We run the 82596 in a standard Ethernet mode. We keep NFRAMES
received frame descriptors around for the receiver to use, and
NRXBUF associated receive buffer descriptors, both in a circular
list. Whenever a frame is received, we rotate both lists as
- necessary. (The 586 treats both lists as a simple queue.) We also
+ necessary. (The 596 treats both lists as a simple queue.) We also
keep a transmit command around so that packets can be sent off
quickly.
@@ -130,19 +130,13 @@ Mode of operation:
#include <vm/vm.h>
-/*
- * ugly byte-order hack for SUNs
- */
-
-#define SWAP(x) (x)
-
#include <machine/autoconf.h>
#include <machine/cpu.h>
#include <machine/pmap.h>
#include "pcctwo.h"
#include <mvme88k/dev/pcctworeg.h>
#include <mvme88k/dev/if_ie.h>
-#include <mvme88k/dev/i82586.h>
+#include <mvme88k/dev/i82596.h>
#include <machine/board.h>
static struct mbuf *last_not_for_us;
@@ -167,42 +161,7 @@ vm_map_t ie_map; /* for obio */
#define NTXBUF 2 /* number of transmit commands */
#define IE_TBUF_SIZE ETHER_MAX_LEN /* length of transmit buffer */
-
-/*
- * Ethernet status, per interface.
- *
- * hardware addresses/sizes to know (all KVA):
- * sc_iobase = base of chip's 24 bit address space
- * sc_maddr = base address of chip RAM as stored in ie_base of iscp
- * sc_msize = size of chip's RAM
- * sc_reg = address of card dependent registers
- *
- * the chip uses two types of pointers: 16 bit and 24 bit
- * 16 bit pointers are offsets from sc_maddr/ie_base
- * KVA(16 bit offset) = offset + sc_maddr
- * 24 bit pointers are offset from sc_iobase in KVA
- * KVA(24 bit address) = address + sc_iobase
- *
- * on the vme/multibus we have the page map to control where ram appears
- * in the address space. we choose to have RAM start at 0 in the
- * 24 bit address space. this means that sc_iobase == sc_maddr!
- * to get the phyiscal address of the board's RAM you must take the
- * top 12 bits of the physical address of the register address
- * and or in the 4 bits from the status word as bits 17-20 (remember that
- * the board ignores the chip's top 4 address lines).
- * For example:
- * if the register is @ 0xffe88000, then the top 12 bits are 0xffe00000.
- * to get the 4 bits from the the status word just do status & IEVME_HADDR.
- * suppose the value is "4". Then just shift it left 16 bits to get
- * it into bits 17-20 (e.g. 0x40000). Then or it to get the
- * address of RAM (in our example: 0xffe40000). see the attach routine!
- *
- * on the onboard ie interface the 24 bit address space is hardwired
- * to be 0xff000000 -> 0xffffffff of KVA. this means that sc_iobase
- * will be 0xff000000. sc_maddr will be where ever we allocate RAM
- * in KVA. note that since the SCP is at a fixed address it means
- * that we have to allocate a fixed KVA for the SCP.
- */
+#define CACHED_TO_PHYS(x) pmap_extract(pmap_kernel(), (vm_offset_t)(x))
struct ie_softc {
struct device sc_dev; /* device structure */
@@ -217,15 +176,13 @@ struct ie_softc {
struct arpcom sc_arpcom;/* system arpcom structure */
- void (*reset_586)(); /* card dependent reset function */
+ void (*reset_596)(); /* card dependent reset function */
void (*chan_attn)(); /* card dependent attn function */
- void (*run_586)(); /* card depenent "go on-line" function */
+ void (*run_596)(); /* card depenent "go on-line" function */
void (*memcopy) __P((const void *, void *, u_int));
/* card dependent memory copy function */
- void (*memzero) __P((void *, u_int));
+ void (*memzero) __P((void *, u_int));
/* card dependent memory zero function */
-
-
int want_mcsetup; /* mcsetup flag */
int promisc; /* are we in promisc mode? */
@@ -252,7 +209,7 @@ struct ie_softc {
volatile struct ie_recv_frame_desc *rframes[MXFRAMES];
volatile struct ie_recv_buf_desc *rbuffs[MXRXBUF];
volatile char *cbuffs[MXRXBUF];
- int rfhead, rftail, rbhead, rbtail;
+ int rfhead, rftail, rbhead, rbtail;
volatile struct ie_xmit_cmd *xmit_cmds[NTXBUF];
volatile struct ie_xmit_buf *xmit_buffs[NTXBUF];
@@ -270,7 +227,12 @@ 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 *));
@@ -316,16 +278,20 @@ struct cfdriver ie_cd = {
/*
* address generation macros
- * MK_24 = KVA -> 24 bit address in SUN byte order
- * MK_16 = KVA -> 16 bit address in INTEL byte order
- * ST_24 = store a 24 bit address in SUN byte order to INTEL byte order
*/
-#define MK_24(base, ptr) ((caddr_t)((u_long)ptr))
-#define MK_16(base, ptr) SWAP((u_short)( ((u_long)(ptr)) - ((u_long)(base)) ))
-#define ST_24(to, from) { \
- u_long fval = (u_long)(from); \
- u_char *t = (u_char *)&(to), *f = (u_char *)&fval; \
- t[0] = f[2]; t[1] = f[3]; /*t[2] = f[0]*/; t[3] = f[1]; \
+/* Make 32 bit value from swapped data (err counters access) */
+#define MK_32(ptr) ((((u_int)(ptr) >> 16) & 0xffff) | ((u_int)(ptr) << 16))
+
+#define MKADR_32(ptr) \
+ ((caddr_t)((((u_int)(ptr) >> 16) & 0xffff) | \
+ (((u_int)(ptr) << 16)) + UNCACHED_MEMORY_ADDR))
+
+/* *NOTE* The next macros also converts to physical address! */
+#define ASWAP(ptr) ((((u_int)(ptr) >> 16) & 0x1fff) | ((u_int)(ptr) << 16))
+
+#define SWT_32(to, from) { \
+ u_int *t = (u_int *)&to; \
+ *t = ((((u_int)from >> 16) & 0x1fff) | ((u_int)from << 16)); \
}
/*
* Here are a few useful functions. We could have done these as macros, but
@@ -337,8 +303,8 @@ ie_setup_config(cmd, promiscuous, manchester)
int promiscuous, manchester;
{
- cmd->ie_config_count = 0x0c;
- cmd->ie_fifo = 8;
+ cmd->ie_config_count = 0x0e;
+ cmd->ie_fifo = 0xc8;
cmd->ie_save_bad = 0x40;
cmd->ie_addr_len = 0x2e;
cmd->ie_priority = 0;
@@ -349,6 +315,8 @@ ie_setup_config(cmd, promiscuous, manchester)
cmd->ie_crs_cdt = 0;
cmd->ie_min_len = 64;
cmd->ie_junk = 0xff;
+ cmd->ie_dplx = 0x00;
+ cmd->ie_miabf = 0x3f;
}
static inline void
@@ -369,11 +337,11 @@ iematch(parent, vcf, args)
struct cfdata *cf = vcf;
struct confargs *ca = args;
int ret;
-
+
if ((ret = badvaddr(IIOV(ca->ca_vaddr), 1)) <=0){
- return(0);
+ return(0);
}
- return (1);
+ return(1);
}
/*
@@ -393,8 +361,8 @@ ie_obreset(sc)
ieo->portlow = a >> 16;
delay(1000);
- a = (u_long)pmap_extract(pmap_kernel(), (vm_offset_t)sc->scp) |
- IE_PORT_NEWSCPADDR;
+ a = (u_long)CACHED_TO_PHYS(sc->scp) |
+ IE_PORT_NEWSCPADDR;
ieo->porthigh = a & 0xffff;
t = 0; t = 1;
ieo->portlow = a >> 16;
@@ -433,23 +401,23 @@ ieattach(parent, self, aux)
volatile struct ieob *ieo;
vm_offset_t pa;
- sc->reset_586 = ie_obreset;
+ sc->reset_596 = ie_obreset;
sc->chan_attn = ie_obattend;
- sc->run_586 = ie_obrun;
+ sc->run_596 = ie_obrun;
sc->memcopy = bcopy;
sc->memzero = bzero;
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);
+ pa = CACHED_TO_PHYS(sc->sc_maddr);
if (pa == 0) panic("ie: pmap_extract");
sc->sc_iobase = (caddr_t)pa; /* iobase = paddr (24 bit) */
@@ -457,21 +425,15 @@ ieattach(parent, self, aux)
(sc->memzero)(sc->sc_maddr, sc->sc_msize);
sc->iscp = (volatile struct ie_int_sys_conf_ptr *)
- sc->sc_maddr; /* @ location zero */
+ sc->sc_maddr; /* @@ location zero */
sc->scb = (volatile struct ie_sys_ctl_block *)
roundup((int)sc->iscp + sizeof(struct ie_int_sys_conf_ptr), 16);
sc->scp = (struct ie_sys_conf_ptr *)
roundup((int)sc->scb + sizeof(struct ie_sys_ctl_block), 16);
/*printf("scpV %x iscpV %x scbV %x\n", sc->scp, sc->iscp, sc->scb);*/
- sc->scp->ie_bus_use = 0; /* 16-bit */
- ST_24(sc->scp->ie_iscp_ptr,
- pmap_extract(pmap_kernel(), (vm_offset_t)sc->iscp));
-
- /*printf("iscpV(%x) = iscpP(%x) -> scp.ptr@%x = val:%x\n",
- sc->iscp, pmap_extract(pmap_kernel(), (vm_offset_t)sc->iscp),
- &sc->scp->ie_iscp_ptr, sc->scp->ie_iscp_ptr);*/
-
+ sc->scp->ie_bus_use = 0x44;
+ SWT_32(sc->scp->ie_iscp_ptr, CACHED_TO_PHYS(sc->iscp));
/*
* rest of first page is unused (wasted!), rest of ram
* for buffers
@@ -632,23 +594,26 @@ ierint(sc)
sc->sc_arpcom.ac_if.if_ipackets++;
if (!--timesthru) {
sc->sc_arpcom.ac_if.if_ierrors +=
- SWAP(scb->ie_err_crc) +
- SWAP(scb->ie_err_align) +
- SWAP(scb->ie_err_resource) +
- SWAP(scb->ie_err_overrun);
- scb->ie_err_crc = scb->ie_err_align =
- scb->ie_err_resource = scb->ie_err_overrun =
- 0;
+ MK_32(scb->ie_err_crc) +
+ MK_32(scb->ie_err_align) +
+ MK_32(scb->ie_err_resource) +
+ MK_32(scb->ie_err_overrun) +
+ MK_32(scb->ie_err_coll) +
+ MK_32(scb->ie_err_short);
+ scb->ie_err_crc = 0;
+ scb->ie_err_align = 0;
+ scb->ie_err_resource = 0;
+ scb->ie_err_overrun = 0;
+ scb->ie_err_coll = 0;
+ scb->ie_err_short = 0;
timesthru = 1024;
}
ie_readframe(sc, i);
} else {
if ((status & IE_FD_RNR) != 0 &&
(scb->ie_status & IE_RU_READY) == 0) {
- sc->rframes[0]->ie_fd_buf_desc =
- MK_16(sc->sc_maddr, sc->rbuffs[0]);
- scb->ie_recv_list =
- MK_16(sc->sc_maddr, sc->rframes[0]);
+ sc->rframes[0]->ie_fd_buf_desc = ASWAP(sc->rbuffs[0]);
+ scb->ie_recv_list = ASWAP(sc->rframes[0]);
command_and_wait(sc, IE_RU_START, 0, 0);
}
break;
@@ -678,8 +643,7 @@ ietint(sc)
if (status & IE_STAT_OK) {
sc->sc_arpcom.ac_if.if_opackets++;
- sc->sc_arpcom.ac_if.if_collisions +=
- SWAP(status & IE_XS_MAXCOLL);
+ sc->sc_arpcom.ac_if.if_collisions += status & IE_XS_MAXCOLL;
} else if (status & IE_STAT_ABORT) {
printf("%s: send aborted\n", sc->sc_dev.dv_xname);
sc->sc_arpcom.ac_if.if_oerrors++;
@@ -834,7 +798,7 @@ check_eh(sc, eh, to_bpf)
/*
* Only accept unicast packets destined for us, or multicasts
* for groups that we belong to. For now, we assume that the
- * '586 will only return packets that we asked it for. This
+ * '596 will only return packets that we asked it for. This
* isn't strictly true (it uses hashing for the multicast
* filter), but it will do in this case, and we want to get out
* of here as quickly as possible.
@@ -858,8 +822,7 @@ ie_buflen(sc, head)
int head;
{
- return (SWAP(sc->rbuffs[head]->ie_rbd_actual)
- & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));
+ return (sc->rbuffs[head]->ie_rbd_actual & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));
}
static inline int
@@ -908,29 +871,32 @@ iexmit(sc)
if (sc->sc_arpcom.ac_if.if_bpf)
bpf_tap(sc->sc_arpcom.ac_if.if_bpf,
sc->xmit_cbuffs[sc->xctail],
- SWAP(sc->xmit_buffs[sc->xctail]->ie_xmit_flags));
+ sc->xmit_buffs[sc->xctail]->ie_xmit_flags);
#endif
-/*printf("iexmit base %x cmd %x bfd %x to %x\n",
+#if 0
+printf("iexmit base %x cmd %x bfd %x to %x\n",
sc->sc_maddr,
sc->xmit_cmds[sc->xctail],
sc->xmit_buffs[sc->xctail],
-sc->xmit_cbuffs[sc->xctail]);*/
+sc->xmit_cbuffs[sc->xctail]);
+#endif
sc->xmit_buffs[sc->xctail]->ie_xmit_flags |= IE_XMIT_LAST;
- sc->xmit_buffs[sc->xctail]->ie_xmit_next = SWAP(0xffff);
- ST_24(sc->xmit_buffs[sc->xctail]->ie_xmit_buf,
- MK_24(sc->sc_iobase, sc->xmit_cbuffs[sc->xctail]));
+ sc->xmit_buffs[sc->xctail]->ie_xmit_next = 0xffffffff;
+ SWT_32(sc->xmit_buffs[sc->xctail]->ie_xmit_buf,
+ sc->xmit_cbuffs[sc->xctail]);
- sc->xmit_cmds[sc->xctail]->com.ie_cmd_link = SWAP(0xffff);
+ sc->xmit_cmds[sc->xctail]->com.ie_cmd_link = 0xffffffff;
sc->xmit_cmds[sc->xctail]->com.ie_cmd_cmd =
- IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;
+ IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST | IE_CMD_FLEX;
- sc->xmit_cmds[sc->xctail]->ie_xmit_status = SWAP(0);
+ sc->xmit_cmds[sc->xctail]->ie_xmit_status = 0;
sc->xmit_cmds[sc->xctail]->ie_xmit_desc =
- MK_16(sc->sc_maddr, sc->xmit_buffs[sc->xctail]);
+ ASWAP(sc->xmit_buffs[sc->xctail]);
+ sc->xmit_cmds[sc->xctail]->ie_xmit_count = 0;
sc->scb->ie_command_list =
- MK_16(sc->sc_maddr, sc->xmit_cmds[sc->xctail]);
+ ASWAP(sc->xmit_cmds[sc->xctail]);
command_and_wait(sc, IE_CU_START, 0, 0);
sc->xmit_busy = 1;
@@ -1099,7 +1065,7 @@ ieget(sc, mp, ehp, to_bpf)
*/
nextbuf:
offset = 0;
- sc->rbuffs[head]->ie_rbd_actual = SWAP(0);
+ sc->rbuffs[head]->ie_rbd_actual = 0;
sc->rbuffs[head]->ie_rbd_length |= IE_RBD_LAST;
sc->rbhead = head = (head + 1) % sc->nrxbuf;
sc->rbuffs[sc->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
@@ -1138,7 +1104,8 @@ ie_readframe(sc, num)
status = sc->rframes[num]->ie_fd_status;
/* Immediately advance the RFD list, since we have copied ours now. */
- sc->rframes[num]->ie_fd_status = SWAP(0);
+ sc->rframes[num]->ie_fd_status = 0;
+ sc->rframes[num]->ie_fd_actual = 0;
sc->rframes[num]->ie_fd_last |= IE_FD_LAST;
sc->rframes[sc->rftail]->ie_fd_last &= ~IE_FD_LAST;
sc->rftail = (sc->rftail + 1) % sc->nframes;
@@ -1236,7 +1203,7 @@ ie_drop_packet_buffer(sc)
i = sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_LAST;
sc->rbuffs[sc->rbhead]->ie_rbd_length |= IE_RBD_LAST;
- sc->rbuffs[sc->rbhead]->ie_rbd_actual = SWAP(0);
+ sc->rbuffs[sc->rbhead]->ie_rbd_actual = 0;
sc->rbhead = (sc->rbhead + 1) % sc->nrxbuf;
sc->rbuffs[sc->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
sc->rbtail = (sc->rbtail + 1) % sc->nrxbuf;
@@ -1286,7 +1253,7 @@ iestart(ifp)
m_freem(m0);
len = max(len, ETHER_MIN_LEN);
- sc->xmit_buffs[sc->xchead]->ie_xmit_flags = SWAP(len);
+ sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len;
sc->xmit_free--;
sc->xchead = (sc->xchead + 1) % NTXBUF;
@@ -1317,12 +1284,13 @@ ie_setupram(sc)
scb = sc->scb;
(sc->memzero)((char *) scb, sizeof *scb);
+ scb->ie_off_timer = 10;
+ scb->ie_on_timer = 10000;
iscp->ie_busy = 1; /* ie_busy == char */
- iscp->ie_scb_offset = MK_16(sc->sc_maddr, scb);
- ST_24(iscp->ie_base, sc->sc_iobase);
+ SWT_32(iscp->ie_base, sc->scb);
- (sc->reset_586) (sc);
+ (sc->reset_596) (sc);
(sc->chan_attn) (sc);
delay(100); /* wait a while... */
@@ -1353,7 +1321,7 @@ iereset(sc)
ieioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, 0);
/*
- * Stop i82586 dead in its tracks.
+ * Stop i82596 dead in its tracks.
*/
if (command_and_wait(sc, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
printf("%s: abort commands timed out\n", sc->sc_dev.dv_xname);
@@ -1363,7 +1331,7 @@ iereset(sc)
#ifdef notdef
if (!check_ie_present(sc, sc->sc_maddr, sc->sc_msize))
- panic("ie disappeared!");
+ panic("ie disappeared!\n");
#endif
sc->sc_arpcom.ac_if.if_flags |= IFF_UP;
@@ -1462,12 +1430,12 @@ run_tdr(sc, cmd)
{
int result;
- cmd->com.ie_cmd_status = SWAP(0);
+ cmd->com.ie_cmd_status = 0;
cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
- cmd->com.ie_cmd_link = SWAP(0xffff);
+ cmd->com.ie_cmd_link = 0xffffffff;
- sc->scb->ie_command_list = MK_16(sc->sc_maddr, cmd);
- cmd->ie_tdr_time = SWAP(0);
+ sc->scb->ie_command_list = ASWAP(cmd);
+ cmd->ie_tdr_time = 0;
if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
!(cmd->com.ie_cmd_status & IE_STAT_OK))
@@ -1553,7 +1521,7 @@ setup_bufs(sc)
sc->nframes = n / r;
if (sc->nframes <= 0)
- panic("ie: bogus buffer calc");
+ panic("ie: bogus buffer calc\n");
if (sc->nframes > MXFRAMES)
sc->nframes = MXFRAMES;
@@ -1580,8 +1548,10 @@ setup_bufs(sc)
* step 1b: link together the recv frames and set EOL on last one
*/
for (n = 0; n < sc->nframes; n++) {
+ sc->rframes[n]->ie_fd_last = IE_FD_FLEX;
+ sc->rframes[n]->ie_fd_size = 0;
sc->rframes[n]->ie_fd_next =
- MK_16(sc->sc_maddr, sc->rframes[(n + 1) % sc->nframes]);
+ ASWAP(sc->rframes[(n + 1) % sc->nframes]);
}
sc->rframes[sc->nframes - 1]->ie_fd_last |= IE_FD_LAST;
@@ -1603,7 +1573,7 @@ setup_bufs(sc)
*/
for (n = 0; n < sc->nrxbuf; n++) {
sc->rbuffs[n]->ie_rbd_next =
- MK_16(sc->sc_maddr, sc->rbuffs[(n + 1) % sc->nrxbuf]);
+ ASWAP(sc->rbuffs[(n + 1) % sc->nrxbuf]);
}
sc->rbuffs[sc->nrxbuf - 1]->ie_rbd_length |= IE_RBD_LAST;
@@ -1625,8 +1595,8 @@ setup_bufs(sc)
for (n = 0; n < sc->nrxbuf; n++) {
sc->cbuffs[n] = (char *) ptr; /* XXX why char vs uchar? */
- sc->rbuffs[n]->ie_rbd_length = SWAP(IE_RBUF_SIZE);
- ST_24(sc->rbuffs[n]->ie_rbd_buffer, MK_24(sc->sc_iobase, ptr));
+ sc->rbuffs[n]->ie_rbd_length = IE_RBUF_SIZE;
+ SWT_32(sc->rbuffs[n]->ie_rbd_buffer, ptr);
ptr = Align(ptr + IE_RBUF_SIZE);
}
@@ -1641,8 +1611,8 @@ setup_bufs(sc)
sc->rbhead = 0;
sc->rbtail = sc->nrxbuf - 1;
- sc->scb->ie_recv_list = MK_16(sc->sc_maddr, sc->rframes[0]);
- sc->rframes[0]->ie_fd_buf_desc = MK_16(sc->sc_maddr, sc->rbuffs[0]);
+ sc->scb->ie_recv_list = ASWAP(sc->rframes[0]);
+ sc->rframes[0]->ie_fd_buf_desc = ASWAP(sc->rbuffs[0]);
#ifdef IEDEBUG
printf("IE_DEBUG: reserved %d bytes\n", ptr - sc->buf_area);
@@ -1660,17 +1630,16 @@ mc_setup(sc, ptr)
{
volatile struct ie_mcast_cmd *cmd = ptr;
- cmd->com.ie_cmd_status = SWAP(0);
+ cmd->com.ie_cmd_status = 0;
cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
- cmd->com.ie_cmd_link = SWAP(0xffff);
+ cmd->com.ie_cmd_link = 0xffffffff;
(sc->memcopy)((caddr_t)sc->mcast_addrs, (caddr_t)cmd->ie_mcast_addrs,
sc->mcast_count * sizeof *sc->mcast_addrs);
- cmd->ie_mcast_bytes =
- SWAP(sc->mcast_count * ETHER_ADDR_LEN); /* grrr... */
+ cmd->ie_mcast_bytes = sc->mcast_count * ETHER_ADDR_LEN; /* grrr... */
- sc->scb->ie_command_list = MK_16(sc->sc_maddr, cmd);
+ sc->scb->ie_command_list = ASWAP(cmd);
if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
!(cmd->com.ie_cmd_status & IE_STAT_OK)) {
printf("%s: multicast address setup command failed\n",
@@ -1699,15 +1668,28 @@ ieinit(sc)
ptr = sc->buf_area;
/*
+ * Set up bus throttles.
+ */
+
+ {
+ if (command_and_wait(sc, IE_CU_THROTTLE, 0, 0)) {
+ printf("%s: throttle set command failed\n",
+ sc->sc_dev.dv_xname);
+ return 0;
+ }
+ }
+
+ /*
* Send the configure command first.
*/
+
{
volatile struct ie_config_cmd *cmd = ptr;
- scb->ie_command_list = MK_16(sc->sc_maddr, cmd);
- cmd->com.ie_cmd_status = SWAP(0);
+ scb->ie_command_list = ASWAP(cmd);
+ cmd->com.ie_cmd_status = 0;
cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
- cmd->com.ie_cmd_link = SWAP(0xffff);
+ cmd->com.ie_cmd_link = 0xffffffff;
ie_setup_config(cmd, sc->promisc, 0);
@@ -1725,10 +1707,10 @@ ieinit(sc)
{
volatile struct ie_iasetup_cmd *cmd = ptr;
- scb->ie_command_list = MK_16(sc->sc_maddr, cmd);
- cmd->com.ie_cmd_status = SWAP(0);
+ scb->ie_command_list = ASWAP(cmd);
+ cmd->com.ie_cmd_status = 0;
cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
- cmd->com.ie_cmd_link = SWAP(0xffff);
+ cmd->com.ie_cmd_link = 0xffffffff;
(sc->memcopy)(sc->sc_arpcom.ac_enaddr,
(caddr_t)&cmd->ie_address, sizeof cmd->ie_address);
@@ -1758,13 +1740,13 @@ ieinit(sc)
sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels that we are here */
- sc->scb->ie_recv_list = MK_16(sc->sc_maddr, sc->rframes[0]);
+ sc->scb->ie_recv_list = ASWAP(sc->rframes[0]);
command_and_wait(sc, IE_RU_START, 0, 0);
ie_ack(sc, IE_ST_WHENCE);
- if (sc->run_586)
- (sc->run_586)(sc);
+ if (sc->run_596)
+ (sc->run_596)(sc);
return 0;
}
@@ -1909,3 +1891,4 @@ print_rbd(rbd)
rbd->mbz);
}
#endif
+
diff --git a/sys/arch/mvme88k/dev/if_ie.h b/sys/arch/mvme88k/dev/if_ie.h
index 42b1a0edae0..183e81e8fda 100644
--- a/sys/arch/mvme88k/dev/if_ie.h
+++ b/sys/arch/mvme88k/dev/if_ie.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ie.h,v 1.2 1998/12/15 05:52:30 smurph Exp $ */
+/* $OpenBSD: if_ie.h,v 1.3 1999/09/27 18:43:24 smurph Exp $ */
/* Copyright (c) 1998 Steve Murphree, Jr.
* Copyright (c) 1995 Theo de Raadt
@@ -50,8 +50,8 @@
* generic:
* the generic stuff of the ie chip is all done with data structures
* that live in the chip's memory address space. the chip expects
- * its main data structure (the sys conf ptr -- SCP) to be at a fixed
- * address in its 24 bit space: 0xfffff4
+ * its main data structure (the sys conf ptr -- SCP) to be at a
+ * address loaded into the chip at init.
*
* the SCP points to another structure called the ISCP.
* the ISCP points to another structure called the SCB.
@@ -69,14 +69,6 @@
*
* to get data from the chip you program it to interrupt...
*
- *
- * sun issues:
- *
- * there are 3 kinds of sun "ie" interfaces:
- * 1 - a VME/multibus card
- * 2 - an on-board interface (sun3's, sun-4/100's, and sun-4/200's)
- * 3 - another VME board called the 3E
- *
* the VME boards lives in vme16 space. only 16 and 8 bit accesses
* are allowed, so functions that copy data must be aware of this.
*
@@ -86,37 +78,6 @@
* that means that any buffer pointers you give the chip must be
* swapped to intel format. yuck.
*
- * VME/multibus interface:
- * for the multibus interface the board ignores the top 4 bits
- * of the chip address. the multibus interface seems to have its
- * own MMU like page map (without protections or valid bits, etc).
- * there are 256 pages of physical memory on the board (each page
- * is 1024 bytes). there are 1024 slots in the page map. so,
- * a 1024 byte page takes up 10 bits of address for the offset,
- * and if there are 1024 slots in the page that is another 10 bits
- * of the address. that makes a 20 bit address, and as stated
- * earlier the board ignores the top 4 bits, so that accounts
- * for all 24 bits of address.
- *
- * note that the last entry of the page map maps the top of the
- * 24 bit address space and that the SCP is supposed to be at
- * 0xfffff4 (taking into account allignment). so,
- * for multibus, that entry in the page map has to be used for the SCP.
- *
- * the page map effects BOTH how the ie chip sees the
- * memory, and how the host sees it.
- *
- * the page map is part of the "register" area of the board
- *
- * on-board interface:
- *
- * <fill in useful info later>
- *
- *
- * VME3E interface:
- *
- * <fill in useful info later>
- *
*/
/*
@@ -190,3 +151,4 @@ struct ieob {
/*
* not supported (yet?)
*/
+
diff --git a/sys/arch/mvme88k/dev/nvram.c b/sys/arch/mvme88k/dev/nvram.c
index e231f8ef7ca..94576ccfad5 100644
--- a/sys/arch/mvme88k/dev/nvram.c
+++ b/sys/arch/mvme88k/dev/nvram.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nvram.c,v 1.4 1999/04/11 03:26:27 smurph Exp $ */
+/* $OpenBSD: nvram.c,v 1.5 1999/09/27 18:43:24 smurph Exp $ */
/*
* Copyright (c) 1995 Theo de Raadt
@@ -47,13 +47,12 @@
#include <mvme88k/dev/nvramreg.h>
#include <mvme88k/dev/pcctworeg.h>
-
struct nvramsoftc {
struct device sc_dev;
- void * sc_paddr;
- void * sc_vaddr;
- int sc_len;
- struct clockreg *sc_regs;
+ void * sc_paddr;
+ void * sc_vaddr;
+ int sc_len;
+ void * sc_regs;
};
void nvramattach __P((struct device *, struct device *, void *));
@@ -76,6 +75,7 @@ nvrammatch(parent, vcf, args)
struct cfdata *cf = vcf;
struct confargs *ca = args;
struct bugrtc rtc;
+ ca->ca_vaddr = ca->ca_paddr; /* map 1:1 */
/*X*/ if (ca->ca_vaddr == (void *)-1)
/*X*/ return (1);
@@ -109,7 +109,11 @@ nvramattach(parent, self, args)
sc->sc_paddr = ca->ca_paddr;
sc->sc_vaddr = ca->ca_vaddr;
- sc->sc_len = MK48T08_SIZE;
+ if (cputyp == CPU_188) {
+ sc->sc_len = MK48T02_SIZE;
+ } else {
+ sc->sc_len = MK48T08_SIZE;
+ }
/*X*/ if (sc->sc_vaddr == (void *)-1)
/*X*/ sc->sc_vaddr = mapiodev((void *)sc->sc_paddr,
@@ -117,8 +121,12 @@ nvramattach(parent, self, args)
/*X*/ if (sc->sc_vaddr == NULL)
/*X*/ panic("failed to map!");
- sc->sc_regs = (struct clockreg *)(sc->sc_vaddr + sc->sc_len -
- sizeof(struct clockreg));
+ if (cputyp != CPU_188) {
+ sc->sc_regs = (void *)(sc->sc_vaddr + sc->sc_len -
+ sizeof(struct clockreg));
+ } else {
+ sc->sc_regs = (void *)(sc->sc_vaddr + M188_NVRAM_TOD_OFF);
+ }
printf(": MK48T0%d len %d\n", sc->sc_len / 1024, sc->sc_len);
}
@@ -257,12 +265,12 @@ timetochip(c)
/*
* Set up the system's time, given a `reasonable' time value.
*/
+
void
inittodr(base)
time_t base;
{
struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0];
- register struct clockreg *cl = sc->sc_regs;
int sec, min, hour, day, mon, year;
int badbase = 0, waszero = base == 0;
@@ -277,16 +285,32 @@ inittodr(base)
base = 21*SECYR + 186*SECDAY + SECDAY/2;
badbase = 1;
}
- cl->cl_csr |= CLK_READ; /* enable read (stop time) */
- sec = cl->cl_sec;
- min = cl->cl_min;
- hour = cl->cl_hour;
- day = cl->cl_mday;
- mon = cl->cl_month;
- year = cl->cl_year;
- cl->cl_csr &= ~CLK_READ; /* time wears on */
+ if (cputyp != CPU_188) {
+ register struct clockreg *cl = (struct clockreg *)sc->sc_regs;
+ cl->cl_csr |= CLK_READ; /* enable read (stop time) */
+ sec = cl->cl_sec;
+ min = cl->cl_min;
+ hour = cl->cl_hour;
+ day = cl->cl_mday;
+ mon = cl->cl_month;
+ year = cl->cl_year;
+ cl->cl_csr &= ~CLK_READ; /* time wears on */
+ } else { /* CPU_188 */
+ register struct m188_clockreg *cl = (struct m188_clockreg *)sc->sc_regs;
+ cl->cl_csr |= CLK_READ; /* enable read (stop time) */
+ sec = cl->cl_sec & 0xff;
+ min = cl->cl_min & 0xff;
+ hour = cl->cl_hour & 0xff;
+ day = cl->cl_mday & 0xff;
+ mon = cl->cl_month & 0xff;
+ year = cl->cl_year & 0xff;
+ cl->cl_csr &= ~CLK_READ; /* time wears on */
+ }
if ((time.tv_sec = chiptotime(sec, min, hour, day, mon, year)) == 0) {
- printf("WARNING: bad date in nvram");
+ printf("WARNING: bad date in nvram\n");
+ printf("day = %d, mon = %d, year = %d, hour = %d, min = %d, sec = %d",
+ FROMBCD(day), FROMBCD(mon), FROMBCD(year) + YEAR0,
+ FROMBCD(hour), FROMBCD(min), FROMBCD(sec));
/*
* Believe the time in the file system for lack of
* anything better, resetting the clock.
@@ -316,21 +340,38 @@ inittodr(base)
void resettodr()
{
struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0];
- register struct clockreg *cl = sc->sc_regs;
- struct chiptime c;
-
- if (!time.tv_sec || cl == NULL)
- return;
- timetochip(&c);
- cl->cl_csr |= CLK_WRITE; /* enable write */
- cl->cl_sec = c.sec;
- cl->cl_min = c.min;
- cl->cl_hour = c.hour;
- cl->cl_wday = c.wday;
- cl->cl_mday = c.day;
- cl->cl_month = c.mon;
- cl->cl_year = c.year;
- cl->cl_csr &= ~CLK_WRITE; /* load them up */
+ struct chiptime c;
+ if (cputyp != CPU_188) {
+ register struct clockreg *cl = (struct clockreg *)sc->sc_regs;
+
+ if (!time.tv_sec || cl == NULL)
+ return;
+ timetochip(&c);
+ cl->cl_csr |= CLK_WRITE; /* enable write */
+ cl->cl_sec = c.sec;
+ cl->cl_min = c.min;
+ cl->cl_hour = c.hour;
+ cl->cl_wday = c.wday;
+ cl->cl_mday = c.day;
+ cl->cl_month = c.mon;
+ cl->cl_year = c.year;
+ cl->cl_csr &= ~CLK_WRITE; /* load them up */
+ } else { /* CPU_188 */
+ register struct m188_clockreg *cl = (struct m188_clockreg *)sc->sc_regs;
+
+ if (!time.tv_sec || cl == NULL)
+ return;
+ timetochip(&c);
+ cl->cl_csr |= CLK_WRITE; /* enable write */
+ cl->cl_sec = c.sec;
+ cl->cl_min = c.min;
+ cl->cl_hour = c.hour;
+ cl->cl_wday = c.wday;
+ cl->cl_mday = c.day;
+ cl->cl_month = c.mon;
+ cl->cl_year = c.year;
+ cl->cl_csr &= ~CLK_WRITE; /* load them up */
+ }
}
/*ARGSUSED*/
@@ -351,7 +392,6 @@ nvramclose(dev, flag, mode)
dev_t dev;
int flag, mode;
{
-
return (0);
}
diff --git a/sys/arch/mvme88k/dev/nvramreg.h b/sys/arch/mvme88k/dev/nvramreg.h
index 67de360c02e..365fd5fa880 100644
--- a/sys/arch/mvme88k/dev/nvramreg.h
+++ b/sys/arch/mvme88k/dev/nvramreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nvramreg.h,v 1.2 1998/12/15 05:52:30 smurph Exp $ */
+/* $OpenBSD: nvramreg.h,v 1.3 1999/09/27 18:43:24 smurph Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -74,11 +74,23 @@ struct clockreg {
volatile u_char cl_year; /* year (0..99; BCD) */
};
+struct m188_clockreg {
+ volatile u_long cl_csr; /* control register */
+ volatile u_long cl_sec; /* seconds (0..59; BCD) */
+ volatile u_long cl_min; /* minutes (0..59; BCD) */
+ volatile u_long cl_hour; /* hour (0..23; BCD) */
+ volatile u_long cl_wday; /* weekday (1..7) */
+ volatile u_long cl_mday; /* day in month (1..31; BCD) */
+ volatile u_long cl_month; /* month (1..12; BCD) */
+ volatile u_long cl_year; /* year (0..99; BCD) */
+};
+
/* bits in cl_csr */
#define CLK_WRITE 0x80 /* want to write */
#define CLK_READ 0x40 /* want to read (freeze clock) */
struct clockreg *clockreg;
+struct m188_clockreg *m188_clockreg;
/*
* Motorola chose the year `1900' as their base count.
@@ -87,7 +99,8 @@ struct clockreg *clockreg;
#define YEAR0 00
#define NVRAMSIZE 0x8000
-#define NVRAM_TOD_OFF 0x1ff8 /* offset of tod in NVRAM space */
+#define SBC_NVRAM_TOD_OFF 0x1FF8 /* offset of tod in NVRAM space */
+#define M188_NVRAM_TOD_OFF 0x1FE0 /* offset of tod in NVRAM space */
#define MK48T02_SIZE 2*1024
#define MK48T08_SIZE 8*1024
diff --git a/sys/arch/mvme88k/dev/pcctwo.c b/sys/arch/mvme88k/dev/pcctwo.c
index 415c8aae3b4..d39ee04bc89 100644
--- a/sys/arch/mvme88k/dev/pcctwo.c
+++ b/sys/arch/mvme88k/dev/pcctwo.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pcctwo.c,v 1.6 1999/05/29 04:41:44 smurph Exp $ */
+/* $OpenBSD: pcctwo.c,v 1.7 1999/09/27 18:43:24 smurph Exp $ */
/*
* Copyright (c) 1995 Theo de Raadt
@@ -87,13 +87,19 @@ pcctwomatch(parent, vcf, args)
struct pcctworeg *pcc2;
/* Bomb if wrong cpu */
- if (!(cputyp == CPU_187 || cputyp == CPU_188)){
- printf("==> pcctwo: wrong CPU type %x.\n", cputyp);
- return (0);
- }
-
- pcc2 = (struct pcctworeg *)(IIOV(ca->ca_paddr) + PCC2_PCC2CHIP_OFF);
- if (badvaddr(pcc2, 4) <= 0){
+ switch (cputyp) {
+ case CPU_187:
+ pcc2 = (struct pcctworeg *)(IIOV(ca->ca_paddr) + PCC2_PCC2CHIP_OFF);
+ break;
+ case CPU_197: /* pcctwo is a child of buswitch XXX smurph */
+ pcc2 = (struct pcctworeg *)(IIOV(ca->ca_paddr));
+ break;
+ default:
+ /* Bomb if wrong cpu */
+ return (0);
+ }
+
+ if (badvaddr(pcc2, 4) <= 0){
printf("==> pcctwo: failed address check.\n");
return (0);
}
@@ -170,7 +176,14 @@ pcctwoattach(parent, self, args)
*/
sc->sc_paddr = ca->ca_paddr;
sc->sc_vaddr = (void *)IIOV(sc->sc_paddr);
- sc->sc_pcc2 = (struct pcctworeg *)(sc->sc_vaddr + PCC2_PCC2CHIP_OFF);
+ switch (cputyp) {
+ case CPU_187:
+ sc->sc_pcc2 = (struct pcctworeg *)(sc->sc_vaddr + PCC2_PCC2CHIP_OFF);
+ break;
+ case CPU_197: /* pcctwo is a child of buswitch XXX smurph */
+ sc->sc_pcc2 = (struct pcctworeg *)sc->sc_vaddr;
+ break;
+ }
sys_pcc2 = sc->sc_pcc2;
printf(": rev %d\n", sc->sc_pcc2->pcc2_chiprev);
@@ -183,12 +196,6 @@ pcctwoattach(parent, self, args)
*/
pcc2intr_ipl = (u_char *)&(sc->sc_pcc2->pcc2_ipl);
pcc2intr_mask = (u_char *)&(sc->sc_pcc2->pcc2_mask);
-
-#ifdef MVME187
- printf("setting interrupt ack vectors.\n");
- setupiackvectors();
-#endif /* MVME187 */
-
config_search(pcctwo_scan, self, args);
}
diff --git a/sys/arch/mvme88k/dev/sclock.c b/sys/arch/mvme88k/dev/sclock.c
new file mode 100644
index 00000000000..fcc0ea7a398
--- /dev/null
+++ b/sys/arch/mvme88k/dev/sclock.c
@@ -0,0 +1,412 @@
+/* $OpenBSD: sclock.c,v 1.1 1999/09/27 18:43:25 smurph Exp $ */
+/*
+ * Copyright (c) 1999 Steve Murphree, Jr.
+ *
+ * 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 under OpenBSD by
+ * Theo de Raadt for Willowglen Singapore.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1995 Nivas Madhur
+ * Copyright (c) 1994 Gordon W. Ross
+ * Copyright (c) 1993 Adam Glass
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Statistics clock driver.
+ */
+
+#include <sys/param.h>
+#include <sys/simplelock.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#ifdef GPROF
+#include <sys/gmon.h>
+#endif
+
+#include <machine/psl.h>
+#include <machine/autoconf.h>
+#include <machine/bugio.h>
+#include <machine/cpu.h>
+#include "pcctwo.h"
+#if NPCCTWO > 0
+#include <mvme88k/dev/pcctworeg.h>
+#endif
+#include "syscon.h"
+#if NSYSCON > 0
+#include <mvme88k/dev/sysconreg.h>
+#endif
+#include <mvme88k/dev/vme.h>
+
+extern struct vme2reg *sys_vme2;
+struct simplelock cio_lock;
+/*
+ * Statistics clock interval and variance, in usec. Variance must be a
+ * power of two. Since this gives us an even number, not an odd number,
+ * we discard one case and compensate. That is, a variance of 4096 would
+ * give us offsets in [0..4095]. Instead, we take offsets in [1..4095].
+ * This is symmetric about the point 2048, or statvar/2, and thus averages
+ * to that value (assuming uniform random numbers).
+ */
+int statvar = 8192;
+int statmin; /* statclock interval - 1/2*variance */
+
+static int sclockmatch __P((struct device *, void *, void *));
+static void sclockattach __P((struct device *, struct device *, void *));
+
+void sbc_initstatclock __P((void));
+void m188_initstatclock __P((void));
+void m188_cio_init __P((unsigned));
+void write_cio __P((unsigned, unsigned));
+
+struct sclocksoftc {
+ struct device sc_dev;
+ struct intrhand sc_statih;
+};
+
+struct cfattach sclock_ca = {
+ sizeof(struct sclocksoftc), sclockmatch, sclockattach
+};
+
+struct cfdriver sclock_cd = {
+ NULL, "sclock", DV_DULL, 0
+};
+
+int sbc_statintr __P((void *));
+int m188_statintr __P((void *));
+
+int sclockbus;
+u_char stat_reset;
+
+/*
+ * Every machine needs, but doesn't have to have, a statistics clock.
+ * For this platform, this file manages it, no matter what form it takes.
+ */
+int
+sclockmatch(parent, vcf, args)
+ struct device *parent;
+ void *vcf, *args;
+{
+ register struct confargs *ca = args;
+ register struct cfdata *cf = vcf;
+
+ if (strcmp(cf->cf_driver->cd_name, "sclock")) {
+ return (0);
+ }
+
+ /*
+ * clock has to be at ipl 5
+ * We return the ipl here so that the parent can print
+ * a message if it is different from what ioconf.c says.
+ */
+ ca->ca_ipl = IPL_CLOCK;
+ /* set size to 0 - see pcctwo.c:match for details */
+ ca->ca_len = 0;
+ return (1);
+}
+
+void
+sclockattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ struct confargs *ca = args;
+ struct sclocksoftc *sc = (struct sclocksoftc *)self;
+
+ sclockbus = ca->ca_bustype;
+
+ switch (sclockbus) {
+#if NPCCTWO > 0
+ case BUS_PCCTWO:
+ sc->sc_statih.ih_fn = sbc_statintr;
+ sc->sc_statih.ih_arg = 0;
+ sc->sc_statih.ih_wantframe = 1;
+ sc->sc_statih.ih_ipl = ca->ca_ipl;
+ stat_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
+ pcctwointr_establish(PCC2V_TIMER2, &sc->sc_statih);
+ mdfp.statclock_init_func = &sbc_initstatclock;
+ printf(": VME1x7");
+ break;
+#endif /* NPCCTWO */
+#if NSYSCON > 0
+ case BUS_SYSCON:
+ sc->sc_statih.ih_fn = m188_statintr;
+ sc->sc_statih.ih_arg = 0;
+ sc->sc_statih.ih_wantframe = 1;
+ sc->sc_statih.ih_ipl = ca->ca_ipl;
+ sysconintr_establish(SYSCV_TIMER2, &sc->sc_statih);
+ mdfp.statclock_init_func = &m188_initstatclock;
+ printf(": VME188");
+ break;
+#endif /* NSYSCON */
+ }
+ printf("\n");
+}
+
+#if NPCCTWO > 0
+void
+sbc_initstatclock(void)
+{
+ register int statint, minint;
+
+#ifdef DEBUG
+ printf("SBC statclock init\n");
+#endif
+ if (stathz == 0)
+ stathz = hz;
+ if (1000000 % stathz) {
+ printf("cannot get %d Hz statclock; using 100 Hz\n", stathz);
+ stathz = 100;
+ }
+ profhz = stathz; /* always */
+
+ statint = 1000000 / stathz;
+ minint = statint / 2 + 100;
+ while (statvar > minint)
+ statvar >>= 1;
+
+ /* statclock */
+ sys_pcc2->pcc2_t2ctl = 0;
+ sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(statint);
+ sys_pcc2->pcc2_t2count = 0;
+ sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC |
+ PCC2_TCTL_COVF;
+ sys_pcc2->pcc2_t2irq = stat_reset;
+
+ statmin = statint - (statvar >> 1);
+}
+
+int
+sbc_statintr(cap)
+ void *cap;
+{
+ register u_long newint, r, var;
+
+ sys_pcc2->pcc2_t2irq = stat_reset;
+
+ statclock((struct clockframe *)cap);
+
+ /*
+ * Compute new randomized interval. The intervals are uniformly
+ * distributed on [statint - statvar / 2, statint + statvar / 2],
+ * and therefore have mean statint, giving a stathz frequency clock.
+ */
+ var = statvar;
+ do {
+ r = random() & (var - 1);
+ } while (r == 0);
+ newint = statmin + r;
+
+ sys_pcc2->pcc2_t2ctl = 0;
+ sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(newint);
+ sys_pcc2->pcc2_t2count = 0; /* should I? */
+ sys_pcc2->pcc2_t2irq = stat_reset;
+ sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC;
+ return (1);
+}
+#endif /* NPCCTWO */
+
+#if NSYSCON > 0
+#define CIO_LOCK simple_lock(&cio_lock)
+#define CIO_UNLOCK simple_unlock(&cio_lock)
+
+int
+m188_statintr(cap)
+ void *cap;
+{
+ register u_long newint, r, var;
+
+ CIO_LOCK;
+ statclock((struct clockframe *)cap);
+ write_cio(CIO_CSR1, CIO_GCB|CIO_CIP); /* Ack the interrupt */
+
+ /*
+ * Compute new randomized interval. The intervals are uniformly
+ * distributed on [statint - statvar / 2, statint + statvar / 2],
+ * and therefore have mean statint, giving a stathz frequency clock.
+ */
+ var = statvar;
+ do {
+ r = random() & (var - 1);
+ } while (r == 0);
+ newint = statmin + r;
+/* printf("newint = %d, 0x%x\n", newint, newint);*/
+ write_cio(CIO_CT1MSB, (newint & 0xFF00) >> 8); /* Load time constant CTC #1 */
+ write_cio(CIO_CT1LSB, newint & 0xFF);
+ /* force a trigger event */
+ write_cio(CIO_CSR1, CIO_GCB|CIO_TCB|CIO_IE); /* Start CTC #1 running */
+ CIO_UNLOCK;
+ return (1);
+}
+
+void
+m188_initstatclock(void)
+{
+ register int statint, minint;
+
+#ifdef DEBUG
+ printf("VME188 clock init\n");
+#endif
+ simple_lock_init(&cio_lock);
+ if (stathz == 0)
+ stathz = hz;
+ if (1000000 % stathz) {
+ printf("cannot get %d Hz statclock; using 100 Hz\n", stathz);
+ stathz = 100;
+ }
+ profhz = stathz; /* always */
+
+ statint = 1000000 / stathz;
+ minint = statint / 2 + 100;
+ while (statvar > minint)
+ statvar >>= 1;
+ m188_cio_init(statint);
+ statmin = statint - (statvar >> 1);
+}
+
+#define CIO_CNTRL 0xFFF8300C
+
+/* Write CIO register */
+void
+write_cio(reg, val)
+unsigned reg,val;
+{
+ int s, i;
+ s = splclock();
+ /* Select register */
+ *((volatile int *) CIO_CTRL) = (reg & 0xFF);
+ /* Write the value */
+ *((volatile int *) CIO_CTRL) = (val & 0xFF);
+ splx(s);
+}
+
+/* Read CIO register */
+static u_char
+read_cio(reg)
+unsigned reg;
+{
+ int c;
+ int s, i;
+ volatile int *port = (volatile int *)CIO_CNTRL;
+
+ s = splclock();
+ /* Select register */
+ *port = (char)(reg&0xFF);
+ /* Delay for a short time to allow 8536 to settle */
+ for(i=0;i<100;i++);
+ /* read the value */
+ c = *port;
+ splx(s);
+ return((u_char)c&0xFF);
+}
+
+/*
+ * Initialize the CTC (8536)
+ * Only the counter/timers are used - the IO ports are un-comitted.
+ * Channels 1 and 2 are linked to provide a /32 counter.
+ */
+
+void
+m188_cio_init(unsigned p)
+{
+ long i;
+ short period;
+
+ CIO_LOCK;
+
+ period = p & 0xFFFF;
+
+ /* Initialize 8536 CTC */
+ /* Start by forcing chip into known state */
+ (void) read_cio(CIO_MICR);
+
+ write_cio(CIO_MICR, CIO_MICR_RESET); /* Reset the CTC */
+ for(i=0;i < 1000L; i++) /* Loop to delay */
+ ;
+ /* Clear reset and start init seq. */
+ write_cio(CIO_MICR, 0x00);
+
+ /* Wait for chip to come ready */
+ while((read_cio(CIO_MICR)) != (char) CIO_MICR_RJA)
+ ;
+ /* init Z8036 */
+ write_cio(CIO_MICR, CIO_MICR_MIE | CIO_MICR_NV | CIO_MICR_RJA | CIO_MICR_DLC);
+ write_cio(CIO_CTMS1, CIO_CTMS_CSC); /* Continuous count */
+ write_cio(CIO_PDCB, 0xFF); /* set port B to input */
+
+ write_cio(CIO_CT1MSB, (period & 0xFF00) >> 8); /* Load time constant CTC #1 */
+ write_cio(CIO_CT1LSB, period & 0xFF);
+
+ /* enable counter 1 */
+ write_cio(CIO_MCCR, CIO_MCCR_CT1E | CIO_MCCR_PBE);
+
+ /* enable interrupts and start */
+ /*write_cio(CIO_IVR, SYSCV_TIMER2);*/
+ write_cio(CIO_CSR1, CIO_GCB|CIO_TCB|CIO_IE); /* Start CTC #1 running */
+
+ CIO_UNLOCK;
+}
+
+#endif /* NSYSCON */
diff --git a/sys/arch/mvme88k/dev/syscon.c b/sys/arch/mvme88k/dev/syscon.c
new file mode 100644
index 00000000000..9971544faa8
--- /dev/null
+++ b/sys/arch/mvme88k/dev/syscon.c
@@ -0,0 +1,250 @@
+
+/* $OpenBSD: syscon.c,v 1.1 1999/09/27 18:43:25 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 under OpenBSD by
+ * Theo de Raadt for Willowglen Singapore.
+ * 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.
+ */
+
+/*
+ * VME188 SYSCON
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/tty.h>
+#include <sys/uio.h>
+#include <sys/callout.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/fcntl.h>
+#include <sys/device.h>
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+#include <machine/frame.h>
+#include <machine/board.h>
+#include <dev/cons.h>
+
+#include <mvme88k/dev/sysconreg.h>
+
+struct sysconreg syscon_reg = {
+ (volatile unsigned int*)IEN0_REG,(volatile unsigned int*)IEN1_REG,
+ (volatile unsigned int*)IEN2_REG,(volatile unsigned int*)IEN3_REG,
+ (volatile unsigned int*)IENALL_REG,(volatile unsigned int*)IST_REG,
+ (volatile unsigned int*)SETSWI_REG,(volatile unsigned int*)CLRSWI_REG,
+ (volatile unsigned int*)ISTATE_REG,(volatile unsigned int*)CLRINT_REG,
+ (volatile unsigned char*)GLB0,(volatile unsigned char*)GLB1,
+ (volatile unsigned char*)GLB2,(volatile unsigned char*)GLB3,
+ (volatile unsigned int*)UCSR_REG,(volatile unsigned int*)GLBRES_REG,
+ (volatile unsigned int*)CCSR_REG,(volatile unsigned int*)ERROR_REG,
+ (volatile unsigned int*)PCNFA_REG,(volatile unsigned int*)PCNFB_REG,
+ (volatile unsigned int*)EXTAD_REG,(volatile unsigned int*)EXTAM_REG,
+ (volatile unsigned int*)WHOAMI_REG,(volatile unsigned int*)WMAD_REG,
+ (volatile unsigned int*)RMAD_REG,(volatile unsigned int*)WVAD_REG,
+ (volatile unsigned int*)RVAD_REG,(volatile unsigned int*)CIO_PORTC,
+ (volatile unsigned int*)CIO_PORTB,(volatile unsigned int*)CIO_PORTA,
+ (volatile unsigned int*)CIO_CTRL
+ };
+
+struct sysconsoftc {
+ struct device sc_dev;
+ void *sc_vaddr; /* Utility I/O space */
+ void *sc_paddr;
+ struct sysconreg *sc_syscon; /* the actual registers */
+ struct intrhand sc_abih; /* `abort' switch */
+ struct intrhand sc_acih; /* `ac fial' */
+ struct intrhand sc_sfih; /* `sys fial' */
+};
+
+void sysconattach __P((struct device *, struct device *, void *));
+int sysconmatch __P((struct device *, void *, void *));
+void setupiackvectors __P((void));
+int sysconabort __P((struct frame *frame));
+int sysconacfail __P((struct frame *frame));
+int sysconsysfail __P((struct frame *frame));
+
+struct cfattach syscon_ca = {
+ sizeof(struct sysconsoftc), sysconmatch, sysconattach
+};
+
+struct cfdriver syscon_cd = {
+ NULL, "syscon", DV_DULL, 0
+};
+
+struct sysconreg *sys_syscon = NULL;
+
+int
+sysconmatch(parent, vcf, args)
+ struct device *parent;
+ void *vcf, *args;
+{
+ struct cfdata *cf = vcf;
+ struct confargs *ca = args;
+ struct sysconreg *syscon;
+
+ /* Don't match if wrong cpu */
+ if (cputyp != CPU_188) return (0);
+ /* Uh, MVME188 better have on of these, so always match if it
+ * is a MVME188... */
+ syscon = (struct sysconreg *)(IIOV(ca->ca_paddr));
+ return (1);
+}
+
+int
+syscon_print(args, bus)
+ void *args;
+ const char *bus;
+{
+ struct confargs *ca = args;
+
+ if (ca->ca_offset != -1)
+ printf(" offset 0x%x", ca->ca_offset);
+ if (ca->ca_ipl > 0)
+ printf(" ipl %d", ca->ca_ipl);
+ return (UNCONF);
+}
+
+int
+syscon_scan(parent, child, args)
+ struct device *parent;
+ void *child, *args;
+{
+ struct cfdata *cf = child;
+ struct sysconsoftc *sc = (struct sysconsoftc *)parent;
+ struct confargs *ca = args;
+ struct confargs oca;
+
+ if (parent->dv_cfdata->cf_driver->cd_indirect) {
+ printf(" indirect devices not supported\n");
+ return 0;
+ }
+
+ bzero(&oca, sizeof oca);
+ oca.ca_offset = cf->cf_loc[0];
+ oca.ca_ipl = cf->cf_loc[1];
+ if ((oca.ca_offset != (void*)-1) && ISIIOVA(sc->sc_vaddr + oca.ca_offset)) {
+ oca.ca_vaddr = sc->sc_vaddr + oca.ca_offset;
+ oca.ca_paddr = sc->sc_paddr + oca.ca_offset;
+ } else {
+ oca.ca_vaddr = (void *)-1;
+ oca.ca_paddr = (void *)-1;
+ }
+ oca.ca_bustype = BUS_SYSCON;
+ oca.ca_master = (void *)sc->sc_syscon;
+ oca.ca_name = cf->cf_driver->cd_name;
+ if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0)
+ return (0);
+ config_attach(parent, cf, &oca, syscon_print);
+ return (1);
+}
+
+void
+sysconattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ struct confargs *ca = args;
+ struct sysconsoftc *sc = (struct sysconsoftc *)self;
+ int i;
+
+ if (sys_syscon)
+ panic("syscon already attached!");
+
+ /*
+ * since we know ourself to land in intiobase land,
+ * we must adjust our address
+ */
+ sc->sc_paddr = ca->ca_paddr;
+ sc->sc_vaddr = (void *)IIOV(sc->sc_paddr);
+ sc->sc_syscon = &syscon_reg;
+ sys_syscon = sc->sc_syscon;
+
+ printf(": rev %d\n", 1);
+
+ /*
+ * pseudo driver, abort interrupt handler
+ */
+ sc->sc_abih.ih_fn = sysconabort;
+ sc->sc_abih.ih_arg = 0;
+ sc->sc_abih.ih_ipl = IPL_ABORT;
+ sc->sc_abih.ih_wantframe = 1;
+ sc->sc_acih.ih_fn = sysconacfail;
+ sc->sc_acih.ih_arg = 0;
+ sc->sc_acih.ih_ipl = IPL_ABORT;
+ sc->sc_acih.ih_wantframe = 1;
+ sc->sc_sfih.ih_fn = sysconsysfail;
+ sc->sc_sfih.ih_arg = 0;
+ sc->sc_sfih.ih_ipl = IPL_ABORT;
+ sc->sc_sfih.ih_wantframe = 1;
+
+ intr_establish(SYSCV_ABRT, &sc->sc_abih);
+ intr_establish(SYSCV_ACF, &sc->sc_acih);
+ intr_establish(SYSCV_SYSF, &sc->sc_sfih);
+
+ config_search(syscon_scan, self, args);
+}
+
+int
+sysconintr_establish(vec, ih)
+ int vec;
+ struct intrhand *ih;
+{
+ return (intr_establish(vec, ih));
+}
+
+int
+sysconabort(frame)
+ struct frame *frame;
+{
+ ISR_RESET_NMI;
+ nmihand(frame);
+ return (1);
+}
+
+int
+sysconsysfail(frame)
+ struct frame *frame;
+{
+ ISR_RESET_SYSFAIL;
+ nmihand(frame);
+ return (1);
+}
+
+int
+sysconacfail(frame)
+ struct frame *frame;
+{
+ ISR_RESET_ACFAIL;
+ nmihand(frame);
+ return (1);
+}
+
diff --git a/sys/arch/mvme88k/dev/sysconreg.h b/sys/arch/mvme88k/dev/sysconreg.h
new file mode 100644
index 00000000000..bcf4739371f
--- /dev/null
+++ b/sys/arch/mvme88k/dev/sysconreg.h
@@ -0,0 +1,61 @@
+/* $OpenBSD: sysconreg.h,v 1.1 1999/09/27 18:43:25 smurph Exp $ */
+
+/*
+ * Memory map for SYSCON found in mvme188 board set.
+ * No specific chips are found here like the PCCTWO
+ * on MVME1x7. All chips are included in this one
+ * map/device so that devices don't run rampant in
+ * the config files. I may change this later XXX smurph.
+ */
+
+#include <machine/board.h>
+
+struct sysconreg {
+ volatile unsigned int *ien0;
+ volatile unsigned int *ien1;
+ volatile unsigned int *ien2;
+ volatile unsigned int *ien3;
+ volatile unsigned int *ienall;
+ volatile unsigned int *ist;
+ volatile unsigned int *setswi;
+ volatile unsigned int *clrswi;
+ volatile unsigned int *istate;
+ volatile unsigned int *clrint;
+ volatile unsigned char *global0;
+ volatile unsigned char *global1;
+ volatile unsigned char *global2;
+ volatile unsigned char *global3;
+ volatile unsigned int *ucsr;
+ volatile unsigned int *glbres;
+ volatile unsigned int *ccsr;
+ volatile unsigned int *error;
+ volatile unsigned int *pcnfa;
+ volatile unsigned int *pcnfb;
+ volatile unsigned int *extad;
+ volatile unsigned int *extam;
+ volatile unsigned int *whoami;
+ volatile unsigned int *wmad;
+ volatile unsigned int *rmad;
+ volatile unsigned int *wvad;
+ volatile unsigned int *rvad;
+ volatile unsigned int *cio_portc;
+ volatile unsigned int *cio_portb;
+ volatile unsigned int *cio_porta;
+ volatile unsigned int *cio_ctrl;
+};
+
+extern struct sysconreg *sys_syscon;
+
+/*
+ * Vectors we use
+ */
+#define SYSCV_ABRT 0x110
+#define SYSCV_SYSF 0x111
+#define SYSCV_ACF 0x112
+#define SYSCV_SCC 0x55
+#define SYSCV_TIMER4 0x56
+#define SYSCV_TIMER3 0x57
+#define SYSCV_TIMER2 0x58
+#define SYSCV_TIMER1 0x59
+
+
diff --git a/sys/arch/mvme88k/dev/vme.c b/sys/arch/mvme88k/dev/vme.c
index 958077067a1..3d980f28669 100644
--- a/sys/arch/mvme88k/dev/vme.c
+++ b/sys/arch/mvme88k/dev/vme.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: vme.c,v 1.3 1999/05/29 04:41:44 smurph Exp $ */
-
+/* $OpenBSD: vme.c,v 1.4 1999/09/27 18:43:25 smurph Exp $ */
/*
+ * Copyright (c) 1999 Steve Murphree, Jr.
* Copyright (c) 1995 Theo de Raadt
* All rights reserved.
*
@@ -52,22 +52,22 @@
#include "machine/pmap.h"
#include "pcctwo.h"
+#include "syscon.h"
#include <mvme88k/dev/vme.h>
+#if NSYSCON > 0
+#include <mvme88k/dev/sysconreg.h>
+#endif
int vmematch __P((struct device *, void *, void *));
void vmeattach __P((struct device *, struct device *, void *));
-int vme1chip_init __P((struct vmesoftc *sc));
int vme2chip_init __P((struct vmesoftc *sc));
u_long vme2chip_map __P((u_long base, int len, int dwidth));
int vme2abort __P((struct frame *frame));
+int sysconabort __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 = {
@@ -85,37 +85,9 @@ vmematch(parent, cf, args)
void *args;
{
struct confargs *ca = args;
-
-#if NMC > 0
- if (ca->ca_bustype == BUS_MC) {
- struct mcreg *mc = (struct mcreg *)ca->ca_master;
-
- if (mc->mc_ver & MC_VER_NOVME)
- return (0);
- }
-#endif
return (1);
}
-#ifndef BUGMAP
-/*
- * 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)
-
-#else
-
/*
* make local addresses 1G-2G correspond to VME addresses 3G-4G,
* as D32
@@ -135,8 +107,6 @@ vmematch(parent, cf, args)
#define VME2_A32D16STARTPHYS (0xFF000000UL)
#define VME2_A32D16ENDPHYS (0xFF7FFFFFUL)
-#endif
-
/*
* Returns a physical address mapping for a VME address & length.
@@ -155,43 +125,9 @@ vmepmap(sc, vmeaddr, len, bustype)
len = roundup(len, NBPG);
switch (vmebustype) {
-#if NPCC > 0
- case BUS_PCC:
- switch (bustype) {
- case BUS_VMES:
- printf("base 0x%8x/0x%8x len 0x%x\n",
- vmeaddr, base, len);
- if (base > VME1_A16BASE &&
- (base+len - VME1_A16BASE) < VME1_A16D16LEN) {
- base = base - VME1_A16BASE + VME1_A16D16BASE;
- printf("vmes1: base = 0x%8x\n", base); /* 1:1 */
- } else if (base > VME1_A32D16BASE &&
- base+len < VME1_A16BASE) {
- /* 1:1 mapped */
- printf("vmes2: base = 0x%8x\n", base);
- } else {
- 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 (base >= physmem && (base+len) < VME1_A32D32LEN)
- base = base + VME1_A32D32BASE;
- else if (base+len < VME1_A32D16LEN) /* HACK! */
- base = base + VME1_A32D16BASE;
- else {
- printf("%s: cannot map pa 0x%x len 0x%x\n",
- sc->sc_dev.dv_xname, base, len);
- return (NULL);
- }
- break;
- }
- break;
-#endif
-#if NMC > 0 || NPCCTWO > 0
- case BUS_MC:
+#if NPCCTWO > 0 || NSYSCON > 0
case BUS_PCCTWO:
+ case BUS_SYSCON:
switch (bustype) {
case BUS_VMES: /* D16 VME Transfers */
/*printf("base 0x%8x/0x%8x len 0x%x\n", vmeaddr, base, len);*/
@@ -357,6 +293,7 @@ vmeattach(parent, self, args)
struct vme1reg *vme1;
struct vme2reg *vme2;
int scon;
+ char sconc;
/* XXX any initialization to do? */
@@ -364,16 +301,7 @@ vmeattach(parent, self, args)
vmebustype = ca->ca_bustype;
switch (ca->ca_bustype) {
-#if NPCC > 0
- case BUS_PCC:
- vme1 = (struct vme1reg *)sc->sc_vaddr;
- scon = (vme1->vme1_scon & VME1_SCON_SWITCH);
- printf(": %ssystem controller\n", scon ? "" : "not ");
- vme1chip_init(sc);
- break;
-#endif
-#if (NMC > 0) || (NPCCTWO > 0)
- case BUS_MC:
+#if NPCCTWO > 0
case BUS_PCCTWO:
vme2 = (struct vme2reg *)sc->sc_vaddr;
scon = (vme2->vme2_tctl & VME2_TCTL_SCON);
@@ -382,6 +310,15 @@ vmeattach(parent, self, args)
vme2chip_init(sc);
break;
#endif
+#if NSYSCON > 0
+ case BUS_SYSCON:
+ vme2 = (struct vme2reg *)sc->sc_vaddr;
+ sconc = *(char *)GLOBAL1;
+ sconc &= M188_SYSCON;
+ printf(": %ssystem controller\n", scon ? "" : "not ");
+ vmesyscon_init(sc);
+ break;
+#endif
}
while (config_found(self, NULL, NULL))
@@ -406,125 +343,74 @@ vmeintr_establish(vec, ih)
struct intrhand *ih;
{
struct vmesoftc *sc = (struct vmesoftc *) vme_cd.cd_devs[0];
-#if NPCC > 0
- struct vme1reg *vme1;
-#endif
-#if NMC > 0 || NPCCTWO > 0
+#if NPCCTWO > 0
struct vme2reg *vme2;
#endif
+#if NSYSCON > 0
+ struct sysconreg *syscon;
+#endif
int x;
x = (intr_establish(vec, ih));
switch (vmebustype) {
-#if NPCC > 0
- case BUS_PCC:
- vme1 = (struct vme1reg *)sc->sc_vaddr;
- vme1->vme1_irqen = vme1->vme1_irqen |
- VME1_IRQ_VME(ih->ih_ipl);
- break;
-#endif
-#if NMC > 0 || NPCCTWO > 0
- case BUS_MC:
+#if NPCCTWO > 0
case BUS_PCCTWO:
vme2 = (struct vme2reg *)sc->sc_vaddr;
vme2->vme2_irqen = vme2->vme2_irqen |
VME2_IRQ_VME(ih->ih_ipl);
break;
#endif
+#if NSYSCON > 0
+ case BUS_SYSCON:
+ syscon = (struct sysconreg *)sc->sc_vaddr;
+ /*
+ syscon->vme2_irqen = vme2->vme2_irqen |
+ VMES_IRQ_VME(ih->ih_ipl);
+ */
+ break;
+#endif
}
return (x);
}
-#if defined(MVME147)
-int
-vme1chip_init(sc)
- struct vmesoftc *sc;
-{
- struct vme1reg *vme1 = (struct vme1reg *)sc->sc_vaddr;
-
- vme1->vme1_scon &= ~VME1_SCON_SYSFAIL; /* XXX doesn't work */
-}
-#endif
-
-
-#ifndef BUGMAP
-
-/*
- * XXX what AM bits should be used for the D32/D16 mappings?
- */
+#if NPCCTWO > 0
int
vme2chip_init(sc)
struct vmesoftc *sc;
{
struct vme2reg *vme2 = (struct vme2reg *)sc->sc_vaddr;
- u_long ctl;
+ u_long ctl, addr, vasize;
/* turn off SYSFAIL LED */
vme2->vme2_tctl &= ~VME2_TCTL_SYSFAIL;
ctl = vme2->vme2_masterctl;
-
- /* unused decoders 1 */
- vme2->vme2_master1 = 0;
- ctl &= ~(VME2_MASTERCTL_ALL << VME2_MASTERCTL_1SHIFT);
+ 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);
- /* unused decoders 2 */
- vme2->vme2_master2 = 0;
- ctl &= ~(VME2_MASTERCTL_ALL << VME2_MASTERCTL_2SHIFT);
+ /* 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 */
- vme2->vme2_master3 = ((VME2_D16ENDPHYS-1) & 0xffff0000) |
- (VME2_D16STARTPHYS >> 16);
- 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 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 A32D32 space */
- vme2->vme2_master4 = ((VME2_D32ENDPHYS-1) & 0xffff0000) |
- (VME2_D32STARTPHYS >> 16);
- vme2->vme2_master4mod = (VME2_D32STARTVME & 0xffff0000) |
- (VME2_D32BITSVME >> 16);
- ctl &= ~(VME2_MASTERCTL_ALL << VME2_MASTERCTL_4SHIFT);
- ctl |= (VME2_MASTERCTL_AM32UD) <<
- VME2_MASTERCTL_4SHIFT;
+ /* 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_master4 & 0xffff0000);
-
- vme2->vme2_masterctl = ctl;
- ctl = vme2->vme2_gcsrctl;
-
- /* enable A16 short IO map decoder (0xffffxxxx) */
- ctl &= ~(VME2_GCSRCTL_I1EN | VME2_GCSRCTL_I1D16 | VME2_GCSRCTL_I1WP |
- VME2_GCSRCTL_I1SU);
- ctl |= VME2_GCSRCTL_I1EN | VME2_GCSRCTL_I1D16 | VME2_GCSRCTL_I1SU;
-
- /* enable A24D16 (0xf0xxxxxx) and A32D16 (0xf[1-e]xxxxxx) decoders */
- ctl &= ~(VME2_GCSRCTL_I2EN | VME2_GCSRCTL_I2WP | VME2_GCSRCTL_I2SU |
- VME2_GCSRCTL_I2PD);
- ctl |= VME2_GCSRCTL_I2EN | VME2_GCSRCTL_I2SU | VME2_GCSRCTL_I2PD;
-
- /* map decoders 3 & 4 which were just configured */
- ctl &= ~(VME2_GCSRCTL_MDEN4 | VME2_GCSRCTL_MDEN3 | VME2_GCSRCTL_MDEN1 |
- VME2_GCSRCTL_MDEN2);
- ctl |= VME2_GCSRCTL_MDEN4 | VME2_GCSRCTL_MDEN3;
-
- vme2->vme2_gcsrctl = ctl;
-
+ 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.
@@ -533,101 +419,69 @@ vme2chip_init(sc)
(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) {
+ */
+ if (vmebustype == BUS_PCCTWO){
+ /*
+ * pseudo driver, abort interrupt handler
+ */
sc->sc_abih.ih_fn = vme2abort;
sc->sc_abih.ih_arg = 0;
- sc->sc_abih.ih_ipl = 7;
+ sc->sc_abih.ih_ipl = IPL_NMI;
sc->sc_abih.ih_wantframe = 1;
-
- intr_establish(110, &sc->sc_abih); /* XXX 110 */
+ intr_establish(110, &sc->sc_abih);
vme2->vme2_irqen |= VME2_IRQ_AB;
}
-#endif
vme2->vme2_irqen = vme2->vme2_irqen | VME2_IRQ_ACF;
}
+#endif /* NPCCTWO */
-#else /* BUGMAP */
-
+#if NSYSCON > 0
int
-vme2chip_init(sc)
+vmesyscon_init(sc)
struct vmesoftc *sc;
{
- struct vme2reg *vme2 = (struct vme2reg *)sc->sc_vaddr;
+ struct sysconreg *syscon = (struct sysconreg *)sc->sc_vaddr;
u_long ctl, addr, vasize;
+#ifdef TODO
/* 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",
+ printf("%s: 1phys 0x%08x-0x%08x to VME 0x%08x-0x%08x master\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",
+ printf("%s: 2phys 0x%08x-0x%08x to VME 0x%08x-0x%08x slave\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
- */
- sc->sc_abih.ih_fn = vme2abort;
- sc->sc_abih.ih_arg = 0;
- sc->sc_abih.ih_ipl = IPL_NMI;
- sc->sc_abih.ih_wantframe = 1;
-#if 0
- printf("inserting vme_ab handler\n");
-#endif
- intr_establish(110, &sc->sc_abih);
- vme2->vme2_irqen |= VME2_IRQ_AB;
- }
-#endif
- vme2->vme2_irqen = vme2->vme2_irqen | VME2_IRQ_ACF;
+ /*
+ * pseudo driver, abort interrupt handler
+ */
+ sc->sc_abih.ih_fn = sysconabort;
+ sc->sc_abih.ih_arg = 0;
+ sc->sc_abih.ih_ipl = IPL_NMI;
+ sc->sc_abih.ih_wantframe = 1;
+ intr_establish(110, &sc->sc_abih);
+#endif /* TODO */
}
-#endif /* BUGMAP */
+#endif /* NSYSCON */
-#if defined(MVME162) || defined(MVME167) || defined(MVME177) || defined (MVME187) || defined (MVME188)
+#if defined(MVME162) || defined(MVME167) || defined(MVME177) || defined (MVME187) || defined (MVME197)
/*
- * A32 accesses on the MVME1[678]x require setting up mappings in
+ * A32 accesses on the MVME1[6789]x require setting up mappings in
* the VME2 chip.
* XXX VME address must be between 2G and 4G
* XXX We only support D32 at the moment..
+ * XXX smurph - This is bogus, get rid of it! Should check vme/syson for offsets.
*/
u_long
vme2chip_map(base, len, dwidth)
@@ -654,7 +508,7 @@ vme2abort(frame)
struct vme2reg *vme2 = (struct vme2reg *)sc->sc_vaddr;
if (vme2->vme2_irqstat & VME2_IRQ_AB == 0) {
- printf("%s: vme2chip irq not set\n", sc->sc_dev.dv_xname);
+ printf("%s: abort irq not set\n", sc->sc_dev.dv_xname);
return (0);
}
vme2->vme2_irqclr = VME2_IRQ_AB;
diff --git a/sys/arch/mvme88k/dev/vs.c b/sys/arch/mvme88k/dev/vs.c
index a92f1bf6211..5c5e44b991d 100644
--- a/sys/arch/mvme88k/dev/vs.c
+++ b/sys/arch/mvme88k/dev/vs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vs.c,v 1.1 1999/05/29 04:41:44 smurph Exp $ */
+/* $OpenBSD: vs.c,v 1.2 1999/09/27 18:43:25 smurph Exp $ */
/*
* Copyright (c) 1999 Steve Murphree, Jr.
@@ -52,13 +52,19 @@
#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"
+
+#if defined(MVME187) || defined(MVME188) || defined(MVME197)
+ #define PAGESIZE 4096
+ #include <mvme88k/dev/vsreg.h>
+ #include <mvme88k/dev/vsvar.h>
+ #include "machine/mmu.h"
+ #define ROUND_PAGE m88k_round_page
+ #define TRUNC_PAGE m88k_trunc_page
#else
-#include <mvme68k/dev/vsreg.h>
-#include <mvme68k/dev/vsvar.h>
+ #include <mvme68k/dev/vsreg.h>
+ #include <mvme68k/dev/vsvar.h>
+ #define ROUND_PAGE m68k_round_page
+ #define TRUNC_PAGE m68k_trunc_page
#endif /* MVME187 */
int vs_checkintr __P((struct vs_softc *, struct scsi_xfer *, int *));
@@ -73,31 +79,77 @@ M328_CQE * vs_getcqe __P((struct vs_softc *));
M328_IOPB * vs_getiopb __P((struct vs_softc *));
extern int cold;
-extern u_int kvtop();
+extern u_int kvtop();
+/*
+ * 16 bit 's' memory functions. MVME328 is a D16 board.
+ * We must program with that in mind or else...
+ * bcopy/bzero (the 'b' meaning byte) is implemented in
+ * 32 bit operations for speed, so thay are not really
+ * 'byte' operations at all!! MVME1x7 can be set up to
+ * handle D32 -> D16 read/writes via VMEChip2 Address
+ * modifiers, however MVME188 can not. These next two
+ * function insure 16 bit copy/zero operations. The
+ * structures are all implemented with 16 bit or less
+ * types. smurph
+ */
+
+void
+scopy(void *src, void *dst, unsigned short cnt)
+{
+ register unsigned short volatile *x, *y, z;
+
+ z = cnt >> 1;
+ x = (unsigned short *) src;
+ y = (unsigned short *) dst;
+
+ while (z--) {
+ *y++ = *x++;
+ }
+}
+
+void
+szero(void *src, u_long cnt)
+{
+ register unsigned short *source;
+ register unsigned short zero = 0;
+ register unsigned short z;
+
+ source = (unsigned short *) src;
+ z = cnt >> 1;
+
+ while (z--) {
+ *source++ = zero;
+ }
+ return;
+}
+
+
+
+
/*
* default minphys routine for MVME328 based controllers
*/
void
vs_minphys(bp)
- struct buf *bp;
+struct buf *bp;
{
- /*
- * No max transfer at this level.
- */
- minphys(bp);
+ /*
+ * No max transfer at this level.
+ */
+ minphys(bp);
}
int do_vspoll(sc, to)
- struct vs_softc *sc;
- int 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))){
+ while (!(CRSW & (M_CRSW_CRBV | M_CRSW_CC))) {
if (--i <= 0) {
#ifdef DEBUG
printf ("waiting: timeout %d crsw 0x%x\n", to, CRSW);
@@ -118,8 +170,8 @@ int do_vspoll(sc, to)
int
vs_poll(sc, xs)
- struct vs_softc *sc;
- struct scsi_xfer *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;
@@ -129,29 +181,29 @@ vs_poll(sc, xs)
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;
+ 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)
+ vs_scsidone(xs, status);
+ }
+ if (CRSW & M_CRSW_ER)
CRB_CLR_ER(CRSW);
CRB_CLR_DONE(CRSW);
if (xs->flags & ITSDONE) break;
- }
- return (COMPLETE);
+ }
+ return (COMPLETE);
}
void thaw_queue(sc, target)
- struct vs_softc *sc;
- u_int8_t target;
+struct vs_softc *sc;
+u_int8_t target;
{
u_short t;
t = target << 8;
@@ -176,21 +228,21 @@ int stat;
}
xs->flags |= ITSDONE;
/*sc->sc_tinfo[slp->target].cmds++;*/
- if (CRSW & M_CRSW_ER)
+ if (CRSW & M_CRSW_ER)
CRB_CLR_ER(CRSW);
CRB_CLR_DONE(CRSW);
thaw_queue(sc, slp->target + 1);
- bzero(riopb, sizeof(M328_IOPB));
+ szero(riopb, sizeof(M328_IOPB));
scsi_done(xs);
}
int
vs_scsicmd(xs)
- struct scsi_xfer *xs;
+struct scsi_xfer *xs;
{
- struct scsi_link *slp = xs->sc_link;
- struct vs_softc *sc = slp->adapter_softc;
- int flags, s, i;
+ 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;
@@ -200,6 +252,7 @@ vs_scsicmd(xs)
M328_MCSB *mcsb = (M328_MCSB *)&sc->sc_vsreg->sh_MCSB;
M328_CQE *cqep;
M328_IOPB *iopb;
+ M328_CMD *m328_cmd;
/* If the target doesn't exist, abort */
if (!sc->sc_tinfo[slp->target].avail) {
@@ -208,12 +261,12 @@ vs_scsicmd(xs)
xs->flags |= ITSDONE;
scsi_done(xs);
}
-
+
slp->quirks |= SDEV_NOLUNS;
flags = xs->flags;
#ifdef SDEBUG
printf("scsi_cmd() ");
- if (xs->cmd->opcode == 0){
+ if (xs->cmd->opcode == 0) {
printf("TEST_UNIT_READY ");
} else if (xs->cmd->opcode == REQUEST_SENSE) {
printf("REQUEST_SENSE ");
@@ -245,50 +298,52 @@ vs_scsicmd(xs)
printf("READ_COMMAND ");
}
#endif
- if (flags & SCSI_POLL){
+ if (flags & SCSI_POLL) {
cqep = mc;
iopb = miopb;
- }else{
+ } else {
cqep = vs_getcqe(sc);
iopb = vs_getiopb(sc);
}
if (cqep == NULL) {
xs->error = XS_DRIVER_STUFFUP;
- return(TRY_AGAIN_LATER);
+ return (TRY_AGAIN_LATER);
}
-
+
/* s = splbio();*/
iopb_len = sizeof(M328_short_IOPB) + xs->cmdlen;
- bzero(iopb, sizeof(M328_IOPB));
+ szero(iopb, sizeof(M328_IOPB));
- bcopy(xs->cmd, &iopb->iopb_SCSI[0], xs->cmdlen);
- iopb->iopb_CMD = IOPB_SCSI;
+ scopy(xs->cmd, &iopb->iopb_SCSI[0], xs->cmdlen);
+ iopb->iopb_CMD = IOPB_SCSI;
+#if 0
LV(iopb->iopb_BUFF, kvtop(xs->data));
LV(iopb->iopb_LENGTH, xs->datalen);
+#endif
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.
- */
+
+ /*
+ * 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);
+ 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);
+ 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;
@@ -297,23 +352,33 @@ vs_scsicmd(xs)
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);
-
+ while (cqep->cqe_QECR & M_QECR_GO);
+
cqep->cqe_IOPB_ADDR = OFF(iopb);
cqep->cqe_IOPB_LENGTH = iopb_len;
- if (flags & SCSI_POLL){
+ if (flags & SCSI_POLL) {
cqep->cqe_WORK_QUEUE = slp->target + 1;
- }else{
+ } else {
cqep->cqe_WORK_QUEUE = slp->target + 1;
}
- LV(cqep->cqe_CTAG, xs);
+ MALLOC(m328_cmd, M328_CMD*, sizeof(M328_CMD), M_DEVBUF, M_WAITOK);
+
+ m328_cmd->xs = xs;
+ if (xs->datalen) {
+ m328_cmd->top_sg_list = vs_build_memory_structure(xs, iopb);
+ } else {
+ m328_cmd->top_sg_list = (M328_SG)0;
+ }
+
+ LV(cqep->cqe_CTAG, m328_cmd);
+
if (crb->crb_CRSW & M_CRSW_AQ) {
cqep->cqe_QECR = M_QECR_AA;
}
@@ -324,42 +389,42 @@ vs_scsicmd(xs)
slp->lun, buf, len, cqep->cqe_WORK_QUEUE, iopb->iopb_LEVEL);
#endif
cqep->cqe_QECR |= M_QECR_GO;
-
- if (flags & SCSI_POLL){
+
+ if (flags & SCSI_POLL) {
/* poll for the command to complete */
/* splx(s);*/
vs_poll(sc, xs);
return (COMPLETE);
}
/* splx(s);*/
- return(SUCCESSFULLY_QUEUED);
+ return (SUCCESSFULLY_QUEUED);
}
int
vs_chksense(xs)
- struct scsi_xfer *xs;
+struct scsi_xfer *xs;
{
- int flags, s, i;
+ 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));
+
+ szero(miopb, sizeof(M328_IOPB));
/* This is a command, so point to it */
ss = (void *)&miopb->iopb_SCSI[0];
- bzero(ss, sizeof(*ss));
+ szero(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;
@@ -368,8 +433,8 @@ vs_chksense(xs)
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));
+
+ szero(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;
@@ -391,42 +456,42 @@ vs_chksense(xs)
M328_CQE *
vs_getcqe(sc)
- struct vs_softc *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)
+
+ 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));
+ szero(cqep, sizeof(M328_CQE));
return cqep;
}
M328_IOPB *
vs_getiopb(sc)
- struct vs_softc *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) {
+
+ 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));
+ szero(iopb, sizeof(M328_IOPB));
return iopb;
}
void
vs_initialize(sc)
- struct vs_softc *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;
@@ -438,7 +503,8 @@ vs_initialize(sc)
u_short i, crsw;
int failed = 0;
- bzero(cib, sizeof(M328_CIB));
+ CRB_CLR_DONE(CRSW);
+ szero(cib, sizeof(M328_CIB));
mcsb->mcsb_QHDP = 0;
sc->sc_qhp = 0;
cib->cib_NCQE = 10;
@@ -464,7 +530,7 @@ vs_initialize(sc)
cib->cib_SRATE1 = 0x0;
iopb = (M328_IOPB *)&sc->sc_vsreg->sh_MCE_IOPB;
- bzero(iopb, sizeof(M328_IOPB));
+ szero(iopb, sizeof(M328_IOPB));
iopb->iopb_CMD = CNTR_INIT;
iopb->iopb_OPTION = 0;
iopb->iopb_NVCT = (u_char)sc->sc_nvec;
@@ -473,8 +539,8 @@ vs_initialize(sc)
iopb->iopb_ADDR = SHIO_MOD;
LV(iopb->iopb_BUFF, OFF(cib));
LV(iopb->iopb_LENGTH, sizeof(M328_CIB));
-
- bzero(mc, sizeof(M328_CQE));
+
+ szero(mc, sizeof(M328_CQE));
mc->cqe_IOPB_ADDR = OFF(iopb);
mc->cqe_IOPB_LENGTH = sizeof(M328_IOPB);
mc->cqe_WORK_QUEUE = 0;
@@ -482,10 +548,10 @@ vs_initialize(sc)
/* 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));
+ szero(wiopb, sizeof(M328_IOPB));
wiopb->wqcf_CMD = CNTR_INIT_WORKQ;
wiopb->wqcf_OPTION = 0;
wiopb->wqcf_NVCT = (u_char)sc->sc_nvec;
@@ -495,8 +561,8 @@ vs_initialize(sc)
wiopb->wqcf_WOPT = (WQO_FOE | WQO_INIT);
wiopb->wqcf_SLOTS = JAGUAR_MAX_Q_SIZ;
LV(wiopb->wqcf_CMDTO, 2);
-
- bzero(mc, sizeof(M328_CQE));
+
+ szero(mc, sizeof(M328_CQE));
mc->cqe_IOPB_ADDR = OFF(wiopb);
mc->cqe_IOPB_LENGTH = sizeof(M328_IOPB);
mc->cqe_WORK_QUEUE = 0;
@@ -504,12 +570,12 @@ vs_initialize(sc)
/* 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);
+ /*printf("\nerror: queue %d status = 0x%x\n", i, riopb->iopb_STATUS);*/
/*failed = 1;*/
CRB_CLR_ER(CRSW);
}
CRB_CLR_DONE(CRSW);
- delay(1000);
+ delay(500);
}
/* start queue mode */
CRSW = 0;
@@ -521,7 +587,7 @@ vs_initialize(sc)
CRB_CLR_ER(CRSW);
}
CRB_CLR_DONE(CRSW);
-
+
if (failed) {
printf(": failed!\n");
return;
@@ -530,12 +596,12 @@ vs_initialize(sc)
vs_reset(sc);
/* sync all devices */
vs_resync(sc);
- printf(": target %d\n", sc->sc_link.adapter_target);
+ printf(": target %d\n", sc->sc_link.adapter_target);
}
-
+
void
vs_resync(sc)
- struct vs_softc *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;
@@ -543,15 +609,15 @@ vs_resync(sc)
u_short i;
for (i=0; i<7; i++) {
- bzero(devreset, sizeof(M328_DRCF));
+ szero(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));
+
+ szero(mc, sizeof(M328_CQE));
mc->cqe_IOPB_ADDR = OFF(devreset);
mc->cqe_IOPB_LENGTH = sizeof(M328_DRCF);
mc->cqe_WORK_QUEUE = 0;
@@ -572,12 +638,12 @@ vs_resync(sc)
void
vs_reset(sc)
- struct vs_softc *sc;
+struct vs_softc *sc;
{
- struct vsreg * rp;
- u_int s;
- u_char i;
- struct iopb_reset* iopr;
+ struct vsreg * rp;
+ u_int s;
+ u_char i;
+ struct iopb_reset* iopr;
struct cqe *cqep;
struct iopb_scsi *iopbs;
struct scsi_sense *ss;
@@ -588,8 +654,8 @@ vs_reset(sc)
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));
+
+ szero(reset, sizeof(M328_SRCF));
reset->srcf_CMD = IOPB_RESET;
reset->srcf_OPTION = 0x00; /* no interrupts yet... */
reset->srcf_NVCT = sc->sc_nvec;
@@ -597,14 +663,14 @@ vs_reset(sc)
reset->srcf_ILVL = 0;
reset->srcf_BUSID = 0;
s = splbio();
-
- bzero(mc, sizeof(M328_CQE));
+
+ szero(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){
+ while (1) {
do_vspoll(sc, 0);
/* ack & clear scsi error condition cause by reset */
if (CRSW & M_CRSW_ER) {
@@ -617,7 +683,7 @@ vs_reset(sc)
}
/* thaw all work queues */
thaw_queue(sc, 0xFF);
- splx (s);
+ splx (s);
}
@@ -629,13 +695,13 @@ vs_reset(sc)
int
vs_checkintr(sc, xs, status)
- struct vs_softc *sc;
- struct scsi_xfer *xs;
- int *status;
+struct vs_softc *sc;
+struct scsi_xfer *xs;
+int *status;
{
- struct vsreg * rp = sc->sc_vsreg;
- int target = -1;
- int lun = -1;
+ 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;
@@ -646,7 +712,7 @@ vs_checkintr(sc, xs, status)
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;
@@ -654,8 +720,8 @@ vs_checkintr(sc, xs, status)
#ifdef SDEBUG
printf("scsi_chk() ");
-
- if (xs->cmd->opcode == 0){
+
+ if (xs->cmd->opcode == 0) {
printf("TEST_UNIT_READY ");
} else if (xs->cmd->opcode == REQUEST_SENSE) {
printf("REQUEST_SENSE ");
@@ -686,9 +752,9 @@ vs_checkintr(sc, xs, status)
} 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]");
}
@@ -714,7 +780,7 @@ vs_checkintr(sc, xs, status)
} else {
xs->resid = 0;
}
-
+
if (error == SCSI_SELECTION_TO) {
xs->error = XS_SELTIMEOUT;
xs->status = -1;
@@ -725,34 +791,235 @@ vs_checkintr(sc, xs, status)
int
vs_intr (sc)
- register struct vs_softc *sc;
+register struct vs_softc *sc;
{
M328_CRB *crb = (M328_CRB *)&sc->sc_vsreg->sh_CRB;
- struct scsi_xfer *xs;
+ struct scsi_xfer *xs;
+ M328_CMD *m328_cmd;
unsigned long loc;
- int status;
+ int status;
int s;
- s = splbio();
- /* Got a valid interrupt on this device */
-
+ 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
+ * If this is a controller error, there won't be a m328_cmd
* 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.
+ * in vsdma.c I'll change this soon - steve.
*/
if (loc) {
- xs = (struct scsi_xfer *)loc;
+ m328_cmd = (M328_CMD *)loc;
+ xs = m328_cmd->xs;
+ if (m328_cmd->top_sg_list) {
+ vs_dealloc_scatter_gather(m328_cmd->top_sg_list);
+ m328_cmd->top_sg_list = (M328_SG)0;
+ }
+
+ FREE(m328_cmd, M_DEVBUF); /* free the command tag */
if (vs_checkintr (sc, xs, &status)) {
vs_scsidone(xs, status);
}
}
- splx(s);
+ splx(s);
+}
+
+/*
+ * Useful functions for scatter/gather list
+ */
+
+M328_SG
+vs_alloc_scatter_gather(void)
+{
+ M328_SG sg;
+
+ MALLOC(sg, M328_SG, sizeof(struct m328_sg), M_DEVBUF, M_WAITOK);
+ assert ( sg );
+ if ( !sg ) {
+ panic ("Memory for scatter_gather_list not available");
+ }
+ bzero(sg, sizeof(struct m328_sg));
+
+ return (sg);
+}
+
+void
+vs_dealloc_scatter_gather(M328_SG sg)
+{
+ register int i;
+
+ if (sg->level > 0) {
+ for (i=0; sg->down[i] && i<MAX_SG_ELEMENTS; i++) {
+ vs_dealloc_scatter_gather(sg->down[i]);
+ }
+ }
+ FREE(sg, M_DEVBUF);
+}
+
+void
+vs_link_sg_element(sg_list_element_t * element,
+ register vm_offset_t phys_add,
+ register int len)
+{
+ element->count.bytes = len;
+ LV(element->address, phys_add);
+ element->link = 0; /* FALSE */
+ element->transfer_type = NORMAL_TYPE;
+ element->memory_type = LONG_TRANSFER;
+ element->address_modifier = 0xD;
+}
+
+void
+vs_link_sg_list(sg_list_element_t * list,
+ register vm_offset_t phys_add,
+ register int elements)
+{
+
+ list->count.scatter.gather = elements;
+ LV(list->address, phys_add);
+ list->link = 1; /* TRUE */
+ list->transfer_type = NORMAL_TYPE;
+ list->memory_type = LONG_TRANSFER;
+ list->address_modifier = 0xD;
}
+M328_SG
+vs_build_memory_structure(xs, iopb)
+struct scsi_xfer *xs;
+M328_IOPB *iopb; /* the iopb */
+{
+ M328_SG sg;
+ vm_offset_t starting_point_virt, starting_point_phys, point_virt,
+ point1_phys, point2_phys, virt;
+ unsigned len;
+ int level;
+
+ sg = (M328_SG)0; /* Hopefully we need no scatter/gather list */
+
+ /*
+ * We have the following things:
+ * virt the virtuell address of the contiguous virtual memory block
+ * len the lenght of the contiguous virtual memory block
+ * starting_point_virt the virtual address of the contiguous *physical* memory block
+ * starting_point_phys the *physical* address of the contiguous *physical* memory block
+ * point_virt the pointer to the virtual memory we are checking at the moment
+ * point1_phys the pointer to the *physical* memory we are checking at the moment
+ * point2_phys the pointer to the *physical* memory we are checking at the moment
+ */
+
+ level = 0;
+ virt = starting_point_virt = (vm_offset_t)xs->data;
+ point1_phys = starting_point_phys = kvtop(xs->data);
+ len = xs->datalen;
+ /*
+ * Check if we need scatter/gather
+ */
+
+ if (len > PAGESIZE) {
+ for (level = 0, point_virt = ROUND_PAGE(starting_point_virt+1);
+ /* if we do already scatter/gather we have to stay in the loop and jump */
+ point_virt < virt + (vm_offset_t)len || sg ;
+ point_virt += PAGESIZE) { /* out later */
+
+ point2_phys = kvtop(point_virt);
+
+ if ((point2_phys - TRUNC_PAGE(point1_phys) - PAGESIZE) || /* physical memory is not contiguous */
+ (point_virt - starting_point_virt >= MAX_SG_BLOCK_SIZE && sg)) { /* we only can access (1<<16)-1 bytes in scatter/gather_mode */
+ if (point_virt - starting_point_virt >= MAX_SG_BLOCK_SIZE) { /* We were walking too far for one scatter/gather block ... */
+ assert( MAX_SG_BLOCK_SIZE > PAGESIZE );
+ point_virt = TRUNC_PAGE(starting_point_virt+MAX_SG_BLOCK_SIZE-1); /* So go back to the beginning of the last matching page */
+ /* and gererate the physadress of this location for the next time. */
+ point2_phys = kvtop(point_virt);
+ }
+
+ if (!sg) {
+ /* We allocate our fist scatter/gather list */
+ sg = vs_alloc_scatter_gather();
+ }
+#if 1 /* broken firmware */
+
+ if (sg->elements >= MAX_SG_ELEMENTS) {
+ vs_dealloc_scatter_gather(sg);
+ return (NULL);
+ }
+
+#else /* if the firmware will ever get fixed */
+ while (sg->elements >= MAX_SG_ELEMENTS) {
+ if (!sg->up) { /* If the list full in this layer ? */
+ sg->up = vs_alloc_scatter_gather();
+ sg->up->level = sg->level+1;
+ sg->up->down[0] = sg;
+ sg->up->elements = 1;
+ }
+ /* link this full list also in physical memory */
+ vs_link_sg_list(&(sg->up->list[sg->up->elements-1]),
+ kvtop((vm_offset_t)sg->list),
+ sg->elements);
+ sg = sg->up; /* Climb up */
+ }
+ while (sg->level) { /* As long as we are not a the base level */
+ register int i;
+
+ i = sg->elements;
+ /* We need a new element */
+ sg->down[i] = vs_alloc_scatter_gather();
+ sg->down[i]->level = sg->level - 1;
+ sg->down[i]->up = sg;
+ sg->elements++;
+ sg = sg->down[i]; /* Climb down */
+ }
+#endif /* 1 */
+
+ if (point_virt < virt+(vm_offset_t)len) {
+ /* linking element */
+ vs_link_sg_element(&(sg->list[sg->elements]),
+ starting_point_phys,
+ point_virt-starting_point_virt);
+ sg->elements++;
+ } else {
+ /* linking last element */
+ vs_link_sg_element(&(sg->list[sg->elements]),
+ starting_point_phys,
+ (vm_offset_t)(virt+len)-starting_point_virt);
+ sg->elements++;
+ break; /* We have now collected all blocks */
+ }
+ starting_point_virt = point_virt;
+ starting_point_phys = point2_phys;
+ }
+ point1_phys = point2_phys;
+ }
+ }
+
+ /*
+ * Climb up along the right side of the tree until we reach the top.
+ */
+
+ if (sg) {
+ while (sg->up) {
+ /* link this list also in physical memory */
+ vs_link_sg_list(&(sg->up->list[sg->up->elements-1]),
+ kvtop((vm_offset_t)sg->list),
+ sg->elements);
+ sg = sg->up; /* Climb up */
+ }
+
+ iopb->iopb_OPTION |= M_OPT_SG;
+ iopb->iopb_ADDR |= M_ADR_SG_LINK;
+ LV(iopb->iopb_BUFF, kvtop((vm_offset_t)sg->list));
+ LV(iopb->iopb_LENGTH, sg->elements);
+ LV(iopb->iopb_SGTTL, len);
+ } else {
+ /* no scatter/gather neccessary */
+ LV(iopb->iopb_BUFF, starting_point_phys);
+ LV(iopb->iopb_LENGTH, len);
+ }
+ return (sg);
+}
+
diff --git a/sys/arch/mvme88k/dev/vsdma.c b/sys/arch/mvme88k/dev/vsdma.c
index c8a3186d0ab..ce15c791b55 100644
--- a/sys/arch/mvme88k/dev/vsdma.c
+++ b/sys/arch/mvme88k/dev/vsdma.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vsdma.c,v 1.1 1999/05/29 04:41:44 smurph Exp $ */
+/* $OpenBSD: vsdma.c,v 1.2 1999/09/27 18:43:26 smurph Exp $ */
/*
* Copyright (c) 1999 Steve Murphree, Jr.
* All rights reserved.
@@ -96,11 +96,13 @@ vsmatch(pdp, 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);
+ */
+ return(1);
} else {
return (0);
}
diff --git a/sys/arch/mvme88k/dev/vsreg.h b/sys/arch/mvme88k/dev/vsreg.h
index d722d62e7ea..8adac5f60fe 100644
--- a/sys/arch/mvme88k/dev/vsreg.h
+++ b/sys/arch/mvme88k/dev/vsreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vsreg.h,v 1.1 1999/05/29 04:41:44 smurph Exp $ */
+/* $OpenBSD: vsreg.h,v 1.2 1999/09/27 18:43:26 smurph Exp $ */
/*
* Copyright (c) 1999 Steve Murphree, Jr.
* Copyright (c) 1990 The Regents of the University of California.
@@ -38,6 +38,7 @@
#if !defined(_M328REG_H_)
#define _M328REG_H_
+
typedef struct LONGV
{
u_short msw;
@@ -161,6 +162,52 @@ typedef struct mcsb
/**************** END Master Control Status Block (MCSB) *******************/
+/**************** Scater/Gather Stuff *******************/
+
+typedef struct {
+ union {
+ unsigned short bytes :16;
+ #define MAX_SG_BLOCK_SIZE (1<<16) /* the size *has* to be always *smaller* */
+ struct {
+ unsigned short :8;
+ unsigned short gather :8;
+ } scatter;
+ } count;
+ LONGV address;
+ unsigned short link :1;
+ unsigned short :3;
+ unsigned short transfer_type :2;
+ /* 0x0 is reserved */
+ #define SHORT_TREANSFER 0x1
+ #define LONG_TRANSFER 0x2
+ #define SCATTER_GATTER_LIST_IN_SHORT_IO 0x3
+ unsigned short memory_type :2;
+ #define NORMAL_TYPE 0x0
+ #define BLOCK_MODE 0x1
+ /* 0x2 is reserved */
+ /* 0x3 is reserved */
+ unsigned short address_modifier :8;
+}sg_list_element_t;
+
+typedef sg_list_element_t * scatter_gather_list_t;
+
+#define MAX_SG_ELEMENTS 64
+
+struct m328_sg {
+ struct m328_sg *up;
+ int elements;
+ int level;
+ struct m328_sg *down[MAX_SG_ELEMENTS];
+ sg_list_element_t list[MAX_SG_ELEMENTS];
+};
+
+typedef struct m328_sg *M328_SG;
+
+typedef struct {
+ struct scsi_xfer *xs;
+ M328_SG top_sg_list;
+} M328_CMD;
+/**************** END Scater/Gather Stuff *******************/
/**************** Host Semaphore Block (HSB) *******************/
@@ -388,6 +435,7 @@ typedef struct csb
#define M_ADR_TRANS 0x0C00 /* transfer type */
#define M_ADR_MEMT 0x0300 /* memory type */
#define M_ADR_MOD 0x00FF /* VME address modifier */
+#define M_ADR_SG_LINK 0x8000 /* Scatter/Gather Link bit */
/*
* defines for IOPB Unit Address on SCSI Bus
@@ -412,8 +460,7 @@ typedef struct short_iopb
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 LONGV iopb_SGTTL; /* IOPB Scatter/Gather Total Transfer len */
volatile u_short iopb_RES4; /* IOPB Reserved word */
volatile u_short iopb_UNIT; /* IOPB Unit address on SCSI bus */
} M328_short_IOPB;
@@ -431,8 +478,7 @@ typedef struct iopb
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 LONGV iopb_SGTTL; /* IOPB Scatter/Gather Total Transfer len */
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 */
@@ -596,6 +642,7 @@ typedef struct ipsg
#define CNTR_ISSUE_ABORT 0x4E /* An abort has been issued */
#define CNTR_DOWNLOAD_FIRMWARE 0x4F /* Download firmware (COUGAR) */
+
/*
* Memory types
*/
@@ -692,4 +739,18 @@ typedef struct ipsg
#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)
+/*
+ * Scatter/gather functions
+ */
+
+M328_SG vs_alloc_scatter_gather __P((void));
+void vs_dealloc_scatter_gather __P((M328_SG sg));
+void vs_link_scatter_gather_element __P((sg_list_element_t *element,
+ register vm_offset_t phys_add,
+ register int len));
+void vs_link_scatter_gather_list __P((sg_list_element_t *list,
+ register vm_offset_t phys_add,
+ register int elements));
+M328_SG vs_build_memory_structure __P((struct scsi_xfer *xs, M328_IOPB *iopb));
+
#endif /* _M328REG_H_ */