*** /old/src/sys/pdpuba/ts.c	Tue Apr  3 09:55:25 1990
--- /usr/src/sys/pdpuba/ts.c	Sun Sep 22 08:43:39 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.2 (2.11BSD) 9/22/91
   */
  
  /*
***************
*** 21,26 ****
--- 21,28 ----
  #include "fs.h"
  #include "tsreg.h"
  #include "mtio.h"
+ #include "map.h"
+ #include "uba.h"
  
  /*
   * Software state per tape transport:
***************
*** 36,41 ****
--- 38,44 ----
   */
  
  struct	ts_softc {
+ 	struct	tsdevice *sc_addr; /* CSR of controller */
  	char	sc_openf;	/* lock against multiple opens */
  	char	sc_lastiow;	/* last op was a write */
  	short	sc_resid;	/* copy of last bc */
***************
*** 44,58 ****
  	struct	ts_cmd	sc_cmd;	/* the command packet */
  	struct	ts_char	sc_char;/* status packet, for returned status */
  	struct	ts_sts	sc_sts; /* characteristics packet */
- #ifdef UNIBUS_MAP
  	u_short	sc_uba;		/* Unibus addr of cmd pkt for tsdb */
  	ubadr_t	sc_uadr;	/* actual unibus address */
! 	short	sc_mapped;	/* is sc_cmd mapped in Unibus space? */
! #endif
! } *ts_softc;
  
! struct	buf	tstab;
  
  /*
   * There is a ctsbuf per tape controller.
   * It is used as the token to pass to the internal routines
--- 47,61 ----
  	struct	ts_cmd	sc_cmd;	/* the command packet */
  	struct	ts_char	sc_char;/* status packet, for returned status */
  	struct	ts_sts	sc_sts; /* characteristics packet */
  	u_short	sc_uba;		/* Unibus addr of cmd pkt for tsdb */
  	ubadr_t	sc_uadr;	/* actual unibus address */
! 	struct	tty *sc_ttyp;	/* record user's tty for errors */
! } *ts_softc[NTS];
  
! static	ubadr_t	TS_ubadr;
  
+ struct	buf	tstab[NTS];
+ 
  /*
   * There is a ctsbuf per tape controller.
   * It is used as the token to pass to the internal routines
***************
*** 61,86 ****
   * the user process but any further attempts to use the tape drive
   * before the rewind completes will hang waiting for ctsbuf.
   */
! struct	buf	ctsbuf;
  
- /*
-  * Raw tape operations use rtsbuf.  The driver
-  * notices when rtsbuf is being used and allows the user
-  * program to continue after errors and read records
-  * not of the standard length (DEV_BSIZE).
-  */
- struct	buf	rtsbuf;
- 
- struct	tsdevice *TSADDR;
- 
  #define	INF		((daddr_t) ((u_short) 65535))
  
  /* bits in minor device */
! #define	TSUNIT(dev)	(minor(dev)&03)
  #define	T_NOREWIND	04
  
- 	/* command code definitions */
- 
  /*
   * States for tstab.b_active, the state flag.
   * This is used to sequence control in the driver.
--- 64,78 ----
   * the user process but any further attempts to use the tape drive
   * before the rewind completes will hang waiting for ctsbuf.
   */
! struct	buf	ctsbuf[NTS];
  
  #define	INF		((daddr_t) ((u_short) 65535))
  
  /* bits in minor device */
! #define	TSUNIT(dev)	(minor(dev)&03)		/* not used */
! #define	TSCTLR(dev)	((minor(dev) >> 6) & 3)
  #define	T_NOREWIND	04
  
  /*
   * States for tstab.b_active, the state flag.
   * This is used to sequence control in the driver.
***************
*** 90,117 ****
  #define	SCOM		3	/* sending a control command */
  #define	SREW		4	/* sending a drive rewind */
  
! char softspace[sizeof(struct ts_softc)*NTS + 3];
  
  tsattach(addr, unit)
  struct tsdevice *addr;
  {
  	/*
! 	 * This driver supports only one controller.
  	 */
! 	if (unit == 0) {
! 		/*
! 		 * We want space for an array of NTS ts_softc structures,
! 		 * where the sc_cmd field of each is long-aligned, i.e. the
! 		 * core address is a 4-byte multiple.  The compiler only
! 		 * guarantees word alignment.  We reserve and extra 3 bytes
! 		 * so that we can slide the array down by 2 if the compiler
! 		 * gets it wrong.
! 		 */
! 		ts_softc = (struct ts_softc *)((u_short)softspace + 3 & ~3);
! 		TSADDR = addr;
! 		return(1);
  	}
! 	return(0);
  }
  
  /*
--- 82,136 ----
  #define	SCOM		3	/* sending a control command */
  #define	SREW		4	/* sending a drive rewind */
  
! u_short softspace[NTS][(sizeof(struct ts_softc)/2) + 1];
  
  tsattach(addr, unit)
  struct tsdevice *addr;
+ register int unit;
  {
+ 	register u_short sp = (u_short)softspace[unit];
+ 	register struct ts_softc *sc;
+ 	struct buf tbuf;
+ 
+ 	if (unit >= NTS)
+ 		return(0);
  	/*
! 	 * We want space for an array of NTS ts_softc structures,
! 	 * where the sc_cmd field of each is long-aligned, i.e. the
! 	 * core address is a 4-byte multiple.  The compiler only
! 	 * guarantees word alignment.  We reserve and extra 3 bytes
! 	 * so that we can slide the array down by 2 if the compiler
! 	 * gets it wrong.  Only allocate 1 UMR to map all of the
! 	 * communication area instead of a UMR per controller.
! 	 *
! 	 * On a UNIBUS system the ts_softc structure is aligned so
! 	 * that the UNIBUS virtual address of sc_cmd falls on a 4
! 	 * byte boundary - the physical address may be on a 2 byte bound.
! 	 *
! 	 * On non-UNIBUS systems the ts_softc structure is aligned so
! 	 * that sc_cmd falls on a physical 4 byte boundary.
  	 */
! 	sc = (struct ts_softc *)sp;
! 	if (((u_short)&sc->sc_cmd  - (ubmap ? (u_short)softspace : 0)) & 3)
! 		sp += 2;
! 	if (ubmap && TS_ubadr == 0) {
! 		tbuf.b_xmem = 0;	/* won't work above 64k any way */
! 		tbuf.b_un.b_addr = (caddr_t) softspace;
! 		tbuf.b_flags = B_PHYS;
! 		tbuf.b_bcount = sizeof (softspace);
! #ifdef	UNIBUS_MAP
! 		mapalloc(&tbuf);
! #endif
! 		TS_ubadr = ((long)((unsigned)tbuf.b_xmem)) << 16
! 				| ((long)((unsigned)tbuf.b_un.b_addr));
  	}
! 	sc = ts_softc[unit] = (struct ts_softc *) sp;
! 	sc->sc_addr = addr;
! 	sc->sc_uadr = TS_ubadr + ((u_short)&sc->sc_cmd - 
! 				(ubmap ? (u_short)softspace : 0));
! 	sc->sc_uba = loint(sc->sc_uadr) 
! 		   | hiint(sc->sc_uadr);	/* register format */
! 	return(1);
  }
  
  /*
***************
*** 123,150 ****
   */
  tsopen(dev, flag)
  dev_t	dev;
  {
! 	register tsunit;
! 	register struct ts_softc *sc;
  
! 	tsunit = TSUNIT(dev);
! 	if (TSADDR == (struct tsdevice *) NULL || tsunit >= NTS
! 	    || (sc = &ts_softc[tsunit])->sc_openf)
  		return(ENXIO);
! 	if(tsinit(tsunit)) {
! 		printf("ts%d: initialization failure tssr=%b\n",
! 			tsunit, TSADDR->tssr, TSSR_BITS);
  		return(ENXIO);
  	}
! 	tstab.b_flags |= B_TAPE;
  	tscommand(dev, TS_SENSE, 1);
  	if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) {
! 		uprintf("ts%d: not online\n", tsunit);
  		return(EIO);
  	}
  	if ((flag & (FREAD | FWRITE)) == FWRITE
  	    && (sc->sc_sts.s_xs0 & TS_WLK)) {
! 		uprintf("ts%d: no write ring\n", tsunit);
  		return(EIO);
  	}
  	sc->sc_openf = 1;
--- 142,168 ----
   */
  tsopen(dev, flag)
  dev_t	dev;
+ int	flag;
  {
! 	register ts11 = TSCTLR(dev);
! 	register struct ts_softc *sc = ts_softc[ts11];
  
! 	if (ts11 >= NTS || !sc || sc->sc_openf)
  		return(ENXIO);
! 	if (tsinit(ts11)) {
! 		printf("ts%d: init failure tssr=%b\n",
! 			ts11, sc->sc_addr->tssr, TSSR_BITS);
  		return(ENXIO);
  	}
! 	tstab[ts11].b_flags |= B_TAPE;
  	tscommand(dev, TS_SENSE, 1);
  	if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) {
! 		uprintf("ts%d: not online\n", ts11);
  		return(EIO);
  	}
  	if ((flag & (FREAD | FWRITE)) == FWRITE
  	    && (sc->sc_sts.s_xs0 & TS_WLK)) {
! 		uprintf("ts%d: no write ring\n", ts11);
  		return(EIO);
  	}
  	sc->sc_openf = 1;
***************
*** 151,156 ****
--- 169,175 ----
  	sc->sc_blkno = (daddr_t) 0;
  	sc->sc_nxrec = INF;
  	sc->sc_lastiow = 0;
+ 	sc->sc_ttyp = u.u_ttyp;
  	return(0);
  }
  
***************
*** 164,174 ****
   */
  tsclose(dev, flag)
  register dev_t	dev;
! register flag;
  {
! 	register struct ts_softc *sc = &ts_softc[TSUNIT(dev)];
  
! 	if(flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) {
  		tscommand(dev, TS_WEOF, 1);
  		tscommand(dev, TS_WEOF, 1);
  		tscommand(dev, TS_SREV, 1);
--- 183,193 ----
   */
  tsclose(dev, flag)
  register dev_t	dev;
! register int flag;
  {
! 	register struct ts_softc *sc = ts_softc[TSCTLR(dev)];
  
! 	if (flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) {
  		tscommand(dev, TS_WEOF, 1);
  		tscommand(dev, TS_WEOF, 1);
  		tscommand(dev, TS_SREV, 1);
***************
*** 189,201 ****
   * a specified number of times.
   */
  tscommand(dev, com, count)
! dev_t	dev;
  register u_short count;
  {
! 	register s;
  	register struct buf *bp;
  
! 	bp = &ctsbuf;
  	s = splbio();
  	while(bp->b_flags & B_BUSY) {
  		/*
--- 208,220 ----
   * a specified number of times.
   */
  tscommand(dev, com, count)
! 	dev_t	dev;
  register u_short count;
  {
! 	register int s;
  	register struct buf *bp;
  
! 	bp = &ctsbuf[TSCTLR(dev)];
  	s = splbio();
  	while(bp->b_flags & B_BUSY) {
  		/*
***************
*** 233,256 ****
  register struct buf *bp;
  {
  	register int s;
  
  #ifdef UNIBUS_MAP
- 	if (bp->b_flags & B_PHYS)	/* if RAW I/O call */
  		mapalloc(bp);
  #endif
  	bp->av_forw = NULL;
  	s = splbio();
! 	if (tstab.b_actf == NULL)
! 		tstab.b_actf = bp;
  	else
! 		tstab.b_actl->av_forw = bp;
! 	tstab.b_actl = bp;
  	/*
  	 * If the controller is not busy, get
  	 * it going.
  	 */
! 	if (tstab.b_active == 0)
! 		tsstart();
  	splx(s);
  }
  
--- 252,281 ----
  register struct buf *bp;
  {
  	register int s;
+ 	int ts11 = TSCTLR(bp->b_dev);
+ 	struct ts_softc *sc = ts_softc[ts11];
+ 	register struct buf *dp = &tstab[ts11];
  
+ 	if (bp->b_flags & B_PHYS) {	/* if RAW I/O call */
  #ifdef UNIBUS_MAP
  		mapalloc(bp);
  #endif
+ 		sc->sc_blkno = sc->sc_nxrec = dbtofsb(bp->b_blkno);
+ 		sc->sc_nxrec++;
+ 	}
  	bp->av_forw = NULL;
  	s = splbio();
! 	if (dp->b_actf == NULL)
! 		dp->b_actf = bp;
  	else
! 		dp->b_actl->av_forw = bp;
! 	dp->b_actl = bp;
  	/*
  	 * If the controller is not busy, get
  	 * it going.
  	 */
! 	if (dp->b_active == 0)
! 		tsstart(ts11);
  	splx(s);
  }
  
***************
*** 257,278 ****
  /*
   * Start activity on a ts controller.
   */
! tsstart()
  {
  	daddr_t	blkno;
! 	int	cmd, tsunit;
  	register struct ts_softc *sc;
  	register struct ts_cmd *tc;
  	register struct buf *bp;
  
  	/*
  	 * Start the controller if there is something for it to do.
  	 */
  loop:
! 	if ((bp = tstab.b_actf) == NULL)
  		return;
! 	tsunit = TSUNIT(bp->b_dev);
! 	sc = &ts_softc[tsunit];
  	tc = &sc->sc_cmd;
  	/*
  	 * Default is that last command was NOT a write command;
--- 282,304 ----
  /*
   * Start activity on a ts controller.
   */
! tsstart(ts11)
! 	int ts11;
  {
  	daddr_t	blkno;
! 	int	cmd;
  	register struct ts_softc *sc;
  	register struct ts_cmd *tc;
  	register struct buf *bp;
+ 	struct buf *um = &tstab[ts11];
  
  	/*
  	 * Start the controller if there is something for it to do.
  	 */
  loop:
! 	if ((bp = um->b_actf) == NULL)
  		return;
! 	sc = ts_softc[ts11];
  	tc = &sc->sc_cmd;
  	/*
  	 * Default is that last command was NOT a write command;
***************
*** 279,285 ****
  	 * if we do a write command we will notice this in tsintr().
  	 */
  	sc->sc_lastiow = 0;
! 	if (sc->sc_openf < 0 || (TSADDR->tssr & TS_OFL)) {
  		/*
  		 * Have had a hard error on a non-raw tape
  		 * or the tape unit is now unavailable
--- 305,311 ----
  	 * if we do a write command we will notice this in tsintr().
  	 */
  	sc->sc_lastiow = 0;
! 	if (sc->sc_openf < 0 || (sc->sc_addr->tssr & TS_OFL)) {
  		/*
  		 * Have had a hard error on a non-raw tape
  		 * or the tape unit is now unavailable
***************
*** 288,298 ****
  		bp->b_flags |= B_ERROR;
  		goto next;
  	}
! 	if (bp == &ctsbuf) {
  		/*
  		 * Execute control operation with the specified count.
  		 */
! 		tstab.b_active = bp->b_command == TS_REW ?  SREW : SCOM;
  		goto dobpcmd;
  	}
  	/*
--- 314,324 ----
  		bp->b_flags |= B_ERROR;
  		goto next;
  	}
! 	if (bp == &ctsbuf[ts11]) {
  		/*
  		 * Execute control operation with the specified count.
  		 */
! 		um->b_active = bp->b_command == TS_REW ?  SREW : SCOM;
  		goto dobpcmd;
  	}
  	/*
***************
*** 301,307 ****
  	 * sc->sc_nxrec by tsphys causes them to be skipped normally
  	 * (except in the case of retries).
  	 */
! 	if(dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
  		/*
  		 * Can't read past known end-of-file.
  		 */
--- 327,333 ----
  	 * sc->sc_nxrec by tsphys causes them to be skipped normally
  	 * (except in the case of retries).
  	 */
! 	if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
  		/*
  		 * Can't read past known end-of-file.
  		 */
***************
*** 309,318 ****
  		bp->b_error = ENXIO;
  		goto next;
  	}
! 	if(dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) {
  		/*
  		 * Reading at end of file returns 0 bytes.
! 		 * Buffer will be cleared (if written) in writei.
  		 */
  		bp->b_resid = bp->b_bcount;
  		goto next;
--- 335,344 ----
  		bp->b_error = ENXIO;
  		goto next;
  	}
! 	if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) {
  		/*
  		 * Reading at end of file returns 0 bytes.
! 		 * Buffer will be cleared (if written) in rwip.
  		 */
  		bp->b_resid = bp->b_bcount;
  		goto next;
***************
*** 327,333 ****
  	 * set up all registers and do the transfer.
  	 */
  	if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
! 		tstab.b_active = SIO;
  		tc->c_loba = (u_short)bp->b_un.b_addr;
  		tc->c_hiba = bp->b_xmem;
  		tc->c_size = bp->b_bcount;
--- 353,359 ----
  	 * set up all registers and do the transfer.
  	 */
  	if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
! 		um->b_active = SIO;
  		tc->c_loba = (u_short)bp->b_un.b_addr;
  		tc->c_hiba = bp->b_xmem;
  		tc->c_size = bp->b_bcount;
***************
*** 335,348 ****
  			cmd = TS_WCOM;
  		else
  			cmd = TS_RCOM;
! 		if (tstab.b_errcnt)
  			cmd |= TS_RETRY;
  		tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd;
! #ifdef UNIBUS_MAP
! 		TSADDR->tsdb = sc->sc_uba;
! #else
! 		TSADDR->tsdb = (u_short)&sc->sc_cmd.c_cmd;
! #endif
  		return;
  	}
  	/*
--- 361,370 ----
  			cmd = TS_WCOM;
  		else
  			cmd = TS_RCOM;
! 		if (um->b_errcnt)
  			cmd |= TS_RETRY;
  		tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd;
! 		sc->sc_addr->tsdb = sc->sc_uba;
  		return;
  	}
  	/*
***************
*** 350,357 ****
  	 * set to seek forward or backward to the correct spot.
  	 * This happens for raw tapes only on error retries.
  	 */
! 	tstab.b_active = SSEEK;
! 	if(blkno < dbtofsb(bp->b_blkno)) {
  		bp->b_command = TS_SFORW;
  		bp->b_repcnt = dbtofsb(bp->b_blkno) - blkno;
  	} else
--- 372,379 ----
  	 * set to seek forward or backward to the correct spot.
  	 * This happens for raw tapes only on error retries.
  	 */
! 	um->b_active = SSEEK;
! 	if (blkno < dbtofsb(bp->b_blkno)) {
  		bp->b_command = TS_SFORW;
  		bp->b_repcnt = dbtofsb(bp->b_blkno) - blkno;
  	} else
***************
*** 365,375 ****
  	 * Do the command in bp.
  	 */
  	tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command;
! #ifdef UNIBUS_MAP
! 	TSADDR->tsdb = sc->sc_uba;
! #else
! 	TSADDR->tsdb = (u_short)&sc->sc_cmd.c_cmd;
! #endif
  	return;
  
  next:
--- 387,393 ----
  	 * Do the command in bp.
  	 */
  	tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command;
! 	sc->sc_addr->tsdb = sc->sc_uba;
  	return;
  
  next:
***************
*** 378,385 ****
  	 * the fact that it doesn't do anything.
  	 * Dequeue the transfer and continue processing this slave.
  	 */
! 	tstab.b_errcnt = 0;
! 	tstab.b_actf = bp->av_forw;
  	iodone(bp);
  	goto loop;
  }
--- 396,403 ----
  	 * the fact that it doesn't do anything.
  	 * Dequeue the transfer and continue processing this slave.
  	 */
! 	um->b_errcnt = 0;
! 	um->b_actf = bp->av_forw;
  	iodone(bp);
  	goto loop;
  }
***************
*** 387,428 ****
  /*
   * TS interrupt routine
   */
! tsintr()
  {
! 	register state;
! 	register struct buf *bp;
! 	register struct ts_softc *sc;
! 	int	tsunit;
  
! 	if((bp = tstab.b_actf) == NULL)
  		return;
- 	tsunit = TSUNIT (bp->b_dev);
  
  	/*
  	 * If last command was a rewind, and tape is still
  	 * rewinding, wait for the rewind complete interrupt.
  	 *
! 	 * SHOULD NEVER GET AN INTERRUPT IN THIS STATE.
  	 */
! 	if (tstab.b_active == SREW) {
! 		tstab.b_active = SCOM;
! 		if ((TSADDR->tssr & TS_SSR) == 0)
  			return;
  	}
  	/*
  	 * An operation completed... record status
  	 */
- 	sc = &ts_softc[tsunit];
  	if ((bp->b_flags & B_READ) == 0)
  		sc->sc_lastiow = 1;
! 	state = tstab.b_active;
! 	tstab.b_active = 0;
  
  	/*
  	 * Check for errors.
  	 */
! 	if(TSADDR->tssr & TS_SC) {
! 		switch (TSADDR->tssr & TS_TC) {
  			case TS_UNREC:	/* unrecoverable */
  			case TS_FATAL:	/* fatal error */
  			case TS_ATTN:	/* attention (shouldn't happen) */
--- 405,445 ----
  /*
   * TS interrupt routine
   */
! tsintr(dev)
! 	int dev;
  {
! 	int state;
! 	register struct buf *bp, *um = &tstab[dev];
! 	register struct ts_softc *sc = ts_softc[dev];
  
! 	if ((bp = um->b_actf) == NULL)
  		return;
  
  	/*
  	 * If last command was a rewind, and tape is still
  	 * rewinding, wait for the rewind complete interrupt.
  	 *
! 	 * SHOULD NEVER GET AN INTERRUPT IN THIS STATE, but it
! 	 * happens when a rewind completes.
  	 */
! 	if (um->b_active == SREW) {
! 		um->b_active = SCOM;
! 		if ((sc->sc_addr->tssr & TS_SSR) == 0)
  			return;
  	}
  	/*
  	 * An operation completed... record status
  	 */
  	if ((bp->b_flags & B_READ) == 0)
  		sc->sc_lastiow = 1;
! 	state = um->b_active;
! 	um->b_active = 0;
  
  	/*
  	 * Check for errors.
  	 */
! 	if (sc->sc_addr->tssr & TS_SC) {
! 		switch (sc->sc_addr->tssr & TS_TC) {
  			case TS_UNREC:	/* unrecoverable */
  			case TS_FATAL:	/* fatal error */
  			case TS_ATTN:	/* attention (shouldn't happen) */
***************
*** 454,460 ****
  				 * was too long or too short, then we don't
  				 * consider this an error.
  				 */
! 				if (bp == &rtsbuf && (bp->b_flags & B_READ)
  				    && sc->sc_sts.s_xs0 & (TS_RLS | TS_RLL))
  					goto ignoreerr;
  					/*NOTREACHED*/
--- 471,477 ----
  				 * was too long or too short, then we don't
  				 * consider this an error.
  				 */
! 				if ((bp->b_flags & B_PHYS) && (bp->b_flags & B_READ)
  				    && sc->sc_sts.s_xs0 & (TS_RLS | TS_RLL))
  					goto ignoreerr;
  					/*NOTREACHED*/
***************
*** 465,471 ****
  				 * retry up to 8 times.
  				 */
  				if (state == SIO) {
! 					if (++tstab.b_errcnt < 7)
  						goto opcont;
  					else
  						sc->sc_blkno++;
--- 482,488 ----
  				 * retry up to 8 times.
  				 */
  				if (state == SIO) {
! 					if (++(um->b_errcnt) < 7)
  						goto opcont;
  					else
  						sc->sc_blkno++;
***************
*** 475,481 ****
  					 * Non-i/o errors on non-raw tape
  					 * cause it to close.
  					 */
! 					if (sc->sc_openf > 0 && bp != &rtsbuf)
  						sc->sc_openf = -1;
  				}
  				break;
--- 492,498 ----
  					 * Non-i/o errors on non-raw tape
  					 * cause it to close.
  					 */
! 					if (sc->sc_openf > 0 && !(bp->b_flags & B_PHYS))
  						sc->sc_openf = -1;
  				}
  				break;
***************
*** 482,504 ****
  
  			case TS_REJECT:
  				if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE)
! 					printf("ts%d: no write ring\n", tsunit);
  				if ((sc->sc_sts.s_xs0 & TS_ONL) == 0)
! 					printf("ts%d: not online\n", tsunit);
  				break;
  		}
  		/*
  		 * Couldn't recover error.
  		 */
! 		printf("ts%d: hard error bn%D xs0=%b", TSUNIT(bp->b_dev),
  		     bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS);
  		if (sc->sc_sts.s_xs1)
! 			printf(" xs1=%b", sc->sc_sts.s_xs1, TSXS1_BITS);
  		if (sc->sc_sts.s_xs2)
! 			printf(" xs2=%b", sc->sc_sts.s_xs2, TSXS2_BITS);
  		if (sc->sc_sts.s_xs3)
! 			printf(" xs3=%b", sc->sc_sts.s_xs3, TSXS3_BITS);
! 		printf("\n");
  		bp->b_flags |= B_ERROR;
  		goto opdone;
  		/*NOTREACHED*/
--- 499,521 ----
  
  			case TS_REJECT:
  				if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE)
! 					tprintf(sc->sc_ttyp,"ts%d: no write ring\n", dev);
  				if ((sc->sc_sts.s_xs0 & TS_ONL) == 0)
! 					tprintf(sc->sc_ttyp,"ts%d: not online\n", dev);
  				break;
  		}
  		/*
  		 * Couldn't recover error.
  		 */
! 		tprintf(sc->sc_ttyp,"ts%d: hard error bn%D xs0=%b", dev,
  		     bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS);
  		if (sc->sc_sts.s_xs1)
! 			tprintf(sc->sc_ttyp," xs1=%b", sc->sc_sts.s_xs1, TSXS1_BITS);
  		if (sc->sc_sts.s_xs2)
! 			tprintf(sc->sc_ttyp," xs2=%b", sc->sc_sts.s_xs2, TSXS2_BITS);
  		if (sc->sc_sts.s_xs3)
! 			tprintf(sc->sc_ttyp," xs3=%b", sc->sc_sts.s_xs3, TSXS3_BITS);
! 		tprintf(sc->sc_ttyp,"\n");
  		bp->b_flags |= B_ERROR;
  		goto opdone;
  		/*NOTREACHED*/
***************
*** 521,527 ****
  			 * For forward/backward space record
  			 * update current position.
  			 */
! 			if (bp == &ctsbuf)
  				switch (bp->b_command) {
  					case TS_SFORW:
  						sc->sc_blkno += bp->b_repcnt;
--- 538,544 ----
  			 * For forward/backward space record
  			 * update current position.
  			 */
! 			if (bp == &ctsbuf[dev])
  				switch (bp->b_command) {
  					case TS_SFORW:
  						sc->sc_blkno += bp->b_repcnt;
***************
*** 549,571 ****
  	 * Reset error count and remove
  	 * from device queue.
  	 */
! 	tstab.b_errcnt = 0;
! 	tstab.b_actf = bp->av_forw;
  	bp->b_resid = sc->sc_sts.s_rbpcr;
  	iodone(bp);
! 	if (tstab.b_actf == NULL)
  		return;
  opcont:
! 	tsstart();
  }
  
  tsseteof(bp)
  register struct buf *bp;
  {
! 	register tsunit = TSUNIT(bp->b_dev);
! 	register struct ts_softc *sc = &ts_softc[tsunit];
  
! 	if (bp == &ctsbuf) {
  		if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {
  			/* reversing */
  			sc->sc_nxrec = dbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr;
--- 566,588 ----
  	 * Reset error count and remove
  	 * from device queue.
  	 */
! 	um->b_errcnt = 0;
! 	um->b_actf = bp->av_forw;
  	bp->b_resid = sc->sc_sts.s_rbpcr;
  	iodone(bp);
! 	if (um->b_actf == NULL)
  		return;
  opcont:
! 	tsstart(dev);
  }
  
  tsseteof(bp)
  register struct buf *bp;
  {
! 	register int ts11 = TSCTLR(bp->b_dev);
! 	register struct ts_softc *sc = ts_softc[ts11];
  
! 	if (bp == &ctsbuf[ts11]) {
  		if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {
  			/* reversing */
  			sc->sc_nxrec = dbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr;
***************
*** 586,683 ****
  /*
   * Initialize the TS11.
   */
! tsinit(tsunit)
  {
! 	struct	ts_softc *sc = &ts_softc[tsunit];
  	register struct ts_cmd *tcmd = &sc->sc_cmd;
  	register struct ts_char *tchar = &sc->sc_char;
  	int cnt;
- #ifdef	UNIBUS_MAP
- 	struct buf tbuf;
- 
  	/*
- 	 * Map the command and message packets into Unibus
- 	 * address space.  We do all the command and message
- 	 * packets at once to minimize the amount of Unibus
- 	 * mapping necessary.
- 	 */
- 	if (!sc->sc_mapped) {
- 		tbuf.b_xmem = 0;	/* won't work past 64k any way */
- 		tbuf.b_un.b_addr = (caddr_t)tcmd;
- 		tbuf.b_flags = B_PHYS;	/* want map to point to phys. addr. */
- 		tbuf.b_bcount = sizeof(struct ts_cmd);
- 		mapalloc(&tbuf);
- 		sc->sc_uadr = ((long)((unsigned)tbuf.b_xmem)) << 16
- 			 | ((long) ((unsigned)tbuf.b_un.b_addr));
- 		sc->sc_mapped++;
- 	}
- #endif	UNIBUS_MAP
- 
- 	/*
  	 * Now initialize the TS11 controller.
  	 * Set the characteristics.
  	 */
! 	if (TSADDR->tssr & (TS_NBA | TS_OFL)) {
  		tcmd->c_cmd = TS_ACK | TS_CVC | TS_INIT;
! #ifdef	UNIBUS_MAP
! 		sc->sc_uba = loint(sc->sc_uadr)
! 			   | hiint(sc->sc_uadr); /*register format*/
! #endif
! #ifdef DIAGNOSTIC
! #ifdef UNIBUS_MAP
! 		if (sc->sc_uadr & 03)
! #else	UNIBUS_MAP
! 		if (((u_short) tcmd) & 03)
! #endif
! 		{
! 			printf("ts%d: addr mod 4 != 0\n", tsunit);
! 			return (1);
! 		}
! #endif
! #ifdef	UNIBUS_MAP
! 		TSADDR->tsdb = sc->sc_uba;
! #else	UNIBUS_MAP
! 		TSADDR->tsdb = (u_short) tcmd;
! #endif
  		for (cnt = 0; cnt < 10000; cnt++) {
! 			if (TSADDR->tssr & TS_SSR)
  				break;
  		}
! 		if (cnt >= 10000) {
! 			printf("ts%d: subsystem init. failure\n", tsunit);
  			return (1);
- 		}
- #ifdef	UNIBUS_MAP
  		tchar->char_bptr = (u_short)loint(sc->sc_uadr)+
  			((u_short)&sc->sc_sts-(u_short)tcmd);
  		tchar->char_bae = hiint(sc->sc_uadr);
- #else	UNIBUS_MAP
- 		tchar->char_bptr = (u_short) &sc->sc_sts;
- 		tchar->char_bae = 0;
- #endif
  		tchar->char_size = sizeof(struct ts_sts);
  		tchar->char_mode = TS_ESS;
  		tcmd->c_cmd = TS_ACK | TS_CVC | TS_SETCHR;
- #ifdef	UNIBUS_MAP
  		tcmd->c_loba = (u_short)loint(sc->sc_uadr)+
  			((u_short)tchar-(u_short)tcmd);
  		tcmd->c_hiba = hiint(sc->sc_uadr);
- #else	UNIBUS_MAP
- 		tcmd->c_loba = (u_short) tchar;
- 		tcmd->c_hiba = 0;
- #endif
  		tcmd->c_size = sizeof(struct ts_char);
! #ifdef	UNIBUS_MAP
! 		TSADDR->tsdb = sc->sc_uba;
! #else	UNIBUS_MAP
! 		TSADDR->tsdb = (u_short) tcmd;
! #endif
  		for (cnt = 0; cnt < 10000; cnt++) {
! 			if (TSADDR->tssr & TS_SSR)
  				break;
  		}
! 		if (TSADDR->tssr & TS_NBA) {
! 			printf("ts%d: set characteristics failure\n", tsunit);
  			return (1);
  		}
  	}
--- 603,644 ----
  /*
   * Initialize the TS11.
   */
! tsinit(ts11)
  {
! 	register struct	ts_softc *sc = ts_softc[ts11];
  	register struct ts_cmd *tcmd = &sc->sc_cmd;
  	register struct ts_char *tchar = &sc->sc_char;
  	int cnt;
  	/*
  	 * Now initialize the TS11 controller.
  	 * Set the characteristics.
  	 */
! 	if (sc->sc_addr->tssr & (TS_NBA | TS_OFL)) {
  		tcmd->c_cmd = TS_ACK | TS_CVC | TS_INIT;
! 		sc->sc_addr->tsdb = sc->sc_uba;
  		for (cnt = 0; cnt < 10000; cnt++) {
! 			if (sc->sc_addr->tssr & TS_SSR)
  				break;
  		}
! 		if (cnt >= 10000)
  			return (1);
  		tchar->char_bptr = (u_short)loint(sc->sc_uadr)+
  			((u_short)&sc->sc_sts-(u_short)tcmd);
  		tchar->char_bae = hiint(sc->sc_uadr);
  		tchar->char_size = sizeof(struct ts_sts);
  		tchar->char_mode = TS_ESS;
  		tcmd->c_cmd = TS_ACK | TS_CVC | TS_SETCHR;
  		tcmd->c_loba = (u_short)loint(sc->sc_uadr)+
  			((u_short)tchar-(u_short)tcmd);
  		tcmd->c_hiba = hiint(sc->sc_uadr);
  		tcmd->c_size = sizeof(struct ts_char);
! 		sc->sc_addr->tsdb = sc->sc_uba;
  		for (cnt = 0; cnt < 10000; cnt++) {
! 			if (sc->sc_addr->tssr & TS_SSR)
  				break;
  		}
! 		if (sc->sc_addr->tssr & TS_NBA) {
! 			printf("ts%d: set char. failure\n", ts11);
  			return (1);
  		}
  	}
***************
*** 684,736 ****
  	return(0);
  }
  
- tsread(dev, uio)
- 	register dev_t	dev;
- 	register struct uio *uio;
- {
- 	register int error;
- 
- 	error = tsphys(dev, uio);
- 	if (error)
- 		return (error);
- 	return (physio(tsstrategy, &rtsbuf, dev, B_READ, BYTE, uio));
- }
- 
- tswrite(dev, uio)
- 	register dev_t	dev;
- 	register struct uio *uio;
- {
- 	register int error;
- 
- 	error = tsphys(dev, uio);
- 	if (error)
- 		return (error);
- 	return (physio(tsstrategy, &rtsbuf, dev, B_WRITE, BYTE, uio));
- }
- 
- /*
-  * Check that a raw device exists.
-  * If it does, set up sc_blkno and sc_nxrec
-  * so that the tape will appear positioned correctly.
-  */
- static
- tsphys(dev, uio)
- 	dev_t	dev;
- 	register struct uio *uio;
- {
- 	register int tsunit = TSUNIT(dev);
- 	register struct ts_softc *sc;
- 	daddr_t a;
- 
- 	if (tsunit >= NTS)
- 		return (ENXIO);
- 	sc = &ts_softc[tsunit];
- 	a = dbtofsb(uio->uio_offset >> 9);
- 	sc->sc_blkno = a;
- 	sc->sc_nxrec = a + 1;
- 	return (0);
- }
- 
  /*ARGSUSED*/
  tsioctl(dev, cmd, data, flag)
  	dev_t dev;
--- 645,650 ----
***************
*** 737,744 ****
  	u_int cmd;
  	caddr_t data;
  {
! 	register struct ts_softc *sc = &ts_softc[TSUNIT(dev)];
! 	register struct buf *bp = &ctsbuf;
  	register callcount;
  	u_short	fcount;
  	struct	mtop *mtop;
--- 651,659 ----
  	u_int cmd;
  	caddr_t data;
  {
! 	int ts11 = TSCTLR(dev);
! 	register struct ts_softc *sc = ts_softc[ts11];
! 	register struct buf *bp = &ctsbuf[ts11];
  	register callcount;
  	u_short	fcount;
  	struct	mtop *mtop;
*** /old/src/sys/pdpuba/xp.c	Tue Apr  3 09:48:00 1990
--- /usr/src/sys/pdpuba/xp.c	Sun Sep 22 08:44:09 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)xp.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.
   *
!  *	@(#)xp.c	1.3 (2.11BSD) 9/22/91
   */
  
  /*
***************
*** 230,239 ****
  	   9600,	  0,	/* a: cyl   0 -  29 */
  	   9600,	 30,	/* b: cyl  30 -  59 */
  	 244160,	 60,	/* c: cyl  60 - 822 */
! 	 125440,	 60,	/* d: cyl  60 - 451 */
! 	 118720,	452,	/* e: cyl 452 - 822 */
! 	  59520,	452,	/* f: cyl 452 - 637 */
! 	  59200,	638,	/* g: cyl 638 - 822 */
  	 263360,	  0,	/* h: cyl   0 - 822 */
  }, dv_sizes[8] = { /* Diva Comp V, Ampex 9300 in direct mode */
  	   9405,	  0,	/* a: cyl   0 -  14 */
--- 230,239 ----
  	   9600,	  0,	/* a: cyl   0 -  29 */
  	   9600,	 30,	/* b: cyl  30 -  59 */
  	 244160,	 60,	/* c: cyl  60 - 822 */
! 	 164800,	 60,	/* d: cyl  60 - 574 */
! 	  79360,	575,	/* e: cyl 575 - 822 */
! 	  39680,	575,	/* f: cyl 575 - 698 */
! 	  39680,	699,	/* g: cyl 699 - 822 */
  	 263360,	  0,	/* h: cyl   0 - 822 */
  }, dv_sizes[8] = { /* Diva Comp V, Ampex 9300 in direct mode */
  	   9405,	  0,	/* a: cyl   0 -  14 */
***************
*** 273,279 ****
  #endif
  
  struct	buf	xptab;
- struct	buf	rxpbuf[NXPD];
  struct	buf	xputab[NXPD];
  
  #ifdef BADSECT
--- 273,278 ----
***************
*** 295,300 ****
--- 294,303 ----
  	register int i;
  	register struct hpdevice *xpaddr;
  
+ #if	(PDP11 == GENERIC)
+ 	printf("\nxp_drive=0%o xp_controller=0%o\n",xp_drive,xp_controller);
+ 	delay(10000000L);	/* 10 secs to halt and patch xp_drive */
+ #endif
  	for (i = 0; i < NXPC; i++)
  		if (((xpaddr = xp_controller[i].xp_addr) == 0)
  			|| (xpattach(xpaddr, i) == 0))
***************
*** 381,390 ****
  		xpaddr->hpcs1.w = 0;
  		xpaddr->hpcs2.w = j;
  		xpaddr->hpcs1.w = HP_GO;	/* testing... */
! 		{
! 			int x = 6000;
! 			while (--x);		/* delay */
! 		}
  		dummy = xpaddr->hpds;
  		if (xpaddr->hpcs2.w & HPCS2_NED) {
  			xpaddr->hpcs2.w = HPCS2_CLR;
--- 384,390 ----
  		xpaddr->hpcs1.w = 0;
  		xpaddr->hpcs2.w = j;
  		xpaddr->hpcs1.w = HP_GO;	/* testing... */
! 		delay(6000L);
  		dummy = xpaddr->hpds;
  		if (xpaddr->hpcs2.w & HPCS2_NED) {
  			xpaddr->hpcs2.w = HPCS2_CLR;
***************
*** 881,901 ****
  	xpstart(xc);
  }
  
- xpread(dev, uio)
- 	dev_t	dev;
- 	struct uio *uio;
- {
- 	return (physio(xpstrategy, &rxpbuf[xpunit(dev)], dev, B_READ, WORD, uio));
- }
- 
- xpwrite(dev, uio)
- 	dev_t	dev;
- 	struct uio *uio;
- {
- 	return (physio(xpstrategy, &rxpbuf[xpunit(dev)], dev, B_WRITE, WORD, uio));
- }
- 
- 
  #define exadr(x,y)	(((long)(x) << 16) | (unsigned)(y))
  
  /*
--- 881,886 ----
***************
*** 1128,1134 ****
  		}
  #endif
  		/* Emulex controller emulating two RM03's needs a delay */
! 		DELAY(50000L);
  		while (xpaddr->hpcs1.w & HP_GO)
  			continue;
  		if (xpaddr->hpcs1.w & HP_TRE) {
--- 1113,1119 ----
  		}
  #endif
  		/* Emulex controller emulating two RM03's needs a delay */
! 		delay(50000L);
  		while (xpaddr->hpcs1.w & HP_GO)
  			continue;
  		if (xpaddr->hpcs1.w & HP_TRE) {
*** /old/src/sys/sys/init_main.c	Sat Apr  7 23:39:53 1990
--- /usr/src/sys/sys/init_main.c	Sun Jul 12 16:27:15 1992
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)init_main.c	1.2 (2.10BSD Berkeley) 1/26/90
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)init_main.c	1.3 (2.11BSD Berkeley) 9/22/91
   */
  
  #include "param.h"
***************
*** 46,53 ****
--- 46,57 ----
   */
  main()
  {
+ 	extern dev_t bootdev;
+ 	extern caddr_t bootcsr;
  	register struct proc *p;
  	register int i;
+ 	register struct fs *fs;
+ 	time_t  toytime, toyclk();
  
  	startup();
  
***************
*** 92,99 ****
  #endif
  	nchinit();
  	clkstart();
- 	iinit();
  
  /* kick off timeout driven events by calling first time */
  	schedcpu();
  
--- 96,130 ----
  #endif
  	nchinit();
  	clkstart();
  
+ /*
+  * Need to attach the root device.  The CSR is passed thru because this
+  * may be a 2nd or 3rd controller rather than the 1st.  NOTE: This poses
+  * a big problem if 'swapdev' is not on the same controller as 'rootdev'
+  * _or_ if 'swapdev' itself is on a 2nd or 3rd controller.  Short of moving
+  * autconfigure back in to the kernel it is not known what can be done about
+  * this.
+  *
+  * As a "compatibility hack" call swapdev's attach routine with a zero
+  * address.  The MSCP driver treats the 0 as a signal to perform the
+  * old (fixed address) attach.  Drivers (all the rest at this point) which
+  * do not support alternate controller booting always attach the first
+  * (primary) CSR and do not expect an argument to be passed.
+ */
+ 	(void)(*bdevsw[major(bootdev)].d_root)(bootcsr);
+ 	(void)(*bdevsw[major(swapdev)].d_root)((caddr_t) 0);	/* XXX */
+ 	(*bdevsw[major(swapdev)].d_open)(swapdev, B_READ);
+ 	fs = mountfs(rootdev, boothowto & RB_RDONLY, (struct inode *)0);
+ 	if (!fs)
+ 		panic("iinit");
+ 	mount[0].m_inodp = (struct inode *)1;	/* XXX */
+ 	fs->fs_fsmnt[0] = '/';
+ 	fs->fs_fsmnt[1] = '\0';
+ 	time.tv_sec = fs->fs_time;
+ 	if	(toytime = toyclk())
+ 		time.tv_sec = toytime;
+ 	boottime = time;
+ 
  /* kick off timeout driven events by calling first time */
  	schedcpu();
  
***************
*** 198,248 ****
  #endif
  }
  
- /*
-  * Iinit is called once (from main) very early in initialization.
-  * It reads the root's super block and initializes the current date
-  * from the last modified date.
-  *
-  * panic: iinit -- cannot read the super block
-  * (usually because of an IO error).
-  */
- static
- iinit()
- {
- 	register struct bdevsw *bdp;
- 	register struct buf *bp;
- 	register struct fs *fp;
- 
- 	for (bdp = bdevsw; bdp < bdevsw + nblkdev; bdp++)
- 		(void)(*bdp->d_root)();
- 	(*bdevsw[major(rootdev)].d_open)(rootdev, B_READ);
- 	(*bdevsw[major(swapdev)].d_open)(swapdev, B_READ);
- 	bp = bread(rootdev, SUPERB);
- 	if (u.u_error)
- 		panic("iinit");
- 	fp = &mount[0].m_filsys;
- 	bcopy(mapin(bp), (caddr_t)fp, sizeof(struct fs));
- 	mapout(bp);
- 	mount[0].m_inodp = (struct inode *)1;
- 	brelse(bp);
- 	mount[0].m_dev = rootdev;
- 	fp->fs_flock = fp->fs_ilock = fp->fs_ronly = 0;
- 	fp->fs_lasti = 1;
- 	fp->fs_nbehind = 0;
- 	fp->fs_fsmnt[0] = '/';
- 	fp->fs_fsmnt[1] = '\0';
- 	fp->fs_ronly = boothowto&RB_RDONLY ? 1 : 0;
- 	time.tv_sec = fp->fs_time;
- 	boottime = time;
- }
- 
  #ifdef UCB_NET
  memaddr netdata;		/* click address of start of net data */
  
  /*
   * We are called here after all the other init routines (clist, inode,
!  * unibusmap, etc...) have been called.  'init' is probably running, but
!  * other than that we can allocate memory without fragmenting.  Open the
   * file NETNIX and read the a.out header, based on that go allocate
   * memory and read the text+data into the memory.  Set up supervisor page
   * registers, SDSA6 and SDSA7 have already been set up in mch_start.s.
--- 229,240 ----
  #endif
  }
  
  #ifdef UCB_NET
  memaddr netdata;		/* click address of start of net data */
  
  /*
   * We are called here after all the other init routines (clist, inode,
!  * unibusmap, etc...) have been called.  Open the
   * file NETNIX and read the a.out header, based on that go allocate
   * memory and read the text+data into the memory.  Set up supervisor page
   * registers, SDSA6 and SDSA7 have already been set up in mch_start.s.
***************
*** 269,294 ****
  	ndp->ni_segflg = UIO_SYSSPACE;
  	ndp->ni_dirp = NETNIX;
  	if (!(ip = namei(ndp))) {
! 		printf("%s: not found.\n", NETNIX);
  		goto leave;
  	}
  	if ((ip->i_mode & IFMT) != IFREG || !ip->i_size) {
! 		printf("%s: bad inode\n", NETNIX);
  		goto leave;
  	}
  	err = rdwri(UIO_READ, ip, &ex, sizeof (ex), (off_t)0, UIO_SYSSPACE,
  			&resid);
  	if (err || resid) {
! 		printf("%s: header err %d\n", NETNIX, ret);
  		goto leave;
  	}
  	if (ex.a_magic != A_MAGIC3) {
! 		printf("%s: bad magic %o.\n", NETNIX, ex.a_magic);
  		goto leave;
  	}
  	lsize = (long)ex.a_data + (long)ex.a_bss;
  	if (lsize > 48L * 1024L) {
! 		printf("%s: too big, %ld\n", NETNIX, lsize);
  		goto leave;
  	}
  	nettsize = btoc(ex.a_text);
--- 261,286 ----
  	ndp->ni_segflg = UIO_SYSSPACE;
  	ndp->ni_dirp = NETNIX;
  	if (!(ip = namei(ndp))) {
! 		printf("%s not found\n", NETNIX);
  		goto leave;
  	}
  	if ((ip->i_mode & IFMT) != IFREG || !ip->i_size) {
! 		printf("%s bad inode\n", NETNIX);
  		goto leave;
  	}
  	err = rdwri(UIO_READ, ip, &ex, sizeof (ex), (off_t)0, UIO_SYSSPACE,
  			&resid);
  	if (err || resid) {
! 		printf("%s header err %d\n", NETNIX, ret);
  		goto leave;
  	}
  	if (ex.a_magic != A_MAGIC3) {
! 		printf("%s bad magic %o\n", NETNIX, ex.a_magic);
  		goto leave;
  	}
  	lsize = (long)ex.a_data + (long)ex.a_bss;
  	if (lsize > 48L * 1024L) {
! 		printf("%s too big %ld\n", NETNIX, lsize);
  		goto leave;
  	}
  	nettsize = btoc(ex.a_text);
***************
*** 321,327 ****
  		err = rdwri(UIO_READ, ip, oneclick, ex.a_data & 077, off,
  				UIO_SYSSPACE, &resid);
  		if (err || resid) {
! release:		printf("%s: err %d resid %d\n", NETNIX, err, resid);
  			mfree(coremap, nettsize, nettext);
  			mfree(coremap, netdsize, netdata);
  			nettsize = netdsize = 0;
--- 313,319 ----
  		err = rdwri(UIO_READ, ip, oneclick, ex.a_data & 077, off,
  				UIO_SYSSPACE, &resid);
  		if (err || resid) {
! release:		printf("%s err %d\n", NETNIX, err);
  			mfree(coremap, nettsize, nettext);
  			mfree(coremap, netdsize, netdata);
  			nettsize = netdsize = 0;
*** /old/src/sys/sys/kern_acct.c	Sun Apr  8 00:45:42 1990
--- /usr/src/sys/sys/kern_acct.c	Sat Feb 22 14:02:40 1992
***************
*** 3,14 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_acct.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  #include "param.h"
- #include "../machine/seg.h"
- 
  #include "systm.h"
  #include "fs.h"
  #include "dir.h"
--- 3,12 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)kern_acct.c	2.0 (2.11BSD) 2/21/92
   */
  
  #include "param.h"
  #include "systm.h"
  #include "fs.h"
  #include "dir.h"
***************
*** 17,26 ****
--- 15,28 ----
  #include "proc.h"
  #include "acct.h"
  #include "kernel.h"
+ #include "syslog.h"
  
  /*
   * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
   */
+ int	acctsuspend = 2;	/* stop accounting when < 2% free space left */
+ int	acctresume = 4;		/* resume when free space risen to > 4% */
+ struct	timeval chk = {15, 0};	/* frequency to check space for accounting */
  struct	inode *acctp;
  struct	inode *savacctp;
  
***************
*** 34,39 ****
--- 36,42 ----
  		char	*fname;
  	} *uap = (struct a *)u.u_ap;
  	register struct nameidata *ndp = &u.u_nd;
+ 	int acctwatch();
  
  	if (suser()) {
  		if (savacctp) {
***************
*** 44,49 ****
--- 47,54 ----
  			if (ip = acctp) {
  				irele(ip);
  				acctp = NULL;
+ 				chk.tv_usec = 0;
+ 				untimeout(acctwatch, &chk);
  			}
  			return;
  		}
***************
*** 68,88 ****
  			irele(acctp);
  		acctp = ip;
  		iunlock(ip);
  	}
  }
  
! int	acctsuspend = 2;	/* stop accounting when < 2% free space left */
! int	acctresume = 4;		/* resume when free space risen to > 4% */
! 
! struct	acct acctbuf;
! /*
!  * On exit, write a record on the accounting file.
!  */
! acct()
  {
- 	register struct inode *ip;
  	register struct fs *fs;
- 	off_t siz;
  
  	if (savacctp) {
  		fs = savacctp->i_fs;
--- 73,89 ----
  			irele(acctp);
  		acctp = ip;
  		iunlock(ip);
+ 		if (chk.tv_usec == 0) {
+ 			chk.tv_usec = 1;	/* usec is timer enabled flag */
+ 			timeout(acctwatch, &chk, chk.tv_sec * hz);
+ 		}
  	}
  }
  
! acctwatch(resettime)
! 	struct	timeval *resettime;
  {
  	register struct fs *fs;
  
  	if (savacctp) {
  		fs = savacctp->i_fs;
***************
*** 89,122 ****
  		if (freespace(fs, acctresume) > 0) {
  			acctp = savacctp;
  			savacctp = NULL;
! 			printf("Accounting resumed\n");
  		}
  	}
! 	if ((ip = acctp) == NULL)
! 		return;
  	fs = acctp->i_fs;
  	if (freespace(fs, acctsuspend) <= 0) {
  		savacctp = acctp;
  		acctp = NULL;
! 		printf("Accounting suspended\n");
! 		return;
  	}
  	ilock(ip);
! 	bcopy(u.u_comm, acctbuf.ac_comm, sizeof(acctbuf.ac_comm));
! 	acctbuf.ac_utime = compress(u.u_ru.ru_utime);
! 	acctbuf.ac_stime = compress(u.u_ru.ru_stime);
! 	acctbuf.ac_etime = compress(time.tv_sec - u.u_start);
! 	acctbuf.ac_btime = u.u_start;
! 	acctbuf.ac_uid = u.u_ruid;
! 	acctbuf.ac_gid = u.u_rgid;
! 	acctbuf.ac_mem = u.u_dsize+u.u_ssize;	/* probably max */
! #ifdef UCB_RUSAGE
! 	acctbuf.ac_io = compress(u.u_ru.ru_inblock + u.u_ru.ru_oublock);
! #endif
! 	acctbuf.ac_tty = u.u_ttyd;
! 	acctbuf.ac_flag = u.u_acflag;
  	siz = ip->i_size;
! 	u.u_error = rdwri(UIO_WRITE, ip, &acctbuf, sizeof(acctbuf), siz,
  			UIO_SYSSPACE, (int *)0);
  	if (u.u_error)
  		itrunc(ip, (u_long)siz);
--- 90,139 ----
  		if (freespace(fs, acctresume) > 0) {
  			acctp = savacctp;
  			savacctp = NULL;
! 			log(LOG_NOTICE, "Accounting resumed\n");
! /*			return;		/* XXX - fall thru and refresh timer */
  		}
  	}
! 	if (acctp == NULL)
! 		return;		/* do not refresh timer */
  	fs = acctp->i_fs;
  	if (freespace(fs, acctsuspend) <= 0) {
  		savacctp = acctp;
  		acctp = NULL;
! 		log(LOG_NOTICE, "Accounting suspended\n");
  	}
+ 	timeout(acctwatch, resettime, resettime->tv_sec * hz);
+ }
+ 
+ /*
+  * On exit, write a record on the accounting file.
+  */
+ acct()
+ {
+ 	struct	acct acctbuf;
+ 	register struct inode *ip;
+ 	off_t siz;
+ 	register struct acct *ap = &acctbuf;
+ 
+ 	if ((ip = acctp) == NULL)
+ 		return;
  	ilock(ip);
! 	bcopy(u.u_comm, ap->ac_comm, sizeof(acctbuf.ac_comm));
! 	ap->ac_utime = compress(u.u_ru.ru_utime);
! 	ap->ac_stime = compress(u.u_ru.ru_stime);
! 	ap->ac_etime = compress(time.tv_sec - u.u_start);
! 	ap->ac_btime = u.u_start;
! 	ap->ac_uid = u.u_ruid;
! 	ap->ac_gid = u.u_rgid;
! 	ap->ac_mem = (u.u_dsize+u.u_ssize) / 16; /* fast ctok() */
! 	ap->ac_io = compress(u.u_ru.ru_inblock + u.u_ru.ru_oublock);
! 	if (u.u_ttyp)
! 		ap->ac_tty = u.u_ttyd;
! 	else
! 		ap->ac_tty = NODEV;
! 	ap->ac_flag = u.u_acflag;
  	siz = ip->i_size;
! 	u.u_error = rdwri(UIO_WRITE, ip, ap, sizeof(acctbuf), siz,
  			UIO_SYSSPACE, (int *)0);
  	if (u.u_error)
  		itrunc(ip, (u_long)siz);
*** /old/src/sys/sys/kern_clock.c	Fri Jun 22 15:46:17 1990
--- /usr/src/sys/sys/kern_clock.c	Wed Jun  5 23:05:41 1991
***************
*** 144,150 ****
  	}
  
  	if (needsoft && BASEPRI(ps)) {	/* if ps is high, just return */
! 		(void) splsoftclock();
  		softclock(pc,ps);
  	}
  	restormap(map);
--- 144,150 ----
  	}
  
  	if (needsoft && BASEPRI(ps)) {	/* if ps is high, just return */
! 		(void) _splsoftclock();
  		softclock(pc,ps);
  	}
  	restormap(map);
*** /old/src/sys/sys/kern_exec.c	Sat Apr  7 20:07:25 1990
--- /usr/src/sys/sys/kern_exec.c	Thu Jun  6 19:59:43 1991
***************
*** 181,187 ****
  	uap = (struct execa *)u.u_ap;
  	bno = malloc(swapmap, ctod((int)btoc(NCARGS + MAXBSIZE)));
  	if (bno == 0) {
! 		swkill(u.u_procp, "exec: no swap space");
  		goto bad;
  	}
  	/*
--- 181,187 ----
  	uap = (struct execa *)u.u_ap;
  	bno = malloc(swapmap, ctod((int)btoc(NCARGS + MAXBSIZE)));
  	if (bno == 0) {
! 		swkill(u.u_procp, "exec");
  		goto bad;
  	}
  	/*
*** /old/src/sys/sys/kern_sig.c	Sat Apr  7 22:39:58 1990
--- /usr/src/sys/sys/kern_sig.c	Wed Jun  5 23:07:01 1991
***************
*** 91,97 ****
  	/*
  	 * Change setting atomically.
  	 */
! 	(void) splhigh();
  	u.u_signal[sig] = sv->sv_handler;
  	u.u_sigmask[sig] = sv->sv_mask &~ cantmask;
  	if (sv->sv_flags & SV_INTERRUPT)
--- 91,97 ----
  	/*
  	 * Change setting atomically.
  	 */
! 	(void) _splhigh();
  	u.u_signal[sig] = sv->sv_handler;
  	u.u_sigmask[sig] = sv->sv_mask &~ cantmask;
  	if (sv->sv_flags & SV_INTERRUPT)
***************
*** 113,119 ****
  		else
  			p->p_sigcatch |= bit;
  	}
! 	(void) spl0();
  }
  
  sigblock()
--- 113,119 ----
  		else
  			p->p_sigcatch |= bit;
  	}
! 	(void) _spl0();
  }
  
  sigblock()
***************
*** 123,132 ****
  	} *uap = (struct a *)u.u_ap;
  	register struct proc *p = u.u_procp;
  
! 	(void) splhigh();
  	u.u_r.r_long = p->p_sigmask;
  	p->p_sigmask |= uap->mask &~ cantmask;
! 	(void) spl0();
  }
  
  sigsetmask()
--- 123,132 ----
  	} *uap = (struct a *)u.u_ap;
  	register struct proc *p = u.u_procp;
  
! 	(void) _splhigh();
  	u.u_r.r_long = p->p_sigmask;
  	p->p_sigmask |= uap->mask &~ cantmask;
! 	(void) _spl0();
  }
  
  sigsetmask()
***************
*** 136,145 ****
  	} *uap = (struct a *)u.u_ap;
  	register struct proc *p = u.u_procp;
  
! 	(void) splhigh();
  	u.u_r.r_long = p->p_sigmask;
  	p->p_sigmask = uap->mask &~ cantmask;
! 	(void) spl0();
  }
  
  sigpause()
--- 136,145 ----
  	} *uap = (struct a *)u.u_ap;
  	register struct proc *p = u.u_procp;
  
! 	(void) _splhigh();
  	u.u_r.r_long = p->p_sigmask;
  	p->p_sigmask = uap->mask &~ cantmask;
! 	(void) _spl0();
  }
  
  sigpause()
***************
*** 758,764 ****
  		 * mask from before the sigpause is what we want restored
  		 * after the signal processing is completed.
  		 */
! 		(void) splhigh();
  		if (p->p_flag & SOMASK) {
  			returnmask = u.u_oldmask;
  			p->p_flag &= ~SOMASK;
--- 758,764 ----
  		 * mask from before the sigpause is what we want restored
  		 * after the signal processing is completed.
  		 */
! 		(void) _splhigh();
  		if (p->p_flag & SOMASK) {
  			returnmask = u.u_oldmask;
  			p->p_flag &= ~SOMASK;
***************
*** 765,771 ****
  		} else
  			returnmask = p->p_sigmask;
  		p->p_sigmask |= u.u_sigmask[sig] | mask;
! 		(void) spl0();
  #ifdef UCB_RUSAGE
  		u.u_ru.ru_nsignals++;
  #endif
--- 765,771 ----
  		} else
  			returnmask = p->p_sigmask;
  		p->p_sigmask |= u.u_sigmask[sig] | mask;
! 		(void) _spl0();
  #ifdef UCB_RUSAGE
  		u.u_ru.ru_nsignals++;
  #endif
*** /old/src/sys/sys/kern_synch.c	Thu May 24 23:49:36 1990
--- /usr/src/sys/sys/kern_synch.c	Wed Jun  5 23:07:32 1991
***************
*** 120,126 ****
  		 * by the filesystem, but for now avoid network interrupts
  		 * that might cause another panic.
  		 */
! 		(void)splnet();
  		noop();
  		splx(s);
  		return;
--- 120,126 ----
  		 * by the filesystem, but for now avoid network interrupts
  		 * that might cause another panic.
  		 */
! 		(void) _splnet();
  		noop();
  		splx(s);
  		return;
***************
*** 142,154 ****
  			if (rp->p_wchan)
  				unsleep(rp);
  			rp->p_stat = SRUN;
! 			(void) spl0();
  			goto psig;
  		}
  		if (rp->p_wchan == 0)
  			goto out;
  		rp->p_stat = SSLEEP;
! 		(void) spl0();
  		/*
  		 * maybe a very small core memory, give swapped out
  		 * processes a chance.
--- 142,154 ----
  			if (rp->p_wchan)
  				unsleep(rp);
  			rp->p_stat = SRUN;
! 			(void) _spl0();
  			goto psig;
  		}
  		if (rp->p_wchan == 0)
  			goto out;
  		rp->p_stat = SSLEEP;
! 		(void) _spl0();
  		/*
  		 * maybe a very small core memory, give swapped out
  		 * processes a chance.
***************
*** 165,171 ****
  			goto psig;
  	} else {
  		rp->p_stat = SSLEEP;
! 		(void) spl0();
  #ifdef UCB_RUSAGE
  		u.u_ru.ru_nvcsw++;
  #endif
--- 165,171 ----
  			goto psig;
  	} else {
  		rp->p_stat = SSLEEP;
! 		(void) _spl0();
  #ifdef UCB_RUSAGE
  		u.u_ru.ru_nvcsw++;
  #endif
*** /old/src/sys/sys/sys_net.c	Wed Dec 26 23:39:18 1990
--- /usr/src/sys/sys/sys_net.c	Sun Mar 17 01:14:29 1991
***************
*** 122,138 ****
  	 * This is early in the systems life, so there had better be
  	 * sufficient UMRs available!
  	 */
! 	miostart = miobase;
! 	s = (int)btoub(miosize);
! 	first = NETUBAA(s);
! 	mioumr = (ubadr_t)first << 13;
! 	ubp = &UBMAP[first];
! 	paddr = ctob((ubadr_t)miostart);
! 	while	(s--) {
! 		ubp->ub_lo = loint(paddr);
! 		ubp->ub_hi = hiint(paddr);
! 		ubp++;
! 		paddr += (ubadr_t)UBPAGE;
  	}
  #endif UNIBUS_MAP
  
--- 122,140 ----
  	 * This is early in the systems life, so there had better be
  	 * sufficient UMRs available!
  	 */
! 	if (mfkd(&ubmap)) {
! 		miostart = miobase;
! 		s = (int)btoub(miosize);
! 		first = NETUBAA(s);
! 		mioumr = (ubadr_t)first << 13;
! 		ubp = &UBMAP[first];
! 		paddr = ctob((ubadr_t)miostart);
! 		while	(s--) {
! 			ubp->ub_lo = loint(paddr);
! 			ubp->ub_hi = hiint(paddr);
! 			ubp++;
! 			paddr += (ubadr_t)UBPAGE;
! 		}
  	}
  #endif UNIBUS_MAP
  
*** /old/src/sys/sys/ufs_bio.c	Fri Jun 22 15:28:17 1990
--- /usr/src/sys/sys/ufs_bio.c	Sat Jun 29 14:04:36 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ufs_bio.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ufs_bio.c	2.0 (2.11BSD) 5/18/91
   */
  
  #include "param.h"
***************
*** 29,35 ****
  	register struct buf *bp;
  
  	bp = getblk(dev, blkno);
! 	if (bp->b_flags&B_DONE) {
  		trace(TR_BREADHIT);
  		return (bp);
  	}
--- 29,35 ----
  	register struct buf *bp;
  
  	bp = getblk(dev, blkno);
! 	if (bp->b_flags&(B_DONE|B_DELWRI)) {
  		trace(TR_BREADHIT);
  		return (bp);
  	}
***************
*** 64,70 ****
  	 */
  	if (!incore(dev, blkno)) {
  		bp = getblk(dev, blkno);
! 		if ((bp->b_flags&B_DONE) == 0) {
  			bp->b_flags |= B_READ;
  			bp->b_bcount = DEV_BSIZE;	/* XXX? KB */
  			(*bdevsw[major(dev)].d_strategy)(bp);
--- 64,70 ----
  	 */
  	if (!incore(dev, blkno)) {
  		bp = getblk(dev, blkno);
! 		if ((bp->b_flags&(B_DONE|B_DELWRI)) == 0) {
  			bp->b_flags |= B_READ;
  			bp->b_bcount = DEV_BSIZE;	/* XXX? KB */
  			(*bdevsw[major(dev)].d_strategy)(bp);
***************
*** 81,100 ****
  	 * If there's a read-ahead block, start i/o
  	 * on it also (as above).
  	 */
! 	if (rablkno && !incore(dev, rablkno)) {
! 		rabp = getblk(dev, rablkno);
! 		if (rabp->b_flags & B_DONE) {
! 			brelse(rabp);
! 			trace(TR_BREADHITRA);
! 		} else {
! 			rabp->b_flags |= B_READ|B_ASYNC;
! 			rabp->b_bcount = DEV_BSIZE;	/* XXX? KB */
! 			(*bdevsw[major(dev)].d_strategy)(rabp);
! 			trace(TR_BREADMISSRA);
  #ifdef UCB_RUSAGE
! 			u.u_ru.ru_inblock++;		/* pay in advance */
  #endif
! 		}
  	}
  
  	/*
--- 81,103 ----
  	 * If there's a read-ahead block, start i/o
  	 * on it also (as above).
  	 */
! 	if (rablkno) {
! 		if (!incore(dev, rablkno)) {
! 			rabp = getblk(dev, rablkno);
! 			if (rabp->b_flags & (B_DONE|B_DELWRI)) {
! 				brelse(rabp);
! 				trace(TR_BREADHITRA);
! 			} else {
! 				rabp->b_flags |= B_READ|B_ASYNC;
! 				rabp->b_bcount = DEV_BSIZE;	/* XXX? KB */
! 				(*bdevsw[major(dev)].d_strategy)(rabp);
! 				trace(TR_BREADMISSRA);
  #ifdef UCB_RUSAGE
! 				u.u_ru.ru_inblock++;	/* pay in advance */
  #endif
! 			}
! 		} else
! 			trace(TR_BREADHITRA);	
  	}
  
  	/*
***************
*** 185,191 ****
  		wakeup((caddr_t)bfreelist);
  	}
  	if (bp->b_flags&B_ERROR)
! 		bp->b_dev = NODEV;	/* no assoc */
  
  	/*
  	 * Stick the buffer back on a free list.
--- 188,197 ----
  		wakeup((caddr_t)bfreelist);
  	}
  	if (bp->b_flags&B_ERROR)
! 		if (bp->b_flags & B_LOCKED)
! 			bp->b_flags &= ~B_ERROR;	/* try again later */
! 		else
! 			bp->b_dev = NODEV;  		/* no assoc */
  
  	/*
  	 * Stick the buffer back on a free list.
***************
*** 196,202 ****
  		flist = &bfreelist[BQ_AGE];
  		binsheadfree(bp, flist);
  	} else {
! 		if (bp->b_flags & B_AGE)
  			flist = &bfreelist[BQ_AGE];
  		else
  			flist = &bfreelist[BQ_LRU];
--- 202,210 ----
  		flist = &bfreelist[BQ_AGE];
  		binsheadfree(bp, flist);
  	} else {
! 		if (bp->b_flags & B_LOCKED)
! 			flist = &bfreelist[BQ_LOCKED];
! 		else if (bp->b_flags & B_AGE)
  			flist = &bfreelist[BQ_AGE];
  		else
  			flist = &bfreelist[BQ_LRU];
***************
*** 331,338 ****
  		bwrite(bp);
  		goto loop;
  	}
! #ifdef NRAM > 0
! 	if(bp->b_flags & B_RAMREMAP) {
  		register memaddr paddr;	/* click address of real buffer */
  		extern memaddr bpaddr;
  
--- 339,345 ----
  		bwrite(bp);
  		goto loop;
  	}
! 	if(bp->b_flags & (B_RAMREMAP|B_PHYS)) {
  		register memaddr paddr;	/* click address of real buffer */
  		extern memaddr bpaddr;
  
***************
*** 344,350 ****
  		bp->b_un.b_addr = (caddr_t)(paddr << 6);
  		bp->b_xmem = (paddr >> 10) & 077;
  	}
- #endif
  	trace(TR_BRELSE);
  	bp->b_flags = B_BUSY;
  	return (bp);
--- 351,356 ----
***************
*** 454,459 ****
--- 460,480 ----
  		}
  	}
  	splx(s);
+ }
+ 
+ /*
+  * Pick up the device's error number and pass it to the user;
+  * if there is an error but the number is 0 set a generalized code.
+  */
+ geterror(bp)
+ 	register struct buf *bp;
+ {
+ 	register int error = 0;
+ 
+ 	if (bp->b_flags&B_ERROR)
+ 		if ((error = bp->b_error)==0)
+ 			return(EIO);
+ 	return (error);
  }
  
  /*
*** /old/src/sys/sys/ufs_namei.c	Thu May 31 14:06:28 1990
--- /usr/src/sys/sys/ufs_namei.c	Mon Aug 19 14:47:46 1991
***************
*** 18,24 ****
  #include "namei.h"
  
  struct	buf *blkatoff();
- struct	buf *freenamebuf;
  int	dirchk = 0;
  
  /*
--- 18,23 ----
*** /old/src/sys/sys/vm_swp.c	Wed Apr 11 09:49:09 1990
--- /usr/src/sys/sys/vm_swp.c	Sun Sep 22 08:03:40 1991
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)vm_swp.c	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)vm_swp.c	2.2 (2.11BSD) 9/22/91
   */
  
  #include "param.h"
***************
*** 19,30 ****
  #include "uio.h"
  
  /*
-  * swap IO headers.  They are filled in to point
-  * at the desired IO operation.
-  */
- struct	buf swbuf1, swbuf2;
- 
- /*
   * swap I/O
   */
  swap(blkno, coreaddr, count, rdflg)
--- 19,24 ----
***************
*** 46,63 ****
  		cnt.v_pgout++;
  	}
  #endif
! 	bp = &swbuf1;
! 	if (bp->b_flags & B_BUSY)
! 		if ((swbuf2.b_flags&B_WANTED) == 0)
! 			bp = &swbuf2;
! 	s = splbio();
! 	while (bp->b_flags&B_BUSY) {
! 		bp->b_flags |= B_WANTED;
! 		sleep((caddr_t)bp, PSWP+1);
! 	}
! 	splx(s);
  	while (count) {
! 		bp->b_flags = B_BUSY | B_PHYS | rdflg;
  		bp->b_dev = swapdev;
  		tcount = count;
  		if (tcount >= 01700)	/* prevent byte-count wrap */
--- 40,49 ----
  		cnt.v_pgout++;
  	}
  #endif
! 	bp = geteblk();			/* allocate a buffer header */
! 
  	while (count) {
! 		bp->b_flags = B_BUSY | B_PHYS | B_INVAL | rdflg;
  		bp->b_dev = swapdev;
  		tcount = count;
  		if (tcount >= 01700)	/* prevent byte-count wrap */
***************
*** 67,96 ****
  		bp->b_un.b_addr = (caddr_t)(coreaddr<<6);
  		bp->b_xmem = (coreaddr>>10) & 077;
  		trace(TR_SWAPIO);
! 		physstrat(bp, bdevsw[major(swapdev)].d_strategy, PSWP);
  		if ((bp->b_flags & B_ERROR) || bp->b_resid)
! 			panic("hard IO err in swap");
  		count -= tcount;
  		coreaddr += tcount;
  		blkno += ctod(tcount);
  	}
! 	if (bp->b_flags&B_WANTED)
! 		wakeup((caddr_t)bp);
! 	bp->b_flags &= ~(B_BUSY|B_WANTED);
  }
  
  /*
!  * If rout == 0 then killed on swap error, else
!  * rout is the name of the routine where we ran out of
!  * swap space.
   */
  swkill(p, rout)
  	register struct proc *p;
! 	register char *rout;
  {
  
! 	printf("pid %d: %s\n", p->p_pid, rout);
! 	uprintf("sorry, pid %d was killed in %s\n", p->p_pid, rout);
  	/*
  	 * To be sure no looping (e.g. in vmsched trying to
  	 * swap out) mark process locked in core (as though
--- 53,82 ----
  		bp->b_un.b_addr = (caddr_t)(coreaddr<<6);
  		bp->b_xmem = (coreaddr>>10) & 077;
  		trace(TR_SWAPIO);
! 		(*bdevsw[major(swapdev)].d_strategy)(bp);
! 		s = splbio();
! 		while ((bp->b_flags & B_DONE) == 0)
! 			sleep((caddr_t)bp, PSWP);
! 		splx(s);
  		if ((bp->b_flags & B_ERROR) || bp->b_resid)
! 			panic("hard err: swap");
  		count -= tcount;
  		coreaddr += tcount;
  		blkno += ctod(tcount);
  	}
! 	brelse(bp);
  }
  
  /*
!  * rout is the name of the routine where we ran out of swap space.
   */
  swkill(p, rout)
  	register struct proc *p;
! 	char *rout;
  {
  
! 	tprintf(u.u_ttyp, "sorry, pid %d killed in %s: no swap space\n", 
! 		p->p_pid, rout);
  	/*
  	 * To be sure no looping (e.g. in vmsched trying to
  	 * swap out) mark process locked in core (as though
***************
*** 104,238 ****
  /*
   * Raw I/O. The arguments are
   *	The strategy routine for the device
!  *	A buffer, which will always be a special buffer
!  *	  header owned exclusively by the device for this purpose
   *	The device number
   *	Read/write flag
   * Essentially all the work is computing physical addresses and
   * validating them.
   *
-  * physio broken into smaller routines, 3/81 mjk
-  *	chkphys(WORD or BYTE) checks validity of word- or byte-
-  *	oriented transfer (for physio or device drivers);
-  *	physbuf(strat,bp,rw) fills in the buffer header.
-  *
-  * physio divided into two functions, 1/83 - Mike Edmonds - Tektronix
-  *	Physio divided into separate functions:
-  *		physio (for WORD i/o)
-  *		bphysio (for BYTE i/o)
-  *	This allows byte-oriented devices (such as tape drives)
-  *	to write/read odd length blocks.
-  *
-  * since physio/bphysio just called physio1 with BYTE or WORD added
-  *	to the argument list, adjusted all calls to physio/bphysio
-  *	to pass the correct argument themselves.
-  *		5/86 kb
-  *
   * rewritten to use the iov/uio mechanism from 4.3bsd.  the physbuf routine
   * was inlined.  essentially the chkphys routine performs the same task
   * as the useracc routine on a 4.3 system. 3/90 sms
   */
! physio(strat, bp, dev, rw, kind, uio)
  	int (*strat)();
  	register struct buf *bp;
  	dev_t dev;
! 	int rw, kind;
  	register struct uio *uio;
  {
! 	int error, s, nb, ts, c;
  	register struct iovec *iov;
  
! nextiov:
! 	u.u_procp->p_flag |= SLOCK;
! 	if (uio->uio_iovcnt == 0) {
! 		u.u_procp->p_flag &= ~SLOCK;
! 		return (0);
  	}
! 	iov = uio->uio_iov;
! 	error = chkphys(kind, iov);
! 	if (error) {
! 		u.u_procp->p_flag &= ~SLOCK;
! 		return(error);
! 	}
! 	s = splbio();
! 	while (bp->b_flags & B_BUSY) {
! 		bp->b_flags |= B_WANTED;
! 		sleep((caddr_t)bp, PRIBIO+1);
! 	}
! 	splx(s);
! 	while (iov->iov_len) {
! 		bp->b_flags = B_BUSY|B_PHYS|rw;
! 		bp->b_dev = dev;
  		nb = ((int)iov->iov_base >> 6) & 01777;
! 		ts = (u.u_sep ? UDSA : UISA)[nb >> 7] + (nb & 0177);
! 		bp->b_un.b_addr = (caddr_t)((ts << 6) + ((int)iov->iov_base & 077));
! 		bp->b_xmem = (ts >> 10) & 077;
! 		bp->b_blkno = uio->uio_offset >> PGSHIFT;
! 		bp->b_bcount = iov->iov_len;
! 		c = bp->b_bcount;
  		bp->b_error = 0;
! 		physstrat(bp, strat, PRIBIO);
! 		c -= bp->b_resid;
! 		iov->iov_base += c;
! 		iov->iov_len -= c;
! 		uio->uio_resid -= c;
! 		uio->uio_offset += c;
  		/* temp kludge for tape drives */
! 		if (bp->b_resid || (bp->b_flags & B_ERROR))
  			break;
  	}
! 	if (bp->b_flags & B_WANTED)
! 		wakeup((caddr_t)bp);
! 	bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS);
! 	error = geterror(bp);
! 	/* temp kludge for tape drives */
! 	if (bp->b_resid || error) {
! 		u.u_procp->p_flag &= ~SLOCK;
! 		return (error);
! 	}
! 	uio->uio_iov++;
! 	uio->uio_iovcnt--;
! 	goto nextiov;
  }
  
! /*
!  * check for validity of physical I/O area
!  * (modified from physio to use flag for BYTE-oriented transfers)
!  */
! chkphys(flag, iov)
! 	int flag;
! 	register struct iovec *iov;
! {
! 	register int nb, ts;
  
! 	/*
! 	 * Check odd base, odd count, and address wraparound
! 	 * Odd base and count not allowed if flag = WORD,
! 	 * allowed if flag = BYTE.
! 	 */
! 	if (flag == WORD && (((int)iov->iov_base|iov->iov_len) & 01))
! 		return(EFAULT);
! 	if (iov->iov_base >= iov->iov_base + iov->iov_len)
! 		return(EFAULT);
! 	if (u.u_sep)
! 		ts = 0;
! 	else
! 		ts = (u.u_tsize + 127) & ~0177;
! 	nb = ((int)iov->iov_base >> 6) & 01777;
! 	/*
! 	 * Check overlap with text. (ts and nb now
! 	 * in 64-byte clicks)
! 	 */
! 	if (nb < ts)
! 		return(EFAULT);
! 	/*
! 	 * Check that transfer is either entirely in the
! 	 * data or in the stack: that is, either
! 	 * the end is in the data or the start is in the stack
! 	 * (remember wraparound was already checked).
! 	 */
! 	if (((((int)iov->iov_base + iov->iov_len) >> 6) & 01777) >= ts + u.u_dsize &&
! 	    nb < 1024 - u.u_ssize)
! 		return(EFAULT);
! 	return(0);
! }
--- 90,229 ----
  /*
   * Raw I/O. The arguments are
   *	The strategy routine for the device
!  *	A buffer, which may be a special buffer header
!  *	  owned exclusively by the device for this purpose or
!  *	  NULL if one is to be allocated.
   *	The device number
   *	Read/write flag
   * Essentially all the work is computing physical addresses and
   * validating them.
   *
   * rewritten to use the iov/uio mechanism from 4.3bsd.  the physbuf routine
   * was inlined.  essentially the chkphys routine performs the same task
   * as the useracc routine on a 4.3 system. 3/90 sms
+  *
+  * If the buffer pointer is NULL then one is allocated "dynamically" from
+  * the system cache.  the 'invalid' flag is turned on so that the brelse()
+  * done later doesn't place the buffer back in the cache.  the 'phys' flag
+  * is left on so that the address of the buffer is recalcuated in getnewbuf().
+  * The BYTE/WORD stuff began to be removed after testing proved that either
+  * 1) the underlying hardware gives an error or 2) nothing bad happens.
+  * besides, 4.3BSD doesn't do the byte/word check and noone could remember
+  * why the byte/word check was added in the first place - likely historical
+  * paranoia.  chkphys() inlined.  5/91 sms
+  *
+  * Refined (and streamlined) the flow by using a 'for' construct 
+  * (a la 4.3Reno).  Avoid allocating/freeing the buffer for each iovec
+  * element (i must have been confused at the time).  6/91-sms
+  *
+  * Finished removing the BYTE/WORD code as part of implementing the common
+  * raw read&write routines , systems had been running fine for several
+  * months with it ifdef'd out.  9/91-sms
   */
! physio(strat, bp, dev, rw, uio)
  	int (*strat)();
  	register struct buf *bp;
  	dev_t dev;
! 	int rw;
  	register struct uio *uio;
  {
! 	int error = 0, s, nb, ts, c, allocbuf = 0;
  	register struct iovec *iov;
  
! 	if (!bp) {
! 		allocbuf++;
! 		bp = geteblk();
  	}
! 	u.u_procp->p_flag |= SLOCK;
! 	for ( ; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) {
! 		iov = uio->uio_iov;
! 		if (iov->iov_base >= iov->iov_base + iov->iov_len) {
! 			error = EFAULT;
! 			break;
! 		}
! 		if (u.u_sep)
! 			ts = 0;
! 		else
! 			ts = (u.u_tsize + 127) & ~0177;
  		nb = ((int)iov->iov_base >> 6) & 01777;
! 		/*
! 		 * Check overlap with text. (ts and nb now
! 		 * in 64-byte clicks)
! 		 */
! 		if (nb < ts) {
! 			error = EFAULT;
! 			break;
! 		}
! 		/*
! 		 * Check that transfer is either entirely in the
! 		 * data or in the stack: that is, either
! 		 * the end is in the data or the start is in the stack
! 		 * (remember wraparound was already checked).
! 		 */
! 		if (((((int)iov->iov_base + iov->iov_len) >> 6) & 01777) >= 
! 			ts + u.u_dsize && nb < 1024 - u.u_ssize) {
! 			error = EFAULT;
! 			break;
! 		}
! 		if (!allocbuf) {
! 			s = splbio();
! 			while (bp->b_flags & B_BUSY) {
! 				bp->b_flags |= B_WANTED;
! 				sleep((caddr_t)bp, PRIBIO+1);
! 			}
! 			splx(s);
! 		}
  		bp->b_error = 0;
! 		while (iov->iov_len) {
! 			bp->b_flags = B_BUSY|B_PHYS|B_INVAL|rw;
! 			bp->b_dev = dev;
! 			nb = ((int)iov->iov_base >> 6) & 01777;
! 			ts = (u.u_sep ? UDSA : UISA)[nb >> 7] + (nb & 0177);
! 			bp->b_un.b_addr = (caddr_t)((ts << 6) + ((int)iov->iov_base & 077));
! 			bp->b_xmem = (ts >> 10) & 077;
! 			bp->b_blkno = uio->uio_offset >> PGSHIFT;
! 			bp->b_bcount = iov->iov_len;
! 			c = bp->b_bcount;
! 			(*strat)(bp);
! 			s = splbio();
! 			while ((bp->b_flags & B_DONE) == 0)
! 				sleep((caddr_t)bp, PRIBIO);
! 			if (bp->b_flags & B_WANTED)	/* rare */
! 				wakeup((caddr_t)bp);
! 			splx(s);
! 			c -= bp->b_resid;
! 			iov->iov_base += c;
! 			iov->iov_len -= c;
! 			uio->uio_resid -= c;
! 			uio->uio_offset += c;
! 			/* temp kludge for tape drives */
! 			if (bp->b_resid || (bp->b_flags & B_ERROR))
! 				break;
! 		}
! 		bp->b_flags &= ~(B_BUSY|B_WANTED);
! 		error = geterror(bp);
  		/* temp kludge for tape drives */
! 		if (bp->b_resid || error)
  			break;
  	}
! 	if (allocbuf)
! 		brelse(bp);
! 	u.u_procp->p_flag &= ~SLOCK;
! 	return(error);
  }
  
! rawread(dev, uio)
! 	dev_t dev;
! 	struct uio *uio;
! 	{
! 	return(physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, dev,
! 		B_READ, uio));
! 	}
  
! rawwrite(dev, uio)
! 	dev_t dev;
! 	struct uio *uio;
! 	{
! 	return(physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, dev,
! 		B_WRITE, uio));
! 	}
