NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
port-mac68k/60722: mac68k: enable_nubus_intr() tests six bits where the rest of via.c uses seven
>Number: 60722
>Category: port-mac68k
>Synopsis: mac68k: enable_nubus_intr() tests six bits where the rest of via.c uses seven
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: port-mac68k-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Sep 13 05:00:01 +0000 2026
>Originator: Ray Tran
>Release: 11.0
>Organization:
Diamond Creek Digital
>Environment:
Centris 650 running NetBSD 11.0 / current kernel with no NuBus cards
>Description:
sys/arch/mac68k/mac68k/via.c keeps seven NuBus slot handlers, for slots
9 through 15. Slot 15 is not a real slot: the file's own header says so,
* Nubus slot interrupt routines and parameters for slots 9-15.
* Note that for simplicity of code, "v2IRQ0" for internal video
* is treated as a slot 15 interrupt; this slot is quite
* fictitious in real-world Macs.
and slotitab[]'s seventh and last entry carries the comment
"int_video_intr" to say what it is for.
Everything that walks those tables is seven bits wide. add_nubus_intr()
sets bit (slot - 9), so slot 15 is bit 6. via2_nubus_intr() and
rbv_nubus_intr() both start at i = 6 and count down. oss_intr() masks
intbits with 0x7f. enable_nubus_intr() is the exception:
if ((nubus_intr_mask & 0x3f) == 0)
return;
if (VIA2 == VIA2OFF)
via2_reg(vIER) = 0x80 | V2IF_SLOTINT;
else
via2_reg(rIER) = 0x80 | V2IF_SLOTINT;
0x3f is bits 0 through 5, slots 9 through 14, the six physical slots.
Bit 6 is missing, so a kernel whose only registered slot is 15 returns
without ever unmasking V2IF_SLOTINT. The device asserts its line on
VIA2 port A bit 6 and holds it there; via2_nubus_intr() is never
entered, and the interrupt is silently lost forever.
Any NuBus card in a real slot hides this completely. That driver's own
enable_nubus_intr() call has a bit inside 0x3f, unmasks the shared
V2IF_SLOTINT, and the slot 15 handler is dispatched along with it, since
via2_nubus_intr() loops over every bit in nubus_intr_mask. The fault is
therefore visible only on a machine with an empty NuBus, and it looks
like a hardware or driver problem rather than a missing register write.
Nothing else takes a slot on such a machine. Under the A/UX interrupt
scheme, which machdep.c selects for the Quadra and Centris class,
if_sn_obio.c attaches the built-in SONIC with intr_establish(..., 3) and
calls add_nubus_intr(SONIC_SLOTNO, ...) only on the other path.
The second caller of slot 15 in the tree meets the same wall from the
other side: wdc_obio.c registers add_nubus_intr(0xf, ...) for the
Quadra/Performa IDE interface and never calls enable_nubus_intr() at
all, so that interrupt likewise depends on some other driver having
unmasked the bit. This change does not touch it; it is reported here
because it is the same assumption and someone with that hardware should
judge it.
>How-To-Repeat:
On a Quadra or Centris with nothing in the NuBus slots, register a
handler on slot 15, call enable_nubus_intr(), enable a source that
raises the internal-video interrupt, and count. The count stays at
zero. Add the one register write enable_nubus_intr() declined to make,
via2_reg(vIER) = 0x80 | V2IF_SLOTINT;
and the same code counts the interrupt at its real rate.
>Fix:
One expression, and a comment saying why the width matters. With it,
sys/arch/mac68k/mac68k/via.c reads
if ((nubus_intr_mask & 0x7f) == 0)
return;
nubus_intr_mask only ever holds bits 0 through 6, so testing the mask
against zero would do as well; 0x7f is written to match oss_intr() and
to keep the seven-bit intent visible at the point of the test.
The same patch applies to -current.
Applies with "patch -p1" from the top of usr/src; verified with -F0
(no fuzz) against NetBSD-current 11.99.8 (20260911135556Z) and 11.0.
--- a/sys/arch/mac68k/mac68k/via.c
+++ b/sys/arch/mac68k/mac68k/via.c
@@ -397,7 +397,18 @@
void
enable_nubus_intr(void)
{
- if ((nubus_intr_mask & 0x3f) == 0)
+ if ((nubus_intr_mask & 0x7f) == 0)
return;
if (VIA2 == VIA2OFF)
Home |
Main Index |
Thread Index |
Old Index