*** /old/src/sys/pdpuba/tmscp.c	Wed Dec 19 10:11:09 1990
--- /usr/src/sys/pdpuba/tmscp.c	Sun Sep 22 08:43:13 1991
***************
*** 1,4 ****
! /*	@(#)tmscp.c	7.1 (Berkeley) 6/5/86 */
  
  #if	!defined(lint) && defined(DOSCCS)
  static	char	*sccsid = "@(#)tmscp.c	1.24	(ULTRIX)	1/21/86";
--- 1,4 ----
! /*	@(#)tmscp.c	1.2 (2.11BSD) 9/22/91 */
  
  #if	!defined(lint) && defined(DOSCCS)
  static	char	*sccsid = "@(#)tmscp.c	1.24	(ULTRIX)	1/21/86";
***************
*** 31,40 ****
   * tmscp.c - TMSCP (TK50/TU81) tape device driver
   * 
   * Modification History:
   *
   * 17-Jun-90,14Aug90 - sms@wlv.imsd.contel.com
   *	Began porting to 2.10.1BSD/2.11BSD.  Multiple drives per controller
!  *	NOT supported, although multiple controllers are.  Programmable
   *	vectors don't work very well with the autoconfigure scheme in use.
   *	the define TMSCP_VEC will have to be adjusted in tms.h (see
   *	conf/config and the sample config files).  For patching purposes
--- 31,76 ----
   * tmscp.c - TMSCP (TK50/TU81) tape device driver
   * 
   * Modification History:
+  * 23-May-91 - sms@wlv.imsd.contel.com [2.11BSD]
+  *	Minor typo in the multicontroller support fixed.  Major overhaul
+  *	of the density selection, apparently some TMSCP controllers
+  *	do not treat 0 in the mscp_format word as meaning the highest
+  *	density, instead leaving the drive in the current/last-used
+  *	density.
   *
+  * 29-Mar-91 - sms@wlv.imsd.contel.com [2.11BSD]
+  *	Major changes to 1) support multiple drives per controller
+  *	(the maximum number of drives per controller is 4 for now in order
+  *	to maximize compatibility with existing minor device numbers - the
+  *	norewind and density bit stay in the same place) and 2) more
+  *	importantly reduce the bloat of this driver.  The command
+  *	packet area is now allocated from an external heap setup at boot
+  *	time (the MSCP, ra.c driver also does this).  Allocating from an
+  * 	external arena save approximately 2kb of kernel D space PER CONTROLLER
+  *	and costs little in speed because the amount of remapping involved is
+  *	quite small.
+  *
+  *	The 'errinfo' routine was removed in the interest of space savings,
+  *	the error code was already being printed out in hex and it's not
+  *	worth eating up another 250 or so bytes of kernel D space to pretty
+  *	print messages for which tmscp.h provides the cross reference (I space
+  *	is also saved by not printing the messages).  Besides, the ra.c (MSCP)
+  *	driver doesn't do it and it is worth a degree of non 4.3BSD verisimility
+  *	to save a significant amount of space.
+  *
+  *	The tms_type field should have been a 'long' (mediatype).  Since the
+  *	drives are not probed at autoconfigure time a GTUNT (TMS_SENSE) command
+  *	is done at open() time to fetch the format/density menu and unit flags.
+  *	iodone() proccessing was missing for the GTUNT function in tmscprsp()
+  *	causing hangs in both open and ioctl functions.
+  *
+  *	Multiple controller support made to work, the top 2 bits of the minor
+  *	device number are used to designate the controller, thus there is
+  *	a maximum of 4 TMSCP controllers per system.
+  *
   * 17-Jun-90,14Aug90 - sms@wlv.imsd.contel.com
   *	Began porting to 2.10.1BSD/2.11BSD.  Multiple drives per controller
!  *	NOT supported, although multiple controllers are (maybe).  Programmable
   *	vectors don't work very well with the autoconfigure scheme in use.
   *	the define TMSCP_VEC will have to be adjusted in tms.h (see
   *	conf/config and the sample config files).  For patching purposes
***************
*** 156,161 ****
--- 192,212 ----
  
  	short	TMSvec = TMSCP_VEC;	/* patchable base of vectors */
  
+ /*
+  * The density array is indexed by the density bits (bits 3 and 4) of the
+  * minor device number AND the format menu returned for the drive.  Since
+  * only 3 densities are apparently supported by TMSCP (no DPE/3200bpi), the 
+  * second MEDium table is a copy of the first MEDium entry.
+ */
+ 
+ 	char	Dmatrix[4][8] =
+ 		{
+ /* LOW */   {0,M_TF_800,M_TF_PE,M_TF_800,M_TF_GCR,M_TF_800,M_TF_PE,M_TF_800},
+ /* MED1 */  {0,M_TF_800,M_TF_PE,M_TF_800,M_TF_GCR,M_TF_800,M_TF_PE,M_TF_PE },
+ /* MED2 */  {0,M_TF_800,M_TF_PE,M_TF_800,M_TF_GCR,M_TF_800,M_TF_PE,M_TF_PE },
+ /* HI */    {0,M_TF_800,M_TF_PE,M_TF_PE,M_TF_GCR,M_TF_GCR,M_TF_GCR,M_TF_GCR}
+ 		};
+ 
  /* Software state per controller */
  
  struct tmscp_softc {
***************
*** 162,167 ****
--- 213,219 ----
  	struct	tmscpdevice *sc_addr;	/* controller CSR address */
  	short   sc_state;       /* state of controller */
  	short	sc_ivec;        /* interrupt vector address */
+ 	short	sc_unit;	/* CONTROLLER number - NOT drive unit # */
  	short   sc_credits;     /* transfer credits */
  	short   sc_lastcmd;     /* pointer into command ring */
  	short   sc_lastrsp;     /* pointer into response ring */
***************
*** 169,174 ****
--- 221,227 ----
  	struct	buf sc_ctab;	/* controller queue */
  	struct	buf sc_wtab;	/* I/O wait queue for controller */
  	struct	tmscp *sc_com;	/* communications area pointer */
+ 	struct	tms_info *sc_drives[4];	/* pointers to per drive info */
  } tmscp_softc[NTMSCP];
  
  #define	RINGBASE	(4 * sizeof (short))
***************
*** 177,190 ****
  	struct tmscpca	tmscp_ca;         /* communications area */
  	struct mscp	tmscp_rsp[NRSP];  /* response packets */
  	struct mscp	tmscp_cmd[NCMD];  /* command packets */
! } tmscp[NTMSCP];
  
  /*
   * Per drive-unit info
   */
  struct tms_info {
  	daddr_t		tms_dsize;	/* Max user size from online pkt */
! 	unsigned	tms_type;	/* Drive type int field  */
  	int		tms_resid;	/* residual from last xfer */
  	u_char		tms_endcode;	/* last command endcode */
  	u_char		tms_flags;	/* last command end flags */
--- 230,245 ----
  	struct tmscpca	tmscp_ca;         /* communications area */
  	struct mscp	tmscp_rsp[NRSP];  /* response packets */
  	struct mscp	tmscp_cmd[NCMD];  /* command packets */
! };					  /* 1896 bytes per controller! */
  
+ 	memaddr	tmscp[NTMSCP];		/* click addresses of ctrl comm area */
+ 
  /*
   * Per drive-unit info
   */
  struct tms_info {
  	daddr_t		tms_dsize;	/* Max user size from online pkt */
! 	long		tms_type;	/* Drive type field  */
  	int		tms_resid;	/* residual from last xfer */
  	u_char		tms_endcode;	/* last command endcode */
  	u_char		tms_flags;	/* last command end flags */
***************
*** 198,218 ****
  	short		tms_format;	/* the unit's current format (density) */
  	struct tty	*tms_ttyp;	/* record user's tty for errors */
  	struct	buf	tms_dtab;	/* I/O tape drive queues */
! 	struct	buf	tms_rtab;	/* raw I/O tape block header */
! 	short		tms_online;	/* online flag */
  } tms_info[NTMS];
  
- struct	buf	tmscomphys;		/* Communication area phys map */
- long	tmsphys();
- 
- #ifndef	KDSA0
- #define KDSA0		((u_short *)0172360)
- #endif
  /* Bits in minor device */
  #define	TMSUNIT(dev)	(minor(dev)&03)
  #define	T_NOREWIND	04
- #define	T_HIDENSITY	010
  
  /*
   * Internal (ioctl) command codes (these must also be declared in the
   * tmscpioctl routine).  These correspond to ioctls in mtio.h
--- 253,272 ----
  	short		tms_format;	/* the unit's current format (density) */
  	struct tty	*tms_ttyp;	/* record user's tty for errors */
  	struct	buf	tms_dtab;	/* I/O tape drive queues */
! 	short		tms_online;	/* 0=available, 1=online, -1=offline */
  } tms_info[NTMS];
  
  /* Bits in minor device */
  #define	TMSUNIT(dev)	(minor(dev)&03)
+ #define	TMSCTLR(dev)	((minor(dev) >> 6) & 3)
+ #define	TMSDENS(dev)	((minor(dev) >> 3) & 3)
+ #define	FMTMASK		(M_TF_800|M_TF_PE|M_TF_GCR)	/* = 7 */
+ 
  #define	T_NOREWIND	04
  
+ /* Size to map in when mapping a controller's command packet area */
+ #define	MAPBUFDESC	(((btoc(sizeof (struct tmscp)) - 1) << 8) | RW)
+ 
  /*
   * Internal (ioctl) command codes (these must also be declared in the
   * tmscpioctl routine).  These correspond to ioctls in mtio.h
***************
*** 229,236 ****
  #define TMS_NOCACHE	9		/* disable cache */
  /* These go last: after all real mt cmds, just bump the numbers up */
  #define TMS_CSE		10		/* clear serious exception */
! #define TMS_LOWDENSITY	11		/* set unit to low density */
! #define TMS_HIDENSITY	12		/* set unit to high density */
  
  /*
   * Controller states
--- 283,289 ----
  #define TMS_NOCACHE	9		/* disable cache */
  /* These go last: after all real mt cmds, just bump the numbers up */
  #define TMS_CSE		10		/* clear serious exception */
! #define TMS_SETDENSITY	11		/* set unit density */
  
  /*
   * Controller states
***************
*** 247,252 ****
--- 300,306 ----
  				/* packets and or credits. */
  int	wakeup();
  extern	int	hz;		/* Should find the right include */
+ extern	long	_iomap();
  
  #ifdef	TMSCP_DEBUG
  #define printd if (tmscpdebug) printf
***************
*** 259,282 ****
  #define b_qsize         b_resid         /* queue size per drive, in tmsutab */
  
  /* 
-  * Set ui flags to zero to show device is not online & set tmscpip.
-  * Unit to Controller mapping is set up here.
   * Open routine will issue the online command, later.
   */
  tmsattach(addr, unit)
  	struct tmscpdevice *addr;
  	register int unit;
  {
! 	register struct tmscp_softc *sc = &tmscp_softc[TMSUNIT(unit)];
  
  	if (sc->sc_addr == NULL && addr != NULL) {
  		sc->sc_addr = addr;
! 		sc->sc_com = &tmscp[TMSUNIT(unit)];
  		return (1);
  	}
  	return(0);
  }
  
  /*
   * TMSCP interrupt routine.
   */
--- 313,359 ----
  #define b_qsize         b_resid         /* queue size per drive, in tmsutab */
  
  /* 
   * Open routine will issue the online command, later.
+  *
+  * This routine attaches controllers, not drives - sc_unit and 'unit' are 
+  * the controller number not a drive unit number.  sc_com is initialized
+  * to SEG5 because all communication areas are mapped to the same virtual
+  * address now.
   */
  tmsattach(addr, unit)
  	struct tmscpdevice *addr;
  	register int unit;
  {
! 	register struct tmscp_softc *sc = &tmscp_softc[unit];
  
+ 	if (unit >= NTMSCP)
+ 		return(0);
  	if (sc->sc_addr == NULL && addr != NULL) {
+ 		tmscp[unit] = (memaddr)_ioget(sizeof (struct tmscp));
+ 		if (tmscp[unit] == NULL)
+ 			return(0);
  		sc->sc_addr = addr;
! 		sc->sc_unit = unit;
! 		sc->sc_com = (struct tmscp *)SEG5;
  		return (1);
  	}
  	return(0);
  }
  
+ struct tms_info *
+ getdd()
+ {
+ 	register int i;
+ 	register struct tms_info *p;
+ 
+ 	for (i = NTMS, p = tms_info; i--; p++) {
+ 		if (p->tms_online == 0)
+ 			return(p);
+ 	}
+ 	log(TMS_PRI, "tms: no drive descriptors\n");
+ 	return(NULL);
+ }
+ 
  /*
   * TMSCP interrupt routine.
   */
***************
*** 283,295 ****
  tmsintr(dev)
  	dev_t dev;
  {
- 	int unit = TMSUNIT(dev);
  	register struct tmscpdevice *tmscpaddr;
  	struct buf *bp;
  	register int i;
! 	register struct tmscp_softc *sc = &tmscp_softc[unit];
! 	register struct tmscp *tm = &tmscp[unit];
  	struct mscp *mp;
  
  	tmscpaddr = sc->sc_addr;
  #ifdef TMSCP_DEBUG
--- 360,372 ----
  tmsintr(dev)
  	dev_t dev;
  {
  	register struct tmscpdevice *tmscpaddr;
  	struct buf *bp;
  	register int i;
! 	register struct tmscp_softc *sc = &tmscp_softc[dev];
! 	register struct tmscp *tm = sc->sc_com;
  	struct mscp *mp;
+ 	segm seg5;
  
  	tmscpaddr = sc->sc_addr;
  #ifdef TMSCP_DEBUG
***************
*** 302,308 ****
  	switch (sc->sc_state) {
  
  	case S_IDLE:
! 		printf("tms%d: random interrupt ignored\n", unit);
  		return;
  
  	/* Controller was in step 1 last, see if its gone to step 2 */
--- 379,385 ----
  	switch (sc->sc_state) {
  
  	case S_IDLE:
! 		printf("tms%d: random intr ignored\n", dev);
  		return;
  
  	/* Controller was in step 1 last, see if its gone to step 2 */
***************
*** 325,331 ****
  			{
  			sc->sc_state = S_IDLE;
  			sc->sc_ctab.b_active = 0;
! 			printf("failed to init, in step1: sa 0x%x", tmscpaddr->tmscpsa);
  			wakeup((caddr_t)&sc->sc_ctab);
  			return;
  			}
--- 402,408 ----
  			{
  			sc->sc_state = S_IDLE;
  			sc->sc_ctab.b_active = 0;
! 			printf("step1 init failed: sa 0x%x",tmscpaddr->tmscpsa);
  			wakeup((caddr_t)&sc->sc_ctab);
  			return;
  			}
***************
*** 353,359 ****
  			{
  			sc->sc_state = S_IDLE;
  			sc->sc_ctab.b_active = 0;
! 			printf("failed to init, in step2: sa 0x%x", tmscpaddr->tmscpsa);
  			wakeup((caddr_t)&sc->sc_ctab);
  			return;
  			}
--- 430,436 ----
  			{
  			sc->sc_state = S_IDLE;
  			sc->sc_ctab.b_active = 0;
! 			printf("step2 init failed: sa 0x%x",tmscpaddr->tmscpsa);
  			wakeup((caddr_t)&sc->sc_ctab);
  			return;
  			}
***************
*** 381,387 ****
  			{
  			sc->sc_state = S_IDLE;
  			sc->sc_ctab.b_active = 0;
! 			printf("failed to init, in step3: sa 0x%x", tmscpaddr->tmscpsa);
  			wakeup((caddr_t)&sc->sc_ctab);
  			return;
  			}
--- 458,464 ----
  			{
  			sc->sc_state = S_IDLE;
  			sc->sc_ctab.b_active = 0;
! 			printf("step3 init failed: sa 0x%x",tmscpaddr->tmscpsa);
  			wakeup((caddr_t)&sc->sc_ctab);
  			return;
  			}
***************
*** 402,407 ****
--- 479,486 ----
  	    /*
  	     * Initialize the data structures (response and command queues).
  	     */
+ 	    saveseg5(seg5);
+ 	    mapseg5(tmscp[sc->sc_unit], MAPBUFDESC);
  	    tmsginit(sc, sc->sc_com->tmscp_ca.ca_rspdsc, sc->sc_com->tmscp_rsp,
  			0, NRSP, TMSCP_OWN|TMSCP_INT);
  	    tmsginit(sc, sc->sc_com->tmscp_ca.ca_cmddsc, sc->sc_com->tmscp_cmd,
***************
*** 425,430 ****
--- 504,510 ----
  	    mp->mscp_opcode = M_OP_STCON;
  	    ((Trl *)mp->mscp_dscptr)->hsh |= TMSCP_OWN|TMSCP_INT;
  	    i = tmscpaddr->tmscpip;      /* initiate polling */
+ 	    restorseg5(seg5);
  	    return;
  
  	case S_SCHAR:
***************
*** 432,438 ****
  		break;
  
  	default:
! 	    printf("tms%d: interrupt in unknown state %d ignored\n",unit,sc->sc_state);
  	    return;
  	}	/* end switch */
  
--- 512,518 ----
  		break;
  
  	default:
! 	    printf("tms%d: intr unknown state %d ignored\n",dev,sc->sc_state);
  	    return;
  	}	/* end switch */
  
***************
*** 446,452 ****
  	 */
  	if (tmscpaddr->tmscpsa&TMSCP_ERR)
  		{
! 		printf("tms%d: fatal error (%o)\n", unit, tmscpaddr->tmscpsa);
  		tmscpaddr->tmscpip = 0;
  		sc->sc_state = S_IDLE;
  		sc->sc_ctab.b_active = 0;
--- 526,532 ----
  	 */
  	if (tmscpaddr->tmscpsa&TMSCP_ERR)
  		{
! 		printf("tms%d: fatal error %o\n", dev, tmscpaddr->tmscpsa);
  		tmscpaddr->tmscpip = 0;
  		sc->sc_state = S_IDLE;
  		sc->sc_ctab.b_active = 0;
***************
*** 455,460 ****
--- 535,542 ----
  	/*
  	 * Check for a buffer purge request. (Won't happen w/ TK50 on Q22 bus)
  	 */
+ 	saveseg5(seg5);
+ 	mapseg5(tmscp[sc->sc_unit], MAPBUFDESC);
  	if (tm->tmscp_ca.ca_bdp)
  		{
  		tm->tmscp_ca.ca_bdp = 0;
***************
*** 472,478 ****
  			i %= NRSP;
  			if (tm->tmscp_ca.ca_rspdsc[i].hsh&TMSCP_OWN)
  			    break;
! 			tmscprsp(unit, tm, sc, i);
  			tm->tmscp_ca.ca_rspdsc[i].hsh |= TMSCP_OWN;
  			}
  		sc->sc_lastrsp = i;
--- 554,560 ----
  			i %= NRSP;
  			if (tm->tmscp_ca.ca_rspdsc[i].hsh&TMSCP_OWN)
  			    break;
! 			tmscprsp(sc, i);
  			tm->tmscp_ca.ca_rspdsc[i].hsh |= TMSCP_OWN;
  			}
  		sc->sc_lastrsp = i;
***************
*** 488,494 ****
  #endif		
  		tm->tmscp_ca.ca_cmdint = 0;
  		}
!     	if(tmscp_cp_wait)
  		wakeup((caddr_t)&tmscp_cp_wait);
      	(void) tmsstart(sc);
  }
--- 570,577 ----
  #endif		
  		tm->tmscp_ca.ca_cmdint = 0;
  		}
! 	restorseg5(seg5);
!     	if (tmscp_cp_wait)
  		wakeup((caddr_t)&tmscp_cp_wait);
      	(void) tmsstart(sc);
  }
***************
*** 504,510 ****
  	dev_t dev;
  	int flag;
  {
! 	register int unit;
  	register struct tmscp_softc *sc;
  	register struct tms_info *tms;
  	register struct mscp *mp;
--- 587,594 ----
  	dev_t dev;
  	int flag;
  {
! 	register int unit = TMSUNIT(dev);
! 	int ctlr = TMSCTLR(dev);
  	register struct tmscp_softc *sc;
  	register struct tms_info *tms;
  	register struct mscp *mp;
***************
*** 511,529 ****
  	struct tmscpdevice *tmscpaddr;
  	int s,i;
  	
- 	unit = TMSUNIT(dev);
  #ifdef TMSCP_DEBUG
! 	printd("tmscpopen unit %d\n",unit);
! 	if(tmscpdebug)delay(10000L);
  #endif
! 	if (unit >= NTMS)
  		return (ENXIO);
! 	tms = &tms_info[unit];
! 	if (tms->tms_openf)
! 		return (EBUSY);
! 	sc = &tmscp_softc[unit];
  	if (sc->sc_addr == NULL)
  		return (ENXIO);
  	tms->tms_openf = 1;
  	tms->tms_ttyp = u.u_ttyp;
  	s = spl5();
--- 595,618 ----
  	struct tmscpdevice *tmscpaddr;
  	int s,i;
  	
  #ifdef TMSCP_DEBUG
! 	printd("tmscpopen %d,%d\n", ctlr, unit);
! 	if (tmscpdebug) delay(10000L);
  #endif
! 	if (ctlr >= NTMSCP)
  		return (ENXIO);
! 	sc = &tmscp_softc[ctlr];
  	if (sc->sc_addr == NULL)
  		return (ENXIO);
+ 	if ((tms = sc->sc_drives[unit]) == NULL) {
+ 		tms = getdd();
+ 		if (!tms)
+ 			return(ENXIO);
+ 		tms->tms_online = -1;
+ 		sc->sc_drives[unit] = tms;
+ 	}
+ 	if (tms->tms_openf)
+ 		return(EBUSY);
  	tms->tms_openf = 1;
  	tms->tms_ttyp = u.u_ttyp;
  	s = spl5();
***************
*** 532,538 ****
  		if (sc->sc_state == S_IDLE)
  			if(!tkini(sc))
  				{
! 				printf("tms ctrl failed to init\n");
  				(void) splx(s);
  				return(ENXIO);
  				}
--- 621,627 ----
  		if (sc->sc_state == S_IDLE)
  			if(!tkini(sc))
  				{
! 				printf("tms%d init failed\n", ctlr);
  				(void) splx(s);
  				return(ENXIO);
  				}
***************
*** 543,550 ****
  		sleep((caddr_t)&sc->sc_ctab, PSWP+1);
  		if (sc->sc_state != S_RUN)
  			{
  			(void) splx(s);
- 			tms->tms_openf = 0;
  			return (EIO);
  			}
  		}
--- 632,640 ----
  		sleep((caddr_t)&sc->sc_ctab, PSWP+1);
  		if (sc->sc_state != S_RUN)
  			{
+ 			sc->sc_drives[unit] = NULL;
+ 			tms->tms_online = tms->tms_openf = 0;
  			(void) splx(s);
  			return (EIO);
  			}
  		}
***************
*** 554,563 ****
  	 */
  	tmscpaddr = (struct tmscpdevice *) sc->sc_addr;
  	(void) splx(s);
! 	if(tms->tms_online == 0)
  		{
  		s = spl5();
! 		while((mp = tmscpgetcp(sc)) == 0)
  			{
  			tmscp_cp_wait++;
  			sleep((caddr_t)&tmscp_cp_wait,PSWP+1);
--- 644,653 ----
  	 */
  	tmscpaddr = (struct tmscpdevice *) sc->sc_addr;
  	(void) splx(s);
! 	if(tms->tms_online == -1)
  		{
  		s = spl5();
! 		while ((mp = tmscpgetcp(sc)) == 0)
  			{
  			tmscp_cp_wait++;
  			sleep((caddr_t)&tmscp_cp_wait,PSWP+1);
***************
*** 564,577 ****
  			tmscp_cp_wait--;
  			}
  		(void) splx(s);
  		mp->mscp_opcode = M_OP_ONLIN;
! 		mp->mscp_unit = 0;		/* unit? */
  		mp->mscp_cmdref = (u_short)&tms->tms_type;
  					    /* need to sleep on something */
  #ifdef TMSCP_DEBUG
! 		printd("tmscpopen: bring unit %d online\n",unit);
  #endif	
  		((Trl *)mp->mscp_dscptr)->hsh |= TMSCP_OWN | TMSCP_INT;
  		i = tmscpaddr->tmscpip;
  		/* 
  		 * To make sure we wake up, timeout in 240 seconds.
--- 654,669 ----
  			tmscp_cp_wait--;
  			}
  		(void) splx(s);
+ 		mapseg5(tmscp[sc->sc_unit], MAPBUFDESC);
  		mp->mscp_opcode = M_OP_ONLIN;
! 		mp->mscp_unit = unit;		/* unit? */
  		mp->mscp_cmdref = (u_short)&tms->tms_type;
  					    /* need to sleep on something */
  #ifdef TMSCP_DEBUG
! 		printd("tmscpopen: bring unit %d,%d online\n",ctlr, unit);
  #endif	
  		((Trl *)mp->mscp_dscptr)->hsh |= TMSCP_OWN | TMSCP_INT;
+ 		normalseg5();
  		i = tmscpaddr->tmscpip;
  		/* 
  		 * To make sure we wake up, timeout in 240 seconds.
***************
*** 579,602 ****
  		 * 240 seconds (4 minutes) is necessary since a rewind
  		 * can take a few minutes.
  		 */
! 		timeout(wakeup,(caddr_t) mp->mscp_cmdref,240 * hz);
! 		sleep((caddr_t) mp->mscp_cmdref,PSWP+1);
  		}
! 	if(tms->tms_online == 0) {
! 		tms->tms_openf = 0;
  		return(ENXIO);  /* Didn't go online */
! 	}
  	tms->tms_lastiow = 0;
  	/*
! 	 * If the high density device is not specified, set unit to low
! 	 * density.  This is done as an "internal" ioctl command so
  	 * that the command setup and response handling
  	 * is done thru "regular" command routines.
  	 */
! 	if ((minor(dev) & T_HIDENSITY) == 0)
! 		tmscpcommand(dev, TMS_LOWDENSITY, 1);
! 	else
! 		tmscpcommand(dev, TMS_HIDENSITY, 1);
  	return (0);
  }
  
--- 671,704 ----
  		 * 240 seconds (4 minutes) is necessary since a rewind
  		 * can take a few minutes.
  		 */
! 		timeout(wakeup,(caddr_t) &tms->tms_type,240 * hz);
! 		sleep((caddr_t) &tms->tms_type,PSWP+1);
  		}
! 	if	(tms->tms_online == -1)
! 		{
! oops:		tms->tms_online = tms->tms_openf = 0;
! 		sc->sc_drives[unit] = NULL;
  		return(ENXIO);  /* Didn't go online */
! 		}
! 	/*
! 	 * Get the unit characteristics (GTUNT).  Done here because we
! 	 * do not check for slave units at autoconfigure time.  This really
! 	 * only need be done once, but it's easier to do it on each open.
! 	 * tmscpcommand() is used since the iodone() handling for GTUNT has
! 	 * been fixed.
! 	*/
! 	tms->tms_type = 0;
! 	tmscpcommand(dev, TMS_SENSE, 1);
! 	if	(tms->tms_type == 0)
! 		goto oops;
  	tms->tms_lastiow = 0;
  	/*
! 	 * Set unit density using the density matrix.
! 	 * This is done as an "internal" ioctl command so
  	 * that the command setup and response handling
  	 * is done thru "regular" command routines.
  	 */
! 	tmscpcommand(dev, TMS_SETDENSITY, 1);
  	return (0);
  }
  
***************
*** 619,632 ****
  	register dev_t dev;
  	register flag;
  {
  	register struct tms_info *tms;
  	int unit = TMSUNIT(dev);
  
  #ifdef TMSCP_DEBUG
! 	printd("tmscpclose: unit = %d\n", unit);
  	if(tmscpdebug)delay(10000L);
  #endif
! 	tms = &tms_info[unit];
  	if (flag == FWRITE || (flag&FWRITE) && tms->tms_lastiow)
  		{
  		/*	   device, command, count */
--- 721,736 ----
  	register dev_t dev;
  	register flag;
  {
+ 	struct tmscp_softc *sc;
  	register struct tms_info *tms;
  	int unit = TMSUNIT(dev);
  
  #ifdef TMSCP_DEBUG
! 	printd("tmscpclose: %d,%d\n", TMSCTLR(dev), unit);
  	if(tmscpdebug)delay(10000L);
  #endif
! 	sc = &tmscp_softc[TMSCTLR(dev)];
! 	tms = sc->sc_drives[unit];
  	if (flag == FWRITE || (flag&FWRITE) && tms->tms_lastiow)
  		{
  		/*	   device, command, count */
***************
*** 668,674 ****
  	register int s;
  	int unit = TMSUNIT(dev);
  
! 	bp = &tmscp_softc[unit].sc_cmdbuf;
  
  	s = spl5();
  	while (bp->b_flags&B_BUSY)
--- 772,778 ----
  	register int s;
  	int unit = TMSUNIT(dev);
  
! 	bp = &tmscp_softc[TMSCTLR(dev)].sc_cmdbuf;
  
  	s = spl5();
  	while (bp->b_flags&B_BUSY)
***************
*** 723,731 ****
  	/* 
  	 * Figure out virtual address of message 
  	 * skip comm area and mscp messages header and previous messages
  	 */
! 	vaddr = (u_int)tmscomphys.b_un.b_addr | ((long)tmscomphys.b_xmem << 16);
! 	vaddr += (u_int)sc->sc_com - (u_int)tmscp;	/* unit offset */
  	vaddr += sizeof(struct tmscpca)			/* skip comm area */
  		+sizeof(struct mscp_header);		/* m_cmdref disp */
  	vaddr += offset * sizeof(struct mscp);		/* skip previous */
--- 827,837 ----
  	/* 
  	 * Figure out virtual address of message 
  	 * skip comm area and mscp messages header and previous messages
+ 	 *
+ 	 * N.B. Assumes SEG5 has been remapped to the comm area for this
+ 	 * controller.
  	 */
! 	vaddr = _iomap(tmscp[sc->sc_unit]);
  	vaddr += sizeof(struct tmscpca)			/* skip comm area */
  		+sizeof(struct mscp_header);		/* m_cmdref disp */
  	vaddr += offset * sizeof(struct mscp);		/* skip previous */
***************
*** 746,757 ****
  tmscpgetcp(sc)
  	register struct tmscp_softc *sc;
  {
! 	register struct mscp *mp;
  	struct tmscpca *cp;
  	register int i;
  	int	s;
  
  	s = spl5();
  	cp = &sc->sc_com->tmscp_ca;
  	/*
  	 * If no credits, can't issue any commands
--- 852,866 ----
  tmscpgetcp(sc)
  	register struct tmscp_softc *sc;
  {
! 	register struct mscp *mp = NULL;
  	struct tmscpca *cp;
  	register int i;
  	int	s;
+ 	segm seg5;
  
  	s = spl5();
+ 	saveseg5(seg5);
+ 	mapseg5(tmscp[sc->sc_unit], MAPBUFDESC);
  	cp = &sc->sc_com->tmscp_ca;
  	/*
  	 * If no credits, can't issue any commands
***************
*** 773,786 ****
  		mp->mscp_buffer_h = mp->mscp_buffer_l = 0;
  		mp->mscp_zzz2 = 0;
  		sc->sc_lastcmd = (i + 1) % NCMD;
- 		(void) splx(s);
- 		return(mp);
  		}
  	(void) splx(s);
! 	return(NULL);
  }
  
- 
  /*
   * Initialize a TMSCP device.  Set up UBA mapping registers,
   * initialize data structures, and start hardware
--- 882,893 ----
  		mp->mscp_buffer_h = mp->mscp_buffer_l = 0;
  		mp->mscp_zzz2 = 0;
  		sc->sc_lastcmd = (i + 1) % NCMD;
  		}
+ 	restorseg5(seg5);
  	(void) splx(s);
! 	return(mp);
  }
  
  /*
   * Initialize a TMSCP device.  Set up UBA mapping registers,
   * initialize data structures, and start hardware
***************
*** 790,822 ****
  	register struct tmscp_softc *sc;
  {
  	register struct tmscpdevice *tmscpaddr;
! 	register int unit = sc - tmscp_softc;
! 	long comaddr, rap;
  
! 	sc->sc_ivec = TMSvec + unit * 4;
  	sc->sc_ctab.b_active++;
  	tmscpaddr = sc->sc_addr;
- 	if (tmscomphys.b_flags == 0)
- 		{
- 		/*
- 		 * Map or calculate the addresses (Qbus) of communications area
- 		 * and response packets
- 		 */
- 		rap = tmsphys((u_int)tmscp);
- 		tmscomphys.b_un.b_addr = (caddr_t)loint(rap);
- 		tmscomphys.b_xmem = hiint(rap);
- 		tmscomphys.b_bcount = sizeof (tmscp);
- 		tmscomphys.b_flags = B_PHYS;
- #ifdef	UNIBUS_MAP
- 		mapalloc(&tmscomphys);
- #endif
- 		comaddr = ((u_int)tmscomphys.b_un.b_addr | 
- 				((long)tmscomphys.b_xmem << 16)) +
- 				sizeof (struct tmscp) * unit +
- 				(u_int)RINGBASE;
- 		sc->sc_ctab.b_un.b_addr = (caddr_t)loint(comaddr);
- 		sc->sc_ctab.b_xmem = hiint(comaddr);
- 		}
  
  	/*
  	 * Start the hardware initialization sequence.
--- 897,910 ----
  	register struct tmscp_softc *sc;
  {
  	register struct tmscpdevice *tmscpaddr;
! 	long adr;
  
! 	sc->sc_ivec = TMSvec + sc->sc_unit * 4;
  	sc->sc_ctab.b_active++;
+ 	adr = _iomap(tmscp[sc->sc_unit]) + (u_int)RINGBASE;
+ 	sc->sc_ctab.b_un.b_addr = (caddr_t)loint(adr);
+ 	sc->sc_ctab.b_xmem = hiint(adr);
  	tmscpaddr = sc->sc_addr;
  
  	/*
  	 * Start the hardware initialization sequence.
***************
*** 841,847 ****
  	return(1);
  }
  
- 
  /*
   * Start I/O operation
   * This code is convoluted.  The majority of it was copied from the uda driver.
--- 929,934 ----
***************
*** 850,864 ****
  tmsstart(sc)
  	register struct tmscp_softc *sc;
  {
- 	register struct buf *bp, *dp;
  	register struct mscp *mp;
  	register struct tms_info *tms;
  	struct   tmscpdevice *tmscpaddr;
! 	struct   tmscp *tm;
! 	int i, unit = sc - tmscp_softc;
! 	char ioctl;		/* flag: set true if its an IOCTL command */
  
! 	tm = &tmscp[unit];
       for(;;)
  	{
  	if ((dp = sc->sc_ctab.b_actf) == NULL)
--- 937,950 ----
  tmsstart(sc)
  	register struct tmscp_softc *sc;
  {
  	register struct mscp *mp;
+ 	register struct buf *bp, *dp;
  	register struct tms_info *tms;
  	struct   tmscpdevice *tmscpaddr;
! 	int i, unit;
! 	segm seg5;
  
!      saveseg5(seg5);		/* save just once at top */
       for(;;)
  	{
  	if ((dp = sc->sc_ctab.b_actf) == NULL)
***************
*** 882,896 ****
  		continue;		/* Need to check for loop */
  		}
  	sc->sc_ctab.b_active++;
  	tmscpaddr = (struct tmscpdevice *)sc->sc_addr;
! 	tms = &tms_info[TMSUNIT(bp->b_dev)];
  	if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN)
  		{
  		tprintf(tms->tms_ttyp,
! 		    "tms%d: hard error bn%ld\n",
! 		    minor(bp->b_dev)&03, bp->b_blkno);
! 		log(TMS_PRI, "tms%d: sa 0%o, state %d\n", unit,
! 				tmscpaddr->tmscpsa&0xffff, sc->sc_state);
  		(void)tkini(sc);
  		/* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */
  		break;
--- 968,983 ----
  		continue;		/* Need to check for loop */
  		}
  	sc->sc_ctab.b_active++;
+ 	unit = TMSUNIT(bp->b_dev);
  	tmscpaddr = (struct tmscpdevice *)sc->sc_addr;
! 	tms = sc->sc_drives[unit];
  	if ((tmscpaddr->tmscpsa&TMSCP_ERR) || sc->sc_state != S_RUN)
  		{
  		tprintf(tms->tms_ttyp,
! 		    "tms%d,%d: hard error bn%ld\n", sc->sc_unit, unit,
! 		    bp->b_blkno);
! 		log(TMS_PRI, "tms%d,%d: sa 0%o state %d\n", sc->sc_unit,
! 			unit, tmscpaddr->tmscpsa, sc->sc_state);
  		(void)tkini(sc);
  		/* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE TMSCPRESET */
  		break;
***************
*** 900,938 ****
  	 * if a write command is done it will be detected in tmscprsp.
  	 */
  	tms->tms_lastiow = 0;
! 	if (tms->tms_online == 0)
  		{        /* not online */
  		if ((mp = tmscpgetcp(sc)) == NULL)
  			break;
  		mp->mscp_opcode = M_OP_ONLIN;
! 		mp->mscp_unit = 0;	/* ui->ui_slave; */
  		dp->b_active = 2;
  		sc->sc_ctab.b_actf = dp->b_forw; /* remove from controller q */
  		((Trl *)mp->mscp_dscptr)->hsh |= TMSCP_OWN|TMSCP_INT;
  		if (tmscpaddr->tmscpsa&TMSCP_ERR)
! 			printf("tms%d fatal error (0%o)\n", unit,
! 					tmscpaddr->tmscpsa);
  		i = tmscpaddr->tmscpip;
  		continue;
  		}
- 	/*
- 	 * If command is an ioctl command then set the ioctl flag for later use.
- 	 * If not (i.e. it is a read or write) then attempt
- 	 * to set up a buffer pointer.
- 	 */
- 	ioctl = 0;
- 	if (bp == &sc->sc_cmdbuf)
- 		ioctl = 1;
  	if ((mp = tmscpgetcp(sc)) == NULL)
  		break;
  	mp->mscp_cmdref = (u_short)bp;		/* pointer to get back */
! 	mp->mscp_unit = 0;	/* ui->ui_slave; */
  	/*
  	 * If its an ioctl-type command then set up the appropriate
  	 * tmscp command;  by doing a switch on the "b_resid" field where
  	 * the command mneumonic is stored.
  	 */
! 	if (ioctl)
  		{
  #ifdef TMSCP_DEBUG
  		printd("tmsstart: doing ioctl cmd %d\n", bp->b_resid);
--- 987,1020 ----
  	 * if a write command is done it will be detected in tmscprsp.
  	 */
  	tms->tms_lastiow = 0;
! 	if (tms->tms_online == -1)
  		{        /* not online */
  		if ((mp = tmscpgetcp(sc)) == NULL)
  			break;
+ 		mapseg5(tmscp[sc->sc_unit], MAPBUFDESC);
  		mp->mscp_opcode = M_OP_ONLIN;
! 		mp->mscp_unit = unit;
  		dp->b_active = 2;
  		sc->sc_ctab.b_actf = dp->b_forw; /* remove from controller q */
  		((Trl *)mp->mscp_dscptr)->hsh |= TMSCP_OWN|TMSCP_INT;
  		if (tmscpaddr->tmscpsa&TMSCP_ERR)
! 			printf("tms%d,%d fatal error 0%o\n", sc->sc_unit,
! 					TMSUNIT(bp->b_dev), tmscpaddr->tmscpsa);
! 		restorseg5(seg5);
  		i = tmscpaddr->tmscpip;
  		continue;
  		}
  	if ((mp = tmscpgetcp(sc)) == NULL)
  		break;
+ 	mapseg5(tmscp[sc->sc_unit], MAPBUFDESC);
  	mp->mscp_cmdref = (u_short)bp;		/* pointer to get back */
! 	mp->mscp_unit = unit;
  	/*
  	 * If its an ioctl-type command then set up the appropriate
  	 * tmscp command;  by doing a switch on the "b_resid" field where
  	 * the command mneumonic is stored.
  	 */
! 	if (bp == &sc->sc_cmdbuf)
  		{
  #ifdef TMSCP_DEBUG
  		printd("tmsstart: doing ioctl cmd %d\n", bp->b_resid);
***************
*** 1012,1042 ****
  			tms->tms_serex = 0;
  			tms->tms_clserex = 1;
  			break;
! 		case TMS_LOWDENSITY:
  			/*
! 			 * Set the unit to low density
  			 */
  			mp->mscp_opcode = M_OP_STUNT;
  			mp->mscp_unitflgs = tms->tms_unitflgs;
  			mp->mscp_mediaid = 0;	/* default device dependant parameters */
! 			if ((tms->tms_fmtmenu & M_TF_800) != 0)
! 				mp->mscp_format = M_TF_800;
! 			else
! 				mp->mscp_format = M_TF_PE & tms->tms_fmtmenu;
  			tms->tms_format = mp->mscp_format;
  			break;
- 		case TMS_HIDENSITY:
- 			/*
- 			 * Set the unit to high density (format == 0)
- 			 */
- 			mp->mscp_opcode = M_OP_STUNT;
- 			mp->mscp_unitflgs = tms->tms_unitflgs;
- 			mp->mscp_mediaid = 0;	/* default device dependant parameters */
- 			mp->mscp_format = 0;
- 			tms->tms_format = 0;
- 			break;
  		default:
! 			printf("Bad ioctl on tms%d\n", unit);
  			/* Need a no-op. Reposition no amount */
  			mp->mscp_opcode = M_OP_REPOS;
  			break;
--- 1094,1115 ----
  			tms->tms_serex = 0;
  			tms->tms_clserex = 1;
  			break;
! 		case TMS_SETDENSITY:
  			/*
! 			 * Set the unit density
  			 */
  			mp->mscp_opcode = M_OP_STUNT;
  			mp->mscp_unitflgs = tms->tms_unitflgs;
  			mp->mscp_mediaid = 0;	/* default device dependant parameters */
! 			mp->mscp_format = Dmatrix[TMSDENS(bp->b_dev)][tms->tms_fmtmenu & FMTMASK];
! #ifdef	TMSCP_DEBUG
! 			printd("b_dev: 0%o fmtmenu: 0%o format: 0%o\n", bp->b_dev, tms->tms_fmtmenu, mp->mscp_format);
! 			delay(4000000L);
! #endif
  			tms->tms_format = mp->mscp_format;
  			break;
  		default:
! 			printf("tms%d,%d bad ioctl\n",sc->sc_unit,mp->mscp_unit);
  			/* Need a no-op. Reposition no amount */
  			mp->mscp_opcode = M_OP_REPOS;
  			break;
***************
*** 1082,1088 ****
  	dp->av_back = bp;
  	if (tmscpaddr->tmscpsa&TMSCP_ERR)
  		{
! 		printf("tms%d: fatal error (0%o)\n",unit, tmscpaddr->tmscpsa);
  		(void)tkini(sc);
  		break;
  		}
--- 1155,1162 ----
  	dp->av_back = bp;
  	if (tmscpaddr->tmscpsa&TMSCP_ERR)
  		{
! 		printf("tms%d,%d: fatal error 0%o\n",sc->sc_unit, 
! 			mp->mscp_unit, tmscpaddr->tmscpsa);
  		(void)tkini(sc);
  		break;
  		}
***************
*** 1089,1114 ****
      }   /* end for */
      /*
       * Check for response ring transitions lost in the
!      * Race condition
       */
      for (i = sc->sc_lastrsp;; i++)
  	    {
  	    i %= NRSP;
! 	    if (tm->tmscp_ca.ca_rspdsc[i].hsh&TMSCP_OWN)
  		    break;
! 	    tmscprsp(unit, tm, sc, i);
! 	    tm->tmscp_ca.ca_rspdsc[i].hsh |= TMSCP_OWN;
  	    }
      sc->sc_lastrsp = i;
  }
  
  
  /*
!  * Process a response packet
   */
! tmscprsp(unit, tm, sc, i)
! 	int unit;
! 	register struct tmscp *tm;
  	register struct tmscp_softc *sc;
  	int i;
  {
--- 1163,1188 ----
      }   /* end for */
      /*
       * Check for response ring transitions lost in the
!      * Race condition.  Map SEG5 in case we escaped early from the for().
       */
+     mapseg5(tmscp[sc->sc_unit], MAPBUFDESC);
      for (i = sc->sc_lastrsp;; i++)
  	    {
  	    i %= NRSP;
! 	    if (sc->sc_com->tmscp_ca.ca_rspdsc[i].hsh&TMSCP_OWN)
  		    break;
! 	    tmscprsp(sc, i);
! 	    sc->sc_com->tmscp_ca.ca_rspdsc[i].hsh |= TMSCP_OWN;
  	    }
      sc->sc_lastrsp = i;
+     restorseg5(seg5);
  }
  
  
  /*
!  * Process a response packet.  N.B.  Assumes SEG5 maps comm area for controller
   */
! tmscprsp(sc, i)
  	register struct tmscp_softc *sc;
  	int i;
  {
***************
*** 1117,1123 ****
  	struct buf *dp, *bp;
  	int st;
  
! 	mp = &tm->tmscp_rsp[i];
  	mp->mscp_header.tmscp_msglen = mscp_msglen;
  	sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf;  /* low 4 bits */
  	if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10)	/* Check */
--- 1191,1197 ----
  	struct buf *dp, *bp;
  	int st;
  
! 	mp = &sc->sc_com->tmscp_rsp[i];
  	mp->mscp_header.tmscp_msglen = mscp_msglen;
  	sc->sc_credits += mp->mscp_header.tmscp_credits & 0xf;  /* low 4 bits */
  	if ((mp->mscp_header.tmscp_credits & 0xf0) > 0x10)	/* Check */
***************
*** 1124,1129 ****
--- 1198,1204 ----
  		return;
  #ifdef TMSCP_DEBUG
  	printd("tmscprsp, opcode 0%o status 0%o\n",mp->mscp_opcode,mp->mscp_status&M_ST_MASK);
+ 	printd("  SEG5: 0%o sc: 0%o mp: 0%o i: %d\n",*KDSA5, sc, mp, i);
  #endif	
  	/*
  	 * If it's an error log message (datagram),
***************
*** 1131,1137 ****
  	 */
  	if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10)
  		{	/* check */
! 		tmserror(unit, (struct mslg *)mp);
  		return;
  		}
  	st = mp->mscp_status&M_ST_MASK;
--- 1206,1212 ----
  	 */
  	if ((mp->mscp_header.tmscp_credits & 0xf0) == 0x10)
  		{	/* check */
! 		tmserror(sc->sc_unit, (struct mslg *)mp);
  		return;
  		}
  	st = mp->mscp_status&M_ST_MASK;
***************
*** 1156,1164 ****
  		wakeup((caddr_t)&sc->sc_ctab);
  		return;
  		}
! 	if (mp->mscp_unit >= NTMS)
  		return;
! 	tms = &tms_info[unit];
  	/*
  	 * Save endcode, endflags, and status for mtioctl get unit status.
  	 * NOTE: Don't do this on Clear serious exception (reposition no-op);
--- 1231,1241 ----
  		wakeup((caddr_t)&sc->sc_ctab);
  		return;
  		}
! 	if (mp->mscp_unit >= 4)
  		return;
! 	tms = sc->sc_drives[mp->mscp_unit];
! 	if (!tms)		/* unopened unit coming online - ignore it */
! 		return;
  	/*
  	 * Save endcode, endflags, and status for mtioctl get unit status.
  	 * NOTE: Don't do this on Clear serious exception (reposition no-op);
***************
*** 1190,1207 ****
  			sc->sc_ctab.b_actl = dp;
  			tms->tms_online = 1;       /* mark it online */
  			tms->tms_dsize=(daddr_t)mp->mscp_maxwrt;
- #ifdef TMSCP_DEBUG
- 			printd("tmscprsp: unit %d online\n", mp->mscp_unit);
- #endif			
  			/* 
  			 * This define decodes the Media type identifier
  			 */
- #	        	define F_to_C(x,i)     ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ')
  #ifdef TMSCP_DEBUG
! 			printd("tmscprsp: unit %d online %x %c%c %c%c%c%d\n"
! 				,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4)
! 				,F_to_C(mp,3), F_to_C(mp,2)
! 				,F_to_C(mp,1), F_to_C(mp,0), mp->mscp_mediaid & 0x7f);
  #endif				
  			dp->b_active = 1;
  			}	/* end if st == M_ST_SUCC */
--- 1267,1279 ----
  			sc->sc_ctab.b_actl = dp;
  			tms->tms_online = 1;       /* mark it online */
  			tms->tms_dsize=(daddr_t)mp->mscp_maxwrt;
  			/* 
  			 * This define decodes the Media type identifier
  			 */
  #ifdef TMSCP_DEBUG
! 			printd("tmscprsp: %d,%d online mediaid 0x%lx format 0x%x\n",
! 				sc->sc_unit, mp->mscp_unit, mp->mscp_mediaid,
! 				mp->mscp_format);
  #endif				
  			dp->b_active = 1;
  			}	/* end if st == M_ST_SUCC */
***************
*** 1209,1219 ****
  			{
  			if (bp = dp->b_actf)
  				tprintf(tms->tms_ttyp,
! 				    "tms%d: hard error bn%ld: OFFLINE\n",
! 				    minor(bp->b_dev)&03, bp->b_blkno);
  			else
  				tprintf(tms->tms_ttyp,
! 				    "tms%d: hard error: OFFLINE\n", unit);
  			while (bp = dp->b_actf)
  				{
  				dp->b_actf = bp->av_forw;
--- 1281,1292 ----
  			{
  			if (bp = dp->b_actf)
  				tprintf(tms->tms_ttyp,
! 				    "tms%d,%d: hard error bn%ld: OFFLINE\n",
! 				    sc->sc_unit, mp->mscp_unit, bp->b_blkno);
  			else
  				tprintf(tms->tms_ttyp,
! 				    "tms%d,%d: hard error: OFFLINE\n", 
! 				    sc->sc_unit, mp->mscp_unit);
  			while (bp = dp->b_actf)
  				{
  				dp->b_actf = bp->av_forw;
***************
*** 1228,1238 ****
  	/*
  	 * The AVAILABLE ATTENTION message occurs when the
  	 * unit becomes available after loading,
! 	 * marking the unit offline (ui_flags = 0) will force an
  	 * online command prior to using the unit.
  	 */
  	case M_OP_AVATN:
! 		tms->tms_online = 0;
  		tms->tms_type = mp->mscp_mediaid;
  		break;
  	case M_OP_END:
--- 1301,1311 ----
  	/*
  	 * The AVAILABLE ATTENTION message occurs when the
  	 * unit becomes available after loading,
! 	 * marking the unit offline (tms_online = -1) will force an
  	 * online command prior to using the unit.
  	 */
  	case M_OP_AVATN:
! 		tms->tms_online = -1;
  		tms->tms_type = mp->mscp_mediaid;
  		break;
  	case M_OP_END:
***************
*** 1246,1253 ****
  		 * of 0200 instead of the 0241 (read) that was expected.
  		 */
  			
! 		printf("tms%d: invalid cmd, endcode = %o, status=%o\n",
! 			unit, mp->mscp_opcode, st);
  		bp = (struct buf *)mp->mscp_cmdref;
  		/*
  		 * Unlink buffer from I/O wait queue.
--- 1319,1327 ----
  		 * of 0200 instead of the 0241 (read) that was expected.
  		 */
  			
! 		printf("tms%d,%d: invalid cmd endcode = %o status=%o\n",
! 			sc->sc_unit, mp->mscp_unit, mp->mscp_opcode, st);
! common:	/* GTUNT finishes up thru here too */
  		bp = (struct buf *)mp->mscp_cmdref;
  		/*
  		 * Unlink buffer from I/O wait queue.
***************
*** 1272,1279 ****
  	 * issued.  For the ioctl, "rewoffl", a tmscp AVAILABLE command is
  	 * done with the UNLOAD modifier.  This performs a rewind, followed
  	 * by marking the unit offline.  So mark the unit offline
! 	 * software wise as well (ui_flags = 0 and 
! 	 * tms->tms_openf = 0).
  	 */
  	case M_OP_AVAIL|M_OP_END:
  #ifdef TMSCP_DEBUG
--- 1346,1352 ----
  	 * issued.  For the ioctl, "rewoffl", a tmscp AVAILABLE command is
  	 * done with the UNLOAD modifier.  This performs a rewind, followed
  	 * by marking the unit offline.  So mark the unit offline
! 	 * software wise as well (tms->tms_online = -1 and tms_open = 0).
  	 */
  	case M_OP_AVAIL|M_OP_END:
  #ifdef TMSCP_DEBUG
***************
*** 1289,1295 ****
  		dp->b_qsize--;
  		if (st == M_ST_OFFLN || st == M_ST_AVLBL)
  			{
! 			tms->tms_online = 0;       /* mark unit offline */
  			tms->tms_openf = 0;
  			tms->tms_type = mp->mscp_mediaid;
  			/*
--- 1362,1368 ----
  		dp->b_qsize--;
  		if (st == M_ST_OFFLN || st == M_ST_AVLBL)
  			{
! 			tms->tms_online = -1;       /* mark unit offline */
  			tms->tms_openf = 0;
  			tms->tms_type = mp->mscp_mediaid;
  			/*
***************
*** 1320,1329 ****
  			if (st != M_ST_TAPEM)
  				{
  				tprintf(tms->tms_ttyp,
! 				    "tms%d: hard error bn%ld\n",minor(bp->b_dev)&03, bp->b_blkno);
! 				tprintf(tms->tms_ttyp, "status:0%o flags:0%o\n",
! 				     (mp->mscp_status & 177740)>>5, mp->mscp_flags);
! 				errinfo(st);		/* produces more info */
  				bp->b_flags |= B_ERROR;
  				}
  			else
--- 1393,1401 ----
  			if (st != M_ST_TAPEM)
  				{
  				tprintf(tms->tms_ttyp,
! 				"tms%d,%d: hard error bn%ld status:0%o flags:0%o\n",
! 				    sc->sc_unit, mp->mscp_unit, bp->b_blkno,
! 				    mp->mscp_status >> 5, mp->mscp_flags);
  				bp->b_flags |= B_ERROR;
  				}
  			else
***************
*** 1349,1450 ****
  	case M_OP_GTUNT|M_OP_END:
  #ifdef TMSCP_DEBUG
  		printd("tmscprsp: GTUNT end packet status = 0%o\n",st);
! 		printd("tmscprsp: unit %d mediaid %x %c%c %c%c%c%d %x %x t=%d\n"
! 		    ,mp->mscp_unit, mp->mscp_mediaid
! 		    ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2)
! 		    ,F_to_C(mp,1),F_to_C(mp,0)
! 		    ,mp->mscp_mediaid & 0x7f
  		    ,mp->mscp_unitid.val[0]
  		    ,mp->mscp_unitid.val[1]
! 		    ,mp->mscp_format);
! #endif		
  		tms->tms_type = mp->mscp_mediaid;
  		tms->tms_fmtmenu = mp->mscp_fmtmenu;
  		tms->tms_unitflgs = mp->mscp_unitflgs;
! 		break;
  
  	default:
! 		printf("tms unknown packet\n");
! 		tmserror(unit, (struct mslg *)mp);
  	}	/* end switch mp->mscp_opcode */
  }
  
- 
- /* 
-  * Give a meaningful error when the mscp_status field returns an error code.
-  */
- 
- errinfo(st)
- 	int st;			/* the status code */
- {
- 	switch(st) {
- 	case M_ST_ICMD:
- 		printf("invalid command\n");
- 		break;
- 	case M_ST_ABRTD:
- 		printf("command aborted\n");
- 		break;
- 	case M_ST_OFFLN:
- 		printf("unit offline\n");
- 		break;
- 	case M_ST_WRTPR:
- 		printf("unit write protected\n");
- 		break;
- 	case M_ST_COMP:
- 		printf("compare error\n");
- 		break;
- 	case M_ST_DATA:
- 		printf("data error\n");
- 		break;
- 	case M_ST_HSTBF:
- 		printf("host buffer access error\n");
- 		break;
- 	case M_ST_CNTLR:
- 		printf("controller error\n");
- 		break;
- 	case M_ST_DRIVE:
- 		printf("drive error\n");
- 		break;
- 	case M_ST_FMTER:
- 		printf("formatter error\n");
- 		break;
- 	case M_ST_BOT:
- 		printf("BOT encountered\n");
- 		break;
- 	case M_ST_TAPEM:
- 		printf("tape mark encountered\n");
- 		break;
- 	case M_ST_RDTRN:
- 		printf("record data truncated\n");
- 		break;
- 	case M_ST_PLOST:
- 		printf("position lost\n");
- 		break;
- 	case M_ST_SEX:
- 		printf("serious exception\n");
- 		break;
- 	case M_ST_LED:
- 		printf("LEOT detected\n");
- 		break;
- 	}
- }
- 
  /*
-  * Return the physical address corresponding to a virtual data space address.
-  * On a separate I&D CPU this is a noop, but it's only called when the first
-  * controller is initialized and on a dump.
-  */
- long
- tmsphys(vaddr)
- 	register	unsigned	vaddr;
- {
- 	register	unsigned	click;
- 
- 	click = (sep_id ? KDSA0 : KISA0)[(vaddr >> 13) & 07];
- 	return(((long)click << 6) + (vaddr & 017777));
- }
- 
- /*
   * Manage buffers and perform block mode read and write operations.
   */
  
--- 1421,1444 ----
  	case M_OP_GTUNT|M_OP_END:
  #ifdef TMSCP_DEBUG
  		printd("tmscprsp: GTUNT end packet status = 0%o\n",st);
! 		printd("tmscprsp: %d,%d mediaid 0x%lx 0x%lx 0x%lx format=%d speed = %d\n",
! 		    sc->sc_unit,mp->mscp_unit, mp->mscp_mediaid
  		    ,mp->mscp_unitid.val[0]
  		    ,mp->mscp_unitid.val[1]
! 		    ,mp->mscp_format, mp->mscp_speed);
! #endif
  		tms->tms_type = mp->mscp_mediaid;
  		tms->tms_fmtmenu = mp->mscp_fmtmenu;
  		tms->tms_unitflgs = mp->mscp_unitflgs;
! 		goto common;	/* need to dequeue buffer and do iodone() */
  
  	default:
! 		printf("tms%d,%d unknown packet\n", sc->sc_unit,mp->mscp_unit);
! 		tmserror(sc->sc_unit, (struct mslg *)mp);
  	}	/* end switch mp->mscp_opcode */
  }
  
  /*
   * Manage buffers and perform block mode read and write operations.
   */
  
***************
*** 1454,1479 ****
  	register struct buf *dp;
  	register struct tmscp_softc *sc;
  	struct	tms_info *tms;
! 	int unit = TMSUNIT(bp->b_dev);
  	int s;
  
! 	if (unit >= NTMS)
  		{
- #ifdef TMSCP_DEBUG
- 		printd ("tmscpstrategy: bad unit # %d\n",unit);
- #endif
  		bp->b_flags |= B_ERROR;
  		iodone(bp);
  		return;
  		}
- 	sc = &tmscp_softc[unit];
- 	tms = &tms_info[unit];
- 	if (tms->tms_online == 0)
- 		{
- 		bp->b_flags |= B_ERROR;
- 		iodone(bp);
- 		return;
- 		}
  #ifdef	UNIBUS_MAP
  	mapalloc(bp);
  #endif
--- 1448,1464 ----
  	register struct buf *dp;
  	register struct tmscp_softc *sc;
  	struct	tms_info *tms;
! 	int ctlr = TMSCTLR(bp->b_dev);
  	int s;
  
! 	sc = &tmscp_softc[ctlr];
! 	tms = sc->sc_drives[TMSUNIT(bp->b_dev)];
! 	if (!tms || tms->tms_online != 1)
  		{
  		bp->b_flags |= B_ERROR;
  		iodone(bp);
  		return;
  		}
  #ifdef	UNIBUS_MAP
  	mapalloc(bp);
  #endif
***************
*** 1526,1555 ****
  	register struct	mscp	*mp;
  	daddr_t bn, dumpsize;
  	long paddr, maddr;
! 	int unit, count;
  	struct	ubmap *ubp;
  
! 	unit = TMSUNIT(dev);
! 	if (unit >= NTMS)
  		return (ENXIO);
! 	sc = &tmscp_softc[unit];
  	tmscpaddr = sc->sc_addr;
  	if (tmscpaddr == NULL)
  		return(ENXIO);
  
  #ifdef	UNIBUS_MAP
  	if (ubmap) {
  		ubp = UBMAP;
! 		ubp->ub_lo = loint(tmscomphys.b_un.b_addr);
! 		ubp->ub_hi = hiint(tmscomphys.b_xmem);
! 		tmscomphys.b_un.b_addr = NULL;
! 		tmscomphys.b_xmem = 0;
  	}
  #endif
! 	paddr = (u_int)tmscomphys.b_un.b_addr +
! 			((long)tmscomphys.b_xmem << 16) +
! 			(u_int)RINGBASE;
! 	sc->sc_com = tmscp;
  	mp = sc->sc_com->tmscp_rsp;
  	sc->sc_com->tmscp_ca.ca_cmdint = sc->sc_com->tmscp_ca.ca_rspint = 0;
  	bzero(mp, 2 * sizeof (*mp));
--- 1511,1538 ----
  	register struct	mscp	*mp;
  	daddr_t bn, dumpsize;
  	long paddr, maddr;
! 	int unit = TMSUNIT(dev), count, ctlr = TMSCTLR(dev);
  	struct	ubmap *ubp;
+ 	segm seg5;
  
! 	if (ctlr >= NTMSCP)
  		return (ENXIO);
! 	sc = &tmscp_softc[ctlr];
  	tmscpaddr = sc->sc_addr;
  	if (tmscpaddr == NULL)
  		return(ENXIO);
  
+ 	paddr = _iomap(tmscp[sc->sc_unit]);
  #ifdef	UNIBUS_MAP
  	if (ubmap) {
  		ubp = UBMAP;
! 		ubp->ub_lo = loint(paddr);
! 		ubp->ub_hi = hiint(paddr);
  	}
  #endif
! 	paddr += RINGBASE;
! 	saveseg5(seg5);
! 	mapseg5(tmscp[sc->sc_unit], MAPBUFDESC);
  	mp = sc->sc_com->tmscp_rsp;
  	sc->sc_com->tmscp_ca.ca_cmdint = sc->sc_com->tmscp_ca.ca_rspint = 0;
  	bzero(mp, 2 * sizeof (*mp));
***************
*** 1573,1579 ****
  	if (tmscpcmd(M_OP_STCON, unit, sc) == 0) {
  		return(EFAULT);
  	}
! 	sc->sc_com->tmscp_cmd[0].mscp_unit = 0;		/* ui->ui_slave */
  	if (tmscpcmd(M_OP_ONLIN, unit, sc) == 0) {
  		return(EFAULT);
  	}
--- 1556,1562 ----
  	if (tmscpcmd(M_OP_STCON, unit, sc) == 0) {
  		return(EFAULT);
  	}
! 	sc->sc_com->tmscp_cmd[0].mscp_unit = unit;
  	if (tmscpcmd(M_OP_ONLIN, unit, sc) == 0) {
  		return(EFAULT);
  	}
***************
*** 1604,1609 ****
--- 1587,1593 ----
  		return(EIO);
  	paddr += (DBSIZE << PGSHIFT);
  	}
+ 	restorseg5(seg5);
  	return (0);
  }
  
***************
*** 1625,1637 ****
  	rlp = &sc->sc_com->tmscp_ca.ca_rspdsc[0];
  
  	cmp->mscp_opcode = op;
! 	cmp->mscp_unit = 0;		/* unit? */
  	cmp->mscp_header.tmscp_msglen = mscp_msglen;
  	rmp->mscp_header.tmscp_msglen = mscp_msglen;
  	rlp[0].hsh |= TMSCP_OWN|TMSCP_INT;
  	rlp[1].hsh |= TMSCP_OWN|TMSCP_INT;
  	if (sc->sc_addr->tmscpsa&TMSCP_ERR)
! 		printf("tms fatal error (0%o)\n", sc->sc_addr->tmscpsa);
  	i = sc->sc_addr->tmscpip;
  
  	while ((rlp[1].hsh & TMSCP_INT) == 0)
--- 1609,1622 ----
  	rlp = &sc->sc_com->tmscp_ca.ca_rspdsc[0];
  
  	cmp->mscp_opcode = op;
! 	cmp->mscp_unit = unit;
  	cmp->mscp_header.tmscp_msglen = mscp_msglen;
  	rmp->mscp_header.tmscp_msglen = mscp_msglen;
  	rlp[0].hsh |= TMSCP_OWN|TMSCP_INT;
  	rlp[1].hsh |= TMSCP_OWN|TMSCP_INT;
  	if (sc->sc_addr->tmscpsa&TMSCP_ERR)
! 		printf("tms%d,%d fatal error 0%o\n", sc->sc_unit, unit,
! 			sc->sc_addr->tmscpsa);
  	i = sc->sc_addr->tmscpip;
  
  	while ((rlp[1].hsh & TMSCP_INT) == 0)
***************
*** 1644,1650 ****
  	if (rmp->mscp_opcode != (op|M_OP_END) ||
  	    (rmp->mscp_status&M_ST_MASK) != M_ST_SUCC)
  		{
! 		printf("error: com %d opc 0x%x stat 0x%x\ndump ", op,
  			rmp->mscp_opcode, rmp->mscp_status);
  		return(0);
  		}
--- 1629,1635 ----
  	if (rmp->mscp_opcode != (op|M_OP_END) ||
  	    (rmp->mscp_status&M_ST_MASK) != M_ST_SUCC)
  		{
! 		printf("err: com %d opc 0x%x stat 0x%x\ndump ", op,
  			rmp->mscp_opcode, rmp->mscp_status);
  		return(0);
  		}
***************
*** 1653,1690 ****
  #endif TMSCP_DUMP
  
  /*
-  * Perform raw read
-  */
- 
- tmscpread(dev, uio)
- 	dev_t dev;
- 	struct uio *uio;
- {
- 	register int unit = TMSUNIT(dev);
- 
- 	if (unit >= NTMS)
- 		return (ENXIO);
- 	return (physio(tmscpstrategy, &tms_info[unit].tms_rtab, dev, B_READ, BYTE, uio));
- }
- 
- 
- /*
-  * Perform raw write
-  */
- 
- tmscpwrite(dev, uio)
- 	dev_t dev;
- 	struct uio *uio;
- {
- 	register int unit = TMSUNIT(dev);
- 
- 	if (unit >= NTMS)
- 		return (ENXIO);
- 	return (physio(tmscpstrategy, &tms_info[unit].tms_rtab, dev, B_WRITE, BYTE, uio));
- }
- 
- 
- /*
   * Catch ioctl commands, and call the "command" routine to do them.
   */
  
--- 1638,1643 ----
***************
*** 1695,1701 ****
  	caddr_t data;
  	int flag;
  {
! 	register struct buf *bp = &tmscp_softc[TMSUNIT(dev)].sc_cmdbuf;
  	register callcount;	/* number of times to call cmd routine */
  	register struct tms_info *tms;
  	int fcount;		/* number of files (or records) to space */
--- 1648,1655 ----
  	caddr_t data;
  	int flag;
  {
! 	struct tmscp_softc *sc = &tmscp_softc[TMSCTLR(dev)];
! 	register struct buf *bp = &sc->sc_cmdbuf;
  	register callcount;	/* number of times to call cmd routine */
  	register struct tms_info *tms;
  	int fcount;		/* number of files (or records) to space */
***************
*** 1747,1753 ****
  		/*
  		 * Return status info associated with the particular UNIT.
  		 */
! 		tms = &tms_info[TMSUNIT(dev)];
  		mtget = (struct mtget *)data;
  		mtget->mt_type = MT_ISTMSCP;
  		mtget->mt_dsreg = tms->tms_flags << 8;
--- 1701,1709 ----
  		/*
  		 * Return status info associated with the particular UNIT.
  		 */
! 		tms = sc->sc_drives[TMSUNIT(dev)];
! 		if (!tms)
! 			return(ENXIO);
  		mtget = (struct mtget *)data;
  		mtget->mt_type = MT_ISTMSCP;
  		mtget->mt_dsreg = tms->tms_flags << 8;
***************
*** 1770,1777 ****
   * send message to an error logger.
   */
  
! tmserror(unit, mp)
! 	register int unit;
  	register struct mslg *mp;
  {
  	register i;
--- 1726,1733 ----
   * send message to an error logger.
   */
  
! tmserror(ctlr, mp)
! 	register int ctlr;
  	register struct mslg *mp;
  {
  	register i;
***************
*** 1780,1803 ****
  	printd("tmserror:\n");
  #endif
  	if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT)))
! 		log(TMS_PRI, "tms%d: %s error, ", unit,
  		mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard");
  
  	switch (mp->mslg_format) {
  
  	case M_FM_CNTERR:
! 		log(TMS_PRI, "controller error, event 0%o\n", mp->mslg_event);
  		break;
  	case M_FM_BUSADDR:
! 		log(TMS_PRI, "host memory access error, event 0%o, addr 0%o\n",
  			mp->mslg_event, mp->mslg_busaddr);
  		break;
  	case M_FM_TAPETRN:
! 		log(TMS_PRI, "tape transfer error, unit %d, grp 0x%x, event 0%o\n",
  			mp->mslg_unit, mp->mslg_group, mp->mslg_event);
  		break;
  	case M_FM_STIERR:
! 		log(TMS_PRI, "STI error, unit %d, event 0%o\n",
  			mp->mslg_unit, mp->mslg_event);
  #ifdef notdef
  		/* too painful to do with log() */
--- 1736,1759 ----
  	printd("tmserror:\n");
  #endif
  	if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT)))
! 		log(TMS_PRI, "tms%d,%d: %s err ", ctlr, mp->mslg_unit,
  		mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard");
  
  	switch (mp->mslg_format) {
  
  	case M_FM_CNTERR:
! 		log(TMS_PRI, "ctlr err event 0%o\n", mp->mslg_event);
  		break;
  	case M_FM_BUSADDR:
! 		log(TMS_PRI, "host memory access err, event 0%o, addr 0%o\n",
  			mp->mslg_event, mp->mslg_busaddr);
  		break;
  	case M_FM_TAPETRN:
! 		log(TMS_PRI, "tape transfer err unit %d grp 0x%x event 0%o\n",
  			mp->mslg_unit, mp->mslg_group, mp->mslg_event);
  		break;
  	case M_FM_STIERR:
! 		log(TMS_PRI, "STI err unit %d event 0%o\n",
  			mp->mslg_unit, mp->mslg_event);
  #ifdef notdef
  		/* too painful to do with log() */
***************
*** 1807,1822 ****
  #endif
  		break;
  	case M_FM_STIDEL:
! 		log(TMS_PRI, "STI Drive Error Log, unit %d, event 0%o\n",
  			mp->mslg_unit, mp->mslg_event);
  		break;
  	case M_FM_STIFEL:
! 		log(TMS_PRI, "STI Formatter Error Log, unit %d, event 0%o\n",
  			mp->mslg_unit, mp->mslg_event);
  		break;
  	default:
! 		log(TMS_PRI, "unknown error, unit %d, format 0%o, event 0%o\n",
! 			mp->mslg_unit, mp->mslg_format, mp->mslg_event);
  	}
  
  	if (tmscperror)
--- 1763,1778 ----
  #endif
  		break;
  	case M_FM_STIDEL:
! 		log(TMS_PRI, "STI Drive ErrorLog unit %d event 0%o\n",
  			mp->mslg_unit, mp->mslg_event);
  		break;
  	case M_FM_STIFEL:
! 		log(TMS_PRI, "STI Formatter ErrorLog unit %d event 0%o\n",
  			mp->mslg_unit, mp->mslg_event);
  		break;
  	default:
! 		log(TMS_PRI, "unknown err %d,%d format 0%o event 0%o\n",
! 			ctlr,mp->mslg_unit, mp->mslg_format, mp->mslg_event);
  	}
  
  	if (tmscperror)
***************
*** 1828,1849 ****
  		printf("\n");
  		}
  }
! 
! #ifdef	notSMS
! tprintf(pri,fmt,a)
! 	int pri;
! 	char *fmt;
! 	unsigned a;
! 	{
! 	prf(fmt, &a, 5);	/* 5 = TOLOG|TOCONSOLE */
! 	}
! 
! log(pri,fmt,a)
! 	int pri;
! 	char *fmt;
! 	unsigned a;
! 	{
! 	prf(fmt, &a, 5);
! 	}
! #endif	notSMS
! #endif
--- 1784,1787 ----
  		printf("\n");
  		}
  }
! #endif NTMSCP
