Nsys/sys/nsys/dmr/pc.c
#
/*
* PC-11 Paper tape reader/punch driver
*/
#include "/sys/nsys/param.h"
#include "/sys/nsys/conf.h"
#include "/sys/nsys/user.h"
#define PCADDR 0177550
#define CLOSED 0
#define WAITING 1
#define READING 2
#define EOF 3
#define RDRENB 01
#define IENABLE 0100
#define DONE 0200
#define BUSY 04000
#define ERROR 0100000
#define PCIPRI 30
#define PCOPRI 40
#define PCOLWAT 50
#define PCOHWAT 100
#define PCIHWAT 250
struct {
int pcrcsr;
int pcrbuf;
int pcpcsr;
int pcpbuf;
};
struct clist {
int cc;
int cf;
int cl;
};
struct pc11 {
int pcstate;
struct clist pcin;
struct clist pcout;
} pc11;
pcopen(dev, flag)
{
extern lbolt;
if (flag==0) {
if (pc11.pcstate!=CLOSED) {
u.u_error = ENXIO;
return;
}
pc11.pcstate = WAITING;
while(pc11.pcstate==WAITING) {
PCADDR->pcrcsr = IENABLE|RDRENB;
sleep(&lbolt, PCIPRI);
}
} else {
PCADDR->pcpcsr =| IENABLE;
pcleader();
}
}
pcclose(dev, flag)
{
int i;
if (flag==0) {
spl4();
while (getc(&pc11.pcin) >= 0);
PCADDR->pcrcsr = 0;
pc11.pcstate = CLOSED;
spl0();
} else
pcleader();
}
pcread()
{
register int c;
spl4();
do {
while ((c = getc(&pc11.pcin)) < 0) {
if (pc11.pcstate==EOF)
goto out;
if ((PCADDR->pcrcsr&(ERROR|BUSY|DONE))==0)
PCADDR->pcrcsr =| IENABLE|RDRENB;
sleep(&pc11.pcin, PCIPRI);
}
} while (passc(c)>=0);
out:
spl0();
}
pcwrite()
{
int c;
while (cpass(&c)>=0)
pcoutput(c);
}
pcstart()
{
register int c;
if (PCADDR->pcpcsr&DONE && (c = getc(&pc11.pcout)) >= 0)
PCADDR->pcpbuf = c;
}
pcrint()
{
if (pc11.pcstate==WAITING) {
if (PCADDR->pcrcsr&ERROR)
return;
pc11.pcstate = READING;
}
if (pc11.pcstate==READING) {
if (PCADDR->pcrcsr&ERROR)
pc11.pcstate = EOF;
else {
putc(PCADDR->pcrbuf, &pc11.pcin);
if (pc11.pcin.cc < PCIHWAT)
PCADDR->pcrcsr =| IENABLE|RDRENB;
}
wakeup(&pc11.pcin);
}
}
pcpint()
{
register int c;
if ((c=getc(&pc11.pcout)) >= 0)
PCADDR->pcpbuf = c;
if (pc11.pcout.cc <= PCOLWAT)
wakeup(&pc11.pcout);
}
pcoutput(c)
{
if (PCADDR->pcpcsr&ERROR) {
u.u_error = EIO;
return;
}
if (pc11.pcout.cc >= PCOHWAT)
sleep(&pc11.pcout, PCOPRI);
putc(c, &pc11.pcout);
pcstart();
}
pcleader()
{
int i;
for (i=0; i<100; i++)
pcoutput(0);
}