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 */