1 /* vp.c 4.11 82/04/01 */ 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 #ifdef lint 87 br = 0; cvec = br; br = cvec; 88 vpintr(0); 89 #endif 90 vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 91 vpaddr->pbaddr = 0; 92 vpaddr->pbxaddr = 0; 93 vpaddr->prbcr = 1; 94 DELAY(10000); 95 vpaddr->prcsr = 0; 96 #ifdef ERNIE 97 /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ 98 if (cvec == 0200) { 99 printf("vp reset vec from 200 to 174\n"); 100 cvec = 0174; 101 } 102 #endif 103 } 104 105 /*ARGSUSED*/ 106 vpattach(ui) 107 struct uba_device *ui; 108 { 109 110 ui->ui_addr -= 010; 111 ui->ui_physaddr -= 010; 112 } 113 114 vpopen(dev) 115 dev_t dev; 116 { 117 register struct vp_softc *sc; 118 register struct vpdevice *vpaddr; 119 register struct uba_device *ui; 120 121 if (VPUNIT(dev) >= NVP || 122 ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 123 (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) { 124 u.u_error = ENXIO; 125 return; 126 } 127 vpaddr = (struct vpdevice *)ui->ui_addr; 128 sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 129 sc->sc_count = 0; 130 vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 131 vptimo(dev); 132 while (sc->sc_state & VPSC_CMNDS) { 133 (void) spl4(); 134 if (vpwait(dev)) { 135 vpclose(dev); 136 u.u_error = EIO; 137 return; 138 } 139 vpstart(dev); 140 (void) spl0(); 141 } 142 } 143 144 vpstrategy(bp) 145 register struct buf *bp; 146 { 147 register int e; 148 register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 149 register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 150 register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 151 152 (void) spl4(); 153 while (sc->sc_state & VPSC_BUSY) 154 sleep((caddr_t)sc, VPPRI); 155 sc->sc_state |= VPSC_BUSY; 156 sc->sc_bp = bp; 157 sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 158 if (e = vpwait(bp->b_dev)) 159 goto brkout; 160 sc->sc_count = bp->b_bcount; 161 vpstart(bp->b_dev); 162 while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 163 sleep((caddr_t)sc, VPPRI); 164 sc->sc_count = 0; 165 if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 166 sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 167 (void) spl0(); 168 brkout: 169 ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 170 sc->sc_state &= ~VPSC_BUSY; 171 sc->sc_bp = 0; 172 iodone(bp); 173 if (e) 174 u.u_error = EIO; 175 wakeup((caddr_t)sc); 176 } 177 178 int vpblock = 16384; 179 180 unsigned 181 minvpph(bp) 182 struct buf *bp; 183 { 184 185 if (bp->b_bcount > vpblock) 186 bp->b_bcount = vpblock; 187 } 188 189 /*ARGSUSED*/ 190 vpwrite(dev) 191 dev_t dev; 192 { 193 194 physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph); 195 } 196 197 vpwait(dev) 198 dev_t dev; 199 { 200 register struct vpdevice *vpaddr = 201 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 202 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 203 register int e; 204 205 for (;;) { 206 e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 207 if (e & (VP_READY|VP_ERROR)) 208 break; 209 sleep((caddr_t)sc, VPPRI); 210 } 211 /* I wish i could tell whether an error indicated an npr timeout */ 212 return (e & VP_ERROR); 213 } 214 215 vpstart(dev) 216 dev_t; 217 { 218 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 219 register struct vpdevice *vpaddr = 220 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 221 short bit; 222 223 if (sc->sc_count) { 224 vpaddr->pbaddr = sc->sc_ubinfo; 225 vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 226 if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 227 vpaddr->prbcr = sc->sc_count; 228 else 229 vpaddr->plbcr = sc->sc_count; 230 return; 231 } 232 for (bit = 1; bit != 0; bit <<= 1) 233 if (sc->sc_state&bit&VPSC_CMNDS) { 234 vpaddr->plcsr |= bit; 235 sc->sc_state &= ~bit; 236 return; 237 } 238 } 239 240 /*ARGSUSED*/ 241 vpioctl(dev, cmd, addr, flag) 242 dev_t dev; 243 int cmd; 244 register caddr_t addr; 245 int flag; 246 { 247 register int m; 248 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 249 register struct vpdevice *vpaddr = 250 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 251 252 switch (cmd) { 253 254 case VGETSTATE: 255 (void) suword(addr, sc->sc_state); 256 return; 257 258 case VSETSTATE: 259 m = fuword(addr); 260 if (m == -1) { 261 u.u_error = EFAULT; 262 return; 263 } 264 sc->sc_state = 265 (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); 266 break; 267 268 default: 269 u.u_error = ENOTTY; 270 return; 271 } 272 (void) spl4(); 273 (void) vpwait(dev); 274 if (sc->sc_state&VPSC_SPP) 275 vpaddr->plcsr |= VP_SPP; 276 else 277 vpaddr->plcsr &= ~VP_SPP; 278 sc->sc_count = 0; 279 while (sc->sc_state & VPSC_CMNDS) { 280 (void) vpwait(dev); 281 vpstart(dev); 282 } 283 (void) spl0(); 284 } 285 286 vptimo(dev) 287 dev_t dev; 288 { 289 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 290 291 if (sc->sc_state&VPSC_OPEN) 292 timeout(vptimo, (caddr_t)dev, hz/10); 293 vpintr(dev); 294 } 295 296 /*ARGSUSED*/ 297 vpintr(dev) 298 dev_t dev; 299 { 300 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 301 302 wakeup((caddr_t)sc); 303 } 304 305 vpclose(dev) 306 dev_t dev; 307 { 308 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 309 register struct vpdevice *vpaddr = 310 (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 311 312 sc->sc_state = 0; 313 sc->sc_count = 0; 314 vpaddr->plcsr = 0; 315 } 316 317 vpreset(uban) 318 int uban; 319 { 320 register int vp11; 321 register struct uba_device *ui; 322 register struct vp_softc *sc = vp_softc; 323 register struct vpdevice *vpaddr; 324 325 for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 326 if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 327 ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 328 continue; 329 printf(" vp%d", vp11); 330 vpaddr = (struct vpdevice *)ui->ui_addr; 331 vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 332 if ((sc->sc_state & VPSC_BUSY) == 0) 333 continue; 334 if (sc->sc_ubinfo) { 335 printf("<%d>", (sc->sc_ubinfo>>28)&0xf); 336 ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 337 } 338 sc->sc_count = sc->sc_bp->b_bcount; 339 vpstart(sc->sc_bp->b_dev); 340 } 341 } 342 343 vpselect() 344 { 345 return (1); 346 } 347 #endif 348