Nsys/sys/nsys/dmr/rk.c
#
/*
* RK disk driver
*/
#include "/sys/nsys/param.h"
#include "/sys/nsys/buf.h"
#include "/sys/nsys/conf.h"
#include "/sys/nsys/user.h"
struct buf *rk_q[NRK];
int *rk_ap;
struct {
int rkds;
int rker;
int rkcs;
int rkwc;
int rkba;
int rkda;
};
#define RKADDR 0177400
#define NRKBLK 4872
#define JRK 1 /* temp */
#define RESET 0
#define GO 01
#define SEEK 010
#define DRESET 014
#define IENABLE 0100
#define DRY 0200
#define ARDY 0100
#define WLO 020000
#define CTLRDY 0200
#define SEEKCMP 020000
#define B_SEEK 02000
rkstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register *qc, *ql;
int d;
bp = abp;
if (bp->b_blkno >= NRKBLK
&& (bp->b_blkno >= NRKBLK*3 || bp->b_dev.d_major==JRK)) {
bp->b_flags =| B_ERROR;
iodone(bp);
return;
}
bp->av_forw = 0;
bp->b_flags =& ~B_SEEK;
if (bp->b_dev.d_major==JRK)
d = bp->b_dev.d_minor;
else
d = bp->b_blkno%3;
spl5();
if ((ql = *(qc = &rk_q[d])) == NULL) {
*qc = bp;
if (RKADDR->rkcs&CTLRDY)
rkstart();
goto ret;
}
while ((qc = ql->av_forw) != NULL) {
if (ql->b_blkno<bp->b_blkno
&& bp->b_blkno<qc->b_blkno
|| ql->b_blkno>bp->b_blkno
&& bp->b_blkno>qc->b_blkno) {
ql->av_forw = bp;
bp->av_forw = qc;
goto ret;
}
ql = qc;
}
ql->av_forw = bp;
ret:
spl0();
}
rkstart()
{
register struct buf *bp;
struct buf *sbp;
int *qp;
for (qp = rk_q; qp < &rk_q[NRK];) {
if ((bp = *qp++) && (bp->b_flags&B_SEEK)==0) {
sbp = bp;
RKADDR->rkda = rkaddr(bp);
bp = sbp;
rkcommand(IENABLE|SEEK|GO);
if (RKADDR->rkcs<0) { /* error bit */
bp->b_flags =| B_ERROR;
*--qp = bp->av_forw;
iodone(bp);
rkerror();
} else
bp->b_flags =| B_SEEK;
}
}
}
rkaddr(bp)
struct buf *bp;
{
register struct buf *p;
register int b;
int d;
p = bp;
b = p->b_blkno;
if (p->b_dev.d_major==JRK)
d = p->b_dev.d_minor;
else {
d = b%3;
b =/ 3;
}
return(d<<13 | (b/12)<<4 | b%12);
}
rkintr()
{
register struct buf *bp;
if (RKADDR->rkcs < 0) { /* error bit */
if (RKADDR->rker&WLO || ++devtab[JRK].d_errcnt>10)
rkpost(B_ERROR);
rkerror();
}
if (RKADDR->rkcs&SEEKCMP) {
rk_ap = &rk_q[(RKADDR->rkds>>13) & 07];
devstart(*rk_ap, &RKADDR->rkda, rkaddr(*rk_ap));
} else
rkpost(0);
}
rkpost(errbit)
{
register struct buf *bp;
if (rk_ap) {
bp = *rk_ap;
bp->b_flags =| B_DONE | errbit;
*rk_ap = bp->av_forw;
rk_ap = NULL;
iodone(bp);
devtab[JRK].d_errcnt = 0;
rkstart();
}
}
rkerror()
{
int *qp;
register struct buf *bp;
rkcommand(IENABLE|RESET|GO);
for (qp = rk_q; qp < &rk_q[NRK];)
if ((bp = *qp++) != NULL && bp->b_flags&B_SEEK) {
RKADDR->rkda = rkaddr(bp);
while ((RKADDR->rkds&(DRY|ARDY)) == DRY);
rkcommand(IENABLE|DRESET|GO);
}
}
rkcommand(com)
{
RKADDR->rkcs = com;
while((RKADDR->rkcs&CTLRDY)==0);
}