summaryrefslogtreecommitdiff
path: root/sys/arch/mvme88k/dev/dart.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mvme88k/dev/dart.c')
-rw-r--r--sys/arch/mvme88k/dev/dart.c351
1 files changed, 206 insertions, 145 deletions
diff --git a/sys/arch/mvme88k/dev/dart.c b/sys/arch/mvme88k/dev/dart.c
index c46ae78a9c6..124c2eeb040 100644
--- a/sys/arch/mvme88k/dev/dart.c
+++ b/sys/arch/mvme88k/dev/dart.c
@@ -50,12 +50,12 @@
#include <machine/db_machdep.h> /* for details on entering kdb */
#define DDB_ENTER_BREAK 0x1
#define DDB_ENTER_CHAR 0x2
-unsigned char ddb_break_mode = DDB_ENTER_BREAK | DDB_ENTER_CHAR;
-unsigned char ddb_break_char = '!';
+unsigned char ddb_break_mode = DDB_ENTER_BREAK;
+unsigned char ddb_break_char = 0;
#endif
-#if DEBUG
- int dart_debug = 0;
+#ifdef DEBUG
+ int dart_debug = 1;
#define dprintf(stuff) if (dart_debug) printf stuff
#else
#define dprintf(stuff)
@@ -71,6 +71,7 @@ struct dartsoftc {
struct device sc_dev;
struct evcnt sc_intrcnt;
union dartreg *dart_reg;
+ union dart_pt_io *port_reg[2];
struct dart_info sc_dart[2];
struct intrhand sc_ih;
int sc_flags;
@@ -89,6 +90,7 @@ struct cfdriver dart_cd = {
NULL, "dart", DV_TTY, 0
};
+int dart_cons = -1;
/* prototypes */
int dartcnprobe __P((struct consdev *cp));
int dartcninit __P((struct consdev *cp));
@@ -118,26 +120,41 @@ void dartbreak __P((dev_t dev, int state));
struct dart_sv_reg dart_sv_reg;
/* speed tables */
-int dart_speeds[] =
-{
- 0, /* 0 baud, special HUP condition */
- NOBAUD, /* 50 baud, not implemented */
- BD75, /* 75 baud */
- BD110, /* 110 baud */
- BD134, /* 134.5 baud */
- BD150, /* 150 baud */
- NOBAUD, /* 200 baud, not implemented */
- BD300, /* 300 baud */
- BD600, /* 600 baud */
- BD1200, /* 1200 baud */
- BD1800, /* 1800 baud */
- BD2400, /* 2400 baud */
- BD4800, /* 4800 baud */
- BD9600, /* 9600 baud */
- BD19200, /* 19200 baud */
- NOBAUD /* 38400 baud, not implemented */
+struct 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 */
+ {0xFFFF, NOBAUD }, /* anything more is uncivilized */
};
+int
+dart_speed(speed)
+int speed;
+{
+ struct dart_s *ds = dart_speeds;
+ while (ds->kspeed != 0xFFFF) {
+ if (ds->kspeed == speed)
+ return ds->dspeed;
+ ds++;
+ }
+ return NOBAUD;
+}
+
struct tty*
darttty(dev)
dev_t dev;
@@ -184,7 +201,13 @@ void *aux;
/* set up dual port memory and registers and init*/
sc->dart_reg = (union dartreg *)ca->ca_vaddr;
+ ptaddr = (union dart_pt_io *)ca->ca_vaddr;
+ sc->port_reg[A_PORT] = ptaddr;
+ ptaddr++;
+ sc->port_reg[B_PORT] = ptaddr;
sc->sc_ipl = ca->ca_ipl = IPL_TTY; /* always... hard coded ipl */
+ sc->sc_dart[A_PORT].tty = NULL;
+ sc->sc_dart[B_PORT].tty = NULL;
ca->ca_vec = SYSCV_SCC; /* hard coded vector */
sc->sc_vec = ca->ca_vec;
@@ -206,8 +229,12 @@ void *aux;
/* Start out with Tx and RX interrupts disabled */
/* Enable input port change interrupt */
dart_sv_reg.sv_imr = IIPCHG;
+
+ if (dart_cons >= 0) {
+ printf(" console (tty%s) ", dart_cons == 0 ? "a" : "b");
+ }
- dprintf(("dartattach: resetting port A\n"));
+ dprintf(("\ndartattach: resetting port A\n"));
/* reset port a */
addr->write.wr_cra = RXRESET | TXDIS | RXDIS;
@@ -277,65 +304,82 @@ struct tty *tp;
{
dev_t dev;
struct dartsoftc *sc;
- int s, cnt;
+ int s, cnt, cc;
union dart_pt_io *ptaddr;
union dartreg *addr;
int port;
int c;
dev = tp->t_dev;
- port = DART_PORT(dev);
+ if((port = DART_PORT(dev)) > 1)
+ return;
+
sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ addr = sc->dart_reg;
+ ptaddr = sc->port_reg[port];
if ((tp->t_state & TS_ISOPEN) == 0)
return;
+
+ 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);
+ }
+ if (tp->t_outq.c_cc == 0)
+ goto bail;
+ selwakeup(&tp->t_wsel);
+ }
- addr = sc->dart_reg;
- ptaddr = (union dart_pt_io *)addr + port;
+ if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
+ goto bail;
- if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
- goto out;
+ dprintf(("dartstart: dev(%d, %d)\n", major(dev), minor(dev)));
- /*
- if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
- ttwakeup(tp);
- }
- */
+ if (port != dart_cons)
+ dprintf(("dartstart: ptaddr = 0x%08x from uart at 0x%08x\n",
+ ptaddr, addr));
if (tp->t_outq.c_cc != 0) {
-
tp->t_state |= TS_BUSY;
-
+ cc = tp->t_outq.c_cc;
/* load transmitter until it is full */
while (ptaddr->read.rd_sr & TXRDY) {
+ if(cc == 0)
+ break;
c = getc(&tp->t_outq);
-
+ cc--;
if (tp->t_flags & CS8 || c <= 0177) {
-
- dprintf(("dartstart: writing char \"%c\" (0x%02x)\n",
- c & 0xff, c % 0xff));
+ if (port != dart_cons)
+ dprintf(("dartstart: writing char \"%c\" (0x%02x) to port %d\n",
+ c & 0xff, c & 0xff, port));
ptaddr->write.wr_tb = c & 0xff;
-
- dprintf(("dartstart: enabling Tx int\n"));
+
+ if (port != dart_cons)
+ dprintf(("dartstart: enabling Tx int\n"));
if (port == A_PORT)
dart_sv_reg.sv_imr = dart_sv_reg.sv_imr | ITXRDYA;
else
dart_sv_reg.sv_imr = dart_sv_reg.sv_imr | ITXRDYB;
- addr -> write.wr_imr = dart_sv_reg.sv_imr;
+ addr->write.wr_imr = dart_sv_reg.sv_imr;
+
} else {
tp->t_state &= ~TS_BUSY;
- dprintf(("dartxint: timing out char \"%c\" (0x%02x)\n",
+ if (port != dart_cons)
+ dprintf(("dartxint: timing out char \"%c\" (0x%02x)\n",
c & 0xff, c % 0xff));
-#if 1
timeout_add(&tp->t_rstrt_to, 1);
-#else
- ttrstrt(tp);
-#endif
tp->t_state |= TS_TIMEOUT;
}
}
}
-out:
+bail:
+ splx(s);
return;
}
@@ -348,11 +392,13 @@ 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;
}
@@ -387,6 +433,7 @@ int how;
int newflags = 0;
struct dart_info *dart;
struct dartsoftc *sc;
+ int s;
if (port = DART_PORT(dev) > 1) {
return (ENODEV);
@@ -396,6 +443,7 @@ int how;
addr = sc->dart_reg;
/* special case: set or clear break */
+#if 0
if (flags & TIOCSBRK) {
dartbreak(port, 1);
flags &= ~TIOCSBRK;
@@ -404,7 +452,9 @@ int how;
dartbreak(port, 0);
flags &= ~TIOCCBRK;
}
-
+#endif
+ s = spltty();
+
HANDLE_FLAG(TIOCM_DTR, port, OPDTRA, OPDTRB);
HANDLE_FLAG(TIOCM_RTS, port, OPRTSA, OPRTSB);
@@ -440,7 +490,7 @@ int how;
dcdstate = !(addr->read.rd_ip & ((port == A_PORT) ? IPDCDA : IPDCDB));
dprintf(("dartmctl: DCD is %s\n", dcdstate ? "up" : "down"));
-
+ splx(s);
return dcdstate;
}
@@ -465,11 +515,11 @@ int state;
dart = &sc->sc_dart[port];
addr = sc->dart_reg;
- ptaddr = (union dart_pt_io *) addr + port;
-
+ ptaddr = sc->port_reg[port];
+
if (state == 1) {
/* the duart must be enabled with a dummy byte,
- to prevent the transmitter empty interrupt */
+ to prevent the transmitter empty interrupt */
ptaddr->write.wr_cr = BRKSTART|TXEN;
ptaddr->write.wr_tb = 0;
} else {
@@ -540,6 +590,8 @@ struct proc *p;
/* *(int *)data = dartmctl(dev, 0, DMGET);*/
break;
case TIOCGFLAGS:
+ if (dart_cons == port)
+ dart->dart_swflags |= TIOCFLAG_SOFTCAR;
*(int *)data = dart->dart_swflags;
break;
case TIOCSFLAGS:
@@ -548,6 +600,8 @@ struct proc *p;
return(EPERM);
dart->dart_swflags = *(int *)data;
+ if (dart_cons == port)
+ dart->dart_swflags |= TIOCFLAG_SOFTCAR;
dart->dart_swflags &= /* only allow valid flags */
(TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
break;
@@ -576,17 +630,17 @@ struct termios *t;
struct dartsoftc *sc;
dev_t dev;
- dprintf(("dartparam: setting param for dev %d\n", dev));
-
dev = tp->t_dev;
- if (port = DART_PORT(dev) > 1) {
+ dprintf(("dartparam: setting param for dev(%d, %d)\n", major(dev), minor(dev)));
+ if ((port = DART_PORT(dev)) > 1) {
return (ENODEV);
}
sc = (struct dartsoftc *) dart_cd.cd_devs[0];
dart = &sc->sc_dart[port];
addr = sc->dart_reg;
- ptaddr = (union dart_pt_io *) addr + port;
+ ptaddr = sc->port_reg[port];
+
tp->t_ispeed = t->c_ispeed;
tp->t_ospeed = t->c_ospeed;
tp->t_cflag = t->c_cflag;
@@ -597,81 +651,86 @@ struct termios *t;
/* disable Tx and Rx */
dprintf(("dartparam: disabling Tx and Rx int\n"));
- if (port == A_PORT)
- dart_sv_reg.sv_imr = dart_sv_reg.sv_imr & ~(ITXRDYA | IRXRDYA);
- else
- dart_sv_reg.sv_imr = dart_sv_reg.sv_imr & ~(ITXRDYB | IRXRDYB);
- addr -> write.wr_imr = dart_sv_reg.sv_imr;
-
- /* hang up on zero baud rate */
- if (tp->t_ispeed == 0) {
- dprintf(("dartparam: ispeed == 0 -> HUP\n"));
- dartmctl(tp, HUPCL, DMSET);
- return;
+ if (dart_cons == port) {
+ dprintf(("dartparam: skipping console init\n"));
} else {
- /* set baudrate */
- speeds = dart_speeds[(unsigned char)tp->t_ispeed];
- if (speeds == NOBAUD)
- speeds = dart_sv_reg.sv_csr[port];
- ptaddr->write.wr_csr = speeds;
- dart_sv_reg.sv_csr[port] = speeds;
- dprintf(("dartparam: baudrate set param = %d\n", speeds));
- }
+ if (port == A_PORT)
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr & ~(ITXRDYA | IRXRDYA);
+ else
+ dart_sv_reg.sv_imr = dart_sv_reg.sv_imr & ~(ITXRDYB | IRXRDYB);
+ addr -> write.wr_imr = dart_sv_reg.sv_imr;
- /* get saved mode registers and clear set up parameters */
- mr1 = dart_sv_reg.sv_mr1[port];
- mr1 &= ~(CLMASK | PARTYPEMASK | PARMODEMASK);
+ /* hang up on zero baud rate */
+ if (tp->t_ispeed == 0) {
+ dprintf(("dartparam: ispeed == 0 -> HUP\n"));
+ dartmctl(tp, HUPCL, DMSET);
+ return 0;
+ } else {
+ /* set baudrate */
+ speeds = dart_speed(tp->t_ispeed);
+ dprintf(("dartparam: speed 0x%x, baudrate %d\n", speeds, tp->t_ispeed));
+ if (speeds == NOBAUD)
+ speeds = dart_sv_reg.sv_csr[port];
+ ptaddr->write.wr_csr = speeds;
+ dart_sv_reg.sv_csr[port] = speeds;
+ dprintf(("dartparam: baudrate set param = %d\n", speeds));
+ }
- mr2 = dart_sv_reg.sv_mr2[port];
- mr2 &= ~SBMASK;
+ /* get saved mode registers and clear set up parameters */
+ mr1 = dart_sv_reg.sv_mr1[port];
+ mr1 &= ~(CLMASK | PARTYPEMASK | PARMODEMASK);
- /* set up character size */
- if (flags & CS8) {
- mr1 |= CL8;
- dprintf(("dartparam: PASS8\n"));
- } else if (tp->t_ispeed == B134) {
- mr1 |= CL6;
- dprintf(("dartparam: CS6\n"));
- } else {
- mr1 |= CL7;
- dprintf(("dartparam: CS7\n"));
- }
+ mr2 = dart_sv_reg.sv_mr2[port];
+ mr2 &= ~SBMASK;
- /* set up stop bits */
- if (tp->t_ospeed == B110) {
- mr2 |= SB2;
- dprintf(("dartparam: two stop bits\n"));
- } else {
- mr2 |= SB1;
- dprintf(("dartparam: one stop bit\n"));
- }
+ /* set up character size */
+ if (flags & CS8) {
+ mr1 |= CL8;
+ dprintf(("dartparam: PASS8\n"));
+ } else if (tp->t_ispeed == B134) {
+ mr1 |= CL6;
+ dprintf(("dartparam: CS6\n"));
+ } else {
+ mr1 |= CL7;
+ dprintf(("dartparam: CS7\n"));
+ }
- /* set up parity */
- if (((flags & PARENB) != PARENB) &&
- (flags & PARENB)) {
- mr1 |= PAREN;
- if (flags & PARODD) {
- mr1 |= ODDPAR;
- dprintf(("dartparam: odd parity\n"));
+ /* set up stop bits */
+ if (tp->t_ospeed == B110) {
+ mr2 |= SB2;
+ dprintf(("dartparam: two stop bits\n"));
} else {
- mr1 |= EVENPAR;
- dprintf(("dartparam: even parity\n"));
+ mr2 |= SB1;
+ dprintf(("dartparam: one stop bit\n"));
+ }
+
+ /* set up parity */
+ if (((flags & PARENB) != PARENB) &&
+ (flags & PARENB)) {
+ mr1 |= PAREN;
+ if (flags & PARODD) {
+ mr1 |= ODDPAR;
+ dprintf(("dartparam: odd parity\n"));
+ } else {
+ mr1 |= EVENPAR;
+ dprintf(("dartparam: even parity\n"));
+ }
+ } else {
+ mr1 |= PARDIS;
+ dprintf(("dartparam: no parity\n"));
}
- } else {
- mr1 |= PARDIS;
- dprintf(("dartparam: no parity\n"));
- }
- if ((dart_sv_reg.sv_mr1[port] != mr1)
- || (dart_sv_reg.sv_mr2[port] != mr2)) {
- /* write mode registers to duart */
- ptaddr->write.wr_cr = MRRESET;
- ptaddr->write.wr_mr = mr1;
- ptaddr->write.wr_mr = mr2;
+ if ((dart_sv_reg.sv_mr1[port] != mr1)
+ || (dart_sv_reg.sv_mr2[port] != mr2)) {
+ /* write mode registers to duart */
+ ptaddr->write.wr_cr = MRRESET;
+ ptaddr->write.wr_mr = mr1;
+ ptaddr->write.wr_mr = mr2;
- /* save changed mode registers */
- dart_sv_reg.sv_mr1[port] = mr1;
- dart_sv_reg.sv_mr2[port] = mr2;
+ /* save changed mode registers */
+ dart_sv_reg.sv_mr1[port] = mr1;
+ dart_sv_reg.sv_mr2[port] = mr2;
+ }
}
/* enable transmitter? */
@@ -747,12 +806,12 @@ struct proc *p;
struct dartsoftc *sc;
struct tty *tp;
- if (port = DART_PORT(dev) > 1) {
+ if ((port = DART_PORT(dev)) > 1) {
return (ENODEV);
}
- sc = (struct dartsoftc *) dart_cd.cd_devs[0];
+ sc = (struct dartsoftc *) dart_cd.cd_devs[0]; /* the only one */
dart = &sc->sc_dart[port];
- s = spldart();
+ s = spltty();
if (dart->tty) {
tp = dart->tty;
@@ -773,7 +832,7 @@ struct proc *p;
tp->t_lflag = TTYDEF_LFLAG;
tp->t_ispeed = tp->t_ospeed = B9600;
dartparam(tp, &tp->t_termios);
- if (port == 0) {
+ if (port == dart_cons) {
/* console is 8N1 */
tp->t_cflag = (CREAD | CS8 | HUPCL);
} else {
@@ -783,8 +842,8 @@ struct proc *p;
(void)dartmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
tp->t_state |= TS_CARR_ON;
} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
- splx(s);
simple_unlock(&dart->t_lock);
+ splx(s);
return (EBUSY);
}
/*
@@ -810,17 +869,16 @@ struct proc *p;
struct dartsoftc *sc;
int s, port;
- if (port = DART_PORT(dev) > 1) {
+ if ((port = DART_PORT(dev)) > 1) {
+ printf("dartclose: inavalid device dev(%d, %d)\n", major(dev), minor(dev));
return (ENODEV);
}
sc = (struct dartsoftc *) dart_cd.cd_devs[0];
dart = &sc->sc_dart[port];
tp = dart->tty;
(*linesw[tp->t_line].l_close)(tp, flag);
-
- s = spldart();
ttyclose(tp);
- splx(s);
+
return 0;
}
@@ -885,7 +943,7 @@ int port;
addr = sc->dart_reg;
/* read status reg */
- ptaddr = (union dart_pt_io *) addr + port;
+ ptaddr = sc->port_reg[port];
dprintf(("dartrint: Rx int port %d\n", port));
@@ -902,7 +960,7 @@ int port;
dprintf(("dartrint: read char \"%c\" (0x%02x) tp = 0x%x\n",
data, data, tp));
- if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0) {
+ if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0 && dart_cons != port) {
return;
}
@@ -942,17 +1000,18 @@ int port;
gimmeabreak();
} else
#endif
+ (*linesw[tp->t_line].l_rint)(data,tp);
+#if 0
{
if (tp->t_ispeed == B134) /* CS6 */
data &= 077;
-#if 0 /* XXX ??? */
- else if (tp->t_flags & (RAW|LITOUT|PASS8)) /*CS8*/
+ else if (tp->t_flags & CS8)
;
-#endif
else
data &= 0177; /* CS7 */
ttyinput(data, tp);
}
+#endif
}
}
}
@@ -992,7 +1051,7 @@ int port;
return;
}
}
- out:
+out:
/* disable transmitter */
if (port == 0)
@@ -1022,14 +1081,15 @@ struct dartsoftc *sc;
addr = sc->dart_reg;
isr = addr->read.rd_isr;
+
isr &= dart_sv_reg.sv_imr;
-
+
if (isr) { /* interrupt from this duart */
if (isr & IIPCHG) {
unsigned int ip = addr->read.rd_ip;
unsigned int ipcr = addr->read.rd_ipcr;
dartmodemtrans(sc, ip, ipcr);
- return 0;
+ return 1;
}
if (isr & (IRXRDYA | ITXRDYA))
@@ -1095,7 +1155,8 @@ int
dartcninit(cp)
struct consdev *cp;
{
- /* Nothing to do */
+ dart_cons = A_PORT;
+ return 0;
}
int
@@ -1114,13 +1175,13 @@ char c;
addr = (union dartreg *) MVME188_DUART;
#if 1
- ptaddr = (union dart_pt_io *) addr + port;
+ ptaddr = (union dart_pt_io *) addr + (port * 0x20);
#else
ptaddr = (union dart_pt_io *) addr + ((dev & 1) ? 1 : 0);
#endif
#if 1
- s = spldart();
+ s = spltty();
#else
psr = disable_interrupts_return_psr();
#endif
@@ -1177,13 +1238,13 @@ dev_t dev;
port = DART_PORT(dev);
#if 1
- s = spldart();
+ s = spltty();
#else
psr = disable_interrupts_return_psr();
#endif
addr = (union dartreg *) DART_BASE;
#if 1
- ptaddr = (union dart_pt_io *) addr + port;
+ ptaddr = (union dart_pt_io *) addr + (port * 0x20);
#else
ptaddr = (union dart_pt_io *) addr + ((dev & 1) ? 1 : 0);
#endif