1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)ct.c 6.4 (Berkeley) 04/21/86 7 */ 8 9 #include "ct.h" 10 #if NCT > 0 11 /* 12 * GP DR11C driver used for C/A/T or Autologic APS micro-5 13 */ 14 #include "../machine/pte.h" 15 16 #include "param.h" 17 #include "systm.h" 18 #include "tty.h" 19 #include "map.h" 20 #include "buf.h" 21 #include "conf.h" 22 #include "dir.h" 23 #include "user.h" 24 #include "kernel.h" 25 26 #include "ubareg.h" 27 #include "ubavar.h" 28 29 #define PCAT (PZERO+9) 30 #define CATHIWAT 100 31 #define CATLOWAT 30 32 33 #define REQUEST_B 0x8000 34 #define REQUEST_A 0x80 35 #define INT_ENB_A 0x40 36 #define INT_ENB_B 0x20 37 #define CSR1 0x2 38 #define CSR0 0x1 39 40 struct ct_softc { 41 int sc_state; 42 struct clist sc_oq; 43 } ct_softc[NCT]; 44 45 #define CT_OPEN 0x1 46 #define CT_RUNNING 0x2 47 48 struct ctdevice { 49 u_short ctcsr; 50 u_short ctobuf; 51 u_short ctibuf; 52 }; 53 54 int ctprobe(), ctattach(), ctintr(); 55 struct uba_device *ctdinfo[NCT]; 56 u_short ctstd[] = { 0167770, 0 }; 57 struct uba_driver ctdriver = 58 { ctprobe, 0, ctattach, 0, ctstd, "ct", ctdinfo }; 59 60 #define CTUNIT(dev) (minor(dev)) 61 62 int ct_init = 0; /* set to CSR1 for testing loopback on controller */ 63 64 ctprobe(reg) 65 caddr_t reg; 66 { 67 register int br, cvec; /* value-result */ 68 register struct ctdevice *ctaddr = (struct ctdevice *)reg; 69 70 #ifdef lint 71 br = 0; cvec = br; br = cvec; 72 ctintr(0); 73 #endif 74 /* 75 * There is no way to make a DR11c interrupt without some 76 * external support. We can't always trust that the typesetter 77 * will be online and ready so we've made other provisions. 78 * This probe assumes setting the B Int Enb will generate 79 * an interrupt. To do this, we set CSR0 and loop this back 80 * to REQUEST_B in the second plug on the controller. 81 * Then, we reset the vector to be that for the "real" device. 82 */ 83 ctaddr->ctcsr = INT_ENB_B | CSR0; /* Assume hardware loopback! */ 84 DELAY(1000); 85 ctaddr->ctcsr = ct_init; /* should be CSR1 for loopback testing */ 86 if (cvec & 04) { 87 printf("ct: resetting vector %o to %o\n", cvec, cvec&0773); 88 cvec &= 0773; 89 } 90 return (sizeof (struct ctdevice)); 91 } 92 93 /*ARGSUSED*/ 94 ctattach(ui) 95 register struct uba_device *ui; 96 { 97 } 98 99 ctopen(dev) 100 dev_t dev; 101 { 102 register struct ct_softc *sc; 103 register struct uba_device *ui; 104 register struct ctdevice *ctaddr; 105 106 if (CTUNIT(dev) >= NCT || (ui = ctdinfo[CTUNIT(dev)]) == 0 || 107 ui->ui_alive == 0) 108 return (ENODEV); 109 if ((sc = &ct_softc[CTUNIT(dev)])->sc_state&CT_OPEN) 110 return (EBUSY); 111 sc->sc_state = CT_OPEN; 112 ctaddr = (struct ctdevice *)ui->ui_addr; 113 ctaddr->ctcsr |= INT_ENB_A; 114 return (0); 115 } 116 117 ctclose(dev) 118 dev_t dev; 119 { 120 ct_softc[CTUNIT(dev)].sc_state = 0; 121 ctintr(dev); 122 return (0); 123 } 124 125 ctwrite(dev, uio) 126 dev_t dev; 127 struct uio *uio; 128 { 129 register struct ct_softc *sc = &ct_softc[CTUNIT(dev)]; 130 register int c; 131 int s; 132 133 while ((c = uwritec(uio)) >= 0) { 134 s = spl5(); 135 while (sc->sc_oq.c_cc > CATHIWAT) 136 sleep((caddr_t)&sc->sc_oq, PCAT); 137 while (putc(c, &sc->sc_oq) < 0) 138 sleep((caddr_t)&lbolt, PCAT); 139 if ( ! (sc->sc_state & CT_RUNNING) ) 140 ctintr(dev); 141 splx(s); 142 } 143 return (0); 144 } 145 146 /* 147 * The C/A/T is usually wired to accept data on the .5us DATA_AVAIL strobe. 148 * If you use this with a C/A/T you can remove the lines with "APSu5" below. 149 * This is way out of spec for the Autologic APS micro-5 which requires 150 * at least a 40 microsec strobe. We therefore use CSR1 output as the 151 * "strobe". It is set after data is loaded and reset only in the 152 * interrupt routine. Therefore, the "strobe" is high for adequate time. 153 * The constant "ctdelay" determines the "low" time for the strobe 154 * and may have to be larger on a 780. "2" gives about 10us on a 750. 155 */ 156 int ctdelay = 2; /* here so it's visible & changeable */ 157 158 ctintr(dev) 159 dev_t dev; 160 { 161 register int c; 162 register struct ct_softc *sc = &ct_softc[CTUNIT(dev)]; 163 register struct ctdevice *ctaddr = 164 (struct ctdevice *)ctdinfo[CTUNIT(dev)]->ui_addr; 165 166 if ((ctaddr->ctcsr&(INT_ENB_B|REQUEST_B)) == (INT_ENB_B|REQUEST_B)) { 167 ctaddr->ctcsr &= ~(CSR0 | INT_ENB_B); /* set in ctprobe */ 168 } 169 if ((ctaddr->ctcsr&(INT_ENB_A|REQUEST_A)) == (INT_ENB_A|REQUEST_A)) { 170 if ((c = getc(&sc->sc_oq)) >= 0) { 171 ctaddr->ctcsr &= ~CSR1; /* APSu5 - drop strobe */ 172 ctaddr->ctobuf = c; 173 DELAY(ctdelay); /* APSu5 - pause a bit */ 174 ctaddr->ctcsr |= CSR1; /* APSu5 - raise strobe */ 175 sc->sc_state |= CT_RUNNING; 176 if (sc->sc_oq.c_cc==0 || sc->sc_oq.c_cc==CATLOWAT) 177 wakeup(&sc->sc_oq); 178 } else if (sc->sc_state == 0) { 179 ctaddr->ctcsr = 0; 180 } else 181 sc->sc_state &= ~CT_RUNNING; 182 } 183 } 184 #endif 185