diff options
author | Thomas Graichen <graichen@cvs.openbsd.org> | 1996-12-22 15:19:07 +0000 |
---|---|---|
committer | Thomas Graichen <graichen@cvs.openbsd.org> | 1996-12-22 15:19:07 +0000 |
commit | ca1c7fedd990e6b1e7244233df5a6a638f0e4e31 (patch) | |
tree | 20016b11dce3c72001f0e250c8f1a714ed64e546 /sys/arch/pmax/dev/dc.c | |
parent | de4c3561677938c64d13b1e5112686a88b0b47fe (diff) |
update the pmax stuff to NetBSD 961107 - this version i got somehow
compiled on my decstation 2100 (PLUTO) - but it will not fully work
out of the box - but i want to bring it into the tree because i get
my own pmax on 961228 - so that i have a good startpoint then :-)
all the OpenBSD changes to the pmax tree will follow in the next commit
Diffstat (limited to 'sys/arch/pmax/dev/dc.c')
-rw-r--r-- | sys/arch/pmax/dev/dc.c | 756 |
1 files changed, 481 insertions, 275 deletions
diff --git a/sys/arch/pmax/dev/dc.c b/sys/arch/pmax/dev/dc.c index 0a180c1cd49..8b5712d7372 100644 --- a/sys/arch/pmax/dev/dc.c +++ b/sys/arch/pmax/dev/dc.c @@ -1,4 +1,4 @@ -/* $NetBSD: dc.c,v 1.16.4.5 1996/06/16 17:15:51 mhitch Exp $ */ +/* $NetBSD: dc.c,v 1.30 1996/10/16 02:10:33 jonathan Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)dc.c 8.2 (Berkeley) 11/30/93 + * @(#)dc.c 8.5 (Berkeley) 6/2/95 */ /* @@ -56,11 +56,10 @@ * v 1.4 89/08/29 11:55:30 nelson Exp SPRITE (DECWRL)"; */ -#include "dc.h" -#if NDC > 0 /* * DC7085 (DZ-11 look alike) Driver */ + #include <sys/param.h> #include <sys/systm.h> #include <sys/ioctl.h> @@ -77,7 +76,6 @@ #include <machine/conf.h> #include <sys/device.h> #include <machine/autoconf.h> -#include <machine/machConst.h> #include <dev/tc/tcvar.h> #include <dev/tc/ioasicvar.h> @@ -87,21 +85,25 @@ #include <pmax/pmax/pmaxtype.h> #include <pmax/pmax/cons.h> -#include <pmax/dev/pdma.h> #include <pmax/dev/lk201.h> +/* + * XXX in dcvar.h or not? + * #include <pmax/dev/pdma.h> + */ #include "dcvar.h" + #include "tc.h" #include <pmax/dev/lk201var.h> /* XXX KbdReset band friends */ -extern int pmax_boardtype; +#include <pmax/dev/dcvar.h> +#include <pmax/dev/dc_cons.h> + extern struct cfdriver mainbus_cd; -struct dc_softc { - struct device sc_dv; - struct pdma dc_pdma[4]; -}; +#define DCUNIT(dev) (minor(dev) >> 2) +#define DCLINE(dev) (minor(dev) & 3) /* * Autoconfiguration data for config. @@ -109,47 +111,49 @@ struct dc_softc { * Use the statically-allocated softc until old autoconfig code and * config.old are completely gone. */ -int dcmatch __P((struct device * parent, void *cfdata, void *aux)); -void dcattach __P((struct device *parent, struct device *self, void *aux)); +int old_dcmatch __P((struct device * parent, void *cfdata, void *aux)); +void old_dcattach __P((struct device *parent, struct device *self, void *aux)); -int dc_doprobe __P((void *addr, int unit, int flags, int pri)); -int dcintr __P((void * xxxunit)); extern struct cfdriver dc_cd; - -struct cfattach dc_ca = { - sizeof(struct dc_softc), dcmatch, dcattach -}; - struct cfdriver dc_cd = { NULL, "dc", DV_TTY }; -#define NDCLINE (NDC*4) +/* + * Forward declarations + */ +struct tty *dctty __P((dev_t dev)); void dcstart __P((struct tty *)); +void dcrint __P((struct dc_softc *sc)); void dcxint __P((struct tty *)); -void dcPutc __P((dev_t, int)); +int dcmctl __P((dev_t dev, int bits, int how)); void dcscan __P((void *)); +int dcparam __P((struct tty *tp, struct termios *t)); +static int cold_dcparam __P((struct tty *tp, struct termios *t, + dcregs *dcaddr, int allow_19200)); + extern void ttrstrt __P((void *)); -int dcGetc __P((dev_t)); -int dcparam __P((struct tty *, struct termios *)); - -struct tty *dc_tty[NDCLINE]; -int dc_cnt = NDCLINE; -void (*dcDivertXInput)(); /* X windows keyboard input routine */ -void (*dcMouseEvent)(); /* X windows mouse motion event routine */ -void (*dcMouseButtons)(); /* X windows mouse buttons event routine */ + +void dc_reset __P ((dcregs *dcaddr)); + +/* console I/O */ +int dcGetc __P((dev_t)); +void dcPutc __P((dev_t, int)); +void dcPollc __P((dev_t, int)); +void dc_consinit __P((dev_t dev, dcregs *dcaddr)); + + +/* QVSS-compatible in-kernel X input event parser, pointer tracker */ +void (*dcDivertXInput) __P((int cc)); /* X windows keyboard input routine */ +void (*dcMouseEvent) __P((int)); /* X windows mouse motion event routine */ +void (*dcMouseButtons) __P((int)); /* X windows mouse buttons event routine */ #ifdef DEBUG int debugChar; #endif -/* - * Software copy of brk register since it isn't readable - */ -int dc_brk[NDC]; -char dcsoftCAR[NDC]; /* mask of dc's with carrier on (DSR) */ /* * The DC7085 doesn't interrupt on carrier transitions, so @@ -160,7 +164,6 @@ int dc_timer; /* true if timer started */ /* * Pdma structures for fast output code */ -struct pdma dcpdma[NDCLINE]; struct speedtab dcspeedtab[] = { { 0, 0, }, @@ -177,6 +180,9 @@ struct speedtab dcspeedtab[] = { { 4800, LPR_B4800 }, { 9600, LPR_B9600 }, { 19200,LPR_B19200 }, +#ifdef notyet + { 19200,LPR_B38400 }, /* Overloaded with 19200, per chip. */ +#endif { -1, -1 } }; @@ -189,96 +195,10 @@ struct speedtab dcspeedtab[] = { #endif /* - * Forward declarations + * Console line variables, for use when cold */ -struct tty *dctty __P((dev_t dev)); -void dcrint __P((int)); -int dcmctl __P((dev_t dev, int bits, int how)); - - - -/* - * Match driver based on name - */ -int -dcmatch(parent, match, aux) - struct device *parent; - void *match; - void *aux; -{ - struct confargs *ca = aux; -#if NTC>0 - struct ioasicdev_attach_args *d = aux; -#endif - - static int nunits = 0; - -#if NTC > 0 - if (parent->dv_cfdata->cf_driver == &ioasic_cd) { - if (strcmp(d->iada_modname, "dc") != 0 && - strcmp(d->iada_modname, "dc7085") != 0) - return (0); - } - else -#endif /* NTC */ - - if (parent->dv_cfdata->cf_driver == &mainbus_cd) { - if (strcmp(ca->ca_name, "dc") != 0 && - strcmp(ca->ca_name, "mdc") != 0 && - strcmp(ca->ca_name, "dc7085") != 0) - return (0); - } - else - return (0); - - /* - * Use statically-allocated softc and attach code until - * old config is completely gone. Don't over-run softc. - */ - if (nunits > NDC) { - printf("dc: too many units for old config\n"); - return (0); - } - nunits++; - return (1); -} - -void -dcattach(parent, self, aux) - struct device *parent; - struct device *self; - void *aux; -{ - register struct confargs *ca = aux; -#if NTC > 0 - struct ioasicdev_attach_args *d = aux; -#endif /* NTC */ - caddr_t dcaddr; - - -#if NTC > 0 - if (parent->dv_cfdata->cf_driver == &ioasic_cd) { - dcaddr = (caddr_t)d->iada_addr; - (void) dc_doprobe((void*)MACH_PHYS_TO_UNCACHED(dcaddr), - self->dv_unit, self->dv_cfdata->cf_flags, - (int)d->iada_cookie); - /* tie pseudo-slot to device */ - ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_TTY, - dcintr, self); - } - else -#endif /* NTC */ - if (parent->dv_cfdata->cf_driver == &mainbus_cd) { - dcaddr = (caddr_t)ca->ca_addr; - (void) dc_doprobe((void*)MACH_PHYS_TO_UNCACHED(dcaddr), - self->dv_unit, self->dv_cfdata->cf_flags, - ca->ca_slot); - - /* tie pseudo-slot to device */ - BUS_INTR_ESTABLISH(ca, dcintr, self); - } - printf("\n"); -} +extern int cold; +dcregs *dc_cons_addr = 0; /* * Is there a framebuffer console device using this serial driver? @@ -295,66 +215,113 @@ raster_console() } +/* XXX move back into dc_consinit when debugged */ +static struct consdev dccons = { + NULL, NULL, dcGetc, dcPutc, dcPollc, NODEV, CN_REMOTE +}; + +/* + * Special-case code to attach a console. + * We were using PROM callbacks for console I/O, + * and we just reset the chip under the console. + * wire up this driver as console ASAP. + * + * Must be called at spltty() or higher. + */ +void +dc_consinit(dev, dcaddr) + dev_t dev; + register dcregs *dcaddr; +{ + struct termios cterm; + struct tty ctty; + + /* save address in case we're cold */ + if (cold && dc_cons_addr == 0) + dc_cons_addr = dcaddr; + + /* reset chip */ + dc_reset(dcaddr); + + dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | + LPR_B9600 | DCLINE(dev); + wbflush(); + DELAY(10); + + bzero(&cterm, sizeof(cterm)); + bzero(&ctty, sizeof(ctty)); + ctty.t_dev = dev; + dccons.cn_dev = dev; + cterm.c_cflag |= CLOCAL; + cterm.c_cflag = CS8; + cterm.c_ospeed = 9600; + *cn_tab = dccons; + cold_dcparam(&ctty, &cterm, dcaddr, 0); /* XXX untested */ +} + + /* - * DC7085 (dz-11) probe routine from old-style config. - * This is only here out of intertia. + * Attach DC7085 (dz-11) device. */ int -dc_doprobe(addr, unit, flags, priority) +dcattach(sc, addr, dtr_mask, rtscts_mask, speed, + console_line) + register struct dc_softc *sc; void *addr; - int unit, flags, priority; + int dtr_mask, rtscts_mask, speed, console_line; { register dcregs *dcaddr; register struct pdma *pdp; register struct tty *tp; - register int cntr; + register int line; int s; - - if (unit >= NDC) - return (0); - if (badaddr(addr, 2)) - return (0); + + dcaddr = (dcregs *)addr; /* * For a remote console, wait a while for previous output to * complete. + * XXX both cn_dev == 0 and cn_pri == CN_DEAD are bug workarounds. + * The interface between ttys and cpu_cons.c should be reworked. */ - if (major(cn_tab->cn_dev) == DCDEV && unit == 0 && - cn_tab->cn_pri == CN_REMOTE) + if (sc->sc_dv.dv_unit == 0 && /* XXX why only unit 0? */ + (major(cn_tab->cn_dev) == DCDEV || major(cn_tab->cn_dev) == 0) && + (cn_tab->cn_pri == CN_REMOTE || (cn_tab->cn_pri == CN_DEAD))) { DELAY(10000); - - /* reset chip */ - dcaddr = (dcregs *)addr; - dcaddr->dc_csr = CSR_CLR; - wbflush(); - while (dcaddr->dc_csr & CSR_CLR) - ; - dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE; + } + /* reset chip and enable interrupts */ + dc_reset(dcaddr); + dcaddr->dc_csr |= (CSR_MSE | CSR_TIE | CSR_RIE); /* init pseudo DMA structures */ - pdp = &dcpdma[unit * 4]; - for (cntr = 0; cntr < 4; cntr++) { + pdp = &sc->dc_pdma[0]; + for (line = 0; line < 4; line++) { pdp->p_addr = (void *)dcaddr; - tp = dc_tty[unit * 4 + cntr] = ttymalloc(); - if (cntr != DCKBD_PORT && cntr != DCMOUSE_PORT) + tp = sc->dc_tty[line] = ttymalloc(); + if (line != DCKBD_PORT && line != DCMOUSE_PORT) tty_attach(tp); + tp->t_dev = makedev(DCDEV, 4 * sc->sc_dv.dv_unit + line); pdp->p_arg = (int) tp; pdp->p_fcn = dcxint; pdp++; } - dcsoftCAR[unit] = flags | 0xB; + sc->dcsoftCAR = sc->sc_dv.dv_cfdata->cf_flags | 0xB; if (dc_timer == 0) { dc_timer = 1; timeout(dcscan, (void *)0, hz); } + sc->dc_19200 = speed; + sc->dc_modem = dtr_mask; + sc->dc_rtscts = rtscts_mask; + + /* * Special handling for consoles. */ - if (unit == 0) { - if (cn_tab->cn_pri == CN_INTERNAL || - cn_tab->cn_pri == CN_NORMAL) { + if (sc->sc_dv.dv_unit == 0) { + if (raster_console()) { s = spltty(); dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | LPR_B4800 | DCKBD_PORT; @@ -366,20 +333,42 @@ dc_doprobe(addr, unit, flags, priority) KBDReset(makedev(DCDEV, DCKBD_PORT), dcPutc); MouseInit(makedev(DCDEV, DCMOUSE_PORT), dcPutc, dcGetc); splx(s); - } else if (major(cn_tab->cn_dev) == DCDEV) { + } + else if (major(cn_tab->cn_dev) == DCDEV) { s = spltty(); - dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | - LPR_B9600 | minor(cn_tab->cn_dev); - wbflush(); - DELAY(1000); - /*cn_tab.cn_disabled = 0;*/ /* FIXME */ + dc_consinit(cn_tab->cn_dev, dcaddr); + dcaddr->dc_csr |= (CSR_MSE | CSR_TIE | CSR_RIE); splx(s); } } - return (1); } + +/* + * Reset chip. Does not change modem control output bits + * or modem state register. + * Does not enable interrupts; caller must explicitly or + * TIE and RIE on if desired (XXX not true yet) + */ +void +dc_reset(dcaddr) + register dcregs *dcaddr; +{ + /* Reset CSR and wait until cleared. */ + dcaddr->dc_csr = CSR_CLR; + wbflush(); + DELAY(10); + while (dcaddr->dc_csr & CSR_CLR) + ; + + /* Enable scanner. */ + dcaddr->dc_csr = CSR_MSE; + wbflush(); + DELAY(10); +} + + int dcopen(dev, flag, mode, p) dev_t dev; @@ -387,15 +376,22 @@ dcopen(dev, flag, mode, p) struct proc *p; { register struct tty *tp; - register int unit; + register struct dc_softc *sc; + register int unit, line; int s, error = 0; - unit = minor(dev); - if (unit >= dc_cnt || dcpdma[unit].p_addr == (void *)0) + unit = DCUNIT(dev); + line = DCLINE(dev); + if (unit >= dc_cd.cd_ndevs || line > 4) return (ENXIO); - tp = dc_tty[unit]; + + sc = dc_cd.cd_devs[unit]; + if (sc->dc_pdma[line].p_addr == (void *)0) + return (ENXIO); + + tp = sc->dc_tty[line]; if (tp == NULL) { - tp = dc_tty[unit] = ttymalloc(); + tp = sc->dc_tty[line] = ttymalloc(); tty_attach(tp); } tp->t_oproc = dcstart; @@ -421,7 +417,14 @@ dcopen(dev, flag, mode, p) ttsetwater(tp); } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) return (EBUSY); +#ifdef HW_FLOW_CONTROL + (void) dcmctl(dev, DML_DTR | DML_RTS, DMSET); +#else (void) dcmctl(dev, DML_DTR, DMSET); +#endif + if ((sc->dcsoftCAR & (1 << line)) || + (dcmctl(dev, 0, DMGET) & DML_CAR)) + tp->t_state |= TS_CARR_ON; s = spltty(); while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && !(tp->t_state & TS_CARR_ON)) { @@ -443,16 +446,22 @@ dcclose(dev, flag, mode, p) int flag, mode; struct proc *p; { + register struct dc_softc *sc; register struct tty *tp; - register int unit, bit; + register int line, bit; + int s; - unit = minor(dev); - tp = dc_tty[unit]; - bit = 1 << ((unit & 03) + 8); - if (dc_brk[unit >> 2] & bit) { - dc_brk[unit >> 2] &= ~bit; + sc = dc_cd.cd_devs[DCUNIT(dev)]; + line = DCLINE(dev); + tp = sc->dc_tty[line]; + bit = 1 << (line + 8); + s = spltty(); + /* turn off the break bit if it is set */ + if (sc->dc_brk & bit) { + sc->dc_brk &= ~bit; ttyoutput(0, tp); } + splx(s); (*linesw[tp->t_line].l_close)(tp, flag); if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || !(tp->t_state & TS_ISOPEN)) @@ -465,9 +474,20 @@ dcread(dev, uio, flag) dev_t dev; struct uio *uio; { + register struct dc_softc *sc; register struct tty *tp; - tp = dc_tty[minor(dev)]; + sc = dc_cd.cd_devs[DCUNIT(dev)]; + tp = sc->dc_tty[DCLINE(dev)]; + +#ifdef HW_FLOW_CONTROL + if ((tp->t_cflag & CRTS_IFLOW) && (tp->t_state & TS_TBLOCK) && + tp->t_rawq.c_cc < TTYHOG/5) { + tp->t_state &= ~TS_TBLOCK; + (void) dcmctl(dev, DML_RTS, DMBIS); + } +#endif /* HW_FLOW_CONTROL */ + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } @@ -476,9 +496,11 @@ dcwrite(dev, uio, flag) dev_t dev; struct uio *uio; { + register struct dc_softc *sc; register struct tty *tp; - tp = dc_tty[minor(dev)]; + sc = dc_cd.cd_devs[DCUNIT(dev)]; + tp = sc->dc_tty[DCLINE(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); } @@ -486,7 +508,11 @@ struct tty * dctty(dev) dev_t dev; { - struct tty *tp = dc_tty [minor (dev)]; + register struct dc_softc *sc; + register struct tty *tp; + + sc = dc_cd.cd_devs[DCUNIT(dev)]; + tp = sc->dc_tty[DCLINE(dev)]; return (tp); } @@ -499,12 +525,18 @@ dcioctl(dev, cmd, data, flag, p) int flag; struct proc *p; { + register struct dc_softc *sc; register struct tty *tp; - register int unit = minor(dev); - register int dc = unit >> 2; + register int unit; + register int line; int error; - tp = dc_tty[unit]; + + unit = DCUNIT(dev); + line = DCLINE(dev); + sc = dc_cd.cd_devs[unit]; + tp = sc->dc_tty[line]; + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error >= 0) return (error); @@ -515,12 +547,12 @@ dcioctl(dev, cmd, data, flag, p) switch (cmd) { case TIOCSBRK: - dc_brk[dc] |= 1 << ((unit & 03) + 8); + sc->dc_brk |= 1 << (line + 8); ttyoutput(0, tp); break; case TIOCCBRK: - dc_brk[dc] &= ~(1 << ((unit & 03) + 8)); + sc->dc_brk &= ~(1 << (line + 8)); ttyoutput(0, tp); break; @@ -554,55 +586,77 @@ dcioctl(dev, cmd, data, flag, p) return (0); } +/* + * Set line parameters + */ + int dcparam(tp, t) register struct tty *tp; register struct termios *t; { + register struct dc_softc *sc; + register dcregs *dcaddr; + + + /* + * Extract softc data, and pass entire request onto + * cold_dcparam() for argument checking and execution. + */ + sc = dc_cd.cd_devs[DCUNIT(tp->t_dev)]; + dcaddr = (dcregs *)sc->dc_pdma[0].p_addr; + return (cold_dcparam(tp, t, dcaddr, sc->dc_19200)); + +} + +int +cold_dcparam(tp, t, dcaddr, allow_19200) + register struct tty *tp; + register struct termios *t; register dcregs *dcaddr; + int allow_19200; +{ register int lpr; register int cflag = t->c_cflag; int unit = minor(tp->t_dev); int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab); + int s; + int line; + + line = DCLINE(tp->t_dev); /* check requested parameters */ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) || (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6 || - (pmax_boardtype == DS_PMAX && t->c_ospeed == 19200)) + (t->c_ospeed >= 19200 && allow_19200 != 1)) return (EINVAL); /* and copy to tty */ tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; tp->t_cflag = cflag; - dcaddr = (dcregs *)dcpdma[unit].p_addr; - /* * Handle console cases specially. */ if (raster_console()) { if (unit == DCKBD_PORT) { - dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | + lpr = LPR_RXENAB | LPR_8_BIT_CHAR | LPR_B4800 | DCKBD_PORT; - wbflush(); - return (0); + goto out; } else if (unit == DCMOUSE_PORT) { - dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | + lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT; - wbflush(); - return (0); + goto out; } } else if (tp->t_dev == cn_tab->cn_dev) { - dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | - LPR_B9600 | unit; - wbflush(); - return (0); + lpr = LPR_RXENAB | LPR_8_BIT_CHAR | LPR_B9600 | line; + goto out; } if (ospeed == 0) { (void) dcmctl(unit, 0, DMSET); /* hang up line */ return (0); } - lpr = LPR_RXENAB | ospeed | (unit & 03); + lpr = LPR_RXENAB | ospeed | line; if ((cflag & CSIZE) == CS7) lpr |= LPR_7_BIT_CHAR; else @@ -613,12 +667,16 @@ dcparam(tp, t) lpr |= LPR_OPAR; if (cflag & CSTOPB) lpr |= LPR_2_STOP; +out: + s = spltty(); dcaddr->dc_lpr = lpr; wbflush(); + splx(s); DELAY(10); return (0); } + /* * Check for interrupts from all devices. */ @@ -630,40 +688,42 @@ dcintr(xxxunit) register dcregs *dcaddr; register unsigned csr; - register int unit = sc->sc_dv.dv_unit; - - unit <<= 2; - dcaddr = (dcregs *)dcpdma[unit].p_addr; + dcaddr = (dcregs *)sc->dc_pdma[0].p_addr; while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) { if (csr & CSR_RDONE) - dcrint(unit); + dcrint(sc); if (csr & CSR_TRDY) - dcxint(dc_tty[unit + ((csr >> 8) & 03)]); + dcxint(sc->dc_tty[((csr >> 8) & 03)]); } /* XXX check for spurious interrupts */ return 0; } void -dcrint(unit) - register int unit; +dcrint(sc) + register struct dc_softc * sc; { register dcregs *dcaddr; register struct tty *tp; register int c, cc; int overrun = 0; + register struct tty **dc_tty; - dcaddr = (dcregs *)dcpdma[unit].p_addr; + dc_tty = ((struct dc_softc*)dc_cd.cd_devs[0])->dc_tty; /* XXX */ + + dcaddr = (dcregs *)sc->dc_pdma[0].p_addr; /*XXX*/ while ((c = dcaddr->dc_rbuf) < 0) { /* char present */ cc = c & 0xff; - tp = dc_tty[unit + ((c >> 8) & 03)]; + tp = sc->dc_tty[((c >> 8) & 03)]; + if ((c & RBUF_OERR) && overrun == 0) { - log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2, + log(LOG_WARNING, "%s,%d: silo overflow\n", + sc->sc_dv.dv_xname, (c >> 8) & 03); overrun = 1; } /* the keyboard requires special translation */ - if (tp == dc_tty[DCKBD_PORT] && raster_console()) { + if (raster_console() && tp == dc_tty[DCKBD_PORT]) { #ifdef KADB if (cc == LK_DO) { spl0(); @@ -695,6 +755,13 @@ dcrint(unit) cc |= TTY_FE; if (c & RBUF_PERR) cc |= TTY_PE; +#ifdef HW_FLOW_CONTROL + if ((tp->t_cflag & CRTS_IFLOW) && !(tp->t_state & TS_TBLOCK) && + tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) { + tp->t_state &= ~TS_TBLOCK; + (void) dcmctl(tp->t_dev, DML_RTS, DMBIC); + } +#endif /* HWW_FLOW_CONTROL */ (*linesw[tp->t_line].l_rint)(cc, tp); } DELAY(10); @@ -704,14 +771,48 @@ void dcxint(tp) register struct tty *tp; { + register struct dc_softc *sc; register struct pdma *dp; register dcregs *dcaddr; - int unit = minor(tp->t_dev); + int line, linemask; - dp = &dcpdma[unit]; + sc = dc_cd.cd_devs[DCUNIT(tp->t_dev)]; /* XXX */ + + line = DCLINE(tp->t_dev); + linemask = 1 << line; + + dp = &sc->dc_pdma[line]; if (dp->p_mem < dp->p_end) { dcaddr = (dcregs *)dp->p_addr; - dcaddr->dc_tdr = dc_brk[unit >> 2] | *dp->p_mem++; + +#ifdef HW_FLOW_CONTROL + /* check for hardware flow control of output */ + if ((tp->t_cflag & CCTS_OFLOW) && (sc->dc_rtscts & linemask)) { + switch (line) { + case 2: + if (dcaddr->dc_msr & MSR_CTS2) + break; + goto stop; + + case 3: + if (dcaddr->dc_msr & MSR_CTS3) + break; + stop: + tp->t_state &= ~TS_BUSY; + tp->t_state |= TS_TTSTOP; + ndflush(&tp->t_outq, dp->p_mem - + (caddr_t)tp->t_outq.c_cf); + dp->p_end = dp->p_mem = tp->t_outq.c_cf; + dcaddr->dc_tcr &= ~(1 << line); + wbflush(); + DELAY(10); + return; + } + } +#endif /* HW_FLOW_CONTROL */ + dcaddr->dc_tdr = sc->dc_brk | *(u_char *)dp->p_mem; + dp->p_mem++; + wbflush(); DELAY(10); return; @@ -729,7 +830,7 @@ dcxint(tp) dcstart(tp); if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { dcaddr = (dcregs *)dp->p_addr; - dcaddr->dc_tcr &= ~(1 << (unit & 03)); + dcaddr->dc_tcr &= ~(1 << line); wbflush(); DELAY(10); } @@ -739,12 +840,15 @@ void dcstart(tp) register struct tty *tp; { + register struct dc_softc *sc; register struct pdma *dp; register dcregs *dcaddr; register int cc; - int s; + int line, s; - dp = &dcpdma[minor(tp->t_dev)]; + sc = dc_cd.cd_devs[DCUNIT(tp->t_dev)]; + line = DCLINE(tp->t_dev); + dp = &sc->dc_pdma[line]; dcaddr = (dcregs *)dp->p_addr; s = spltty(); if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) @@ -759,7 +863,7 @@ dcstart(tp) if (tp->t_outq.c_cc == 0) goto out; /* handle console specially */ - if (tp == dc_tty[DCKBD_PORT] && raster_console()) { + if (raster_console() && tp == sc->dc_tty[DCKBD_PORT]) { while (tp->t_outq.c_cc > 0) { cc = getc(&tp->t_outq) & 0x7f; cnputc(cc); @@ -777,14 +881,13 @@ dcstart(tp) } goto out; } - cc = ndqb(&tp->t_outq, 0); - if (cc == 0) + cc = ndqb(&tp->t_outq, 0); + if (cc == 0) goto out; - tp->t_state |= TS_BUSY; dp->p_end = dp->p_mem = tp->t_outq.c_cf; dp->p_end += cc; - dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03); + dcaddr->dc_tcr |= 1 << line; wbflush(); out: splx(s); @@ -794,14 +897,16 @@ out: * Stop output on a line. */ /*ARGSUSED*/ -int +int /* was void TTTTT */ dcstop(tp, flag) register struct tty *tp; { + register struct dc_softc *sc; register struct pdma *dp; register int s; - dp = &dcpdma[minor(tp->t_dev)]; + sc = dc_cd.cd_devs[DCUNIT(tp->t_dev)]; + dp = &sc->dc_pdma[DCLINE(tp->t_dev)]; s = spltty(); if (tp->t_state & TS_BUSY) { dp->p_end = dp->p_mem; @@ -809,8 +914,6 @@ dcstop(tp, flag) tp->t_state |= TS_FLUSH; } splx(s); - - return (0); } int @@ -818,38 +921,62 @@ dcmctl(dev, bits, how) dev_t dev; int bits, how; { + register struct dc_softc *sc; register dcregs *dcaddr; - register int unit, mbits; + register int line, mbits; int b, s; - register int msr; + register int tcr, msr; - unit = minor(dev); - b = 1 << (unit & 03); - dcaddr = (dcregs *)dcpdma[unit].p_addr; + line = DCLINE(dev); + sc = dc_cd.cd_devs[DCUNIT(dev)]; + b = 1 << line; + dcaddr = (dcregs *)sc->dc_pdma[line].p_addr; s = spltty(); - /* only channel 2 has modem control (what about line 3?) */ + /* only channel 2 has modem control on a DECstation 2100/3100 */ mbits = DML_DTR | DML_DSR | DML_CAR; - switch (unit & 03) { - case 2: +#ifdef HW_FLOW_CONTROL + mbits != DML_RTS; +#endif /* HW_FLOW_CONTROL */ + switch (line) { + case 2: /* pmax partial-modem comms port, full-modem port on 3max */ mbits = 0; - if (dcaddr->dc_tcr & TCR_DTR2) + tcr = dcaddr->dc_tcr; + if (tcr & TCR_DTR2) mbits |= DML_DTR; + if ((sc->dc_rtscts & (1<<line)) && (tcr & TCR_RTS2)) + mbits |= DML_RTS; msr = dcaddr->dc_msr; if (msr & MSR_CD2) mbits |= DML_CAR; if (msr & MSR_DSR2) { - if (pmax_boardtype == DS_PMAX) + /* + * XXX really tests for DS_PMAX instead of DS_3MAX + * but close enough for now. Vaxes? + */ + if ((sc->dc_rtscts & (1 << line )) == 0 && + (sc->dc_modem & (1 << line ))) mbits |= DML_CAR | DML_DSR; else mbits |= DML_DSR; } break; - case 3: - if (pmax_boardtype != DS_PMAX) { + case 3: /* no modem control on pmax, console port on 3max */ + /* + * XXX really tests for DS_3MAX instead of DS_PMAX + * but close enough for now. Vaxes? + */ + if ( sc->dc_modem & (1 << line )) { mbits = 0; - if (dcaddr->dc_tcr & TCR_DTR3) + tcr = dcaddr->dc_tcr; + if (tcr & TCR_DTR3) mbits |= DML_DTR; +#ifdef HW_FLOW_CONTROL + /* XXX OK for get, but not for set? */ + /*if ( sc->dc_rtscts & (1 << line ))*/ + if (tcr & TCR_RTS3) + mbits |= DML_RTS; +#endif /*HW_FLOW_CONTROL*/ msr = dcaddr->dc_msr; if (msr & MSR_CD3) mbits |= DML_CAR; @@ -874,24 +1001,42 @@ dcmctl(dev, bits, how) (void) splx(s); return (mbits); } - switch (unit & 03) { - case 2: + switch (line) { + case 2: /* 2 */ + tcr = dcaddr->dc_tcr; if (mbits & DML_DTR) - dcaddr->dc_tcr |= TCR_DTR2; + tcr |= TCR_DTR2; else - dcaddr->dc_tcr &= ~TCR_DTR2; + tcr &= ~TCR_DTR2; + /*if (pmax_boardtype != DS_PMAX)*/ + if (sc->dc_rtscts & (1 << line)) { + if (mbits & DML_RTS) + tcr |= TCR_RTS2; + else + tcr &= ~TCR_RTS2; + } + dcaddr->dc_tcr = tcr; break; case 3: - if (pmax_boardtype != DS_PMAX) { + /* XXX DTR not supported on this line on 2100/3100 */ + /*if (pmax_boardtype != DS_PMAX)*/ + if (sc->dc_modem & (1 << line)) { + tcr = dcaddr->dc_tcr; if (mbits & DML_DTR) - dcaddr->dc_tcr |= TCR_DTR3; + tcr |= TCR_DTR3; else - dcaddr->dc_tcr &= ~TCR_DTR3; + tcr &= ~TCR_DTR3; +#ifdef HW_FLOW_CONTROL + /*if (sc->dc_rtscts & (1 << line))*/ + if (mbits & DML_RTS) + tcr |= TCR_RTS3; + else + tcr &= ~TCR_RTS3; +#endif /* HW_FLOW_CONTROL */ + dcaddr->dc_tcr = tcr; } } - if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b)) - dc_tty[unit]->t_state |= TS_CARR_ON; (void) splx(s); return (mbits); } @@ -904,27 +1049,56 @@ void dcscan(arg) void *arg; { + register struct dc_softc *sc = dc_cd.cd_devs[0]; /* XXX */ register dcregs *dcaddr; register struct tty *tp; - register int i, bit, car; + register int unit, limit, dtr, dsr; int s; + /* only channel 2 has modem control on a DECstation 2100/3100 */ + dtr = TCR_DTR2; + dsr = MSR_DSR2; +#ifdef HW_FLOW_CONTROL + /*limit = (pmax_boardtype == DS_PMAX) ? 2 : 3;*/ + limit = (sc->dc_rtscts & (1 << 3)) :3 : 2; /*XXX*/ +#else + limit = 2; +#endif s = spltty(); - /* only channel 2 has modem control (what about line 3?) */ - dcaddr = (dcregs *)dcpdma[i = 2].p_addr; - tp = dc_tty[i]; - bit = TCR_DTR2; - if (dcsoftCAR[i >> 2] & bit) - car = 1; - else - car = dcaddr->dc_msr & MSR_DSR2; - if (car) { - /* carrier present */ - if (!(tp->t_state & TS_CARR_ON)) - (void)(*linesw[tp->t_line].l_modem)(tp, 1); - } else if ((tp->t_state & TS_CARR_ON) && - (*linesw[tp->t_line].l_modem)(tp, 0) == 0) - dcaddr->dc_tcr &= ~bit; + for (unit = 2; unit <= limit; unit++, dtr >>= 2, dsr >>= 8) { + tp = sc->dc_tty[unit]; + dcaddr = (dcregs *)sc->dc_pdma[unit].p_addr; + if ((dcaddr->dc_msr & dsr) || (sc->dcsoftCAR & (1 << unit))) { + /* carrier present */ + if (!(tp->t_state & TS_CARR_ON)) + (void)(*linesw[tp->t_line].l_modem)(tp, 1); + } else if ((tp->t_state & TS_CARR_ON) && + (*linesw[tp->t_line].l_modem)(tp, 0) == 0) + dcaddr->dc_tcr &= ~dtr; +#ifdef HW_FLOW_CONTROL + /* + * If we are using hardware flow control and output is stopped, + * then resume transmit. + */ + if ((tp->t_cflag & CCTS_OFLOW) && (tp->t_state & TS_TTSTOP) && + /*pmax_boardtype != DS_PMAX*/ + (sc->dc_rtscts & (1 << unit)) ) { + switch (unit) { + case 2: + if (dcaddr->dc_msr & MSR_CTS2) + break; + continue; + + case 3: + if (dcaddr->dc_msr & MSR_CTS3) + break; + continue; + } + tp->t_state &= ~TS_TTSTOP; + dcstart(tp); + } +#endif /* HW_FLOW_CONTROL */ + } splx(s); timeout(dcscan, (void *)0, hz); } @@ -950,9 +1124,17 @@ dcGetc(dev) { register dcregs *dcaddr; register int c; + register int line; int s; - dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; + line = DCLINE(dev); + if (cold && dc_cons_addr) { + dcaddr = dc_cons_addr; + } else { + struct dc_softc *sc; + sc = dc_cd.cd_devs[DCUNIT(dev)]; + dcaddr = (dcregs *)sc->dc_pdma[line].p_addr; + } if (!dcaddr) return (0); s = spltty(); @@ -961,7 +1143,7 @@ dcGetc(dev) continue; c = dcaddr->dc_rbuf; DELAY(10); - if (((c >> 8) & 03) == (minor(dev) & 03)) + if (((c >> 8) & 03) == line) break; } splx(s); @@ -979,13 +1161,23 @@ dcPutc(dev, c) register dcregs *dcaddr; register u_short tcr; register int timeout; - int s, line; + int s, out_line, activeline; + int brk; s = spltty(); - - dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; + out_line = DCLINE(dev); + if (cold && dc_cons_addr) { + brk = 0; + dcaddr = dc_cons_addr; + } else { + struct dc_softc *sc; + + sc = dc_cd.cd_devs[DCUNIT(dev)]; + dcaddr = (dcregs *)sc->dc_pdma[out_line].p_addr; + brk = sc->dc_brk; + } tcr = dcaddr->dc_tcr; - dcaddr->dc_tcr = tcr | (1 << minor(dev)); + dcaddr->dc_tcr = tcr | (1 << out_line); wbflush(); DELAY(10); while (1) { @@ -999,13 +1191,13 @@ dcPutc(dev, c) printf("dcPutc: timeout waiting for CSR_TRDY\n"); break; } - line = (dcaddr->dc_csr >> 8) & 3; + activeline = (dcaddr->dc_csr >> 8) & 3; /* * Check to be sure its the right port. */ - if (line != minor(dev)) { - tcr |= 1 << line; - dcaddr->dc_tcr &= ~(1 << line); + if (activeline != out_line) { + tcr |= 1 << activeline; + dcaddr->dc_tcr &= ~(1 << out_line); wbflush(); DELAY(10); continue; @@ -1013,7 +1205,7 @@ dcPutc(dev, c) /* * Start sending the character. */ - dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); + dcaddr->dc_tdr = brk | (c & 0xff); wbflush(); DELAY(10); /* @@ -1028,15 +1220,15 @@ dcPutc(dev, c) timeout = 1000000; while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) timeout--; - line = (dcaddr->dc_csr >> 8) & 3; - if (line != minor(dev)) { - tcr |= 1 << line; - dcaddr->dc_tcr &= ~(1 << line); + activeline = (dcaddr->dc_csr >> 8) & 3; + if (activeline != out_line) { + tcr |= 1 << activeline; + dcaddr->dc_tcr &= ~(1 << activeline); wbflush(); DELAY(10); continue; } - dcaddr->dc_tcr &= ~(1 << minor(dev)); + dcaddr->dc_tcr &= ~(1 << out_line); wbflush(); DELAY(10); break; @@ -1054,4 +1246,18 @@ dcPutc(dev, c) splx(s); } -#endif /* NDC */ + + +/* + * Enable/disable polling mode + */ +void +dcPollc(dev, on) + dev_t dev; + int on; +{ +#if defined(DIAGNOSTIC) || defined(DEBUG) + printf("dc_Pollc(%d, %d): not implemented\n", minor(dev), on); +#endif +} + |