/boot,/mdec/,[T]MSCP (Part 7b of 22)

Steven M. Schultz sms at wlv.imsd.contel.com
Sat May 18 16:29:33 AEST 1991


Subject: Part 7b 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 7b of 22

Remove this introductory text and append to part 7a.  
---------------------------cut here------------------------------
*** /usr/src/sys/pdpstand.old/rk.c	Fri Aug 19 11:57:25 1988
--- /usr/src/sys/pdpstand/rk.c	Sun Apr 21 00:14:35 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)rk.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.
   *
!  *	@(#)rk.c	2.0 (2.11BSD) 4/20/91
   */
  
  /*
***************
*** 15,48 ****
  #include "../pdpuba/rkreg.h"
  #include "saio.h"
  
! #define	RKADDR	((struct rkdevice *)0177400)
  
  rkstrategy(io, func)
  	register struct iob *io;
  {
  	register com;
  	daddr_t bn;
  	int dn, cn, sn;
  
  	bn = io->i_bn;
! 	dn = io->i_unit;
  	cn = bn/12;
  	sn = bn%12;
! 	RKADDR->rkda = (dn<<13) | (cn<<4) | sn;
! 	RKADDR->rkba = io->i_ma;
! 	RKADDR->rkwc = -(io->i_cc>>1);
  	com = (segflag<<4)|RKCS_GO;
  	if (func == READ)
  		com |= RKCS_RCOM;
  	else
  		com |= RKCS_WCOM;
! 	RKADDR->rkcs = com;
! 	while ((RKADDR->rkcs & RKCS_RDY) == 0)
  		continue;
! 	if (RKADDR->rkcs<0) {	/* error bit */
! 		printf("disk error: cyl=%d, sector=%d, er=%o, ds=%o\n",
! 		    cn, sn, RKADDR->rker, RKADDR->rkds);
  		return(-1);
  	}
  	return(io->i_cc);
  }
--- 15,64 ----
  #include "../pdpuba/rkreg.h"
  #include "saio.h"
  
! #define	NRK	2
  
+ 	struct	rkdevice *RKcsr[NRK + 1] =
+ 		{
+ 		(struct rkdevice *)0177400,
+ 		(struct	rkdevice *)0,
+ 		(struct rkdevice *)-1
+ 		};
+ 
  rkstrategy(io, func)
  	register struct iob *io;
  {
  	register com;
+ 	register struct rkdevice *rkaddr;
  	daddr_t bn;
  	int dn, cn, sn;
  
  	bn = io->i_bn;
! 	dn = UNITn(io->i_unit);
  	cn = bn/12;
  	sn = bn%12;
! 	rkaddr = RKcsr[CTLRn(io->i_unit)];
! 	rkaddr->rkda = (dn<<13) | (cn<<4) | sn;
! 	rkaddr->rkba = io->i_ma;
! 	rkaddr->rkwc = -(io->i_cc>>1);
  	com = (segflag<<4)|RKCS_GO;
  	if (func == READ)
  		com |= RKCS_RCOM;
  	else
  		com |= RKCS_WCOM;
! 	rkaddr->rkcs = com;
! 	while ((rkaddr->rkcs & RKCS_RDY) == 0)
  		continue;
! 	if (rkaddr->rkcs<0) {	/* error bit */
! 		printf("RK%d,%d err cy=%d sc=%d, er=%o, ds=%o\n",
! 		    CTLRn(io->i_unit), UNITn(io->i_unit), cn, sn,
! 		    rkaddr->rker, rkaddr->rkds);
  		return(-1);
  	}
  	return(io->i_cc);
+ }
+ 
+ rkopen(io)
+ 	struct iob *io;
+ {
+ 	return(genopen(NRK, io));
  }
*** /usr/src/sys/pdpstand.old/rl.c	Fri Aug 19 11:57:42 1988
--- /usr/src/sys/pdpstand/rl.c	Sun Apr 21 00:15:03 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)rl.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.
   *
!  *	@(#)rl.c	2.0 (2.11BSD) 4/20/91
   */
  
  /*
***************
*** 18,31 ****
  #include "../pdpuba/rlreg.h"
  #include "saio.h"
  
! #define RLADDR	((struct rldevice *)0174400)
  
  #define	BLKRL1	10240		/* Number of UNIX blocks for an RL01 drive */
  #define BLKRL2	20480		/* Number of UNIX blocks for an RL02 drive */
  #define RLCYLSZ 10240		/* bytes per cylinder */
  #define RLSECSZ 256		/* bytes per sector */
  
! struct 
  {
  	int	cn[4];		/* location of heads for each drive */
  	int	type[4];	/* parameter dependent upon drive type  (RL01/02) */
--- 18,38 ----
  #include "../pdpuba/rlreg.h"
  #include "saio.h"
  
! #define	NRL	2
  
+ 	struct	rldevice *RLcsr[NRL + 1] =
+ 		{
+ 		(struct rldevice *)0174400,
+ 		(struct rldevice *)0,
+ 		(struct rldevice *)-1
+ 		};
+ 
  #define	BLKRL1	10240		/* Number of UNIX blocks for an RL01 drive */
  #define BLKRL2	20480		/* Number of UNIX blocks for an RL02 drive */
  #define RLCYLSZ 10240		/* bytes per cylinder */
  #define RLSECSZ 256		/* bytes per sector */
  
! struct	Rldrives
  {
  	int	cn[4];		/* location of heads for each drive */
  	int	type[4];	/* parameter dependent upon drive type  (RL01/02) */
***************
*** 39,45 ****
  		long	l;
  	} addr;			/* address of memory for transfer */
  
! }	rl = {-1,-1,-1,-1,-1,-1,-1,-1};  /* initialize cn[] and type[] */
  
  rlstrategy(io, func)
  	register struct iob *io;
--- 46,53 ----
  		long	l;
  	} addr;			/* address of memory for transfer */
  
! } rl[NRL] = {{-1,-1,-1,-1,-1,-1,-1,-1},
! 	     {-1,-1,-1,-1,-1,-1,-1,-1}};  /* initialize cn[] and type[] */
  
  rlstrategy(io, func)
  	register struct iob *io;
***************
*** 50,57 ****
  	int dif;
  	int head;
  	int ctr;
  
- 
  	/*
  	 * We must determine what type of drive we are talking to in order 
  	 * to determine how many blocks are on the device.  The rl.type[]
--- 58,67 ----
  	int dif;
  	int head;
  	int ctr;
+ 	int ctlr = CTLRn(io->i_unit);
+ 	register struct rldevice *rladdr;
+ 	register struct Rldrives *rlp;
  
  	/*
  	 * We must determine what type of drive we are talking to in order 
  	 * to determine how many blocks are on the device.  The rl.type[]
***************
*** 72,152 ****
  	 * drive type. If a valid status is not returned after eight
  	 * attempts, then an error message is printed.
  	 */
! 	drive = io->i_unit;
! 	if (rl.type[drive] < 0) {
  		ctr = 0;
  		do {
  			/* load this register; what a dumb controller */
! 			RLADDR->rlda = RLDA_RESET|RLDA_GS;
  			/* set up csr */
! 			RLADDR->rlcs = (drive << 8) | RL_GETSTATUS;
! 			while ((RLADDR->rlcs & RL_CRDY) == 0)	/* wait for it */		
  				continue;
! 		} while (((RLADDR->rlmp & 0177477) != 035) && (++ctr < 8));
  		if (ctr >= 8)
! 			printf("\nCan't get status of RL unit %d\n", drive);
! 		if (RLADDR->rlmp & RLMP_DTYP) 
! 			rl.type[drive] = BLKRL2;	/* drive is RL02 */
  		else
! 			rl.type[drive] = BLKRL1;	/* drive RL01 */
  		/*
  		 * When the device is first touched, find out where the heads are.
  		 */
  		/* find where the heads are */
! 		RLADDR->rlcs = (drive << 8) | RL_RHDR;
! 		while ((RLADDR->rlcs&RL_CRDY) == 0)
  			continue;
! 		rl.cn[drive] = ((RLADDR->rlmp) >> 6) & 01777;
  	}
! 	nblocks = rl.type[drive];	/* how many blocks on this drive */
  	if (io->i_bn >= nblocks)
  		return -1;
! 	rl.chn = io->i_bn/20;
! 	rl.sn = (io->i_bn%20) << 1;
! 	rl.bleft = io->i_cc;
! 	rl.addr.w[0] = segflag & 3;
! 	rl.addr.w[1] = (int)io->i_ma;
! 	rl.com = (drive << 8);
  	if (func == READ)
! 		rl.com |= RL_RCOM;
  	else
! 		rl.com |= RL_WCOM;
  reading:
  	/*
  	 * One has to seek an RL head, relativily.
  	 */
! 	dif =(rl.cn[drive] >> 1) - (rl.chn >>1);
! 	head = (rl.chn & 1) << 4;
  	if (dif < 0)
! 		RLADDR->rlda = (-dif <<7) | RLDA_SEEKHI | head;
  	else
! 		RLADDR->rlda = (dif << 7) | RLDA_SEEKLO | head;
! 	RLADDR->rlcs = (drive << 8) | RL_SEEK;
! 	rl.cn[drive] = rl.chn; 	/* keep current, our notion of where the heads are */
! 	if (rl.bleft < (rl.bpart = RLCYLSZ - (rl.sn * RLSECSZ)))
! 		rl.bpart = rl.bleft;
! 	while ((RLADDR->rlcs&RL_CRDY) == 0)
  		continue;
! 	RLADDR->rlda = (rl.chn << 6) | rl.sn;
! 	RLADDR->rlba = (caddr_t) rl.addr.w[1];
! 	RLADDR->rlmp = -(rl.bpart >> 1);
! 	RLADDR->rlcs = rl.com | rl.addr.w[0] << 4;
! 	while ((RLADDR->rlcs & RL_CRDY) == 0)	/* wait for completion */
  		continue;
! 	if (RLADDR->rlcs < 0) {
  		/* check error bit */
! 		if (RLADDR->rlcs & 040000) {
  			/* Drive error */
  			/*
  			 * get status from drive
  			 */
! 			RLADDR->rlda = RLDA_GS;
! 			RLADDR->rlcs = (drive << 8) | RL_GETSTATUS;
! 			while ((RLADDR->rlcs & RL_CRDY) == 0)	/* wait for controller */
  				continue;
  		}
! 		printf("Rl disk error: cyl=%d, head=%d, sector=%d, rlcs=%o, rlmp=%o\n",
! 			rl.chn>>01, rl.chn&01, rl.sn, RLADDR->rlcs, RLADDR->rlmp);
  		return(-1);
  	}
  	/*
--- 82,166 ----
  	 * drive type. If a valid status is not returned after eight
  	 * attempts, then an error message is printed.
  	 */
! 	drive = UNITn(io->i_unit);
! 	rladdr = RLcsr[ctlr];
! 	rlp = &rl[ctlr];
! 
! 	if (rlp->type[drive] < 0) {
  		ctr = 0;
  		do {
  			/* load this register; what a dumb controller */
! 			rladdr->rlda = RLDA_RESET|RLDA_GS;
  			/* set up csr */
! 			rladdr->rlcs = (drive << 8) | RL_GETSTATUS;
! 			while ((rladdr->rlcs & RL_CRDY) == 0)	/* wait for it */		
  				continue;
! 		} while (((rladdr->rlmp & 0177477) != 035) && (++ctr < 8));
  		if (ctr >= 8)
! 			printf("\nCan't get RL%d,%d sts\n", ctlr, drive);
! 		if (rladdr->rlmp & RLMP_DTYP) 
! 			rlp->type[drive] = BLKRL2;	/* drive is RL02 */
  		else
! 			rlp->type[drive] = BLKRL1;	/* drive RL01 */
  		/*
  		 * When the device is first touched, find out where the heads are.
  		 */
  		/* find where the heads are */
! 		rladdr->rlcs = (drive << 8) | RL_RHDR;
! 		while ((rladdr->rlcs&RL_CRDY) == 0)
  			continue;
! 		rlp->cn[drive] = ((rladdr->rlmp) >> 6) & 01777;
  	}
! 	nblocks = rlp->type[drive];	/* how many blocks on this drive */
  	if (io->i_bn >= nblocks)
  		return -1;
! 	rlp->chn = io->i_bn/20;
! 	rlp->sn = (io->i_bn%20) << 1;
! 	rlp->bleft = io->i_cc;
! 	rlp->addr.w[0] = segflag & 3;
! 	rlp->addr.w[1] = (int)io->i_ma;
! 	rlp->com = (drive << 8);
  	if (func == READ)
! 		rlp->com |= RL_RCOM;
  	else
! 		rlp->com |= RL_WCOM;
  reading:
  	/*
  	 * One has to seek an RL head, relativily.
  	 */
! 	dif =(rlp->cn[drive] >> 1) - (rlp->chn >>1);
! 	head = (rlp->chn & 1) << 4;
  	if (dif < 0)
! 		rladdr->rlda = (-dif <<7) | RLDA_SEEKHI | head;
  	else
! 		rladdr->rlda = (dif << 7) | RLDA_SEEKLO | head;
! 	rladdr->rlcs = (drive << 8) | RL_SEEK;
! 	rlp->cn[drive] = rlp->chn; 	/* keep current, our notion of where the heads are */
! 	if (rlp->bleft < (rlp->bpart = RLCYLSZ - (rl->sn * RLSECSZ)))
! 		rlp->bpart = rlp->bleft;
! 	while ((rladdr->rlcs&RL_CRDY) == 0)
  		continue;
! 	rladdr->rlda = (rlp->chn << 6) | rlp->sn;
! 	rladdr->rlba = (caddr_t) rlp->addr.w[1];
! 	rladdr->rlmp = -(rlp->bpart >> 1);
! 	rladdr->rlcs = rlp->com | rlp->addr.w[0] << 4;
! 	while ((rladdr->rlcs & RL_CRDY) == 0)	/* wait for completion */
  		continue;
! 	if (rladdr->rlcs < 0) {
  		/* check error bit */
! 		if (rladdr->rlcs & 040000) {
  			/* Drive error */
  			/*
  			 * get status from drive
  			 */
! 			rladdr->rlda = RLDA_GS;
! 			rladdr->rlcs = (drive << 8) | RL_GETSTATUS;
! 			while ((rladdr->rlcs & RL_CRDY) == 0)	/* wait for controller */
  				continue;
  		}
! 		printf("RL%d,%d err cy=%d, hd=%d, sc=%d, rlcs=%o, rlmp=%o\n",
! 			ctlr, drive, rlp->chn>>01, rlp->chn&01, rlp->sn, 
! 			rladdr->rlcs, rladdr->rlmp);
  		return(-1);
  	}
  	/*
***************
*** 153,163 ****
  	 * Determine if there is more to read to satisfy this request.
  	 * This is to compensate for the lacl of spiraling reads.
  	 */
! 	if ((rl.bleft -= rl.bpart) > 0) {
! 		rl.addr.l += rl.bpart;
! 		rl.sn = 0;
! 		rl.chn++;
  		goto reading;	/* read some more */
  	}
  	return(io->i_cc);
  }
--- 167,183 ----
  	 * Determine if there is more to read to satisfy this request.
  	 * This is to compensate for the lacl of spiraling reads.
  	 */
! 	if ((rlp->bleft -= rlp->bpart) > 0) {
! 		rlp->addr.l += rlp->bpart;
! 		rlp->sn = 0;
! 		rlp->chn++;
  		goto reading;	/* read some more */
  	}
  	return(io->i_cc);
+ }
+ 
+ rlopen(io)
+ 	struct iob *io;
+ {
+ 	return(genopen(NRL, io));
  }
*** /usr/src/sys/pdpstand.old/saio.h	Fri Apr 29 20:01:13 1988
--- /usr/src/sys/pdpstand/saio.h	Fri Apr 12 22:06:04 1991
***************
*** 43,48 ****
--- 43,49 ----
  	int	(*dv_strategy)();
  	int	(*dv_open)();
  	int	(*dv_close)();
+ 	caddr_t	**dv_csr;
  };
  
  struct	devsw	devsw[];
***************
*** 60,62 ****
--- 61,71 ----
   * Must be set by the user's main (or thereabouts).
   */
  int	segflag;
+ 
+ /*
+  * macros to extract the controller and unit number.  common to all drivers
+  * so the macros are defined here rather than in each driver.
+ */
+ 
+ #define	CTLRn(dev)	((minor(dev) >> 6) & 3)
+ #define	UNITn(dev)	(minor(dev) & 7)
*** /usr/src/sys/pdpstand.old/si.c	Fri Aug 19 11:58:28 1988
--- /usr/src/sys/pdpstand/si.c	Sun Apr 21 00:15:46 1991
***************
*** 3,12 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)si.c	1.1 (2.10BSD Berkeley) 12/1/86
!  */
! 
! /*
   *	SI 9500 CDC 9766 Stand Alone disk driver
   */
  
--- 3,10 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)si.c	2.0 (2.11BSD) 4/20/91
!  *
   *	SI 9500 CDC 9766 Stand Alone disk driver
   */
  
***************
*** 15,88 ****
  #include "../pdpuba/sireg.h"
  #include "saio.h"
  
! #define SIADDR ((struct sidevice *)0176700)
  
  /* defines for 9766 */
  #define NHEADS	19
  #define NSECT	32
  
  #define NSPC	NSECT*NHEADS
! static int dualsi;
  
  sistrategy(io, func)
  	register struct iob *io;
  {
! 	register unit;
! 	register ii;
  	daddr_t bn;
  	int sn, cn, tn;
  
! 	if (((unit = io->i_unit) & 04) == 0)
! 		bn = io->i_bn;
! 	else {
! 		unit &= 03;
! 		bn = io->i_bn;
! 		bn -= io->i_boff;
! 		ii = unit + 1;
! 		unit = bn % ii;
! 		bn /= ii;
! 		bn += io->i_boff;
! 	}
! 
  	cn = bn / (NSPC);
  	sn = bn % (NSPC);
  	tn = sn / (NSECT);
  	sn = sn % (NSECT);
  
! 	if (!dualsi) {
! 		if (SIADDR->siscr != 0)
! 			dualsi++;
  		else
! 			if ((SIADDR->sierr & (SIERR_ERR | SIERR_CNT)) == (SIERR_ERR | SIERR_CNT))
! 				dualsi++;
  	}
! 	if (dualsi)
! 		while (!(SIADDR->siscr & 0200)) {
! 			SIADDR->sicnr = SI_RESET;
! 			SIADDR->siscr = 1;
  		}
! 	SIADDR->sipcr = cn;
! 	SIADDR->sihsr = (tn << 5) + sn;
! 	SIADDR->simar = io->i_ma;
! 	SIADDR->siwcr = io->i_cc >> 1;
! 	/*
! 	 * warning: unit is being used as a temporary.
! 	 */
! 	unit = ((segflag & 03) << 4) | SI_GO;
  	if (func == READ)
! 		unit |= SI_READ;
  	else if (func == WRITE)
! 		unit |= SI_WRITE;
  	
! 	SIADDR->sicnr = unit;
  
! 	while ((SIADDR->sicnr & SI_DONE) == 0)
  		continue;
  
! 	if (SIADDR->sierr & SIERR_ERR) {
! 		printf("disk error cyl=%d head=%d sect=%d cnr=%o, err=%o\n",
! 			cn, tn, sn, SIADDR->sicnr, SIADDR->sierr);
  		return(-1);
  	}
  	return(io->i_cc);
  }
--- 13,91 ----
  #include "../pdpuba/sireg.h"
  #include "saio.h"
  
! #define	NSI	2
  
+ 	struct	sidevice *SIcsr[NSI + 1] =
+ 		{
+ 		(struct sidevice *)0176700,
+ 		(struct sidevice *)0,
+ 		(struct sidevice *)-1
+ 		};
+ 
  /* defines for 9766 */
  #define NHEADS	19
  #define NSECT	32
  
  #define NSPC	NSECT*NHEADS
! static u_char dualsi[NSI];
  
  sistrategy(io, func)
  	register struct iob *io;
  {
! 	int unit = UNITn(io->i_unit);
! 	register int ctlr = CTLRn(io->i_unit);
! 	register struct sidevice *siaddr = SIcsr[ctlr];
! 	int ii;
  	daddr_t bn;
  	int sn, cn, tn;
  
! 	/*
! 	 * weirdness with bit 2 (04) removed - see xp.c for comments
! 	 * about this
! 	*/
! 	bn = io->i_bn;
  	cn = bn / (NSPC);
  	sn = bn % (NSPC);
  	tn = sn / (NSECT);
  	sn = sn % (NSECT);
  
! 	if (!dualsi[ctlr]) {
! 		if (siaddr->siscr != 0)
! 			dualsi[ctlr]++;
  		else
! 			if ((siaddr->sierr & (SIERR_ERR | SIERR_CNT)) == (SIERR_ERR | SIERR_CNT))
! 				dualsi[ctlr]++;
  	}
! 	if (dualsi[ctlr])
! 		while (!(siaddr->siscr & 0200)) {
! 			siaddr->sicnr = SI_RESET;
! 			siaddr->siscr = 1;
  		}
! 	siaddr->sipcr = cn + (unit <<10);
! 	siaddr->sihsr = (tn << 5) + sn;
! 	siaddr->simar = io->i_ma;
! 	siaddr->siwcr = io->i_cc >> 1;
! 	ii = ((segflag & 03) << 4) | SI_GO;
  	if (func == READ)
! 		ii |= SI_READ;
  	else if (func == WRITE)
! 		ii |= SI_WRITE;
  	
! 	siaddr->sicnr = ii;
  
! 	while ((siaddr->sicnr & SI_DONE) == 0)
  		continue;
  
! 	if (siaddr->sierr & SIERR_ERR) {
! 		printf("SI%d,%d err cy=%d hd=%d sc=%d cnr=%o, err=%o\n",
! 			ctlr, unit, cn, tn, sn, siaddr->sicnr, siaddr->sierr);
  		return(-1);
  	}
  	return(io->i_cc);
+ }
+ 
+ siopen(io)
+ 	struct iob *io;
+ {
+ 	return(genopen(NSI, io));
  }
*** /usr/src/sys/pdpstand.old/srt0.s	Thu Aug 18 22:53:21 1988
--- /usr/src/sys/pdpstand/srt0.s	Tue Apr 23 21:29:33 1991
***************
*** 1,4 ****
--- 1,5 ----
  / Startup code for standalone utilities
+ / sms- mods to pass boot device and csr on to program
  / wfj- mod's to allow non sep i/d machines, error recovery
  /      note that the bootstrap passes the cputype through in
  /      r0.
***************
*** 6,12 ****
  PS	= 177776
  
  .globl	_end
! .globl	_main, __rtt
  .globl	_edata
  	jmp	start
  
--- 7,13 ----
  PS	= 177776
  
  .globl	_end
! .globl	_main, __rtt, _devsw, _ADJcsr
  .globl	_edata
  	jmp	start
  
***************
*** 31,43 ****
  /
  / restore what kind of cpu we are running on
  	mov	r0,*$_cputype	/ assume that the boot left this in r0
! / check if there is a switch register
! 	mov	$1f,nofault
! 	tst	CSW
! 	incb	_haveCSW
! 1:
! 	clr	nofault
! 	mov	$157776,sp
  	mov	$_edata,r0
  	mov	$_end,r1
  	sub	r0,r1
--- 32,40 ----
  /
  / restore what kind of cpu we are running on
  	mov	r0,*$_cputype	/ assume that the boot left this in r0
! 	mov	r1,_bootcsr	/ assume that boot left csr in r1
! 	mov	r3,_bootdev	/ and boot device major,minor in r3
! 	mov	$157772,sp	/ return address,psw at 157774&6
  	mov	$_edata,r0
  	mov	$_end,r1
  	sub	r0,r1
***************
*** 47,60 ****
  1:
  	clr	(r0)+
  	sob	r1,1b
  	jsr	pc,_main
  
! / fix up stack to point at trap ps-pc pair,
! / located at bottom of memory.
! / so we can return to the bootstrap
  
  __rtt:
! 	mov	$140000,sp
  	rtt				/ we hope!
  	br	.
  
--- 44,85 ----
  1:
  	clr	(r0)+
  	sob	r1,1b
+ 
+ / controller number is in bits 6&7 of r3 (_bootdev).  major device number
+ / is in bits 8-15.  what we need to do now is place the csr into
+ / the appropriate driver's csrlist which is indexed by controller number.
+ 
+ 	ash	$-5,r3			/ r3 = controller# * 2
+ 	mov	r3,r0			/ controller number in bits 1,2
+ 	bic	$!6,r0			/ make a word index
+ 	ash	$-3,r3			/ major device # to bits 0-7
+ 	mov	r3,r2			/ save major for later
+ 	mul	$10.,r3			/ devsw[] members are 10. bytes each
+ 	mov	_devsw+10(r3),r3	/ get csrlist for driver
+ 	add	r0,r3			/ point to controller's entry
+ 
+ / the CSR passed from the ROMs is not necessarily the first address
+ / of a device!  We therefore have to adjust the CSR so that the structure
+ / pointers in the drivers are origined at the base address rather than
+ / the ROM supplied address.  The adjustment was not stored in devsw[] to
+ / save space (can get by with an array of bytes instead of words).
+ 
+ 	movb	_ADJcsr(r2),r2		/ adjust (possibly) the CSR
+ 	mov	_bootcsr,r1
+ 	sub	r2,r1
+ 
+ 	mov	r1,(r3)			/ store controller's csr in table
  	jsr	pc,_main
  
! / fix up stack to point at trap ps-pc pair located at top of memory
! / so we can return to the bootstrap.
! /
! / the return protocol originally changed from 140000 because icheck was
! / too large.  icheck was reduced in size but the 157774 return protocol
! / was retained to allow for slightly oversized programs.
  
  __rtt:
! 	mov	$157774,sp
  	rtt				/ we hope!
  	br	.
  
***************
*** 62,90 ****
  .globl	_trap
  trap:
  	mov	*$PS,-(sp)
- 	mov	r0,-(sp)
- 	mov	r1,-(sp)
  	tst	nofault
  	bne	3f
  2:	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
  
  .data
! .globl	_cputype, _haveCSW
  
  nofault:	.=.+2	/ where to go on predicted trap
! _cputype:	.=.+2	/ cpu type (currently 24,40,45 or 70)
! _haveCSW:	.=.+1	/ one if there is a switch register
! KISA6 = 172354
! KISA7 = 172356
! KDSA6 = 172374
! UBMAP = 170200
! CSW   = 177570
--- 87,109 ----
  .globl	_trap
  trap:
  	mov	*$PS,-(sp)
  	tst	nofault
  	bne	3f
+ 	mov	r0,-(sp)
+ 	mov	r1,-(sp)
  2:	jsr	pc,_trap
  	mov	(sp)+,r1
  	mov	(sp)+,r0
  	tst	(sp)+
  	rtt
! 3:	tst	(sp)+
  	mov	nofault,(sp)
  	rtt
  
  .data
! .globl	_cputype, _bootcsr, _bootdev
  
  nofault:	.=.+2	/ where to go on predicted trap
! _cputype:	.=.+2	/ cpu type (currently 44, 70, 73)
! _bootdev:	.=.+2	/ makedev(major,unit) for boot device
! _bootcsr:	.=.+2	/ csr of boot controller
*** /usr/src/sys/pdpstand.old/sys.c	Wed May 23 14:50:13 1990
--- /usr/src/sys/pdpstand/sys.c	Sun Apr 21 00:18:28 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)sys.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.
   *
!  *	@(#)sys.c	2.0 (2.11BSD) 4/20/91
   */
  
  #include "../h/param.h"
***************
*** 28,34 ****
  
  static
  openi(n, io)
! 	ino_t n;
  	register struct iob *io;
  {
  	register struct dinode *dp;
--- 28,34 ----
  
  static
  openi(n, io)
! 	register ino_t n;
  	register struct iob *io;
  {
  	register struct dinode *dp;
***************
*** 55,61 ****
  	struct iob *file;
  {
  	register char *q;
! 	char c;
  	ino_t n;
  
  	if (path==NULL || *path=='\0') {
--- 55,61 ----
  	struct iob *file;
  {
  	register char *q;
! 	register char c;
  	ino_t n;
  
  	if (path==NULL || *path=='\0') {
***************
*** 102,108 ****
  
  	ip = &io->i_ino;
  	if (bn < 0) {
! 		printf("bn negative\n");
  		return((daddr_t)0);
  	}
  
--- 102,108 ----
  
  	ip = &io->i_ino;
  	if (bn < 0) {
! 		printf("bn < 0\n");
  		return((daddr_t)0);
  	}
  
***************
*** 183,194 ****
  		return(0);
  	ip = &io->i_ino;
  	if ((ip->i_mode&IFMT)!=IFDIR) {
! 		printf("%s: not a directory mode %o ip %o\n",s, ip->i_mode, ip);
  		return(0);
  	}
  
  	if (ip->i_size==0) {
! 		printf("%s: zero length directory\n",s);
  		return(0);
  	}
  
--- 183,194 ----
  		return(0);
  	ip = &io->i_ino;
  	if ((ip->i_mode&IFMT)!=IFDIR) {
! 		printf("%s: not directory,mode %o ip %o\n",s, ip->i_mode, ip);
  		return(0);
  	}
  
  	if (ip->i_size==0) {
! 		printf("%s: 0 len directory\n",s);
  		return(0);
  	}
  
***************
*** 236,242 ****
  }
  
  lseek(fdesc, addr, ptr)
! 	int fdesc;
  	off_t addr;
  	int ptr;
  {
--- 236,242 ----
  }
  
  lseek(fdesc, addr, ptr)
! 	register int fdesc;
  	off_t addr;
  	int ptr;
  {
***************
*** 243,249 ****
  	register struct iob *io;
  
  	if (ptr != 0) {
! 		printf("Seek not from beginning of file\n");
  		return(-1);
  	}
  	fdesc -= 3;
--- 243,249 ----
  	register struct iob *io;
  
  	if (ptr != 0) {
! 		printf("illegal lseek\n");
  		return(-1);
  	}
  	fdesc -= 3;
***************
*** 325,331 ****
  }
  
  read(fdesc, buf, count)
! 	int fdesc;
  	char *buf;
  	int count;
  {
--- 325,331 ----
  }
  
  read(fdesc, buf, count)
! 	register int fdesc;
  	char *buf;
  	int count;
  {
***************
*** 364,370 ****
  }
  
  write(fdesc, buf, count)
! 	int fdesc;
  	char *buf;
  	int count;
  {
--- 364,370 ----
  }
  
  write(fdesc, buf, count)
! 	register int fdesc;
  	char *buf;
  	int count;
  {
***************
*** 410,416 ****
  	for (fdesc = 0; fdesc < NFILES; fdesc++)
  		if (iob[fdesc].i_flgs == 0)
  			goto gotfile;
! 	_stop("No more file slots");
  gotfile:
  	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
  
--- 410,416 ----
  	for (fdesc = 0; fdesc < NFILES; fdesc++)
  		if (iob[fdesc].i_flgs == 0)
  			goto gotfile;
! 	_stop("No file slots");
  gotfile:
  	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
  
***************
*** 432,446 ****
  gotdev:
  	*(cp-1) = '(';
  	file->i_ino.i_dev = dp-devsw;
! 	file->i_unit = *cp++ - '0';
! 	if (file->i_unit < 0 || file->i_unit > 7) {
! 		printf("Bad unit specifier\n");
! 		file->i_flgs = 0;
! 		return(-1);
  	}
  	if (*cp++ != ',') {
  badoff:
! 		printf("Missing offset specification\n");
  		file->i_flgs = 0;
  		return(-1);
  	}
--- 432,444 ----
  gotdev:
  	*(cp-1) = '(';
  	file->i_ino.i_dev = dp-devsw;
! 	for (file->i_unit = 0; *cp >= '0' && *cp <= '9'; cp++) {
! 		file->i_unit *= 10;
! 		file->i_unit += (*cp - '0');
  	}
  	if (*cp++ != ',') {
  badoff:
! 		printf("Missing offset\n");
  		file->i_flgs = 0;
  		return(-1);
  	}
***************
*** 452,458 ****
  			continue;
  		goto badoff;
  	}
! 	devopen(file);
  	if (*++cp == '\0') {
  		file->i_flgs |= how+1;
  		file->i_cc = 0;
--- 450,457 ----
  			continue;
  		goto badoff;
  	}
! 	if (devopen(file) < 0)
! 		return(-1);
  	if (*++cp == '\0') {
  		file->i_flgs |= how+1;
  		file->i_cc = 0;
***************
*** 464,470 ****
  		return(-1);
  	}
  	if (how != 0) {
! 		printf("Can't write files yet.. Sorry\n");
  		file->i_flgs = 0;
  		return(-1);
  	}
--- 463,469 ----
  		return(-1);
  	}
  	if (how != 0) {
! 		printf("Can't write files\n");
  		file->i_flgs = 0;
  		return(-1);
  	}
***************
*** 476,484 ****
  }
  
  close(fdesc)
! 	int fdesc;
  {
! 	struct iob *file;
  
  	fdesc -= 3;
  	if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
--- 475,483 ----
  }
  
  close(fdesc)
! 	register int fdesc;
  {
! 	register struct iob *file;
  
  	fdesc -= 3;
  	if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
***************
*** 537,539 ****
--- 536,562 ----
  	for (;;)
  		;
  }
+ 
+ genopen(maxctlr, io)
+ 	int maxctlr;
+ 	struct iob *io;
+ 	{
+ 	register struct devsw *dp = &devsw[io->i_ino.i_dev];
+ 	register char *cp;
+ 	register int ctlr = CTLRn(io->i_unit);
+ 	int csr;
+ 	char line[64];
+ 
+ 	if (ctlr >= maxctlr)
+ 		return(-1);
+ 	if (dp->dv_csr[ctlr])
+ 		return(0);
+ 	printf("%s%d csr[0%o]: ", dp->dv_name, ctlr, dp->dv_csr[ctlr]);
+ 	gets(line);
+ 	for (csr = 0, cp = line; *cp >= '0' && *cp <= '7'; cp++)
+ 		csr = csr * 8 + (*cp - '0');
+ 	if (csr == 0)
+ 		return(-1);
+ 	dp->dv_csr[ctlr] = (caddr_t *)csr;
+ 	return(0);
+ 	}
*** /usr/src/sys/pdpstand.old/tm.c	Fri Aug 19 11:59:26 1988
--- /usr/src/sys/pdpstand/tm.c	Sun Apr 21 00:19:06 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)tm.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.
   *
!  *	@(#)tm.c	2.0 (2.11BSD) 4/20/91
   */
  
  /*
***************
*** 15,34 ****
  #include "../pdpuba/tmreg.h"
  #include "saio.h"
  
! #define	TMADDR ((struct tmdevice *)0172520)
  
  extern int tapemark;	/* flag to indicate tapemark 
  			has been encountered (see sys.c) 	*/
  
  /*
!  * Bits in deivice code.
   */
- #define	TEUNIT(dev)	((dev) & 03)
  #define	T_NOREWIND	04		/* not used in stand alone driver */
! #define	TEDENS(dev)	(((dev) & 030) >> 3)
  
! tmrew(io)
! 	register struct iob *io;
  {
  	tmstrategy(io, TM_REW);
  }
--- 15,40 ----
  #include "../pdpuba/tmreg.h"
  #include "saio.h"
  
! #define	NTM	2
  
+ 	struct	tmdevice *TMcsr[NTM + 1] =
+ 		{
+ 		(struct tmdevice *)0172520,
+ 		(struct tmdevice *)0,
+ 		(struct tmdevice *)-1
+ 		};
+ 
  extern int tapemark;	/* flag to indicate tapemark 
  			has been encountered (see sys.c) 	*/
  
  /*
!  * Bits in device code.
   */
  #define	T_NOREWIND	04		/* not used in stand alone driver */
! #define	TMDENS(dev)	(((dev) & 030) >> 3)
  
! tmclose(io)
! 	struct iob *io;
  {
  	tmstrategy(io, TM_REW);
  }
***************
*** 38,43 ****
--- 44,51 ----
  {
  	register skip;
  
+ 	if (genopen(NTM, io) < 0)
+ 		return(-1);
  	tmstrategy(io, TM_REW);
  	skip = io->i_boff;
  	while (skip--) {
***************
*** 45,50 ****
--- 53,59 ----
  		while (tmstrategy(io, TM_SFORW))
  			continue;
  	}
+ 	return(0);
  }
  
  u_short tmdens[4] = { TM_D800, TM_D1600, TM_D6250, TM_D800 };
***************
*** 52,86 ****
  tmstrategy(io, func)
  	register struct iob *io;
  {
! 	register int com, unit, errcnt;
  
! 	unit = io->i_unit;
! 	errcnt = 0;
  retry:
! 	tmquiet();
! 	com = (TEUNIT(unit)<<8)|(segflag<<4) | tmdens[TEDENS(unit)];
! 	TMADDR->tmbc = -io->i_cc;
! 	TMADDR->tmba = io->i_ma;
  	if (func == READ)
! 		TMADDR->tmcs = com | TM_RCOM | TM_GO;
  	else if (func == WRITE)
! 		TMADDR->tmcs = com | TM_WCOM | TM_GO;
  	else if (func == TM_SREV) {
! 		TMADDR->tmbc = -1;
! 		TMADDR->tmcs = com | TM_SREV | TM_GO;
  		return(0);
  	} else
! 		TMADDR->tmcs = com | func | TM_GO;
! 	while ((TMADDR->tmcs&TM_CUR) == 0)
  		continue;
! 	if (TMADDR->tmer&TMER_EOF) {
  		tapemark=1;
  		return(0);
  	}
! 	if (TMADDR->tmer & TM_ERR) {
  		if (errcnt == 0)
! 			printf("\nTM unit %d tape error: er=%o cs=%o",
! 				unit, TMADDR->tmer, TMADDR->tmcs);
  		if (errcnt++ == 10) {
  			printf("\n(FATAL ERROR)\n");
  			return(-1);
--- 61,101 ----
  tmstrategy(io, func)
  	register struct iob *io;
  {
! 	register int com, unit = UNITn(io->i_unit);
! 	register struct tmdevice *tmaddr;
! 	int errcnt = 0, ctlr = CTLRn(io->i_unit);
  
! 	tmaddr = TMcsr[ctlr];
  retry:
! 	while ((tmaddr->tmcs&TM_CUR) == 0)
! 		continue;
! 	while ((tmaddr->tmer&TMER_TUR) == 0)
! 		continue;
! 	while ((tmaddr->tmer&TMER_SDWN) != 0)
! 		continue;
! 	com = (unit<<8)|(segflag<<4) | tmdens[TMDENS(unit)];
! 	tmaddr->tmbc = -io->i_cc;
! 	tmaddr->tmba = io->i_ma;
  	if (func == READ)
! 		tmaddr->tmcs = com | TM_RCOM | TM_GO;
  	else if (func == WRITE)
! 		tmaddr->tmcs = com | TM_WCOM | TM_GO;
  	else if (func == TM_SREV) {
! 		tmaddr->tmbc = -1;
! 		tmaddr->tmcs = com | TM_SREV | TM_GO;
  		return(0);
  	} else
! 		tmaddr->tmcs = com | func | TM_GO;
! 	while ((tmaddr->tmcs&TM_CUR) == 0)
  		continue;
! 	if (tmaddr->tmer&TMER_EOF) {
  		tapemark=1;
  		return(0);
  	}
! 	if (tmaddr->tmer & TM_ERR) {
  		if (errcnt == 0)
! 			printf("\nTM%d,%d err: er=%o cs=%o",
! 				ctlr, unit, tmaddr->tmer, tmaddr->tmcs);
  		if (errcnt++ == 10) {
  			printf("\n(FATAL ERROR)\n");
  			return(-1);
***************
*** 88,104 ****
  		tmstrategy(io, TM_SREV);
  		goto retry;
  	}
! 	if (errcnt)
! 		printf("\n(RECOVERED by retry)\n");
! 	return(io->i_cc+TMADDR->tmbc);
! }
! 
! tmquiet()
! {
! 	while ((TMADDR->tmcs&TM_CUR) == 0)
! 		continue;
! 	while ((TMADDR->tmer&TMER_TUR) == 0)
! 		continue;
! 	while ((TMADDR->tmer&TMER_SDWN) != 0)
! 		continue;
  }
--- 103,107 ----
  		tmstrategy(io, TM_SREV);
  		goto retry;
  	}
! 	return(io->i_cc+tmaddr->tmbc);
  }
*** /usr/src/sys/pdpstand.old/tmscp.c	Wed Dec 19 10:18:53 1990
--- /usr/src/sys/pdpstand/tmscp.c	Sun Apr 21 00:21:54 1991
***************
*** 26,35 ****
   */
   
  /* static char *sccsid = "@(#)tmscp.c	1.5	(ULTRIX) 4/18/86"; */
!  
  /* ------------------------------------------------------------------------
   * Modification History: /sys/pdpstand/tmscp.c
   *
   * 8-20-90 steven m. schultz (sms at wlv.imsd.contel.com)
   *	Port from 4.3BSD to 2.11BSD
   * 3-15-85  afd
--- 26,36 ----
   */
   
  /* static char *sccsid = "@(#)tmscp.c	1.5	(ULTRIX) 4/18/86"; */
! 
  /* ------------------------------------------------------------------------
   * Modification History: /sys/pdpstand/tmscp.c
   *
+  * 4-20-91 sms - add multi controller and unit support (sms)
   * 8-20-90 steven m. schultz (sms at wlv.imsd.contel.com)
   *	Port from 4.3BSD to 2.11BSD
   * 3-15-85  afd
***************
*** 44,50 ****
  #include "../h/param.h"
  #include "../h/inode.h"
  #include "saio.h"
!  
  /*
   * Parameters for the communications area
   * (Only 1 cmd & 1 rsp packet)
--- 45,51 ----
  #include "../h/param.h"
  #include "../h/inode.h"
  #include "saio.h"
! 
  /*
   * Parameters for the communications area
   * (Only 1 cmd & 1 rsp packet)
***************
*** 53,76 ****
  #define	NCMDL2	0
  #define	NRSP	(1<<NRSPL2)
  #define	NCMD	(1<<NCMDL2)
!  
  #include "../pdpuba/tmscpreg.h"
  #include "../pdp/tmscp.h"
  
! struct tmscpdevice *tmscpaddr = (struct tmscpdevice *)0174500;
   
  struct tmscp {
  	struct tmscpca	tmscp_ca;
  	struct mscp	tmscp_rsp;
  	struct mscp	tmscp_cmd;
! 	} tmscp;
   
! struct mscp *tmscpcmd();
   
- int tmsoffline = 1;		/* Flag to prevent multiple STCON */
- u_char tms_offline[4] = {1,1,1,1}; /* Flag to prevent multiple ONLIN */
- static char opnmsg[] = "tmscpopen: step %d not successful sa=0%o\n";
-  
  extern int tapemark;		/* flag to indicate tapemark encountered
  				   (see sys.c as to how it's used) */
   
--- 54,84 ----
  #define	NCMDL2	0
  #define	NRSP	(1<<NRSPL2)
  #define	NCMD	(1<<NCMDL2)
! 
  #include "../pdpuba/tmscpreg.h"
  #include "../pdp/tmscp.h"
  
! #define	NTMS	2
! #define	TMSDENS(dev) ((minor(dev) >> 3) & 3)	/* unused for now */
! 
! 	struct	tmscpdevice *TMScsr[NTMS + 1] =
! 		{
! 		(struct tmscpdevice *)0174500,
! 		(struct tmscpdevice *)0,
! 		(struct tmscpdevice *)-1
! 		};
   
  struct tmscp {
  	struct tmscpca	tmscp_ca;
  	struct mscp	tmscp_rsp;
  	struct mscp	tmscp_cmd;
! 	} tmscp[NTMS];
   
! u_char tmsoffline[NTMS] = {1, 1};	/* Flag to prevent multiple STCON */
! u_char tms_offline[NTMS][4] = {{1,1,1,1},
! 			       {1,1,1,1}}; /* Flag to prevent multiple ONLIN */
! static char opnmsg[] = "tms%d: step %d failed sa=0%o\n";
   
  extern int tapemark;		/* flag to indicate tapemark encountered
  				   (see sys.c as to how it's used) */
   
***************
*** 80,92 ****
  tmscpopen(io)
  	register struct iob *io;
  {
! 	register struct mscp *mp;
   
  	/*
  	 * Have the tmscp controller characteristics already been set up
  	 * (STCON)?
  	 */
! 	if (tmsoffline)
  		{
  		/*
  		 * Initialize the tmscp device and wait for the 4 steps
--- 88,106 ----
  tmscpopen(io)
  	register struct iob *io;
  {
! 	register struct tmscpdevice *tmscpaddr;
! 	int ctlr = CTLRn(io->i_unit);
! 	register struct tmscp *tms = &tmscp[ctlr];
   
+ 	if (genopen(NTMS, io) < 0)
+ 		return(-1);
+ 	tmscpaddr = TMScsr[ctlr];
+ 
  	/*
  	 * Have the tmscp controller characteristics already been set up
  	 * (STCON)?
  	 */
! 	if (tmsoffline[ctlr])
  		{
  		/*
  		 * Initialize the tmscp device and wait for the 4 steps
***************
*** 102,109 ****
  #		define STEP1MASK 0174377
  #		define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2)
  		if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD)
! 			printf(opnmsg, 1, tmscpaddr->tmscpsa);
! 		tmscpaddr->tmscpsa = (short)&tmscp.tmscp_ca.ca_ringbase;
   
  		while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0)
  			;
--- 116,123 ----
  #		define STEP1MASK 0174377
  #		define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2)
  		if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD)
! 			printf(opnmsg, ctlr, 1, tmscpaddr->tmscpsa);
! 		tmscpaddr->tmscpsa = (short)&tms->tmscp_ca.ca_ringbase;
   
  		while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0)
  			;
***************
*** 110,116 ****
  #		define STEP2MASK 0174377
  #		define STEP2GOOD (TMSCP_STEP3)
  		if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD)
! 			printf(opnmsg, 2, tmscpaddr->tmscpsa);
  		tmscpaddr->tmscpsa = (short) (segflag & 3);
   
  		while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0)
--- 124,130 ----
  #		define STEP2MASK 0174377
  #		define STEP2GOOD (TMSCP_STEP3)
  		if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD)
! 			printf(opnmsg, ctlr, 2, tmscpaddr->tmscpsa);
  		tmscpaddr->tmscpsa = (short) (segflag & 3);
   
  		while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0)
***************
*** 118,159 ****
  #		define STEP3MASK 0174000
  #		define STEP3GOOD TMSCP_STEP4
  		if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD)
! 			printf(opnmsg, 2, tmscpaddr->tmscpsa);
  		tmscpaddr->tmscpsa = TMSCP_GO;
!  
! 		if (tmscpcmd(M_OP_STCON, 0) == 0)
  			{
! 			_stop("tms: open error, STCON");
! 			return;
  			}
! 		tmsoffline = 0;
  		}
! 	tmscp.tmscp_cmd.mscp_unit = io->i_unit&03;
  	/* 
  	 * Has this unit been issued an ONLIN?
  	 */
! 	if (tms_offline[tmscp.tmscp_cmd.mscp_unit])
  		{
! 		if ((mp = tmscpcmd(M_OP_ONLIN, 0)) == 0)
  			{
! 			_stop("tms: open error, ONLIN");
! 			return;
  			}
! 		tms_offline[tmscp.tmscp_cmd.mscp_unit] = 0;
  		}
! 	if (io->i_boff < 0)
! 		_stop("tms: bad offset");
  	else if (io->i_boff > 0)
  		/*
  		 * Skip forward the appropriate number of files on the tape.
  		 */
  		{
! 		tmscp.tmscp_cmd.mscp_tmkcnt = io->i_boff;
! 		tmscp.tmscp_cmd.mscp_buffer_h = 0;
! 		tmscp.tmscp_cmd.mscp_bytecnt = 0;
! 		tmscpcmd(M_OP_REPOS, 0);
! 		tmscp.tmscp_cmd.mscp_tmkcnt = 0;
  		}
  }
   
  /*
--- 132,176 ----
  #		define STEP3MASK 0174000
  #		define STEP3GOOD TMSCP_STEP4
  		if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD)
! 			printf(opnmsg, ctlr, 2, tmscpaddr->tmscpsa);
  		tmscpaddr->tmscpsa = TMSCP_GO;
! 		if (tmscpcmd(ctlr, M_OP_STCON, 0) == 0)
  			{
! 			printf("tms%d STCON", ctlr);
! 			return(-1);
  			}
! 		tmsoffline[ctlr] = 0;
  		}
! 	tms->tmscp_cmd.mscp_unit = UNITn(io->i_unit);
  	/* 
  	 * Has this unit been issued an ONLIN?
  	 */
! 	if (tms_offline[ctlr][tms->tmscp_cmd.mscp_unit])
  		{
! 		if (tmscpcmd(ctlr, M_OP_ONLIN, 0) == 0)
  			{
! 			printf("tms%d ONLIN", ctlr);
! 			return(-1);
  			}
! 		tms_offline[ctlr][tms->tmscp_cmd.mscp_unit] = 0;
  		}
! 	tmscpclose(io);		/* close just does a rewind */
! 	if (io->i_boff < 0) {
! 		printf("tms%d bad offset", ctlr);
! 		return(-1);
! 	}
  	else if (io->i_boff > 0)
  		/*
  		 * Skip forward the appropriate number of files on the tape.
  		 */
  		{
! 		tms->tmscp_cmd.mscp_tmkcnt = io->i_boff;
! 		tms->tmscp_cmd.mscp_buffer_h = 0;
! 		tms->tmscp_cmd.mscp_bytecnt = 0;
! 		tmscpcmd(ctlr, M_OP_REPOS, 0);
! 		tms->tmscp_cmd.mscp_tmkcnt = 0;
  		}
+ 	return(0);
  }
   
  /*
***************
*** 162,171 ****
  tmscpclose(io)
  	register struct iob *io;
  {
! 	tmscp.tmscp_cmd.mscp_buffer_l = 0;	/* tmkcnt */
! 	tmscp.tmscp_cmd.mscp_buffer_h = 0;
! 	tmscp.tmscp_cmd.mscp_bytecnt = 0;
! 	tmscpcmd(M_OP_REPOS, M_MD_REWND | M_MD_CLSEX);
  }
   
  /*
--- 179,192 ----
  tmscpclose(io)
  	register struct iob *io;
  {
! 	register int ctlr = CTLRn(io->i_unit);
! 	register struct tmscp *tms = &tmscp[ctlr];
! 
! 	tms->tmscp_cmd.mscp_buffer_l = 0;	/* tmkcnt */
! 	tms->tmscp_cmd.mscp_buffer_h = 0;
! 	tms->tmscp_cmd.mscp_bytecnt = 0;
! 	tms->tmscp_cmd.mscp_unit = UNITn(io->i_unit);
! 	tmscpcmd(ctlr, M_OP_REPOS, M_MD_REWND | M_MD_CLSEX);
  }
   
  /*
***************
*** 172,181 ****
   * Set up tmscp command packet.  Cause the controller to poll to pick up
   * the command.
   */
! struct mscp *
! tmscpcmd(op,mod)
! 	register int op, mod;		/* opcode and modifier (usu 0) */
  {
  	register struct mscp *mp;	/* ptr to cmd packet */
  	int i;				/* read into to init polling */
   
--- 193,203 ----
   * Set up tmscp command packet.  Cause the controller to poll to pick up
   * the command.
   */
! tmscpcmd(ctlr, op,mod)
! 	register int ctlr;
! 	int op, mod;		/* opcode and modifier (usu 0) */
  {
+ 	register struct tmscp *tms = &tmscp[ctlr];
  	register struct mscp *mp;	/* ptr to cmd packet */
  	int i;				/* read into to init polling */
   
***************
*** 182,214 ****
  	/*
  	 * Init cmd & rsp area
  	 */
! 	tmscp.tmscp_ca.ca_cmddsc[0].lsh = (short)&tmscp.tmscp_cmd.mscp_cmdref;
! 	tmscp.tmscp_ca.ca_cmddsc[0].hsh = segflag & 3;
! 	tmscp.tmscp_cmd.mscp_dscptr = (long *)tmscp.tmscp_ca.ca_cmddsc;
! 	tmscp.tmscp_cmd.mscp_header.tmscp_vcid = 1;	/* for tape */
! 	tmscp.tmscp_ca.ca_rspdsc[0].lsh = (short)&tmscp.tmscp_rsp.mscp_cmdref;
! 	tmscp.tmscp_ca.ca_rspdsc[0].hsh = segflag & 3;
! 	tmscp.tmscp_rsp.mscp_dscptr = (long *)tmscp.tmscp_ca.ca_rspdsc;
! 	tmscp.tmscp_cmd.mscp_cntflgs = 0;
  
! 	tmscp.tmscp_cmd.mscp_opcode = op;
! 	tmscp.tmscp_cmd.mscp_modifier = mod;
! 	tmscp.tmscp_cmd.mscp_header.tmscp_msglen = mscp_msglen;
! 	tmscp.tmscp_ca.ca_cmddsc[0].hsh |= TMSCP_OWN;	/* | TMSCP_INT */
! 	tmscp.tmscp_rsp.mscp_header.tmscp_msglen = mscp_msglen;
! 	tmscp.tmscp_ca.ca_rspdsc[0].hsh |= TMSCP_OWN;	/* | TMSCP_INT */
! 	tmscp.tmscp_cmd.mscp_zzz2 = 0;
   
! 	i = tmscpaddr->tmscpip;
  	for (;;)
  		{
! 		if (tmscpaddr->tmscpsa & TMSCP_ERR) {
! 			printf("tmscpcmd: Fatal error sa=%o\n",tmscpaddr->tmscpsa);
  			return(0);
  		}
   
! 		if (tmscp.tmscp_ca.ca_cmdint)
! 			tmscp.tmscp_ca.ca_cmdint = 0;
  		/*
  		 * This is to handle the case of devices not setting the
  		 * interrupt field in the communications area. Some
--- 204,237 ----
  	/*
  	 * Init cmd & rsp area
  	 */
! 	tms->tmscp_ca.ca_cmddsc[0].lsh = (short)&tms->tmscp_cmd.mscp_cmdref;
! 	tms->tmscp_ca.ca_cmddsc[0].hsh = segflag & 3;
! 	tms->tmscp_cmd.mscp_dscptr = (long *)tms->tmscp_ca.ca_cmddsc;
! 	tms->tmscp_cmd.mscp_header.tmscp_vcid = 1;	/* for tape */
! 	tms->tmscp_ca.ca_rspdsc[0].lsh = (short)&tms->tmscp_rsp.mscp_cmdref;
! 	tms->tmscp_ca.ca_rspdsc[0].hsh = segflag & 3;
! 	tms->tmscp_rsp.mscp_dscptr = (long *)tms->tmscp_ca.ca_rspdsc;
! 	tms->tmscp_cmd.mscp_cntflgs = 0;
  
! 	tms->tmscp_cmd.mscp_opcode = op;
! 	tms->tmscp_cmd.mscp_modifier = mod;
! 	tms->tmscp_cmd.mscp_header.tmscp_msglen = mscp_msglen;
! 	tms->tmscp_ca.ca_cmddsc[0].hsh |= TMSCP_OWN;	/* | TMSCP_INT */
! 	tms->tmscp_rsp.mscp_header.tmscp_msglen = mscp_msglen;
! 	tms->tmscp_ca.ca_rspdsc[0].hsh |= TMSCP_OWN;	/* | TMSCP_INT */
! 	tms->tmscp_cmd.mscp_zzz2 = 0;
   
! 	i = TMScsr[ctlr]->tmscpip;
  	for (;;)
  		{
! 		if (TMScsr[ctlr]->tmscpsa & TMSCP_ERR) {
! 			printf("tmscp%d: Fatal error sa=%o\n",
! 				ctlr, TMScsr[ctlr]->tmscpsa);
  			return(0);
  		}
   
! 		if (tms->tmscp_ca.ca_cmdint)
! 			tms->tmscp_ca.ca_cmdint = 0;
  		/*
  		 * This is to handle the case of devices not setting the
  		 * interrupt field in the communications area. Some
***************
*** 216,229 ****
  		 * in the Response Descriptor.
  		 */
  /*
! 		if (tmscp.tmscp_ca.ca_rspint)
  			break;
  */
! 		if (!(tmscp.tmscp_ca.ca_rspdsc[0].hsh & TMSCP_OWN))
  			break;
  		}
! 	tmscp.tmscp_ca.ca_rspint = 0;
! 	mp = &tmscp.tmscp_rsp;
  	if (mp->mscp_opcode != (op|M_OP_END) ||
  	   (mp->mscp_status&M_ST_MASK) != M_ST_SUCC) {
  		/* Detect hitting tape mark.  This signifies the end of the
--- 239,252 ----
  		 * in the Response Descriptor.
  		 */
  /*
! 		if (tms->tmscp_ca.ca_rspint)
  			break;
  */
! 		if (!(tms->tmscp_ca.ca_rspdsc[0].hsh & TMSCP_OWN))
  			break;
  		}
! 	tms->tmscp_ca.ca_rspint = 0;
! 	mp = &tms->tmscp_rsp;
  	if (mp->mscp_opcode != (op|M_OP_END) ||
  	   (mp->mscp_status&M_ST_MASK) != M_ST_SUCC) {
  		/* Detect hitting tape mark.  This signifies the end of the
***************
*** 233,243 ****
  		 */
  		if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM) {
  			tapemark = 1;
! 			return(mp);
  		}
  		return(0);
  	}
! 	return(mp);
  }
   
  /*
--- 256,266 ----
  		 */
  		if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM) {
  			tapemark = 1;
! 			return(1);
  		}
  		return(0);
  	}
! 	return(1);
  }
   
  /*
***************
*** 247,263 ****
  	register struct iob *io;
  	int func;
  {
  	register struct mscp *mp;
   
! 	mp = &tmscp.tmscp_cmd;
  	mp->mscp_lbn_l = loint(io->i_bn);
  	mp->mscp_lbn_h = hiint(io->i_bn);
! 	mp->mscp_unit = io->i_unit&03;
  	mp->mscp_bytecnt = io->i_cc;
  	mp->mscp_buffer_l = (u_short)io->i_ma;
  	mp->mscp_buffer_h = segflag & 3;
! 	if ((mp = tmscpcmd(func == READ ? M_OP_READ : M_OP_WRITE, 0)) == 0) {
! 		printf("tms: I/O error\n");
  		return(-1);
  	}
  	/*
--- 270,288 ----
  	register struct iob *io;
  	int func;
  {
+ 	int ctlr = CTLRn(io->i_unit);
+ 	register struct tmscp *tms = &tmscp[ctlr];
  	register struct mscp *mp;
   
! 	mp = &tms->tmscp_cmd;
  	mp->mscp_lbn_l = loint(io->i_bn);
  	mp->mscp_lbn_h = hiint(io->i_bn);
! 	mp->mscp_unit = UNITn(io->i_unit);
  	mp->mscp_bytecnt = io->i_cc;
  	mp->mscp_buffer_l = (u_short)io->i_ma;
  	mp->mscp_buffer_h = segflag & 3;
! 	if (tmscpcmd(ctlr, func == READ ? M_OP_READ : M_OP_WRITE, 0)==0) {
! 		printf("tms%d,%d: I/O err\n", ctlr, UNITn(io->i_unit));
  		return(-1);
  	}
  	/*
***************
*** 264,270 ****
  	 * Detect hitting tape mark so we do it gracefully and return a
  	 * character count of 0 to signify end of copy.
  	 */
! 	if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM)
  		return(0);
  	return(io->i_cc);
  }
--- 289,295 ----
  	 * Detect hitting tape mark so we do it gracefully and return a
  	 * character count of 0 to signify end of copy.
  	 */
! 	if (tapemark)
  		return(0);
  	return(io->i_cc);
  }
*** /usr/src/sys/pdpstand.old/ts.c	Sat Aug 20 21:49:47 1988
--- /usr/src/sys/pdpstand/ts.c	Wed Apr 24 20:32:32 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ts.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.
   *
!  *	@(#)ts.c	2.0 (2.11BSD) 4/20/91
   */
  
  /*
***************
*** 18,58 ****
  extern int tapemark;	/* flag to indicate tapemark encountered
  			   (see sys.c as to how its used) */
  
! caddr_t tsptr;
! struct	ts_char	chrbuf;		/* characteristics buffer */
! struct	ts_sts	mesbuf;		/* message buffer */
! struct	ts_cmd	*combuf;	/* command packet buffer */
! char	softspace[sizeof(struct ts_cmd)+3];
  
! #define	TSADDR	((struct tsdevice *)0172520)
  
  
  	/* bit definitions for Command mode field during read command */
  #define	TS_RPREV	0400	/* read previous (reverse) */
  
- 
  tsopen(io)
  	register struct iob *io;
  {
! 	register skip;
  
  	/* combuf must be alligned on a mod 4 byte boundary */
! 	combuf = (struct ts_cmd *)((u_short)softspace + 3 & ~3);
! 	tsptr = (caddr_t)((int)&combuf->c_cmd | (int)segflag);
! 	combuf->c_cmd = (TS_ACK|TS_CVC|TS_INIT);
! 	TSADDR->tsdb = (u_short) tsptr;
! 	while ((TSADDR->tssr & TS_SSR) == 0)
  		continue;
! 	chrbuf.char_bptr = (u_short) &mesbuf;
! 	chrbuf.char_bae = segflag;
! 	chrbuf.char_size = 016;
! 	chrbuf.char_mode = 0;
! 	combuf->c_cmd = (TS_ACK|TS_CVC|TS_SETCHR);
! 	combuf->c_loba = (u_short) &chrbuf;
! 	combuf->c_hiba = segflag;
! 	combuf->c_size = 010;
! 	TSADDR->tsdb = (u_short) tsptr;
! 	while ((TSADDR->tssr & TS_SSR) == 0)
  		continue;
  	tsstrategy(io, TS_REW);
  	skip = io->i_boff;
--- 18,75 ----
  extern int tapemark;	/* flag to indicate tapemark encountered
  			   (see sys.c as to how its used) */
  
! #define	NTS	2
  
! 	struct	tsdevice *TScsr[NTS + 1] =
! 		{
! 		(struct tsdevice *)0172520,
! 		(struct tsdevice *)0,
! 		(struct tsdevice *)-1
! 		};
  
+ caddr_t tsptr[NTS];
+ struct	ts_char	chrbuf[NTS];		/* characteristics buffer */
+ struct	ts_sts	mesbuf[NTS];		/* message buffer */
+ struct	ts_cmd	*combuf[NTS];		/* command packet buffer */
+ char	softspace[(NTS * sizeof(struct ts_cmd)) + 3];
  
  	/* bit definitions for Command mode field during read command */
  #define	TS_RPREV	0400	/* read previous (reverse) */
  
  tsopen(io)
  	register struct iob *io;
  {
! 	int skip;
! 	register struct tsdevice *tsaddr;
! 	register struct ts_char *chrb;
! 	struct ts_cmd *cmb;
! 	int ctlr = CTLRn(io->i_unit);
! 	char *cp;
  
+ 	if (genopen(NTS, io) < 0)
+ 		return(-1);
+ 	tsaddr = TScsr[ctlr];
+ 
  	/* combuf must be alligned on a mod 4 byte boundary */
! 	cp = (char *)((u_short)softspace + 3 & ~3);
! 	cp += (ctlr * sizeof (struct ts_cmd));
! 	cmb = combuf[ctlr] = (struct ts_cmd *)cp;
! 	tsptr[ctlr] = (caddr_t)((int)&combuf[ctlr]->c_cmd | (int)segflag);
! 	cmb->c_cmd = (TS_ACK|TS_CVC|TS_INIT);
! 	tsaddr->tsdb = (u_short) tsptr[ctlr];
! 	while ((tsaddr->tssr & TS_SSR) == 0)
  		continue;
! 	chrb = &chrbuf[ctlr];
! 	chrb->char_bptr = (u_short) &mesbuf;
! 	chrb->char_bae = segflag;
! 	chrb->char_size = 016;
! 	chrb->char_mode = 0;
! 	cmb->c_cmd = (TS_ACK|TS_CVC|TS_SETCHR);
! 	cmb->c_loba = (u_short) &chrbuf;
! 	cmb->c_hiba = segflag;
! 	cmb->c_size = 010;
! 	tsaddr->tsdb = (u_short) tsptr[ctlr];
! 	while ((tsaddr->tssr & TS_SSR) == 0)
  		continue;
  	tsstrategy(io, TS_REW);
  	skip = io->i_boff;
***************
*** 61,69 ****
  		while (tsstrategy(io, TS_SFORW))
  			continue;
  	}
  }
  tsclose(io)
! 	register struct iob *io;
  {
  	tsstrategy(io, TS_REW);
  }
--- 78,88 ----
  		while (tsstrategy(io, TS_SFORW))
  			continue;
  	}
+ 	return(0);
  }
+ 
  tsclose(io)
! 	struct iob *io;
  {
  	tsstrategy(io, TS_REW);
  }
***************
*** 71,119 ****
  tsstrategy(io, func)
  	register struct iob *io;
  {
! 	register unit, errcnt;
  
! 	unit = io->i_unit;
  	errcnt = 0;
! 	combuf->c_loba = (u_short) io->i_ma;
! 	combuf->c_hiba = segflag;
! 	combuf->c_size = io->i_cc;
  	if (func == READ)
! 		combuf->c_cmd = TS_ACK|TS_RCOM;
  	else if (func == WRITE)
! 		combuf->c_cmd = TS_ACK|TS_WCOM;
  	else
! 		combuf->c_cmd = TS_ACK|func;
! 	TSADDR->tsdb = (u_short) tsptr;
  retry:
! 	while ((TSADDR->tssr & TS_SSR) == 0)
  		continue;
! 	if (mesbuf.s_xs0 & TS_TMK) {
  		tapemark = 1;
  		return(0);
  	}
! 	if (TSADDR->tssr & TS_SC) {
  		if (errcnt == 0)
! 		    printf("\nTS tape error: sr=%o xs0=%o xs1=%o xs2=%o xs3=%o",
! 			TSADDR->tssr,
! 			mesbuf.s_xs0, mesbuf.s_xs1,
! 			mesbuf.s_xs2, mesbuf.s_xs3);
  		if (errcnt++ == 10) {
  			printf("\n(FATAL ERROR)\n");
  			return(-1);
  		}
  		if (func == READ)
! 			combuf->c_cmd = (TS_ACK|TS_RPREV|TS_RCOM);
  		else if (func == WRITE)
! 			combuf->c_cmd = (TS_ACK|TS_RETRY|TS_WCOM);
  		else {
  			printf("\n");
  			return(-1);
  		}
! 		TSADDR->tsdb = (u_short) tsptr;
  		goto retry;
  	}
! 	if (errcnt)
! 		printf("\n(RECOVERED by retry)\n");
! 	return (io->i_cc+mesbuf.s_rbpcr);
  }
--- 90,138 ----
  tsstrategy(io, func)
  	register struct iob *io;
  {
! 	register int ctlr = CTLRn(io->i_unit);
! 	int errcnt, unit;
! 	register struct tsdevice *tsaddr = TScsr[ctlr];
  
! 	unit = UNITn(io->i_unit);
  	errcnt = 0;
! 	combuf[ctlr]->c_loba = (u_short) io->i_ma;
! 	combuf[ctlr]->c_hiba = segflag;
! 	combuf[ctlr]->c_size = io->i_cc;
  	if (func == READ)
! 		combuf[ctlr]->c_cmd = TS_ACK|TS_RCOM;
  	else if (func == WRITE)
! 		combuf[ctlr]->c_cmd = TS_ACK|TS_WCOM;
  	else
! 		combuf[ctlr]->c_cmd = TS_ACK|func;
! 	tsaddr->tsdb = (u_short) tsptr[ctlr];
  retry:
! 	while ((tsaddr->tssr & TS_SSR) == 0)
  		continue;
! 	if (mesbuf[ctlr].s_xs0 & TS_TMK) {
  		tapemark = 1;
  		return(0);
  	}
! 	if (tsaddr->tssr & TS_SC) {
  		if (errcnt == 0)
! 		    printf("\nTS%d,%d err sr=%o xs0=%o xs1=%o xs2=%o xs3=%o",
! 			ctlr, UNITn(io->i_unit), tsaddr->tssr,
! 			mesbuf[ctlr].s_xs0, mesbuf[ctlr].s_xs1,
! 			mesbuf[ctlr].s_xs2, mesbuf[ctlr].s_xs3);
  		if (errcnt++ == 10) {
  			printf("\n(FATAL ERROR)\n");
  			return(-1);
  		}
  		if (func == READ)
! 			combuf[ctlr]->c_cmd = (TS_ACK|TS_RPREV|TS_RCOM);
  		else if (func == WRITE)
! 			combuf[ctlr]->c_cmd = (TS_ACK|TS_RETRY|TS_WCOM);
  		else {
  			printf("\n");
  			return(-1);
  		}
! 		tsaddr->tsdb = (u_short) tsptr[ctlr];
  		goto retry;
  	}
! 	return (io->i_cc+mesbuf[ctlr].s_rbpcr);
  }
*** /usr/src/sys/pdpstand.old/xp.c	Tue Sep 27 13:44:23 1988
--- /usr/src/sys/pdpstand/xp.c	Sat May  4 17:49:43 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)xp.c	1.2 (2.10BSD Berkeley) 1/12/88
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)xp.c	2.0 (2.11BSD) 4/20/91
   */
  
  /*
***************
*** 15,75 ****
  #include "../machine/iopage.h"
  #include "saio.h"
  
! #define	XPADDR	((struct hpdevice *)0176700)
  
! extern	char haveCSW;		/* bool, set if switch register exists */
  
  /*
   * Drive type; declared so we can patch; see hpreg.h for more information.
   */
! int	xptype = 0;
  
  xpstrategy(io, func)
  	register struct iob *io;
  {
! 	register unit;
! 	register i;
  	register nm_sect_per_cyl, nsect;
  	daddr_t bn;
  	int sn, cn, tn;
  
! 	if (((unit = io->i_unit) & 04) == 0)
! 		bn = io->i_bn;
! 	else {
! 		unit &= 03;
! 		bn = io->i_bn;
! 		bn -= io->i_boff;
! 		i = unit + 1;
! 		unit = bn%i;
! 		bn /= i;
! 		bn += io->i_boff;
! 	}
  
! 	XPADDR->hpcs2.w = unit;
! 
! 	if ((XPADDR->hpds & HPDS_VV) == 0) {
! 		XPADDR->hpcs1.c[0] = HP_PRESET|HP_GO;
! 		XPADDR->hpof = HPOF_FMT22;
  	}
  	/*
!  	 *	This next weirdness handled the look up into the Drive Type
!  	 *	register to tell what type of disk we have here.
! 	 *	Look in switch register first (if there is one).
!  	 *
!  	 *	Note: No need to look up after the first time.
   	 */
  	
! 	if (xptype == 0) {
! 		if (haveCSW && (*CSW == RP04 || *CSW == RP05 || *CSW == RP06
! 		    || *CSW == RM02 || *CSW == RM03 || *CSW == RM05
! 		    || *CSW == CAP  || *CSW == SI5  || *CSW == SI
! 		    || *CSW == RM2X || *CSW == RM5X || *CSW == DV))
! 			xptype = *CSW;
! 		else
! 			xptype = (XPADDR->hpdt & 077);
  	}
  
! 	switch (xptype) {
  	case RP04:
  	case RP05:
  	case RP06:
--- 15,73 ----
  #include "../machine/iopage.h"
  #include "saio.h"
  
! #define	NXP	2
  
! 	struct	hpdevice *XPcsr[NXP + 1] =
! 		{
! 		(struct hpdevice *)0176700,
! 		(struct hpdevice *)0,
! 		(struct hpdevice *)-1
! 		};
  
  /*
   * Drive type; declared so we can patch; see hpreg.h for more information.
   */
! int	xptype[NXP] = 0;
  
  xpstrategy(io, func)
  	register struct iob *io;
  {
! 	int unit = UNITn(io->i_unit);
! 	int ctlr = CTLRn(io->i_unit);
! 	int i;
  	register nm_sect_per_cyl, nsect;
  	daddr_t bn;
  	int sn, cn, tn;
+ 	struct hpdevice *xpaddr = XPcsr[ctlr];
  
! 	bn = io->i_bn;
! 	/*
! 	 * The weirdness involving bit 2 (04) in the unit # was removed
! 	 * because 1) the xp driver in the kernel didn't know about it,
! 	 * 2) no mention was made in any .h file or documentation/notes
! 	*/
! 	xpaddr->hpcs2.w = unit;
  
! 	if ((xpaddr->hpds & HPDS_VV) == 0) {
! 		xpaddr->hpcs1.c[0] = HP_PRESET|HP_GO;
! 		xpaddr->hpof = HPOF_FMT22;
  	}
  	/*
!  	 *	The weirdness of (possibly) looking at the console switch
!  	 *	register to tell what type of disk we have here was removed
! 	 *	because 1) most systems do not have one, 2) space contraints
! 	 *	imposed by adding multi controller support were creating a
! 	 * 	size problem, and 3) an alternative method is provided for
! 	 *	setting the type (the address and content is printed).
   	 */
  	
! 	if (xptype[ctlr] == 0) {
! 		xptype[ctlr] = (xpaddr->hpdt & 077);
! 		printf("\n&xptype=0%o xptype[%d]=0%o\n", xptype, ctlr, 
! 			xptype[ctlr]);
  	}
  
! 	switch (xptype[ctlr]) {
  	case RP04:
  	case RP05:
  	case RP06:
***************
*** 76,121 ****
  		nm_sect_per_cyl = HP_SECT * HP_TRAC;
  		nsect = HP_SECT;
  		break;
- 
  	case RM02:
  	case RM03:
  		nm_sect_per_cyl = RM_SECT * RM_TRAC;
  		nsect = RM_SECT;
  		break;
- 
  	case RM05:
  	case RM5X:
  		nm_sect_per_cyl = RM5_SECT * RM5_TRAC;
  		nsect = RM5_SECT;
  		break;
- 
  	case CAP:
  		nm_sect_per_cyl = CAP_SECT * CAP_TRAC;
  		nsect = CAP_SECT;
  		break;
- 
  	case SI5:
  		nm_sect_per_cyl = SI5_SECT * SI5_TRAC;
  		nsect = SI5_SECT;
  		break;
- 
  	case SI:
  		nm_sect_per_cyl = SI_SECT * SI_TRAC;
  		nsect = SI_SECT;
  		break;
- 
  	case RM2X:
  		nm_sect_per_cyl = RM2X_SECT * RM2X_TRAC;
  		nsect = RM2X_SECT;
  		break;
- 
  	case DV:
  		nm_sect_per_cyl = DV_SECT * DV_TRAC;
  		nsect = DV_SECT;
  		break;
- 
  	default:
! 		printf("xp: unknown device type 0%o\n", xptype);
  		return(-1);	
  	}
  	cn = bn/(nm_sect_per_cyl);
--- 74,111 ----
  		nm_sect_per_cyl = HP_SECT * HP_TRAC;
  		nsect = HP_SECT;
  		break;
  	case RM02:
  	case RM03:
  		nm_sect_per_cyl = RM_SECT * RM_TRAC;
  		nsect = RM_SECT;
  		break;
  	case RM05:
  	case RM5X:
  		nm_sect_per_cyl = RM5_SECT * RM5_TRAC;
  		nsect = RM5_SECT;
  		break;
  	case CAP:
  		nm_sect_per_cyl = CAP_SECT * CAP_TRAC;
  		nsect = CAP_SECT;
  		break;
  	case SI5:
  		nm_sect_per_cyl = SI5_SECT * SI5_TRAC;
  		nsect = SI5_SECT;
  		break;
  	case SI:
  		nm_sect_per_cyl = SI_SECT * SI_TRAC;
  		nsect = SI_SECT;
  		break;
  	case RM2X:
  		nm_sect_per_cyl = RM2X_SECT * RM2X_TRAC;
  		nsect = RM2X_SECT;
  		break;
  	case DV:
  		nm_sect_per_cyl = DV_SECT * DV_TRAC;
  		nsect = DV_SECT;
  		break;
  	default:
! 		printf("xp%d: unknown type 0%o\n", ctlr, xptype[ctlr]);
  		return(-1);	
  	}
  	cn = bn/(nm_sect_per_cyl);
***************
*** 123,144 ****
  	tn = sn/nsect;
  	sn = sn%nsect;
  
! 	XPADDR->hpdc = cn;
! 	XPADDR->hpda = (tn << 8) + sn;
! 	XPADDR->hpba = io->i_ma;
! 	XPADDR->hpwc = -(io->i_cc>>1);
! 	unit = (segflag << 8) | HP_GO;
  	if (func == READ)
! 		unit |= HP_RCOM;
  	else if (func == WRITE)
! 		unit |= HP_WCOM;
! 	XPADDR->hpcs1.w = unit;
! 	while ((XPADDR->hpcs1.w & HP_RDY) == 0)
  			continue;
! 	if (XPADDR->hpcs1.w & HP_TRE) {
! 		printf("disk error: cyl=%d track=%d sect=%d cs2=%o, er1=%o\n",
! 		    cn, tn, sn, XPADDR->hpcs2, XPADDR->hper1);
  		return(-1);
  	}
  	return(io->i_cc);
  }
--- 113,140 ----
  	tn = sn/nsect;
  	sn = sn%nsect;
  
! 	xpaddr->hpdc = cn;
! 	xpaddr->hpda = (tn << 8) + sn;
! 	xpaddr->hpba = io->i_ma;
! 	xpaddr->hpwc = -(io->i_cc>>1);
! 	i = (segflag << 8) | HP_GO;
  	if (func == READ)
! 		i |= HP_RCOM;
  	else if (func == WRITE)
! 		i |= HP_WCOM;
! 	xpaddr->hpcs1.w = i;
! 	while ((xpaddr->hpcs1.w & HP_RDY) == 0)
  			continue;
! 	if (xpaddr->hpcs1.w & HP_TRE) {
! 		printf("xp%d,%d err cy=%d tr=%d sc=%d cs2=%o er1=%o\n",
! 		    ctlr, unit, cn, tn, sn, xpaddr->hpcs2, xpaddr->hper1);
  		return(-1);
  	}
  	return(io->i_cc);
+ }
+ 
+ xpopen(io)
+ 	struct iob *io;
+ {
+ 	return(genopen(NXP, io));
  }



More information about the Comp.bugs.2bsd mailing list