MiniUnix/usr/sys/dev/ht.c
#
/*
*/
/*
* TJU16 tape driver
*/
#include "../param.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
struct {
int htcs1;
int htwc;
int htba;
int htfc;
int htcs2;
int htds;
int hter;
int htas;
int htck;
int htdb;
int htmr;
int htdt;
int htsn;
int httc;
int htbae; /* 11/70 bus extension */
};
struct devtab httab;
#define NUNIT 8
char h_openf[NUNIT];
char *h_blkno[NUNIT];
char *h_nxrec[NUNIT];
#define HTADDR 0172440
#define GO 01
#define NOP 0
#define WEOF 026
#define SFORW 030
#define SREV 032
#define ERASE 024
#define REW 06
#define CLR 010
#define P800 01300 /* 800 + pdp11 mode */
#define P1600 02300 /* 1600 + pdp11 mode */
#define IENABLE 0100
#define CRDY 0200
#define EOF 04
#define DRY 0200
#define MOL 010000
#define PIP 020000
#define ERR 040000
#define SSEEK 1
#define SIO 2
htopen(dev, flag)
{
register unit;
unit = dev.d_minor&077;
if (unit >= NUNIT || h_openf[unit])
u.u_error = ENXIO;
else {
h_openf[unit]++;
h_blkno[unit] = 0;
h_nxrec[unit] = 65535;
hcommand(dev, NOP);
}
}
htclose(dev, flag)
{
register int unit;
unit = dev.d_minor&077;
h_openf[unit] = 0;
if (flag) {
hcommand(dev, WEOF);
hcommand(dev, WEOF);
}
hcommand(dev, REW);
}
hcommand(dev, com)
{
register unit;
extern lbolt;
unit = dev.d_minor;
while (httab.d_active || (HTADDR->htcs1 & CRDY)==0)
sleep(&lbolt, 1);
HTADDR->htcs2 = (unit>>3)&07;
while((HTADDR->htds&DRY) == 0)
sleep(&lbolt, 1);
if(unit >= 64)
HTADDR->httc = P800 | (unit&07); else
HTADDR->httc = P1600 | (unit&07);
while((HTADDR->htds&(MOL|PIP)) != MOL)
sleep(&lbolt, 1);
HTADDR->htcs1 = com | GO;
}
htstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register char **p;
bp = abp;
p = &h_nxrec[bp->b_dev.d_minor&077];
if (*p <= bp->b_blkno) {
if (*p < bp->b_blkno) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
if (bp->b_flags&B_READ) {
clrbuf(bp);
iodone(bp);
return;
}
}
if ((bp->b_flags&B_READ)==0)
*p = bp->b_blkno + 1;
bp->av_forw = 0;
spl5();
if (httab.d_actf==0)
httab.d_actf = bp;
else
httab.d_actl->av_forw = bp;
httab.d_actl = bp;
if (httab.d_active==0)
htstart();
spl0();
}
htstart()
{
register struct buf *bp;
register int unit;
register char *blkno;
loop:
if ((bp = httab.d_actf) == 0)
return;
unit = bp->b_dev.d_minor;
HTADDR->htcs2 = (unit>>3)&07;
if(unit >= 64)
HTADDR->httc = P800 | (unit&07); else
HTADDR->httc = P1600 | (unit&07);
unit =& 077;
blkno = h_blkno[unit];
if (h_openf[unit] < 0 || (HTADDR->htcs1 & CRDY)==0) {
bp->b_flags =| B_ERROR;
httab.d_actf = bp->av_forw;
iodone(bp);
goto loop;
}
if (blkno != bp->b_blkno) {
httab.d_active = SSEEK;
if (blkno < bp->b_blkno) {
HTADDR->htfc = blkno - bp->b_blkno;
HTADDR->htcs1 = SFORW|IENABLE|GO;
} else {
if (bp->b_blkno == 0)
HTADDR->htcs1 = REW|IENABLE|GO;
else {
HTADDR->htfc = bp->b_blkno - blkno;
HTADDR->htcs1 = SREV|IENABLE|GO;
}
}
return;
}
httab.d_active = SIO;
rhstart(bp, &HTADDR->htfc, bp->b_wcount<<1, &HTADDR->htbae);
}
htintr()
{
register struct buf *bp;
register int unit;
if ((bp = httab.d_actf)==0)
return;
unit = bp->b_dev.d_minor&077;
if (HTADDR->htcs1 & ERR) {
if(HTADDR->htds&EOF) {
if(h_openf[unit])
h_openf[unit] = -1;
}
HTADDR->htcs1 = ERR|CLR|GO;
if ((HTADDR->htds&DRY)!=0 && httab.d_active==SIO) {
if (++httab.d_errcnt < 10) {
h_blkno[unit]++;
httab.d_active = 0;
htstart();
return;
}
}
bp->b_flags =| B_ERROR;
httab.d_active = SIO;
}
if (httab.d_active == SIO) {
httab.d_errcnt = 0;
h_blkno[unit]++;
httab.d_actf = bp->av_forw;
httab.d_active = 0;
iodone(bp);
bp->b_resid = HTADDR->htfc;
} else
h_blkno[unit] = bp->b_blkno;
htstart();
}