Aucbvax.3281 net.2bsd-bugs utzoo!decvax!ucbvax!william Wed Sep 23 16:39:32 1981 Re: MENLO_ECC The released code is old and know not to work. It is part of a shitload of old code that got edited in at the last momement for reasons not made clear to me (I think someone got his diff mixed up). Here is code known to work on a RP06 RH70 sys. ##### hpecc (hp.c) ###### hpecc(rp,bp,dp) register struct device *rp; register struct buf *bp; struct buf *dp; { # define exadr(x,y) (((long)(x)<<16)|(unsigned)(y)) # define bitfld(x) ~(~0L<<(x)) long bb,addr; int bit,byte,nok,hpx,wc; long wrong; int ocmd; int cn,tn,sn; long bn; ubadr_t *ubp; /* *nok is #bytes including the error *which is assumed to be in the last disk page xferred. */ wc = rp->hpwc; nok = (wc+bp->b_bcount/NBPW)*NBPW; hpx = nok/PGSIZE; printf("%D ",bp->b_blkno+hpx); prdev("ECC",bp->b_dev); wrong = rp->hpec2&(int)bitfld(11); if( wrong==0 ) { rp->hpof = FMT22; rp->hpcs1.w |= IE; return 0; } ocmd = (rp->hpcs1.w&~DRY)|IE|GO; /* *compute the byte/bit position of the err *within the last disk page xferred. */ byte = rp->hpec1-1; bit = byte&(int)bitfld(3); byte >>= 3; /*correct while possible bits remain of mask*/ bb = exadr(bp->b_xmem,bp->b_un.b_addr); if( byte0 && nok%PGSIZE==0) || wc==0) ) { if( hpx>0 ) byte += nok-PGSIZE; while( 0<=byte && byteb_bcount && (wrong<<=bit)!=0 ) { addr = bb+byte; if( bp->b_flags&B_PHYS && bp->b_flags&B_MAP ) { /*simulate ubmap if twas unibus xfer*/ /*untested*/ printf("RAW XFER\n"); ubp = UBMAP+((addr>>13)&(int)bitfld(5)); addr = exadr(ubp->ub_hi,ubp->ub_lo) +(addr&bitfld(13)); } printf("MEMADR==%D\n",addr); putmemc(addr,getmemc(addr)^(int)wrong); byte++; bit = -8; } } /*getmemc() changes pri. might be a race.*/ spl5(); dp->b_active++; if( wc==0 ) return 0; /*have to continue the transfer*/ /*cross fingers*/ printf("RESTARTING...\n"); nok = hpx*PGSIZE; /*rp->hpcs1.w=DCLR|GO;*/ rp->hpcs2.w = dkunit(bp); rp->hpcs1.w = TRE|DCLR|GO/*~IE*/; bn = dkblock(bp); cn = bp->b_cylin-bn/(NSECT*NTRAC)/*.cyloff*/; bn += hpx; addr = bb+nok; cn += bn/(NSECT*NTRAC); sn = bn%(NSECT*NTRAC); tn = sn/NSECT; sn %= NSECT; rp->hpdc = cn; rp->hpda = (tn<<8)+sn; rp->hpwc = nok/NBPW-bp->b_bcount/NBPW; rp->hpba = (int)addr; if( cputype==70 ) rp->hpbae = (int)(addr>>16); /*rp->hpcs1.w=RCOM|IE|GO;*/ rp->hpcs1.w = ocmd; return 1; } ######################### The RAW code is seldom used, because there are no bad swap areas I have no idea if it works on single 512 reads, it should. This routine works correcting about 8 times a day one bad spot on one RP06. There is one change from the working version here; menlo70 calls some of their hps np's.... Bill.