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