/* * Interdata versatec model 1200A driver * Version 7 by Jim Rees Oct 1980 * * Makes use of wb() (write block) if WB is defined -- * this routine must be added to ../conf/mch.s wb equ * write block l r1,0(sp) wb r1,4(sp) br rf */ #include "../h/param.h" #include "../h/buf.h" #include "../h/conf.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/tty.h" #define WB /* wb() exists in ../conf/mch.s */ #define min(A,B) ((A) < (B) ? (A) : (B)) /* tuneable constants */ #define NVP 1 /* # of line printers */ #define VPPRI 28 /* Versatec priority */ #define LPBASE 0x62 /* starting address */ /* These next two depend on the Versatec model */ #define CBUFSIZ 132 /* character buffer size */ #define PLBUFSIZ 264 /* plot buffer size */ /* commands to controller */ #define CLEAR 04 #define REOT 05 #define RLF 06 #define RFF 07 #define RESET 014 #define PLOT 020 #define SPP 040 #define DISARM 0300 #define ENABLE 0100 #define PRINT 0 #define MODE (PLOT | SPP | ENABLE | DISARM) /* status from controller */ #define NOPWR 01 #define NOPAP 04 #define V_BUSY 010 /* flags */ #define ODD 01 /* Odd count */ #define OPEN 02 /* if device open for plot or print */ struct lp { short flags; short mode; /* command register copy */ short addr; /* physical address of device */ short nplchar; /* number of bytes plotted this line */ struct buf lpb; /* buffer header */ } vp[NVP]; char vpmodes[] = { 0, RESET, CLEAR, REOT, RFF, RLF, PRINT, PLOT, SPP }; vpopen(dev) int dev; { struct lp *alp; struct buf *abp; alp = &vp[minor(dev) % 64]; if (alp->flags & OPEN) { /* if already open */ u.u_error = EACCES; return; } if (minor(dev) < 64) alp->mode = PRINT; else alp->mode = PLOT; if (minor(dev)%64 >= NVP) { u.u_error = ENXIO; return; } alp->addr = LPBASE + 2 * (minor(dev)%64); abp = &alp->lpb; abp->b_flags = 0; abp->b_bcount = 0; if (ss(alp->addr) & (NOPAP | NOPWR | V_BUSY)) { u.u_error = EIO; return; } alp->nplchar = 0; alp->flags = OPEN; alp->mode |= ENABLE; oc(alp->addr,alp->mode | CLEAR); trace(01<<8, "vpopen", alp->mode); } /* * close printer */ vpclose(dev) { struct lp *alp; struct buf *abp; trace(01<<8, "vpclose", dev); alp = &vp[minor(dev) % 64]; abp = &alp->lpb; vprdy(abp); abp->b_flags |= B_BUSY; oc(alp->addr, ENABLE | RFF); vprdy(abp); alp->mode = DISARM; oc(alp->addr,alp->mode); alp->flags = 0; } vpwrite(dev) { register struct lp *alp; int vpstrategy(); alp = &vp[minor(dev) % 64]; alp->flags &= ~ODD; alp->flags |= u.u_count & ODD; /* Make count even to satisfy physio */ u.u_count &= ~ODD; trace(04<<8, "write", u.u_count); physio(vpstrategy, &alp->lpb, dev, B_WRITE); } vpstrategy(abp) register struct buf *abp; { struct lp *alp; trace(04<<8,"vpstrategy", abp->b_bcount); alp = &vp[minor(abp->b_dev) % 64]; abp->b_bcount |= alp->flags & ODD; /* In case count was odd */ if (abp->b_bcount > 0) vpstart(alp); } vpstart(alp) struct lp *alp; { register char *i,*ilast; register count; struct buf *abp; abp = &alp->lpb; trace(04<<8,"vpstart", abp->b_bcount); if ((count = abp->b_bcount) == 0) return; i = abp->b_un.b_addr; abp->b_flags |= B_BUSY; if (alp->mode&PLOT) { ilast = i + min(PLBUFSIZ - alp->nplchar, abp->b_bcount); count -= ilast - i; alp->nplchar += ilast - i; alp->nplchar %= PLBUFSIZ; #ifdef WB wb(alp->addr, i, ilast-1); i = ilast; #else while (i < ilast) wd(alp->addr,*i++); #endif } else { ilast = i + min(CBUFSIZ, count); while (i < ilast) { wd(alp->addr,*i++); count--; if (*(i-1) == '\n' || *(i-1) == '\f') break; } if (alp->mode & SPP) { alp->mode |= PLOT; oc(alp->addr,alp->mode|CLEAR); } } abp->b_un.b_addr += abp->b_bcount - count; abp->b_resid = abp->b_bcount = count; } vprdy(abp) register struct buf *abp; { iowait(abp); spl4(); while (abp->b_flags & B_BUSY) sleep(abp, VPPRI); spl0(); } /* * interrupt handling routine */ vpint(dev,stat) { register struct lp *alp; register struct buf *abp; trace(8<<8, "vpint", stat); alp = &vp[minor(dev) % 64]; abp = &alp->lpb; if (stat&NOPAP) { printf("Versatec: out of paper\n"); return; } if (stat&NOPWR) { printf("Versatec: not ready\n"); return; } if (stat&V_BUSY) return; abp->b_flags &= ~B_BUSY; if (abp->b_bcount > 0 && alp->flags) vpstart(alp); else iodone(abp); } vpioctl(dev, cmd, addr, flag) int cmd, flag; int *addr; { int v[1]; register i; struct lp *alp; struct buf *abp; alp = &vp[minor(dev) % 64]; cmd &= 07; /* Sort of a kluge */ if (cmd == 0) { /* gtty */ v[0] = 0; for (i=0; i<9; i++) if (alp->mode & (vpmodes[i])) v[0] |= 1<lpb; vprdy(abp); alp->nplchar = 0; alp->mode &= (ENABLE | DISARM); if (copyin(addr, v, 4)) { u.u_error = EFAULT; return(1); } for (i=0; i<9; i++) if (v[0] & 1<mode |= vpmodes[i]; abp->b_flags |= B_BUSY; oc(alp->addr, alp->mode | CLEAR); trace(1<<8, "vpioctl", alp->mode); alp->mode &= MODE; } return(0); }