Subject: kern/3968: ISA PnP doesn't check for DRQ conflict
To: None <gnats-bugs@gnats.netbsd.org>
From: Lennart Augustsson <augustss@cs.chalmers.se>
List: netbsd-bugs
Date: 08/12/1997 01:30:56
>Number:         3968
>Category:       kern
>Synopsis:       ISA PnP doesn't check for DRQ conflict
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 11 16:35:01 1997
>Last-Modified:
>Originator:     Lennart Augustsson
>Organization:
Department of Computing Science, Chalmers University
>Release:        NetBSD-current 97-08-11
>Environment:
System: NetBSD calvin 1.2G NetBSD 1.2G (CALVIN) #109: Tue Aug 12 01:11:51 CEST 1997 augustss@calvin:/users/NetBSD/src/sys/arch/i386/compile/CALVIN i386


>Description:
	When The PnP code selects a DRQ for a PnP card it doesn't
	check if that DRQ is already in use by another device.
	When the duplicated DRQ is later used to create a DMA map
	there will be a panic.
>How-To-Repeat:
	Make sure the DRQ that is the first choice of a PnP device
	is taken, boot and see it panic.  E.g. take DRQ 0 and
	boot with a PnP SoundBlaster.
>Fix:
	Well, I will not pretend that I've really penetrated how
	the PnP code works, but here is a patch that works for me.
	I'm sure someone who is PnP savvy can beat it into shape.

	The patch presumes that that isapnp is attached to isa,
	but that is the only way it supposed to be, isn't it?


Index: isapnp.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isapnp/isapnp.c,v
retrieving revision 1.8
diff -c -r1.8 isapnp.c
*** isapnp.c	1997/08/06 04:52:31	1.8
--- isapnp.c	1997/08/11 23:22:52
***************
*** 223,237 ****
  {
  	int b;
  
! 	if (i->bits == 0)
! 		i->num = 0;
! 	else
! 		for (b = 0; b < 16; b++)
! 			if (i->bits & (1 << b)) {
! 				i->num = b;
! 				break;
! 			}
! 	return 0;
  }
  
  
--- 223,234 ----
  {
  	int b;
  
! 	for (b = 0; b < 16; b++)
! 		if (i->bits & (1 << b)) {
! 			i->num = b;
! 			return 0;
! 		}
! 	return 1;
  }
  
  
***************
*** 276,281 ****
--- 273,281 ----
  	}
  
  	for (; ndrq < ipa->ipa_ndrq; ndrq++) {
+ 		struct isa_softc *isa = 
+ 			(struct isa_softc *)ipa->ipa_sc->sc_dev.dv_parent;
+ 		ipa->ipa_drq[ndrq].bits &= ~isa->sc_drqmap;
  		error = isapnp_alloc_pin(&ipa->ipa_drq[ndrq]);
  		if (error)
  			goto bad;
Index: isapnpres.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isapnp/isapnpres.c,v
retrieving revision 1.7
diff -c -r1.7 isapnpres.c
*** isapnpres.c	1997/08/03 08:12:25	1.7
--- isapnpres.c	1997/08/11 23:22:56
***************
*** 89,94 ****
--- 89,95 ----
  	struct isapnp_attach_args *ipa, *dev = ISAPNP_MALLOC(sizeof(*dev));
  
  	memset(dev, 0, sizeof(*dev));
+ 	dev->ipa_sc = card->ipa_sc;
  
  	dev->ipa_pref = ISAPNP_DEP_ACCEPTABLE;
  	memcpy(dev->ipa_devident, card->ipa_devident,
***************
*** 118,123 ****
--- 119,125 ----
  	struct isapnp_attach_args *ipa, *conf = ISAPNP_MALLOC(sizeof(*conf));
  
  	memset(conf, 0, sizeof(*conf));
+ 	conf->ipa_sc = dev->ipa_sc;
  
  	memcpy(conf->ipa_devident, dev->ipa_devident,
  	    sizeof(conf->ipa_devident));
***************
*** 447,452 ****
--- 449,455 ----
  
  	card = ISAPNP_MALLOC(sizeof(*card));
  	memset(card, 0, sizeof(*card));
+ 	card->ipa_sc = sc;
  
  #define NEXT_BYTE \
  		if (isapnp_wait_status(sc)) \
Index: isapnpvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/isapnp/isapnpvar.h,v
retrieving revision 1.5
diff -c -r1.5 isapnpvar.h
*** isapnpvar.h	1997/08/06 04:52:29	1.5
--- isapnpvar.h	1997/08/11 23:22:57
***************
*** 124,129 ****
--- 124,131 ----
  	bus_space_tag_t ipa_memt;	/* isa mem space tag */
  	bus_dma_tag_t	ipa_dmat;	/* isa dma tag */
  
+ 	struct isapnp_softc *ipa_sc;
+ 
  	isa_chipset_tag_t ipa_ic;
  
  	struct isapnp_attach_args *ipa_sibling;
>Audit-Trail:
>Unformatted: