1 /* vp.c 4.9 81/04/02 */ 2 3 #include "vp.h" 4 #if NVP > 0 5 /* 6 * Versatec matrix printer/plotter 7 * dma interface driver 8 * 9 * SETUP NOTES: 10 * Set up both print and plot interrupts to go through the same vector 11 * Give the address of the plcsr register in the config specification 12 */ 13 #include "../h/param.h" 14 #include "../h/dir.h" 15 #include "../h/user.h" 16 #include "../h/buf.h" 17 #include "../h/systm.h" 18 #include "../h/map.h" 19 #include "../h/pte.h" 20 #include "../h/ubavar.h" 21 #include "../h/ubareg.h" 22 #include "../h/vcmd.h" 23 24 unsigned minvpph(); 25 26 #define VPPRI (PZERO-1) 27 28 struct vpdevice { 29 short plbcr; 30 short pbxaddr; 31 short prbcr; 32 u_short pbaddr; 33 short plcsr; 34 short plbuf; 35 short prcsr; 36 u_short prbuf; 37 }; 38 39 #define VP_ERROR 0100000 40 #define VP_DTCINTR 0040000 41 #define VP_DMAACT 0020000 42 #define VP_READY 0000200 43 #define VP_IENABLE 0000100 44 #define VP_TERMCOM 0000040 45 #define VP_FFCOM 0000020 46 #define VP_EOTCOM 0000010 47 #define VP_CLRCOM 0000004 48 #define VP_RESET 0000002 49 #define VP_SPP 0000001 50 51 struct vp_softc { 52 int sc_state; 53 int sc_count; 54 int sc_bufp; 55 struct buf *sc_bp; 56 int sc_ubinfo; 57 } vp_softc[NVP]; 58 59 /* sc_state bits */ 60 #define VPSC_BUSY 0001000 61 #define VPSC_MODE 0000700 62 #define VPSC_SPP 0000400 63 #define VPSC_PLOT 0000200 64 #define VPSC_PRINT 0000100 65 #define VPSC_CMNDS 0000076 66 #define VPSC_OPEN 0000001 67 68 struct uba_device *vpdinfo[NVP]; 69 70 #define VPUNIT(dev) (minor(dev)) 71 72 struct buf rvpbuf[NVP]; 73 74 int vpprobe(), vpattach(); 75 struct uba_device *vpdinfo[NVP]; 76 u_short vpstd[] = { 0777500, 0 }; 77 struct uba_driver vpdriver = 78 { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 79 80 vpprobe(reg) 81 caddr_t reg; 82 { 83 register int br, cvec; /* value-result */ 84 register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 85 86 vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 87 vpaddr->pbaddr = 0; 88 vpaddr->pbxaddr = 0; 89 vpaddr->prbcr = 1; 90 DELAY(10000); 91 vpaddr->prcsr = 0; 92 #ifdef ERNIE 93 /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ 94 if (cvec == 0200) { 95 printf("vp reset vec from 200 to 174\n"); 96 cvec = 0174; 97 } 98 #endif 99 } 100 101 /*ARGSUSED*/ 102 vpattach(ui) 103 struct uba_device *ui; 104 { 105 106 ui->ui_addr -= 010; 107 ui->ui_physaddr -= 010; 108 } 109 110 vpopen(dev) 111 dev_t dev; 112 { 113 register struct vp_softc *sc; 114 register struct vpdevice *vpaddr; 115 register struct uba_device *ui; 116 117 if (VPUNIT(dev) >= NVP || 118 ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 119 (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) { 120 u.u_error = ENXIO; 121 return; 122 } 123 vpaddr = (struct vpdevice *)ui->ui_addr; 124 sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 125 sc->sc_count = 0; 126 vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 127 vptimo(dev); 128 while (sc->sc_state & VPSC_CMNDS) { 129 (void) spl4(); 130 if (vpwait(dev)) { 131 vpclose(dev); 132 u.u_error = EIO; 133 return; 134 } 135 vpstart(dev); 136 (void) spl0(); 137 } 138 } 139 140 vpstrategy(bp) 141 register struct buf *bp; 142 { 143 register int e; 144 register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 145 register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 146 register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 147 148 (void) spl4(); 149 while (sc->sc_state & VPSC_BUSY) 150 sleep((caddr_t)sc, VPPRI); 151 sc->sc_state |= VPSC_BUSY; 152 sc->sc_bp = bp; 153 sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 154 if (e = vpwait(bp->b_dev)) 155 goto brkout; 156 sc->sc_count = bp->b_bcount; 157 vpstart(bp->b_dev); 158 while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 159 sleep((caddr_t)sc, VPPRI); 160 sc->sc_count = 0; 161 if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 162 sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 163 (void) spl0(); 164 brkout: 165 ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 166 sc->sc_state &= ~VPSC_BUSY; 167 sc->sc_bp = 0; 168 iodone(bp); 169 if (e) 170 u.u_error = EIO; 171 wakeup((caddr_t)sc); 172 } 173 174 int vpblock = 16384; 175 176 unsigned 177 minvpph(bp) 178 struct buf *bp; 179 { 180 181 if (bp->b_bcount > vpblock) 182 bp->b_bcount = vpblock; 183 } 184 185 /*ARGSUSED*/ 186 vpwrite(dev) 187 dev_t dev; 188 { 189 190 physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph); 191 } 192 193 vpwait(dev) 194 dev_t dev; 195 { 196 register struct vpdevice *vpaddr = 197 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 198 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 199 register int e; 200 201 for (;;) { 202 e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 203 if (e & (VP_READY|VP_ERROR)) 204 break; 205 sleep((caddr_t)sc, VPPRI); 206 } 207 /* I wish i could tell whether an error indicated an npr timeout */ 208 return (e & VP_ERROR); 209 } 210 211 vpstart(dev) 212 dev_t; 213 { 214 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 215 register struct vpdevice *vpaddr = 216 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 217 short bit; 218 219 if (sc->sc_count) { 220 vpaddr->pbaddr = sc->sc_ubinfo; 221 vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 222 if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 223 vpaddr->prbcr = sc->sc_count; 224 else 225 vpaddr->plbcr = sc->sc_count; 226 return; 227 } 228 for (bit = 1; bit != 0; bit <<= 1) 229 if (sc->sc_state&bit&VPSC_CMNDS) { 230 vpaddr->plcsr |= bit; 231 sc->sc_state &= ~bit; 232 return; 233 } 234 } 235 236 /*ARGSUSED*/ 237 vpioctl(dev, cmd, addr, flag) 238 dev_t dev; 239 int cmd; 240 register caddr_t addr; 241 int flag; 242 { 243 register int m; 244 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 245 register struct vpdevice *vpaddr = 246 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 247 248 switch (cmd) { 249 250 case VGETSTATE: 251 (void) suword(addr, sc->sc_state); 252 return; 253 254 case VSETSTATE: 255 m = fuword(addr); 256 if (m == -1) { 257 u.u_error = EFAULT; 258 return; 259 } 260 sc->sc_state = 261 (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); 262 break; 263 264 default: 265 u.u_error = ENOTTY; 266 return; 267 } 268 (void) spl4(); 269 (void) vpwait(dev); 270 if (sc->sc_state&VPSC_SPP) 271 vpaddr->plcsr |= VP_SPP; 272 else 273 vpaddr->plcsr &= ~VP_SPP; 274 sc->sc_count = 0; 275 while (sc->sc_state & VPSC_CMNDS) { 276 (void) vpwait(dev); 277 vpstart(dev); 278 } 279 (void) spl0(); 280 } 281 282 vptimo(dev) 283 dev_t dev; 284 { 285 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 286 287 if (sc->sc_state&VPSC_OPEN) 288 timeout(vptimo, (caddr_t)dev, hz/10); 289 vpintr(dev); 290 } 291 292 /*ARGSUSED*/ 293 vpintr(dev) 294 dev_t dev; 295 { 296 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 297 298 wakeup((caddr_t)sc); 299 } 300 301 vpclose(dev) 302 dev_t dev; 303 { 304 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 305 register struct vpdevice *vpaddr = 306 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 307 308 sc->sc_state = 0; 309 sc->sc_count = 0; 310 vpaddr->plcsr = 0; 311 } 312 313 vpreset(uban) 314 int uban; 315 { 316 register int vp11; 317 register struct uba_device *ui; 318 register struct vp_softc *sc = vp_softc; 319 register struct vpdevice *vpaddr; 320 321 for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 322 if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 323 ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 324 continue; 325 printf(" vp%d", vp11); 326 vpaddr = (struct vpdevice *)ui->ui_addr; 327 vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 328 if ((sc->sc_state & VPSC_BUSY) == 0) 329 continue; 330 if (sc->sc_ubinfo) { 331 printf("<%d>", (sc->sc_ubinfo>>28)&0xf); 332 ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 333 } 334 sc->sc_count = sc->sc_bp->b_bcount; 335 vpstart(sc->sc_bp->b_dev); 336 } 337 } 338 #endif 339