USG_PG3/usr/source/io2/rk.c
#
/*
* RK disk driver
*/
#include "../head/param.h"
#include "../head/systm.h"
#include "../head/buf.h"
#include "../head/bufx.h"
#include "../head/conf.h"
#include "../head/user.h"
#include "../head/userx.h"
#include "../head/elog.h"
#define NRK 4
#define NRKBLK 4872
#define RKADDR 0177400
#define RESET 0
#define GO 01
#define DRESET 014
#define IENABLE 0100
#define DRY 0200
#define ARDY 0100
#define WLO 020000
#define CTLRDY 0200
/*
* Monitoring device bit
*/
#define DK_N 1
struct rkregs {
int rkds;
int rker;
int rkcs;
int rkwc;
int rkba;
int rkda;
};
struct devtab rktab;
struct buf rrkbuf;
struct iostat rkstat[NRK];
struct errtab rketab { etabinit(E_BLK,NRK,RK,rkstat) };
rkopen(dev, flag)
{
if((dev.d_minor&07) >= NRK) /* even in interleaved, max */
u.u_error = ENXIO; /* unit num must be < NRK */
}
rkstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register int d;
bp = abp;
if(bp->b_flags&B_PHYS)
mapalloc(bp);
d = bp->b_dev.d_minor-7;
if(d <= 0)
d = 1;
if (bp->b_blkno >= NRKBLK*d) {
if (bp->b_flags&B_READ)
bp->b_resid = bp->b_wcount;
else {
bp->b_flags =| B_ERROR;
bp->b_error = ENXIO;
}
iodone(bp);
return;
}
bp->av_forw = 0;
spl5();
if (rktab.d_actf==0)
rktab.d_actf = bp;
else
rktab.d_actl->av_forw = bp;
rktab.d_actl = bp;
if (rktab.d_active==0)
rkstart();
spl0();
}
rkaddr(bp)
struct buf *bp;
{
register int b, d, m;
b = bp->b_blkno;
m = bp->b_dev.d_minor - 7;
if(m <= 0)
d = bp->b_dev.d_minor;
else {
d = lrem(b, m);
b = ldiv(b, m);
}
rketab.e_aunit = &rkstat[d];
return(d<<13 | (b/12)<<4 | b%12);
}
rkstart()
{
register struct buf *bp;
register a;
if ((bp = rktab.d_actf) == 0)
return;
rktab.d_active++;
a = rkaddr(bp); /* also sets e_aunit */
rketab.e_aunit->io_ops++;
blkacty =| (1<<RK);
devstart(bp, &RKADDR->rkda, a, 0);
dk_busy =| 1<<DK_N;
dk_numb[DK_N] =+ 1;
dk_wds[DK_N] =+ (-bp->b_wcount>>5) & 03777;
}
rkintr()
{
register struct buf *bp;
struct rkregs rkregs[0];
if (rktab.d_active == 0)
return;
blkacty =& ~(1<<RK);
dk_busy =& ~(1<<DK_N);
bp = rktab.d_actf;
rktab.d_active = 0;
if (RKADDR->rkcs < 0) { /* error bit */
/* deverror(bp, RKADDR->rker, RKADDR->rkds); /**/
fmtblk(&rketab,RKADDR,sizeof(rkregs[0])/2,bp);
RKADDR->rkcs = RESET|GO;
rketab.e_aunit->io_misc++;
while((RKADDR->rkcs&CTLRDY) == 0) ;
if (rktab.d_errcnt < 10) {
if(rktab.d_errcnt++ == 0)
logerr(&rketab,E_FIRST);
rkstart();
return;
}
bp->b_flags =| B_ERROR;
}
if(rketab.e_emsg != NULL)
logerr(&rketab,E_RETRY);
rktab.d_errcnt = 0;
rktab.d_actf = bp->av_forw;
bp->b_resid = RKADDR->rkwc;
iodone(bp);
rkstart();
}
rkread(dev)
{
register nblks;
nblks = dev.d_minor - 7;
if (nblks <= 0)
nblks = 1;
physio(rkstrategy, &rrkbuf, dev, B_READ, NRKBLK*nblks);
}
rkwrite(dev)
{
register nblks;
nblks = dev.d_minor - 7;
if (nblks <= 0)
nblks = 1;
physio(rkstrategy, &rrkbuf, dev, B_WRITE, NRKBLK*nblks);
}