USG_PG3/usr/source/io2/rp.c
#
/*
* RP 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"
struct rpregs {
int rpds;
int rper;
int rpcs;
int rpwc;
int rpba;
int rpca;
int rpda;
};
#define RPADDR 0176710
#define NRP 2
struct {
char *nblocks;
int cyloff;
} rp_sizes[] {
40600L, 0, /* cyl 0 thru 202 */
40600L, 203, /* cyl 203 thru 405 */
9200, 0, /* cyl 0 thru 45 */
9200, 360, /* cyl 360 thru 405 */
65535L, 0, /* cyl 0 thru 327 */
65535L, 78, /* cyl 78 thru 405 */
15600, 0, /* cyl 0 thru 77 */
15600, 328, /* cyl 328 thru 405 */
};
struct devtab rptab;
struct buf rrpbuf;
struct iostat rpstat[NRP];
struct errtab rpetab { etabinit(E_BLK,NRP,RP,rpstat) };
#define GO 01
#define RESET 0
#define HSEEK 014
#define IENABLE 0100
#define READY 0200
#define SUFU 01000
#define SUSU 02000
#define SUSI 04000
#define HNF 010000
/*
* Use av_back to save track+sector,
* b_resid for cylinder.
*/
#define trksec av_back
#define cylin b_resid
/*
* Monitoring device number
*/
#define DK_N 2
rpopen(dev, flag)
{
if (dev.d_minor >= (NRP<<3))
u.u_error = ENXIO;
}
rpstrategy(abp)
struct buf *abp;
{
register struct buf *bp;
register char *p1, *p2;
bp = abp;
if(bp->b_flags&B_PHYS)
mapalloc(bp);
p1 = &rp_sizes[bp->b_dev.d_minor&07];
if(bp->b_blkno >= p1->nblocks) {
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;
bp->cylin = p1->cyloff;
p1 = bp->b_blkno;
p2 = lrem(p1, 10);
p1 = ldiv(p1, 10);
bp->trksec = (p1%20)<<8 | p2;
bp->cylin =+ p1/20;
spl5();
if ((p1 = rptab.d_actf)==0)
rptab.d_actf = bp;
else {
for (; p2 = p1->av_forw; p1 = p2) {
if (p1->cylin <= bp->cylin
&& bp->cylin < p2->cylin
|| p1->cylin >= bp->cylin
&& bp->cylin > p2->cylin)
break;
}
bp->av_forw = p2;
p1->av_forw = bp;
}
if (rptab.d_active==0)
rpstart();
spl0();
}
rpstart()
{
register struct buf *bp;
register int n;
if ((bp = rptab.d_actf) == 0)
return;
rptab.d_active++;
n = bp->b_dev.d_minor>>3;
rpetab.e_aunit = &rpstat[n];
rpetab.e_aunit->io_ops++;
blkacty =| (1<<RP);
RPADDR->rpda = bp->trksec;
devstart(bp, &RPADDR->rpca, bp->cylin, n);
dk_busy =| 1<<DK_N;
dk_numb[DK_N] =+ 1;
dk_wds[DK_N] =+ (-bp->b_wcount>>5) & 03777;
}
rpintr()
{
register struct buf *bp;
register int ctr;
struct rpregs rpregs[0];
if (rptab.d_active == 0)
return;
blkacty =& ~(1<<RP);
dk_busy =& ~(1<<DK_N);
bp = rptab.d_actf;
rptab.d_active = 0;
if (RPADDR->rpcs < 0) { /* error bit */
/* deverror(bp, RPADDR->rper, RPADDR->rpds); /**/
fmtblk(&rpetab,RPADDR,sizeof(rpregs[0])/2,bp);
if(RPADDR->rpds & (SUFU|SUSI|HNF)) {
RPADDR->rpcs.lobyte = HSEEK|GO;
rpetab.e_aunit->io_misc++;
ctr = 0;
while ((RPADDR->rpds&SUSU) && --ctr);
}
RPADDR->rpcs = RESET|GO;
rpetab.e_aunit->io_misc++;
ctr = 0;
while ((RPADDR->rpcs&READY) == 0 && --ctr);
if (rptab.d_errcnt < 10) {
if(rptab.d_errcnt++ == 0)
logerr(&rpetab,E_FIRST);
rpstart();
return;
}
bp->b_flags =| B_ERROR;
}
if(rpetab.e_emsg != NULL)
logerr(&rpetab,E_RETRY);
rptab.d_errcnt = 0;
rptab.d_actf = bp->av_forw;
bp->b_resid = RPADDR->rpwc;
iodone(bp);
rpstart();
}
rpread(dev)
{
register nblks;
nblks = rp_sizes[dev.d_minor & 07].nblocks;
physio(rpstrategy, &rrpbuf, dev, B_READ, nblks);
}
rpwrite(dev)
{
register nblks;
nblks = rp_sizes[dev.d_minor & 07].nblocks;
physio(rpstrategy, &rrpbuf, dev, B_WRITE, nblks);
}