summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2006-05-09 18:14:34 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2006-05-09 18:14:34 +0000
commit8421d0b16c28fb92cbc740972557e19380c75a72 (patch)
tree9bb1a646704aace8f40f4127436a7dfc4f233203
parentc1df95c0790333c06a9f179bfb2a40c48af6e600 (diff)
Oops, correct import this time.
-rw-r--r--sys/arch/aviion/conf/files.aviion55
-rw-r--r--sys/arch/aviion/dev/dart.c1039
-rw-r--r--sys/arch/aviion/dev/dart_syscon.c103
-rw-r--r--sys/arch/aviion/dev/if_le_syscon.c172
-rw-r--r--sys/arch/aviion/dev/mainbus.c163
-rw-r--r--sys/arch/aviion/dev/syscon.c201
-rw-r--r--sys/arch/aviion/dev/vme.c550
7 files changed, 2283 insertions, 0 deletions
diff --git a/sys/arch/aviion/conf/files.aviion b/sys/arch/aviion/conf/files.aviion
new file mode 100644
index 00000000000..072f95ddf85
--- /dev/null
+++ b/sys/arch/aviion/conf/files.aviion
@@ -0,0 +1,55 @@
+# $OpenBSD: files.aviion,v 1.1 2006/05/09 18:14:33 miod Exp $
+#
+maxpartitions 16
+
+device mainbus {[addr = -1]}
+attach mainbus at root
+
+device syscon {[offset = -1], [ipl = 0]}
+attach syscon at mainbus
+file arch/aviion/dev/syscon.c syscon needs-flag
+
+device nvram
+attach nvram at syscon
+file arch/aviion/dev/nvram.c nvram needs-flag
+
+device dart: tty
+attach dart at syscon with dart_syscon
+file arch/aviion/dev/dart.c dart needs-flag
+file arch/aviion/dev/dart_syscon.c dart_syscon
+
+attach le at syscon with le_syscon
+file arch/aviion/dev/if_le_syscon.c le_syscon
+
+include "../../../scsi/files.scsi"
+
+major {sd = 4}
+major {st = 5}
+major {cd = 6}
+major {rd = 7}
+major {vnd = 8}
+
+device vme {[a16 = -1], [a24 = -1], [a32 = -1], [ipl = -1]}
+attach vme at syscon
+file arch/aviion/dev/vme.c vme needs-flag
+
+attach le at vme with le_vme
+file arch/aviion/dev/if_le_vme.c le_vme
+
+# list of standard files
+file dev/cninit.c
+
+file arch/aviion/aviion/autoconf.c
+#file arch/aviion/aviion/bus_dma.c
+file arch/aviion/aviion/conf.c
+file arch/aviion/aviion/db_machdep.c ddb
+file arch/aviion/aviion/disksubr.c
+file arch/aviion/aviion/eh.S
+file arch/aviion/aviion/machdep.c
+file arch/aviion/aviion/av400_machdep.c av400
+file arch/aviion/aviion/m8820x.c m88100
+file arch/aviion/aviion/mem.c
+file arch/aviion/aviion/pmap_bootstrap.c
+file arch/aviion/aviion/pmap_table.c
+file arch/aviion/aviion/prom.c
+file arch/aviion/dev/mainbus.c
diff --git a/sys/arch/aviion/dev/dart.c b/sys/arch/aviion/dev/dart.c
new file mode 100644
index 00000000000..ccbca07b568
--- /dev/null
+++ b/sys/arch/aviion/dev/dart.c
@@ -0,0 +1,1039 @@
+/* $OpenBSD: dart.c,v 1.1 2006/05/09 18:13:32 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/conf.h>
+#include <machine/cpu.h>
+
+#include <dev/cons.h>
+
+#include <machine/av400.h>
+#include <aviion/dev/sysconreg.h>
+#include <aviion/dev/dartreg.h>
+#include <aviion/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
+#ifdef USE_PROM_CONSOLE
+#define dartcn_sv sc->sc_sv_reg_storage
+#else
+struct dart_sv_reg dartcn_sv;
+#endif
+
+/* 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);
+#if 0
+ dart_write(sc, DART_OPCR, OPSET);
+#endif
+#if 0
+ dart_write(sc, DART_IVR, SYSCON_VECT + SYSCV_SCC);
+#endif
+
+ 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.
+#ifdef USE_PROM_CONSOLE
+ * Since we select the actual console after all devices are attached,
+ * we can safely pick the appropriate softc and use its information.
+#endif
+ */
+
+#ifdef USE_PROM_CONSOLE
+#define dart_cnread(reg) dart_read(sc, (reg))
+#define dart_cnwrite(reg, val) dart_write(sc, (reg), (val))
+#else
+#define dart_cnread(reg) \
+ *(volatile u_int8_t *)(DART_BASE + 3 + ((reg) << 2))
+#define dart_cnwrite(reg, val) \
+ *(volatile u_int8_t *)(DART_BASE + 3 + ((reg) << 2)) = (val)
+#endif
+
+void
+dartcnprobe(struct consdev *cp)
+{
+ int maj;
+
+ if (badaddr(DART_BASE, 4) != 0)
+ return;
+
+#ifdef USE_PROM_CONSOLE
+ /* do not attach as console if dart has been disabled */
+ if (dart_cd.cd_ndevs == 0 || dart_cd.cd_devs[0] == NULL)
+ return;
+#endif
+
+ /* 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_NORMAL;
+}
+
+void
+dartcninit(cp)
+ struct consdev *cp;
+{
+#ifndef USE_PROM_CONSOLE
+ 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);
+#endif
+}
+
+void
+dartcnputc(dev_t dev, int c)
+{
+#ifdef USE_PROM_CONSOLE
+ struct dartsoftc *sc;
+#endif
+ int s;
+ u_int port;
+ bus_addr_t ptaddr;
+
+#ifdef USE_PROM_CONSOLE
+ sc = (struct dartsoftc *)dart_cd.cd_devs[0];
+ port = DART_PORT(dev);
+#else
+ port = CONS_PORT;
+#endif
+ 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)
+{
+#ifdef USE_PROM_CONSOLE
+ struct dartsoftc *sc;
+#endif
+ unsigned char sr; /* status reg of port a/b */
+ u_char c; /* received character */
+ int s;
+ u_int port;
+ bus_addr_t ptaddr;
+
+#ifdef USE_PROM_CONSOLE
+ sc = (struct dartsoftc *)dart_cd.cd_devs[0];
+ port = DART_PORT(dev);
+#else
+ port = CONS_PORT;
+#endif
+ 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/aviion/dev/dart_syscon.c b/sys/arch/aviion/dev/dart_syscon.c
new file mode 100644
index 00000000000..73d63540e40
--- /dev/null
+++ b/sys/arch/aviion/dev/dart_syscon.c
@@ -0,0 +1,103 @@
+/* $OpenBSD: dart_syscon.c,v 1.1 2006/05/09 18:13:37 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+
+#include <machine/av400.h>
+
+#include <aviion/dev/sysconreg.h>
+#include <aviion/dev/dartvar.h>
+
+int dart_syscon_match(struct device *parent, void *self, void *aux);
+void dart_syscon_attach(struct device *parent, struct device *self, void *aux);
+
+struct cfattach dart_syscon_ca = {
+ sizeof(struct dartsoftc), dart_syscon_match, dart_syscon_attach
+};
+
+int
+dart_syscon_match(struct device *parent, void *cf, void *aux)
+{
+ struct confargs *ca = aux;
+ bus_space_handle_t ioh;
+ int rc;
+
+ /*
+ * We do not accept empty locators here...
+ */
+ if (ca->ca_paddr == (paddr_t)-1)
+ return (0);
+
+ if (bus_space_map(ca->ca_iot, ca->ca_paddr, DART_SIZE, 0, &ioh) != 0)
+ return (0);
+ rc = badaddr((vaddr_t)bus_space_vaddr(ca->ca_iot, ioh), 4);
+ bus_space_unmap(ca->ca_iot, ca->ca_paddr, DART_SIZE);
+
+ return (rc == 0);
+}
+
+void
+dart_syscon_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct dartsoftc *sc = (struct dartsoftc *)self;
+ struct confargs *ca = aux;
+ bus_space_handle_t ioh;
+ u_int vec;
+
+ 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;
+
+ if (ca->ca_paddr == DART_BASE) {
+ vec = SYSCV_SCC;
+ sc->sc_console = 1; /* XXX for now */
+ printf(": console");
+ } else {
+ vec = SYSCV_SCC2;
+ sc->sc_console = 0;
+ }
+
+ /* 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;
+
+ sysconintr_establish(vec, &sc->sc_ih, self->dv_xname);
+
+ dart_common_attach(sc);
+}
diff --git a/sys/arch/aviion/dev/if_le_syscon.c b/sys/arch/aviion/dev/if_le_syscon.c
new file mode 100644
index 00000000000..7142c7af5ea
--- /dev/null
+++ b/sys/arch/aviion/dev/if_le_syscon.c
@@ -0,0 +1,172 @@
+/* $OpenBSD: if_le_syscon.c,v 1.1 2006/05/09 18:13:40 miod Exp $ */
+
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Adam Glass and Gordon W. Ross.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <net/if_media.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+
+#include <machine/av400.h>
+#include <aviion/dev/sysconreg.h>
+
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
+
+/*
+ * LANCE registers. Although these are 16 bit registers, on the AV400
+ * design, they need to be accessed as 32 bit registers. Bus magic...
+ * The real stuff is in dev/ic/am7990reg.h
+ */
+struct av_lereg {
+ volatile u_int32_t ler1_rdp; /* data port */
+ volatile u_int32_t ler1_rap; /* register select port */
+};
+
+/*
+ * Ethernet software status per interface.
+ * The real stuff is in dev/ic/am7990var.h
+ */
+struct le_softc {
+ struct am7990_softc sc_am7990; /* glue to MI code */
+
+ struct av_lereg *sc_r1; /* LANCE registers */
+ struct intrhand sc_ih;
+};
+
+int le_syscon_match(struct device *, void *, void *);
+void le_syscon_attach(struct device *, struct device *, void *);
+
+struct cfattach le_syscon_ca = {
+ sizeof(struct le_softc), le_syscon_match, le_syscon_attach
+};
+
+void le_syscon_wrcsr(struct am7990_softc *, u_int16_t, u_int16_t);
+u_int16_t le_syscon_rdcsr(struct am7990_softc *, u_int16_t);
+
+void
+le_syscon_wrcsr(sc, port, val)
+ struct am7990_softc *sc;
+ u_int16_t port, val;
+{
+ struct av_lereg *ler1 = ((struct le_softc *)sc)->sc_r1;
+
+ ler1->ler1_rap = port;
+ ler1->ler1_rdp = val;
+}
+
+u_int16_t
+le_syscon_rdcsr(sc, port)
+ struct am7990_softc *sc;
+ u_int16_t port;
+{
+ struct av_lereg *ler1 = ((struct le_softc *)sc)->sc_r1;
+ u_int16_t val;
+
+ ler1->ler1_rap = port;
+ val = ler1->ler1_rdp;
+ return (val);
+}
+
+int
+le_syscon_match(parent, cf, aux)
+ struct device *parent;
+ void *cf, *aux;
+{
+ return (1);
+}
+
+void
+le_syscon_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct le_softc *lesc = (struct le_softc *)self;
+ struct am7990_softc *sc = &lesc->sc_am7990;
+ struct confargs *ca = aux;
+ extern void *etherbuf;
+ extern size_t etherlen;
+
+ if (etherbuf == NULL) {
+ printf(": no available memory, kernel is too large\n");
+ return;
+ }
+
+ lesc->sc_r1 = (struct av_lereg *)ca->ca_paddr;
+
+ sc->sc_mem = (void *)etherbuf;
+ etherbuf = NULL;
+ sc->sc_conf3 = LE_C3_BSWP;
+ sc->sc_addr = (u_long)sc->sc_mem & 0x00ffffff;
+ sc->sc_memsize = etherlen;
+
+ myetheraddr(sc->sc_arpcom.ac_enaddr);
+
+ sc->sc_copytodesc = am7990_copytobuf_contig;
+ sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
+ sc->sc_copytobuf = am7990_copytobuf_contig;
+ sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
+ sc->sc_zerobuf = am7990_zerobuf_contig;
+
+ sc->sc_rdcsr = le_syscon_rdcsr;
+ sc->sc_wrcsr = le_syscon_wrcsr;
+ sc->sc_hwreset = NULL;
+ sc->sc_hwinit = NULL;
+
+ am7990_config(sc);
+
+ lesc->sc_ih.ih_fn = am7990_intr;
+ lesc->sc_ih.ih_arg = sc;
+ lesc->sc_ih.ih_wantframe = 0;
+ lesc->sc_ih.ih_ipl = ca->ca_ipl;
+
+ sysconintr_establish(SYSCV_LE, &lesc->sc_ih, self->dv_xname);
+}
diff --git a/sys/arch/aviion/dev/mainbus.c b/sys/arch/aviion/dev/mainbus.c
new file mode 100644
index 00000000000..6795ebb0c66
--- /dev/null
+++ b/sys/arch/aviion/dev/mainbus.c
@@ -0,0 +1,163 @@
+/* $OpenBSD: mainbus.c,v 1.1 2006/05/09 18:13:53 miod Exp $ */
+/*
+ * Copyright (c) 1998 Steve Murphree, Jr.
+ * Copyright (c) 2004, 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/reboot.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/extent.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+#include <machine/cmmu.h>
+#include <machine/cpu.h>
+#include <machine/prom.h>
+
+#include <machine/av400.h>
+
+void mainbus_attach(struct device *, struct device *, void *);
+int mainbus_match(struct device *, void *, void *);
+int mainbus_print(void *, const char *);
+int mainbus_scan(struct device *, void *, void *);
+
+/*
+ * bus_space routines for 1:1 obio mappings
+ */
+
+int mainbus_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
+void mainbus_unmap(bus_space_handle_t, bus_size_t);
+int mainbus_subregion(bus_space_handle_t, bus_size_t, bus_size_t,
+ bus_space_handle_t *);
+void *mainbus_vaddr(bus_space_handle_t);
+
+const struct aviion_bus_space_tag mainbus_bustag = {
+ mainbus_map,
+ mainbus_unmap,
+ mainbus_subregion,
+ mainbus_vaddr
+};
+
+/*
+ * Obio (internal IO) space is mapped 1:1 (see pmap_bootstrap() for details).
+ */
+
+int
+mainbus_map(bus_addr_t addr, bus_size_t size, int flags,
+ bus_space_handle_t *ret)
+{
+ *ret = (bus_space_handle_t)addr;
+ return 0;
+}
+
+void
+mainbus_unmap(bus_space_handle_t handle, bus_size_t size)
+{
+ /* nothing to do */
+}
+
+int
+mainbus_subregion(bus_space_handle_t handle, bus_addr_t offset,
+ bus_size_t size, bus_space_handle_t *ret)
+{
+ *ret = handle + offset;
+ return (0);
+}
+
+void *
+mainbus_vaddr(bus_space_handle_t handle)
+{
+ return (void *)handle;
+}
+
+/*
+ * Configuration glue
+ */
+
+struct cfattach mainbus_ca = {
+ sizeof(struct device), mainbus_match, mainbus_attach
+};
+
+struct cfdriver mainbus_cd = {
+ NULL, "mainbus", DV_DULL
+};
+
+int
+mainbus_match(struct device *parent, void *cf, void *args)
+{
+ return (mainbus_cd.cd_ndevs == 0);
+}
+
+void
+mainbus_attach(struct device *parent, struct device *self, void *args)
+{
+ extern char cpu_model[];
+ extern int32_t cpuid, sysid;
+
+ printf(": %s, cpuid 0x%x", cpu_model, cpuid);
+ if (sysid != -1)
+ printf(", sysid %x", sysid);
+ printf("\n");
+
+ /*
+ * Display cpu/mmu details for the main processor.
+ */
+ cpu_configuration_print(1);
+
+ (void)config_search(mainbus_scan, self, args);
+}
+
+int
+mainbus_scan(struct device *parent, void *child, void *args)
+{
+ struct cfdata *cf = child;
+ struct confargs oca;
+
+ oca.ca_iot = &mainbus_bustag;
+ oca.ca_paddr = (paddr_t)cf->cf_loc[0];
+ oca.ca_offset = (paddr_t)-1;
+ oca.ca_ipl = (u_int)-1;
+
+ if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0)
+ return (0);
+
+ config_attach(parent, cf, &oca, mainbus_print);
+ return (1);
+}
+
+int
+mainbus_print(void *args, const char *bus)
+{
+ struct confargs *ca = args;
+
+ if (ca->ca_paddr != (paddr_t)-1)
+ printf(" addr 0x%08x", ca->ca_paddr);
+ return (UNCONF);
+}
diff --git a/sys/arch/aviion/dev/syscon.c b/sys/arch/aviion/dev/syscon.c
new file mode 100644
index 00000000000..8921ed28266
--- /dev/null
+++ b/sys/arch/aviion/dev/syscon.c
@@ -0,0 +1,201 @@
+/* $OpenBSD: syscon.c,v 1.1 2006/05/09 18:14:07 miod 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.
+ *
+ * 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/conf.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+
+#include <machine/av400.h>
+#include <aviion/dev/sysconreg.h>
+
+struct sysconsoftc {
+ struct device sc_dev;
+
+ struct intrhand sc_abih; /* `abort' switch */
+ struct intrhand sc_acih; /* `ac fail' */
+ struct intrhand sc_sfih; /* `sys fail' */
+#if 0
+ struct intrhand sc_av400ih; /* `av400 interrupt' */
+#endif
+};
+
+void sysconattach(struct device *, struct device *, void *);
+int sysconmatch(struct device *, void *, void *);
+
+int syscon_print(void *, const char *);
+int syscon_scan(struct device *, void *, void *);
+int sysconabort(void *);
+int sysconacfail(void *);
+int sysconsysfail(void *);
+int sysconav400(void *);
+
+struct cfattach syscon_ca = {
+ sizeof(struct sysconsoftc), sysconmatch, sysconattach
+};
+
+struct cfdriver syscon_cd = {
+ NULL, "syscon", DV_DULL
+};
+
+int
+sysconmatch(struct device *parent, void *cf, void *args)
+{
+ return (syscon_cd.cd_ndevs == 0);
+}
+
+void
+sysconattach(struct device *parent, struct device *self, void *args)
+{
+ struct sysconsoftc *sc = (struct sysconsoftc *)self;
+
+ printf("\n");
+
+ /*
+ * Clear SYSFAIL if lit.
+ */
+ *(volatile u_int32_t *)AV400_UCSR |= UCSR_DRVSFBIT;
+
+ /*
+ * pseudo driver, abort interrupt handler
+ */
+ sc->sc_abih.ih_fn = sysconabort;
+ sc->sc_abih.ih_arg = 0;
+ sc->sc_abih.ih_wantframe = 1;
+ sc->sc_abih.ih_ipl = IPL_ABORT;
+
+ sc->sc_acih.ih_fn = sysconacfail;
+ sc->sc_acih.ih_arg = 0;
+ sc->sc_acih.ih_wantframe = 1;
+ sc->sc_acih.ih_ipl = IPL_ABORT;
+
+ sc->sc_sfih.ih_fn = sysconsysfail;
+ sc->sc_sfih.ih_arg = 0;
+ sc->sc_sfih.ih_wantframe = 1;
+ sc->sc_sfih.ih_ipl = IPL_ABORT;
+
+#if 0
+ sc->sc_av400ih.ih_fn = sysconav400;
+ sc->sc_av400ih.ih_arg = 0;
+ sc->sc_av400ih.ih_wantframe = 1;
+ sc->sc_av400ih.ih_ipl = IPL_ABORT;
+#endif
+
+ sysconintr_establish(SYSCV_ABRT, &sc->sc_abih, "abort");
+ sysconintr_establish(SYSCV_ACF, &sc->sc_acih, "acfail");
+ sysconintr_establish(SYSCV_SYSF, &sc->sc_sfih, "sysfail");
+#if 0
+ intr_establish(AV400_IVEC, &sc->sc_av400ih, self->dv_xname);
+#endif
+
+ config_search(syscon_scan, self, args);
+}
+
+int
+syscon_scan(struct device *parent, void *child, void *args)
+{
+ struct cfdata *cf = child;
+ struct confargs oca, *ca = args;
+
+ bzero(&oca, sizeof oca);
+ oca.ca_iot = ca->ca_iot;
+ oca.ca_offset = (paddr_t)cf->cf_loc[0];
+ if (oca.ca_offset != (paddr_t)-1)
+ oca.ca_paddr = ca->ca_paddr + oca.ca_offset;
+ else
+ oca.ca_paddr = (paddr_t)-1;
+ oca.ca_ipl = (u_int)cf->cf_loc[1];
+
+ if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0)
+ return (0);
+
+ config_attach(parent, cf, &oca, syscon_print);
+ return (1);
+}
+
+int
+syscon_print(void *args, const char *pnp)
+{
+ struct confargs *ca = args;
+
+ if (ca->ca_offset != (paddr_t)-1)
+ printf(" offset 0x%x", ca->ca_offset);
+ if (ca->ca_ipl != (u_int)-1)
+ printf(" ipl %u", ca->ca_ipl);
+ return (UNCONF);
+}
+
+int
+sysconintr_establish(u_int vec, struct intrhand *ih, const char *name)
+{
+#ifdef DIAGNOSTIC
+ if (vec < 0 || vec >= SYSCON_NVEC) {
+ printf("sysconintr_establish: illegal vector 0x%x\n", vec);
+ return (EINVAL);
+ }
+#endif
+
+ return (intr_establish(SYSCON_VECT + vec, ih, name));
+}
+
+int
+sysconabort(void *eframe)
+{
+ *(volatile u_int32_t *)AV400_CLRINT = ISTATE_ABORT;
+ nmihand(eframe);
+ return (1);
+}
+
+int
+sysconsysfail(void *eframe)
+{
+ *(volatile u_int32_t *)AV400_CLRINT = ISTATE_SYSFAIL;
+ printf("WARNING: SYSFAIL* ASSERTED\n");
+ return (1);
+}
+
+int
+sysconacfail(void *eframe)
+{
+ *(volatile u_int32_t *)AV400_CLRINT = ISTATE_ACFAIL;
+ printf("WARNING: ACFAIL* ASSERTED\n");
+ return (1);
+}
+
+#if 0
+int
+sysconav400(void *eframe)
+{
+ /* shouldn't happen! */
+ printf("AV400: self-inflicted interrupt\n");
+ return (1);
+}
+#endif
diff --git a/sys/arch/aviion/dev/vme.c b/sys/arch/aviion/dev/vme.c
new file mode 100644
index 00000000000..514150dc19b
--- /dev/null
+++ b/sys/arch/aviion/dev/vme.c
@@ -0,0 +1,550 @@
+/* $OpenBSD: vme.c,v 1.1 2006/05/09 18:14:15 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.
+ */
+
+/*
+ * XXX TODO: Finish /dev/vme{a16,a24,a32}{d8,d16,d32} interface.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/extent.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/conf.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <aviion/dev/vmevar.h>
+
+#include <machine/av400.h>
+#include <aviion/dev/sysconreg.h>
+
+struct vmesoftc {
+ struct device sc_dev;
+
+ struct extent *sc_ext_a16;
+ struct extent *sc_ext_a24;
+ struct extent *sc_ext_a32;
+};
+
+int vmematch(struct device *, void *, void *);
+void vmeattach(struct device *, struct device *, void *);
+
+struct cfattach vme_ca = {
+ sizeof(struct vmesoftc), vmematch, vmeattach
+};
+
+struct cfdriver vme_cd = {
+ NULL, "vme", DV_DULL
+};
+
+int vme16_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
+void vme16_unmap(bus_space_handle_t, bus_size_t);
+void * vme16_vaddr(bus_space_handle_t);
+int vme24_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
+void vme24_unmap(bus_space_handle_t, bus_size_t);
+void * vme24_vaddr(bus_space_handle_t);
+int vme32_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
+void vme32_unmap(bus_space_handle_t, bus_size_t);
+void * vme32_vaddr(bus_space_handle_t);
+int vme_subregion(bus_space_handle_t, bus_size_t, bus_size_t,
+ bus_space_handle_t *);
+
+int vme_map(struct extent *, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
+void vme_unmap(struct extent *, bus_space_handle_t, bus_size_t);
+int vmeprint(void *, const char *);
+int vmescan(struct device *, void *, void *);
+
+u_int vmevecbase;
+
+int
+vmematch(struct device *parent, void *vcf, void *aux)
+{
+ /* XXX no VME on AV100/AV200/AV300, though */
+ return (1);
+}
+
+void
+vmeattach(struct device *parent, struct device *self, void *aux)
+{
+ struct vmesoftc *sc = (struct vmesoftc *)self;
+ u_int32_t ucsr;
+
+ printf("\n");
+
+ /*
+ * Initialize extents
+ */
+ sc->sc_ext_a16 = extent_create("vme a16", 0, 1 << (16 - PAGE_SHIFT),
+ M_DEVBUF, NULL, 0, EX_NOWAIT);
+ sc->sc_ext_a24 = extent_create("vme a24", 0, 1 << (24 - PAGE_SHIFT),
+ M_DEVBUF, NULL, 0, EX_NOWAIT);
+ sc->sc_ext_a32 = extent_create("vme a32", 0, 1 << (32 - PAGE_SHIFT),
+ M_DEVBUF, NULL, 0, EX_NOWAIT);
+
+ vmevecbase = 0x80; /* Hard coded for AV400 */
+
+ /*
+ * Force a reasonable timeout for VME data transfers.
+ * We can not disable this, this would cause autoconf to hang
+ * on the first missing device we'll probe.
+ */
+ ucsr = *(volatile u_int32_t*)AV400_UCSR;
+ ucsr = (ucsr & ~VTOSELBITS) | VTO128US;
+ *(volatile u_int32_t *)AV400_UCSR = ucsr;
+
+ /*
+ * Clear EXTAD to allow VME A24 devices to access the first 16MB
+ * of memory.
+ */
+ *(volatile u_int32_t *)AV400_EXTAD = 0x00000000;
+
+ /*
+ * Use supervisor data address modifiers for VME accesses.
+ */
+ *(volatile u_int32_t *)AV400_EXTAM = 0x0d;
+
+ /*
+ * Display AV400 VME ranges.
+ */
+ printf("%s: A32 %08x-%08x\n", self->dv_xname,
+ AV400_VME32_START1, AV400_VME32_END1);
+ printf("%s: A32 %08x-%08x\n", self->dv_xname,
+ AV400_VME32_START2, AV400_VME32_END2);
+ printf("%s: A24 %08x-%08x\n", self->dv_xname,
+ AV400_VME24_START, AV400_VME24_END);
+ printf("%s: A16 %08x-%08x\n", self->dv_xname,
+ AV400_VME16_START, AV400_VME16_END);
+
+ /* scan for child devices */
+ config_search(vmescan, self, aux);
+}
+
+int
+vmescan(struct device *parent, void *vcf, void *aux)
+{
+ struct cfdata *cf = vcf;
+ struct vme_attach_args vaa;
+
+ bzero(&vaa, sizeof vaa);
+ vaa.vaa_addr_a16 = (vme_addr_t)cf->cf_loc[0];
+ vaa.vaa_addr_a24 = (vme_addr_t)cf->cf_loc[1];
+ vaa.vaa_addr_a32 = (vme_addr_t)cf->cf_loc[2];
+ vaa.vaa_ipl = (u_int)cf->cf_loc[3];
+
+ if ((*cf->cf_attach->ca_match)(parent, cf, &vaa) == 0)
+ return (0);
+
+ config_attach(parent, cf, &vaa, vmeprint);
+ return (1);
+}
+
+int
+vmeprint(void *aux, const char *pnp)
+{
+ struct vme_attach_args *vaa = aux;
+
+ if (vaa->vaa_addr_a16 != (vme_addr_t)-1)
+ printf(" a16 0x%04x", vaa->vaa_addr_a16);
+ if (vaa->vaa_addr_a24 != (vme_addr_t)-1)
+ printf(" a24 0x%06x", vaa->vaa_addr_a24);
+ if (vaa->vaa_addr_a32 != (vme_addr_t)-1)
+ printf(" a32 0x%08x", vaa->vaa_addr_a32);
+ if (vaa->vaa_ipl != (u_int)-1)
+ printf(" ipl %u", vaa->vaa_ipl);
+
+ return (UNCONF);
+}
+
+/*
+ * Interrupt related code
+ */
+
+/* allocate interrupt vectors */
+int
+vmeintr_allocate(u_int count, int flags, u_int *array)
+{
+ u_int vec, v;
+
+ if ((flags & VMEINTR_CONTIGUOUS) == 0) {
+ for (vec = vmevecbase; vec <= NVMEINTR - count; vec++) {
+ if (SLIST_EMPTY(&intr_handlers[vec])) {
+ *array++ = vec;
+ if (--count == 0)
+ return (0);
+ }
+ }
+ } else {
+ for (vec = vmevecbase; vec <= NVMEINTR - count; vec++) {
+ /* do we have count contiguous unassigned vectors? */
+ for (v = count; v != 0; v--)
+ if (!SLIST_EMPTY(&intr_handlers[vec + v - 1]))
+ break;
+
+ if (v == 0) {
+ *array = vec;
+ return (0);
+ }
+ }
+ }
+
+ return (EPERM);
+}
+
+/* enable and establish interrupt */
+int
+vmeintr_establish(u_int vec, struct intrhand *ih, const char *name)
+{
+ /*
+ * No need to enable the VME interrupt source in the AV400 interrupt
+ * controller, as they are enabled by default.
+ */
+ return intr_establish(vec, ih, name);
+}
+
+/*
+ * bus_space specific functions
+ */
+
+int
+vme16_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret)
+{
+ struct vmesoftc *sc = (void *)vme_cd.cd_devs[0];
+
+ if (AV400_ISVMEA32(addr) && AV400_ISVMEA32(addr + size - 1))
+ return (vme_map(sc->sc_ext_a16, addr, size, flags, ret));
+ else
+ return (EINVAL);
+}
+
+int
+vme24_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret)
+{
+ struct vmesoftc *sc = (void *)vme_cd.cd_devs[0];
+
+ if (AV400_ISVMEA24(addr) && AV400_ISVMEA24(addr + size - 1))
+ return (vme_map(sc->sc_ext_a24, addr, size, flags, ret));
+ else
+ return (EINVAL);
+}
+
+int
+vme32_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret)
+{
+ struct vmesoftc *sc = (void *)vme_cd.cd_devs[0];
+
+ if (AV400_ISVMEA16(addr) && AV400_ISVMEA16(addr + size - 1))
+ return (vme_map(sc->sc_ext_a32, addr, size, flags, ret));
+ else
+ return (EINVAL);
+}
+
+int
+vme_map(struct extent *ext, bus_addr_t addr, bus_size_t size, int flags,
+ bus_space_handle_t *ret)
+{
+ int rc;
+ paddr_t pa;
+ psize_t len;
+ vaddr_t ova, va;
+ u_int pg;
+ extern vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, vm_prot_t, u_int);
+
+ pa = trunc_page((paddr_t)addr);
+ len = round_page((paddr_t)addr + size) - pa;
+
+ if (ext != NULL) {
+ rc = extent_alloc_region(ext, atop(pa), atop(len),
+ EX_NOWAIT | EX_MALLOCOK);
+ if (rc != 0)
+ return (rc);
+ }
+
+ ova = va = uvm_km_valloc(kernel_map, len);
+ if (va == NULL) {
+ rc = ENOMEM;
+ goto fail;
+ }
+
+ *ret = (bus_space_handle_t)va;
+
+ for (pg = atop(len); pg !=0; pg--) {
+ pmap_kenter_pa(va, pa, UVM_PROT_RW);
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ }
+ if (flags & BUS_SPACE_MAP_CACHEABLE)
+ pmap_cache_ctrl(pmap_kernel(), ova, ova + len, CACHE_GLOBAL);
+ pmap_update(pmap_kernel());
+
+ return (0);
+
+fail:
+ if (ext != NULL)
+ extent_free(ext, atop(pa), atop(len), EX_NOWAIT | EX_MALLOCOK);
+ return (rc);
+}
+
+void
+vme16_unmap(bus_space_handle_t handle, bus_size_t size)
+{
+ struct vmesoftc *sc = (void *)vme_cd.cd_devs[0];
+
+ return (vme_unmap(sc->sc_ext_a16, handle, size));
+}
+
+void
+vme24_unmap(bus_space_handle_t handle, bus_size_t size)
+{
+ struct vmesoftc *sc = (void *)vme_cd.cd_devs[0];
+
+ return (vme_unmap(sc->sc_ext_a24, handle, size));
+}
+
+void
+vme32_unmap(bus_space_handle_t handle, bus_size_t size)
+{
+ struct vmesoftc *sc = (void *)vme_cd.cd_devs[0];
+
+ return (vme_unmap(sc->sc_ext_a32, handle, size));
+}
+
+void
+vme_unmap(struct extent *ext, bus_space_handle_t handle, bus_size_t size)
+{
+ vaddr_t va;
+ vsize_t len;
+
+ va = trunc_page((vaddr_t)handle);
+ len = round_page((vaddr_t)handle + size) - va;
+
+ pmap_kremove(va, len);
+ pmap_update(pmap_kernel());
+ uvm_km_free(kernel_map, va, len);
+
+ if (ext != NULL)
+ extent_free(ext, atop(va), atop(len), EX_NOWAIT | EX_MALLOCOK);
+}
+
+int
+vme_subregion(bus_space_handle_t handle, bus_addr_t offset, bus_size_t size,
+ bus_space_handle_t *ret)
+{
+ /* since vme_map produces linear mappings, this is safe */
+ *ret = handle + offset;
+ return (0);
+}
+
+void *
+vme16_vaddr(bus_space_handle_t handle)
+{
+ return (void *)(AV400_VME16_START + (vaddr_t)handle);
+}
+
+void *
+vme24_vaddr(bus_space_handle_t handle)
+{
+ return (void *)(AV400_VME24_START + (vaddr_t)handle);
+}
+
+void *
+vme32_vaddr(bus_space_handle_t handle)
+{
+ return (void *)(handle);
+}
+
+/*
+ * Get a bus_space_tag for the requested address and data access modes.
+ *
+ * On aviion, we do not honour the dspace yet.
+ */
+int
+vmebus_get_bst(struct device *vsc, u_int aspace, u_int dspace,
+ bus_space_tag_t *bst)
+{
+ struct aviion_bus_space_tag *tag;
+
+ switch (dspace) {
+ case VME_D32:
+ case VME_D16:
+ case VME_D8:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ switch (aspace) {
+ case VME_A32:
+ case VME_A24:
+ case VME_A16:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ tag = (struct aviion_bus_space_tag *)malloc(sizeof *tag, M_DEVBUF,
+ M_NOWAIT);
+ if (tag == NULL)
+ return (ENOMEM);
+
+ switch (aspace) {
+ default:
+ case VME_A32:
+ tag->bs_map = vme32_map;
+ tag->bs_unmap = vme32_unmap;
+ tag->bs_subregion = vme_subregion;
+ tag->bs_vaddr = vme32_vaddr;
+ break;
+ case VME_A24:
+ tag->bs_map = vme24_map;
+ tag->bs_unmap = vme24_unmap;
+ tag->bs_subregion = vme_subregion;
+ tag->bs_vaddr = vme24_vaddr;
+ break;
+ case VME_A16:
+ tag->bs_map = vme16_map;
+ tag->bs_unmap = vme16_unmap;
+ tag->bs_subregion = vme_subregion;
+ tag->bs_vaddr = vme16_vaddr;
+ break;
+ }
+
+ *bst = tag;
+ return (0);
+}
+
+void
+vmebus_release_bst(struct device *vsc, bus_space_tag_t b)
+{
+ free((void *)b, M_DEVBUF);
+}
+
+/*
+ * /dev/vme* access routines
+ */
+
+/* minor device number encoding */
+#define AWIDTH_FIELD(minor) (minor & 0x0f)
+#define AWIDTH(w) ((w) << 3)
+#define DWIDTH_FIELD(minor) ((minor & 0xf0) >> 4)
+#define DWIDTH(w) ((w) << 3)
+
+int
+vmeopen(dev_t dev, int flags, int type, struct proc *p)
+{
+ if (vme_cd.cd_ndevs == 0 || vme_cd.cd_devs[0] == NULL)
+ return (ENODEV);
+
+ switch (AWIDTH_FIELD(minor(dev))) {
+ case VME_A32:
+ case VME_A24:
+ case VME_A16:
+ break;
+ default:
+ return (ENODEV);
+ }
+
+ switch (DWIDTH_FIELD(minor(dev))) {
+ case VME_D32:
+ case VME_D16:
+ case VME_D8:
+ break;
+ default:
+ return (ENODEV);
+ }
+
+ return (0);
+}
+
+int
+vmeclose(dev_t dev, int flags, int type, struct proc *p)
+{
+ return (0);
+}
+
+int
+vmeread(dev_t dev, struct uio *uio, int flags)
+{
+ return (EIO);
+}
+
+int
+vmewrite(dev_t dev, struct uio *uio, int flags)
+{
+ return (EIO);
+}
+
+int
+vmeioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ switch (cmd) {
+ default:
+ return (ENOTTY);
+ }
+}
+
+paddr_t
+vmemmap(dev_t dev, off_t off, int prot)
+{
+ int awidth;
+ paddr_t pa;
+
+ if ((off & PAGE_MASK) != 0)
+ return (-1);
+
+ awidth = AWIDTH_FIELD(minor(dev));
+
+ /* check offset range */
+ if (off < 0 || off >= (1ULL << AWIDTH(awidth)))
+ return (-1);
+
+ pa = (paddr_t)off;
+
+ switch (awidth) {
+ case VME_A32:
+ if (!AV400_ISVMEA32(pa))
+ return (-1);
+ break;
+ case VME_A24:
+ pa += AV400_VME24_START;
+ if (!AV400_ISVMEA24(pa))
+ return (-1);
+ break;
+ case VME_A16:
+ pa += AV400_VME16_START;
+ if (!AV400_ISVMEA16(pa))
+ return (-1);
+ break;
+ }
+
+ return (atop(pa));
+}