V7/usr/sys/dev/vp.c
/*
* 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;
}