*** /old/src/sys/pdpstand/Makefile	Tue Aug 28 20:46:17 1990
--- /usr/src/sys/pdpstand/Makefile	Wed Mar 18 00:21:44 1992
***************
*** 4,23 ****
  #	Note that there are limitations on how large a program may
  #	be loaded along with all device drivers.  This is especially
  #	a problem with restor.  Programs should be <= 48K to be safe.
- 
- # BPI will compile a primary tape bootstrap capable of supporting 800 (HT and
- # TM), 1600 (HT, some third party TMs, and TS), or 6250 (some third party
- # TMs only).  2.10BSD is only distributed at 1600BPI, but others may have
- # need to make boot tapes at different densities ...
  #
! BPI=	1600
  
- # RB_DEFNAME is the name the secondary boot will go for if you just type
- # carriage return to the boot prompt, or if boot detects boot options passed
- # in and RB_ASKNAME isn't set.
- #
- RB_DEFNAME=xp(0,0)unix
- 
  # DISK	which disk to take a root dump of for the distribution tape
  # TAPE	which tape to write the distribution on
  # DUMP	where to store a root system dump if you do a ``make dump''
--- 4,14 ----
  #	Note that there are limitations on how large a program may
  #	be loaded along with all device drivers.  This is especially
  #	a problem with restor.  Programs should be <= 48K to be safe.
  #
! #	If a GENERIC kernel distribution is being created be sure
! #	to install /sys/pdpdist/dtab (or /etc/dtab.save) as ${ROOT}/etc/dtab 
! #	so that the GENERIC kernel can find the tape device.
  
  # DISK	which disk to take a root dump of for the distribution tape
  # TAPE	which tape to write the distribution on
  # DUMP	where to store a root system dump if you do a ``make dump''
***************
*** 32,39 ****
  RESTOR=	${ETCSRC}/restor/restor.c
  ICHECK=	${ETCSRC}/icheck.c
  
! DEFS=	-DBPI=${BPI} -DRB_DEFNAME='"${RB_DEFNAME}"' -DSTANDALONE \
! 	-I${ROOT}/usr/include
  CFLAGS=	-O ${DEFS}
  
  BOOT=	M.o boot.o ubmapset.o
--- 23,29 ----
  RESTOR=	${ETCSRC}/restor/restor.c
  ICHECK=	${ETCSRC}/icheck.c
  
! DEFS=	-DSTANDALONE -I${ROOT}/usr/include
  CFLAGS=	-O ${DEFS}
  
  BOOT=	M.o boot.o ubmapset.o
***************
*** 41,47 ****
  	ht.o tm.o ts.o tmscp.o \
  	xp.o rk.o rl.o br.o hk.o si.o ra.o
  
! ALL=	mtboot boot mkfs restor icheck maketape tmscpboot
  
  .c.o:
  	cc ${CFLAGS} -c $*.c
--- 31,37 ----
  	ht.o tm.o ts.o tmscp.o \
  	xp.o rk.o rl.o br.o hk.o si.o ra.o
  
! ALL=	mtboot boot mkfs restor icheck maketape
  
  .c.o:
  	cc ${CFLAGS} -c $*.c
***************
*** 56,62 ****
  distribution: tape1 switch_tapes tape2
  
  tmscptape: ${ALL} ${DUMP}
! 	./maketape /dev/nr${TAPE} tmscptape.data
  	dd if=${DUMP} of=/dev/nr${TAPE} bs=20b
  	cd ${ROOT}/usr; tar cfb /dev/nr${TAPE} 20 \
  		adm bin dict doc games guest hosts include ingres lib \
--- 46,52 ----
  distribution: tape1 switch_tapes tape2
  
  tmscptape: ${ALL} ${DUMP}
! 	./maketape /dev/nr${TAPE} maketape.data
  	dd if=${DUMP} of=/dev/nr${TAPE} bs=20b
  	cd ${ROOT}/usr; tar cfb /dev/nr${TAPE} 20 \
  		adm bin dict doc games guest hosts include ingres lib \
***************
*** 115,125 ****
  mtboot: mtboot.o
  	strip $@.o
  	dd if=$@.o of=mtboot bs=16 skip=1
- 	rm -f $@.o
- 
- tmscpboot: tmscpboot.o
- 	strip $@.o
- 	dd if=$@.o of=tmscpboot bs=16 skip=1
  	rm -f $@.o
  
  boot: M.o conf.o boot.o ubmapset.o libsa.a
--- 105,110 ----
*** /old/src/sys/pdpstand/Makefile.vax	Fri Jan 11 16:15:39 1991
--- /usr/src/sys/pdpstand/Makefile.vax	Sun Apr 28 00:13:32 1991
***************
*** 22,35 ****
  DUMP=	/xusr/root.dump
  TMP1=	/xusr/1st.tar
  TMP2=	/xusr/2nd.tar
- TMP3=	/tmp/maketape.data
  
  ROOT=	/xusr/root
  
  distribution: tape1 switch_tapes tape2
  
! tape1: ${TMP3} ${TMP2} ${TMP1}
! 	./maketape /dev/r${TAPE} ${TMP3}
  
  switch_tapes: FRC
  	@echo "Switch tapes.  Hit CR when second tape is mounted."
--- 22,34 ----
  DUMP=	/xusr/root.dump
  TMP1=	/xusr/1st.tar
  TMP2=	/xusr/2nd.tar
  
  ROOT=	/xusr/root
  
  distribution: tape1 switch_tapes tape2
  
! tape1: ${TMP2} ${TMP1}
! 	./maketape /dev/r${TAPE} maketape.data
  
  switch_tapes: FRC
  	@echo "Switch tapes.  Hit CR when second tape is mounted."
***************
*** 50,62 ****
  
  ${TMP2}:
  	cd ${ROOT}/usr/src; tar cf ${TMP2} sys include
- 
- ${TMP3}:
- 	cp tmscptape.data ${TMP3}
- #	cp maketape.data ${TMP3}
- 	echo "* 1" >> ${TMP3}
- 	echo ${DUMP} 20 >> ${TMP3}
- 	echo "* 1" >> ${TMP3}
- 	echo ${TMP1} 20 >> ${TMP3}
- 	echo "* 1" >> ${TMP3}
- 	echo ${TMP2} 20 >> ${TMP3}
--- 49,51 ----
*** /old/src/sys/pdpstand/boot.c	Fri Aug 19 11:53:12 1988
--- /usr/src/sys/pdpstand/boot.c	Mon May 27 20:33:44 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)boot.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  #include "../h/param.h"
  #include "../machine/seg.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)boot.c	2.1 (2.11BSD) 5/25/91
   */
  #include "../h/param.h"
  #include "../machine/seg.h"
***************
*** 12,25 ****
  #include "../h/inode.h"
  #include "../h/reboot.h"
  #include "saio.h"
- 
  #include <a.out.h>
  
! #ifndef RB_DEFNAME
! #	define	RB_DEFNAME	"xp(0,0)unix"
! #endif
! 
! #undef	btoc
  #define	KB	* 1024L
  
  #define	KISD0	((u_short *) 0172300)
--- 12,20 ----
  #include "../h/inode.h"
  #include "../h/reboot.h"
  #include "saio.h"
  #include <a.out.h>
  
! #undef	btoc			/* to save space */
  #define	KB	* 1024L
  
  #define	KISD0	((u_short *) 0172300)
***************
*** 34,48 ****
  #define	SEG_TEXT	02
  #define	SEG_OVLY	04
  
! extern int	bootopts;	/* boot options from previous incarnation */
! extern int	bootdev;	/* UNIX dev we were booted from (not used) */
! extern int	checkword;	/* one's complements of bootopts */
! extern int	cputype;	/* 24, 40, 44, 45, 70, or 73 */
! extern bool_t	ksep;		/* is kernel mode currently separated */
! extern bool_t	sep_id;		/* does the cpu support separate I/D? */
  
  char		module[] = "Boot"; /* this program's name (used by trap) */
- char		line[100] = RB_DEFNAME;
  bool_t		overlaid = 0;
  u_short		pdrproto[16 + NOVL] = {0};
  struct exec	exec;
--- 29,45 ----
  #define	SEG_TEXT	02
  #define	SEG_OVLY	04
  
! extern	caddr_t	*bootcsr;	/* csr of boot controller */
! extern	int	bootopts;	/* boot options from previous incarnation */
! extern	int	bootdev;	/* makedev(major,unit) booted from */
! extern	int	checkword;	/* one's complements of bootopts */
! extern	int	cputype;	/* 24, 40, 44, 45, 70, or 73 */
! extern	bool_t	ksep;		/* is kernel mode currently separated */
! extern	bool_t	sep_id;		/* does the cpu support separate I/D? */
! extern	int	ndevsw;		/* number of devices in devsw[] */
! extern	char	ADJcsr[];	/* adjustments for ROM csr addresses */
  
  char		module[] = "Boot"; /* this program's name (used by trap) */
  bool_t		overlaid = 0;
  u_short		pdrproto[16 + NOVL] = {0};
  struct exec	exec;
***************
*** 58,75 ****
  	struct	loadmap	*lt_map;
  };
  
- /*
-  * The 0401 references below are to a weird ULTRIX magic which signifies a
-  * stand alone 0407.  This entry is present so we can boot the ULTRIX boot if
-  * necessary (we can't load an ULTRIX kernel and most of the ULTRIX stand alone
-  * utilities for instance).
-  */
- #define	A_MAGICU	0401
- 
- struct	loadmap	load401[] = {
- 	SEG_DATA,	56 KB,
- 	0,		0  KB
- };
  struct	loadmap	load407[] = {
  	SEG_DATA,	56 KB,
  	0,		0  KB
--- 55,60 ----
***************
*** 126,132 ****
  };
  
  struct	loadtable	loadtable[] = {
- 	A_MAGICU,	load401,	/* ULTRIX boot */
  	A_MAGIC1,	load407,
  	A_MAGIC2,	load410,
  	A_MAGIC3,	load411,
--- 111,116 ----
***************
*** 136,146 ****
  
  main()
  {
! 	int i, j;
  	int retry = 0;
  	struct loadtable *setup();
  
! 	printf("\nboot: %d%s\n", cputype, module);
  	/*
  	 * The machine language will have gotten the bootopts
  	 * if we're an autoboot and will pass them along.
--- 120,159 ----
  
  main()
  {
! 	register int i, j, maj;
  	int retry = 0;
+ 	caddr_t	*adjcsr;
  	struct loadtable *setup();
+ 	struct iob *file;
+ 	char	line[64], defnam[64], *itoa();
  
! 	maj = major(bootdev);
! 	if (maj >= ndevsw) {
! 		printf("bootdev: 0%o", bootdev);
! 		_stop("bad major");
! 	}
! 	adjcsr = (caddr_t *)((short)bootcsr - ADJcsr[maj]);
! 	for (i = 0; devsw[maj].dv_csr != (caddr_t) -1; i++) {
! 		if (adjcsr == devsw[maj].dv_csr[i])
! 			break;
! 		if (devsw[maj].dv_csr[i] == 0) {
! 			devsw[maj].dv_csr[i] = adjcsr;
! 			break;
! 		}
! 	}
! 	if (devsw[maj].dv_csr[i] == (caddr_t *) -1) {
! 		printf("bootdev: 0%o", bootdev);
! 		_stop("no free csr slots");
! 	}
! 	bootdev &= ~(3 << 6);
! 	bootdev |= (i << 6);	/* controller # to bits 6&7 */
! 	printf("\n%d%s from %s(%d,0,0%o)\n", cputype, module, 
! 		devsw[major(bootdev)].dv_name, minor(bootdev), bootcsr);
! 	strcpy(defnam, devsw[major(bootdev)].dv_name);
! 	strcat(defnam, "(");
! 	strcat(defnam, itoa(minor(bootdev)));
! 	strcat(defnam, ",0)unix");
! 	strcpy(line, defnam);
  	/*
  	 * The machine language will have gotten the bootopts
  	 * if we're an autoboot and will pass them along.
***************
*** 156,167 ****
  		} else
  			printf(": %s\n", line);
  		if (line[0] == '\0') {
! 			printf(": %s\n", RB_DEFNAME);
! 			i = open(RB_DEFNAME, 0);
! 		} else
! 			i = open(line, 0);
  		j = -1;
  		if (i >= 0) {
  			j = checkunix(i, setup(i));
  			(void) close(i);
  		}
--- 169,181 ----
  		} else
  			printf(": %s\n", line);
  		if (line[0] == '\0') {
! 			strcpy(line, defnam);
! 			printf(": %s\n", line);
! 		}
! 		i = open(line, 0);
  		j = -1;
  		if (i >= 0) {
+ 			file = &iob[i - 3];	/* -3 for pseudo stdin/o/e */
  			j = checkunix(i, setup(i));
  			(void) close(i);
  		}
***************
*** 168,173 ****
--- 182,192 ----
  		if (++retry > 2)
  			bootopts = RB_SINGLE | RB_ASKNAME;
  	} while (j < 0);
+ 	i = file->i_ino.i_dev;
+ 	bootdev = makedev(i, file->i_unit);
+ 	bootcsr = devsw[i].dv_csr[(file->i_unit >> 6) & 3];
+ 	bootcsr = (caddr_t *)((short)bootcsr + ADJcsr[i]);
+ 	printf("%s: bootdev=0%o bootcsr=0%o\n", module, bootdev, bootcsr);
  }
  
  struct loadtable *
***************
*** 342,348 ****
  				 * If this is a 0407 style object, the text
  				 * and data are loaded together.
  				 */
! 				if (exec.a_magic != A_MAGIC1 && exec.a_magic != A_MAGICU) {
  					segoff += (off_t) exec.a_text;
  					if (overlaid)
  						for (i = 0; i < NOVL; i++)
--- 361,367 ----
  				 * If this is a 0407 style object, the text
  				 * and data are loaded together.
  				 */
! 				if (exec.a_magic != A_MAGIC1) {
  					segoff += (off_t) exec.a_text;
  					if (overlaid)
  						for (i = 0; i < NOVL; i++)
***************
*** 539,545 ****
  
  unsigned
  btoc(nclicks)
! 	unsigned nclicks;
  {
  	return((unsigned)(((((long) nclicks) + ((long) 63)) >> 6)));
  }
--- 558,578 ----
  
  unsigned
  btoc(nclicks)
! 	register unsigned nclicks;
  {
  	return((unsigned)(((((long) nclicks) + ((long) 63)) >> 6)));
+ }
+ 
+ char *
+ itoa(i)
+ 	register int i;
+ {
+ 	static char x[8];
+ 	register char *cp = x+8;
+ 
+ 	do {
+ 		*--cp = (i % 10) + '0';
+ 		i /= 10;
+ 	} while (i);
+ 	return(cp);
  }
*** /old/src/sys/pdpstand/br.c	Fri Aug 26 14:25:30 1988
--- /usr/src/sys/pdpstand/br.c	Sun Apr 21 00:05:45 1991
***************
*** 3,17 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)br.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  /*
!  * br03-like disk driver
!  *  	modified to handle EATON 1537 and 1711 controllers with
!  *	T300, T200, T80 and T50 drives.  NOTE: the boot block is
!  *	hard coded to 32 sec/trk and 19 trk/cyl because he can't
!  *	be made big enough to autosize like this program can.
   */
  
  #include "../h/param.h"
--- 3,15 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)br.c	2.0 (2.11BSD) 4/20/91
   */
  
  /*
!  * rp03-like disk driver
!  *  	modified to handle BR 1537 and 1711 controllers with
!  *	T300, T200, T80 and T50 drives.
   */
  
  #include "../h/param.h"
***************
*** 19,49 ****
  #include "../pdpuba/brreg.h"
  #include "saio.h"
  
! #define BRADDR ((struct brdevice *) 0176710)
! 
  #define	SEC22	02400	/* T200 or T50 */
  #define CYL5	01400	/* T80 or T50 */
  
! int	brsctrk[8], brtrkcyl[8];
  
  brstrategy(io, func)
  	register struct iob *io;
  {
  	int com, cn, tn, sn, unit, sectrk, trkcyl, ctr;
  
  	/* if we haven't gotten the characteristics yet, do so now. */
! 	trkcyl = brtrkcyl[unit = io->i_unit];
! 	if (!(sectrk = brsctrk[unit])) {
! 		/* give a home seek command, then wait for complete */
! 		BRADDR->brcs.w = (unit << 8) | BR_HSEEK | BR_GO;
  		ctr = 0;
! 		while ((BRADDR->brcs.w & BR_RDY) == 0 && --ctr)
  			continue;
! 		if (BRADDR->brcs.w & BR_HE) {
! 			printf("br%d not ready\n", unit);
  			return(-1);
  		}
! 		com = BRADDR->brae;
  		if (com & SEC22)
  			sectrk = 22;
  		else
--- 17,59 ----
  #include "../pdpuba/brreg.h"
  #include "saio.h"
  
! #define	NBR	2
  #define	SEC22	02400	/* T200 or T50 */
  #define CYL5	01400	/* T80 or T50 */
  
! 	struct	brdevice *BRcsr[NBR + 1] =
! 		{
! 		(struct brdevice *)0176710,
! 		(struct brdevice *)0,
! 		(struct brdevice *)-1
! 		};
  
+ int	brsctrk[NBR][8], brtrkcyl[NBR][8];
+ 
  brstrategy(io, func)
  	register struct iob *io;
  {
+ 	register struct brdevice *braddr;
+ 	register int ctlr;
  	int com, cn, tn, sn, unit, sectrk, trkcyl, ctr;
  
+ 	unit = UNITn(io->i_unit);
+ 	ctlr = CTLRn(io->i_unit);
+ 	braddr = BRcsr[ctlr];
+ 
  	/* if we haven't gotten the characteristics yet, do so now. */
! 	trkcyl = brtrkcyl[ctlr][unit];
! 	if (!(sectrk = brsctrk[ctlr][unit])) {
! 		/* give a home seek command, then wait for complete */
! 		braddr->brcs.w = (unit << 8) | BR_HSEEK | BR_GO;
  		ctr = 0;
! 		while ((braddr->brcs.w & BR_RDY) == 0 && --ctr)
  			continue;
! 		if (braddr->brcs.w & BR_HE) {
! 			printf("br%d,%d not ready\n", ctlr,unit);
  			return(-1);
  		}
! 		com = braddr->brae;
  		if (com & SEC22)
  			sectrk = 22;
  		else
***************
*** 52,82 ****
  			trkcyl = 5;
  		else
  			trkcyl = 19;
! 		brsctrk[unit] = sectrk;
! 		brtrkcyl[unit] = trkcyl;
  	}
  	cn = io->i_bn/(sectrk * trkcyl);
  	sn = io->i_bn%(sectrk * trkcyl);
  	tn = sn/sectrk;
  	sn = sn%sectrk;
! 	BRADDR->brcs.w = (unit<<8);
! 	BRADDR->brda = (tn<<8) | sn;
! 	BRADDR->brca = cn;
! 	BRADDR->brba = io->i_ma;
! 	BRADDR->brwc = -(io->i_cc>>1);
! 	BRADDR->brae = segflag;
  	com = (segflag<<4)|BR_GO;
  	if (func == READ)
  		com |= BR_RCOM;
  	else
  		com |= BR_WCOM;
! 	BRADDR->brcs.w |= com;
! 	while ((BRADDR->brcs.w& BR_RDY)==0)
  		continue;
! 	if (BRADDR->brcs.w < 0) {	/* error bit */
! 		printf("disk error: cyl=%d track=%d sect=%d er=%o ds=%o\n",
! 		    cn, tn, sn, BRADDR->brer, BRADDR->brds);
  		return(-1);
  	}
  	return(io->i_cc);
  }
--- 62,98 ----
  			trkcyl = 5;
  		else
  			trkcyl = 19;
! 		brsctrk[ctlr][unit] = sectrk;
! 		brtrkcyl[ctlr][unit] = trkcyl;
  	}
  	cn = io->i_bn/(sectrk * trkcyl);
  	sn = io->i_bn%(sectrk * trkcyl);
  	tn = sn/sectrk;
  	sn = sn%sectrk;
! 	braddr->brcs.w = (unit<<8);
! 	braddr->brda = (tn<<8) | sn;
! 	braddr->brca = cn;
! 	braddr->brba = io->i_ma;
! 	braddr->brwc = -(io->i_cc>>1);
! 	braddr->brae = segflag;
  	com = (segflag<<4)|BR_GO;
  	if (func == READ)
  		com |= BR_RCOM;
  	else
  		com |= BR_WCOM;
! 	braddr->brcs.w |= com;
! 	while ((braddr->brcs.w& BR_RDY)==0)
  		continue;
! 	if (braddr->brcs.w < 0) {	/* error bit */
! 		printf("br%d,%d err: cy=%d tr=%d sc=%d er=%o ds=%o\n",
! 		    ctlr, unit, cn, tn, sn, braddr->brer, braddr->brds);
  		return(-1);
  	}
  	return(io->i_cc);
+ }
+ 
+ bropen(io)
+ 	struct iob *io;
+ {
+ 	return(genopen(NBR, io));
  }
*** /old/src/sys/pdpstand/conf.c	Mon Aug 20 13:53:26 1990
--- /usr/src/sys/pdpstand/conf.c	Tue Apr 23 10:39:58 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)c.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  #include "../h/param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)conf.c	2.0 (2.11BSD) 4/20/91
   */
  
  #include "../h/param.h"
***************
*** 26,32 ****
  devopen(io)
  	register struct iob *io;
  {
! 	(*devsw[io->i_ino.i_dev].dv_open)(io);
  }
  
  devclose(io)
--- 26,32 ----
  devopen(io)
  	register struct iob *io;
  {
! 	return((*devsw[io->i_ino.i_dev].dv_open)(io));
  }
  
  devclose(io)
***************
*** 37,67 ****
  
  nullsys()
  {
  }
  
! int	xpstrategy();
! int	brstrategy();
! int	rkstrategy();
! int	hkstrategy();
! int	rlstrategy();
! int	sistrategy();
! int	rastrategy(), raopen(), raclose();
! int	tmstrategy(), tmrew(), tmopen();
! int	htstrategy(), htopen(), htclose();
! int	tsstrategy(), tsopen(), tsclose();
! int	tmscpstrategy(), tmscpopen(), tmscpclose();
  
  struct devsw devsw[] = {
! 	"xp",	xpstrategy,	nullsys,	nullsys,
! 	"br",	brstrategy,	nullsys,	nullsys,
! 	"rk",	rkstrategy,	nullsys,	nullsys,
! 	"hk",	hkstrategy,	nullsys,	nullsys,
! 	"rl",	rlstrategy,	nullsys,	nullsys,
! 	"si",	sistrategy,	nullsys,	nullsys,
! 	"ra",	rastrategy,	raopen,		raclose,
! 	"tm",	tmstrategy,	tmopen,		tmrew,
! 	"ht",	htstrategy,	htopen,		htclose,
! 	"ts",	tsstrategy,	tsopen,		tsclose,
! 	"tms",  tmscpstrategy,	tmscpopen,	tmscpclose,
  	0,	0,		0,		0,
  };
--- 37,97 ----
  
  nullsys()
  {
+ 	return(-1);
  }
  
! extern	int	xpstrategy(), xpopen();
! extern	int	brstrategy(), bropen();
! extern	int	rkstrategy(), rkopen();
! extern	int	hkstrategy(), hkopen();
! extern	int	rlstrategy(), rlopen();
! extern	int	sistrategy(), siopen();
! extern	int	rastrategy(), raopen(), raclose();
! extern	int	tmstrategy(), tmopen(), tmclose();
! extern	int	htstrategy(), htopen(), htclose();
! extern	int	tsstrategy(), tsopen(), tsclose();
! extern	int	tmscpstrategy(), tmscpopen(), tmscpclose();
  
+ extern	caddr_t	*XPcsr[], *BRcsr[], *RKcsr[], *HKcsr[], *RLcsr[];
+ extern	caddr_t	*SIcsr[], *RAcsr[], *TMcsr[], *HTcsr[], *TScsr[], *TMScsr[];
+ 
+ /*
+  * NOTE!  This table must be in major device number order.  See /sys/pdp/conf.c
+  *	  for the major device numbers.
+ */
+ 
  struct devsw devsw[] = {
! 	"ht",	htstrategy,	htopen,		htclose,	HTcsr, /* 0 */
! 	"tm",	tmstrategy,	tmopen,		tmclose,	TMcsr, /* 1 */
! 	"ts",	tsstrategy,	tsopen,		tsclose,	TScsr, /* 2 */
! 	"ram",	nullsys,	nullsys,	nullsys,	0,     /* 3 */
! 	"hk",	hkstrategy,	hkopen,		nullsys,	HKcsr, /* 4 */
! 	"ra",	rastrategy,	raopen,		raclose,	RAcsr, /* 5 */
! 	"rk",	rkstrategy,	rkopen,		nullsys,	RKcsr, /* 6 */
! 	"rl",	rlstrategy,	rlopen,		nullsys,	RLcsr, /* 7 */
! 	"rx",	nullsys,	nullsys,	nullsys,	0,     /* 8 */
! 	"si",	sistrategy,	siopen,		nullsys,	SIcsr, /* 9 */
! 	"xp",	xpstrategy,	xpopen,		nullsys,	XPcsr, /* 10 */
! 	"br",	brstrategy,	bropen,		nullsys,	BRcsr, /* 11 */
! 	"tms",  tmscpstrategy,	tmscpopen,	tmscpclose,	TMScsr,/* 12 */
  	0,	0,		0,		0,
  };
+ 
+ 	int	ndevsw = (sizeof (devsw) / sizeof (devsw[0])) - 1;
+ 
+ 	char	ADJcsr[] =
+ 		{
+ 		0,	/* HT = 0 */
+ 		2,	/* TM = 1 */
+ 		2,	/* TS = 2 */
+ 		0,	/* RAM = 3 */
+ 		0,	/* HK = 4 */
+ 		0,	/* RA = 5 */
+ 		4,	/* RK = 6 */
+ 		0,	/* RL = 7 */
+ 		0,	/* RX = 8 */
+ 		0,	/* XP/SI = 9 */
+ 		0,	/* XP = 10 */
+ 		4,	/* BR =11 */
+ 		0,	/* TMS = 12 */
+ 		};
*** /old/src/sys/pdpstand/hk.c	Fri Aug 19 11:52:23 1988
--- /usr/src/sys/pdpstand/hk.c	Sun Apr 21 00:06:35 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)hk.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)hk.c	2.0 (2.11BSD) 4/20/91
   */
  
  /*
***************
*** 15,63 ****
  #include "../pdpuba/hkreg.h"
  #include "saio.h"
  
! 
! #define	HKADDR	((struct hkdevice *)0177440)
! 
! #define	NHK	8
  #define	NSECT	22
  #define	NTRAC	3
  
! int hk_drvtyp[NHK];
! char hk_mntflg[NHK];
  
  
  hkstrategy(io, func)
  	register struct iob *io;
  {
  	register unit, com;
! 	register i;
  	daddr_t bn;
! 	int sn, cn, tn;
  
! 	unit = io->i_unit;
! 	if (hk_mntflg[unit] != '1') {
! 		hk_drvtyp[unit] = 0;
! 		HKADDR->hkcs2 = unit;
! 		HKADDR->hkcs1 = HK_SELECT|HK_GO;
! 		while ((HKADDR->hkcs1 & HK_CRDY) == 0)
  			continue;
! 		if (HKADDR->hkcs1 & HK_CERR && HKADDR->hker & HKER_DTYE) {
! 			hk_drvtyp[unit] = 02000;
  		}
! 		hk_mntflg[unit] = '1';
  	}
  	bn = io->i_bn;
! 	HKADDR->hkcs2 = HKCS2_SCLR;
! 	while ((HKADDR->hkcs1 & HK_CRDY) == 0)
  		continue;
! 	HKADDR->hkcs2 = unit;
! 	HKADDR->hkcs1 = hk_drvtyp[unit]|HK_SELECT|HK_GO;
! 	while ((HKADDR->hkcs1 & HK_CRDY) == 0)
  		continue;
  
! 	if ((HKADDR->hkds & HKDS_VV) == 0) {
! 		HKADDR->hkcs1 = hk_drvtyp[unit]|HK_PACK|HK_GO;
! 		while ((HKADDR->hkcs1 & HK_CRDY) == 0)
  			continue;
  	}
  	cn = bn/(NSECT*NTRAC);
--- 15,68 ----
  #include "../pdpuba/hkreg.h"
  #include "saio.h"
  
! #define	NHK	2
  #define	NSECT	22
  #define	NTRAC	3
  
! 	struct	hkdevice *HKcsr[NHK + 1] =
! 		{
! 		(struct hkdevice *)0177440,
! 		(struct hkdevice *)0,
! 		(struct hkdevice *)-1
! 		};
  
+ int hk_drvtyp[NHK][8];
+ char hk_mntflg[NHK][8];
  
  hkstrategy(io, func)
  	register struct iob *io;
  {
  	register unit, com;
! 	register struct hkdevice *hkaddr;
  	daddr_t bn;
! 	int sn, cn, tn, ctlr;
  
! 	unit = UNITn(io->i_unit);
! 	ctlr = CTLRn(io->i_unit);
! 	hkaddr = HKcsr[ctlr];
! 	if (hk_mntflg[ctlr][unit] != '1') {
! 		hk_drvtyp[ctlr][unit] = 0;
! 		hkaddr->hkcs2 = unit;
! 		hkaddr->hkcs1 = HK_SELECT|HK_GO;
! 		while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  			continue;
! 		if (hkaddr->hkcs1 & HK_CERR && hkaddr->hker & HKER_DTYE) {
! 			hk_drvtyp[ctlr][unit] = 02000;
  		}
! 		hk_mntflg[ctlr][unit] = '1';
  	}
  	bn = io->i_bn;
! 	hkaddr->hkcs2 = HKCS2_SCLR;
! 	while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  		continue;
! 	hkaddr->hkcs2 = unit;
! 	hkaddr->hkcs1 = hk_drvtyp[ctlr][unit]|HK_SELECT|HK_GO;
! 	while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  		continue;
  
! 	if ((hkaddr->hkds & HKDS_VV) == 0) {
! 		hkaddr->hkcs1 = hk_drvtyp[ctlr][unit]|HK_PACK|HK_GO;
! 		while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  			continue;
  	}
  	cn = bn/(NSECT*NTRAC);
***************
*** 65,88 ****
  	tn = sn/NSECT;
  	sn = sn%NSECT;
  
! 	HKADDR->hkcyl = cn;
! 	HKADDR->hkda = (tn<<8) | sn;
! 	HKADDR->hkba = io->i_ma;
! 	HKADDR->hkwc = -(io->i_cc>>1);
! 	com = hk_drvtyp[unit]|(segflag << 8) | HK_GO;
  	if (func == READ)
  		com |= HK_READ;
  	else if (func == WRITE)
  		com |= HK_WRITE;
! 	HKADDR->hkcs1 = com;
  
! 	while ((HKADDR->hkcs1 & HK_CRDY) == 0)
  		continue;
  
! 	if (HKADDR->hkcs1 & HK_CERR) {
! 		printf("disk error: cyl=%d track=%d sect=%d cs2=%d err=%o\n",
! 			cn, tn, sn, HKADDR->hkcs2, HKADDR->hker);
  		return(-1);
  	}
  	return(io->i_cc);
  }
--- 70,99 ----
  	tn = sn/NSECT;
  	sn = sn%NSECT;
  
! 	hkaddr->hkcyl = cn;
! 	hkaddr->hkda = (tn<<8) | sn;
! 	hkaddr->hkba = io->i_ma;
! 	hkaddr->hkwc = -(io->i_cc>>1);
! 	com = hk_drvtyp[ctlr][unit]|(segflag << 8) | HK_GO;
  	if (func == READ)
  		com |= HK_READ;
  	else if (func == WRITE)
  		com |= HK_WRITE;
! 	hkaddr->hkcs1 = com;
  
! 	while ((hkaddr->hkcs1 & HK_CRDY) == 0)
  		continue;
  
! 	if (hkaddr->hkcs1 & HK_CERR) {
! 		printf("hk%d,%d err: cy=%d tr=%d sc=%d cs2=%d er=%o\n",
! 			ctlr, unit, cn, tn, sn, hkaddr->hkcs2, hkaddr->hker);
  		return(-1);
  	}
  	return(io->i_cc);
+ }
+ 
+ hkopen(io)
+ 	struct iob *io;
+ {
+ 	return(genopen(NHK, io));
  }
*** /old/src/sys/pdpstand/ht.c	Fri Aug 19 11:53:51 1988
--- /usr/src/sys/pdpstand/ht.c	Sun Apr 21 00:07:30 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ht.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ht.c	2.0 (2.11BSD) 4/20/91
   */
  
  /*
***************
*** 15,27 ****
  #include "../pdpuba/htreg.h"
  #include "saio.h"
  
! 
! #define	HTADDR	((struct htdevice *)0172440)
! 
! #define	TUUNIT(dev)	(minor(dev) & 03)
  #define	H_NOREWIND	004		/* not used in stand alone driver */
  #define	H_1600BPI	010
  
  extern int tapemark;	/* flag to indicate tapemark encountered
  			   (see sys.c as to how it's used) */
  
--- 15,30 ----
  #include "../pdpuba/htreg.h"
  #include "saio.h"
  
! #define	NHT		2
  #define	H_NOREWIND	004		/* not used in stand alone driver */
  #define	H_1600BPI	010
  
+ 	struct	htdevice *HTcsr[NHT + 1] =
+ 		{
+ 		(struct htdevice *)0172440,
+ 		(struct htdevice *)0,
+ 		(struct htdevice *)-1
+ 		};
  extern int tapemark;	/* flag to indicate tapemark encountered
  			   (see sys.c as to how it's used) */
  
***************
*** 29,36 ****
--- 32,42 ----
  	register struct iob *io;
  {
  	register skip;
+ 	register int ctlr = CTLRn(io->i_unit);
  	int i;
  
+ 	if (genopen(NHT, io) < 0)
+ 		return(-1);
  	htstrategy(io, HT_REW);
  	skip = io->i_boff;
  	while (skip--) {
***************
*** 42,47 ****
--- 48,54 ----
  			continue;
  		htstrategy(io, HT_SENSE);
  	}
+ 	return(0);
  }
  
  htclose(io)
***************
*** 53,71 ****
  htstrategy(io, func)
  	register struct iob *io;
  {
! 	register unit, com, errcnt;
  
! 	unit = io->i_unit;
  	errcnt = 0;
  retry:
! 	htquiet();
  
! 	HTADDR->httc =
! 		((unit&H_1600BPI) ? HTTC_1600BPI : HTTC_800BPI)
! 		| HTTC_PDP11 | TUUNIT(unit);
! 	HTADDR->htba = io->i_ma;
! 	HTADDR->htfc = -io->i_cc;
! 	HTADDR->htwc = -(io->i_cc >> 1);
  	com = ((segflag) << 8) | HT_GO;
  	if (func == READ)
  		com |= HT_RCOM;
--- 60,85 ----
  htstrategy(io, func)
  	register struct iob *io;
  {
! 	register unit, com;
! 	int errcnt, ctlr;
! 	register struct htdevice *htaddr;
  
! 	unit = UNITn(io->i_unit);
! 	ctlr = CTLRn(io->i_unit);
! 	htaddr = HTcsr[ctlr];
  	errcnt = 0;
  retry:
! 	while ((htaddr->htcs1 & HT_RDY) == 0)
! 		continue;
! 	while (htaddr->htfs & HTFS_PIP)
! 		continue;
  
! 	htaddr->httc =
! 		((io->i_unit&H_1600BPI) ? HTTC_1600BPI : HTTC_800BPI)
! 		| HTTC_PDP11 | unit;
! 	htaddr->htba = io->i_ma;
! 	htaddr->htfc = -io->i_cc;
! 	htaddr->htwc = -(io->i_cc >> 1);
  	com = ((segflag) << 8) | HT_GO;
  	if (func == READ)
  		com |= HT_RCOM;
***************
*** 72,95 ****
  	else if (func == WRITE)
  		com |= HT_WCOM;
  	else if (func == HT_SREV) {
! 		HTADDR->htfc = -1;
! 		HTADDR->htcs1 = com | HT_SREV;
  		return(0);
  	} else
  		com |= func;
! 	HTADDR->htcs1 = com;
! 	while ((HTADDR->htcs1 & HT_RDY) == 0)
  		continue;
! 	if (HTADDR->htfs & HTFS_TM) {
  		tapemark = 1;
! 		htinit();
  		return(0);
  	}
! 	if (HTADDR->htcs1 & HT_TRE) {
  		if (errcnt == 0)
! 			printf("\nHT unit %d tape error: cs2=%o, er=%o",
! 			    unit, HTADDR->htcs2, HTADDR->hter);
! 		htinit();
  		if (errcnt++ == 10) {
  			printf("\n(FATAL ERROR)\n");
  			return(-1);
--- 86,109 ----
  	else if (func == WRITE)
  		com |= HT_WCOM;
  	else if (func == HT_SREV) {
! 		htaddr->htfc = -1;
! 		htaddr->htcs1 = com | HT_SREV;
  		return(0);
  	} else
  		com |= func;
! 	htaddr->htcs1 = com;
! 	while ((htaddr->htcs1 & HT_RDY) == 0)
  		continue;
! 	if (htaddr->htfs & HTFS_TM) {
  		tapemark = 1;
! 		htinit(htaddr);
  		return(0);
  	}
! 	if (htaddr->htcs1 & HT_TRE) {
  		if (errcnt == 0)
! 			printf("\nHT%d,%d err: cs2=%o, er=%o",
! 			    ctlr, unit, htaddr->htcs2, htaddr->hter);
! 		htinit(htaddr);
  		if (errcnt++ == 10) {
  			printf("\n(FATAL ERROR)\n");
  			return(-1);
***************
*** 97,124 ****
  		htstrategy(io, HT_SREV);
  		goto retry;
  	}
! 	if (errcnt)
! 		printf("\n(RECOVERED by retry)\n");
! 	return(io->i_cc+HTADDR->htfc);
  }
  
! htinit()
  {
  	register int omt, ocs2;
  
! 	omt = HTADDR->httc & 03777;
! 	ocs2 = HTADDR->htcs2 & 07;
  
! 	HTADDR->htcs2 = HTCS2_CLR;
! 	HTADDR->htcs2 = ocs2;
! 	HTADDR->httc = omt;
! 	HTADDR->htcs1 = HT_DCLR|HT_GO;
! }
! 
! htquiet()
! {
! 	while ((HTADDR->htcs1 & HT_RDY) == 0)
! 		continue;
! 	while (HTADDR->htfs & HTFS_PIP)
! 		continue;
  }
--- 111,129 ----
  		htstrategy(io, HT_SREV);
  		goto retry;
  	}
! 	return(io->i_cc+htaddr->htfc);
  }
  
! htinit(htaddr)
! 	register struct htdevice *htaddr;
  {
  	register int omt, ocs2;
  
! 	omt = htaddr->httc & 03777;
! 	ocs2 = htaddr->htcs2 & 07;
  
! 	htaddr->htcs2 = HTCS2_CLR;
! 	htaddr->htcs2 = ocs2;
! 	htaddr->httc = omt;
! 	htaddr->htcs1 = HT_DCLR|HT_GO;
  }
*** /old/src/sys/pdpstand/maketape.c	Wed Dec 19 10:18:27 1990
--- /usr/src/sys/pdpstand/maketape.c	Sun Apr 28 22:56:06 1991
***************
*** 4,10 ****
   * specifies the terms and conditions for redistribution.
   *
   *	@(#)maketape.c	1.1 (2.10BSD Berkeley) 12/1/86
!  *			    (2.11BSD Contel) 10/1/90
   *		TU81s didn't like open/close/write at 1600bpi, use
   *		ioctl to write tape marks instead.
   */
--- 4,10 ----
   * specifies the terms and conditions for redistribution.
   *
   *	@(#)maketape.c	1.1 (2.10BSD Berkeley) 12/1/86
!  *			    (2.11BSD Contel) 4/20/91
   *		TU81s didn't like open/close/write at 1600bpi, use
   *		ioctl to write tape marks instead.
   */
***************
*** 30,36 ****
  	int argc;
  	char *argv[];
  {
! 	int i, j = 0, k = 0;
  	FILE *mf;
  
  	if (argc != 3) {
--- 30,36 ----
  	int argc;
  	char *argv[];
  {
! 	register int i, j = 0, k = 0;
  	FILE *mf;
  
  	if (argc != 3) {
***************
*** 91,96 ****
--- 91,97 ----
  			}
  		}
  		if (cnt>0) {
+ 			j++;
  			bzero(buf + cnt, recsz - cnt);
  			if (write(mt, buf, recsz) < 0) {
  				perror(argv[1]);
*** /old/src/sys/pdpstand/mtboot.s	Fri Sep  2 21:02:25 1988
--- /usr/src/sys/pdpstand/mtboot.s	Fri May  3 23:55:21 1991
***************
*** 1,39 ****
  /*
   * Primary tape boot program to load and execute secondary boot.
   *
!  * Two copies of the primary boot are stored in the first and second blocks
!  * of the first tape file (some boot proms execute the second block when
   * booting a tape).  The secondary boot is also stored in the first tape
!  * file, starting at block #3.
   *
-  * Note that this boot has been hacked to death in order to squeeze three
-  * primary tape boots in for the HT, TM, and TS.  It turns out that this
-  * wasn't as hard as one might think since the original primary tape boots
-  * were overly ambitious in their generality.  Needless to say, that
-  * generality is no longer present ...
-  *
-  * Note that while we are prepared to compile multiple different primary
-  * bootstraps to support different tape densities (BPI), we don't bother
-  * ifdef'ing out the various drivers which don't support the defined
-  * BPI.  They all fit in 512 bytes now, so who cares?
-  *
   * Also note that the struct exec header must be removed from this bootstrap.
!  * This needs to be done so taking the addresses of the various tape rewind
!  * and read functions will work.
   */
  NEWLOC	= [48.*1024.]			/ we relocate ourselves to this address
  
! #ifndef BPI
! #	define	BPI	1600
! #endif
  
- busvec	= 04				/ bus error trap vector
- hipri	= 0340				/ PS slp 7
- 
  a_text	= 02				/ a_text (struct exec) field offset
  a_data	= 04				/ a_data (struct exec) field offset
  
! trew	= r5				/ pointer at trew routine
  tread	= r4				/ pointer at tread routine
  blkcnt	= r3				/ number of blocks to read
  memaddr	= r2				/ memory location to read into
--- 1,35 ----
  /*
   * Primary tape boot program to load and execute secondary boot.
   *
!  * This is a universal tape boot which can handle HT, TM, TS and TMSCP
!  * tapes.  This boot is FULL.  Some of the more extended error
!  * checking had to be left out to get all the drivers to fit.
!  *
!  * Two copies of the primary boot are stored in the first and second records
!  * of the first tape file (some boot proms execute the second one when
   * booting a tape).  The secondary boot is also stored in the first tape
!  * file, starting at record #3.
   *
   * Also note that the struct exec header must be removed from this bootstrap.
!  * This needs to be done so taking the address of the tape read and rewind
!  * functions will work.
!  *
!  * Due to size constraints and the rather destructive way in which
!  * all the registers are used, this boot does not support the 
!  * "jsr pc,0; br restart" convention.
   */
  NEWLOC	= [48.*1024.]			/ we relocate ourselves to this address
+ OURSIZE = 512.				/ assume we are up to this size
  
! HT_MAJOR = 0				/ major device number from bdevsw[]
! TM_MAJOR = 1
! TS_MAJOR = 2
! TMS_MAJOR = 12.
  
  a_text	= 02				/ a_text (struct exec) field offset
  a_data	= 04				/ a_data (struct exec) field offset
  
! csr	= r5				/ saved csr of boot device
  tread	= r4				/ pointer at tread routine
  blkcnt	= r3				/ number of blocks to read
  memaddr	= r2				/ memory location to read into
***************
*** 45,86 ****
  	br	1f			/ "   "    "     "
  1:
  	mov	$NEWLOC,sp		/ give ourselves a stack to work with
! 	cmp	pc,sp			/ are we running above the stack?
! 	bhis	3f			/ [yes, no need to relocate ourselves]
! 	mov	sp,r1			/ no, we gotta move ourselves up
! 	clr	r0			/ [assume we're at location 0 now]
! 	mov	$256.,r2		/ primary boot is at most 256 words
  2:
! 	mov	(r0)+,(r1)+		/ move primary boot to just above
! 	sob	r2,2b			/   the stack
! 	jmp	(sp)			/ reexecute ourselves at our new loc
  3:
! 	mov	$hipri,*$busvec+2	/ take bus errors at high priority
! httest:
! 	mov	$1f,*$busvec+0		/ HT htcs1 register present?
! 	tst	*$htcs1			/   yes, if we got here: set trew and
! 	mov	$htrew,trew		/   tread routines and continue
! 	mov	$htread,tread
! 	br	readit
! 1:
! tmtest:
! 	mov	$1f,*$busvec+0		/ TM tmmr register present? (the TM
! 	tst	*$tmmr			/   TS controllers use the same CSR
! 	mov	$tmread,tread		/   address, but tmmr is above the
! 	mov	$tmrew,trew		/   last CSR address of the TS ...)
! 	br	readit
! 1:
! tstest:
! 	mov	$tsread,tread		/ else it has to be a TS ...
! 	mov	$tsrew,trew
  readit:
! 	jsr	pc,*trew		/ rewind the tape
! 	mov	$2,blkcnt		/ skip past the two copies of our
! 	clr	memaddr			/   self on the tape (throw them
! 	jsr	pc,*tread		/   at location zero)
! 	mov	$1,blkcnt		/ and read the first block
! 	clr	memaddr			/   to location 0 ...
! 	jsr	pc,*tread
  
  	mov	*$a_text,blkcnt		/ compute remaining amount to read:
  	add	*$a_data,blkcnt		/   (a_text + a_data
--- 41,88 ----
  	br	1f			/ "   "    "     "
  1:
  	mov	$NEWLOC,sp		/ give ourselves a stack to work with
! 	clr	r4
! 	mov	sp,r5
! 	mov	$OURSIZE\/2,r3		/ primary boot size in words
  2:
! 	clr	OURSIZE(r5)		/ clear work area (major & TS/MSCP area)
! 	mov	(r4)+,(r5)+		/ move primary boot to just above
! 	sob	r3,2b			/   the stack
! 	jmp	*$3f			/ bypass the relocation code
  3:
! 	mov	r0,unit			/ save unit number
! 	mov	r1,csr			/ save the csr
! 	cmp	r1,$172440		/ HT is always at this address
! 	beq	common			/ r3 is table index
! 	inc	r3			/ index for TMSCP
! 	cmp	r1,$172522		/ is this a TS?
! 	blo	common			/ no - br, likely TMSCP
! 	cmp	r1,$172522+[7*4]	/ is CSR in the TS range?
! 	bhi	common			/ no, is a TMSCP - br
! 	inc	r3			/ adjust index to TS
! 	mov	(r1),r4			/ save contents of csr in case of a TM
! 	clr	(r1)			/ poke the controller
! /	clr	r2			/ now we delay
! /1:
! /	sob	r2,1b			/ time for TS to run diagnostics
! 2:
! 	tstb	(r1)			/ is controller ready?
! 	bpl	2b			/ no - br
! 	bit	$2000,(r1)		/ TS "address required" bit
! 	bne	common			/ if a TS - br
! 	mov	r4,(r1)			/ is a TM, restore unit/density select
! 	inc	r3			/ make TM index
! common:
! 	movb	table1(r3),major+1	/ save major device number to high byte
! 	asl	r3			/ make a word index
! 	mov	table2(r3),tread	/ fetch read routine address
! 	jsr	pc,*table3(r3)		/ call rewind routine (must preserve r4)
  readit:
! 	clr	memaddr			/ load starting at 0
! 	jsr	pc,*tread		/ skip the two copies of this
! 	jsr	pc,*tread		/ program on the tape
! 	clr	memaddr			/ reset memory address
! 	jsr	pc,*tread		/ read first block of boot
  
  	mov	*$a_text,blkcnt		/ compute remaining amount to read:
  	add	*$a_data,blkcnt		/   (a_text + a_data
***************
*** 88,247 ****
  	ash	$-9.,blkcnt		/    - 512) [already read one block]
  	bic	$177600,blkcnt		/   / 512 [[unsigned]]
  	beq	done			/ already done if == 0 [not likely]
! 
  	jsr	pc,*tread
  done:
- 	clr	r0			/ strip the a.out header from the
- 	mov	$16.,r1			/   secondary boot by shifting it
  1:					/   down by sizeof(struct exec)
! 	mov	(r1)+,(r0)+
! 	cmp	r1,sp
  	blo	1b
! 	clr	pc			/ jump to location 0 ...
  
  /*
!  *			HT tape driver
   */
! htcs1	= 0172440
! htba	= 0172444
! htfc	= 0172446
! htcs2	= 0172450
! htds	= 0172452
! httc	= 0172472
  
- PIP	= 020000
  RESET	= 040
- MOL	= 010000
- ERR	= 040000
- REV	= 033
  READ	= 071
  REW	= 07
  
- #if BPI == 800
- 	HTBPI	= 01700			/ 800BPI | PDP-11 mode
- #endif
- #if BPI == 1600
- 	HTBPI	= 02300			/ 1600BPI | PDP-11 mode
- #endif
- #if BPI == 6250
- 	HTBPI	= 0			/ just so things assemble right
- #endif
- 
- /*
-  * Read blkcnt tape records into location memaddr.
-  * Side effects:
-  *	blkcnt gets zeroed
-  *	memaddr += 512 * blkcnt
-  *	tape is advanced blkcnt records
-  */
- htread:
- 	jsr	pc,hrrec		/ read tape records until blkcnt
- 	sob	blkcnt,htread		/   goes to 0 ...
- 	rts	pc
- 
- /*
-  * Read one tape record.
-  * Side effects:
-  *	memaddr += 512
-  *	tape is advanced 1 record
-  */
  hrrec:
! 	mov	$htds,r0
! 	tstb	(r0)
! 	bpl	hrrec
! 	bit	$PIP,(r0)
! 	bne	hrrec
! 	bit	$MOL,(r0)
! 	beq	hrrec
! 	mov	$htfc,r0
! 	mov	$-512.,(r0)
! 	mov	memaddr,-(r0)
! 	mov	$-256.,-(r0)
! 	mov	$READ,-(r0)
! 1:
! 	tstb	(r0)
! 	bpl	1b
! 	bit	$ERR,(r0)
! 	bpl	2f
! 	mov	$RESET,*$htcs2
! 	mov	$-1,*$htfc
! 	mov	$REV,(r0)
! 	br	hrrec
! 2:
! 	add	$512.,memaddr
! 	rts	pc
  
  /*
!  * Rewind tape.
!  * Side effects:
!  *	just what the first line says ...
   */
  htrew:
! 	mov	$RESET,*$htcs2
! 	mov	$HTBPI,*$httc
! 	mov	$REW,*$htcs1
! 	rts	pc
  
- 
  /*
!  *			TM tape driver
   */
! tmer	= 172520
! tmcs	= 172522
! tmbc	= 172524
! tmba	= 172526
! tmdb	= 172530
! tmrd	= 172532
! tmmr	= 172534
  
- #if BPI == 800
- 	TMBPI	= 060000
- #endif
- #if BPI == 1600
- 	TMBPI	= 000000		/ Third party TMs only
- #endif
- #if BPI == 6250
- 	TMBPI	= 020000		/ Third party TMs only
- #endif
- 
- /*
-  * Read blkcnt tape records into location memaddr.
-  * Side effects:
-  *	blkcnt gets zeroed
-  *	memaddr += 512 * blkcnt
-  *	tape is advanced blkcnt records
-  */
- tmread:
- 	jsr	pc,tmrrec		/ read tape records until blkcnt
- 	sob	blkcnt,tmread		/   goes to 0 ...
- 	rts	pc
- 
- /*
-  * Read one tape record.
-  * Side effects:
-  *	memaddr += 512
-  *	tape is advanced 1 record
-  */
  tmrrec:
! 	mov	$tmer,r0
! 	bit	$2,(r0)+		/ rewind status
! 	bne	tmrrec
! 	tstb	(r0)+			/ cu ready
! 	bpl	tmrrec
! 	inc 	r0
! 	mov	$-512.,(r0)+		/ byte count
! 	mov	memaddr,(r0)		/ bus address
! 	mov	$tmcs,r0
! 	mov	$TMBPI|3,(r0)		/ read
! 1:
! 	tstb	(r0)
! 	bpl	1b
! 	tst	(r0)+
! 	bpl	2f
! 	mov	$-1,(r0)
! 	mov	$TMBPI|13,-(r0)		/ backspace
! 	br	tmrrec
! 2:
  	add	$512.,memaddr
  	rts	pc
  
--- 90,187 ----
  	ash	$-9.,blkcnt		/    - 512) [already read one block]
  	bic	$177600,blkcnt		/   / 512 [[unsigned]]
  	beq	done			/ already done if == 0 [not likely]
! 2:
  	jsr	pc,*tread
+ 	sob	blkcnt,2b
  done:
  1:					/   down by sizeof(struct exec)
! 	mov	20(blkcnt),(blkcnt)+	/ r3 cleared by loop above
! 	cmp	blkcnt,sp
  	blo	1b
! 	mov	csr,r1			/ put things where 'boot'
! 	mov	unit,r3			/  expects them
! 	bis	major,r3		/ the major device to high byte
! 	clr	pc			/ go to location 0 ... no return
  
  /*
!  *	HT tape driver
   */
! htcs1	= 0				/ offset from base csr
! htwc	= 2
! htba	= 4
! htfc	= 6
! htcs2	= 10
! htds	= 12
! hter	= 14
! httc	= 32
  
  RESET	= 040
  READ	= 071
  REW	= 07
  
  hrrec:
! 	mov	memaddr,htba(csr)
! 	mov	$-256.,htwc(csr)
! 	mov	$READ,(csr)		/ htcs1
! htcmd:
! 	tstb	(csr)			/ controller ready?
! 	bpl	htcmd
! 	tst	htds(csr)		/ drive ready?
! 	bpl	htcmd
! 	tstb	htcs2+1(csr)		/ any controller errors?
! 	bne	ctlerr
! 	bit	$!1000,hter(csr)	/ any drive errors except HTER_FCE?
! 	beq	bumpaddr		/ no, go bump address
! ctlerr:
! 	halt
  
  /*
!  * Rewind tape.  This routine is only done once and must preceed any reads.
   */
  htrew:
! 	tstb	(csr)			/ controller ready?
! 	bpl	htrew			/ no - go try again
! 	mov	htcs2(csr),r1		/ boot unit(formatter) number
! 	bic	$!7,r1			/ only the low bits
! 	mov	httc(csr),r0		/ save format,slave,density
! 	bic	$!3767,r0		/ only the bits we're interested in
! 	mov	$RESET,htcs2(csr)	/ reset controller
! 	movb	r1,htcs2(csr)		/ reselect boot unit(formatter)
! 	mov	r0,httc(csr)		/ reselect density/format/slave(drive)
! 	mov	$REW,(csr)
! 	br	htcmd			/ join common code
  
  /*
!  *	TM tape driver
   */
! tmer	= -2				/ offset from base csr
! tmcs	= 0
! tmbc	= 2
! tmba	= 4
! tmdb	= 6
! tmrd	= 10
! tmmr	= 12
  
  tmrrec:
! 	mov	$-512.,tmbc(csr)	/ bytecount
! 	mov	memaddr,tmba(csr)	/ bus address
! 	mov	$3,r1			/ 'read'
! tmcmd:
! 	mov	(csr),r0
! 	bic	$!63400,r0		/ save the density and unit
! 	bis	r1,r0			/ merge in the function code
! 	mov	r0,(csr)		/ tmcs - give command
! /1:
! /	bit	$100,tmer(csr)		/ unit still selected? (TMER_SELR)
! /	beq	ctlerr			/ nope, go halt
! /	bit	$1,tmer(csr)		/ unit ready? (TMER_TUR)
! /	beq	1b			/ no, keep waiting
! tmtscom:
! 	bit	$100200,(csr)		/ error or ready?
! 	beq	tmtscom			/ neither, keep looking
! 	bmi	ctlerr			/ error - go halt
! 
! bumpaddr:
  	add	$512.,memaddr
  	rts	pc
  
***************
*** 251,337 ****
   *	just what the first line says ...
   */
  tmrew:
! 	mov	$TMBPI|17,*$tmcs
! 	rts	pc
  
- 
  /*
!  *			TS tape driver
!  *
   */
! tsdb = 172520
! tssr  = 172522
  
- TSINIT = 140013
  TSCHAR = 140004
  TSREW  = 102010
  TSREAD = 100001
- TSRETRY = 100401
  
- tsdbuf = NEWLOC + 512.			/ put ts data buffer just after us
- 
- /*
-  * Read blkcnt tape records into location memaddr.
-  * Side effects:
-  *	blkcnt gets zeroed
-  *	memaddr += 512 * blkcnt
-  *	tape is advanced blkcnt records
-  */
- tsread:
- 	jsr	pc,tsrrec		/ read tape records until blkcnt
- 	sob	blkcnt,tsread		/   goes to 0 ...
- 	rts	pc
- 
- /*
-  * Read one tape record.
-  * Side effects:
-  *	memaddr += 512
-  *	tape is advanced 1 record
-  */
  tsrrec:
- 	tstb	tssr
- 	bpl	tsrrec
  	mov	$tsdbuf+6,r0
  	mov	$512.,(r0)
  	clr	-(r0)
  	mov	memaddr,-(r0)
  	mov	$TSREAD,-(r0)
! 	mov	r0,tsdb
! 1:
! 	tstb	tssr
! 	bpl	1b
! 	cmp	$1,tssr
! 	blos	2f
! 	mov	$TSRETRY,(r0)
! 	mov	r0,tsdb
! 	br	1b
! 2:
! 	add	$512.,memaddr
! 	rts	pc
  
  /*
!  * Rewind tape.
   * Side effects:
   *	just what the first line says ...
   */
  tsrew:
! 	tstb	tssr			/ initialize ...
! 	bpl	tsrew
! 	mov	$tsdbuf,r0
! 	mov	$TSCHAR,(r0)+
! 	mov	$tsdbuf+10,(r0)+
! 	clr	(r0)+
! 	mov	$10,(r0)+
! 	mov	r0,(r0)+
! 	clr	(r0)+
! 	mov	$16,(r0)+
! 	mov	$tsdbuf,tsdb
! 1:
! 	tstb	tssr
! 	bpl	1b
  /*
!  * rewind
!  */
! 	mov	$TSREW,tsdbuf
! 	mov	$tsdbuf,tsdb
  	rts	pc
--- 191,352 ----
   *	just what the first line says ...
   */
  tmrew:
! 	mov	$17,r1			/ 'rewind'
! 	br	tmcmd			/ join common code
  
  /*
!  *	TS tape driver
   */
! tsdb = -2				/ offset from ROM supplied address
! tssr = 0
  
  TSCHAR = 140004
  TSREW  = 102010
  TSREAD = 100001
  
  tsrrec:
  	mov	$tsdbuf+6,r0
  	mov	$512.,(r0)
  	clr	-(r0)
  	mov	memaddr,-(r0)
  	mov	$TSREAD,-(r0)
! 	mov	r0,tsdb(csr)
! 	br	tmtscom
  
  /*
!  * Rewind and initialize tape - only done once.
   * Side effects:
   *	just what the first line says ...
   */
  tsrew:
! 	mov	$tsdbuf,tsdb(csr)
! 	br	tmtscom			/ go join common code
! 
! .if [.-start]&2
! 	.blkb	2			/ tsdbuf must be on a mod 4 boundary
! .endif
! tsdbuf:
! 	TSCHAR				/ command
! 	tsdbuf+10			/ buffer address (lo)
! 	0				/ buffer address (hi - always 0)
! 	10				/ length of command buffer
! 
! / from here on is used only at initialization/rewind time.  The Set
! / Charactistics command only looks at the word following the buffer length,
! / part of the TMSCP code is used as the remainder of the characteristics packet.
! 
! 	tsdbuf+10			/ buffer address (lo)
! 	0				/ buffer address (hi - always 0)
! 	16				/ minimum length packet
! 	0				/ characteristics to set (lo byte)
! 
  /*
!  * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.
!  * All Rights Reserved.
!  * Reference "/usr/src/COPYRIGHT" for applicable restrictions.
!  *
!  * ULTRIX-11 Block Zero Bootstrap for TMSCP Magtape
!  *
!  * SCCSID: @(#)tkboot.s	3.0	4/21/86
!  *
!  * Chung_wu Lee		2/8/85
!  *
!  * sms 4/27/91 - merged into universal tape boot
!  * sms 4/12/91 - saved some more space.  the major device number and unit
!  *	number are now passed to the secondary boot along with the csr of
!  *	the booting controller.
!  *
!  * Steven M. Schultz (sms@wlv.imsd.contel.com) Aug 20 1990.  Port to 2.11BSD
! */
! 
! s1	= 4000
! go	= 1
! 
! / TK initialization (and rewind) - only done once
! tkrew:
! 	clr	(csr)+		/ start tk init sequence
! 				/ move pointer to tksa register
! 	mov	$s1,r0		/ set tk state test bit to step 1
! 	mov	$cmdtbl,r1	/ address of init seq table
! 2:
! 	tst	(csr)		/ error ?
! 	bmi	.		/ yes, hang - can't restart !!!
! 	bit	r0,(csr)	/ current step done ?
! 	beq	2b		/ no
! 	mov	(r1)+,(csr)	/ yes, load next step info from table
! 	asl	r0		/ change state test bit to next step
! 	bpl	2b		/ if all steps not done, go back
! 				/ r0 now = 100000, TK_OWN bit
! 	mov	$400,cmdhdr+2	/ tape VCID = 1
! 	mov	$36.,cmdhdr	/ command packet length
! 				/ don't set response packet length,
! 				/ little shakey but it works.
! 				/ unit is already loaded at tkcmd+4
! 	mov	$11,tkcmd+8.	/ on-line command opcode
! 	mov	$20000,tkcmd+10.	/ set clear serious exception
! 	mov	$ring,r2	/ initialize cmd/rsp ring
! 	mov	$tkrsp,(r2)+	/ address of response packet
! 	mov	r0,(r2)+	/ set TK owner
! 	mov	$tkcmd,(r2)+	/ address of command packet
! 	mov	r0,(r2)+	/ set TK owner
! 	mov	-(csr),r0	/ start TK polling
! 3:
! 	jsr	pc,tkready
! 	mov	$tkcmd+8.,r0
! 	mov	$45,(r0)+		/ reposition opcode
! 	mov	$20002,(r0)+		/ set rewind & clear serious exception
! 	clr	(r0)+			/ clear record/object count
! 	clr	(r0)+			/ zzz2
! 	clr	(r0)+			/ clear tape mark count
! tkpoll:
! 	mov	$100000,ring+2		/ set TK owner of response
! 	mov	$100000,ring+6		/ set TK owner of command
! 	mov	(csr),r0		/ start TK polling
! tkready:
! 	tst	ring+2			/ wait for response
! 	bmi	tkready
! 	tstb	tkrsp+10.		/ does returned status = SUCCESS ?
! 	bne	.			/ no, hang
  	rts	pc
+ tkread:
+ 	mov	$tkcmd+8.,r0
+ 	mov	$41,(r0)+		/ read opcode
+ 	mov	$20000,(r0)+		/ set clear serious exception
+ 	mov	$512.,(r0)+		/ byte count
+ 	clr	(r0)+			/ zzz2
+ 	mov	memaddr,(r0)+		/ buffer address
+ 	jsr	pc,bumpaddr		/ bump address
+ 	br	tkpoll			/ wait for response
+ 
+ cmdtbl:
+ 	100000			/ TK_ERR, init step 1
+ 	ring			/ address of ringbase
+ 	0			/ hi ringbase address
+ 	go			/ TK go bit
+ 
+ table1:
+ 	.byte HT_MAJOR
+ 	.byte TMS_MAJOR
+ 	.byte TS_MAJOR
+ 	.byte TM_MAJOR
+ table2:
+ 	hrrec
+ 	tkread
+ 	tsrrec
+ 	tmrrec
+ table3:
+ 	htrew
+ 	tkrew
+ 	tsrew
+ 	tmrew
+ end:
+ 
+ major = NEWLOC+OURSIZE
+ cmdint = major+2		/ TMSCP stuff
+ rspint = cmdint+2.
+ ring = rspint+2.
+ rsphdr = ring+8.
+ tkrsp = rsphdr+4.
+ cmdhdr = tkrsp+48.
+ tkcmd = cmdhdr+4.
+ unit = tkcmd+4
