123319Smckusick /*
229208Smckusick * Copyright (c) 1982, 1986 Regents of the University of California.
323319Smckusick * All rights reserved. The Berkeley software License Agreement
423319Smckusick * specifies the terms and conditions for redistribution.
523319Smckusick *
6*45804Sbostic * @(#)ct.c 7.6 (Berkeley) 12/16/90
723319Smckusick */
82621Swnj
93201Swnj #include "ct.h"
102621Swnj #if NCT > 0
112621Swnj /*
1227234Skarels * GP DR11C driver used for C/A/T or Autologic APS micro-5
132621Swnj */
14*45804Sbostic #include "../include/pte.h"
152621Swnj
16*45804Sbostic #include "sys/param.h"
17*45804Sbostic #include "sys/systm.h"
18*45804Sbostic #include "sys/ioctl.h"
19*45804Sbostic #include "sys/tty.h"
20*45804Sbostic #include "sys/map.h"
21*45804Sbostic #include "sys/buf.h"
22*45804Sbostic #include "sys/conf.h"
23*45804Sbostic #include "sys/user.h"
24*45804Sbostic #include "sys/kernel.h"
252621Swnj
2617073Sbloom #include "ubareg.h"
2717073Sbloom #include "ubavar.h"
288472Sroot
292621Swnj #define PCAT (PZERO+9)
302621Swnj #define CATHIWAT 100
312621Swnj #define CATLOWAT 30
322621Swnj
3327234Skarels #define REQUEST_B 0x8000
3427234Skarels #define REQUEST_A 0x80
3527234Skarels #define INT_ENB_A 0x40
3627234Skarels #define INT_ENB_B 0x20
3727234Skarels #define CSR1 0x2
3827234Skarels #define CSR0 0x1
3927234Skarels
403201Swnj struct ct_softc {
4127234Skarels int sc_state;
423201Swnj struct clist sc_oq;
433201Swnj } ct_softc[NCT];
442621Swnj
4527234Skarels #define CT_OPEN 0x1
4627234Skarels #define CT_RUNNING 0x2
4727234Skarels
483201Swnj struct ctdevice {
4927234Skarels u_short ctcsr;
5027234Skarels u_short ctobuf;
5127234Skarels u_short ctibuf;
522621Swnj };
532621Swnj
543201Swnj int ctprobe(), ctattach(), ctintr();
553201Swnj struct uba_device *ctdinfo[NCT];
5627234Skarels u_short ctstd[] = { 0167770, 0 };
573201Swnj struct uba_driver ctdriver =
583201Swnj { ctprobe, 0, ctattach, 0, ctstd, "ct", ctdinfo };
592621Swnj
603217Swnj #define CTUNIT(dev) (minor(dev))
613217Swnj
6227234Skarels int ct_init = 0; /* set to CSR1 for testing loopback on controller */
6327234Skarels
ctprobe(reg)643201Swnj ctprobe(reg)
653201Swnj caddr_t reg;
663201Swnj {
673936Sbugs register int br, cvec; /* value-result */
683201Swnj register struct ctdevice *ctaddr = (struct ctdevice *)reg;
693201Swnj
704932Swnj #ifdef lint
714932Swnj br = 0; cvec = br; br = cvec;
724932Swnj ctintr(0);
734932Swnj #endif
7427234Skarels /*
7527234Skarels * There is no way to make a DR11c interrupt without some
7627234Skarels * external support. We can't always trust that the typesetter
7727234Skarels * will be online and ready so we've made other provisions.
7827234Skarels * This probe assumes setting the B Int Enb will generate
7927234Skarels * an interrupt. To do this, we set CSR0 and loop this back
8027234Skarels * to REQUEST_B in the second plug on the controller.
8127234Skarels * Then, we reset the vector to be that for the "real" device.
8227234Skarels */
8327234Skarels ctaddr->ctcsr = INT_ENB_B | CSR0; /* Assume hardware loopback! */
8427234Skarels DELAY(1000);
8527234Skarels ctaddr->ctcsr = ct_init; /* should be CSR1 for loopback testing */
8627234Skarels if (cvec & 04) {
8727234Skarels printf("ct: resetting vector %o to %o\n", cvec, cvec&0773);
8827234Skarels cvec &= 0773;
8927234Skarels }
907409Skre return (sizeof (struct ctdevice));
913201Swnj }
923201Swnj
933217Swnj /*ARGSUSED*/
943217Swnj ctattach(ui)
9528955Skarels struct uba_device *ui;
963217Swnj {
973217Swnj }
983217Swnj
ctopen(dev)992621Swnj ctopen(dev)
1003201Swnj dev_t dev;
1012621Swnj {
1023201Swnj register struct ct_softc *sc;
1033201Swnj register struct uba_device *ui;
1043201Swnj register struct ctdevice *ctaddr;
1053201Swnj
1063201Swnj if (CTUNIT(dev) >= NCT || (ui = ctdinfo[CTUNIT(dev)]) == 0 ||
10727234Skarels ui->ui_alive == 0)
10827234Skarels return (ENODEV);
10927234Skarels if ((sc = &ct_softc[CTUNIT(dev)])->sc_state&CT_OPEN)
11027234Skarels return (EBUSY);
11127234Skarels sc->sc_state = CT_OPEN;
11227234Skarels ctaddr = (struct ctdevice *)ui->ui_addr;
11327234Skarels ctaddr->ctcsr |= INT_ENB_A;
1148566Sroot return (0);
1152621Swnj }
1162621Swnj
ctclose(dev)1173201Swnj ctclose(dev)
1183201Swnj dev_t dev;
1192621Swnj {
12027234Skarels ct_softc[CTUNIT(dev)].sc_state = 0;
1213201Swnj ctintr(dev);
12227234Skarels return (0);
1232621Swnj }
1242621Swnj
ctwrite(dev,uio)1257831Sroot ctwrite(dev, uio)
1263201Swnj dev_t dev;
1277831Sroot struct uio *uio;
1282621Swnj {
1293201Swnj register struct ct_softc *sc = &ct_softc[CTUNIT(dev)];
1303201Swnj register int c;
13140728Skarels int s, error;
1322621Swnj
13327234Skarels while ((c = uwritec(uio)) >= 0) {
13427234Skarels s = spl5();
1353201Swnj while (sc->sc_oq.c_cc > CATHIWAT)
13640728Skarels if (error = tsleep((caddr_t)&sc->sc_oq, PCAT | PCATCH,
13740728Skarels devout, 0))
13840728Skarels goto out;
1393201Swnj while (putc(c, &sc->sc_oq) < 0)
14040728Skarels if (error = tsleep((caddr_t)&lbolt, PCAT | PCATCH,
14140728Skarels ttybuf, 0))
14240728Skarels goto out;
14327234Skarels if ( ! (sc->sc_state & CT_RUNNING) )
14427234Skarels ctintr(dev);
14527234Skarels splx(s);
1462621Swnj }
14727234Skarels return (0);
14840728Skarels out:
14940728Skarels splx(s);
15040728Skarels return (error);
1512621Swnj }
1522621Swnj
15327234Skarels /*
15427234Skarels * The C/A/T is usually wired to accept data on the .5us DATA_AVAIL strobe.
15527234Skarels * If you use this with a C/A/T you can remove the lines with "APSu5" below.
15627234Skarels * This is way out of spec for the Autologic APS micro-5 which requires
15727234Skarels * at least a 40 microsec strobe. We therefore use CSR1 output as the
15827234Skarels * "strobe". It is set after data is loaded and reset only in the
15927234Skarels * interrupt routine. Therefore, the "strobe" is high for adequate time.
16027234Skarels * The constant "ctdelay" determines the "low" time for the strobe
16127234Skarels * and may have to be larger on a 780. "2" gives about 10us on a 750.
16227234Skarels */
16327234Skarels int ctdelay = 2; /* here so it's visible & changeable */
16427234Skarels
ctintr(dev)1653201Swnj ctintr(dev)
1663201Swnj dev_t dev;
1672621Swnj {
1682621Swnj register int c;
1693201Swnj register struct ct_softc *sc = &ct_softc[CTUNIT(dev)];
1703201Swnj register struct ctdevice *ctaddr =
1713201Swnj (struct ctdevice *)ctdinfo[CTUNIT(dev)]->ui_addr;
1722621Swnj
17327234Skarels if ((ctaddr->ctcsr&(INT_ENB_B|REQUEST_B)) == (INT_ENB_B|REQUEST_B)) {
17427234Skarels ctaddr->ctcsr &= ~(CSR0 | INT_ENB_B); /* set in ctprobe */
17527234Skarels }
17627234Skarels if ((ctaddr->ctcsr&(INT_ENB_A|REQUEST_A)) == (INT_ENB_A|REQUEST_A)) {
1773201Swnj if ((c = getc(&sc->sc_oq)) >= 0) {
17827234Skarels ctaddr->ctcsr &= ~CSR1; /* APSu5 - drop strobe */
17927234Skarels ctaddr->ctobuf = c;
18027234Skarels DELAY(ctdelay); /* APSu5 - pause a bit */
18127234Skarels ctaddr->ctcsr |= CSR1; /* APSu5 - raise strobe */
18227234Skarels sc->sc_state |= CT_RUNNING;
1833201Swnj if (sc->sc_oq.c_cc==0 || sc->sc_oq.c_cc==CATLOWAT)
18428955Skarels wakeup((caddr_t)&sc->sc_oq);
18527234Skarels } else if (sc->sc_state == 0) {
1863201Swnj ctaddr->ctcsr = 0;
18727234Skarels } else
18827234Skarels sc->sc_state &= ~CT_RUNNING;
1892621Swnj }
1902621Swnj }
1912621Swnj #endif
192