Nsys/sys/nsys/dmr/tc.c
#
/*
* TC-11 DECtape driver
*/
#include "/sys/nsys/param.h"
#include "/sys/nsys/conf.h"
#include "/sys/nsys/buf.h"
#include "/sys/nsys/user.h"
struct {
char lbyte;
char hbyte;
};
struct {
int tccsr;
int tccm;
int tcwc;
int tcba;
int tcdt;
};
#define TCADDR 0177340
#define NTCBLK 578
#define JTC 2
#define TAPERR 0100000
#define TREV 04000
#define READY 0200
#define IENABLE 0100
#define UPS 0200
#define SAT 0
#define RNUM 02
#define RDATA 04
#define SST 010
#define WDATA 014
#define GO 01
#define SFORW 1
#define SREV 2
#define SIO 3
tcclose(dev)
{
bflush(dev);
}
tcstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
bp = abp;
bp->av_forw = 0;
spl6();
if (devtab[JTC].d_actf==0)
devtab[JTC].d_actf = bp;
else
devtab[JTC].d_actl->av_forw = bp;
devtab[JTC].d_actl = bp;
if (devtab[JTC].d_active==0)
tcstart();
spl0();
}
tcstart()
{
register struct buf *bp;
register int *tccmp, com;
if ((bp = devtab[JTC].d_actf) == 0)
return;
tccmp = &TCADDR->tccm;
if (((*tccmp).hbyte&07) != bp->b_dev.d_minor)
(*tccmp).lbyte = SAT|GO;
devtab[JTC].d_errcnt = 20;
devtab[JTC].d_active = SFORW;
com = (bp->b_dev.d_minor<<8) | IENABLE|RNUM|GO;
if ((TCADDR->tccsr & UPS) == 0) {
com =| TREV;
devtab[JTC].d_active = SREV;
}
*tccmp = com;
}
tcintr()
{
register struct buf *bp;
struct buf *sbp;
register int *tccmp;
register int *tcdtp;
tccmp = &TCADDR->tccm;
bp = devtab[JTC].d_actf;
if (*tccmp&TAPERR) {
*tccmp =& ~TAPERR;
if (--devtab[JTC].d_errcnt <= 0) {
bp->b_flags =| B_ERROR;
goto done;
}
if (*tccmp&TREV) {
setforw:
devtab[JTC].d_active = SFORW;
*tccmp =& ~TREV;
} else {
setback:
devtab[JTC].d_active = SREV;
*tccmp =| TREV;
}
(*tccmp).lbyte = IENABLE|RNUM|GO;
return;
}
tcdtp = &TCADDR->tcdt;
switch (devtab[JTC].d_active) {
case SIO:
done:
devtab[JTC].d_active = 0;
sbp = bp;
if (devtab[JTC].d_actf = bp->av_forw)
tcstart();
else
TCADDR->tccm.lbyte = SAT|GO;
iodone(sbp);
return;
case SFORW:
if (*tcdtp > bp->b_blkno)
goto setback;
if (*tcdtp < bp->b_blkno)
goto setforw;
*--tcdtp = bp->b_addr; /* core address */
*--tcdtp = bp->b_wcount;
tccmp->lbyte = (bp->b_flags&B_XMEM) | IENABLE|GO
| (bp->b_flags&B_READ?RDATA:WDATA);
devtab[JTC].d_active = SIO;
return;
case SREV:
if (*tcdtp+3 > bp->b_blkno)
goto setback;
goto setforw;
}
}