BBN-Vax-TCP/stand/d2tcpy.c

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

# define MIN(a,b) (a<b?a:b)
# define RP6CYL  815  /*  no. RP06 cylinders/pack */
# define RP6TRK  19  /*  no. tracks/cyl  */
# define RP6SEC  22  /*  no. sectors/track  */
# define RP6ST  (RP6TRK*RP6SEC)  /*  no. sectors/cyl  */
# define MAXSEC  (RP6CYL*RP6TRK*RP6SEC)  /*  sectors/pack  */
# define M0  0x20010000  /* phys addr MBA 0  */
# define M1  0x20012000  /*  phys addr MBA 1  */
# define M0_cr  (M0+4)  /*  MBA 0 control reg addr */
# define M1_cr  (M1+4)  /*  MBA 1 control reg addr  */
# define M0_map  (M0+0x800)  /* start MBA 0 map reg's */
# define M1_map  (M1+0x800)  /* start MBA 1 map reg's  */
# define M0_var  (M0+0xc)  /* MBA 0 virt addr reg */
# define M1_var  (M1+0xc)  /*  MBA 1 virt addr reg  */
# define M0_bc  (M0+0x10)  /*  MBA 0 byte count reg */
# define M1_bc  (M1+0x10)  /*  MBA 1 byte count reg  */
# define MBAinit 01  /*  MBA init bit */
/*		*/
# define TM  (M1+0x400)  /*  base for TM02/TE16 reg's */
# define RP  (M0+0x400)  /*  base for RP06 reg's, drive 0  */
/*		*/
# define TM_tc  (TM+0x24)  /*  TM02 tape control reg */
# define TM_cs1  (TM+0)  /*  TM02 control 1 reg */
# define TM_ds  (TM+4)  /*  status reg */
# define TM_fc  (TM+0x14)  /*  TM02 frame count reg */
/*		*/
# define RP_cr  0  /* RP06 control reg offset, longword */
# define RP_sr  1  /*  RP06 status reg offset */
# define RP_stk  5  /*  RP06 sector/track reg offset */
# define RP_off  011  /*  RP offset reg */
# define RP_cyl  10  /*  RP06 cylinder reg offset */
/*		*/
# 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 TM_GO  1  /*  TM02 go bit */
# define TM_DCLR  010  /*  TM02 drive clear function code */
# define TM_SFWD  030  /*  space forward function code */
# define TM_WRTF	060	/* write forward function code */
# define TM_REDF  070  /*  read forward function code */
# define TM_RWND  06  /*  TM02 Rewind  */
# define TM_WEOF	026	/* write end of file function */
# define TCHAR 01300  /*  TM02/TE16 drive 0 ,800 BPI,PDP11,etc. */
# define TM_DRDY  0200  /*  TM02/drive ready,status reg */
# define TM_ERR 040000  /*  TM02 composite error, status reg */
/*		*/
# 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 BUFSIZ 5120  /*  max tape block size = input buffer size */
# define MAXUNI  1
# define NL  012
# define CR 015
/*		*/
char input[BUFSIZ]  ;  /*  tape input buffer */
struct { int reg ; } ;
int blksiz ,tapoff , dskoff ,  wsize , dblks ;
int count;
unsigned int ins , outs ;
unsigned short nread  , bytoff , error ;
int *RPptr , dunit ; /* ptr to start of RP reg's for desired drive */
main() {
/*
*  Stand-alone program to copy TM02/TE16 drive 0 mag tape to
*  RP06 disc.
*  User specifies tape block size (must be multiple of 512), tape
*  offset (tape blocks), disc unit no., disc offset (512-byte
*  blocks) and count of tape blocks to be transferred.
*/
int getcon() , putstr() , a2l() , l2a() ;

putlin("d2tcpy : Disk-to-Tape Copy") ;
putnl() ;
 
bsize :
if (putstr("tape block size : ")) goto fini ;
if (getcon(input)) goto fini ;
putnl() ;
blksiz = a2l(input) ;
if ((blksiz <= 0) || (blksiz > BUFSIZ)) goto bsize ;
if (blksiz%512) goto bsize ;  /*  block size must be 512 multiple */
M0_cr->reg = MBAinit ; /* MBA 0 init */
M1_cr->reg = MBAinit ; /* MBA 1 init */
 
TM_tc->reg = TCHAR ; /* TE16,drive 0 ,800 BPI, PDP11, odd parity,
			abort on error */
TM_cs1->reg = TM_DCLR | TM_GO ; /* clear tape drive 0 */
if (terror()) goto taperr ;
 
toff :
if (putstr("tape offset : ")) goto fini ;
if (getcon(input)) goto fini ;
putnl() ;
tapoff = a2l(input) ;
if (tapoff < 0) goto toff ;
if (taprew()) goto taperr ;
if (tapspc(tapoff)) goto taperr ;
 
dun :
if (putstr("disk unit : ")) goto fini ;
if (getcon(input)) goto fini ;
putnl() ;
dunit = a2l(input) ;
if ((dunit > MAXUNI) || (dunit < 0)) goto dun ;
 
doff :
if (putstr("disc offset : ")) goto fini ;
if (getcon(input)) goto fini ;
putnl() ;
dskoff = a2l(input) ;
if ((dskoff < 0) || (dskoff > MAXSEC-1)) goto doff ;
 
gknt :
if (putstr("no. of input blocks : ")) goto fini ;
if (getcon(input)) goto fini ;
putnl() ;
count = a2l(input) ;
if (count < 0) goto gknt ;
 
error = 0 ;
 
if (init()) goto bsize ;
 
while ((error == 0) && (count>0)) {
	if (dread()) {
		putlin("disc i/o error") ;
		goto ioerr ;
		}
	ins++ ;  /*  count of disk blocks input */
	if (twrite()) {
		taperr :
			putlin("tape i/o error") ;
			ioerr :
				error++ ;
				continue ;
			}
	outs =+ dblks ;  /*  count of tape blocks output */
	count -= nread ;/*  dec no. blocks read */
}
 
fini :
TM_cs1->reg = TM_WEOF | TM_GO;
twait();
TM_cs1->reg = TM_RWND | TM_GO;
twait();
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() ;
 
inloop :
	c = getc() ; /* get 1 char from terminal */
	putc(c) ;  /*  echo char */
	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) ;
}
 
/*		*/
 
taprew()
{
/*
*  Function to rewind TM02/TE16 drive
*/
TM_cs1->reg = TM_RWND | TM_GO ;
twait() ;
if (terror()) return(-1) ;
return(0) ;
}
 
/*		*/
 
tapspc(fblk)
{
/*
*  Function to space forward 'fblk' blocks on TM02/TE16 drive
*/
if (fblk) {
	TM_fc->reg = (-fblk) ; /* no. blocks */
	TM_cs1->reg = TM_SFWD | TM_GO ;   /* space forward */
	twait() ;
	if (terror()) return(-1) ;
	}
return(0) ;
}
 
/*		*/
 
twait()
{
/*
*  Function to wait until TM02/TE16 is not busy
*/
while ((TM_ds->reg & TM_DRDY) == 0) ;
}
 
/*		*/
 
terror()
{
/*
*  Function to check for TM02 error
*  Return (-1) if error,
*	esle return (0).
*/
if (TM_ds->reg & TM_ERR) return(-1) ;
return(0) ;
}
 
/*		*/
 
init() {
/*
*  Initialization.
*  Initialize MBA 0 (disk) and MBA 1 (tape).
*  Initialize TM02/TE16 for drive 0 , 800 BPI, PDP11, etc.
*  Set up MBA 0 and MBA 1 map registers to map a max.
*    transfer of 'BUFSIZ' bytes.
*/
register int *mp0 , *mp1 , i , page ;
 
 
nread = BUFSIZ/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 */
RPptr = RP + (dunit * 32 * 4) ; /* start of RP reg's for drive */
if ((*(RPptr+RP_sr) & RP_MOL) == 0) {
	putlin("unit not online") ;
	return(-1) ;
	}
 
*(RPptr+RP_cr) = RP_RIP | RP_GO ; /* preset :/
*(RPptr+RP_off) = RP_FMT ; /* set format bit */
bytoff = (int)(&input[0])&0777 ; /* byte offset of buffer addr */
page = ((int)&input[0] >> 9) & 07777777 ; /* start page of buffer */
mp0 = M0_map ; /* phys addr of MBA 0 map reg base */
mp1 = M1_map ; /*  "	"	"  1	"	" */
 
i = (((BUFSIZ+511)>>9)&0777) + 1 ; /* max. no. of pages */
 
while (i--)
	(*mp0++) = (*mp1++) = 0x80000000 | page++ ; /* map entry */
 
}
 
/*		*/
 
twrite()
{
/*
*  Function to write TM02/TE16 tape drive, 'blksiz' bytes each
*  write, and 'nread' writes.
*/
register int i, j ;
 
j = 0;
for (i = MIN(nread,count) ; i ; i--) {
	M1_var->reg = bytoff + j++ * blksiz;
	M1_bc->reg = (-blksiz) ; /* MBA 1 byte count reg */
	TM_fc->reg = (-blksiz);	/* tape frame counter register */
	TM_cs1->reg = TM_WRTF | TM_GO ; /* write forward */
	twait() ; /* wait for ready */
	if (terror()) return(-1) ; /* return on error */
	}
return(0) ; /* normal return */
}
 
/*		*/
 
dread()
{
/*
*  Function to read 'wsize' bytes (512 multiple) from disc
*  to buffer 'input[]".
*/
register int i , j ;
 
*(RPptr+RP_cr) = RP_DC | RP_GO ; /* drive clear */
*(RPptr+RP_cyl) = dskoff/RP6ST ; /* cylinder no. */
i = dskoff%RP6ST ;
j = (i/RP6SEC)<<8 ; /* track */
*(RPptr+RP_stk) = j | (i%RP6SEC) ; /* sector : track */
M0_bc->reg = (count<nread?-(count*512):(-wsize)) ; /* byte count */
M0_var->reg = bytoff ; /* virt addr reg = map no. + byte off */
*(RPptr+RP_cr) = RP_RD | RP_GO ; /* write */
 
dskoff =+ dblks ;  /*  point to next disc sector */
dwait() ; /* wait for i/o to finish */
if (derror()) return(-1) ; /* error */
return(0) ; /* normal return */
}
 
/*		*/
 
dwait() {
/*
* Function to wait MBA 0 RP06 disc unit to be ready.
*/
while ((*(RPptr+RP_sr)&RP_DRY) == 0) ;
}
 
/*		*/
 
derror()
{
/*
*  Function to check for MBA 0 RP06 error.
*/
if (*(RPptr+RP_sr) & RP_ERR) return(-1) ;
return(0) ;
}
 
/*		*/
 
halt()
{
asm("	halt") ;
}
 
/*		*/
 
l2a(val,rptr)
register int val ;
register char *rptr ;
{
register int i ;
register char *tp ;
int knt ;
char tmp[20] , sign ;
 
knt = sign = 0 ;
if (val < 0) {
	sign++ ;
	val = (-val) ;
	}
 
tp = tmp ;
loop :
	knt++ ;
	i = val/10  ;  /*  quotient & base 10 */
	(*tp++) = val%10 + '0' ; /*  ascii remainder  */
	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 ;
}
 
/*		*/
 
echo(lngword)
register int lngword ;
{
char tmp[30] ;
 
l2a(lngword,tmp) ;
putlin(tmp) ;
}