summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-01-05 13:35:51 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-01-05 13:35:51 +0000
commite9b5ce7bb5c9930a3aca4543f63b52c84fa5adbf (patch)
tree61a111e2d563874929bee68cbacdedb2c5c8fe7e /sys
parent65a703de9cedcd4f2575053d83355135b58b87b4 (diff)
from netbsd:
Re-work the serial console support a bit; it doesn't depend on statically allocated softc's now.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/hp300/dev/dca.c160
-rw-r--r--sys/arch/hp300/dev/dcareg.h10
-rw-r--r--sys/arch/hp300/dev/dcm.c194
3 files changed, 198 insertions, 166 deletions
diff --git a/sys/arch/hp300/dev/dca.c b/sys/arch/hp300/dev/dca.c
index af741cf74ac..7d5eecc6f5d 100644
--- a/sys/arch/hp300/dev/dca.c
+++ b/sys/arch/hp300/dev/dca.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dca.c,v 1.18 1995/12/02 18:15:50 thorpej Exp $ */
+/* $NetBSD: dca.c,v 1.19 1995/12/31 00:27:16 thorpej Exp $ */
/*
* Copyright (c) 1995 Jason R. Thorpe. All rights reserved.
@@ -62,10 +62,12 @@
#include <sys/kernel.h>
#include <sys/syslog.h>
+#include <machine/cpu.h>
+
+#include <dev/cons.h>
+
#include <hp300/dev/device.h>
#include <hp300/dev/dcareg.h>
-
-#include <machine/cpu.h>
#include <hp300/hp300/isr.h>
int dcamatch();
@@ -94,16 +96,23 @@ struct dca_softc {
void dcastart();
int dcaparam(), dcaintr();
int ndca = NDCA;
-#ifdef DCACONSOLE
-int dcaconsole = DCACONSOLE;
-#else
-int dcaconsole = -1;
-#endif
-int dcaconsinit;
int dcadefaultrate = TTYDEF_SPEED;
int dcamajor;
int dcafastservice;
+/*
+ * Stuff for DCA console support. This could probably be done a little
+ * better.
+ */
+static struct dcadevice *dca_cn = NULL; /* pointer to hardware */
+static int dca_lastcnpri = CN_DEAD; /* XXX last priority */
+static int dcaconsinit; /* has been initialized */
+#ifdef DCACONSOLE
+static int dcaconsole = DCACONSOLE;
+#else
+static int dcaconsole = -1;
+#endif
+
struct speedtab dcaspeedtab[] = {
0, 0,
50, DCABRD(50),
@@ -141,6 +150,8 @@ long dcaintrcount[16];
long dcamintcount[16];
#endif
+void dcainit __P((struct dcadevice *, int));
+
int
dcamatch(hd)
register struct hp_device *hd;
@@ -216,7 +227,7 @@ dcaattach(hd)
if (dcaconsole == unit)
kgdb_dev = NODEV; /* can't debug over console port */
else {
- (void) dcainit(sc, kgdb_rate);
+ dcainit(dca, kgdb_rate);
dcaconsinit = 1; /* don't re-init in dcaputc */
if (kgdb_debug_init) {
/*
@@ -270,7 +281,7 @@ dcaopen(dev, flag, mode, p)
* The card might be left in an inconsistent state
* if card memory is read inadvertently.
*/
- dcainit(sc, dcadefaultrate);
+ dcainit(dca, dcadefaultrate);
tp->t_state |= TS_WOPEN;
ttychars(tp);
@@ -846,16 +857,42 @@ dcamctl(sc, bits, how)
return (bits);
}
+void
+dcainit(dca, rate)
+ struct dcadevice *dca;
+ int rate;
+{
+ int s;
+ short stat;
+
+ s = splhigh();
+
+ dca->dca_reset = 0xFF;
+ DELAY(100);
+ dca->dca_ic = IC_IE;
+
+ dca->dca_cfcr = CFCR_DLAB;
+ rate = ttspeedtab(rate, dcaspeedtab);
+ dca->dca_data = rate & 0xFF;
+ dca->dca_ier = rate >> 8;
+ dca->dca_cfcr = CFCR_8BITS;
+ dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
+ dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14;
+ dca->dca_mcr |= MCR_IEN;
+ DELAY(100);
+ stat = dca->dca_iir;
+ splx(s);
+}
+
/*
* Following are all routines needed for DCA to act as console
*/
-#include <dev/cons.h>
void
dcacnprobe(cp)
struct consdev *cp;
{
- struct dca_softc *sc;
+ struct dcadevice *dca;
int unit;
/* locate the major number */
@@ -865,12 +902,11 @@ dcacnprobe(cp)
/* XXX: ick */
unit = CONUNIT;
- sc = &dca_softc[unit];
- sc->sc_dca = (struct dcadevice *) sctova(CONSCODE);
+ dca = (struct dcadevice *)sctova(CONSCODE);
/* make sure hardware exists */
- if (badaddr((short *)sc->sc_dca)) {
+ if (badaddr((short *)dca)) {
cp->cn_pri = CN_DEAD;
return;
}
@@ -878,7 +914,7 @@ dcacnprobe(cp)
/* initialize required fields */
cp->cn_dev = makedev(dcamajor, unit);
- switch (sc->sc_dca->dca_id) {
+ switch (dca->dca_id) {
case DCAID0:
case DCAID1:
cp->cn_pri = CN_NORMAL;
@@ -897,6 +933,17 @@ dcacnprobe(cp)
*/
if (dcaconsole == unit)
cp->cn_pri = CN_REMOTE;
+
+ /*
+ * If our priority is higher than the currently-remembered
+ * DCA, stash our priority and address, for the benefit of
+ * dcacninit().
+ */
+ if (cp->cn_pri > dca_lastcnpri) {
+ dca_lastcnpri = cp->cn_pri;
+ dca_cn = dca;
+ }
+
#ifdef KGDB
if (major(kgdb_dev) == 1) /* XXX */
kgdb_dev = makedev(dcamajor, minor(kgdb_dev));
@@ -908,61 +955,35 @@ dcacninit(cp)
struct consdev *cp;
{
int unit = DCAUNIT(cp->cn_dev);
- struct dca_softc *sc = &dca_softc[unit];
- dcainit(sc, dcadefaultrate);
+ dcainit(dca_cn, dcadefaultrate);
dcaconsole = unit;
dcaconsinit = 1;
}
-dcainit(sc, rate)
- struct dca_softc *sc;
- int rate;
-{
- struct dcadevice *dca = sc->sc_dca;
- int s;
- short stat;
-
-#ifdef lint
- stat = sc->sc_hd->hp_unit; if (stat) return;
-#endif
-
- s = splhigh();
-
- dca->dca_reset = 0xFF;
- DELAY(100);
- dca->dca_ic = IC_IE;
-
- dca->dca_cfcr = CFCR_DLAB;
- rate = ttspeedtab(rate, dcaspeedtab);
- dca->dca_data = rate & 0xFF;
- dca->dca_ier = rate >> 8;
- dca->dca_cfcr = CFCR_8BITS;
- dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
- dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14;
- dca->dca_mcr |= MCR_IEN;
- DELAY(100);
- stat = dca->dca_iir;
- splx(s);
-}
-
+/* ARGSUSED */
int
dcacngetc(dev)
dev_t dev;
{
- struct dca_softc *sc = &dca_softc[DCAUNIT(dev)];
- struct dcadevice *dca = sc->sc_dca;
u_char stat;
int c, s;
#ifdef lint
stat = dev; if (stat) return (0);
#endif
+
+ /*
+ * NOTE: This assumes that DCAUNIT(dev) == dcaconsole. If
+ * it doesn't, well, you lose. (It's also extremely unlikely
+ * that will ever not be the case.)
+ */
+
s = splhigh();
- while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0)
+ while (((stat = dca_cn->dca_lsr) & LSR_RXRDY) == 0)
;
- c = dca->dca_data;
- stat = dca->dca_iir;
+ c = dca_cn->dca_data;
+ stat = dca_cn->dca_iir;
splx(s);
return (c);
}
@@ -970,13 +991,12 @@ dcacngetc(dev)
/*
* Console kernel output character routine.
*/
+/* ARGSUSED */
void
dcacnputc(dev, c)
dev_t dev;
register int c;
{
- struct dca_softc *sc = &dca_softc[DCAUNIT(dev)];
- struct dcadevice *dca = sc->sc_dca;
int timo;
u_char stat;
int s = splhigh();
@@ -984,26 +1004,28 @@ dcacnputc(dev, c)
#ifdef lint
stat = dev; if (stat) return;
#endif
+
+ /*
+ * NOTE: This assumes that DCAUNIT(dev) == dcaconsole. If
+ * it doesn't, well, you lose. (It's also extremely unlikely
+ * that will ever not be the case.)
+ */
+
if (dcaconsinit == 0) {
- (void) dcainit(sc, dcadefaultrate);
+ dcainit(dca_cn, dcadefaultrate);
dcaconsinit = 1;
}
/* wait for any pending transmission to finish */
timo = 50000;
- while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
+ while (((stat = dca_cn->dca_lsr) & LSR_TXRDY) == 0 && --timo)
;
- dca->dca_data = c;
+ dca_cn->dca_data = c;
/* wait for this transmission to complete */
timo = 1500000;
- while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
+ while (((stat = dca_cn->dca_lsr) & LSR_TXRDY) == 0 && --timo)
;
- /*
- * If the "normal" interface was busy transfering a character
- * we must let our interrupt through to keep things moving.
- * Otherwise, we clear the interrupt that we have caused.
- */
- if ((sc->sc_tty->t_state & TS_BUSY) == 0)
- stat = dca->dca_iir;
+ /* clear any interrupts generated by this transmission */
+ stat = dca_cn->dca_iir;
splx(s);
}
-#endif
+#endif /* NDCA > 0 */
diff --git a/sys/arch/hp300/dev/dcareg.h b/sys/arch/hp300/dev/dcareg.h
index 42f957b06ed..d6b76c6cf1a 100644
--- a/sys/arch/hp300/dev/dcareg.h
+++ b/sys/arch/hp300/dev/dcareg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: dcareg.h,v 1.4 1994/10/26 07:23:33 cgd Exp $ */
+/* $NetBSD: dcareg.h,v 1.5 1995/12/31 00:27:19 thorpej Exp $ */
/*
* Copyright (c) 1982, 1986, 1990, 1993
@@ -174,14 +174,6 @@ struct dcadevice {
#define MSR_DDSR 0x02
#define MSR_DCTS 0x01
-#ifdef hp300
/* WARNING: Serial console is assumed to be at SC9 */
#define CONSCODE (9)
-#endif
-#ifdef hp700
-/* hardwired port addresses */
-#define PORT1 ((struct dcadevice *)CORE_RS232_1)
-#define PORT2 ((struct dcadevice *)CORE_RS232_2)
-#define CONPORT PORT1
-#endif
#define CONUNIT (0)
diff --git a/sys/arch/hp300/dev/dcm.c b/sys/arch/hp300/dev/dcm.c
index 11f424db983..12202b9c4cf 100644
--- a/sys/arch/hp300/dev/dcm.c
+++ b/sys/arch/hp300/dev/dcm.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dcm.c,v 1.20 1995/12/02 18:18:50 thorpej Exp $ */
+/* $NetBSD: dcm.c,v 1.22 1995/12/31 00:27:21 thorpej Exp $ */
/*
* Copyright (c) 1995 Jason R. Thorpe. All rights reserved.
@@ -68,6 +68,8 @@
#include <machine/cpu.h>
+#include <dev/cons.h>
+
#include <hp300/dev/device.h>
#include <hp300/dev/dcmreg.h>
#include <hp300/hp300/isr.h>
@@ -122,14 +124,18 @@ struct dcmischeme {
};
/*
- * Console support
+ * Stuff for DCM console support. This could probably be done a little
+ * better.
*/
+static struct dcmdevice *dcm_cn = NULL; /* pointer to hardware */
+static int dcm_lastcnpri = CN_DEAD; /* XXX last priority */
+static int dcmconsinit; /* has been initialized */
#ifdef DCMCONSOLE
-int dcmconsole = DCMCONSOLE;
+static int dcmconsole = DCMCONSOLE;
#else
-int dcmconsole = -1;
+static int dcmconsole = -1;
#endif
-int dcmconsinit;
+
int dcmdefaultrate = DEFAULT_BAUD_RATE;
int dcmconbrdbusy = 0;
int dcmmajor;
@@ -214,7 +220,11 @@ static char iconv[16] = {
MI_RI|MI_CD|MI_CTS|MI_DM
};
-#define NDCMPORT 4 /* XXX what about 8-port cards? */
+/*
+ * Note that 8-port boards appear as 2 4-port boards at consecutive
+ * select codes.
+ */
+#define NDCMPORT 4
struct dcm_softc {
struct hp_device *sc_hd; /* device info */
@@ -228,7 +238,6 @@ struct dcm_softc {
/*
* Mask of soft-carrier bits in config flags.
- * XXX What about 8-port cards?
*/
#define DCM_SOFTCAR 0x0000000f
@@ -246,6 +255,8 @@ struct dcm_softc {
#endif
} dcm_softc[NDCM];
+void dcminit __P((struct dcmdevice *, int, int));
+
int
dcmmatch(hd)
register struct hp_device *hd;
@@ -374,7 +385,8 @@ dcmattach(hd)
* by the corresponding code in dcmcnprobe.
*/
else {
- (void) dcminit(kgdb_dev, kgdb_rate);
+ dcminit(dcm, DCMPORT(DCMUNIT(kgdb_dev)),
+ kgdb_rate);
if (kgdb_debug_init) {
printf("%s port %d: ", sc->sc_hd->hp_xname,
DCMPORT(DCMUNIT(kgdb_dev)));
@@ -428,7 +440,7 @@ dcmopen(dev, flag, mode, p)
* The card might be left in an inconsistent state
* if the card memory is read inadvertently.
*/
- dcminit(dev, dcmdefaultrate);
+ dcminit(sc->sc_dcm, port, dcmdefaultrate);
tp->t_state |= TS_WOPEN;
ttychars(tp);
@@ -1325,16 +1337,50 @@ dcmsetischeme(brd, flags)
SEM_UNLOCK(dcm);
}
+void
+dcminit(dcm, port, rate)
+ struct dcmdevice *dcm;
+ int port, rate;
+{
+ int s, mode;
+
+ mode = LC_8BITS | LC_1STOP;
+
+ s = splhigh();
+
+ /*
+ * Wait for transmitter buffer to empty.
+ */
+ while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
+ DELAY(DCM_USPERCH(rate));
+
+ /*
+ * Make changes known to hardware.
+ */
+ dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab);
+ dcm->dcm_data[port].dcm_conf = mode;
+ SEM_LOCK(dcm);
+ dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
+ dcm->dcm_cr |= (1 << port);
+ SEM_UNLOCK(dcm);
+
+ /*
+ * Delay for config change to take place. Weighted by baud.
+ * XXX why do we do this?
+ */
+ DELAY(16 * DCM_USPERCH(rate));
+ splx(s);
+}
+
/*
* Following are all routines needed for DCM to act as console
*/
-#include <dev/cons.h>
void
dcmcnprobe(cp)
struct consdev *cp;
{
- struct dcm_softc *sc;
+ struct dcm_softc *sc; /* XXX thorpej */
struct dcmdevice *dcm;
struct hp_hw *hw;
int unit;
@@ -1345,6 +1391,7 @@ dcmcnprobe(cp)
break;
/*
+ * XXX FIX ME!
* Implicitly assigns the lowest select code DCM card found to be
* logical unit 0 (actually CONUNIT). If your config file does
* anything different, you're screwed.
@@ -1358,8 +1405,7 @@ dcmcnprobe(cp)
}
unit = CONUNIT;
- sc = &dcm_softc[DCMBOARD(CONUNIT)];
- dcm = sc->sc_dcm = (struct dcmdevice *)hw->hw_kva;
+ dcm = (struct dcmdevice *)hw->hw_kva;
/* initialize required fields */
cp->cn_dev = makedev(dcmmajor, unit);
@@ -1382,6 +1428,17 @@ dcmcnprobe(cp)
*/
if (dcmconsole == unit)
cp->cn_pri = CN_REMOTE;
+
+ /*
+ * If our priority is higher than the currently-remembered
+ * DCM, stash our priority and address, for the benefit of
+ * dcmcninit().
+ */
+ if (cp->cn_pri > dcm_lastcnpri) {
+ dcm_lastcnpri = cp->cn_pri;
+ dcm_cn = dcm;
+ }
+
#ifdef KGDB_CHEAT
/*
* This doesn't currently work, at least not with ite consoles;
@@ -1389,7 +1446,7 @@ dcmcnprobe(cp)
*/
if (major(kgdb_dev) == dcmmajor &&
DCMBOARD(DCMUNIT(kgdb_dev)) == DCMBOARD(unit)) {
- (void) dcminit(kgdb_dev, kgdb_rate);
+ dcminit(dcm_cn, DCMPORT(DCMUNIT(kgdb_dev)), kgdb_rate);
if (kgdb_debug_init) {
/*
* We assume that console is ready for us...
@@ -1408,77 +1465,37 @@ void
dcmcninit(cp)
struct consdev *cp;
{
+ int unit = DCMUNIT(cp->cn_dev);
+ int port = DCMPORT(unit);
- dcminit(cp->cn_dev, dcmdefaultrate);
+ dcminit(dcm_cn, port, dcmdefaultrate);
dcmconsinit = 1;
dcmconsole = DCMUNIT(cp->cn_dev);
}
-dcminit(dev, rate)
- dev_t dev;
- int rate;
-{
- struct dcm_softc *sc;
- struct dcmdevice *dcm;
- int s, mode, unit, board, port;
-
- unit = DCMUNIT(dev);
- board = DCMBOARD(unit);
- port = DCMPORT(unit);
-
- sc = &dcm_softc[board];
- dcm = sc->sc_dcm;
-
- mode = LC_8BITS | LC_1STOP;
-
- s = splhigh();
-
- /*
- * Wait for transmitter buffer to empty.
- */
- while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
- DELAY(DCM_USPERCH(rate));
-
- /*
- * Make changes known to hardware.
- */
- dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab);
- dcm->dcm_data[port].dcm_conf = mode;
- SEM_LOCK(dcm);
- dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
- dcm->dcm_cr |= (1 << port);
- SEM_UNLOCK(dcm);
-
- /*
- * Delay for config change to take place. Weighted by baud.
- * XXX why do we do this?
- */
- DELAY(16 * DCM_USPERCH(rate));
- splx(s);
-}
-
int
dcmcngetc(dev)
dev_t dev;
{
- struct dcm_softc *sc;
- struct dcmdevice *dcm;
struct dcmrfifo *fifo;
struct dcmpreg *pp;
u_int head;
- int s, c, stat, unit, board, port;
+ int s, c, stat, unit, port;
unit = DCMUNIT(dev);
- board = DCMBOARD(unit);
port = DCMPORT(unit);
- sc = &dcm_softc[board];
- dcm = sc->sc_dcm;
- pp = dcm_preg(dcm, port);
+ /*
+ * NOTE: This assumes that unit == dcmconsole. If it doesn't,
+ * well, you lose. (It's also extremely unlikely that will ever
+ * not be the case.)
+ */
+
+ pp = dcm_preg(dcm_cn, port);
s = splhigh();
head = pp->r_head & RX_MASK;
- fifo = &dcm->dcm_rfifos[3-port][head>>1];
+ fifo = &dcm_cn->dcm_rfifos[3-port][head>>1];
while (head == (pp->r_tail & RX_MASK))
;
/*
@@ -1486,10 +1503,10 @@ dcmcngetc(dev)
* interrupt through in case some other port on the board was
* busy. Otherwise we must clear the interrupt.
*/
- SEM_LOCK(dcm);
- if ((dcm->dcm_ic & IC_IE) == 0)
- stat = dcm->dcm_iir;
- SEM_UNLOCK(dcm);
+ SEM_LOCK(dcm_cn);
+ if ((dcm_cn->dcm_ic & IC_IE) == 0)
+ stat = dcm_cn->dcm_iir;
+ SEM_UNLOCK(dcm_cn);
c = fifo->data_char;
stat = fifo->data_stat;
pp->r_head = (head + 2) & RX_MASK;
@@ -1505,37 +1522,38 @@ dcmcnputc(dev, c)
dev_t dev;
int c;
{
- struct dcm_softc *sc;
- struct dcmdevice *dcm;
struct dcmpreg *pp;
unsigned tail;
- int s, unit, board, port, stat;
+ int s, unit, port, stat;
unit = DCMUNIT(dev);
- board = DCMBOARD(unit);
port = DCMPORT(unit);
- sc = &dcm_softc[board];
- dcm = sc->sc_dcm;
- pp = dcm_preg(dcm, port);
+ /*
+ * NOTE: This assumes that unit == dcmconsole. If it doesn't,
+ * well, you lose. (It's also extremely unlikely that will ever
+ * not be the case.)
+ */
+
+ pp = dcm_preg(dcm_cn, port);
s = splhigh();
#ifdef KGDB
if (dev != kgdb_dev)
#endif
if (dcmconsinit == 0) {
- (void) dcminit(dev, dcmdefaultrate);
+ dcminit(dcm_cn, port, dcmdefaultrate);
dcmconsinit = 1;
}
tail = pp->t_tail & TX_MASK;
while (tail != (pp->t_head & TX_MASK))
;
- dcm->dcm_tfifos[3-port][tail].data_char = c;
+ dcm_cn->dcm_tfifos[3-port][tail].data_char = c;
pp->t_tail = tail = (tail + 1) & TX_MASK;
- SEM_LOCK(dcm);
- dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
- dcm->dcm_cr |= (1 << port);
- SEM_UNLOCK(dcm);
+ SEM_LOCK(dcm_cn);
+ dcm_cn->dcm_cmdtab[port].dcm_data |= CT_TX;
+ dcm_cn->dcm_cr |= (1 << port);
+ SEM_UNLOCK(dcm_cn);
while (tail != (pp->t_head & TX_MASK))
;
/*
@@ -1543,11 +1561,11 @@ dcmcnputc(dev, c)
* interrupt through in case some other port on the board
* was busy. Otherwise we must clear the interrupt.
*/
- if ((dcm->dcm_ic & IC_IE) == 0) {
- SEM_LOCK(dcm);
- stat = dcm->dcm_iir;
- SEM_UNLOCK(dcm);
+ if ((dcm_cn->dcm_ic & IC_IE) == 0) {
+ SEM_LOCK(dcm_cn);
+ stat = dcm_cn->dcm_iir;
+ SEM_UNLOCK(dcm_cn);
}
splx(s);
}
-#endif
+#endif /* NDCM > 0 */