Subject: Part 7a of 22 /boot,/mdec,[T]MSCP updates
Index:	/sys/<many>, /usr/src/etc/<several> 2.11BSD

Description:
Repeat-By:
Fix:
	See part 0 (the README) for the Description, the Reason and
	the instructions on how update your system.

This is part 7a of 22 

Because part 7 was so large it was split into two (still large)
pieces.  The two parts (7a and 7b) should be joined together with no 
intervening text.

/sys/pdpstand/* was basically rewritten.  All of the drivers were
modified to support at least 2 controllers.  The device array in
'conf.c' was placed in major device number order (see bdevsw[] in
/sys/pdp/conf.c)

The files tmscpboot.s and tmscptape.data should be removed, they
are no longer needed now that 'mtboot.s' can handle all 4 controller
types.

The switch register is no longer examined for cpu or drive type (xp)
information.

The return protocol for the standalone utilities was changed to prevent
slightly oversized programs from wiping out the 'rtt' information stored
at 0140000.  A higher address at the top (rather than the bottom) of the
stack is now used.

*** /usr/src/sys/pdpstand.old/M.s	Fri Aug 19 12:03:46 1988
--- /usr/src/sys/pdpstand/M.s	Tue Apr 23 10:21:47 1991
***************
*** 1,9 ****
  /
  /	SCCS id	@(#)M.s	1.7 (Berkeley)	7/11/83
  /
  / Startup code for two-stage bootstrap with support for autoboot.
! / Supports 11/40, 11/45, 11/70, 11/23, 11/23+I/O map (11/24), 11/73
! / and similar machines.
  
  systrap = 104400	/ trap 0
  
--- 1,9 ----
  /
  /	SCCS id	@(#)M.s	1.7 (Berkeley)	7/11/83
+ /		@(#)M.s	2.0 (2.11BSD)	4/12/91 (sms@wlv.imsd.contel.com)
  /
  / Startup code for two-stage bootstrap with support for autoboot.
! / Supports 11/45, 11/70, 11/53, 11/73, 11/83, 11/84, 11/93, 11/94
  
  systrap = 104400	/ trap 0
  
***************
*** 14,21 ****
  ENDCORE=	160000		/ end of core, mem. management off
  SZFLAGS=	6		/ size of boot flags
  BOOTOPTS=	2		/ location of options, bytes below ENDCORE
! BOOTDEV=	4
! CHECKWORD=	6
  
  .globl	_end
  .globl	_main,_ubmapset
--- 14,21 ----
  ENDCORE=	160000		/ end of core, mem. management off
  SZFLAGS=	6		/ size of boot flags
  BOOTOPTS=	2		/ location of options, bytes below ENDCORE
! BOOTDEV=	4		/ makedev(major,unit)
! CHECKWORD=	6		/ ~BOOTOPTS
  
  .globl	_end
  .globl	_main,_ubmapset
***************
*** 54,59 ****
--- 54,60 ----
  	mov	r4,_bootopts
  	mov	r3,_bootdev
  	mov	r2,_checkword
+ 	mov	r1,_bootcsr		/ 'boot' will apply ADJcsr[] correction
  /clobber any boot flags left in memory
  	clr	ENDCORE-BOOTOPTS
  	clr	ENDCORE-BOOTDEV
***************
*** 60,101 ****
  	clr	ENDCORE-CHECKWORD
  /
  / determine what kind of cpu we are running on
! / first, check switches. if they are 40, 24, 44, 45, 70, or 73
! / set appropriately
! /
  	clrb	_sep_id
  	clrb	_ubmap
- 	clrb	_haveCSW
- 	mov	$2f,nofault	/ check if we even have switches!
- 	tst	*$SWREG
- 	clr	nofault		/ apparently we do
- 	incb	_haveCSW
- 	mov	$40.,r0
- 	cmp	*$SWREG,$40
- 	beq	gotcha
- 	cmp	*$SWREG,$24
- 	bne	1f
- 	mov	$24.,r0
- 	incb	_ubmap
- 	jbr	gotcha
- 1:
- 	cmp	*$SWREG,$45
- 	bne	1f
- 	mov	$45.,r0
- 	incb	_sep_id
- 	jbr	gotcha
- 1:
- 	cmp	*$SWREG,$70
- 	bne	2f
- 	mov	$70.,r0
- 	incb	_sep_id
- 	incb	_ubmap
- 	jbr	gotcha
- /
- / if we can't find out from switches,
- / explore and see what we find
- /
- 2:
  	mov	$40.,r0		/ assume 11/40
  	mov	$2f,nofault
  	mov	*$KDSA6,r1	/ then we have sep i/d 45, 70, 73
--- 61,77 ----
  	clr	ENDCORE-CHECKWORD
  /
  / determine what kind of cpu we are running on
! / The check for the switch register removed because:  1) the only use
! / of it was in xp.c for the drive type and an alternate method of 
! / modifying xptype is provided, 2) the only machine with a front panel
! / which can run the system is the 11/70 and i got tired of having the
! / system think it was on a 11/40 because switches were left up after the
! / boot, 3) the standalone code was becoming large enough that 'restor'
! / was having size problems due to the addition of multi-controller support,
! / 4) the probing proceedure adequately determines the hardware capabilities.
! 
  	clrb	_sep_id
  	clrb	_ubmap
  	mov	$40.,r0		/ assume 11/40
  	mov	$2f,nofault
  	mov	*$KDSA6,r1	/ then we have sep i/d 45, 70, 73
***************
*** 120,126 ****
  	incb	_ubmap
  	mov	$24.,r0		/ unibus map, no sep. I/D = 24
  1:	clr	nofault
- gotcha:
  	mov	r0,_cputype
  
  /
--- 96,101 ----
***************
*** 150,159 ****
  / physical addressing is completely reworked, 3*64Kb is probably the
  / highest we'll ever see boot relocated.  This means that the maximum size
  / of any program boot can load is 192Kb.  That size includes text, data
! / and bss.  This is a problem for the current (9/87) networking kernels
! / which have the networking code and data space incorporated as part of
! / the main line kernel.  Which only adds more impetus to get the networking
! / put into supervisor space ...
  
  N	= 3			/ 3*64Kb = 192Kb
  
--- 125,131 ----
  / physical addressing is completely reworked, 3*64Kb is probably the
  / highest we'll ever see boot relocated.  This means that the maximum size
  / of any program boot can load is 192Kb.  That size includes text, data
! / and bss.
  
  N	= 3			/ 3*64Kb = 192Kb
  
***************
*** 224,240 ****
  	mtpi	(r1)+
  	sob	r0,1b
  
  
- / continue execution in user space copy; return protocol uses
- / absolute address 140000.
- 	mov	$140004,sp
- 	tstb	_sep_id
- 	bne	1f
- 	clr	*$KISA6
- 	br	2f
- 1:
- 	clr	*$KDSA6
- 2:
  	mov	$140340,-(sp)
  	mov	$user,-(sp)
  	rtt
--- 196,204 ----
  	mtpi	(r1)+
  	sob	r0,1b
  
+ / continue execution in user space copy.  No sense in loading sp with
+ / anything special since the call to _main below overwrites low core.
  
  	mov	$140340,-(sp)
  	mov	$user,-(sp)
  	rtt
***************
*** 257,265 ****
--- 221,233 ----
  
  	jsr	pc,_main
  	mov	_cputype,r0
+ 	mov	_bootcsr,r1	/ csr of boot controller (from ROMs)
+ 	mov	_bootdev,r3	/ makedev(major,unit) (from ROMs & bootblock)
  	mov	_bootopts,r4
  	mov	r4,r2
  	com	r2		/ checkword
+ 	mov	$160000,-(sp)	/ set ksp to very top so that the trap
+ 	mtpi	sp		/ puts the return address and psw at 157774,6
  	systrap
  
  	br	user
***************
*** 343,360 ****
  
  trap:
  	mov	*$PS,-(sp)
- 	mov	r0,-(sp)
- 	mov	r1,-(sp)
  	tst	nofault
  	bne	3f
  	jsr	pc,_trap
  	mov	(sp)+,r1
  	mov	(sp)+,r0
  	tst	(sp)+
  	rtt
! 3:	mov	(sp)+,r1
! 	mov	(sp)+,r0
! 	tst	(sp)+
  	mov	nofault,(sp)
  	rtt
  
--- 311,326 ----
  
  trap:
  	mov	*$PS,-(sp)
  	tst	nofault
  	bne	3f
+ 	mov	r0,-(sp)
+ 	mov	r1,-(sp)
  	jsr	pc,_trap
  	mov	(sp)+,r1
  	mov	(sp)+,r0
  	tst	(sp)+
  	rtt
! 3:	tst	(sp)+
  	mov	nofault,(sp)
  	rtt
  
***************
*** 364,383 ****
  SSR2	= 177576
  SSR3	= 172516
  KISA0	= 172340
- KISA1	= 172342
  KISA6	= 172354
- KISA7	= 172356
  KISD0	= 172300
  KISD7	= 172316
  KDSA0	= 172360
  KDSA6	= 172374
- KDSA7	= 172376
  KDSD0	= 172320
- KDSD5	= 172332
- SISA0	= 172240
- SISA1	= 172242
- SISD0	= 172200
- SISD1	= 172202
  UISA0	= 177640
  UISD0	= 177600
  UDSA0	= 177660
--- 330,341 ----
***************
*** 384,403 ****
  UDSD0	= 177620
  MSCR	= 177746	/ 11/44/60/70 memory system cache control register
  IO	= 177600
- SWREG	= 177570
  UBMAP	= 170200
  
  .data
  .globl	_cputype
! .globl	_ksep, _sep_id, _ubmap, _haveCSW
! .globl	_bootopts, _bootdev, _checkword
  
  nofault:	.=.+2	/ where to go on predicted trap
  _cputype:	.=.+2	/ cpu type (currently 40,45 or 70)
  _sep_id:	.=.+1	/ 1 if we have separate I and D
- _ubmap:		.=.+1	/ 1 if we have a unibus map
- _haveCSW:	.=.+1	/ 1 if we have a console switch register
  _ksep:		.=.+1	/ 1 if kernel mode has sep I/D enabled
  _bootopts:	.=.+2	/ flags if an autoboot
! _bootdev:	.=.+2	/ device to get unix from, if not RB_ASKNAME
  _checkword:	.=.+2	/ saved r2, complement of bootopts if an autoboot
--- 342,360 ----
  UDSD0	= 177620
  MSCR	= 177746	/ 11/44/60/70 memory system cache control register
  IO	= 177600
  UBMAP	= 170200
  
  .data
  .globl	_cputype
! .globl	_ksep, _sep_id, _ubmap
! .globl	_bootopts, _bootdev, _checkword, _bootcsr
  
  nofault:	.=.+2	/ where to go on predicted trap
  _cputype:	.=.+2	/ cpu type (currently 40,45 or 70)
  _sep_id:	.=.+1	/ 1 if we have separate I and D
  _ksep:		.=.+1	/ 1 if kernel mode has sep I/D enabled
+ _ubmap:		.=.+2	/ 1 if we have a unibus map
  _bootopts:	.=.+2	/ flags if an autoboot
! _bootdev:	.=.+2	/ device booted from
! _bootcsr:	.=.+2	/ csr of device booted from
  _checkword:	.=.+2	/ saved r2, complement of bootopts if an autoboot
*** /usr/src/sys/pdpstand.old/Makefile	Thu Dec 20 08:55:11 1990
--- /usr/src/sys/pdpstand/Makefile	Sun Apr 28 00:12:26 1991
***************
*** 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
--- 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
  
  .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 \
--- 56,62 ----
  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
--- 115,120 ----
*** /usr/src/sys/pdpstand.old/Makefile.vax	Sun Nov  4 12:19:58 1990
--- /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 ----
*** /usr/src/sys/pdpstand.old/boot.c	Fri Aug 19 11:53:12 1988
--- /usr/src/sys/pdpstand/boot.c	Tue Apr 23 13:08: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.0 (2.11BSD) 4/20/91
   */
  #include "../h/param.h"
  #include "../machine/seg.h"
***************
*** 19,25 ****
  #	define	RB_DEFNAME	"xp(0,0)unix"
  #endif
  
! #undef	btoc
  #define	KB	* 1024L
  
  #define	KISD0	((u_short *) 0172300)
--- 19,25 ----
  #	define	RB_DEFNAME	"xp(0,0)unix"
  #endif
  
! #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;
--- 34,51 ----
  #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) */
! char		line[64] = RB_DEFNAME;
  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
--- 61,66 ----
***************
*** 126,132 ****
  };
  
  struct	loadtable	loadtable[] = {
- 	A_MAGICU,	load401,	/* ULTRIX boot */
  	A_MAGIC1,	load407,
  	A_MAGIC2,	load410,
  	A_MAGIC3,	load411,
--- 117,122 ----
***************
*** 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.
--- 126,160 ----
  
  main()
  {
! 	register int i, j, maj;
  	int retry = 0;
+ 	caddr_t	*adjcsr;
  	struct loadtable *setup();
+ 	struct iob *file;
+ 	char *rb = RB_DEFNAME;
  
! 	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);
  	/*
  	 * 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);
  		}
--- 170,182 ----
  		} else
  			printf(": %s\n", line);
  		if (line[0] == '\0') {
! 			printf(": %s\n", rb);
! 			strcpy(line, rb);
! 		}
! 		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 ****
--- 183,193 ----
  		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++)
--- 362,368 ----
  				 * 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)));
  }
--- 559,565 ----
  
  unsigned
  btoc(nclicks)
! 	register unsigned nclicks;
  {
  	return((unsigned)(((((long) nclicks) + ((long) 63)) >> 6)));
  }
*** /usr/src/sys/pdpstand.old/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));
  }
*** /usr/src/sys/pdpstand.old/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 */
+ 		};
*** /usr/src/sys/pdpstand.old/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));
  }
*** /usr/src/sys/pdpstand.old/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;
  }
*** /usr/src/sys/pdpstand.old/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]);
*** /usr/src/sys/pdpstand.old/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
*** /usr/src/sys/pdpstand.old/prf.c	Fri Aug 19 11:57:00 1988
--- /usr/src/sys/pdpstand/prf.c	Sun Apr 21 00:13:07 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)prf.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  #include "../machine/cons.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)prf.c	1.2 (2.11BSD) 4/20/91
   */
  
  #include "../machine/cons.h"
***************
*** 54,62 ****
   */
  printn(n, b)
  	long n;
! 	int b;
  {
! 	register long a;
  
  	if (n < 0) {	/* shouldn't happen */
  		putchar('-');
--- 54,62 ----
   */
  printn(n, b)
  	long n;
! 	register int b;
  {
! 	long a;
  
  	if (n < 0) {	/* shouldn't happen */
  		putchar('-');
*** /usr/src/sys/pdpstand.old/ra.c	Fri Sep 29 11:48:26 1989
--- /usr/src/sys/pdpstand/ra.c	Sun Apr 21 00:13:54 1991
***************
*** 3,14 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ra.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  /*
   * RAxx disk device driver
!  * RQDX1 (rx50, rd50, rd51, rd52, rd53)
   */
  #include "../h/param.h"
  #include "../h/inode.h"
--- 3,14 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ra.c	2.0 (2.11BSD) 4/20/91
   */
  
  /*
   * RAxx disk device driver
!  * RQDX?/UDA50 (rx33, rx50, rd5?, ra??)
   */
  #include "../h/param.h"
  #include "../h/inode.h"
***************
*** 16,21 ****
--- 16,30 ----
  #include "../pdpuba/rareg.h"
  #include "saio.h"
  
+ #define	NRA	2
+ 
+ 	struct	radevice *RAcsr[NRA + 1] =
+ 		{
+ 		(struct radevice *)0172150,
+ 		(struct	radevice *)0,
+ 		(struct radevice *)-1
+ 		};
+ 
  /*
   * RA Communications Area
  */
***************
*** 36,103 ****
  #define	RA_OWN	0x8000	/* RQ owns this descriptor */
  #define	RA_INT	0x4000	/* allow interrupt on ring transition */
  
- static	struct	radevice *RDADDR = ((struct radevice *)0172150);
- 
  static	struct	ra {
  	struct	rdca	ra_ca;
  	struct	mscp	ra_rsp;
  	struct	mscp	ra_cmd;
! } rd;
  
! struct 	mscp 	*racmd();
! static	int 	rdinit;
! static	long	rdonline[8];
  
- /*
-  * XXX - Not consistent with other stand alone drivers.
-  * static int	rd_boff[] = { 0, 9700, 27000, 30100, 0, 7460, 9700, 0 };
-  */
- 
  raopen(io)
  	register struct iob *io;
  {
! 	register struct mscp *mp;
! 	int i;
  
! 	if (rdinit == 0) {
! 		RDADDR->raip = 0;
! 		while ((RDADDR->rasa & RA_STEP1) == 0)
  			continue;
! 		RDADDR->rasa = RA_ERR;
! 		while ((RDADDR->rasa & RA_STEP2) == 0)
  			continue;
! 		RDADDR->rasa = (short)&rd.ra_ca.ca_ringbase;
! 		while ((RDADDR->rasa & RA_STEP3) == 0)
  			continue;
! 		RDADDR->rasa = (short)(segflag & 3);
! 		while ((RDADDR->rasa & RA_STEP4) == 0)
  			continue;
! 		RDADDR->rasa = RA_GO;
! 		rd.ra_ca.ca_rspl = (short)&rd.ra_rsp.m_cmdref;
! 		rd.ra_ca.ca_rsph = (short)(segflag & 3);
! 		rd.ra_ca.ca_cmdl = (short)&rd.ra_cmd.m_cmdref;
! 		rd.ra_ca.ca_cmdh = (short)(segflag & 3);
! 		rd.ra_cmd.m_cntflgs = 0;
! 		if ((int)racmd(M_O_STCON, 0) < 0) {
! 			printf("RD: controller init error, STCON\n");
  			return(-1);
  		}
! 		rdinit = 1;
  	}
  
! 	if (rdonline[io->i_unit & 7] == 0)
  		if (ramount(io) == -1)
  			return(-1);
- 
- 	/*
- 	 * XXX - Not consistent with other stand alone drivers.
- 	 * if ((io->i_boff < 0) || (io->i_boff > 7) ||
- 	 *    (rd_boff[io->i_boff] == -1)) {
- 	 *	printf("RD: bad partition for unit=%d", io->i_unit & 7);
- 	 * }
- 	 * io->i_boff = rd_boff[io->i_boff];
- 	 */
- 
  	return(0);
  }
  
--- 45,102 ----
  #define	RA_OWN	0x8000	/* RQ owns this descriptor */
  #define	RA_INT	0x4000	/* allow interrupt on ring transition */
  
  static	struct	ra {
  	struct	rdca	ra_ca;
  	struct	mscp	ra_rsp;
  	struct	mscp	ra_cmd;
! } rd[NRA];
  
! static	u_char 	rainit[NRA];
! static	long	raonline[NRA][8];
  
  raopen(io)
  	register struct iob *io;
  {
! 	register struct radevice *raaddr;
! 	register struct ra *racom;
! 	int i, ctlr, unit;
  
! 	ctlr = CTLRn(io->i_unit);
! 	unit = UNITn(io->i_unit);
! 	if (genopen(NRA, io) < 0)
! 		return(-1);
! 	raaddr = RAcsr[ctlr];
! 	racom = &rd[ctlr];
! 
! 	if (rainit[ctlr] == 0) {
! 		raaddr->raip = 0;
! 		while ((raaddr->rasa & RA_STEP1) == 0)
  			continue;
! 		raaddr->rasa = RA_ERR;
! 		while ((raaddr->rasa & RA_STEP2) == 0)
  			continue;
! 		raaddr->rasa = (short)&racom->ra_ca.ca_ringbase;
! 		while ((raaddr->rasa & RA_STEP3) == 0)
  			continue;
! 		raaddr->rasa = (short)(segflag & 3);
! 		while ((raaddr->rasa & RA_STEP4) == 0)
  			continue;
! 		raaddr->rasa = RA_GO;
! 		racom->ra_ca.ca_rspl = (short)&racom->ra_rsp.m_cmdref;
! 		racom->ra_ca.ca_rsph = (short)(segflag & 3);
! 		racom->ra_ca.ca_cmdl = (short)&racom->ra_cmd.m_cmdref;
! 		racom->ra_ca.ca_cmdh = (short)(segflag & 3);
! 		racom->ra_cmd.m_cntflgs = 0;
! 		if (racmd(M_O_STCON, 0) < 0) {
! 			printf("RA%d ctlr STCON err\n", ctlr);
  			return(-1);
  		}
! 		rainit[ctlr] = 1;
  	}
  
! 	if (raonline[ctlr][unit] == 0)
  		if (ramount(io) == -1)
  			return(-1);
  	return(0);
  }
  
***************
*** 104,110 ****
  raclose(io)
  	register struct iob *io;
  {
! 	rdonline[io->i_unit & 7] = 0;
  	return(0);
  }
  
--- 103,109 ----
  raclose(io)
  	register struct iob *io;
  {
! 	raonline[CTLRn(io->i_unit)][UNITn(io->i_unit)] = 0;
  	return(0);
  }
  
***************
*** 111,152 ****
  ramount(io)
  	register struct iob *io;
  {
! 	if ((int)racmd(M_O_ONLIN, io->i_unit) < 0) {
! 		printf("RD: bring online error, unit=%d\n", io->i_unit & 7);
  		return(-1);
  	}
! 	rdonline[io->i_unit & 7] = rd.ra_rsp.m_uslow +  
! 		((long)(rd.ra_rsp.m_ushigh) << 16);
  	return(0);
  }
  
- struct mscp *
  racmd(op, unit)
  	int op, unit;
  {
  	register struct mscp *mp;
! 	register int i;
  
! 	rd.ra_cmd.m_opcode = op;
! 	rd.ra_cmd.m_unit = unit & 7;
! 	rd.ra_rsp.m_header.ra_msglen = sizeof(struct mscp);
! 	rd.ra_cmd.m_header.ra_msglen = sizeof(struct mscp);
! 	rd.ra_ca.ca_rsph = RA_OWN | RA_INT | (segflag & 3);
! 	rd.ra_ca.ca_cmdh = RA_OWN | RA_INT | (segflag & 3);
! 	i = RDADDR->raip;
  	while (1) {
! 		if (rd.ra_ca.ca_cmdint)
! 			rd.ra_ca.ca_cmdint = 0;
! 		if (rd.ra_ca.ca_rspint)
  			break;
  	}
! 	rd.ra_ca.ca_rspint = 0;
! 	mp = &rd.ra_rsp;
! 	if (((mp->m_opcode & 0xff) != (op | M_O_END)) ||
  	    ((mp->m_status & M_S_MASK) != M_S_SUCC)) {
! 		printf("RD: command error, unit=%d, opcode=%x, status=%x\n",
! 			unit & 7, mp->m_opcode & 0xff, mp->m_status);
! 		return((struct mscp *)-1);
  	}
  	return(0);
  }
--- 110,155 ----
  ramount(io)
  	register struct iob *io;
  {
! 	register int ctlr = CTLRn(io->i_unit);
! 	register int unit = UNITn(io->i_unit);
! 
! 	if (racmd(M_O_ONLIN, io->i_unit) < 0) {
! 		printf("RA%d,%d: online err\n", ctlr, unit);
  		return(-1);
  	}
! 	raonline[ctlr][unit] = rd[ctlr].ra_rsp.m_uslow +  
! 		((long)(rd[ctlr].ra_rsp.m_ushigh) << 16);
  	return(0);
  }
  
  racmd(op, unit)
  	int op, unit;
  {
  	register struct mscp *mp;
! 	register int ctlr = CTLRn(unit);
! 	register struct ra *racom = &rd[ctlr];
! 	int i;
  
! 	racom->ra_cmd.m_opcode = op;
! 	racom->ra_cmd.m_unit = UNITn(unit);
! 	racom->ra_rsp.m_header.ra_msglen = sizeof(struct mscp);
! 	racom->ra_cmd.m_header.ra_msglen = sizeof(struct mscp);
! 	racom->ra_ca.ca_rsph = RA_OWN | RA_INT | (segflag & 3);
! 	racom->ra_ca.ca_cmdh = RA_OWN | RA_INT | (segflag & 3);
! 	i = RAcsr[ctlr]->raip;
  	while (1) {
! 		if (racom->ra_ca.ca_cmdint)
! 			racom->ra_ca.ca_cmdint = 0;
! 		if (racom->ra_ca.ca_rspint)
  			break;
  	}
! 	racom->ra_ca.ca_rspint = 0;
! 	mp = &racom->ra_rsp;
! 	if ((mp->m_opcode != (op | M_O_END)) ||
  	    ((mp->m_status & M_S_MASK) != M_S_SUCC)) {
! 		printf("RA%d,%d: cmd err op=%x, sts=%x\n",
! 			ctlr, unit, mp->m_opcode, mp->m_status);
! 		return(-1);
  	}
  	return(0);
  }
***************
*** 155,172 ****
  	register struct iob *io;
  {
  	register struct mscp *mp;
  
! 	if (io->i_bn >= rdonline[io->i_unit & 7])
  		return(0);
  
! 	mp = &rd.ra_cmd;
  	mp->m_lbn_l = loint(io->i_bn);
  	mp->m_lbn_h = hiint(io->i_bn);
  	mp->m_bytecnt = io->i_cc;
  	mp->m_buf_l = (ushort)io->i_ma;
  	mp->m_buf_h = segflag & 3;
! 	if ((int)racmd(func == READ ? M_O_READ : M_O_WRITE, io->i_unit) < 0)
  		return(-1);
- 
  	return(io->i_cc);
  }
--- 158,177 ----
  	register struct iob *io;
  {
  	register struct mscp *mp;
+ 	struct ra *racom;
+ 	register int ctlr = CTLRn(io->i_unit);
  
! 	if (io->i_bn >= raonline[ctlr][UNITn(io->i_unit)])
  		return(0);
  
! 	racom = &rd[ctlr];
! 	mp = &racom->ra_cmd;
  	mp->m_lbn_l = loint(io->i_bn);
  	mp->m_lbn_h = hiint(io->i_bn);
  	mp->m_bytecnt = io->i_cc;
  	mp->m_buf_l = (ushort)io->i_ma;
  	mp->m_buf_h = segflag & 3;
! 	if (racmd(func == READ ? M_O_READ : M_O_WRITE, io->i_unit) < 0)
  		return(-1);
  	return(io->i_cc);
  }


