MENLO_ECC

utzoo!decvax!ucbvax!william utzoo!decvax!ucbvax!william
Wed Sep 23 16:39:32 AEST 1981


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( byte<PGSIZE
     && ((hpx>0 && nok%PGSIZE==0) || wc==0) )
    {
	if( hpx>0 )
	    byte += nok-PGSIZE;
	while( 0<=byte && byte<bp->b_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.



More information about the Comp.bugs.2bsd mailing list