#include "MBA.h" #include "RP.h" #include "TM.h" # include "CON.h" # define BLKMAX 32768 # define MIN(a,b) (a<b?a:b) #define MAXTER 10 /* max. no. consec. tape errors */ /* */ int blksiz , tfoff , tboff , dboff , tunit , dens ; int count , *tmMBA , *rpMBA , dblks , wsize ; unsigned int ins , outs ; unsigned int nread , bytoff , error ; int *RPptr , *TMptr ; int rpcyl,rptrk,rpsec; char input[150] , *bufptr , retry ; /* */ main() { register int i ; /* * Stand-alone program to copy TM[23]/TE16 mag tape to * RP06/RM03 disk. * User specifies tape and disk MBA no.'s, tape and disk unit no.'s, * tape block size, tape file offset, tape block offset in file, * and disk sector offset. */ putlin("tdcopy : TM03 tape-to-disk copy") ; putnl() ; tmbno : count = getval("tape MBA #") ; if ((count < 0) || (count > MAXMBA-1)) goto tmbno ; tmMBA = TMptr = (int *)(M_BASE + (count*NEXSPC)) ; /* TM02 MBA addr */ tuni : tunit = getval("tape unit #") ; if ((tunit < 0) || (tunit > 7)) goto tuni ; TMptr = (int *)((int)TMptr + (tunit*EXTSIZ) + M_extern) ; /* ptr. to MBA ext. reg set for this TM02 unit */ /* * ignore density prompt for tape read - TM02 recognizes and adjusts * for NRZ or PE input (800 or 1600 BPI) gden : dens = getval("tape density(8 or 16)") ; if (dens == 0) dens = TM_D800 ; else if ((dens != 8)&&(dens!=16)) goto gden ; */ dens = (dens==16?TM_D1600:TM_D800) ; toff : tfoff = getval("tape file offset") ; if (tfoff < 0) goto toff ; gtbo : tboff = getval("tape block offset") ; if (tboff < 0) goto gtbo ; putnl() ; gdm : count = getval("disk MBA #") ; if ((count < 0) || (count > MAXMBA-1)) goto gdm ; rpMBA = RPptr = (int *)(M_BASE + (count*NEXSPC)) ; /* RP06 MBA addr */ dun : count = getval("disk unit") ; if ((count > 7) || (count < 0)) goto dun ; RPptr = (int *)((int)RPptr + (count*EXTSIZ) + M_extern) ; /* ptr to MBA ext reg set for this RP06 unit */ doff : dboff = getval("disk block offset") ; putnl() ; gknt : count = getval("no. of input blocks") ; if (count < 0) goto gknt ; if (init()) { putlin("init() error") ; return(-1) ; } if ((dboff < 0) || (dboff > MAXSEC-1)) goto doff ; if (tapfil(TMptr,tfoff)) { tioerr : putlin("tape positioning error") ; return(-1) ; } if (tapfsp(TMptr,tboff)) goto tioerr ; /* read in 1st block of tape file to determine block size */ nread = 1 ; blksiz = 65536 ; for (retry=0,i=10,error=0;i;i--) { if ((tread()&TM_FCE) != TM_FCE) { if (++error > MAXTER) goto tioerr; } else break ; } retry++; blksiz = (*(TMptr+TM_fc)) & 0xffff ; pdstr(" = tape block size",blksiz) ; nread = M_BCMAX/blksiz ; /* no. of tape reads to fill input buffer */ wsize = nread * blksiz ; /* no. bytes each write to disc */ dblks = wsize/512 ; /* no. of disc blocks on each write */ *(TMptr+TM_cs1) = TM_DCLR | TM_GO ; twait(TMptr) ; if (tapbsp(TMptr,1)) goto tioerr ; putnl() ; for (error = 0 ; (error == 0) && (count > 0) ; count -= nread ) { if (i=tread(TMptr)) { putlin("tape i/o error") ; TME_print(i) ; goto ioerr ; } ins += nread ; /* count of tape blocks input */ if (i=dwrite(RPptr)) { putlin("disk i/o error") ; RPE_print(i) ; ioerr : error++ ; continue ; } outs += dblks ; /* count of disk blocks output */ } fini : /* no rewind on normal termination */ if (error == 0) putlin("normal termination") ; else taprew(TMptr) ; pdstr(" input blocks read",ins) ; pdstr(" output blocks written",outs) ; return(0) ; } /* */ init() { /* * Initialization. * Initialize MBA's and tape/disk units. * Initialize TM2/TE16 for drive 0 , 800 BPI, PDP11, etc. * Set up MBA map registers to map a max. * transfer of 'M_BCMAX' bytes. */ register int *mp0 , *mp1 , i , page ; extern char *end ; *(rpMBA+M_cr) = MBAinit ; /* init. RP06 MBA */ if (rpMBA != tmMBA) *(tmMBA+M_cr) = MBAinit ; if ((*(RPptr+RP_sr) & RP_MOL) == 0) { putlin("disk unit not online") ; return(-1) ; } *(RPptr+RP_cr) = RP_RIP | RP_GO ; /* preset */ dwait(RPptr) ; if (i=derror(RPptr)) { putlin("disk init error") ; RPE_print(i) ; return(-1) ; } *(RPptr+RP_off) = RP_FMT ; /* set format bit */ i = *(RPptr+RP_dt)&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); } /* set TM03 unit no., density, PDP11 normal mode, odd parity abort on error */ *(TMptr+TM_tc) = tunit | dens | TM_PNOR | TM_EABO ; *(TMptr+TM_cs1) = TM_DCLR | TM_GO ; twait(TMptr) ; if (i=terror(TMptr)) { tierr : putlin("tape init error") ; TME_print(i) ; return(-1) ; } if ((*(TMptr+TM_ds) & TM_MOL) == 0) { putlin("tape unit not online") ; return(-1) ; } *(TMptr+TM_cs1) = TM_RWND | TM_GO ; twait(TMptr) ; if (i=terror(TMptr)) goto tierr ; bufptr = (char *)((((int)&end)+511)&017777777000) ; page = ((int)((int)bufptr>>9)&017777777) | 0x80000000 ; /* SBI page no. */ mp0 = (int *)((int)tmMBA + (int)(M_map*4)) ; mp1 = (int *)((int)rpMBA + (int)(M_map*4)) ; for (i = ((M_BCMAX+511)/512)+1 ; i ; i--,page++) { (*mp0++) = page ; (*mp1++) = page ; } return(0) ; } /* */ tread() { /* * Function to read TM2/TE16 tape drive, 'blksiz' bytes each * read, and 'nread' reads. */ register int i, j , k , *t , *m , teknt ; m = tmMBA ; t = TMptr ; for (i=MIN(nread,count),j=0,teknt=0 ; i ; i--,j++) { trloop : *(m+M_var) = j * blksiz ; *(m+M_bc) = (-blksiz) ; /* MBA byte count reg */ *(t+TM_cs1) = TM_REDF | TM_GO ; /* read forward */ twait(t) ; /* wait for ready */ if (k=terror(t)) { if ((++teknt > MAXTER) || (retry == 0)) return(k); *(t+TM_cs1) = TM_DCLR | TM_GO ; twait(t); if (k=tapbsp(t,1)) return(k); goto trloop; } } return(0) ; /* normal return */ } /* */ dwrite() { /* * Function to write 'wsize' bytes to disc * from buffer '*bufptr'. */ register int i , j , *m , *d ; m = rpMBA ; d = RPptr ; *(d+RP_cr) = RP_DC | RP_GO ; /* drive clear */ dwait(d) ; *(d+RP_cyl) = dboff/RP6ST ; /* cylinder no. */ i = dboff%RP6ST ; j = (i/rpsec)<<8 ; /* track */ *(d+RP_stk) = j | (i%rpsec) ; /* sector : track */ *(m+M_bc) = (count<nread?-(count*512):(-wsize)) ; /* byte count */ *(m+M_var) = 0 ; /* virt addr reg = map no. + byte off */ *(d+RP_cr) = RP_WR | RP_GO ; dwait(d) ; if (i=derror(d)) return(i) ; /* error */ dboff += dblks ; /* point to next disc sector */ return(0) ; /* normal return */ }