1 /* 2 * Copyright (c) 1982, 1986 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 7.6 (Berkeley) 12/16/90 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 "../include/pte.h" 15 16 #include "sys/param.h" 17 #include "sys/systm.h" 18 #include "sys/ioctl.h" 19 #include "sys/tty.h" 20 #include "sys/map.h" 21 #include "sys/buf.h" 22 #include "sys/conf.h" 23 #include "sys/user.h" 24 #include "sys/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 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, error; 132 133 while ((c = uwritec(uio)) >= 0) { 134 s = spl5(); 135 while (sc->sc_oq.c_cc > CATHIWAT) 136 if (error = tsleep((caddr_t)&sc->sc_oq, PCAT | PCATCH, 137 devout, 0)) 138 goto out; 139 while (putc(c, &sc->sc_oq) < 0) 140 if (error = tsleep((caddr_t)&lbolt, PCAT | PCATCH, 141 ttybuf, 0)) 142 goto out; 143 if ( ! (sc->sc_state & CT_RUNNING) ) 144 ctintr(dev); 145 splx(s); 146 } 147 return (0); 148 out: 149 splx(s); 150 return (error); 151 } 152 153 /* 154 * The C/A/T is usually wired to accept data on the .5us DATA_AVAIL strobe. 155 * If you use this with a C/A/T you can remove the lines with "APSu5" below. 156 * This is way out of spec for the Autologic APS micro-5 which requires 157 * at least a 40 microsec strobe. We therefore use CSR1 output as the 158 * "strobe". It is set after data is loaded and reset only in the 159 * interrupt routine. Therefore, the "strobe" is high for adequate time. 160 * The constant "ctdelay" determines the "low" time for the strobe 161 * and may have to be larger on a 780. "2" gives about 10us on a 750. 162 */ 163 int ctdelay = 2; /* here so it's visible & changeable */ 164 165 ctintr(dev) 166 dev_t dev; 167 { 168 register int c; 169 register struct ct_softc *sc = &ct_softc[CTUNIT(dev)]; 170 register struct ctdevice *ctaddr = 171 (struct ctdevice *)ctdinfo[CTUNIT(dev)]->ui_addr; 172 173 if ((ctaddr->ctcsr&(INT_ENB_B|REQUEST_B)) == (INT_ENB_B|REQUEST_B)) { 174 ctaddr->ctcsr &= ~(CSR0 | INT_ENB_B); /* set in ctprobe */ 175 } 176 if ((ctaddr->ctcsr&(INT_ENB_A|REQUEST_A)) == (INT_ENB_A|REQUEST_A)) { 177 if ((c = getc(&sc->sc_oq)) >= 0) { 178 ctaddr->ctcsr &= ~CSR1; /* APSu5 - drop strobe */ 179 ctaddr->ctobuf = c; 180 DELAY(ctdelay); /* APSu5 - pause a bit */ 181 ctaddr->ctcsr |= CSR1; /* APSu5 - raise strobe */ 182 sc->sc_state |= CT_RUNNING; 183 if (sc->sc_oq.c_cc==0 || sc->sc_oq.c_cc==CATLOWAT) 184 wakeup((caddr_t)&sc->sc_oq); 185 } else if (sc->sc_state == 0) { 186 ctaddr->ctcsr = 0; 187 } else 188 sc->sc_state &= ~CT_RUNNING; 189 } 190 } 191 #endif 192