1*41Sbill /* va.c 3.1 10/14/12 */ 2*41Sbill 3*41Sbill #ifdef ERNIE 4*41Sbill #include "../h/param.h" 5*41Sbill #include "../h/dir.h" 6*41Sbill #include "../h/user.h" 7*41Sbill #include "../h/buf.h" 8*41Sbill #include "../h/systm.h" 9*41Sbill #include "../h/map.h" 10*41Sbill #include "../h/pte.h" 11*41Sbill #include "../h/uba.h" 12*41Sbill #include "../h/vcmd.h" 13*41Sbill 14*41Sbill /* 15*41Sbill * Benson-Varian matrix printer/plotter. Device "va", for "varian". 16*41Sbill * dma interface driver 17*41Sbill */ 18*41Sbill int vabdp = 1; /* Used with ubasetup. */ 19*41Sbill 20*41Sbill unsigned minvaph(); /* Maximum amount transferred by physio. */ 21*41Sbill 22*41Sbill #define VAPRI (PZERO-1) 23*41Sbill 24*41Sbill struct varegs { /* Unibus registers provided by va. */ 25*41Sbill unsigned short vabufaddr; /* DMA buffer address. */ 26*41Sbill short vawcount; /* Negative of number of 16-bit 27*41Sbill words to transfer by DMA. */ 28*41Sbill union { 29*41Sbill short vacsrword; /* csr addressed as a word (for R). */ 30*41Sbill struct { 31*41Sbill char Vacsrlo; 32*41Sbill char Vacsrhi; /* High byte (command bytes go here). */ 33*41Sbill } vacsrbytes; /* csr addressed as bytes (for W). */ 34*41Sbill } vacsr; /* Control/Status Register (csr). */ 35*41Sbill short vadata; 36*41Sbill }; 37*41Sbill 38*41Sbill #define vacsrhi vacsr.vacsrbytes.Vacsrhi 39*41Sbill #define vacsrlo vacsr.vacsrbytes.Vacsrlo 40*41Sbill #define VAADDR ((struct varegs *)(UBA0_DEV + 0164000)) 41*41Sbill 42*41Sbill /* vacsr.vacsrword bits: */ 43*41Sbill #define ERROR 0100000 /* R Some error has occurred */ 44*41Sbill #define NPRTIMO 01000 /* R DMA timeout error */ 45*41Sbill #define NOTREADY 0400 /* R Something besides NPRTIMO */ 46*41Sbill #define DONE 0200 /* R */ 47*41Sbill #define IENABLE 0100 /* R/W Interrupt enable */ 48*41Sbill #define SUPPLIESLOW 04 /* R */ 49*41Sbill #define BOTOFFORM 02 /* R */ 50*41Sbill #define BYTEREVERSE 01 /* R/W Reverse byte order in words */ 51*41Sbill 52*41Sbill /* Command bytes sent to vacsrhi */ 53*41Sbill #define VAPLOT 0340 54*41Sbill #define VAPRINT 0100 55*41Sbill #define VAPRINTPLOT 0160 56*41Sbill #define VAAUTOSTEP 0244 57*41Sbill /* The following commands are not used in this driver: */ 58*41Sbill #define VANOAUTOSTEP 0045 59*41Sbill #define VAFORMFEED 0263 60*41Sbill #define VASLEW 0265 61*41Sbill #define VASTEP 0064 62*41Sbill 63*41Sbill struct { 64*41Sbill char va_is_open; 65*41Sbill char va_busy; 66*41Sbill int va_state; /* State: bits are commands in vcmd.h. */ 67*41Sbill int va_wcount; 68*41Sbill int va_bufp; 69*41Sbill } vainfo; 70*41Sbill int va_ubinfo; 71*41Sbill 72*41Sbill struct buf rvabuf; /* Used by physio for a buffer. */ 73*41Sbill 74*41Sbill vaopen() 75*41Sbill { 76*41Sbill 77*41Sbill if (vainfo.va_is_open) { /* Can't open if it's already open. */ 78*41Sbill u.u_error = ENXIO; 79*41Sbill return; 80*41Sbill } 81*41Sbill vainfo.va_is_open = 1; /* NOW it's open! */ 82*41Sbill VAADDR->vawcount = 0; /* Clear residual errors */ 83*41Sbill vainfo.va_wcount = 0; /* No DMA to do now. */ 84*41Sbill vainfo.va_state = 0; 85*41Sbill VAADDR->vacsrlo = IENABLE; 86*41Sbill /* Enable interrupts. */ 87*41Sbill vatimo(); 88*41Sbill 89*41Sbill vacmd(VPRINT); /* Start in print mode. */ 90*41Sbill if (u.u_error) 91*41Sbill vaclose(); 92*41Sbill } 93*41Sbill 94*41Sbill vastrategy(bp) 95*41Sbill register struct buf *bp; 96*41Sbill { 97*41Sbill register int e; 98*41Sbill 99*41Sbill VOID spl4(); 100*41Sbill while (vainfo.va_busy) /* Wait till not busy. */ 101*41Sbill sleep((caddr_t)&vainfo, VAPRI); 102*41Sbill vainfo.va_busy = 1; /* Grab it. */ 103*41Sbill VOID spl0(); 104*41Sbill 105*41Sbill va_ubinfo = ubasetup(bp, vabdp); /* Set up uba mapper. */ 106*41Sbill vainfo.va_bufp = va_ubinfo & 0x3ffff; 107*41Sbill 108*41Sbill VOID spl4(); 109*41Sbill if (e = vaerror(DONE)) 110*41Sbill goto brkout; 111*41Sbill vainfo.va_wcount = -(bp->b_bcount/2); 112*41Sbill /* va uses a word count, 113*41Sbill so user had better supply an even number of bytes. */ 114*41Sbill vastart(); 115*41Sbill e = vaerror(DONE); /* Wait for DMA to complete. */ 116*41Sbill vainfo.va_wcount = 0; /* Reset state info. */ 117*41Sbill vainfo.va_bufp = 0; 118*41Sbill 119*41Sbill /* After printing a line of characters, VPRINTPLOT mode essentially 120*41Sbill reverts to VPLOT mode, plotting things until a new mode is set. 121*41Sbill This change is indicated by sending a VAAUTOSTEP command to 122*41Sbill the va. We also change va_state to reflect this effective 123*41Sbill mode change. 124*41Sbill */ 125*41Sbill if (vainfo.va_state & VPRINTPLOT) { 126*41Sbill vainfo.va_state = (vainfo.va_state & ~VPRINTPLOT) | VPLOT; 127*41Sbill VAADDR->vacsrhi = VAAUTOSTEP; 128*41Sbill e |= vaerror(DONE); 129*41Sbill } 130*41Sbill VOID spl0(); 131*41Sbill brkout: 132*41Sbill ubafree(va_ubinfo), va_ubinfo = 0; 133*41Sbill vainfo.va_busy = 0; 134*41Sbill iodone(bp); 135*41Sbill if (e) 136*41Sbill u.u_error = EIO; 137*41Sbill wakeup((caddr_t)&vainfo); 138*41Sbill } 139*41Sbill 140*41Sbill int vablock = 16384; 141*41Sbill 142*41Sbill unsigned 143*41Sbill minvaph(bp) 144*41Sbill struct buf *bp; 145*41Sbill { 146*41Sbill if (bp->b_bcount > vablock) 147*41Sbill bp->b_bcount = vablock; 148*41Sbill } 149*41Sbill 150*41Sbill /*ARGSUSED*/ 151*41Sbill vawrite(dev) 152*41Sbill { 153*41Sbill physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph); 154*41Sbill } 155*41Sbill 156*41Sbill /* 157*41Sbill * Vaerror waits until bit or ERROR gets set, then returns non-zero if 158*41Sbill * if it was ERROR that was set. 159*41Sbill */ 160*41Sbill vaerror(bit) 161*41Sbill { 162*41Sbill register int e; 163*41Sbill 164*41Sbill while ((e = VAADDR->vacsr.vacsrword & (bit|ERROR)) == 0) 165*41Sbill sleep((caddr_t)&vainfo, VAPRI); 166*41Sbill return (e & ERROR); 167*41Sbill } 168*41Sbill 169*41Sbill /* vastart starts up the DMA by setting the buffer pointer and the word count. */ 170*41Sbill vastart() 171*41Sbill { 172*41Sbill if (vainfo.va_wcount) { 173*41Sbill VAADDR->vabufaddr = vainfo.va_bufp; 174*41Sbill VAADDR->vawcount = vainfo.va_wcount; 175*41Sbill return; 176*41Sbill } 177*41Sbill } 178*41Sbill 179*41Sbill /*ARGSUSED*/ 180*41Sbill vaioctl(dev, cmd, addr, flag) 181*41Sbill register caddr_t addr; 182*41Sbill { 183*41Sbill register int vcmd; 184*41Sbill 185*41Sbill switch (cmd) { 186*41Sbill 187*41Sbill case VGETSTATE: 188*41Sbill VOID suword(addr, vainfo.va_state); 189*41Sbill return; 190*41Sbill 191*41Sbill case VSETSTATE: 192*41Sbill vcmd = fuword(addr); 193*41Sbill if (vcmd == -1) { 194*41Sbill u.u_error = EFAULT; 195*41Sbill return; 196*41Sbill } 197*41Sbill vacmd(vcmd); 198*41Sbill return; 199*41Sbill 200*41Sbill default: 201*41Sbill u.u_error = ENOTTY; /* Not a legal ioctl cmd. */ 202*41Sbill return; 203*41Sbill } 204*41Sbill } 205*41Sbill 206*41Sbill /* vacmd sends a command code to the va, and waits for it to complete. 207*41Sbill If an error occurs, u.u_error is set to EIO. 208*41Sbill vacmd also updates vainfo.va_state. 209*41Sbill */ 210*41Sbill 211*41Sbill vacmd(vcmd) 212*41Sbill { 213*41Sbill VOID spl4(); 214*41Sbill VOID vaerror(DONE); /* Wait for va to be ready. */ 215*41Sbill switch (vcmd) { 216*41Sbill 217*41Sbill case VPLOT: 218*41Sbill /* Must turn on plot AND autostep modes. */ 219*41Sbill VAADDR->vacsrhi = VAPLOT; 220*41Sbill if (vaerror(DONE)) 221*41Sbill u.u_error = EIO; 222*41Sbill VAADDR->vacsrhi = VAAUTOSTEP; 223*41Sbill break; 224*41Sbill 225*41Sbill case VPRINT: 226*41Sbill VAADDR->vacsrhi = VAPRINT; 227*41Sbill break; 228*41Sbill 229*41Sbill case VPRINTPLOT: 230*41Sbill VAADDR->vacsrhi = VAPRINTPLOT; 231*41Sbill break; 232*41Sbill } 233*41Sbill vainfo.va_state = 234*41Sbill (vainfo.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd; 235*41Sbill 236*41Sbill if (vaerror(DONE)) /* Wait for command to complete. */ 237*41Sbill u.u_error = EIO; 238*41Sbill VOID spl0(); 239*41Sbill } 240*41Sbill 241*41Sbill vatimo() 242*41Sbill { 243*41Sbill if (vainfo.va_is_open) 244*41Sbill timeout(vatimo, (caddr_t)0, HZ/10); 245*41Sbill vaintr(0); 246*41Sbill } 247*41Sbill 248*41Sbill /*ARGSUSED*/ 249*41Sbill vaintr(dev) 250*41Sbill { 251*41Sbill wakeup((caddr_t)&vainfo); 252*41Sbill } 253*41Sbill 254*41Sbill vaclose() 255*41Sbill { 256*41Sbill 257*41Sbill vainfo.va_is_open = 0; 258*41Sbill vainfo.va_busy = 0; 259*41Sbill vainfo.va_state = 0; 260*41Sbill vainfo.va_wcount = 0; 261*41Sbill vainfo.va_bufp = 0; 262*41Sbill VAADDR->vacsrlo = 0; 263*41Sbill } 264*41Sbill #endif 265