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