summaryrefslogtreecommitdiff
path: root/sys/arch/mvme68k/dev
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-03-01 21:40:50 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-03-01 21:40:50 +0000
commit59dcae1e0128e7bebf63bdf1d6cb852a0cf6a509 (patch)
treeb724b47073fb8d1491458c56d52cbdbd696e2c1a /sys/arch/mvme68k/dev
parenta1c26a0a8ac1138d2326c1b8cd8217a879778127 (diff)
Support for MVME165 board - code written in april 2006, eventually debugged
last month.
Diffstat (limited to 'sys/arch/mvme68k/dev')
-rw-r--r--sys/arch/mvme68k/dev/clock.c118
-rw-r--r--sys/arch/mvme68k/dev/dart.c999
-rw-r--r--sys/arch/mvme68k/dev/dart_lrc.c106
-rw-r--r--sys/arch/mvme68k/dev/dartreg.h155
-rw-r--r--sys/arch/mvme68k/dev/dartvar.h63
-rw-r--r--sys/arch/mvme68k/dev/lrc.c232
-rw-r--r--sys/arch/mvme68k/dev/lrcreg.h175
-rw-r--r--sys/arch/mvme68k/dev/nvram.c112
-rw-r--r--sys/arch/mvme68k/dev/nvramreg.h25
-rw-r--r--sys/arch/mvme68k/dev/vme.c42
10 files changed, 1945 insertions, 82 deletions
diff --git a/sys/arch/mvme68k/dev/clock.c b/sys/arch/mvme68k/dev/clock.c
index c3103cedcbc..92bdce49437 100644
--- a/sys/arch/mvme68k/dev/clock.c
+++ b/sys/arch/mvme68k/dev/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.14 2009/02/21 20:32:34 miod Exp $ */
+/* $OpenBSD: clock.c,v 1.15 2009/03/01 21:40:49 miod Exp $ */
/*
* Copyright (c) 1995 Theo de Raadt
@@ -72,10 +72,17 @@
#include <machine/autoconf.h>
#include <machine/cpu.h>
-#include "pcc.h"
+#include "lrc.h"
#include "mc.h"
+#include "pcc.h"
#include "pcctwo.h"
+#if NLRC > 0
+#include <mvme68k/dev/lrcreg.h>
+#endif
+#if NMC > 0
+#include <mvme68k/dev/mcreg.h>
+#endif
#if NPCC > 0
#include <mvme68k/dev/pccreg.h>
#endif
@@ -84,9 +91,6 @@
#include <mvme68k/dev/vme.h>
extern struct vme2reg *sys_vme2;
#endif
-#if NMC > 0
-#include <mvme68k/dev/mcreg.h>
-#endif
/*
* Statistics clock interval and variance, in usec. Variance must be a
@@ -154,12 +158,13 @@ clockattach(parent, self, args)
clockbus = ca->ca_bustype;
switch (ca->ca_bustype) {
-#if NPCC > 0
- case BUS_PCC:
- prof_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
- stat_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
- pccintr_establish(PCCV_TIMER1, &sc->sc_profih, "clock");
- pccintr_establish(PCCV_TIMER2, &sc->sc_statih, "stat");
+#if NLRC > 0
+ case BUS_LRC:
+ /*
+ * XXX once we have dynamic ipl levels, put clock at ipl 6,
+ * move it to timer1, then use timer2/ipl5 for statclock.
+ */
+ lrcintr_establish(LRCVEC_TIMER2, &sc->sc_profih, "clock");
break;
#endif
#if NMC > 0
@@ -170,6 +175,14 @@ clockattach(parent, self, args)
mcintr_establish(MCV_TIMER2, &sc->sc_statih, "stat");
break;
#endif
+#if NPCC > 0
+ case BUS_PCC:
+ prof_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
+ stat_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
+ pccintr_establish(PCCV_TIMER1, &sc->sc_profih, "clock");
+ pccintr_establish(PCCV_TIMER2, &sc->sc_statih, "stat");
+ break;
+#endif
#if NPCCTWO > 0
case BUS_PCCTWO:
prof_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
@@ -191,9 +204,9 @@ clockintr(arg)
void *arg;
{
switch (clockbus) {
-#if NPCC > 0
- case BUS_PCC:
- sys_pcc->pcc_t1irq = prof_reset;
+#if NLRC > 0
+ case BUS_LRC:
+ /* nothing to do */
break;
#endif
#if NMC > 0
@@ -201,6 +214,11 @@ clockintr(arg)
sys_mc->mc_t1irq = prof_reset;
break;
#endif
+#if NPCC > 0
+ case BUS_PCC:
+ sys_pcc->pcc_t1irq = prof_reset;
+ break;
+#endif
#if NPCCTWO > 0
case BUS_PCCTWO:
sys_pcc2->pcc2_t1irq = prof_reset;
@@ -239,17 +257,16 @@ cpu_initclocks()
while (statvar > minint)
statvar >>= 1;
switch (clockbus) {
-#if NPCC > 0
- case BUS_PCC:
- sys_pcc->pcc_t1pload = pcc_timer_us2lim(tick);
- sys_pcc->pcc_t1ctl = PCC_TIMERCLEAR;
- sys_pcc->pcc_t1ctl = PCC_TIMERSTART;
- sys_pcc->pcc_t1irq = prof_reset;
-
- sys_pcc->pcc_t2pload = pcc_timer_us2lim(statint);
- sys_pcc->pcc_t2ctl = PCC_TIMERCLEAR;
- sys_pcc->pcc_t2ctl = PCC_TIMERSTART;
- sys_pcc->pcc_t2irq = stat_reset;
+#if NLRC > 0
+ case BUS_LRC:
+ profhz = stathz = 0;
+
+ sys_lrc->lrc_tcr0 = 0;
+ sys_lrc->lrc_tcr1 = 0;
+ /* profclock as timer 2 */
+ sys_lrc->lrc_t2base = tick + 1;
+ sys_lrc->lrc_tcr2 = TCR_TLD2; /* reset to one */
+ sys_lrc->lrc_tcr2 = TCR_TEN2 | TCR_TCYC2 | TCR_T2IE;
break;
#endif
#if NMC > 0
@@ -269,6 +286,19 @@ cpu_initclocks()
sys_mc->mc_t2irq = stat_reset;
break;
#endif
+#if NPCC > 0
+ case BUS_PCC:
+ sys_pcc->pcc_t1pload = pcc_timer_us2lim(tick);
+ sys_pcc->pcc_t1ctl = PCC_TIMERCLEAR;
+ sys_pcc->pcc_t1ctl = PCC_TIMERSTART;
+ sys_pcc->pcc_t1irq = prof_reset;
+
+ sys_pcc->pcc_t2pload = pcc_timer_us2lim(statint);
+ sys_pcc->pcc_t2ctl = PCC_TIMERCLEAR;
+ sys_pcc->pcc_t2ctl = PCC_TIMERSTART;
+ sys_pcc->pcc_t2irq = stat_reset;
+ break;
+#endif
#if NPCCTWO > 0
case BUS_PCCTWO:
/* profclock */
@@ -375,16 +405,24 @@ delay(us)
#endif
switch (clockbus) {
-#if NPCC > 0
- case BUS_PCC:
- /*
- * XXX MVME147 doesn't have a 3rd free-running timer,
- * so we use a stupid loop. Fix the code to watch t1:
- * the profiling timer.
- */
- c = 2 * us;
- while (--c > 0)
+#if NLRC > 0
+ case BUS_LRC:
+ {
+ struct lrcreg *lrc;
+
+ if (sys_lrc != NULL)
+ lrc = sys_lrc;
+ else
+ lrc = (struct lrcreg *)IIOV(0xfff90000);
+
+ /* use timer0 and wait for it to wrap */
+ lrc->lrc_t0base = us + 1;
+ lrc->lrc_tcr0 = TCR_TLD0; /* reset to one */
+ lrc->lrc_stat = STAT_TMR0; /* clear latch */
+ lrc->lrc_tcr0 = TCR_TEN0;
+ while ((lrc->lrc_stat & STAT_TMR0) == 0)
;
+ }
break;
#endif
#if NMC > 0
@@ -411,6 +449,18 @@ delay(us)
}
break;
#endif
+#if NPCC > 0
+ case BUS_PCC:
+ /*
+ * XXX MVME147 doesn't have a 3rd free-running timer,
+ * so we use a stupid loop. Fix the code to watch t1:
+ * the profiling timer.
+ */
+ c = 2 * us;
+ while (--c > 0)
+ ;
+ break;
+#endif
#if NPCCTWO > 0
case BUS_PCCTWO:
/*
diff --git a/sys/arch/mvme68k/dev/dart.c b/sys/arch/mvme68k/dev/dart.c
new file mode 100644
index 00000000000..c79dacceaad
--- /dev/null
+++ b/sys/arch/mvme68k/dev/dart.c
@@ -0,0 +1,999 @@
+/* $OpenBSD: dart.c,v 1.1 2009/03/01 21:40:49 miod Exp $ */
+
+/*
+ * 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/ioctl.h>
+#include <sys/proc.h>
+#include <sys/tty.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/syslog.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+#include <machine/conf.h>
+#include <machine/cpu.h>
+
+#include <dev/cons.h>
+
+#include <mvme68k/dev/dartreg.h>
+#include <mvme68k/dev/dartvar.h>
+
+#ifdef DDB
+#include <ddb/db_var.h>
+#endif
+
+struct cfdriver dart_cd = {
+ NULL, "dart", DV_TTY
+};
+
+/* console is on the first port */
+#define CONS_PORT A_PORT
+struct dart_sv_reg dartcn_sv;
+
+/* prototypes */
+cons_decl(dart);
+int dart_speed(int);
+struct tty *darttty(dev_t);
+void dartstart(struct tty *);
+int dartmctl(struct dartsoftc *, int, int, int);
+int dartparam(struct tty *, struct termios *);
+void dartmodemtrans(struct dartsoftc *, unsigned int, unsigned int);
+void dartrint(struct dartsoftc *, int);
+void dartxint(struct dartsoftc *, int);
+
+/*
+ * DUART registers are mapped as the least-significant byte of 32-bit
+ * addresses. The following macros hide this.
+ */
+
+#define dart_read(sc, reg) \
+ bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, 3 + ((reg) << 2))
+#define dart_write(sc, reg, val) \
+ bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, 3 + ((reg) << 2), (val))
+
+#define DART_CHIP(dev) (minor(dev) >> 1)
+#define DART_PORT(dev) (minor(dev) & 1)
+
+void
+dart_common_attach(struct dartsoftc *sc)
+{
+ if (sc->sc_console) {
+ sc->sc_sv_reg = &dartcn_sv;
+
+ if (A_PORT != CONS_PORT) {
+ sc->sc_sv_reg->sv_mr1[A_PORT] = PARDIS | RXRTS | CL8;
+ sc->sc_sv_reg->sv_mr2[A_PORT] = /* TXCTS | */ SB1;
+ sc->sc_sv_reg->sv_csr[A_PORT] = BD9600;
+ sc->sc_sv_reg->sv_cr[A_PORT] = TXEN | RXEN;
+ sc->sc_sv_reg->sv_opr |= OPDTRA | OPRTSA;
+ } else {
+ sc->sc_sv_reg->sv_mr1[B_PORT] = PARDIS | RXRTS | CL8;
+ sc->sc_sv_reg->sv_mr2[B_PORT] = /* TXCTS | */ SB1;
+ sc->sc_sv_reg->sv_csr[B_PORT] = BD9600;
+ sc->sc_sv_reg->sv_cr[B_PORT] = TXEN | RXEN;
+ sc->sc_sv_reg->sv_opr |= OPDTRB | OPRTSB;
+ }
+ } else {
+ sc->sc_sv_reg = &sc->sc_sv_reg_storage;
+
+ sc->sc_sv_reg->sv_mr1[A_PORT] = PARDIS | RXRTS | CL8;
+ sc->sc_sv_reg->sv_mr2[A_PORT] = /* TXCTS | */ SB1;
+ sc->sc_sv_reg->sv_csr[A_PORT] = BD9600;
+ sc->sc_sv_reg->sv_cr[A_PORT] = TXEN | RXEN;
+
+ sc->sc_sv_reg->sv_mr1[B_PORT] = PARDIS | RXRTS | CL8;
+ sc->sc_sv_reg->sv_mr2[B_PORT] = /* TXCTS | */ SB1;
+ sc->sc_sv_reg->sv_csr[B_PORT] = BD9600;
+ sc->sc_sv_reg->sv_cr[B_PORT] = TXEN | RXEN;
+
+ sc->sc_sv_reg->sv_opr = OPDTRA | OPRTSA | OPDTRB | OPRTSB;
+
+ /* Start out with Tx and RX interrupts disabled */
+ /* Enable input port change interrupt */
+ sc->sc_sv_reg->sv_imr = IIPCHG;
+ }
+
+ /* reset port a */
+ if (sc->sc_console == 0 || CONS_PORT != A_PORT) {
+ dart_write(sc, DART_CRA, RXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRA, TXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRA, ERRRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRA, BRKINTRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRA, MRRESET | TXDIS | RXDIS);
+#if 0
+ DELAY_CR;
+#endif
+
+ dart_write(sc, DART_MR1A, sc->sc_sv_reg->sv_mr1[A_PORT]);
+ dart_write(sc, DART_MR2A, sc->sc_sv_reg->sv_mr2[A_PORT]);
+ dart_write(sc, DART_CSRA, sc->sc_sv_reg->sv_csr[A_PORT]);
+ dart_write(sc, DART_CRA, sc->sc_sv_reg->sv_cr[A_PORT]);
+ }
+
+ /* reset port b */
+ if (sc->sc_console == 0 || CONS_PORT != B_PORT) {
+ dart_write(sc, DART_CRB, RXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRB, TXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRB, ERRRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRB, BRKINTRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_write(sc, DART_CRB, MRRESET | TXDIS | RXDIS);
+#if 0
+ DELAY_CR;
+#endif
+
+ dart_write(sc, DART_MR1B, sc->sc_sv_reg->sv_mr1[B_PORT]);
+ dart_write(sc, DART_MR2B, sc->sc_sv_reg->sv_mr2[B_PORT]);
+ dart_write(sc, DART_CSRB, sc->sc_sv_reg->sv_csr[B_PORT]);
+ dart_write(sc, DART_CRB, sc->sc_sv_reg->sv_cr[B_PORT]);
+ }
+
+ /* initialize common register of a DUART */
+ dart_write(sc, DART_OPRS, sc->sc_sv_reg->sv_opr);
+
+#if 0
+ dart_write(sc, DART_CTUR, SLCTIM >> 8);
+ dart_write(sc, DART_CTLR, SLCTIM & 0xff);
+ dart_write(sc, DART_ACR, BDSET2 | CCLK16 | IPDCDIB | IPDCDIA);
+#endif
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+ dart_write(sc, DART_OPCR, OPSET);
+
+ if (sc->sc_vec != 0)
+ dart_write(sc, DART_IVR, sc->sc_vec);
+
+ sc->sc_dart[A_PORT].tty = sc->sc_dart[B_PORT].tty = NULL;
+ sc->sc_dart[A_PORT].dart_swflags = sc->sc_dart[B_PORT].dart_swflags = 0;
+ if (sc->sc_console)
+ sc->sc_dart[CONS_PORT].dart_swflags |= TIOCFLAG_SOFTCAR;
+
+ printf("\n");
+}
+
+/* speed tables */
+const struct dart_s {
+ int kspeed;
+ int dspeed;
+} dart_speeds[] = {
+ { B0, 0 }, /* 0 baud, special HUP condition */
+ { B50, NOBAUD }, /* 50 baud, not implemented */
+ { B75, BD75 }, /* 75 baud */
+ { B110, BD110 }, /* 110 baud */
+ { B134, BD134 }, /* 134.5 baud */
+ { B150, BD150 }, /* 150 baud */
+ { B200, NOBAUD }, /* 200 baud, not implemented */
+ { B300, BD300 }, /* 300 baud */
+ { B600, BD600 }, /* 600 baud */
+ { B1200, BD1200 }, /* 1200 baud */
+ { B1800, BD1800 }, /* 1800 baud */
+ { B2400, BD2400 }, /* 2400 baud */
+ { B4800, BD4800 }, /* 4800 baud */
+ { B9600, BD9600 }, /* 9600 baud */
+ { B19200, BD19200 }, /* 19200 baud */
+ { -1, NOBAUD }, /* anything more is uncivilized */
+};
+
+int
+dart_speed(int speed)
+{
+ const struct dart_s *ds;
+
+ for (ds = dart_speeds; ds->kspeed != -1; ds++)
+ if (ds->kspeed == speed)
+ return ds->dspeed;
+
+ return NOBAUD;
+}
+
+struct tty *
+darttty(dev_t dev)
+{
+ u_int port, chip;
+ struct dartsoftc *sc;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ if (dart_cd.cd_ndevs <= chip || port >= NDARTPORTS)
+ return (NULL);
+
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ if (sc == NULL)
+ return (NULL);
+
+ return sc->sc_dart[port].tty;
+}
+
+void
+dartstart(struct tty *tp)
+{
+ struct dartsoftc *sc;
+ dev_t dev;
+ int s;
+ u_int port, chip;
+ int c, tries;
+ bus_addr_t ptaddr;
+
+ if ((tp->t_state & TS_ISOPEN) == 0)
+ return;
+
+ dev = tp->t_dev;
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+
+ s = spltty();
+
+ if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
+ goto bail;
+
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t)&tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ if (tp->t_outq.c_cc == 0)
+ goto bail;
+ }
+
+ tp->t_state |= TS_BUSY;
+ while (tp->t_outq.c_cc != 0) {
+
+ /* load transmitter until it is full */
+ for (tries = 10000; tries != 0; tries --)
+ if (dart_read(sc, ptaddr + DART_SRA) & TXRDY)
+ break;
+
+ if (tries == 0) {
+ timeout_add(&tp->t_rstrt_to, 1);
+ tp->t_state |= TS_TIMEOUT;
+ break;
+ } else {
+ c = getc(&tp->t_outq);
+
+ dart_write(sc, ptaddr + DART_TBA, c & 0xff);
+
+ sc->sc_sv_reg->sv_imr |=
+ port == A_PORT ? ITXRDYA : ITXRDYB;
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+ }
+ }
+ tp->t_state &= ~TS_BUSY;
+
+bail:
+ splx(s);
+}
+
+int
+dartstop(struct tty *tp, int flag)
+{
+ int s;
+
+ s = spltty();
+ if (tp->t_state & TS_BUSY) {
+ if ((tp->t_state & TS_TTSTOP) == 0)
+ tp->t_state |= TS_FLUSH;
+ }
+ splx(s);
+
+ return 0;
+}
+
+/*
+ * To be called at spltty - tty already locked.
+ * Returns status of carrier.
+ */
+int
+dartmctl(struct dartsoftc *sc, int port, int flags, int how)
+{
+ int newflags, flagsmask;
+ struct dart_info *dart;
+ int s;
+
+ dart = &sc->sc_dart[port];
+
+ s = spltty();
+
+ flagsmask = port == A_PORT ? (OPDTRA | OPRTSA) : (OPDTRB | OPRTSB);
+ newflags = (flags & TIOCM_DTR ? (OPDTRA | OPDTRB) : 0) |
+ (flags & TIOCM_RTS ? (OPRTSA | OPRTSB) : 0);
+ newflags &= flagsmask; /* restrict to the port we are acting on */
+
+ switch (how) {
+ case DMSET:
+ dart_write(sc, DART_OPRS, newflags);
+ dart_write(sc, DART_OPRR, ~newflags);
+ /* only replace the sv_opr bits for the port we are acting on */
+ sc->sc_sv_reg->sv_opr &= ~flagsmask;
+ sc->sc_sv_reg->sv_opr |= newflags;
+ break;
+ case DMBIS:
+ dart_write(sc, DART_OPRS, newflags);
+ sc->sc_sv_reg->sv_opr |= newflags;
+ break;
+ case DMBIC:
+ dart_write(sc, DART_OPRR, newflags);
+ sc->sc_sv_reg->sv_opr &= ~newflags;
+ break;
+ case DMGET:
+ flags = 0;
+ if (port == A_PORT) {
+ if (sc->sc_sv_reg->sv_opr & OPDTRA)
+ flags |= TIOCM_DTR;
+ if (sc->sc_sv_reg->sv_opr & OPRTSA)
+ flags |= TIOCM_RTS;
+ } else {
+ if (sc->sc_sv_reg->sv_opr & OPDTRB)
+ flags |= TIOCM_DTR;
+ if (sc->sc_sv_reg->sv_opr & OPRTSB)
+ flags |= TIOCM_RTS;
+ }
+ break;
+ }
+
+ splx(s);
+ return (flags);
+}
+
+int
+dartioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ int error;
+ u_int port, chip;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+
+ tp = dart->tty;
+ if (tp == NULL)
+ 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:
+ case TIOCCBRK:
+ break;
+ case TIOCSDTR:
+ (void)dartmctl(sc, port, TIOCM_DTR | TIOCM_RTS, DMBIS);
+ break;
+ case TIOCCDTR:
+ (void)dartmctl(sc, port, TIOCM_DTR | TIOCM_RTS, DMBIC);
+ break;
+ case TIOCMSET:
+ (void)dartmctl(sc, port, *(int *) data, DMSET);
+ break;
+ case TIOCMBIS:
+ (void)dartmctl(sc, port, *(int *) data, DMBIS);
+ break;
+ case TIOCMBIC:
+ (void)dartmctl(sc, port, *(int *) data, DMBIC);
+ break;
+ case TIOCMGET:
+ *(int *)data = dartmctl(sc, port, 0, DMGET);
+ break;
+ case TIOCGFLAGS:
+ *(int *)data = dart->dart_swflags;
+ break;
+ case TIOCSFLAGS:
+ error = suser(p, 0);
+ 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);
+}
+
+int
+dartparam(struct tty *tp, struct termios *t)
+{
+ int flags;
+ u_int port, chip;
+ int speeds;
+ unsigned char mr1, mr2;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ dev_t dev;
+ bus_addr_t ptaddr;
+
+ dev = tp->t_dev;
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+
+ 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 */
+
+ if (sc->sc_console == 0 || CONS_PORT != port) {
+ if (port == A_PORT)
+ sc->sc_sv_reg->sv_imr &= ~(ITXRDYA | IRXRDYA);
+ else
+ sc->sc_sv_reg->sv_imr &= ~(ITXRDYB | IRXRDYB);
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+
+ /* hang up on zero baud rate */
+ if (tp->t_ispeed == 0) {
+ dartmctl(sc, port, HUPCL, DMSET);
+ return (0);
+ } else {
+ /* set baudrate */
+ speeds = dart_speed(tp->t_ispeed);
+ if (speeds == NOBAUD)
+ speeds = sc->sc_sv_reg->sv_csr[port];
+ dart_write(sc, ptaddr + DART_CSRA, speeds);
+ sc->sc_sv_reg->sv_csr[port] = speeds;
+ }
+
+ /* get saved mode registers and clear set up parameters */
+ mr1 = sc->sc_sv_reg->sv_mr1[port];
+ mr1 &= ~(CLMASK | PARTYPEMASK | PARMODEMASK);
+
+ mr2 = sc->sc_sv_reg->sv_mr2[port];
+ mr2 &= ~SBMASK;
+
+ /* set up character size */
+ switch (t->c_cflag & CSIZE) {
+ case CL8:
+ mr1 |= CL8;
+ break;
+ case CL7:
+ mr1 |= CL7;
+ break;
+ case CL6:
+ mr1 |= CL6;
+ break;
+ case CL5:
+ mr1 |= CL5;
+ break;
+ }
+
+ /* set up stop bits */
+ if (tp->t_ospeed == B110)
+ mr2 |= SB2;
+ else
+ mr2 |= SB1;
+
+ /* set up parity */
+ if (t->c_cflag & PARENB) {
+ mr1 |= PAREN;
+ if (t->c_cflag & PARODD)
+ mr1 |= ODDPAR;
+ else
+ mr1 |= EVENPAR;
+ } else
+ mr1 |= PARDIS;
+
+ if (sc->sc_sv_reg->sv_mr1[port] != mr1 ||
+ sc->sc_sv_reg->sv_mr2[port] != mr2) {
+ /* write mode registers to duart */
+ dart_write(sc, ptaddr + DART_CRA, MRRESET);
+ dart_write(sc, ptaddr + DART_MR1A, mr1);
+ dart_write(sc, ptaddr + DART_MR2A, mr2);
+
+ /* save changed mode registers */
+ sc->sc_sv_reg->sv_mr1[port] = mr1;
+ sc->sc_sv_reg->sv_mr2[port] = mr2;
+ }
+ }
+
+ /* enable transmitter? */
+ if (tp->t_state & TS_BUSY) {
+ sc->sc_sv_reg->sv_imr |= port == A_PORT ? ITXRDYA : ITXRDYB;
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+ }
+
+ /* re-enable the receiver */
+#if 0
+ DELAY_CR;
+#endif
+ sc->sc_sv_reg->sv_imr |= port == A_PORT ? IRXRDYA : IRXRDYB;
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+
+ return (0);
+}
+
+void
+dartmodemtrans(struct dartsoftc *sc, unsigned int ip, unsigned int ipcr)
+{
+ unsigned int dcdstate;
+ struct tty *tp;
+ int port;
+ struct dart_info *dart;
+
+ /* 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 {
+#ifdef DIAGNOSTIC
+ printf("dartmodemtrans: unknown transition ip=0x%x ipcr=0x%x\n",
+ ip, ipcr);
+#endif
+ return;
+ }
+
+ dart = &sc->sc_dart[port];
+ tp = dart->tty;
+ if (tp != NULL)
+ ttymodem(tp, dcdstate);
+}
+
+int
+dartopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+ int s;
+ u_int port, chip;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ struct tty *tp;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ if (dart_cd.cd_ndevs <= chip || port >= NDARTPORTS)
+ return (ENODEV);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ if (sc == NULL)
+ return (ENODEV);
+ dart = &sc->sc_dart[port];
+
+ s = spltty();
+ if (dart->tty != NULL)
+ tp = dart->tty;
+ else
+ tp = dart->tty = ttymalloc();
+
+ tp->t_oproc = dartstart;
+ tp->t_param = dartparam;
+ tp->t_dev = dev;
+
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+
+ if (tp->t_ispeed == 0) {
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = B9600;
+ if (sc->sc_console && port == CONS_PORT) {
+ /* console is 8N1 */
+ tp->t_cflag = (CREAD | CS8 | HUPCL);
+ } else {
+ tp->t_cflag = TTYDEF_CFLAG;
+ }
+ }
+
+ if (dart->dart_swflags & TIOCFLAG_CLOCAL)
+ tp->t_cflag |= CLOCAL;
+ if (dart->dart_swflags & TIOCFLAG_CRTSCTS)
+ tp->t_cflag |= CRTSCTS;
+ if (dart->dart_swflags & TIOCFLAG_MDMBUF)
+ tp->t_cflag |= MDMBUF;
+
+ dartparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+
+ (void)dartmctl(sc, port, TIOCM_DTR | TIOCM_RTS, DMSET);
+ tp->t_state |= TS_CARR_ON;
+ } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
+ splx(s);
+ return (EBUSY);
+ }
+
+ /*
+ * Reset the tty pointer, as there could have been a dialout
+ * use of the tty with a dialin open waiting.
+ */
+ tp->t_dev = dev;
+ splx(s);
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+int
+dartclose(dev_t dev, int flag, int mode, struct proc *p)
+{
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+ u_int port, chip;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+
+ tp = dart->tty;
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ ttyclose(tp);
+
+ return (0);
+}
+
+int
+dartread(dev_t dev, struct uio *uio, int flag)
+{
+ u_int port, chip;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+
+ tp = dart->tty;
+ if (tp == NULL)
+ return (ENXIO);
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+dartwrite(dev_t dev, struct uio *uio, int flag)
+{
+ u_int port, chip;
+ struct tty *tp;
+ struct dart_info *dart;
+ struct dartsoftc *sc;
+
+ chip = DART_CHIP(dev);
+ port = DART_PORT(dev);
+ sc = (struct dartsoftc *)dart_cd.cd_devs[chip];
+ dart = &sc->sc_dart[port];
+
+ tp = dart->tty;
+ if (tp == NULL)
+ return (ENXIO);
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+void
+dartrint(struct dartsoftc *sc, int port)
+{
+ struct tty *tp;
+ unsigned char data, sr;
+ struct dart_info *dart;
+ bus_addr_t ptaddr;
+
+ dart = &sc->sc_dart[port];
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+ tp = dart->tty;
+
+ /* read status reg */
+ while ((sr = dart_read(sc, ptaddr + DART_SRA)) & RXRDY) {
+ /* read data and reset receiver */
+ data = dart_read(sc, ptaddr + DART_RBA);
+
+ if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0 &&
+ (sc->sc_console == 0 || CONS_PORT != port)) {
+ return;
+ }
+
+ if (sr & RBRK) {
+ /* clear break state */
+ dart_write(sc, ptaddr + DART_CRA, BRKINTRESET);
+ DELAY_CR;
+ dart_write(sc, ptaddr + DART_CRA, ERRRESET);
+
+#if defined(DDB)
+ if (db_console != 0 &&
+ sc->sc_console && port == CONS_PORT)
+ Debugger();
+#endif
+ } else {
+ if (sr & (FRERR | PERR | ROVRN)) { /* errors */
+ if (sr & ROVRN)
+ log(LOG_WARNING, "%s port %c: "
+ "receiver overrun\n",
+ sc->sc_dev.dv_xname, 'A' + port);
+ if (sr & FRERR)
+ log(LOG_WARNING, "%s port %c: "
+ "framing error\n",
+ sc->sc_dev.dv_xname, 'A' + port);
+ if (sr & PERR)
+ log(LOG_WARNING, "%s port %c: "
+ "parity error\n",
+ sc->sc_dev.dv_xname, 'A' + port);
+ /* clear error state */
+ dart_write(sc, ptaddr + DART_CRA, ERRRESET);
+ } else {
+ /* no errors */
+ (*linesw[tp->t_line].l_rint)(data,tp);
+ }
+ }
+ }
+}
+
+void
+dartxint(struct dartsoftc *sc, int port)
+{
+ struct tty *tp;
+ struct dart_info *dart;
+
+ dart = &sc->sc_dart[port];
+ tp = dart->tty;
+
+ if ((tp->t_state & (TS_ISOPEN|TS_WOPEN))==0)
+ goto out;
+
+ if (tp->t_state & TS_BUSY) {
+ tp->t_state &= ~(TS_BUSY | TS_FLUSH);
+ dartstart(tp);
+ if (tp->t_state & TS_BUSY) {
+ /* do not disable transmitter, yet */
+ return;
+ }
+ }
+out:
+
+ /* disable transmitter */
+ sc->sc_sv_reg->sv_imr &= port == A_PORT ? ~ITXRDYA : ~ITXRDYB;
+ dart_write(sc, DART_IMR, sc->sc_sv_reg->sv_imr);
+}
+
+int
+dartintr(void *arg)
+{
+ struct dartsoftc *sc = arg;
+ unsigned char isr, imr;
+ int port;
+
+ /* read interrupt status register and mask with imr */
+ isr = dart_read(sc, DART_ISR);
+ imr = sc->sc_sv_reg->sv_imr;
+
+ if ((isr & imr) == 0) {
+ /*
+ * We got an interrupt on a disabled condition (such as TX
+ * ready change on a disabled port). This should not happen,
+ * but we have to claim the interrupt anyway.
+ */
+#ifdef DIAGNOSTIC
+ printf("%s: spurious interrupt, isr %x imr %x\n",
+ sc->sc_dev.dv_xname, isr, imr);
+#endif
+ return (1);
+ }
+ isr &= imr;
+
+ if (isr & IIPCHG) {
+ unsigned int ip, ipcr;
+
+ ip = dart_read(sc, DART_IP);
+ ipcr = dart_read(sc, DART_IPCR);
+ dartmodemtrans(sc, ip, ipcr);
+ return (1);
+ }
+
+ if (isr & (IRXRDYA | ITXRDYA))
+ port = 0;
+#ifdef DIAGNOSTIC
+ else if ((isr & (IRXRDYB | ITXRDYB)) == 0) {
+ printf("%s: spurious interrupt, isr %x\n",
+ sc->sc_dev.dv_xname, isr);
+ return (1); /* claim it anyway */
+ }
+#endif
+ else
+ port = 1;
+
+ if (isr & (IRXRDYA | IRXRDYB))
+ dartrint(sc, port);
+ if (isr & (ITXRDYA | ITXRDYB))
+ dartxint(sc, port);
+ if (isr & (port == A_PORT ? IBRKA : IBRKB))
+ dart_write(sc, port == A_PORT ? DART_CRA : DART_CRB,
+ BRKINTRESET);
+
+ return (1);
+}
+
+/*
+ * Console interface routines.
+ */
+
+#define dart_cnread(reg) \
+ *(volatile u_int8_t *)(IIOV(CONSOLE_DART_BASE) + 3 + ((reg) << 2))
+#define dart_cnwrite(reg, val) \
+ *(volatile u_int8_t *)(IIOV(CONSOLE_DART_BASE) + 3 + ((reg) << 2)) = (val)
+
+void
+dartcnprobe(struct consdev *cp)
+{
+ int maj;
+
+ if (cputyp != CPU_165)
+ return;
+
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == dartopen)
+ break;
+ if (maj == nchrdev)
+ return;
+
+ cp->cn_dev = makedev(maj, CONS_PORT);
+ cp->cn_pri = CN_LOWPRI;
+}
+
+void
+dartcninit(cp)
+ struct consdev *cp;
+{
+ dartcn_sv.sv_mr1[CONS_PORT] = PARDIS | RXRTS | CL8;
+ dartcn_sv.sv_mr2[CONS_PORT] = /* TXCTS | */ SB1;
+ dartcn_sv.sv_csr[CONS_PORT] = BD9600;
+ dartcn_sv.sv_cr[CONS_PORT] = TXEN | RXEN;
+ dartcn_sv.sv_opr = CONS_PORT == A_PORT ? (OPDTRA | OPRTSA) :
+ (OPDTRB | OPRTSB);
+ dartcn_sv.sv_imr = IIPCHG;
+
+ dart_cnwrite(DART_CRA, RXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_cnwrite(DART_CRA, TXRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_cnwrite(DART_CRA, ERRRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_cnwrite(DART_CRA, BRKINTRESET | TXDIS | RXDIS);
+ DELAY_CR;
+ dart_cnwrite(DART_CRA, MRRESET | TXDIS | RXDIS);
+ DELAY_CR;
+
+ dart_cnwrite(DART_MR1A, dartcn_sv.sv_mr1[CONS_PORT]);
+ dart_cnwrite(DART_MR2A, dartcn_sv.sv_mr2[CONS_PORT]);
+ dart_cnwrite(DART_CSRA, dartcn_sv.sv_csr[CONS_PORT]);
+ dart_cnwrite(DART_CRA, dartcn_sv.sv_cr[CONS_PORT]);
+
+ dart_cnwrite(DART_OPRS, dartcn_sv.sv_opr);
+
+ dart_cnwrite(DART_IMR, dartcn_sv.sv_imr);
+}
+
+void
+dartcnputc(dev_t dev, int c)
+{
+ int s;
+ u_int port;
+ bus_addr_t ptaddr;
+
+ port = CONS_PORT;
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+
+ s = spltty();
+
+ /* inhibit interrupts on the chip */
+ dart_cnwrite(DART_IMR, dartcn_sv.sv_imr &
+ (CONS_PORT == A_PORT ? ~ITXRDYA : ~ITXRDYB));
+ /* make sure transmitter is enabled */
+#if 0
+ DELAY_CR;
+#endif
+ dart_cnwrite(ptaddr + DART_CRA, TXEN);
+
+ while ((dart_cnread(ptaddr + DART_SRA) & TXRDY) == 0)
+ ;
+ dart_cnwrite(ptaddr + DART_TBA, c);
+
+ /* wait for transmitter to empty */
+ while ((dart_cnread(ptaddr + DART_SRA) & TXEMT) == 0)
+ ;
+
+ /* restore the previous state */
+ dart_cnwrite(DART_IMR, dartcn_sv.sv_imr);
+#if 0
+ DELAY_CR;
+#endif
+ dart_cnwrite(ptaddr + DART_CRA, dartcn_sv.sv_cr[0]);
+
+ splx(s);
+}
+
+int
+dartcngetc(dev_t dev)
+{
+ unsigned char sr; /* status reg of port a/b */
+ u_char c; /* received character */
+ int s;
+ u_int port;
+ bus_addr_t ptaddr;
+
+ port = CONS_PORT;
+ ptaddr = port == A_PORT ? DART_A_BASE : DART_B_BASE;
+
+ s = spltty();
+
+ /* enable receiver */
+ dart_cnwrite(ptaddr + DART_CRA, RXEN);
+
+ for (;;) {
+ /* read status reg */
+ sr = dart_cnread(ptaddr + DART_SRA);
+
+ /* receiver interrupt handler*/
+ if (sr & RXRDY) {
+ /* read character from port */
+ c = dart_cnread(ptaddr + DART_RBA);
+
+ /* check break condition */
+ if (sr & RBRK) {
+ /* clear break state */
+ dart_cnwrite(ptaddr + DART_CRA, BRKINTRESET);
+ DELAY_CR;
+ dart_cnwrite(ptaddr + DART_CRA, ERRRESET);
+ break;
+ }
+
+ if (sr & (FRERR | PERR | ROVRN)) {
+ /* clear error state */
+ dart_cnwrite(ptaddr + DART_CRA, ERRRESET);
+ } else {
+ break;
+ }
+ }
+ }
+ splx(s);
+
+ return ((int)c);
+}
diff --git a/sys/arch/mvme68k/dev/dart_lrc.c b/sys/arch/mvme68k/dev/dart_lrc.c
new file mode 100644
index 00000000000..576af188e1a
--- /dev/null
+++ b/sys/arch/mvme68k/dev/dart_lrc.c
@@ -0,0 +1,106 @@
+/* $OpenBSD: dart_lrc.c,v 1.1 2009/03/01 21:40:49 miod Exp $ */
+/*
+ * Copyright (c) 2006, 2009, Miodrag Vallat
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+
+#include <mvme68k/dev/lrcreg.h>
+
+#include <mvme68k/dev/dartreg.h>
+#include <mvme68k/dev/dartvar.h>
+
+int dart_lrc_match(struct device *parent, void *self, void *aux);
+void dart_lrc_attach(struct device *parent, struct device *self, void *aux);
+
+struct cfattach dartlrc_ca = {
+ sizeof(struct dartsoftc), dart_lrc_match, dart_lrc_attach
+};
+
+int
+dart_lrc_match(struct device *parent, void *cf, void *aux)
+{
+ struct confargs *ca = aux;
+#if 0
+ bus_space_handle_t ioh;
+ int rc;
+#endif
+
+ if (cputyp != CPU_165)
+ return (0);
+
+ /*
+ * We do not accept empty locators here...
+ */
+ if (ca->ca_paddr != CONSOLE_DART_BASE)
+ return (0);
+
+#if 0 /* overkill, this is the console so if we've run so far, it exists */
+ if (bus_space_map(ca->ca_iot, ca->ca_paddr, DART_SIZE, 0, &ioh) != 0)
+ return (0);
+ rc = badvaddr((vaddr_t)bus_space_vaddr(ca->ca_iot, ioh) + 3, 1);
+ bus_space_unmap(ca->ca_iot, ca->ca_paddr, DART_SIZE);
+
+ return (rc == 0);
+#else
+ return (1);
+#endif
+}
+
+void
+dart_lrc_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct dartsoftc *sc = (struct dartsoftc *)self;
+ struct confargs *ca = aux;
+ bus_space_handle_t ioh;
+
+ if (ca->ca_ipl < 0)
+ ca->ca_ipl = IPL_TTY;
+
+ sc->sc_iot = ca->ca_iot;
+ if (bus_space_map(sc->sc_iot, ca->ca_paddr, DART_SIZE, 0, &ioh) != 0) {
+ printf(": can't map registers!\n");
+ return;
+ }
+ sc->sc_ioh = ioh;
+
+ sc->sc_console = 1; /* there can't be any other */
+ printf(": console");
+
+ /* enable interrupts */
+ sc->sc_ih.ih_fn = dartintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_wantframe = 0;
+ sc->sc_ih.ih_ipl = ca->ca_ipl;
+
+ lrcintr_establish(LRCVEC_DART, &sc->sc_ih, self->dv_xname);
+
+ sc->sc_vec = LRC_VECBASE + LRCVEC_DART;
+ dart_common_attach(sc);
+}
diff --git a/sys/arch/mvme68k/dev/dartreg.h b/sys/arch/mvme68k/dev/dartreg.h
new file mode 100644
index 00000000000..bc364589ae0
--- /dev/null
+++ b/sys/arch/mvme68k/dev/dartreg.h
@@ -0,0 +1,155 @@
+/* $OpenBSD: dartreg.h,v 1.1 2009/03/01 21:40:49 miod Exp $ */
+
+#define CONSOLE_DART_BASE 0xfffd0000 /* on MVME165 */
+
+#define MAXPORTS 2 /* max count of PORTS/DUART */
+
+#define A_PORT 0
+#define B_PORT 1
+
+/* the access to the same command register must be delayed,
+ because the chip has some hardware problems in this case */
+#define DELAY_CR delay(2)
+
+/*********************** MC68681 DEFINITIONS ************************/
+
+/* 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 */
+
+/* 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 */
+
+/*
+ * MC68681 hardware registers.
+ */
+
+#define DART_MR1A 0x00 /* RW: mode register A */
+#define DART_MR2A 0x00 /* RW: mode register A */
+#define DART_SRA 0x01 /* R: status register A */
+#define DART_CSRA 0x01 /* W: clock select register A */
+#define DART_CRA 0x02 /* W: command register A */
+#define DART_RBA 0x03 /* R: receiver buffer A */
+#define DART_TBA 0x03 /* W: transmit buffer A */
+#define DART_IPCR 0x04 /* R: input port change register */
+#define DART_ACR 0x04 /* W: auxiliary control register */
+#define DART_ISR 0x05 /* R: interrupt status register */
+#define DART_IMR 0x05 /* W: interrupt mask register */
+#define DART_CUR 0x06 /* R: count upper register */
+#define DART_CTUR 0x06 /* W: counter/timer upper register */
+#define DART_CLR 0x07 /* R: count lower register */
+#define DART_CTLR 0x07 /* W: counter/timer lower register */
+#define DART_MR1B 0x08 /* RW: mode register B */
+#define DART_MR2B 0x08 /* RW: mode register B */
+#define DART_SRB 0x09 /* R: status register B */
+#define DART_CSRB 0x09 /* W: clock select register B */
+#define DART_CRB 0x0a /* W: command register B */
+#define DART_RBB 0x0b /* R: receiver buffer B */
+#define DART_TBB 0x0b /* W: transmit buffer B */
+#define DART_IVR 0x0c /* RW: interrupt vector register */
+#define DART_IP 0x0d /* R: input port (unlatched) */
+#define DART_OPCR 0x0d /* W: output port configuration register */
+#define DART_CTSTART 0x0e /* R: start counter command */
+#define DART_OPRS 0x0e /* W: output port bit set */
+#define DART_CTSTOP 0x0f /* R: stop counter command */
+#define DART_OPRR 0x0f /* W: output port bit reset */
+
+#define DART_A_BASE 0x00
+#define DART_B_BASE 0x08
diff --git a/sys/arch/mvme68k/dev/dartvar.h b/sys/arch/mvme68k/dev/dartvar.h
new file mode 100644
index 00000000000..78a28fac00b
--- /dev/null
+++ b/sys/arch/mvme68k/dev/dartvar.h
@@ -0,0 +1,63 @@
+/* $OpenBSD: dartvar.h,v 1.1 2009/03/01 21:40:49 miod Exp $ */
+
+/*
+ * 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.
+ */
+
+#define NDARTPORTS 2 /* Number of ports */
+
+struct dart_info {
+ struct tty *tty;
+ u_char dart_swflags;
+};
+
+/* saved registers */
+struct dart_sv_reg {
+ u_int8_t sv_mr1[NDARTPORTS];
+ u_int8_t sv_mr2[NDARTPORTS];
+ u_int8_t sv_csr[NDARTPORTS];
+ u_int8_t sv_cr[NDARTPORTS];
+ u_int8_t sv_opr;
+ u_int8_t sv_imr;
+};
+
+struct dartsoftc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ struct intrhand sc_ih;
+
+ int sc_console;
+ int sc_vec;
+
+ struct dart_sv_reg *sc_sv_reg;
+ struct dart_sv_reg sc_sv_reg_storage;
+ struct dart_info sc_dart[NDARTPORTS];
+};
+
+void dart_common_attach(struct dartsoftc *);
+int dartintr(void *);
+
+#define DART_SIZE 0x40
diff --git a/sys/arch/mvme68k/dev/lrc.c b/sys/arch/mvme68k/dev/lrc.c
new file mode 100644
index 00000000000..05aa7417aea
--- /dev/null
+++ b/sys/arch/mvme68k/dev/lrc.c
@@ -0,0 +1,232 @@
+/* $OpenBSD: lrc.c,v 1.1 2009/03/01 21:40:49 miod Exp $ */
+
+/*
+ * Copyright (c) 2006, Miodrag Vallat.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * LRC Local Resource Controller, found on MVME165
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+
+#include <mvme68k/dev/lrcreg.h>
+
+struct lrcreg *sys_lrc;
+
+struct lrcsoftc {
+ struct device sc_dev;
+ struct lrcreg *sc_regs;
+ vaddr_t sc_vaddr;
+ paddr_t sc_paddr;
+ struct intrhand sc_abortih;
+};
+
+int lrcabort(void *);
+void lrcattach(struct device *, struct device *, void *);
+int lrcmatch(struct device *, void *, void *);
+int lrcprint(void *, const char *);
+int lrcscan(struct device *, void *, void *);
+
+struct cfattach lrc_ca = {
+ sizeof(struct lrcsoftc), lrcmatch, lrcattach
+};
+
+struct cfdriver lrc_cd = {
+ NULL, "lrc", DV_DULL
+};
+
+int
+lrcmatch(struct device *parent, void *cf, void *aux)
+{
+ if (cputyp != CPU_165 || sys_lrc != NULL)
+ return (0);
+
+ return (1);
+}
+
+void
+lrcattach(struct device *parent, struct device *self, void *aux)
+{
+ struct confargs *ca = aux;
+ struct lrcsoftc *sc = (struct lrcsoftc *)self;
+
+ sc->sc_paddr = ca->ca_paddr;
+ sc->sc_vaddr = IIOV(sc->sc_paddr);
+ sys_lrc = sc->sc_regs = (struct lrcreg *)sc->sc_vaddr;
+
+ printf("\n");
+
+ /* sync serial clock with DUART */
+ sc->sc_regs->lrc_gcr &= ~GCR_SCFREQ;
+ /* disable VSB */
+ sc->sc_regs->lrc_bcr &= ~(BCR_VA24 | BCR_VSBEN | BCR_ROEN);
+ /* set up vector base */
+ sc->sc_regs->lrc_icr1 = LRC_VECBASE;
+ /* enable interrupts */
+ sc->sc_regs->lrc_icr0 = ICR0_GIE;
+
+ sc->sc_abortih.ih_fn = lrcabort;
+ sc->sc_abortih.ih_ipl = IPL_HIGH;
+ sc->sc_abortih.ih_wantframe = 1;
+ lrcintr_establish(LRCVEC_ABORT, &sc->sc_abortih, self->dv_xname);
+
+ config_search(lrcscan, self, aux);
+}
+
+int
+lrcprint(void *aux, const char *pnp)
+{
+ struct confargs *ca = aux;
+
+ 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
+lrcscan(struct device *parent, void *self, void *aux)
+{
+ struct cfdata *cf = self;
+ struct lrcsoftc *sc = (struct lrcsoftc *)parent;
+ struct confargs *ca = aux;
+ struct confargs oca;
+
+ bzero(&oca, sizeof oca);
+ oca.ca_iot = ca->ca_iot;
+ oca.ca_dmat = ca->ca_dmat;
+ oca.ca_offset = cf->cf_loc[0];
+ oca.ca_ipl = cf->cf_loc[1];
+ if (oca.ca_offset != -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 = (vaddr_t)-1;
+ oca.ca_paddr = (paddr_t)-1;
+ }
+ oca.ca_bustype = BUS_LRC;
+ 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, lrcprint);
+
+ return (1);
+}
+
+/*
+ * Register an LRC interrupt.
+ * This will take care of enabling the right interrupt source in the
+ * interrupt controller.
+ */
+int
+lrcintr_establish(u_int vec, struct intrhand *ih, const char *name)
+{
+ int rc;
+ const struct {
+ u_int8_t icr0_bit;
+ u_int8_t icr1_bit;
+ } icr_bits[] = {
+ { 0x00, 0x00 }, /* timer 0 done differently */
+ { 0x00, 0x00 }, /* timer 1 done differently */
+ { 0x00, 0x00 }, /* timer 2 done differently */
+ { 0xff, 0xff },
+ { ICR0_IRQ7G2IE, 0x00 },
+ { ICR0_IRQ6G2IE, 0x00 },
+ { 0xff, 0xff },
+ { ICR0_IRQ3G2IE, 0x00 },
+ { ICR0_IRQ7G2IE, 0x00 },
+ { ICR0_IRQ4G2IE, 0x00 }, /* ICR0_IRQ6G4IE */
+ { 0x00, ICR1_IRQ7G5IE },
+ { 0x00, ICR1_IRQ7G6IE },
+ { ICR0_IRQ5G2IE, 0x00 },
+ { 0xff, 0xff },
+ { 0xff, 0xff },
+ { 0xff, 0xff }
+ };
+
+#ifdef DIAGNOSTIC
+ if (vec < 0 || vec >= LRC_NVEC || icr_bits[vec].icr0_bit == 0xff)
+ panic("lrcintr_establish: illegal vector for %s: 0x%x",
+ name, vec);
+#endif
+
+ rc = intr_establish(LRC_VECBASE + vec, ih, name);
+
+ if (rc == 0) {
+ sys_lrc->lrc_icr0 |= icr_bits[vec].icr0_bit;
+ sys_lrc->lrc_icr1 |= icr_bits[vec].icr1_bit;
+ }
+
+ return (rc);
+}
+
+int
+lrcabort(void *frame)
+{
+ nmihand(frame);
+
+ return (1);
+}
+
+/*
+ * Figure out the speed of the board by measuring how many operations
+ * can be issued in a given time, reusing the delay() logic.
+ */
+int
+lrcspeed(struct lrcreg *lrc)
+{
+ uint cnt;
+ int speed;
+
+ /* use timer0 and wait for it to wrap after 200msec */
+ cnt = 0;
+ lrc->lrc_t0base = 200000 + 1;
+ lrc->lrc_tcr0 = TCR_TLD0; /* reset to one */
+ lrc->lrc_stat = STAT_TMR0; /* clear latch */
+ lrc->lrc_tcr0 = TCR_TEN0;
+ while ((lrc->lrc_stat & STAT_TMR0) == 0)
+ cnt++;
+
+ /*
+ * Empirically determined. However since there are only
+ * 25MHz and 33MHz boards available, it is easy to draw
+ * a line - cnt should be close to cpu MHz * 8000.
+ */
+ if (cnt > 30 * 8000)
+ speed = 33;
+ else
+ speed = 25;
+
+ return speed;
+}
diff --git a/sys/arch/mvme68k/dev/lrcreg.h b/sys/arch/mvme68k/dev/lrcreg.h
new file mode 100644
index 00000000000..3ddd40d250e
--- /dev/null
+++ b/sys/arch/mvme68k/dev/lrcreg.h
@@ -0,0 +1,175 @@
+/* $OpenBSD: lrcreg.h,v 1.1 2009/03/01 21:40:49 miod Exp $ */
+
+/*
+ * Copyright (c) 2006, Miodrag Vallat.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * LRC Local Resource Controller, found on MVME165
+ */
+
+/*
+ * Register layout.
+ * Note that this chip is 24-bit internally, so the 8 high-order bits of
+ * each register are undefined and likely set to ones.
+ */
+struct lrcreg {
+ /* timer constants */
+ volatile u_int32_t lrc_t0base;
+ volatile u_int32_t lrc_t1base;
+ volatile u_int32_t lrc_t2base;
+ /* timer counts */
+ volatile u_int32_t lrc_t0cnt;
+ volatile u_int32_t lrc_t1cnt;
+ volatile u_int32_t lrc_t2cnt;
+ /* timer control words */
+ volatile u_int32_t lrc_tcr0;
+ volatile u_int32_t lrc_tcr1;
+ volatile u_int32_t lrc_tcr2;
+ /* general control */
+ volatile u_int32_t lrc_gcr;
+ /* bus control */
+ volatile u_int32_t lrc_bcr;
+ /* interrupt control */
+ volatile u_int32_t lrc_icr0;
+ volatile u_int32_t lrc_icr1;
+ /* status register */
+ volatile u_int32_t lrc_stat;
+ /* RAM address */
+ volatile u_int32_t lrc_ramaddr;
+ /* bus error status */
+ volatile u_int32_t lrc_berrstat;
+};
+
+/* TCR0 bits */
+#define TCR_TEN0 0x80 /* timer0 enable */
+#define TCR_TLD0 0x40 /* timer0 reload */
+#define TCR_TCYC0 0x20 /* timer0 cycle */
+#define TCR_T0IE 0x10 /* time0 interrupt enable */
+#define TCR_TOS_MASK 0x0c /* timer output select */
+#define TCR_TOS_TMR0 0x00
+#define TCR_TOS_TMR1 0x04
+#define TCR_TOS_TMR2 0x08
+#define TCR_TOEN 0x02 /* timer output enable */
+#define TCR_TOMD 0x01 /* timer output mode: pulse / square wave */
+
+/* TCR1 bits */
+#define TCR_TEN1 0x80 /* timer1 enable */
+#define TCR_TLD1 0x40 /* timer1 reload */
+#define TCR_TCYC1 0x20 /* timer1 cycle */
+#define TCR_T1IE 0x10 /* timer1 interrupt enable */
+#define TCR_TIS_MASK 0x0c /* timer input select */
+#define TCR_TIS_TMR0 0x00
+#define TCR_TIS_TMR1 0x04
+#define TCR_TIS_TMR2 0x08
+#define TCR_TIS_NONE 0x0c
+#define TCR_TIEN 0x02 /* timer input enable */
+#define TCR_TIMD 0x01 /* timer input mode */
+
+/* TCR2 bits */
+#define TCR_TEN2 0x80 /* timer2 enable */
+#define TCR_TLD2 0x40 /* timer2 reload */
+#define TCR_TCYC2 0x20 /* timer2 cycle */
+#define TCR_T2IE 0x10 /* timer2 interrupt enable */
+#define TCR_TWD_MASK 0x0c /* timer watchdog select */
+#define TCR_TWD_TMR0 0x00
+#define TCR_TWD_TMR1 0x04
+#define TCR_TWD_TMR2 0x08
+#define TCR_TWD_NONE 0x0c
+#define TCR_TWDEN 0x02 /* timer watchdog enable */
+#define TCR_TTST 0x01 /* timer test (do not use) */
+
+/* GCR bits */
+#define GCR_SCFREQ 0x10 /* dart serial clock frequency */
+#define GCR_FAST 0x08 /* EPROM fast acknowledge */
+#define GCR_GPCTL1 0x04 /* write wrong parity */
+#define GCR_GPCTL0 0x02 /* parity error enable */
+#define GCR_RSTO 0x01 /* reset output */
+
+/* BCR bits */
+#define BCR_VA24 0x10 /* force VME A24 addressing for low 16MB */
+#define BCR_VSBEN 0x08 /* VSB enable */
+#define BCR_VSBMD 0x04 /* restricted VSB ranges */
+#define BCR_ROEN 0x02 /* VSB read only enable */
+#define BCR_ROMD 0x01 /* VSB read only mode uses VSBRO */
+
+/* ICR0 bits */
+#define ICR0_GIE 0x80 /* global interrupt enable */
+#define ICR0_IRQ3G2IE 0x40 /* DART tick timer, level 3 */
+#define ICR0_IRQ4G2IE 0x20 /* VSBIRQ, level 4 */
+#define ICR0_IRQ5G2IE 0x10 /* DART DUART irq */
+#define ICR0_IRQ6G2IE 0x08 /* DART tick timer, level 6 */
+#define ICR0_IRQ6G4IE 0x04 /* VSBIRQ, level 6 */
+#define ICR0_IRQ7G2IE 0x02 /* unused */
+#define ICR0_IRQ7G4IE 0x01 /* PARERR */
+
+/* ICR1 bits */
+#define ICR1_VEC_MASK 0xf0 /* interrupt vector significant nibble */
+#define ICR1_IRQ7G6IE 0x02 /* ACFAIL */
+#define ICR1_IRQ7G5IE 0x01 /* ABORT */
+
+/* STAT bits */
+#define STAT_WTS 0x020000 /* Watchdog timeout */
+#define STAT_IRQ7G6S 0x010000 /* ACFAIL */
+#define STAT_IRQ7G5S 0x008000 /* ABORT */
+#define STAT_GPSTATL 0x004000 /* SYSFAIL (latched) */
+#define STAT_GPSTATS 0x002000 /* SYSFAIL */
+#define STAT_PORS 0x001000 /* Power On Reset */
+#define STAT_IRQ3G2 0x000800 /* DART tick timer */
+#define STAT_IRQ4G2 0x000400 /* VSBIRQ */
+#define STAT_IRQ5G2 0x000200 /* DART irq */
+#define STAT_IRQ6G2 0x000100 /* DART tick timer */
+#define STAT_IRQ7G2 0x000080 /* unused */
+#define STAT_TMR2 0x000040 /* timer2 timeout */
+#define STAT_TMR1 0x000020 /* timer1 timeout */
+#define STAT_TMR0 0x000010 /* timer0 timeout */
+#define STAT_IRQ6G4 0x000008 /* VSBIRQ */
+#define STAT_IRQ7G4 0x000004 /* PARERR */
+#define STAT_IRQ7G5 0x000002 /* ABORT */
+#define STAT_IRQ7G6 0x000001 /* ACFAIL */
+
+/*
+ * Fixed interrupt vectors
+ */
+
+#define LRC_VECBASE 0x40
+#define LRC_NVEC 0x10
+
+#define LRCVEC_TIMER0 0x00
+#define LRCVEC_TIMER1 0x01
+#define LRCVEC_TIMER2 0x02
+#define LRCVEC_IRQ7G2 0x04 /* not used */
+#define LRCVEC_IRQ6G2 0x05
+#define LRCVEC_IRQ3G2 0x07
+#define LRCVEC_PARERR 0x08
+#define LRCVEC_VSBIRQ 0x09
+#define LRCVEC_ABORT 0x0a
+#define LRCVEC_ACFAIL 0x0b
+
+#define LRCVEC_DART 0x0c /* as set up by the BUG; not a fixed value */
+
+int lrcintr_establish(u_int, struct intrhand *, const char *);
+int lrcspeed(struct lrcreg *);
+
+extern struct lrcreg *sys_lrc;
diff --git a/sys/arch/mvme68k/dev/nvram.c b/sys/arch/mvme68k/dev/nvram.c
index 43572b85600..2b843833641 100644
--- a/sys/arch/mvme68k/dev/nvram.c
+++ b/sys/arch/mvme68k/dev/nvram.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nvram.c,v 1.18 2007/12/20 05:19:38 miod Exp $ */
+/* $OpenBSD: nvram.c,v 1.19 2009/03/01 21:40:49 miod Exp $ */
/*
* Copyright (c) 1995 Theo de Raadt
@@ -56,7 +56,7 @@ struct nvramsoftc {
paddr_t sc_paddr;
vaddr_t sc_vaddr;
int sc_len;
- struct clockreg *sc_regs;
+ void *sc_clockregs;
};
void nvramattach(struct device *, struct device *, void *);
@@ -89,22 +89,41 @@ nvramattach(parent, self, args)
{
struct confargs *ca = args;
struct nvramsoftc *sc = (struct nvramsoftc *)self;
+ vsize_t maplen;
sc->sc_paddr = ca->ca_paddr;
sc->sc_vaddr = (vaddr_t)ca->ca_vaddr;
sc->sc_len = MK48T08_SIZE;
+#ifdef MVME147
if (cputyp == CPU_147)
sc->sc_len = MK48T02_SIZE;
+#endif
+ /*
+ * On the MVME165, the MK48T08 is mapped as one byte per longword,
+ * thus spans four time as much address space.
+ */
+#ifdef MVME165
+ if (cputyp == CPU_165)
+ maplen = 4 * sc->sc_len;
+ else
+#endif
+ maplen = sc->sc_len;
/*X*/ if (sc->sc_vaddr == -1)
-/*X*/ sc->sc_vaddr = mapiodev(sc->sc_paddr, MAX(sc->sc_len, NBPG));
+/*X*/ sc->sc_vaddr = mapiodev(sc->sc_paddr, maplen);
/*X*/ if (sc->sc_vaddr == 0)
/*X*/ panic("failed to map!");
- sc->sc_regs = (struct clockreg *)(sc->sc_vaddr + sc->sc_len -
- sizeof(struct clockreg));
+#ifdef MVME165
+ if (cputyp == CPU_165)
+ sc->sc_clockregs = (void *)(sc->sc_vaddr + maplen -
+ sizeof(struct clockreg_165));
+ else
+#endif
+ sc->sc_clockregs = (void *)(sc->sc_vaddr + sc->sc_len -
+ sizeof(struct clockreg));
printf(": MK48T0%d len %d\n", sc->sc_len / 1024, sc->sc_len);
}
@@ -264,7 +283,6 @@ 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;
@@ -279,14 +297,34 @@ 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 */
+
+#ifdef MVME165
+ if (cputyp == CPU_165) {
+ struct clockreg_165 *cl = sc->sc_clockregs;
+
+ 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
+#endif
+ {
+ struct clockreg *cl = sc->sc_clockregs;
+
+ 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 ((time.tv_sec = chiptotime(sec, min, hour, day, mon, year)) == 0) {
printf("WARNING: bad date in nvram");
/*
@@ -319,21 +357,40 @@ 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)
+ if (!time.tv_sec || sc->sc_clockregs == 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 */
+
+#ifdef MVME165
+ if (cputyp == CPU_165) {
+ struct clockreg_165 *cl = sc->sc_clockregs;
+
+ 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
+#endif
+ {
+ struct clockreg *cl = sc->sc_clockregs;
+
+ 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*/
@@ -346,6 +403,11 @@ nvramopen(dev, flag, mode, p)
if (minor(dev) >= nvram_cd.cd_ndevs ||
nvram_cd.cd_devs[minor(dev)] == NULL)
return (ENODEV);
+#ifdef MVME165
+ /* for now, do not allow userland to access the nvram on 165. */
+ if (cputyp == CPU_165)
+ return (ENXIO);
+#endif
return (0);
}
diff --git a/sys/arch/mvme68k/dev/nvramreg.h b/sys/arch/mvme68k/dev/nvramreg.h
index cc573968068..d430a2565f8 100644
--- a/sys/arch/mvme68k/dev/nvramreg.h
+++ b/sys/arch/mvme68k/dev/nvramreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nvramreg.h,v 1.4 2003/06/02 23:27:50 millert Exp $ */
+/* $OpenBSD: nvramreg.h,v 1.5 2009/03/01 21:40:49 miod Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -52,13 +52,34 @@ struct clockreg {
volatile u_char cl_year; /* year (0..99; BCD) */
};
+/*
+ * MK48T08 clock registers as found on MVME165 (sparse layout)
+ */
+struct clockreg_165 {
+ volatile u_char __cl_pad0[3];
+ volatile u_char cl_csr; /* control register */
+ volatile u_char __cl_pad1[3];
+ volatile u_char cl_sec; /* seconds (0..59; BCD) */
+ volatile u_char __cl_pad2[3];
+ volatile u_char cl_min; /* minutes (0..59; BCD) */
+ volatile u_char __cl_pad3[3];
+ volatile u_char cl_hour; /* hour (0..23; BCD) */
+ volatile u_char __cl_pad4[3];
+ volatile u_char cl_wday; /* weekday (1..7) */
+ volatile u_char __cl_pad5[3];
+ volatile u_char cl_mday; /* day in month (1..31; BCD) */
+ volatile u_char __cl_pad6[3];
+ volatile u_char cl_month; /* month (1..12; BCD) */
+ volatile u_char __cl_pad7[3];
+ volatile u_char 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) */
/*
* Motorola chose the year `1900' as their base count.
- * XXX what happens when it wraps?
*/
#define YEAR0 0
diff --git a/sys/arch/mvme68k/dev/vme.c b/sys/arch/mvme68k/dev/vme.c
index ee135608896..0274b47bf9a 100644
--- a/sys/arch/mvme68k/dev/vme.c
+++ b/sys/arch/mvme68k/dev/vme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vme.c,v 1.25 2009/02/17 22:28:41 miod Exp $ */
+/* $OpenBSD: vme.c,v 1.26 2009/03/01 21:40:49 miod Exp $ */
/*
* Copyright (c) 1995 Theo de Raadt
@@ -42,16 +42,20 @@
#include <machine/cpu.h>
#include <mvme68k/dev/vme.h>
-#include "pcc.h"
+#include "lrc.h"
#include "mc.h"
+#include "pcc.h"
#include "pcctwo.h"
-#if NPCC > 0
-#include <mvme68k/dev/pccreg.h>
+#if NLRC > 0
+#include <mvme68k/dev/lrcreg.h>
#endif
#if NMC > 0
#include <mvme68k/dev/mcreg.h>
#endif
+#if NPCC > 0
+#include <mvme68k/dev/pccreg.h>
+#endif
#if NPCCTWO > 0
#include <mvme68k/dev/pcctworeg.h>
#endif
@@ -197,7 +201,7 @@ vmematch(parent, cf, args)
return (1);
}
-#if defined(MVME162) || defined(MVME167) || defined(MVME177)
+#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
/*
* make local addresses 1G-2G correspond to VME addresses 3G-4G,
* as D32
@@ -232,7 +236,8 @@ vmepmap(sc, vmeaddr, len, bustype)
len = roundup(len, NBPG);
switch (vmebustype) {
-#if NPCC > 0
+#if NLRC > 0 || NPCC > 0
+ case BUS_LRC:
case BUS_PCC:
switch (bustype) {
case BUS_VMES:
@@ -412,7 +417,6 @@ vmescan(parent, child, args, bustype)
oca.ca_ipl = cf->cf_loc[2];
if (oca.ca_ipl > 0 && oca.ca_vec == -1)
oca.ca_vec = intr_findvec(255, 0);
-
oca.ca_offset = oca.ca_paddr;
oca.ca_vaddr = (vaddr_t)-1; /* nothing mapped during probe */
oca.ca_name = cf->cf_driver->cd_name;
@@ -431,7 +435,7 @@ vmeattach(parent, self, args)
{
struct vmesoftc *sc = (struct vmesoftc *)self;
struct confargs *ca = args;
-#if NPCC > 0
+#if NLRC > 0 || NPCC > 0
struct vme1reg *vme1;
#endif
#if NMC > 0 || NPCCTWO > 0
@@ -442,7 +446,8 @@ vmeattach(parent, self, args)
vmebustype = ca->ca_bustype;
switch (ca->ca_bustype) {
-#if NPCC > 0
+#if NLRC > 0 || NPCC > 0
+ case BUS_LRC:
case BUS_PCC:
vme1 = (struct vme1reg *)sc->sc_vaddr;
if (vme1->vme1_scon & VME1_SCON_SWITCH)
@@ -486,7 +491,7 @@ vmeintr_establish(vec, ih, name)
const char *name;
{
struct vmesoftc *sc = (struct vmesoftc *) vme_cd.cd_devs[0];
-#if NPCC > 0
+#if NLRC > 0 || NPCC > 0
struct vme1reg *vme1;
#endif
#if NMC > 0 || NPCCTWO > 0
@@ -497,7 +502,8 @@ vmeintr_establish(vec, ih, name)
x = intr_establish(vec, ih, name);
switch (vmebustype) {
-#if NPCC > 0
+#if NLRC > 0 || NPCC > 0
+ case BUS_LRC:
case BUS_PCC:
vme1 = (struct vme1reg *)sc->sc_vaddr;
vme1->vme1_irqen = vme1->vme1_irqen |
@@ -516,7 +522,7 @@ vmeintr_establish(vec, ih, name)
return (x);
}
-#if defined(MVME147)
+#if defined(MVME147) || defined(MVME165)
void
vme1chip_init(sc)
struct vmesoftc *sc;
@@ -528,7 +534,7 @@ vme1chip_init(sc)
#endif
-#if defined(MVME162) || defined(MVME167) || defined(MVME177)
+#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
/*
* XXX what AM bits should be used for the D32/D16 mappings?
@@ -585,7 +591,6 @@ 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);
#if NPCCTWO > 0
if (vmebustype == BUS_PCCTWO) {
@@ -638,14 +643,9 @@ int
vme2abort(frame)
void *frame;
{
- struct vmesoftc *sc = (struct vmesoftc *)vme_cd.cd_devs[0];
- struct vme2reg *vme2 = (struct vme2reg *)sc->sc_vaddr;
+ if ((sys_vme2->vme2_irqstat & VME2_IRQ_AB) != 0)
+ sys_vme2->vme2_irqclr = VME2_IRQ_AB;
- if ((vme2->vme2_irqstat & VME2_IRQ_AB) == 0) {
- printf("%s: abort irq not set\n", sc->sc_dev.dv_xname);
- return (0);
- }
- vme2->vme2_irqclr = VME2_IRQ_AB;
nmihand(frame);
return (1);
}