diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-03-01 21:40:50 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-03-01 21:40:50 +0000 |
commit | 59dcae1e0128e7bebf63bdf1d6cb852a0cf6a509 (patch) | |
tree | b724b47073fb8d1491458c56d52cbdbd696e2c1a /sys/arch/mvme68k/dev | |
parent | a1c26a0a8ac1138d2326c1b8cd8217a879778127 (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.c | 118 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/dart.c | 999 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/dart_lrc.c | 106 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/dartreg.h | 155 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/dartvar.h | 63 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/lrc.c | 232 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/lrcreg.h | 175 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/nvram.c | 112 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/nvramreg.h | 25 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/vme.c | 42 |
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); } |