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*40728Skarels * @(#)ct.c 7.5 (Berkeley) 04/03/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 */ 1437511Smckusick #include "machine/pte.h" 152621Swnj 1617073Sbloom #include "param.h" 1717073Sbloom #include "systm.h" 1828330Smckusick #include "ioctl.h" 1917073Sbloom #include "tty.h" 2017073Sbloom #include "map.h" 2117073Sbloom #include "buf.h" 2217073Sbloom #include "conf.h" 2317073Sbloom #include "user.h" 2427234Skarels #include "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 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 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 1173201Swnj ctclose(dev) 1183201Swnj dev_t dev; 1192621Swnj { 12027234Skarels ct_softc[CTUNIT(dev)].sc_state = 0; 1213201Swnj ctintr(dev); 12227234Skarels return (0); 1232621Swnj } 1242621Swnj 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; 131*40728Skarels int s, error; 1322621Swnj 13327234Skarels while ((c = uwritec(uio)) >= 0) { 13427234Skarels s = spl5(); 1353201Swnj while (sc->sc_oq.c_cc > CATHIWAT) 136*40728Skarels if (error = tsleep((caddr_t)&sc->sc_oq, PCAT | PCATCH, 137*40728Skarels devout, 0)) 138*40728Skarels goto out; 1393201Swnj while (putc(c, &sc->sc_oq) < 0) 140*40728Skarels if (error = tsleep((caddr_t)&lbolt, PCAT | PCATCH, 141*40728Skarels ttybuf, 0)) 142*40728Skarels goto out; 14327234Skarels if ( ! (sc->sc_state & CT_RUNNING) ) 14427234Skarels ctintr(dev); 14527234Skarels splx(s); 1462621Swnj } 14727234Skarels return (0); 148*40728Skarels out: 149*40728Skarels splx(s); 150*40728Skarels 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 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