Subject: kern/7247: Incorrect handling of interrupts with pciide driver in native
To: None <gnats-bugs@gnats.netbsd.org>
From: None <mark@causality.com>
List: netbsd-bugs
Date: 03/25/1999 23:37:54
>Number:         7247
>Category:       kern
>Synopsis:       Incorrect handling of interrupts with pciide driver in native
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Mar 25 23:50:01 1999
>Last-Modified:
>Originator:     Mark Brinicombe
>Organization:
BCCS Ltd
>Release:        NetBSD-current 1999/03/25
>Environment:
	
System: NetBSD p2.devlab.nc.com 1.3I-NCOS NetBSD 1.3I-NCOS (P2) #1: Wed Mar 17 16:37:17 PST 1999 mark@p2.devlab.nc.com:/usr/export/mark/NCOS/os-src/sys/arch/i386/compile/P2 i386


>Description:
	Interrupt handling does not work correctly with the pciide driver if
	running in native mode with two channels bus mustering at the same time.
	In native mode a single interrupt is shared by both IDE channels. The
	result is that wdcintr() gets called for both channels whenever an
	interrupt occurs. If two channels are bus mastering at the same time
	and one completes generating an interrupt, wdcintr() is called for
	both channels, each of which assumes the interrupt was for it.
	This means one DMA transfer completes correctly but the other channel's
	DMA transfer is cut short (with an error) as it assumes that the
	interupt was it's completion.
	This will not normally be seen in i386 architectures with motherboard
	IDE as this configuration does not use native interrupts.

>How-To-Repeat:
	Try bus mastering on two channels on a plug in PCI card (i.e. promise
	ultra/33 or ultra/66). Note the DMA to either channel individually works
	but simultaneous DMA transfers results in lots of nasty errors.

>Fix:
	The routine pciide_pci_intr() needs to check that the IDE channel is
	not still doing DMA before calling wdcintr() by checking the
	status in the bus mastering register i.e. the IDEDMA_CTL_INTR
	bit will be set if a channel did generate the interrupt thus making
	sure that only the channel that generated the interrupt gets it
	delivered.
>Audit-Trail:
>Unformatted:
mode<synopsis of the problem (one line)>