32V/usr/src/standalone/rp6fmt.c

Compare this file to the similar file:
Show the results in this format:

# include "MBA.h"
# include "RP.h"
# include "CON.h"
# define LOW(i)((short)i)
# define HIGH(i)(i>>16)
# define BLKSIZ 512
# define BUFSIZ ((rpsec*BLKSIZ) + (rpsec*hdsiz))
# define MAXUNI  7 /* max. no. units on MBA */
# define MAXERR  20
# define MB_ERR  0x3080  /*  normal error bits  */
# define HDcoff 0
# define HDtoff  3
int track , cylndr , dunit , ecount , daterr , wcerr ;
int badsec , hdsiz , dtype , bsize , bufsiz;
char input[132] ;
int *RPptr ; /* ptr to start of RP reg's for desired drive */
int *Mptr ; /* ptr to MBA reg set */
int rptrk,rpcyl,rpsec;
char wcrflg ;
char *ibuf , *obuf ; /*  buffer pointers */
int Offset[] = {  /*  Centerline offsets  */
	0 , 0x08 , 0x88 , 0x10 , 0x90 , 0x18 , 0x98 , -1
	} ;
 
main() {
/*
*  Stand-alone program to format RP06/RM03 disk.
*  User specifies disk unit.
*/
register int bb;

putlin("format : Format RP06/RM03 Disk") ;
putnl() ;
 
gmba :
putstr("MBA no. : ") ;
getcon(input) ;
dunit = a2l(input) ;
if (dunit < 0) goto fini ;
if (dunit > MAXMBA) goto gmba ;
Mptr = RPptr =  (int *)(M_BASE + (dunit*NEXSPC)) ;
 
dun :
putstr("unit : ");
getcon(input) ;
dunit = a2l(input) ;
if (dunit < 0) goto fini ;
if (dunit > MAXUNI) goto dun ;
 
if (init()) {
	putlin("init error") ;
	goto dun ;
	}
 
bb = bsize = BUFSIZ;
for (cylndr = 0 ; cylndr < rpcyl ; cylndr++) {
	for (track = 0 ; track < rptrk ; track++) {
		if (format(0,bb,0)) return(1) ;
		if (wcheck(0,bb,0)) return(1) ;
		trkinc() ;
		}
	cylinc() ;
	trkclr() ;
	}
 
putnl() ;
putstr("# Bad Sectors : ") ;
l2x(badsec,input) ;
putlin(input) ;
putstr("# Write Check errors : ") ;
l2x(wcerr,input) ;
putlin(input) ;
putstr("# Data Check errors : ") ;
l2x(daterr,input) ;
putlin(input) ;
putstr("# Other errors : ") ;
l2x(ecount,input) ;
putlin(input) ;
putnl() ;
 
goto dun ;
 
fini :
return(0) ;
}
 
/*		*/
 
init() {
/*
*  Initialization.
*  Initialize MBA (disk) .
*  Set up MBA  map register to map a 
*    transfer of 'BUFSIZ' bytes.
*/
extern char *end ;
register int *mp0 , i , page;
register short *shp;
short flg;
 
*(Mptr+M_cr) = MBAinit ; /* MBA init */
/*  start of RP reg's for drive */
/*  get ptr. to RP ext reg set */
RPptr = (int *)((int)RPptr + (dunit*EXTSIZ) + M_extern) ;
if (((page = (*(RPptr+RP_sr))) & RP_MOL) == 0) {
	putlin("unit not online") ;
	return(-1) ;
	}
if (page & RP_WRL) {
	putlin("unit write-protected") ;
	return(1) ;
	}
 
*(RPptr+RP_cr) = RP_RIP | RP_GO ; /* drive preset - sets vv */
dwait(RPptr) ;
*(RPptr+RP_off) = RP_FMT | RP_ECI ; /* set format and ECC inhibit */
 
i = *(RPptr+RP_dt)&0777 ;  /* get disk type */
if (i==RP6typ) { /* RP06 */
	rpsec=RP6SEC; rpcyl=RP6CYL; rptrk=RP6TRK;
	hdsiz = RP6HD;
	dtype = RP6typ;
	}
else {
	if (i==RM3typ) {
		rpsec=RM3SEC; rpcyl=RM3CYL; rptrk=RM3TRK;
		hdsiz = RM3HD;
		dtype = RM3typ;
		}
	else return(-1);
	}
 
/*  output buffer */
obuf = (char *)((((int)&end)+511)&017777777000) ;
/*  input buffer */
ibuf = (char *)(((int)obuf + BUFSIZ + 511) & 017777777000) ;
/*  output buffer uses 1st 128 map reg's -
  input buffer uses last 128 map reg's */
page = (int)((int)obuf>>9) & 017777777 ;
page |= 0x80000000;
mp0 = (int *)((int)Mptr + (int)(M_map*4)) ;
for (i = 0 ; i < 128 ; i++)
	(*mp0++) = page++ ;
page = (int)((int)ibuf>>9) & 017777777 ;
page |= 0x80000000;
for (i = 0 ; i<128 ; i++ )
	(*mp0++) = page++ ;
 
/*  initialize output buffer with sector header and data :
	4 sector header words :
		cylinder
		track/sector
		key word 1 (not on RM03)
		key word 2 (not on RM03)
	256 data words
*/
flg = (dtype==RM3typ?RM_BSB:0);
for (shp = (short *)obuf , i = 0 ; i<rpsec ; i++) {
	*(shp++) = RP_FMT|flg ;
	*(shp++) = i;  /*  sect/trk  */
	if (dtype == RP6typ) {
		*(shp++) = 0;
		*(shp++) = 0;
		}
	for (page = 0 ; page < 256 ; page++)
		(*shp++) = page;
	}

ecount = daterr = wcerr = badsec = 0 ;
bufsiz=BLKSIZ;
return(0) ;
}
 
/*		*/
 
rshd(baddr,nb,s)
int baddr , nb , s ;
{
/*
*  Function to read 'nb' bytes into buffer pointed to
*    by map and offset in 'baddr' - start at sector 's'
*/
register int i , j ;
register int *M , *R ;
 
R = RPptr ;
M = Mptr ;
 
*(R+RP_cyl) = cylndr ; /* cylinder no. */
*(R+RP_stk) = (track<<8) | s ; /* track:sector */
*(M+M_bc) = (-nb) ;
*(M+M_var) = baddr ; /* virt addr reg = map no. + byte off */
rini :
*(R+RP_cr) = RP_DC | RP_GO ; /*  RP06 drive clear function code */
dwait(R) ;
*(R+RP_cr) = RP_RHD | RP_GO ; /* read sector header and data */
 
dwait(R) ; /* wait for i/o to finish */
if (i = mbaerr(M)) {
	return(-1) ;
	}
if (i = derror(R)) { /* error */
	putlin("- - - - - - -") ;
	putstr("read SHD error") ;
	stmes(i) ;
	dadmes(R) ;
	/* return if any header errors */
	if (i & (RP_HCRC|RP_HCE|RP_FER)) return(-1) ; /* error */
	}
/* normal return is to return header-error-free status */
return(i) ;
}
 
/*		*/
 
hcheck(insec,ousec)
register short *insec , *ousec ;
{
/*
* Compare sector header and data info on disk against that which
*  was written from output buffer
*/
register int j ;
 
/*  cyl and sect/track */
if (((*insec++)!=(*ousec++)) ||
  ((*insec++)!=(*ousec++)) ) return(1);
/* if RP06,  keywords */
if ((dtype==RP6typ) && ( ((*insec++)!=(*ousec++)) ||
  ((*insec++)!=(*ousec++)) )) return(1);
for (j = 0 ; j < 256 ; j++)
	if ((*insec++) != (*ousec++))
		return(1) ;
return(0) ;
}
 
/*		*/
 
format(baddr,nb,s)
int baddr , nb , s ;
{
/*
*  Function to write 'nb' bytes worth of sector and data info
*  from buffer whose map/offset is 'baddr' to disk.
*/
register int i , j ;
register int *R , *M ;
 
R = RPptr ;
M = Mptr ;
 
*(R+RP_cr) = RP_DC | RP_GO ;
dwait(R) ;
*(R+RP_cyl) = cylndr ;
*(R+RP_stk) = (track<<8) | s ; /* sector : track */
*(M+M_bc) = (-nb) ; /* byte count */
*(M+M_var) = baddr ; /* virt addr reg = map no. + byte off */
*(R+RP_cr) = RP_WHD | RP_GO ; /* write sector header and data */
 
dwait(R) ; /* wait for i/o to finish */
if (i = mbaerr(M)) {
	return(1) ;
	}
if (i = derror(R)) {
	putlin("- - - - - -") ;
	putstr("write SHD error") ;
	stmes(i) ;
	dadmes(R) ;
	if (wcrflg) return(1) ; /* return if in 'write check' recovery */
	if (++ecount > MAXERR) return(-1) ;
	}
return(0) ; /* normal return */
}
 
/*		*/
 
trkinc()
{
/*
*  Increment track no. in output buffer sector headers.
*/
register char *sp ;
register int i , j;
 
j = hdsiz + 512;
for (i = 0 , sp = obuf ; i < rpsec ; i++ ,  sp += j)
	sp[HDtoff]++ ;
}
 
/*		*/
 
cylinc() {
/*
*  Increment cylinder no. in output buffer sector headers.
*/
register short *sp ;
register int i , j;
 
j = hdsiz + 512;
for (i = 0 , sp = (short *)obuf ; i < rpsec ; i++ , sp = (short *)((int)sp +  j))
	sp[HDcoff]++ ;
}
 
/*		*/
 
trkclr()
{
/*
*  Clear track no. in output buffer sector headers.
*/
register char *sp ;
register int i , j;
 
j = hdsiz + 512;
for (i = 0 , sp = obuf ; i < rpsec ; i++ , sp += j)
	*(sp+HDtoff) = 0;
}
 
/*		*/
 
wcheck(baddr,nb,s)
int baddr , nb , s ;
{
/*
*  Function to write check 'nb' bytes worth of sector and data info
*  from buffer whose map reg is 'baddr' - start at sector 's'.
*/
register int i , j ;
register int *R , *M ;
 
R = RPptr ;
M = Mptr ;
 
*(R+RP_cr) = RP_DC | RP_GO ;
dwait(R) ;
*(R+RP_cyl) = cylndr ;
*(R+RP_stk) = (track<<8) | s ; /* sector : track */
*(M+M_bc) = (-nb) ; /* byte count */
*(M+M_var) = baddr ; /* virt addr reg = map no. + byte off */
*(R+RP_cr) = RP_WCH | RP_GO ; /* write check sector header and data */
 
dwait(R) ; /* wait for i/o to finish */
if (i = mbaerr(M)) {
	if (i & (M_WCKU | M_WCKL)) { /* Write Check Error */
		wcerr++ ;
		putlin("* Write Check Error *") ;
		dadmes(R) ;
		i = *(M+M_bc) | 0xffff0000 ;
		l2x(nb+i,input) ;
		putstr("no. bytes read : ") ;
		putlin(input) ;
		if (wcrflg) return(1) ;
		wckrcv() ;
		}
	}
if (i = derror(R)) {
	putlin("- - - - - -") ;
	putstr("write error") ;
	stmes(i) ;
	dadmes(R) ;
	ecount++ ;
	}
if (ecount > MAXERR) return(-1) ;
return(0) ; /* normal return */
}
 
/*		*/
 
wckrcv()
{
/*
*  Try to recover from a 'write check' error during a
*  'Write Check Header and Data' function.
*  'RPptr' is ptr to RP register set.
*  'Mptr' is ptr to MBA reg set.
*  MBA byte count reg has neg. no. bytes remaining - transfer stops
*  on error, even in middle of a sector.
*  Loop with a 'Write Sector Header and Data' followed by a 'Read
*  Sector Header and Data' - each loop iteration uses a different head 
*  centerline offset.
*  If all fails, report irrecoverable error and finish off the
*  'write check data and header' on the rest of the track.
*/
register int i , j , k , l , m ;
 
wcrflg++ ;  /*  flag says 'write check' recovery i-o is in progress */
/* If no. bytes read thus far is a multiple of 'BLKSIZ+RPHEAD', then
*  error was in last byte of sector and sector has to be backed up
*  by 1.
*/
j = curpos() ; /* return current cyl , trk ,sector */
i = ((*(Mptr+M_bc))>>16) + bsize ;  /*  no. bytes read by 'write check' */
if ((i%(BLKSIZ+hdsiz)) == 0) {
	putlin("wckrcv : backup 1 sector") ;
	j = backup(j) ;
	}
j = j & 0x1f ; /* sector only */
m = j * (BLKSIZ+hdsiz) ; /* page no. and offset */
/*
*  Loop with a 'Write Sector Header and Data' followed by a
*  'Read Sector Header and Data' - each iteration uses a
*  different centerline offset - 1st offset is 0.
*/
for (i = 0 ; (l = Offset[i]) >= 0 ; i++) {
	k = *(RPptr+RP_off) & 0xff00 ;
	*(RPptr+RP_off) = k | l ;
	*(RPptr+RP_cr) = RP_DC | RP_GO ;
	dwait(RPptr) ;
	*(RPptr+RP_cr) = RP_OFF | RP_GO ;
	dwait(RPptr) ;
	/*  Format 1 sector */
	if (format(m,BLKSIZ+hdsiz,j)) {
		putlin("wckrcv: format error");
		continue;
		}
	/*  Format was successful
	    Read sector. */
	if (rshd(128<<9,BLKSIZ+hdsiz,j) < 0) {
		putlin("wckrcv: rshd() error");
		continue ;
		}
	/*  successful 'Read Sector Header and Data' */
	/*  Compare sector written from output buffer
		against sector just read */
	if (hcheck(ibuf,obuf+m)) {
		putlin("wckrcv : sector compare failure") ;
		continue ;
		}
	/*  good read and good compare */
	putstr("    head offset : ") ;
	l2x(l,input) ;
	putlin(input) ;
	goto wckfin ;
	}
 
putlin("wckrcv : bad sector") ;
badsec++ ;
 
wckfin :
 
*(RPptr+RP_cr) = RP_RTC | RP_GO ; /* return to centerline */
dwait(RPptr) ;
/*  Cyl , trk and sector are set to values to continue where
*  original 'Write Check Header and Data' left off
*/
j = curpos() & 0xff ;  /*  sector  */
wcrflg = 0 ;
i = j * (BLKSIZ+hdsiz) ; /* offset */
/*  continue rest of 'wcheck89' */
wcheck(i,(rpsec-j)*(BLKSIZ+hdsiz),j) ;
return(0) ;
}
 
/*		*/
 
curpos()
{
/*
*  Function to return current cyl, trk and sector for RP whose
*  register set is pointed to by 'RPptr'.
*/
register int i , j ;
 
i = *(RPptr+RP_cyl)<<16 ;
j = *(RPptr+RP_stk) & 0x1f1f ;
return(i|j) ;
}
 
/*		*/
 
backup(cts)
register int cts ;
{
/*
*  Function to backup 1 sector.
*  Cyl, track and sector are in 'cts' .
*/
register int trk , sec ;
 
sec = cts & 0x1f ;  /*  sector */
if (sec > 0) return(--cts) ;
 
cts = cts & 0xffffff00 ;
cts = cts | (rpsec-1) ;
 
trk = (cts>>16) & 0x1f ;  /*  track */
if (trk>0) return(cts-0x100) ;  /*  dec track */
 
cts = cts & 0xffff00ff ;
cts = cts | ((rptrk-1)<<8) ;
 
return(cts-0x10000) ;  /*  dec cyl no.  */
}
 
/*		*/
 
dread(baddr,nb,s)
int baddr , nb , s ;
{
/*
*  Function to read 'nb' bytes into buffer pointed to
*    by map 'baddr' - start at sector 's'.
*/
register int i , *R , *M , j;
 
R = RPptr ;
M = Mptr ;
 
*(R+RP_cyl) = cylndr ; /* cylinder no. */
*(R+RP_stk) = (track<<8) | s ;  /* track:sector */
*(M+M_bc) = (-nb) ;
*(M+M_var) = baddr ; /* virt addr reg = map no. + byte off */
rini :
*(R+RP_cr) = RP_DC | RP_GO ; /*  RP06 drive clear function code */
dwait(R) ;
i = *(R+RP_off) & (~(RP_ECI)) ; /* enable ECC */
*(R+RP_off) = i ;
*(R+RP_cr) = RP_RED | RP_GO ; /* read */
 
dwait(R) ; /* wait for i/o to finish */
*(R+RP_off) = *(R+RP_off) | RP_ECI ; /* ECC inhibit on */
if (i = mbaerr(M)) {
	return(-1) ;
	}
if (i = derror(R)) { /* error */
	putlin("- - - - - - -") ;
	putstr("read error") ;
	stmes(i) ;
	dadmes(R) ;
	if (wcrflg)
		if (i & (RP_HCE|RP_HCRC|RP_FER|RP_PAR))
			return(1) ;
	if (i & (~(RP_DCK))) {
		ecount++ ;
		}
	if (i & RP_DCK) { /* Data Check Error */
		daterr++ ;
		putlin("* Data Check *") ;
		if (i & RP_ECH) { /* ECC Hard Error */
			putlin("ECC non-recov") ;
			if (wcrflg) return(1) ;
			ecount++ ;
			}
		else { /* ECC recoverable */
			ECCrcv(R) ;
			}
		if (*(M+M_bc)) { /* more i-o to complete */
			j = (*(R+RP_stk));
			i = (j>>8) & 0x1f;
			j = j & 0x1f;
			if (j>=rpsec) /*sector */
				j = 0;
			if (i>=rptrk) /* track */
				i = 0;
			*(R+RP_stk) = (i<<8) | j;
			goto rini ;
			/* status reg cleared by Drive Clear */
			}
		}
	if (wcrflg) return(0) ;
	if (ecount > MAXERR) return(-1) ;
	}
return(0) ; /* normal return */
}
 
/*		*/
 
ECCrcv(dptr)
register int *dptr ;
{
/*
*  Do ECC error recovery on disk whose register set is pointed
*  to by 'dptr'.
*  'mbaerr()' has cleared MBA status reg.
*  With ECC enabled, disk read has stopped after sector with bad
*  data. After correction of data, return to read routine which will
*  continue read of track if more sectors to do.
*  Return 0.
*/
register unsigned int pos , pat , ll;
register unsigned short *wordp ;
struct www {
	union {
		int x123;
		short wlo , whi ;
		} sss;
	};
char tmp[50] ;
 
pat = (*(dptr+RP_Epat)) & 0xffff ; /* ECC pattern reg */
pos = (*(dptr+RP_Epos)) & 0xffff ; /* ECC position reg */
putstr("pat : ") ;
ul2x(pat,tmp) ;
putlin(tmp) ;
putstr("pos : ") ;
ul2x(pos,tmp) ;
putlin(tmp) ;
wordp = (unsigned short *)ibuf ;   /* ptr to input buffer */
 
/*
*  'bufsiz' bytes are read on each read into buffer pointed to
*  by 'ibuf'. MBA byte count reg has neg. no. of bytes remaining
*  in read if this read error was not in the last sector to be
*  read.
*/
/* calculate buffer location of faulty data */
wordp = (unsigned short *)((int)wordp + (bufsiz + ((*(Mptr+M_bc))>>16) - BLKSIZ)) ; /* sector in buffer */
wordp = (unsigned short *)((int)wordp + ((pos-1)>>4)) ; /* word within sector */
 
/* burst pattern may be across word boundary */
ll = (*wordp) + ((*(wordp+1))<<16) ;
putstr("bad data  : ") ;
ul2x(ll,tmp) ;
putlin(tmp) ;
pat = pat<<((pos%16)-1) ;
ll = ll^pat ; /* correction */
putstr("good data : ") ;
ul2x(ll,tmp) ;
putlin(tmp) ;
 
/* put good data back in buffer */
*wordp = LOW(ll);
*(wordp+1) = HIGH(ll);
 
return(0) ;
}
 
/*		*/
 
mbaerr(mba)
register int *mba ;
{
register int i ;
 
if (i = (*(mba+M_sr))) {
	if (i == 0x2000) return(0) ;
	if (i != MB_ERR) {
		putlin("- - - - - -") ;
		putstr("MBA error") ;
		stmes(i) ;
		*(mba+M_sr) = (-1) ;
		return(i) ;
		}
	}
return(0) ;
}