Unix V6 /usr/sys/dmr/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;
struct	buf	rhtbuf;
 
#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) {
/*
		deverror(bp, HTADDR->hter, 0);
 */
		if(HTADDR->htds&EOF) {
			if(bp != &rhtbuf && 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();
}
 
htread(dev)
{
	htphys(dev);
	physio(htstrategy, &rhtbuf, dev, B_READ);
	u.u_count = -rhtbuf.b_resid;
}
 
htwrite(dev)
{
	htphys(dev);
	physio(htstrategy, &rhtbuf, dev, B_WRITE);
	u.u_count = 0;
}
 
htphys(dev)
{
	register unit, a;
 
	unit = dev.d_minor;
	a = lshift(u.u_offset, -9);
	h_blkno[unit] = a;
	h_nxrec[unit] = ++a;
}
 
unix-history/unix-v6/usr/sys/dmr/ht.c.txt · Последние изменения: 2006/07/26 07:34
 
Copyright (C) 1996-2013 Serge Vakulenko
serge@vak.ru