Subject: Interrupt vector patch for turbochannel machines,
To: None <port-pmax@NetBSD.ORG>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: port-pmax
Date: 12/26/1994 12:57:20
A brief summary of the enclosed patch is this: NetBSD (and presumably
4.4bsd) enabled interrupts when probing for devices, _before_ setting
an interrupt vector. (This is clearly wrong.)  For machines with
turbochannels -- at least 5k/200 -- the boot prom doesn't reset
turbochannel option cards on initialization or reset, only on
power-up.  When trying to reboot after a crash that left a
turbochannel device with an interrupt pending, the kernel would enable
interrupts in tc_find_all_options(), and get an infinite stream of
spurious interrupts.

The patch below is from a source tree containing other changes;
line numbers will show some fuzz relative to NetBSD-current.
My apologies if there are any  untoward differences.

[[I simply #if 0'ed out the offending  code, and duplicated
  it in a more appropriate place. It may be easier to fold
  in subsequent changes from the 4.4bsd pmax port that way;
  or it may be cleaner to just delete the old code.  I don't
  know house style here.]]

Anyway, I beleive this is a correct fix. If the port maintainer could
merge it in, that would be great.


I imagine something conceptually similar is behind the problems with
3100s booting on active Ethernet segments. Either making sure that, on
a PMAX, interrupts from devices aren't enabled until configure() has
called (*drp->d_init) -- or, more simply, moving the PMAX-specific
calls to (*drp->d_init()) from configure() to pmax_slot_hand_fill() --
seems like a good experiment. I don't have access to one right now...





*** machdep.c		Thu Dec  1 17:14:52 1994
--- machdep.c.dsg	Sat Dec 24 19:49:45 1994
***************
*** 161,166 ****
--- 161,167 ----
  u_long	asic_base;		/* Base address of I/O asic */
  const	struct callback *callv;	/* pointer to PROM entry points */
  
+ extern void	(*tc_enable_interrupt)();
  void	(*tc_enable_interrupt)();
  extern	int (*pmax_hardware_intr)();
  void	pmax_slot_hand_fill();
***************
*** 1687,1692 ****
--- 1688,1694 ----
  			if (cp->pmax_addr == (char *)QUES) {
  				cp->pmax_addr = (char *)sl->k1seg_address;
  				cp->pmax_pri = i;
+ #if 0	/* Senseless to enable intrs before setting up the handler */
  				/*
  				 * Only enable interrupts if there is an
  				 * interrupt handler for it. (e.g., PMAG-BA 
***************
*** 1695,1700 ****
--- 1697,1703 ----
  				 */
  				if (drp->d_intr)
  					(*tc_enable_interrupt)(i, 1);
+ #endif
  				cp->pmax_alive = 1;
  				break;
  			}
*** autoconf.c		Fri Nov 25 03:11:38 1994
--- autoconf.c.dsg	Sat Dec 24 19:47:01 1994
***************
*** 74,79 ****
--- 74,80 ----
  int	cpuspeed = 30;	/* approx # instr per usec. */
  extern	int pmax_boardtype;
  extern	tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
+ extern void	(*tc_enable_interrupt)();
  
  /*
   * Determine mass storage and memory configuration for a machine.
***************
*** 171,176 ****
--- 172,187 ----
  						drp->d_name, i);
  				tc_slot_info[i].intr = drp->d_intr;
  				tc_slot_info[i].unit = cp->pmax_unit;
+ #if 1
+ 				/*
+ 				 * Only enable interrupts if there is an
+ 				 * interrupt handler for it. (e.g., PMAG-BA 
+ 				 * can't disable the vertical retrace interrupt
+ 				 * and we might want to ignore it).
+ 				 */
+ 				if (drp->d_intr)
+ 					(*tc_enable_interrupt)(i, 1);
+ #endif
  			}
  			break;
  #endif /* DS5000 */