123319Smckusick /* 2*29208Smckusick * 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*29208Smckusick * @(#)ct.c 7.1 (Berkeley) 06/05/86 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 */ 149771Ssam #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 "dir.h" 2417073Sbloom #include "user.h" 2527234Skarels #include "kernel.h" 262621Swnj 2717073Sbloom #include "ubareg.h" 2817073Sbloom #include "ubavar.h" 298472Sroot 302621Swnj #define PCAT (PZERO+9) 312621Swnj #define CATHIWAT 100 322621Swnj #define CATLOWAT 30 332621Swnj 3427234Skarels #define REQUEST_B 0x8000 3527234Skarels #define REQUEST_A 0x80 3627234Skarels #define INT_ENB_A 0x40 3727234Skarels #define INT_ENB_B 0x20 3827234Skarels #define CSR1 0x2 3927234Skarels #define CSR0 0x1 4027234Skarels 413201Swnj struct ct_softc { 4227234Skarels int sc_state; 433201Swnj struct clist sc_oq; 443201Swnj } ct_softc[NCT]; 452621Swnj 4627234Skarels #define CT_OPEN 0x1 4727234Skarels #define CT_RUNNING 0x2 4827234Skarels 493201Swnj struct ctdevice { 5027234Skarels u_short ctcsr; 5127234Skarels u_short ctobuf; 5227234Skarels u_short ctibuf; 532621Swnj }; 542621Swnj 553201Swnj int ctprobe(), ctattach(), ctintr(); 563201Swnj struct uba_device *ctdinfo[NCT]; 5727234Skarels u_short ctstd[] = { 0167770, 0 }; 583201Swnj struct uba_driver ctdriver = 593201Swnj { ctprobe, 0, ctattach, 0, ctstd, "ct", ctdinfo }; 602621Swnj 613217Swnj #define CTUNIT(dev) (minor(dev)) 623217Swnj 6327234Skarels int ct_init = 0; /* set to CSR1 for testing loopback on controller */ 6427234Skarels 653201Swnj ctprobe(reg) 663201Swnj caddr_t reg; 673201Swnj { 683936Sbugs register int br, cvec; /* value-result */ 693201Swnj register struct ctdevice *ctaddr = (struct ctdevice *)reg; 703201Swnj 714932Swnj #ifdef lint 724932Swnj br = 0; cvec = br; br = cvec; 734932Swnj ctintr(0); 744932Swnj #endif 7527234Skarels /* 7627234Skarels * There is no way to make a DR11c interrupt without some 7727234Skarels * external support. We can't always trust that the typesetter 7827234Skarels * will be online and ready so we've made other provisions. 7927234Skarels * This probe assumes setting the B Int Enb will generate 8027234Skarels * an interrupt. To do this, we set CSR0 and loop this back 8127234Skarels * to REQUEST_B in the second plug on the controller. 8227234Skarels * Then, we reset the vector to be that for the "real" device. 8327234Skarels */ 8427234Skarels ctaddr->ctcsr = INT_ENB_B | CSR0; /* Assume hardware loopback! */ 8527234Skarels DELAY(1000); 8627234Skarels ctaddr->ctcsr = ct_init; /* should be CSR1 for loopback testing */ 8727234Skarels if (cvec & 04) { 8827234Skarels printf("ct: resetting vector %o to %o\n", cvec, cvec&0773); 8927234Skarels cvec &= 0773; 9027234Skarels } 917409Skre return (sizeof (struct ctdevice)); 923201Swnj } 933201Swnj 943217Swnj /*ARGSUSED*/ 953217Swnj ctattach(ui) 9628955Skarels struct uba_device *ui; 973217Swnj { 983217Swnj } 993217Swnj 1002621Swnj ctopen(dev) 1013201Swnj dev_t dev; 1022621Swnj { 1033201Swnj register struct ct_softc *sc; 1043201Swnj register struct uba_device *ui; 1053201Swnj register struct ctdevice *ctaddr; 1063201Swnj 1073201Swnj if (CTUNIT(dev) >= NCT || (ui = ctdinfo[CTUNIT(dev)]) == 0 || 10827234Skarels ui->ui_alive == 0) 10927234Skarels return (ENODEV); 11027234Skarels if ((sc = &ct_softc[CTUNIT(dev)])->sc_state&CT_OPEN) 11127234Skarels return (EBUSY); 11227234Skarels sc->sc_state = CT_OPEN; 11327234Skarels ctaddr = (struct ctdevice *)ui->ui_addr; 11427234Skarels ctaddr->ctcsr |= INT_ENB_A; 1158566Sroot return (0); 1162621Swnj } 1172621Swnj 1183201Swnj ctclose(dev) 1193201Swnj dev_t dev; 1202621Swnj { 12127234Skarels ct_softc[CTUNIT(dev)].sc_state = 0; 1223201Swnj ctintr(dev); 12327234Skarels return (0); 1242621Swnj } 1252621Swnj 1267831Sroot ctwrite(dev, uio) 1273201Swnj dev_t dev; 1287831Sroot struct uio *uio; 1292621Swnj { 1303201Swnj register struct ct_softc *sc = &ct_softc[CTUNIT(dev)]; 1313201Swnj register int c; 13227234Skarels int s; 1332621Swnj 13427234Skarels while ((c = uwritec(uio)) >= 0) { 13527234Skarels s = spl5(); 1363201Swnj while (sc->sc_oq.c_cc > CATHIWAT) 1373201Swnj sleep((caddr_t)&sc->sc_oq, PCAT); 1383201Swnj while (putc(c, &sc->sc_oq) < 0) 1392621Swnj sleep((caddr_t)&lbolt, PCAT); 14027234Skarels if ( ! (sc->sc_state & CT_RUNNING) ) 14127234Skarels ctintr(dev); 14227234Skarels splx(s); 1432621Swnj } 14427234Skarels return (0); 1452621Swnj } 1462621Swnj 14727234Skarels /* 14827234Skarels * The C/A/T is usually wired to accept data on the .5us DATA_AVAIL strobe. 14927234Skarels * If you use this with a C/A/T you can remove the lines with "APSu5" below. 15027234Skarels * This is way out of spec for the Autologic APS micro-5 which requires 15127234Skarels * at least a 40 microsec strobe. We therefore use CSR1 output as the 15227234Skarels * "strobe". It is set after data is loaded and reset only in the 15327234Skarels * interrupt routine. Therefore, the "strobe" is high for adequate time. 15427234Skarels * The constant "ctdelay" determines the "low" time for the strobe 15527234Skarels * and may have to be larger on a 780. "2" gives about 10us on a 750. 15627234Skarels */ 15727234Skarels int ctdelay = 2; /* here so it's visible & changeable */ 15827234Skarels 1593201Swnj ctintr(dev) 1603201Swnj dev_t dev; 1612621Swnj { 1622621Swnj register int c; 1633201Swnj register struct ct_softc *sc = &ct_softc[CTUNIT(dev)]; 1643201Swnj register struct ctdevice *ctaddr = 1653201Swnj (struct ctdevice *)ctdinfo[CTUNIT(dev)]->ui_addr; 1662621Swnj 16727234Skarels if ((ctaddr->ctcsr&(INT_ENB_B|REQUEST_B)) == (INT_ENB_B|REQUEST_B)) { 16827234Skarels ctaddr->ctcsr &= ~(CSR0 | INT_ENB_B); /* set in ctprobe */ 16927234Skarels } 17027234Skarels if ((ctaddr->ctcsr&(INT_ENB_A|REQUEST_A)) == (INT_ENB_A|REQUEST_A)) { 1713201Swnj if ((c = getc(&sc->sc_oq)) >= 0) { 17227234Skarels ctaddr->ctcsr &= ~CSR1; /* APSu5 - drop strobe */ 17327234Skarels ctaddr->ctobuf = c; 17427234Skarels DELAY(ctdelay); /* APSu5 - pause a bit */ 17527234Skarels ctaddr->ctcsr |= CSR1; /* APSu5 - raise strobe */ 17627234Skarels sc->sc_state |= CT_RUNNING; 1773201Swnj if (sc->sc_oq.c_cc==0 || sc->sc_oq.c_cc==CATLOWAT) 17828955Skarels wakeup((caddr_t)&sc->sc_oq); 17927234Skarels } else if (sc->sc_state == 0) { 1803201Swnj ctaddr->ctcsr = 0; 18127234Skarels } else 18227234Skarels sc->sc_state &= ~CT_RUNNING; 1832621Swnj } 1842621Swnj } 1852621Swnj #endif 186