/* * Versatec matrix printer/plotter * dma interface driver */ #include "../h/param.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/buf.h" #include "../h/systm.h" #define VPPRI (PZERO+8) /* device registers */ struct vpregs { int plbcr; int fill; int prbcr; caddr_t pbaddr; int plcsr; int plbuf; int prcsr; caddr_t prbuf; }; #define VPADDR ((struct vpregs *)0177500) /* status bits */ #define ERROR 0100000 #define DTCINTR 040000 #define DMAACT 020000 #define READY 0200 #define IENABLE 0100 #define TERMCOM 040 #define FFCOM 020 #define EOTCOM 010 #define CLRCOM 04 #define RESET 02 #define SPP 01 struct { int vp_state; int vp_count; struct buf *vp_buf; caddr_t vp_bufp; } vp11; /*states */ #define ISOPEN 01 #define CMNDS 076 #define MODE 0700 #define PRINT 0100 #define PLOT 0200 #define PPLOT 0400 #define BUSY 01000 vpopen() { if (vp11.vp_state & ISOPEN) { u.u_error = ENXIO; return; } vp11.vp_state = ISOPEN | PRINT | CLRCOM | FFCOM | RESET; vp11.vp_count = 0; vp11.vp_buf = geteblk(); vp11.vp_bufp = vp11.vp_buf->b_un.b_addr; VPADDR->prcsr = IENABLE | DTCINTR; vptimo(); while(vp11.vp_state & CMNDS) { spl4(); if (vperror(READY)) { vpclose(); u.u_error = EIO; return; } vpstart(); spl0(); } } vpwrite() { register int i, e; if (u.u_count == 0) return; spl4(); while(vp11.vp_state & BUSY) sleep((caddr_t)&vp11, VPPRI); vp11.vp_state |= BUSY; spl0(); while(i = vp11.vp_count = min(512,u.u_count)) { u.u_offset = 0; /* Make even, speed up iomove */ iomove(vp11.vp_buf->b_un.b_addr, i, B_WRITE); spl4(); if (e = vperror(READY)) break; vpstart(); while ((vp11.vp_state&PLOT?VPADDR->plcsr:VPADDR->prcsr)&DMAACT) sleep((caddr_t)&vp11, VPPRI); if ((vp11.vp_state&MODE) == PPLOT) vp11.vp_state = vp11.vp_state&~MODE | PLOT; spl0(); } vp11.vp_state &= ~BUSY; if (e) u.u_error = EIO; wakeup((caddr_t)&vp11); } vperror(bit) { register state, e; state = vp11.vp_state&PLOT; while((e=(state?VPADDR->plcsr:VPADDR->prcsr) & (bit|ERROR)) == 0) sleep((caddr_t)&vp11, VPPRI); return(e&ERROR); } vpstart() { register bit; if (vp11.vp_count) { VPADDR->pbaddr = vp11.vp_bufp; if (vp11.vp_state & (PRINT|PPLOT)) VPADDR->prbcr = vp11.vp_count; else VPADDR->plbcr = vp11.vp_count; return; } for (bit=1; bit!=0; bit <<= 1) if (vp11.vp_state&bit&CMNDS) { VPADDR->plcsr |= bit; vp11.vp_state &= ~bit; return; } } vpioctl(dev, cmd, addr, flag) register caddr_t addr; { register m; switch(cmd) { /* get mode */ case ('v'<<8)+0: suword(addr, vp11.vp_state); return; /* set mode */ case ('v'<<8)+1: m = fuword(addr); if (m == -1) { u.u_error = EFAULT; return; } spl4(); vperror(READY); vp11.vp_state = (vp11.vp_state & ~MODE) | (m&(MODE|CMNDS)); if (vp11.vp_state&PPLOT) VPADDR->plcsr |= SPP; else VPADDR->plcsr &= ~SPP; vp11.vp_count = 0; while(CMNDS & vp11.vp_state) { vperror(READY); vpstart(); } spl0(); return; default: u.u_error = ENOTTY; return; } } vptimo() { if (vp11.vp_state&ISOPEN) timeout(vptimo, (caddr_t)0, HZ/10); vpintr(0); } vpintr(dev) { wakeup((caddr_t)&vp11); } vpclose() { brelse(vp11.vp_buf); vp11.vp_state = 0; vp11.vp_count = 0; vp11.vp_buf = 0; vp11.vp_bufp = 0; VPADDR->plcsr = 0; }