#
/*
 * RK disk driver
 *	UKC System changes which apply to this file:
 *	see changes.h
 *
 *	_1170
 *	ERRLOG
 *	RAW_BUFFER_POOL
 *	RKINTER - define if interleaved RK's are required
 */

#include "../param.h"
#include "../systm.h"
#include "../buf.h"
#include "../conf.h"
#include "../user.h"
#ifdef ERRLOG
#include "../discerr.h"
#endif

#define	RKADDR	0177400
#define	NRK	2
#define	NRKBLK	4872

#define	RESET	0
#define	GO	01
#define	DRESET	014
#define	IENABLE	0100
#define	DRY	0200
#define	ARDY	0100
#define	WLO	020000
#define	CTLRDY	0200

#define sectrk av_back

struct {
	int rkds;
	int rker;
	int rkcs;
	int rkwc;
	int rkba;
	int rkda;
};


struct	devtab	rktab;
#ifndef RAW_BUFFER_POOL
struct	buf	rrkbuf;
#endif

struct buf *rkaddr();

/*
 *	Ordering routine for rks
 *	sort on sector/track number
 */

rkcmp(a1, a2)
struct buf *a1, *a2;
{	register struct buf *b1, *b2;
	b1 = a1;
	b2 = a2;
	if(b1->sectrk < b2->sectrk) return(-1);
	return(b1->sectrk > b2->sectrk);
}


rkstrategy(abp)
struct buf *abp;
{
	register struct buf *bp;
#ifdef RKINTER
	int d;
#endif

	bp = abp;
#ifdef _1170
	if(bp->b_flags&B_PHYS)
		mapalloc(bp);
#endif
#ifdef RKINTER
	d = bp->b_dev.d_minor-7;
	if(d <= 0)
		d = 1;
	if (bp->b_blkno >= NRKBLK*d) {
#endif
#ifndef RKINTER
	if (bp->b_blkno >= NRKBLK) {
#endif
		bp->b_flags =| B_ERROR;
		iodone(bp);
		return;
	}
	bp->sectrk = rkaddr(bp);
	spl5();
	bporder(bp, &rktab, rkcmp);
	if (rktab.d_active==0)
		rkstart();
	spl0();
}

struct buf *rkaddr(bp)
struct buf *bp;
{
	register struct buf *p;
	register int b, d;
#ifdef RKINTER
	int m;
#endif

	p = bp;
	b = p->b_blkno;
#ifndef RKINTER
	d = p->b_dev.d_minor;
#endif
#ifdef RKINTER
	m = p->b_dev.d_minor - 7;
	if(m <= 0)
		d = p->b_dev.d_minor;
	else {
		d = lrem(b, m);
		b = ldiv(b, m);
	}
#endif
	return(d<<13 | (b/12)<<4 | b%12);
}

rkstart()
{
	register struct buf *bp;

	if ((bp = rktab.d_actf) == 0)
		return;
	rktab.d_active++;
	bp->b_error = 0;
	devstart(bp, &RKADDR->rkda, bp->sectrk, 0);
}

rkintr()
{
	register struct buf *bp;
#ifdef ERRLOG
	register struct disc_err *de;
#endif

	if (rktab.d_active == 0)
		return;
	bp = rktab.d_actf;
	rktab.d_active = 0;
	if (RKADDR->rkcs < 0) {		/* error bit */
		deverror(bp, RKADDR->rker, RKADDR->rkds);
#ifdef ERRLOG
		if(rktab.d_errcnt == 0)
		{	de = superblk;
			de->rk_time = time;
			de->rk_retry[((RKADDR->rkda>>13)&07)]++;
			bcopy(&RKADDR->rkds, de->rk_stat, 7);
			de->ds_mod++;
		}
#endif
		RKADDR->rkcs = RESET|GO;
		while((RKADDR->rkcs&CTLRDY) == 0) ;
		if (++rktab.d_errcnt <= 10) {
			rkstart();
			return;
		}
		bp->b_flags =| B_ERROR;
	}
	rktab.d_errcnt = 0;
	rktab.d_actf = bp->av_forw;
	rkstart();
	iodone(bp);
}

rkread(dev)
{

#ifndef RAW_BUFFER_POOL
	physio(rkstrategy, &rrkbuf, dev, B_READ);
#endif
#ifdef RAW_BUFFER_POOL
	physio(rkstrategy, 0, dev, B_READ);
#endif
}

rkwrite(dev)
{

#ifndef RAW_BUFFER_POOL
	physio(rkstrategy, &rrkbuf, dev, B_WRITE);
#endif
#ifdef RAW_BUFFER_POOL
	physio(rkstrategy, 0, dev, B_WRITE);
#endif
}
