1*133Sbill /* va.c 3.2 10/14/12 */ 241Sbill 341Sbill #ifdef ERNIE 441Sbill #include "../h/param.h" 541Sbill #include "../h/dir.h" 641Sbill #include "../h/user.h" 741Sbill #include "../h/buf.h" 841Sbill #include "../h/systm.h" 941Sbill #include "../h/map.h" 1041Sbill #include "../h/pte.h" 1141Sbill #include "../h/uba.h" 1241Sbill #include "../h/vcmd.h" 1341Sbill 1441Sbill /* 1541Sbill * Benson-Varian matrix printer/plotter. Device "va", for "varian". 1641Sbill * dma interface driver 1741Sbill */ 1841Sbill int vabdp = 1; /* Used with ubasetup. */ 1941Sbill 2041Sbill unsigned minvaph(); /* Maximum amount transferred by physio. */ 2141Sbill 2241Sbill #define VAPRI (PZERO-1) 2341Sbill 2441Sbill struct varegs { /* Unibus registers provided by va. */ 2541Sbill unsigned short vabufaddr; /* DMA buffer address. */ 2641Sbill short vawcount; /* Negative of number of 16-bit 2741Sbill words to transfer by DMA. */ 2841Sbill union { 2941Sbill short vacsrword; /* csr addressed as a word (for R). */ 3041Sbill struct { 3141Sbill char Vacsrlo; 3241Sbill char Vacsrhi; /* High byte (command bytes go here). */ 3341Sbill } vacsrbytes; /* csr addressed as bytes (for W). */ 3441Sbill } vacsr; /* Control/Status Register (csr). */ 3541Sbill short vadata; 3641Sbill }; 3741Sbill 3841Sbill #define vacsrhi vacsr.vacsrbytes.Vacsrhi 3941Sbill #define vacsrlo vacsr.vacsrbytes.Vacsrlo 4041Sbill #define VAADDR ((struct varegs *)(UBA0_DEV + 0164000)) 4141Sbill 4241Sbill /* vacsr.vacsrword bits: */ 4341Sbill #define ERROR 0100000 /* R Some error has occurred */ 4441Sbill #define NPRTIMO 01000 /* R DMA timeout error */ 4541Sbill #define NOTREADY 0400 /* R Something besides NPRTIMO */ 4641Sbill #define DONE 0200 /* R */ 4741Sbill #define IENABLE 0100 /* R/W Interrupt enable */ 4841Sbill #define SUPPLIESLOW 04 /* R */ 4941Sbill #define BOTOFFORM 02 /* R */ 5041Sbill #define BYTEREVERSE 01 /* R/W Reverse byte order in words */ 5141Sbill 5241Sbill /* Command bytes sent to vacsrhi */ 5341Sbill #define VAPLOT 0340 5441Sbill #define VAPRINT 0100 5541Sbill #define VAPRINTPLOT 0160 5641Sbill #define VAAUTOSTEP 0244 5741Sbill /* The following commands are not used in this driver: */ 5841Sbill #define VANOAUTOSTEP 0045 5941Sbill #define VAFORMFEED 0263 6041Sbill #define VASLEW 0265 6141Sbill #define VASTEP 0064 6241Sbill 6341Sbill struct { 6441Sbill char va_is_open; 6541Sbill char va_busy; 6641Sbill int va_state; /* State: bits are commands in vcmd.h. */ 6741Sbill int va_wcount; 6841Sbill int va_bufp; 6941Sbill } vainfo; 7041Sbill int va_ubinfo; 7141Sbill 7241Sbill struct buf rvabuf; /* Used by physio for a buffer. */ 7341Sbill 7441Sbill vaopen() 7541Sbill { 7641Sbill 7741Sbill if (vainfo.va_is_open) { /* Can't open if it's already open. */ 7841Sbill u.u_error = ENXIO; 7941Sbill return; 8041Sbill } 8141Sbill vainfo.va_is_open = 1; /* NOW it's open! */ 8241Sbill VAADDR->vawcount = 0; /* Clear residual errors */ 8341Sbill vainfo.va_wcount = 0; /* No DMA to do now. */ 8441Sbill vainfo.va_state = 0; 8541Sbill VAADDR->vacsrlo = IENABLE; 8641Sbill /* Enable interrupts. */ 8741Sbill vatimo(); 8841Sbill 8941Sbill vacmd(VPRINT); /* Start in print mode. */ 9041Sbill if (u.u_error) 9141Sbill vaclose(); 9241Sbill } 9341Sbill 9441Sbill vastrategy(bp) 9541Sbill register struct buf *bp; 9641Sbill { 9741Sbill register int e; 9841Sbill 99*133Sbill (void) spl4(); 10041Sbill while (vainfo.va_busy) /* Wait till not busy. */ 10141Sbill sleep((caddr_t)&vainfo, VAPRI); 10241Sbill vainfo.va_busy = 1; /* Grab it. */ 103*133Sbill (void) spl0(); 10441Sbill 10541Sbill va_ubinfo = ubasetup(bp, vabdp); /* Set up uba mapper. */ 10641Sbill vainfo.va_bufp = va_ubinfo & 0x3ffff; 10741Sbill 108*133Sbill (void) spl4(); 10941Sbill if (e = vaerror(DONE)) 11041Sbill goto brkout; 11141Sbill vainfo.va_wcount = -(bp->b_bcount/2); 11241Sbill /* va uses a word count, 11341Sbill so user had better supply an even number of bytes. */ 11441Sbill vastart(); 11541Sbill e = vaerror(DONE); /* Wait for DMA to complete. */ 11641Sbill vainfo.va_wcount = 0; /* Reset state info. */ 11741Sbill vainfo.va_bufp = 0; 11841Sbill 11941Sbill /* After printing a line of characters, VPRINTPLOT mode essentially 12041Sbill reverts to VPLOT mode, plotting things until a new mode is set. 12141Sbill This change is indicated by sending a VAAUTOSTEP command to 12241Sbill the va. We also change va_state to reflect this effective 12341Sbill mode change. 12441Sbill */ 12541Sbill if (vainfo.va_state & VPRINTPLOT) { 12641Sbill vainfo.va_state = (vainfo.va_state & ~VPRINTPLOT) | VPLOT; 12741Sbill VAADDR->vacsrhi = VAAUTOSTEP; 12841Sbill e |= vaerror(DONE); 12941Sbill } 130*133Sbill (void) spl0(); 13141Sbill brkout: 13241Sbill ubafree(va_ubinfo), va_ubinfo = 0; 13341Sbill vainfo.va_busy = 0; 13441Sbill iodone(bp); 13541Sbill if (e) 13641Sbill u.u_error = EIO; 13741Sbill wakeup((caddr_t)&vainfo); 13841Sbill } 13941Sbill 14041Sbill int vablock = 16384; 14141Sbill 14241Sbill unsigned 14341Sbill minvaph(bp) 14441Sbill struct buf *bp; 14541Sbill { 14641Sbill if (bp->b_bcount > vablock) 14741Sbill bp->b_bcount = vablock; 14841Sbill } 14941Sbill 15041Sbill /*ARGSUSED*/ 15141Sbill vawrite(dev) 15241Sbill { 15341Sbill physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph); 15441Sbill } 15541Sbill 15641Sbill /* 15741Sbill * Vaerror waits until bit or ERROR gets set, then returns non-zero if 15841Sbill * if it was ERROR that was set. 15941Sbill */ 16041Sbill vaerror(bit) 16141Sbill { 16241Sbill register int e; 16341Sbill 16441Sbill while ((e = VAADDR->vacsr.vacsrword & (bit|ERROR)) == 0) 16541Sbill sleep((caddr_t)&vainfo, VAPRI); 16641Sbill return (e & ERROR); 16741Sbill } 16841Sbill 16941Sbill /* vastart starts up the DMA by setting the buffer pointer and the word count. */ 17041Sbill vastart() 17141Sbill { 17241Sbill if (vainfo.va_wcount) { 17341Sbill VAADDR->vabufaddr = vainfo.va_bufp; 17441Sbill VAADDR->vawcount = vainfo.va_wcount; 17541Sbill return; 17641Sbill } 17741Sbill } 17841Sbill 17941Sbill /*ARGSUSED*/ 18041Sbill vaioctl(dev, cmd, addr, flag) 18141Sbill register caddr_t addr; 18241Sbill { 18341Sbill register int vcmd; 18441Sbill 18541Sbill switch (cmd) { 18641Sbill 18741Sbill case VGETSTATE: 188*133Sbill (void) suword(addr, vainfo.va_state); 18941Sbill return; 19041Sbill 19141Sbill case VSETSTATE: 19241Sbill vcmd = fuword(addr); 19341Sbill if (vcmd == -1) { 19441Sbill u.u_error = EFAULT; 19541Sbill return; 19641Sbill } 19741Sbill vacmd(vcmd); 19841Sbill return; 19941Sbill 20041Sbill default: 20141Sbill u.u_error = ENOTTY; /* Not a legal ioctl cmd. */ 20241Sbill return; 20341Sbill } 20441Sbill } 20541Sbill 20641Sbill /* vacmd sends a command code to the va, and waits for it to complete. 20741Sbill If an error occurs, u.u_error is set to EIO. 20841Sbill vacmd also updates vainfo.va_state. 20941Sbill */ 21041Sbill 21141Sbill vacmd(vcmd) 21241Sbill { 213*133Sbill (void) spl4(); 214*133Sbill (void) vaerror(DONE); /* Wait for va to be ready. */ 21541Sbill switch (vcmd) { 21641Sbill 21741Sbill case VPLOT: 21841Sbill /* Must turn on plot AND autostep modes. */ 21941Sbill VAADDR->vacsrhi = VAPLOT; 22041Sbill if (vaerror(DONE)) 22141Sbill u.u_error = EIO; 22241Sbill VAADDR->vacsrhi = VAAUTOSTEP; 22341Sbill break; 22441Sbill 22541Sbill case VPRINT: 22641Sbill VAADDR->vacsrhi = VAPRINT; 22741Sbill break; 22841Sbill 22941Sbill case VPRINTPLOT: 23041Sbill VAADDR->vacsrhi = VAPRINTPLOT; 23141Sbill break; 23241Sbill } 23341Sbill vainfo.va_state = 23441Sbill (vainfo.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd; 23541Sbill 23641Sbill if (vaerror(DONE)) /* Wait for command to complete. */ 23741Sbill u.u_error = EIO; 238*133Sbill (void) spl0(); 23941Sbill } 24041Sbill 24141Sbill vatimo() 24241Sbill { 24341Sbill if (vainfo.va_is_open) 24441Sbill timeout(vatimo, (caddr_t)0, HZ/10); 24541Sbill vaintr(0); 24641Sbill } 24741Sbill 24841Sbill /*ARGSUSED*/ 24941Sbill vaintr(dev) 25041Sbill { 25141Sbill wakeup((caddr_t)&vainfo); 25241Sbill } 25341Sbill 25441Sbill vaclose() 25541Sbill { 25641Sbill 25741Sbill vainfo.va_is_open = 0; 25841Sbill vainfo.va_busy = 0; 25941Sbill vainfo.va_state = 0; 26041Sbill vainfo.va_wcount = 0; 26141Sbill vainfo.va_bufp = 0; 26241Sbill VAADDR->vacsrlo = 0; 26341Sbill } 26441Sbill #endif 265