# /* */ /* * RP04 disk driver * * This driver has been tested on a working RP04 for a few hours. * It does not attempt ECC error correction and is probably * deficient in general in the case of errors and when packs * are dismounted. */ #include "../param.h" #include "../buf.h" #include "../conf.h" #include "../user.h" struct { int hpcs1; /* Control and Status register 1 */ int hpwc; /* Word count register */ int hpba; /* UNIBUS address register */ int hpda; /* Desired address register */ int hpcs2; /* Control and Status register 2*/ int hpds; /* Drive Status */ int hper1; /* Error register 1 */ int hpas; /* Attention Summary */ int hpla; /* Look ahead */ int hpdb; /* Data buffer */ int hpmr; /* Maintenance register */ int hpdt; /* Drive type */ int hpsn; /* Serial number */ int hpof; /* Offset register */ int hpca; /* Desired Cylinder address register*/ int hpcc; /* Current Cylinder */ int hper2; /* Error register 2 */ int hper3; /* Error register 3 */ int hppos; /* Burst error bit position */ int hppat; /* Burst error bit pattern */ int hpbae; /* 11/70 bus extension */ }; #define HPADDR 0176700 #define NHP 8 struct { char *nblocks; int cyloff; } hp_sizes[] { 9614, 0, /* cyl 0 thru 23 */ /* cyl 24 thru 43 available */ -1, 44, /* cyl 44 thru 200 */ -1, 201, /* cyl 201 thru 357 */ 20900, 358, /* cyl 358 thru 407 */ /* cyl 408 thru 410 blank */ 40600, 0, 40600, 100, 40600, 200, 40600, 300, }; struct devtab hptab; struct buf hpbuf; char hp_openf; /* Drive Commands */ #define GO 01 #define PRESET 020 #define RECAL 06 #define RCLR 010 #define OFFSET 014 #define READY 0200 /* hpds - drive ready */ #define PIP 020000 /* hpds - Positioning Operation in Progress */ #define ERR 040000 /* hpcs1 - composite error */ #define DU 040000 /* hper1 - Drive Unsafe */ #define DTE 010000 /* hper1 - Drive Timing Error */ #define OPI 020000 /* hper1 - Operation Incomplete */ /* Error Correction Code errors */ #define DCK 0100000 /* hper1 - Data Check error */ #define ECH 0100 /* hper1 - ECC hard error */ #define CLR 040 /* hpcs2 - Controller Clear */ #define FMT22 010000 /* hpof - 16 bit /word format */ /* * Use av_back to save track+sector, * b_resid for cylinder. */ #define trksec av_back #define cylin b_resid hpopen() { if(!hp_openf){ hp_openf++; HPADDR->hpcs2 = CLR; HPADDR->hpcs1 = RCLR|GO; HPADDR->hpcs1 = PRESET|GO; HPADDR->hpof = FMT22; } } hpstrategy(abp) struct buf *abp; { register struct buf *bp; register char *p1, *p2; bp = abp; p1 = &hp_sizes[bp->b_dev.d_minor&07]; if (bp->b_dev.d_minor >= (NHP<<3) || bp->b_blkno >= p1->nblocks) { bp->b_flags =| B_ERROR; iodone(bp); return; } bp->av_forw = 0; bp->cylin = p1->cyloff; p1 = bp->b_blkno; p2 = lrem(p1, 22); p1 = ldiv(p1, 22); bp->trksec = (p1%19)<<8 | p2; bp->cylin =+ p1/19; spl5(); if ((p1 = hptab.d_actf)==0) hptab.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 (hptab.d_active==0) hpstart(); spl0(); } hpstart() { register struct buf *bp; if ((bp = hptab.d_actf) == 0) return; hptab.d_active++; HPADDR->hpcs2 = bp->b_dev.d_minor >> 3; HPADDR->hpca = bp->cylin; rhstart(bp, &HPADDR->hpda, bp->trksec, &HPADDR->hpbae); } hpintr() { register struct buf *bp; register int ctr; if (hptab.d_active == 0) return; bp = hptab.d_actf; hptab.d_active = 0; if (HPADDR->hpcs1 & ERR) { /* error bit */ deverror(bp, HPADDR->hpcs2, 0); if(HPADDR->hper1 & (DU|DTE|OPI)) { HPADDR->hpcs2 = CLR; HPADDR->hpcs1 = RECAL|GO; ctr = 0; while ((HPADDR->hpds&PIP) && --ctr); } HPADDR->hpcs1 = RCLR|GO; if (++hptab.d_errcnt <= 10) { hpstart(); return; } bp->b_flags =| B_ERROR; } hptab.d_errcnt = 0; hptab.d_actf = bp->av_forw; bp->b_resid = HPADDR->hpwc; iodone(bp); hpstart(); } hpread(dev) { if(hpphys(dev)) physio(hpstrategy, &hpbuf, dev, B_READ); } hpwrite(dev) { if(hpphys(dev)) physio(hpstrategy, &hpbuf, dev, B_WRITE); } hpphys(dev) { register c; c = lshift(u.u_offset, -9); c =+ ldiv(u.u_count+511, 512); if(c > hp_sizes[dev.d_minor & 07].nblocks) { u.u_error = ENXIO; return(0); } return(1); }