SRI-NOSC/dmr/rx.c

Compare this file to the similar file:
Show the results in this format:

#
/*
 * RX floppy disk driver
 * Ron Broersma -- Naval Ocean Systems Center, San Diego, California
 */

#include "param.h"
#include "buf.h"
#include "conf.h"
#include "user.h"
#include "seg.h"

#ifndef RXADDR
#define	RXADDR	0177170
#endif not RXADDR
#define NRX	2
#define	NRXBLK	500

#define GO	1
#define FILL	0
#define EMPTY	2
#define WRITE	4
#define READ	6
#define RDSTAT	012
#define RDERR	016
#define IENABLE	0100
#define	TR	0200
#define DRVRDY	0200
#define DONE	040
#define INIT	040000
#define INITDONE 4

#define WAIT while(!(RXADDR->rxcs&(TR | DONE)))

struct {
    int rxcs;
    int rxdb;
};

struct devtab rxtab;
struct buf rrxbuf;
struct rxadr {
    char sector;
    char track;
};

rxstrategy(abp)
struct buf *abp;
{
	register struct buf *bp;

	bp = abp;
	if (bp->b_blkno >= NRXBLK) {
		if (bp->b_blkno==NRXBLK)
			bp->b_wcount = max(bp->b_wcount, -128);
					/* so we don't get errors when */
					/* trying to read the last 2 sectors */
		else {
			bp->b_flags =| B_ERROR;
			iodone(bp);
			return;
		}
	}
	bp->b_resid = -bp->b_wcount; /* used to tell how far to go */
	bp->b_wcount = 0; /* used to tell how far we are (in bytes!) */
	bp->av_forw = 0;
	spl5();
	if (!(rxtab.d_actf))
		rxtab.d_actf = bp;
	else
		rxtab.d_actl->av_forw = bp;
	rxtab.d_actl = bp;
	if (!(rxtab.d_active)) rxstart();
	spl0();
}

rxaddr(abp)
struct buf *abp;
{
	register int sect, track;
	register struct buf *bp;
	int t1, t2, dtyp;

	bp = abp;
	dtyp = (bp->b_dev.d_minor&6) >> 1;
	sect = (bp->b_blkno<<2) + (bp->b_wcount>>7);
	if (!dtyp)
		sect = sect==36?NRXBLK*4:sect==NRXBLK*4?36:sect;
	t1 = sect/26;
	if ((!dtyp) || dtyp == 2) {
		t2 = sect%26;
		track = t1 + (dtyp?1:0);
		sect = 6*t1 + t2*2 + (t2>=13?1:0);
	}
	else track = t1;
	return((track << 8) + sect%26 + 1);
}

rxto(word)
{
	WAIT;
	RXADDR->rxdb.lobyte = word.lobyte;
	WAIT;
	RXADDR->rxdb.lobyte = word.hibyte;
}

rxfrom()
{
	int word;

	WAIT;
	word.lobyte = RXADDR->rxdb.lobyte;
	WAIT;
	word.hibyte = RXADDR->rxdb.lobyte;
	return(word);
}

char sbuf[128];

rxdata(bp, command, wcount)
struct buf *bp;
{
	register char *cp;
	register int nbytes;
	register int bn;
	int tn[2];
#ifndef UCBUFMOD
	int sa, sps;
#endif not UCBUFMOD

	cp = bp;	/* for speed and size */
	tn[0] = cp->b_xmem;  tn[1] = cp->b_addr;
	dpadd(tn, cp->b_wcount);
	bn = lshift(tn, -6);
	tn[1] =& 077;
	RXADDR->rxcs = command | GO;
	nbytes = wcount<<1;
	if (command == FILL) {
#ifndef UCBUFMOD
		cp = ka6-6;  sa = cp->integ;
		sps = PS->integ;  PS->integ = 030340;
		cp->integ = bn;
		copyin(tn[1], sbuf, nbytes);
		cp->integ = sa;  PS->integ = sps;
#endif not UCBUFMOD
#ifdef UCBUFMOD
		btk(bn, tn[1], sbuf, wcount);
#endif UCBUFMOD
		cp = sbuf;
		do {
			WAIT;
			RXADDR->rxdb.lobyte = *cp++;
		} while --nbytes;
		while(!(RXADDR->rxcs&DONE)) rxto(0);
	}
	else {
		cp = sbuf;
		do {
			WAIT;
			*cp++ = RXADDR->rxdb.lobyte;
		} while --nbytes;
#ifndef UCBUFMOD
		cp = ka6-6;  sa = cp->integ;
		sps = PS->integ;  PS->integ = 030340;
		cp->integ = bn;
		copyout(sbuf, tn[1], wcount<<1);
		cp->integ = sa;  PS->integ = sps;
#endif not UCBUFMOD
#ifdef UCBUFMOD
		ktb(bn, tn[1], sbuf, wcount);
#endif UCBUFMOD
		while(!(RXADDR->rxcs&DONE)) rxfrom();
	}
}

rxstart()
{
	register struct buf *bp;
	register cmd;

	if (!(bp = rxtab.d_actf))
		return;
	cmd = WRITE | GO | IENABLE | ((bp->b_dev.d_minor&1)<<4);
	if (bp->b_flags&B_READ) 
		cmd =| READ;
		else rxdata(bp, FILL, min(bp->b_resid, 64));
	rxtab.d_active++;
	RXADDR->rxcs = cmd;
	rxto(rxaddr(bp));
}

rxintr()
{
	register struct buf *bp;
	int ersave;

	if (!(rxtab.d_active))
		return;
	rxtab.d_active = 0;
	bp = rxtab.d_actf;
	if (RXADDR->rxcs < 0) {
		RXADDR->rxcs = RDSTAT | GO | ((bp->b_dev.d_minor&1)<<4);
		while (!(RXADDR->rxcs&DONE)); 
		if ((ersave = RXADDR->rxdb) & DRVRDY) {
			RXADDR->rxcs = RDERR;
			while(!(RXADDR->rxcs&DONE));
			deverror(bp, ersave, RXADDR->rxdb);
			RXADDR->rxcs = INIT;
			while (!(RXADDR->rxdb&INITDONE));
			if (++rxtab.d_errcnt <= 10) {
				rxstart();
				return;
			}
		}
		bp->b_flags =| B_ERROR;
	}
	if (bp->b_flags&B_READ) 
		rxdata (bp, EMPTY, min(bp->b_resid, 64));
	bp->b_resid =- min(bp->b_resid, 64);
	bp->b_wcount =+ 128;
	if (bp->b_resid && !(bp->b_flags&B_ERROR)) {
		rxstart();
		return;
	}
	rxtab.d_errcnt = 0;
	rxtab.d_actf = bp->av_forw;
	iodone(bp);
	rxstart();
}

rxread(dev)
{
	physio(rxstrategy, &rrxbuf, dev, B_READ);
}

rxwrite(dev)
{
	physio(rxstrategy, &rrxbuf, dev, B_WRITE);
}