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