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