Bell 32V development
authorTom London <tbl@research.uucp>
Wed, 21 Mar 1979 02:04:30 +0000 (21:04 -0500)
committerTom London <tbl@research.uucp>
Wed, 21 Mar 1979 02:04:30 +0000 (21:04 -0500)
Work on file usr/src/standalone/d2dcpy.c

Co-Authored-By: John Reiser <jfr@research.uucp>
Synthesized-from: 32v

usr/src/standalone/d2dcpy.c [new file with mode: 0644]

diff --git a/usr/src/standalone/d2dcpy.c b/usr/src/standalone/d2dcpy.c
new file mode 100644 (file)
index 0000000..c8d34ce
--- /dev/null
@@ -0,0 +1,699 @@
+# define RP6CYL  815  /*  no. RP06 cylinders/pack */
+# define RP6TRK  19  /*  no. tracks/cyl  */
+# define RP6SEC  22  /*  no. sectors/track  */
+# define RP6ST  (rptrk*rpsec)  /*  no. sectors/cyl  */
+# define MAXSEC  (rpcyl*rptrk*rpsec)  /*  sectors/pack  */
+# define M0  0x20010000  /* phys addr MBA 0  */
+# define M_st  2  /*  offset for MBA status reg */
+# define M0_cr  (M0+4)  /*  MBA 0 control reg addr */
+# define M0_map  (M0+0x800)  /* start MBA 0 map reg's */
+# define M0_var  (M0+0xc)  /* MBA 0 virt addr reg */
+# define M0_bc  (M0+0x10)  /*  MBA 0 byte count reg */
+# define MBAinit 01  /*  MBA init bit */
+# define M_DTC  0x2000  /* Data Transfer Complete */
+/*             */
+# define RP  (M0+0x400)  /*  base for RP06 reg's, drive 0  */
+/*             */
+# define RP_cr  0  /* RP06 control reg offset, longword */
+# define RP_sr  1  /*  RP06 status reg offset */
+# define RP_er1  2  /*  RP06 error reg 1 */
+# define RP_stk  5  /*  RP06 sector/track reg offset */
+# define RP_typ  06  /*  disk type reg */
+# define RP_off  011  /*  RP offset reg */
+# define RP_cyl  10  /*  RP06 cylinder reg offset */
+# define RP_Epos 016  /*  RP ECC position reg */
+# define RP_Epat 017  /*  RP ECC pattern reg */
+/*             */
+# define RP_GO  1  /*  go bit */
+# define RP_RD 070     /* RP06 read function code */
+# define RP_WR  060  /*  RP06 write function code */
+# define RP_DC  010  /*  drive clear function code */
+# define RP_FMT  0x1000  /*  format bit in RP offset reg */
+# define RP_RIP  020  /*  Read-in Preset function code */
+# define RP_MOL  0x1000  /*  medium online bit in status */
+# define RP_DRY  0200  /*  drive ready, status reg */
+# define RP_ERR 040000  /* composite error, status reg */
+# define RP_DCK  0x8000  /*  Data Check Error in ERR1 reg */
+# define RP_ECH  0x40  /*  ECC hard error */
+/*             */
+# define RXCS  32  /*  receiver control/staus */
+# define RXDB  33  /*  receiver data */
+# define TXCS  34  /*  transmitter control/status */
+# define TXDB  35  /*  transmitter data */
+# define RXCS_DONE  0x80  /*  receiver done */
+# define TXCS_RDY  0x80  /*  transmitter ready */
+/*             */
+# define BLKSIZ 512
+# define NB 128  /*  max. byte transfer = 64K bytes */
+# define BUFSIZ (NB*BLKSIZ)
+# define MAXUNI  1
+# define MAXERR 10  /*  max. no. i/o errors allowed */
+# define NL  012
+# define CR 015
+# define CDEL  0x23
+# define LDEL  0x40
+/*             */
+# define RM3CYL  823  /* RM03 */
+# define RM3TRK  5
+# define RM3SEC  32
+# define RP6typ  022
+# define RM3typ  024
+struct { int reg ; } ;
+int dinoff , douoff  , dblks , count  , ecount , daterr ;
+char *bufptr ;
+unsigned int page ;
+int *RPin , *RPout ;
+int rpsec,rptrk,rpcyl;
+char input[132] ;
+main() {
+/*
+*  Stand-alone program to copy rp06/RM03 disk to rp06/RM03 disk, same or
+*  different drives. User specifies input and output disk, no.
+*  of 512-byte blocks, and disk offsets.
+*/
+register int i , error ;
+
+putlin("d2dcpy : Disk-to-Disk Copy") ;
+putnl() ;
+d1u :
+putstr("input disk unit : ") ;
+getcon(input) ;
+i = a2l(input) ;
+if (i < 0) goto fini ;
+if (i > MAXUNI) goto d1u ;
+RPin = RP + (i * 32 * 4) ;
+dof1 :
+putstr("offset : ") ;
+getcon(input) ;
+dinoff = a2l(input) ;
+d2u :
+putstr("output disk unit : ") ;
+getcon(input) ;
+i = a2l(input) ;
+if ((i > MAXUNI) || (i < 0)) goto d2u ;
+RPout = RP + (i * 32 * 4) ;
+dof2 :
+putstr("offset : ") ;
+getcon(input) ;
+douoff = a2l(input) ;
+gknt :
+putstr("no. 512-byte blocks : ") ;
+getcon(input) ;
+count = a2l(input) ;
+error = 0 ;
+if (init()) {
+       putlin("init error") ;
+       goto d1u ;
+       }
+if ((dinoff < 0) || (dinoff > MAXSEC-1)) goto dof1 ;
+if ((douoff < 0) || (douoff > MAXSEC-1)) goto dof2 ;
+if (count < 0) goto gknt ;
+if (count == 0) count = MAXSEC ;
+ecount = daterr = 0 ;
+while ((error == 0) && (count>0)) {
+       if (dread()) {
+               dioerr :
+                       putlin("disc i/o error") ;
+                       error++ ;
+                       continue ;
+                       }
+       if (dwrite()) goto dioerr ;
+       count -= dblks ;/*  dec no. blocks read */
+       }
+fini :
+putstr("# Data Check Errors : ") ;
+l2x(daterr,input) ;
+putlin(input) ;
+putstr("# Other errors : ") ;
+l2x(ecount,input) ;
+putlin(input) ;
+return(0) ;
+}
+/*             */
+putstr(csp)
+register char *csp ;
+{
+if (putcon(csp)) return(-1) ;
+return(0) ;
+}
+/*             */
+putlin(sptr)
+register char *sptr ;
+{
+if (putcon(sptr)) return(-1) ;
+if (putnl()) return(-1) ;
+return(0) ;
+}
+/*             */
+putnl()
+{
+if (putcon("\r\n")) return(-1) ;
+return(0) ;
+}
+/*             */
+putcon(csp)
+register char *csp ;
+{
+/*
+*  Function to output null-terminated string pointed to 
+*  by 'csp' to the VAX LSI terminal.
+*/
+register c ;
+c = 0 ;
+while (c = (*csp++)) putc(c) ;
+return(0) ;
+}
+/*             */
+putc(c)
+{
+/*  wait for LSI printer to be ready */
+while ((mfpr(TXCS) & TXCS_RDY) == 0) ;
+/*  output character */
+mtpr(TXDB,c&0177) ;
+}
+/*             */
+getcon(cs)
+register char *cs ;
+{
+/*
+*  Function to return char's from VAX LSI keyboard to
+*  char array 'cs' - input stops when CR or LF received -
+*  null char appended to end of input
+*/
+register int c , c2 ;
+int getc() ;
+char *ocs;
+       ocs=cs;
+inloop :
+       c = getc() ; /* get 1 char from terminal */
+       putc(c) ;  /*  echo char */
+       if (c==CDEL) { --cs; goto inloop; }
+       if (c==LDEL){ putc(NL);putc(0);putc(CR);cs=ocs;goto inloop;}
+       if ((c == NL) || (c == CR)) {
+               putc(CR) ;
+               putc(0) ;
+               putc(NL) ;
+               (*cs++) = '\0' ;
+               return(0) ;
+               }
+       else {
+               (*cs++) = c ;
+               goto inloop ;
+               }
+}
+/*             */
+getc()
+{
+/*
+*  Return char from VAX LSI terminal char buffer
+*/
+int mfpr() ;
+/*  Wait for receiver done (user entered char)
+*/
+while ((mfpr(RXCS) & RXCS_DONE) == 0) ;
+return (mfpr(RXDB) & 0177) ;  /* return char from receiver buffer */
+}
+/*             */
+mtpr(regno,value)
+{
+       asm("   mtpr    8(ap),4(ap)") ;
+}
+/*             */
+mfpr(regno)
+{
+       asm("   mfpr    4(ap),r0") ;
+}
+/*             */
+a2l(as)
+register char *as ;
+{
+/*
+*  Convert null-terminated ascii string to binary
+*  and return value.
+*  1st char in string :
+*      0 -> octal
+*      x -> hex
+*      else decimal
+*/
+register value , base , sign , digit ;
+digit = value = sign = 0 ;
+base = 10 ;  /* default base */
+aloop :
+if ((digit = (*as++)) == 0) return(value) ; /* null */
+if (digit == '-') {
+       sign++ ;
+       goto aloop ;
+       }
+if (digit == '0') base = 8 ;  /* octal base  */
+else { if (digit == 'x') base = 16 ;  /* hex base */
+       else value = (digit-060) ; /* 060 = '0' */
+       }
+while (digit = (*as++)) {
+       if (digit < '0') return(0) ;
+       switch (base) {
+               case 8 : {
+                       if (digit > '7') return(0) ;
+                       digit -= 060 ;
+                       break ;
+                       }
+               case 10 : {
+                       if (digit > '9') return(0) ;
+                       digit -= 060 ;
+                       break ;
+                       }
+               case 16 : {
+                       if (digit <= '9') {
+                               digit -= 060 ;
+                               break ;
+                               }
+                       if ((digit >= 'A') && (digit <= 'F')) {
+                               digit = (digit - 0101 + 10) ;
+                                       break ;
+                               }
+                       if ((digit >= 'a') && (digit <= 'f')) {
+                               digit = digit - 0141 + 10 ;
+                               break ;
+                               }
+                       return(0) ;
+                       break ;
+                       }
+               }
+       value = (value * base) + digit ;
+       }
+return (sign ? -value : value) ;
+}
+/*             */
+init() {
+/*
+*  Initialization.
+*  Initialize MBA 0 for disk i/o.
+*  Set up MBA 0 map registers to map a max.
+*    transfer of 'BUFSIZ' bytes.
+*/
+register int *mp0 , i ;
+extern char *end ;
+M0_cr->reg = MBAinit ;
+dblks = BUFSIZ/BLKSIZ ; /* no. of disk blocks / input buffer */
+if ((*(RPin+RP_sr) & RP_MOL) == 0) {
+       putlin("input unit not online") ;
+       return(-1) ;
+       }
+*(RPin+RP_cr) = RP_RIP | RP_GO ; /* preset */
+*(RPin+RP_off) = RP_FMT ; /* set format bit */
+if (RPin != RPout) {
+       if ((*(RPout + RP_sr) & RP_MOL) == 0) {
+               putlin("output unit not online") ;
+               return(-1) ;
+               }
+       *(RPout+RP_cr) = RP_RIP | RP_GO ;
+       *(RPout+RP_off) = RP_FMT ;
+       }
+i = *(RPout+RP_typ)&0777 ;  /* get disk type */
+if (i==RP6typ) { /* RP06 */
+       rpsec=RP6SEC; rpcyl=RP6CYL; rptrk=RP6TRK;
+       }
+else {
+       if (i==RM3typ) {
+               rpsec=RM3SEC; rpcyl=RM3CYL; rptrk=RM3TRK;
+               }
+       else return(-1);
+       }
+bufptr = (int)(&end + 511) & 017777777000 ;
+page = (int)((int)bufptr>>9) & 017777777 ;
+mp0 = M0_map ; /* phys addr of MBA 0 map reg base */
+i = NB ;
+while (i--)
+       (*mp0++)= 0x80000000 | page++ ; /* map entry */
+
+return(0);
+}
+/*             */
+dread()
+{
+/*
+*  Function to read 'BUFSIZ' bytes (512 multiple) from disc
+*  to buffer .
+*/
+register int i , j ;
+*(RPin+RP_cyl) = dinoff/RP6ST ; /* cylinder no. */
+i = dinoff%RP6ST ;
+j = (i/rpsec)<<8 ; /* track */
+*(RPin+RP_stk) = j | (i%rpsec) ; /* sector : track */
+dinoff += dblks ;  /*  point to next disc sector */
+M0_bc->reg = (count<dblks?-(count*512):(-BUFSIZ)) ; /* byte count */
+M0_var->reg = 0 ; /* virt addr reg = map no. + byte off */
+rbit :
+*(RPin+RP_cr) = RP_DC | RP_GO ; /* drive clear */
+dwait(RPin) ;
+*(RPin+RP_cr) = RP_RD | RP_GO ; /* read */
+dwait(RPin) ; /* wait for i/o to finish */
+if (i = mbaerr(M0)) {
+       /* don't abort on MBA errors - 'mbaerr()' has cleared
+       MBA status reg */
+    }
+if (i = derror(RPin)) { /*  error  */
+       putlin("- - - - - -") ;
+       putstr("read error") ;
+       stmes(i) ;
+       dadmes(RPin) ;
+       if (i & RP_DCK) { /* Data Check Error */
+               daterr++ ;
+               putlin("Data Check") ;
+               if (i & RP_ECH) { /*  ECC Hard Error */
+                       putlin("ECC non-recov") ;
+                       ecount++ ;
+                       }
+               else { /*  ECC Recoverable */
+                       ECCrcv(RPin) ;
+                       }
+               if (M0_bc->reg) { /* more i-o to finish ? */
+                       j = (*(RPin+RP_stk));
+                       i = (j>>8) & 0x1f;
+                       j = j & 0x1f;
+                       if (j>=rpsec) /*sector */
+                               j = 0;
+                       if (i>=rptrk) /* track */
+                               i = 0;
+                       *(RPin+RP_stk) = (i<<8) | j;
+                       goto rbit ; /* staus reg cleared by 'Drive Clear' */
+                       }
+               else {
+               *(RPin+RP_cr) = RP_DC | RP_GO;
+                       mbaerr(M0);
+                       }
+               }
+       else { /* non-Data Check error */
+               ecount++ ;
+               }
+       if (ecount > MAXERR) return(-1) ;
+       }
+return(0) ; /* normal return */
+}
+/*             */
+dwrite()
+{
+/*
+*  Function to write 'BUFSIZ' bytes (512 multiple) to disc
+*  from buffer .
+*/
+register int i , j ;
+*(RPout+RP_cr) = RP_DC | RP_GO ;
+*(RPout+RP_cyl) = douoff/RP6ST;
+i = douoff%RP6ST ;
+j = (i/rpsec)<<8 ; /* track */
+*(RPout+RP_stk) = j | (i%rpsec) ; /* sector : track */
+M0_bc->reg = (count<dblks?-(count*512):(-BUFSIZ)) ; /* byte count */
+M0_var->reg = 0 ; /* virt addr reg = map no. + byte off */
+*(RPout+RP_cr) = RP_WR | RP_GO ; /* write */
+douoff += dblks ;  /*  point to next disc sector */
+dwait(RPout) ; /* wait for i/o to finish */
+if (i = mbaerr(M0)) {
+  return(-1) ;
+  }
+if (i = derror(RPout)) {
+       putstr("write error") ;
+       stmes(i) ;
+       dadmes(RPout) ;
+       if (++ecount > MAXERR) return(-1) ;
+  }
+return(0) ; /* normal return */
+}
+/*             */
+dwait(dptr)
+register int *dptr ;
+{
+/*
+* Function to wait MBA 0 RP06 disc unit to be ready.
+*/
+while ((*(dptr+RP_sr)&RP_DRY) == 0) ;
+}
+/*             */
+derror(dptr)
+register int *dptr ;
+{
+/*
+*  Function to check for MBA 0 RP06 error.
+*/
+if (*(dptr+RP_sr) & RP_ERR) return(*(dptr+RP_er1) & 0177777) ;
+return(0) ;
+}
+/*             */
+halt()
+{
+asm("  halt") ;
+}
+/*             */
+stmes(code)
+int code ;
+{
+putstr(" : err reg : ") ;
+RPE_print(code) ;
+}
+/*             */
+dadmes(dptr)
+register int *dptr ;
+{
+register char *mesp ;
+register int i ;
+mesp = " cyl     trk     sec    " ;
+i = l2x(*(dptr+RP_cyl) & 01777,&mesp[5]) ;
+blnkit(&mesp[5+i],4-i) ;
+i = l2x((*(dptr+RP_stk)>>8) & 037 , &mesp[13]) ;
+blnkit(&mesp[13+i],3-i) ;
+i = l2x(*(dptr+RP_stk)&037,&mesp[21]) ;
+blnkit(&mesp[21+i],3-i) ;
+putlin(mesp) ;
+}
+/*             */
+blnkit(mp,cc)
+register char *mp ;
+register int cc ;
+{
+while (cc--)
+       (*mp++) = ' ' ;
+}
+/*             */
+mbaerr(mba)
+register int *mba ;
+{
+register int i ;
+if ((i = (*(mba+M_st))) != M_DTC) {
+       putlin("- - - - - -") ;
+       putstr("MBA error : status reg = ") ;
+       MBAS_print(i) ;
+       *(mba+M_st) = (-1) ;
+       return(i) ;
+  }
+return(0) ;
+}
+/*             */
+l2x(val,rptr)
+register int val ;
+register char *rptr ;
+{
+register int i , j ;
+register char *tp ;
+int knt ;
+char tmp[20] , sign ;
+knt = sign = 0 ;
+if (val < 0) {
+       sign++ ;
+       val = (-val) ;
+       }
+tp = tmp ;
+loop :
+       knt++ ;
+       i = val/16  ;  /*  quotient & base 16 */
+       j = val%16 ;
+       (*tp++) = j + (j<10?0x30:0x57) ;
+       val = i ;
+       if (val == 0) {
+               /*  done  dividing  */
+               if (sign) { knt++ ; (*tp++) = '-' ; }
+               for (i = knt ; i ; i--)
+                       (*rptr++) = tmp[i-1] ;
+               (*rptr++) = '\0' ;
+               return(knt) ;
+               }
+       else goto loop ;
+}
+/*             */
+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 'dread()' which will
+*  continue read of track if more sectors to do.
+*  Return 0.
+*/
+register unsigned int pos , pat ;
+register unsigned short *wordp ;
+unsigned int ll ;
+struct { short wlo , whi ; } ;
+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 = bufptr ;   /* ptr to buffer */
+/*
+*  'BUFSIZ' bytes are read on each read into buffer pointed to
+*  by 'bufptr'. 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 = (char *)wordp + (BUFSIZ + ((M0_bc->reg)>>16) - BLKSIZ) ; /* sector in buffer */
+wordp = 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 = ll.wlo ;
+*(wordp+1) = ll.whi ;
+return(0) ;
+}
+/*             */
+ul2x(val,rptr)
+register unsigned int val ;
+register char *rptr ;
+{
+register unsigned int i , j ;
+register char *tp ;
+int knt ;
+char tmp[20] ;
+unsigned int udiv() , urem() ;
+knt =  0 ;
+tp = tmp ;
+loop :
+       knt++ ;
+       /* use unsigned integer divide & remainder routines */
+       i = udiv(val,16)  ;  /*  quotient & base 16 */
+       j = urem(val,16) ;
+       (*tp++) = j + (j<10?0x30:0x57) ;
+       val = i ;
+       if (val == 0) {
+               /*  done  dividing  */
+               for (i = knt ; i ; i--)
+                       (*rptr++) = tmp[i-1] ;
+               (*rptr++) = '\0' ;
+               return(knt) ;
+               }
+       else goto loop ;
+}