1*1564Sbill /* va.c 3.7 10/19/80 */ 241Sbill 3*1564Sbill #include "../conf/va.h" 4*1564Sbill #if NVA > 0 5*1564Sbill /* 6*1564Sbill * Benson-Varian matrix printer/plotter 7*1564Sbill * dma interface driver 8*1564Sbill */ 941Sbill #include "../h/param.h" 1041Sbill #include "../h/dir.h" 1141Sbill #include "../h/user.h" 1241Sbill #include "../h/buf.h" 1341Sbill #include "../h/systm.h" 1441Sbill #include "../h/map.h" 1541Sbill #include "../h/pte.h" 1641Sbill #include "../h/uba.h" 1741Sbill #include "../h/vcmd.h" 1841Sbill 19287Sbill int vabdp = 1; 2041Sbill 21287Sbill unsigned minvaph(); 2241Sbill 2341Sbill #define VAPRI (PZERO-1) 2441Sbill 25287Sbill #define ushort unsigned short 26287Sbill struct varegs { 27287Sbill ushort vaba; 28287Sbill short vawc; 2941Sbill union { 30287Sbill short Vacsw; 3141Sbill struct { 32287Sbill char Vacsl; 33287Sbill char Vacsh; 34287Sbill } vacsr; 35287Sbill } vacs; 3641Sbill short vadata; 3741Sbill }; 3841Sbill 39287Sbill #define vacsw vacs.Vacsw 40287Sbill #define vacsh vacs.vacsr.Vacsh 41287Sbill #define vacsl vacs.vacsr.Vacsl 42287Sbill 43287Sbill /* vacsw bits */ 44287Sbill #define ERROR 0100000 /* Some error has occurred */ 45*1564Sbill #define NPRTIMO 01000 /* DMA timeout error */ 46*1564Sbill #define NOTREADY 0400 /* Something besides NPRTIMO */ 47*1564Sbill #define DONE 0200 48287Sbill #define IENABLE 0100 /* Interrupt enable */ 49287Sbill #define SUPPLIESLOW 04 50*1564Sbill #define BOTOFFORM 02 51*1564Sbill #define BYTEREVERSE 01 /* Reverse byte order in words */ 5241Sbill 53287Sbill /* vacsh command bytes */ 54*1564Sbill #define VAPLOT 0340 55*1564Sbill #define VAPRINT 0100 56*1564Sbill #define VAPRINTPLOT 0160 57*1564Sbill #define VAAUTOSTEP 0244 58*1564Sbill #define VANOAUTOSTEP 0045 /* unused */ 59287Sbill #define VAFORMFEED 0263 /* unused */ 60287Sbill #define VASLEW 0265 /* unused */ 61287Sbill #define VASTEP 0064 /* unused */ 6241Sbill 6341Sbill struct { 64287Sbill char va_open; 6541Sbill char va_busy; 6641Sbill int va_state; /* State: bits are commands in vcmd.h. */ 67287Sbill int va_wc; 6841Sbill int va_bufp; 69287Sbill struct buf *va_bp; 70287Sbill } va11; 7141Sbill int va_ubinfo; 7241Sbill 7341Sbill struct buf rvabuf; /* Used by physio for a buffer. */ 7441Sbill 7541Sbill vaopen() 7641Sbill { 7741Sbill 78287Sbill if (va11.va_open) { 7941Sbill u.u_error = ENXIO; 8041Sbill return; 8141Sbill } 82287Sbill va11.va_open = 1; 83287Sbill VAADDR->vawc = 0; 84287Sbill va11.va_wc = 0; 85287Sbill va11.va_state = 0; 86287Sbill VAADDR->vacsl = IENABLE; 8741Sbill vatimo(); 88287Sbill vacmd(VPRINT); 8941Sbill if (u.u_error) 9041Sbill vaclose(); 9141Sbill } 9241Sbill 9341Sbill vastrategy(bp) 9441Sbill register struct buf *bp; 9541Sbill { 9641Sbill register int e; 9741Sbill 98133Sbill (void) spl4(); 99287Sbill while (va11.va_busy) 100287Sbill sleep((caddr_t)&va11, VAPRI); 101287Sbill va11.va_busy = 1; 102287Sbill va11.va_bp = bp; 103287Sbill va_ubinfo = ubasetup(bp, vabdp); 104287Sbill va11.va_bufp = va_ubinfo & 0x3ffff; 10541Sbill if (e = vaerror(DONE)) 10641Sbill goto brkout; 107287Sbill va11.va_wc = -(bp->b_bcount/2); 10841Sbill vastart(); 109287Sbill e = vaerror(DONE); /* Wait for DMA to complete */ 110287Sbill va11.va_wc = 0; 111287Sbill va11.va_bufp = 0; 11241Sbill 113287Sbill /* 114287Sbill * After printing a line of characters, VPRINTPLOT mode essentially 115287Sbill * reverts to VPLOT mode, plotting things until a new mode is set. 116287Sbill * This change is indicated by sending a VAAUTOSTEP command to 117287Sbill * the va. We also change va_state to reflect this effective 118287Sbill * mode change. 11941Sbill */ 120287Sbill if (va11.va_state & VPRINTPLOT) { 121287Sbill va11.va_state = (va11.va_state & ~VPRINTPLOT) | VPLOT; 122287Sbill VAADDR->vacsh = VAAUTOSTEP; 12341Sbill e |= vaerror(DONE); 12441Sbill } 125133Sbill (void) spl0(); 12641Sbill brkout: 12741Sbill ubafree(va_ubinfo), va_ubinfo = 0; 128287Sbill va11.va_bp = 0; 129287Sbill va11.va_busy = 0; 13041Sbill iodone(bp); 13141Sbill if (e) 13241Sbill u.u_error = EIO; 133287Sbill wakeup((caddr_t)&va11); 13441Sbill } 13541Sbill 13641Sbill int vablock = 16384; 13741Sbill 13841Sbill unsigned 13941Sbill minvaph(bp) 14041Sbill struct buf *bp; 14141Sbill { 14241Sbill if (bp->b_bcount > vablock) 14341Sbill bp->b_bcount = vablock; 14441Sbill } 14541Sbill 14641Sbill /*ARGSUSED*/ 14741Sbill vawrite(dev) 14841Sbill { 14941Sbill physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph); 15041Sbill } 15141Sbill 15241Sbill /* 15341Sbill * Vaerror waits until bit or ERROR gets set, then returns non-zero if 15441Sbill * if it was ERROR that was set. 15541Sbill */ 15641Sbill vaerror(bit) 15741Sbill { 15841Sbill register int e; 15941Sbill 160287Sbill while ((e = VAADDR->vacsw & (bit|ERROR)) == 0) 161287Sbill sleep((caddr_t)&va11, VAPRI); 16241Sbill return (e & ERROR); 16341Sbill } 16441Sbill 16541Sbill vastart() 16641Sbill { 167287Sbill if (va11.va_wc) { 168287Sbill VAADDR->vaba = va11.va_bufp; 169287Sbill VAADDR->vawc = va11.va_wc; 17041Sbill return; 17141Sbill } 17241Sbill } 17341Sbill 17441Sbill /*ARGSUSED*/ 17541Sbill vaioctl(dev, cmd, addr, flag) 17641Sbill register caddr_t addr; 17741Sbill { 17841Sbill register int vcmd; 17941Sbill 18041Sbill switch (cmd) { 18141Sbill 18241Sbill case VGETSTATE: 183287Sbill (void) suword(addr, va11.va_state); 18441Sbill return; 18541Sbill 18641Sbill case VSETSTATE: 18741Sbill vcmd = fuword(addr); 18841Sbill if (vcmd == -1) { 18941Sbill u.u_error = EFAULT; 19041Sbill return; 19141Sbill } 19241Sbill vacmd(vcmd); 19341Sbill return; 19441Sbill 19541Sbill default: 19641Sbill u.u_error = ENOTTY; /* Not a legal ioctl cmd. */ 19741Sbill return; 19841Sbill } 19941Sbill } 20041Sbill 201287Sbill /* 202287Sbill * Send a command code to the va, and wait for it to complete. 203287Sbill * If an error occurs, u.u_error is set to EIO. 204287Sbill * In any case, update va11.va_state. 20541Sbill */ 20641Sbill vacmd(vcmd) 20741Sbill { 208133Sbill (void) spl4(); 209287Sbill (void) vaerror(DONE); /* Wait for va to be ready */ 21041Sbill switch (vcmd) { 21141Sbill 21241Sbill case VPLOT: 21341Sbill /* Must turn on plot AND autostep modes. */ 214287Sbill VAADDR->vacsh = VAPLOT; 21541Sbill if (vaerror(DONE)) 21641Sbill u.u_error = EIO; 217287Sbill VAADDR->vacsh = VAAUTOSTEP; 21841Sbill break; 21941Sbill 22041Sbill case VPRINT: 221287Sbill VAADDR->vacsh = VAPRINT; 22241Sbill break; 22341Sbill 22441Sbill case VPRINTPLOT: 225287Sbill VAADDR->vacsh = VAPRINTPLOT; 22641Sbill break; 22741Sbill } 228287Sbill va11.va_state = 229287Sbill (va11.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd; 23041Sbill 23141Sbill if (vaerror(DONE)) /* Wait for command to complete. */ 23241Sbill u.u_error = EIO; 233133Sbill (void) spl0(); 23441Sbill } 23541Sbill 23641Sbill vatimo() 23741Sbill { 238287Sbill if (va11.va_open) 23941Sbill timeout(vatimo, (caddr_t)0, HZ/10); 24041Sbill vaintr(0); 24141Sbill } 24241Sbill 24341Sbill /*ARGSUSED*/ 24441Sbill vaintr(dev) 24541Sbill { 246287Sbill wakeup((caddr_t)&va11); 24741Sbill } 24841Sbill 24941Sbill vaclose() 25041Sbill { 25141Sbill 252287Sbill va11.va_open = 0; 253287Sbill va11.va_busy = 0; 254287Sbill va11.va_state = 0; 255287Sbill va11.va_wc = 0; 256287Sbill va11.va_bufp = 0; 257287Sbill VAADDR->vacsl = 0; 25841Sbill } 259287Sbill 260287Sbill #define DELAY(N) { register int d; d = N; while (--d > 0); } 261287Sbill 262287Sbill vareset() 263287Sbill { 264287Sbill 265287Sbill if (va11.va_open == 0) 266287Sbill return; 267287Sbill printf(" va"); 268287Sbill VAADDR->vacsl = IENABLE; 269287Sbill if (va11.va_state & VPLOT) { 270287Sbill VAADDR->vacsh = VAPLOT; 271287Sbill DELAY(10000); 272287Sbill VAADDR->vacsh = VAAUTOSTEP; 273287Sbill } else if (va11.va_state & VPRINTPLOT) 274287Sbill VAADDR->vacsh = VPRINTPLOT; 275287Sbill else 276287Sbill VAADDR->vacsh = VAPRINTPLOT; 277287Sbill DELAY(10000); 278287Sbill if (va11.va_busy == 0) 279287Sbill return; 280287Sbill if (va_ubinfo) { 281287Sbill printf("<%d>", (va_ubinfo>>28)&0xf); 282287Sbill ubafree(va_ubinfo), va_ubinfo = 0; 283287Sbill } 284287Sbill /* This code belongs in vastart() */ 285287Sbill va_ubinfo = ubasetup(va11.va_bp, vabdp); 286287Sbill va11.va_bufp = va_ubinfo & 0x3ffff; 287287Sbill va11.va_wc = (-va11.va_bp->b_bcount/2); 288287Sbill /* End badly placed code */ 289287Sbill vastart(); 290287Sbill } 291*1564Sbill #endif 292