# /* * RP disk driver */ #include "../h/param.h" #include "../h/systm.h" #include "../h/buf.h" #include "../h/dir.h" #include "../h/conf.h" #include "../h/user.h" struct device { int rpds; int rper; union { int w; char c; } rpcs; int rpwc; char *rpba; int rpca; int rpda; }; #define RPADDR ((struct device *) 0176710) #define NRP 8 struct { daddr_t nblocks; int cyloff; } rp_sizes[] = { 81000, 0, /* cyl 0 thru 405 */ 5000, 0, /* cyl 0 thru 24 */ 2000, 25, /* cyl 25 thru 34 */ 74000, 35, /* cyl 35 thru 405 */ 0, 0, 0, 0, 0, 0, 0, 0, }; struct buf rptab; struct buf rrpbuf; #define GO 01 #define RESET 0 #define HSEEK 014 #define IENABLE 0100 #define READY 0200 #define RCOM 4 #define WCOM 2 #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 rpstrategy(bp) register struct buf *bp; { register struct buf *dp; register int unit; long sz; unit = minor(bp->b_dev); sz = bp->b_bcount; sz = (sz+511)>>9; if (unit >= (NRP<<3) || bp->b_blkno+sz >= rp_sizes[unit&07].nblocks) { bp->b_flags |= B_ERROR; iodone(bp); return; } bp->av_forw = NULL; unit >>= 3; spl5(); dp = & rptab; if (dp->b_actf == NULL) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; if (dp->b_active == NULL) rpstart(); spl0(); } rpstart() { register struct buf *bp; register int unit; int com,cn,tn,sn,dn; daddr_t bn; if ((bp = rptab.b_actf) == NULL) return; rptab.b_active++; unit = minor(bp->b_dev); dn = unit>>3; bn = bp->b_blkno; cn = bn/(20*10) + rp_sizes[unit&07].cyloff; sn = bn%(20*10); tn = sn/10; sn = sn%10; RPADDR->rpcs.w = (dn<<8); RPADDR->rpda = (tn<<8) | sn; RPADDR->rpca = cn; RPADDR->rpba = bp->b_un.b_addr; RPADDR->rpwc = -(bp->b_bcount>>1); com = ((bp->b_xmem&3)<<4) | IENABLE | GO; if (bp->b_flags & B_READ) com |= RCOM; else com |= WCOM; RPADDR->rpcs.w |= com; dk_busy |= 1<b_bcount>>6; dk_wds[DK_N] += unit; } rpintr() { register struct buf *bp; register int ctr; if (rptab.b_active == NULL) return; dk_busy &= ~(1<rpcs.w < 0) { /* error bit */ deverror(bp, RPADDR->rper, RPADDR->rpds); if(RPADDR->rpds & (SUFU|SUSI|HNF)) { RPADDR->rpcs.c = HSEEK|GO; ctr = 0; while ((RPADDR->rpds&SUSU) && --ctr) ; } RPADDR->rpcs.w = RESET|GO; ctr = 0; while ((RPADDR->rpcs.w&READY) == 0 && --ctr) ; if (++rptab.b_errcnt <= 10) { rpstart(); return; } bp->b_flags |= B_ERROR; } rptab.b_errcnt = 0; rptab.b_actf = bp->av_forw; bp->b_resid = 0; iodone(bp); rpstart(); } rpread(dev) { physio(rpstrategy, &rrpbuf, dev, B_READ); } rpwrite(dev) { physio(rpstrategy, &rrpbuf, dev, B_WRITE); }