Subject: MSCP/TMSCP programmable vectors vs. autoconfig (#83)
Index:	sys/autoconfig/*,sys/pdpuba/{ra.c,rareg.h,tmscp.c} 2.11BSD

Description:
	The MSCP and TMSCP vector assignment logic is a kludge which
	can cause those drivers to usurp vectors allocated to other
	devices.

Repeat-By:
	Have more than 1 MSCP (or TMSCP) controller in a system.  Note that the
	vector the driver will is independent of what 'autoconfig' reads
	from /etc/dtab.  If you are lucky the system will ignore the
	controller's interrupts safely and merely report a device error, if
	you are not so lucky the system will crash.

	Since the vectors are programmable the drivers should not presume
	to know better than the contents of /etc/dtab.  By simply assigning
	vectors from the base (in the case of ra.c the formula was 0154 plus
	4 times the controller number) it was possible for the MSCP driver
	to run over the RL11 vector.

Fix:
	The fix below updates 'autoconfig' with the capability to pass
	a vector to the device driver.  If a symbol of the form "_xxxVec"
	is defined (where 'xxx' is "ra" or "tms" at present for the MSCP
	and TMSCP drivers respectively) 'autoconfig' will call that function
	as part of the attach process.

	Also updated are the MSCP (ra.c and rareg.h) and TMSCP (tmscp.c)
	drivers to define the new entry point.  MSCP drives are capable
	of being used as boot/root devices therefore it is not an error
	for the vector to be assigned twice (once at root attach, from
	the kernel init_main.c, and once when 'autoconfig' runs).  For
	other devices it is an error for the vector to be assigned to the
	same controller more than once.

	root/boot controllers always are assigned the first (primary)
	vector for the device (0154 for MSCP, 0260 for TMSCP).  Additional
	controllers receive their interrupt vector from 'autoconfig' (who
	reads it from /etc/dtab).

	A second update (#84) will follow shortly.  That patch will
	provide instructions for updating the kernel config files
	(/sys/conf/GENERIC for example) to remove the extraneous TMSCP_VEC
	statement.  Stay tuned.

	To apply patches (they were all created with full pathnames) use
	the "-p0" option of the 'patch' program:

		patch -p0 < the_file_below
=============================cut here================================
*** /sys/autoconfig/attach.c.old	Fri Feb 27 02:13:00 1987
--- /sys/autoconfig/attach.c	Thu Nov 19 21:37:24 1992
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)attach.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.
   *
!  *	@(#)attach.c	2.0 (2.11BSD GTE) 11/20/92
   */
  
  /*
***************
*** 10,15 ****
--- 10,22 ----
   * Attach the passed device:
   *	Patch the interrupt vector
   *	Call the device attach routine
+  *
+  *	Call (if present) the vector setting routine, passing the
+  *	vector from /etc/dtab to the driver.  At present only the
+  *	MSCP and TMSCP drivers have routines to do this.  The detach()
+  *	routine was removed because it was superfluous.  The kernel no
+  *	longer calls every driver's XXroot() entry point at start up time,
+  *	thus there is nothing to detach any more.
   */
  
  #include <machine/psl.h>
***************
*** 68,73 ****
--- 75,88 ----
  		addr += IVSIZE;
  	}
  	prdev(dp);
+ 	if (dp->dt_setvec && dp->dt_setvec->n_value) {
+ 		ret = ucall(PSL_BR0,dp->dt_setvec->n_value,unit,dp->dt_vector);
+ 		if (ret == -1) {
+ 			printf(" vectorset failed\n");
+ 			exit(AC_SINGLE);
+ 		}
+ 	printf(" vectorset");
+ 	}
  	printf(" attached\n");
  }
  
***************
*** 151,171 ****
  	else if (want_unit <= dn->d_unit)
  		return(ERR);
  	return(dn->d_unit = dp->dt_unit = want_unit);
- }
- 
- /*
-  * Call the device-attach routine with a 0 addr to indicate that the device
-  * isn't present (needed for devices that might be root devices and thus must
-  * have addr/vector initialized).  Only done if the unit number was not a
-  * wildcard.
-  */
- detach(dp)
- DTAB	*dp;
- {
- 	if (dp->dt_unit == -1)
- 		return;
- 	if (debug)
- 		printf("detach: ucall %o(PSL_BR0, %o, %o)\n",dp->dt_attach->n_value,0,dp->dt_unit);
- 	else
- 		ucall(PSL_BR0,dp->dt_attach->n_value,0,dp->dt_unit);
  }
--- 166,169 ----
*** /sys/autoconfig/do_config.c.old	Fri Feb 27 02:13:09 1987
--- /sys/autoconfig/do_config.c	Thu Nov 19 21:42:04 1992
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)do_config.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.
   *
!  *	@(#)do_config.c	2.0 (2.11BSD GTE) 11/20/92
   */
  
  /*
***************
*** 117,123 ****
  				prdev(dp);
  				puts(" skipped:  No CSR.");
  			}
- 			detach(dp);
  			continue;
  		}			/* Ok, try a probe now */
  		if (expect_intr(dp)) {
--- 117,122 ----
***************
*** 125,131 ****
  				prdev(dp);
  				puts(" interrupt vector already in use.");
  			}
- 			detach(dp);
  			continue;
  		}
  		ret = do_probe(dp, dp->dt_addr);
--- 124,129 ----
***************
*** 136,142 ****
  					prdev(dp);
  					puts(" does not exist.");
  				}
- 				detach(dp);
  				break;
  			case ACP_IFINTR:
  				switch (intval()) {
--- 134,139 ----
***************
*** 145,151 ****
  							prdev(dp);
  							puts(" interrupt vector wrong.");
  						}
- 						detach(dp);
  						break;
  					case ACI_NOINTR:
  						if (complain) {
--- 142,147 ----
***************
*** 152,158 ****
  							prdev(dp);
  							puts(" didn't interrupt.");
  						}
- 						detach(dp);
  						break;
  					case ACI_GOODINTR:
  						attach(dp);
--- 148,153 ----
*** /sys/autoconfig/dtab.h.old	Fri Feb 27 02:13:09 1987
--- /sys/autoconfig/dtab.h	Thu Nov 19 21:45:55 1992
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)dtab.h	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.
   *
!  *	@(#)dtab.h	2.0 (2.11BSD GTE) 11/20/92
   */
  
  /*
***************
*** 27,32 ****
--- 27,33 ----
  	int	dt_br;			/* Priority */
  	int	(*dt_uprobe)();		/* User-level (internal) probe */
  	NLIST	*dt_probe,		/* Address of probe function */
+ 		*dt_setvec,		/* Address of vector set function */
  		*dt_attach;		/* Address of attach function */
  } DTAB;
  
*** /sys/autoconfig/read_nlist.c.old	Fri Feb 27 02:13:09 1987
--- /sys/autoconfig/read_nlist.c	Thu Nov 19 21:43:41 1992
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)read_nlist.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.
   *
!  *	@(#)read_nlist.c	2.0 (2.11BSD GTE) 11/20/92
   */
  
  /*
***************
*** 59,64 ****
--- 59,66 ----
  		dp->dt_probe = add_nlist(tname);
  		sprintf(tname, "_%sattach", dp->dt_name);
  		dp->dt_attach = add_nlist(tname);
+ 		sprintf(tname, "_%sVec", dp->dt_name);
+ 		dp->dt_setvec = add_nlist(tname);
  		for (sp = dp->dt_handlers;sp;sp = sp->s_next)
  			sp->s_nl = add_nlist(sp->s_str);
  	}
*** /sys/autoconfig/uprobe.c.old	Sun Dec 22 16:00:36 1991
--- /sys/autoconfig/uprobe.c	Thu Nov 19 21:44:58 1992
***************
*** 3,15 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)uprobe.c	1.2 (2.11BSD Berkeley) 12/22/91
   */
  
  /*
   * The uprobe table contains the pointers to the user-level probe routines
!  * that usually attempt to make various devices interrupt.  The actual
!  * probe routines are in the device driver sources.
   *
   * NOTES:
   *	Reads and writes to kmem (done by grab, stuff) are currently done a
--- 3,14 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)uprobe.c	2.0 (2.11BSD GTE) 11/20/92
   */
  
  /*
   * The uprobe table contains the pointers to the user-level probe routines
!  * that may attempt to make various devices interrupt.
   *
   * NOTES:
   *	Reads and writes to kmem (done by grab, stuff) are currently done a
***************
*** 30,36 ****
  UPROBE uprobe[] = {
  	"hk",	hkprobe,	/* hk -- rk611, rk06/07 */
  	"hp",	xpprobe,	/* hp -- rjp04/06, rwp04/06 */
! 	"ra",	raprobe,	/* ra -- rqdx? (rx50,rd51/52/53), uda50 (ra60/80/81), klesi (ra25) */
  	"rk",	rkprobe,	/* rk -- rk05 */
  	"rl",	rlprobe,	/* rl -- rl01/02 */
  	"si",	siprobe,	/* si -- SI 9500 for CDC 9766 */
--- 29,35 ----
  UPROBE uprobe[] = {
  	"hk",	hkprobe,	/* hk -- rk611, rk06/07 */
  	"hp",	xpprobe,	/* hp -- rjp04/06, rwp04/06 */
! 	"ra",	raprobe,	/* ra -- MSCP
  	"rk",	rkprobe,	/* rk -- rk05 */
  	"rl",	rlprobe,	/* rl -- rl01/02 */
  	"si",	siprobe,	/* si -- SI 9500 for CDC 9766 */
*** /sys/pdpuba/ra.c.old	Thu Nov 12 22:12:50 1992
--- /sys/pdpuba/ra.c	Fri Nov 20 23:20:09 1992
***************
*** 14,19 ****
--- 14,24 ----
  
  /* 
   * ra.c - MSCP Driver
+  * Date:	Nov 1992
+  * Add raVec() routine.  This is called by autoconfig to set the vector
+  * (from /etc/dtab) for controllers other than the root (1st).  The boot/root
+  * controller's vector is always set to 0154.
+  *
   * Date:	Jul  1992
   * Major rework of the partition tables.  Some old (RA60,80,81,RD53) tables 
   * were retained (the rd54 'c' partition is now 'g' but the sizes stay 
***************
*** 284,290 ****
  #define PRINTB(x)
  #endif
  
! int	raattach(), raintr(), wakeup();
  extern	ubadr_t	_iomap();
  struct	mscp 	*ragetcp();
  
--- 289,295 ----
  #define PRINTB(x)
  #endif
  
! int	wakeup();
  extern	ubadr_t	_iomap();
  struct	mscp 	*ragetcp();
  
***************
*** 306,314 ****
--- 311,342 ----
  	if (!csr)		/* XXX */
  		csr = (radeviceT *) 0172150;	/* XXX */
  	raattach(csr, 0);
+ 	raVec(0, 0154);
  }
  
  /*
+  * Called from autoconfig and raroot() to set the vector for a controller.
+  * It is an error to attempt to set the vector more than once except for
+  * the first controller which may have had the vector set from raroot().
+  * In this case the error is ignored and the vector left unchanged.
+ */
+ 
+ raVec(ctlr, vector)
+ 	register int	ctlr;
+ 	int	vector;
+ 	{
+ 	register ra_softcT *sc = &ra_sc[ctlr];
+ 
+ 	if	(ctlr >= NRAC)
+ 		return(-1);
+ 	if	(sc->sc_ivec == 0)
+ 		sc->sc_ivec = vector;
+ 	else if	(ctlr)
+ 		return(-1);
+ 	return(0);
+ 	}
+ 	
+ /*
   * Attach controller for autoconfig system.
   */
  raattach(addr, unit)
***************
*** 457,463 ****
  	/*
  	 * Cold init of controller
  	 */
- 	sc->sc_ivec = RA_VECTOR + sc->sc_unit * 04;
  	++sc->sc_ctab.b_active;
  	PRINTD(("rainit: unit=%d, vec=%o\n", sc->sc_unit, sc->sc_ivec));
  
--- 485,490 ----
***************
*** 754,760 ****
  		break;
  
  	default:
! 		printf("raintr: state %d ignored\n", sc->sc_state);
  		return;
  	}
  
--- 781,787 ----
  		break;
  
  	default:
! 		printf("ra: state %d ignored\n", sc->sc_state);
  		return;
  	}
  
*** /sys/pdpuba/rareg.h.old	Fri Jan  9 01:58:03 1987
--- /sys/pdpuba/rareg.h	Thu Nov 19 22:23:39 1992
***************
*** 25,29 ****
  #define RA_IE		0000200
  #define RA_PI		0000001
  #define RA_GO		0000001
- 
- #define RA_VECTOR	0154
--- 25,27 ----
*** /sys/pdpuba/tmscp.c.old	Sun Sep 22 08:43:13 1991
--- /sys/pdpuba/tmscp.c	Thu Nov 19 21:02:38 1992
***************
*** 31,37 ****
   * 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
--- 31,42 ----
   * tmscp.c - TMSCP (TK50/TU81) tape device driver
   * 
   * Modification History:
!  * 20-Nov-92 - sms@wlv.iipo.gtegsc.com [2.11BSD]
!  *	Add tmsVec() for autoconfig to use in passing the vector from /etc/dtab
!  *	to this driver.  The previous scheme of having a fixed vector with
!  *	all TMSCP vectors contiguous has been removed.
!  *
!  * 23-May-91 - sms@wlv.iipo.gtegsc.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
***************
*** 38,44 ****
   *	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
--- 43,49 ----
   *	density, instead leaving the drive in the current/last-used
   *	density.
   *
!  * 29-Mar-91 - sms@wlv.iipo.gtegsc.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
***************
*** 68,74 ****
   *	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.
--- 73,79 ----
   *	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.iipo.gtegsc.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.
***************
*** 190,197 ****
  #include "../pdp/tmscp.h"
  #include "../machine/seg.h"
  
- 	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
--- 195,200 ----
***************
*** 312,317 ****
--- 315,331 ----
  
  #define b_qsize         b_resid         /* queue size per drive, in tmsutab */
  
+ tmsVec(ctlr, vector)
+ 	int	ctlr, vector;
+ 	{
+ 	register struct tmscp_softc *sc = &tmscp_softc[ctlr];
+ 
+ 	if	(ctlr >= NTMSCP || sc->sc_ivec)
+ 		return(-1);
+ 	sc->sc_ivec = vector;
+ 	return(0);
+ 	}
+ 
  /* 
   * Open routine will issue the online command, later.
   *
***************
*** 899,905 ****
  	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);
--- 913,918 ----
