Subject: Serious [T]MSCP on UNIBUS system bug (+fix)
Index:	sys/pdp/machdep2.c 2.11BSD

Description:
	There is a serious (fatal) bug in the allocation of the out
	of kernel [T]MSCP command packet arena on UNIBUS systems.

	Q-bus systems (11/53,73,83,93) do not suffer from the
	consequences of this bug, but UNIBUS (11/44,70,84) systems
	will crash when a TMSCP or MSCP driver is present in the
	kernel.

Repeat-By:
	You really don't want to.  Best to simply examine machdep2.c.
Fix:
	The patch below will fix the bug.

	The problem was that a UMR was being allocated to map the
	[T]MSCP command packet arena before ubinit() has been called 
	to initialize the UMR map structure.

	This patch leaves the memory allocation where it was, the UMR
	allocation is moved to the end of the ubinit() routine just after
	the UMRs have been free()'d into the UMR map structure.
--------------------------------------------------------------------------
*** /sys/pdp/machdep2.c.old	Thu Jun  6 01:50:37 1991
--- /sys/pdp/machdep2.c	Sun Nov 17 12:20:10 1991
***************
*** 181,213 ****
  
  #if	NRAC > 0 || NTMSCP > 0
  {
- 	register int s, first;
- 	register struct ubmap *ubp;
- 	long paddr;
- 
  	if ((_iobase = malloc(coremap, btoc(_iosize))) == 0)
  		panic("_iobase");
  	maxmem -= btoc(_iosize);
- #ifdef	UNIBUS_MAP
- 	if (ubmap) {
- 		_iostart = _iobase;
- 		s = (int)btoub(_iosize);
- /*
-  * this early in the system's life there had better be a UMR or two
-  * available!!
- */
- 		first = malloc(ub_map, s);
- 		_ioumr = (ubadr_t)first << 13;
- 		ubp = &UBMAP[first];
- 		paddr = ctob((ubadr_t)_iostart);
- 		while (s--) {
- 			ubp->ub_lo = loint(paddr);
- 			ubp->ub_hi = hiint(paddr);
- 			ubp++;
- 			paddr += (ubadr_t)UBPAGE;
- 		}
- 	}
- #endif	UNIBUS_MAP
  }
  #endif	NRAC
  
--- 181,189 ----
***************
*** 325,336 ****
  /*
   * Re-initialize the Unibus map registers to statically map
   * the clists and buffers.  Free the remaining registers for
!  * physical I/O.
   */
  ubinit()
  {
  	register int i, ub_nreg;
  	long paddr;
  
  	if (!ubmap)
  		return;
--- 301,313 ----
  /*
   * Re-initialize the Unibus map registers to statically map
   * the clists and buffers.  Free the remaining registers for
!  * physical I/O.  At this time the [T]MSCP arena is also mapped.
   */
  ubinit()
  {
  	register int i, ub_nreg;
  	long paddr;
+ 	register struct ubmap *ubp;
  
  	if (!ubmap)
  		return;
***************
*** 363,370 ****
  #else
  	mfree(ub_map, 31 - ub_nreg - 1, 1 + ub_nreg);
  #endif
  }
! #endif
  
  int waittime = -1;
  
--- 340,368 ----
  #else
  	mfree(ub_map, 31 - ub_nreg - 1, 1 + ub_nreg);
  #endif
+ 
+ /*
+  * this early in the system's life there had better be a UMR or two
+  * available!!  N.B. This was moved from where the [T]MSCP memory was 
+  * allocated because at that point the UMR map was not initialized.
+ */
+ 
+ #if	NRAC > 0 || NTMSCP > 0
+ 	_iostart = _iobase;
+ 	i = (int)btoub(_iosize);
+ 	ub_nreg = malloc(ub_map, i);
+ 	_ioumr = (ubadr_t)ub_nreg << 13;
+ 	ubp = &UBMAP[ub_nreg];
+ 	paddr = ctob((ubadr_t)_iostart);
+ 	while (i--) {
+ 		ubp->ub_lo = loint(paddr);
+ 		ubp->ub_hi = hiint(paddr);
+ 		ubp++;
+ 		paddr += (ubadr_t)UBPAGE;
+ 	}
+ #endif	NRAC
  }
! #endif	UNIBUS_MAP
  
  int waittime = -1;
  
