From e9b5ce7bb5c9930a3aca4543f63b52c84fa5adbf Mon Sep 17 00:00:00 2001 From: Theo de Raadt Date: Fri, 5 Jan 1996 13:35:51 +0000 Subject: from netbsd: Re-work the serial console support a bit; it doesn't depend on statically allocated softc's now. --- sys/arch/hp300/dev/dca.c | 160 ++++++++++++++++++++---------------- sys/arch/hp300/dev/dcareg.h | 10 +-- sys/arch/hp300/dev/dcm.c | 194 ++++++++++++++++++++++++-------------------- 3 files changed, 198 insertions(+), 166 deletions(-) (limited to 'sys/arch/hp300/dev') 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 #include +#include + +#include + #include #include - -#include #include 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 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 +#include + #include #include #include @@ -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 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 */ -- cgit v1.2.3