Subject: port-i386/6436: PCIC PCI attachment
To: None <gnats-bugs@gnats.netbsd.org>
From: None <danw@MIT.EDU>
List: netbsd-bugs
Date: 11/13/1998 11:45:04
>Number:         6436
>Category:       port-i386
>Synopsis:       PCIC PCI attachment
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Nov 13 08:50:00 1998
>Last-Modified:
>Originator:     Dan Winship
>Organization:
MIT
>Release:        current
>Environment:
System: NetBSD spellbook.mit.edu 1.3H NetBSD 1.3H (SPELLBOOK) #4: Thu Nov 12 13:13:27 EST 1998 danw@spellbook.mit.edu:/u1/usr/src/sys/arch/i386/compile/SPELLBOOK i386


>Description:
	The PCIC PCI attachment doesn't work.
>How-To-Repeat:
	
>Fix:
This uses machdep code in the style of pciide, as suggested by Jason.
It only works for the i386 as written, but could be extended. Also, as
noted in one of the comments, it only works _well_ if your pci bus is
wired such that ISA will end up being configured before the pcmcia
cards are attached.

*** src/sys/dev/pci/i82365_pci.c.orig	Mon Jun  8 07:14:38 1998
--- src/sys/dev/pci/i82365_pci.c	Fri Nov 13 11:37:05 1998
***************
*** 40,45 ****
--- 40,46 ----
  #include <dev/pci/pcivar.h>
  #include <dev/pci/pcireg.h>
  #include <dev/pci/pcidevs.h>
+ #include <dev/pci/i82365_pcivar.h>
  
  /*
   * PCI constants.
***************
*** 50,59 ****
  int	pcic_pci_match __P((struct device *, struct cfdata *, void *));
  void	pcic_pci_attach __P((struct device *, struct device *, void *));
  
- void	*pcic_pci_chip_intr_establish __P((pcmcia_chipset_handle_t,
- 	    struct pcmcia_function *, int, int (*) (void *), void *));
- void	pcic_pci_chip_intr_disestablish __P((pcmcia_chipset_handle_t, void *));
- 
  struct cfattach pcic_pci_ca = {
  	sizeof(struct pcic_softc), pcic_pci_match, pcic_pci_attach
  };
--- 51,56 ----
***************
*** 69,81 ****
  	pcic_chip_io_map,
  	pcic_chip_io_unmap,
  
! 	pcic_pci_chip_intr_establish,
! 	pcic_pci_chip_intr_disestablish,
  
  	pcic_chip_socket_enable,
  	pcic_chip_socket_disable,
  };
  
  int
  pcic_pci_match(parent, match, aux)
  	struct device *parent;
--- 66,80 ----
  	pcic_chip_io_map,
  	pcic_chip_io_unmap,
  
! 	pcic_pci_machdep_chip_intr_establish,
! 	pcic_pci_machdep_chip_intr_disestablish,
  
  	pcic_chip_socket_enable,
  	pcic_chip_socket_disable,
  };
  
+ static void pcic_pci_callback(struct device *);
+ 
  int
  pcic_pci_match(parent, match, aux)
  	struct device *parent;
***************
*** 107,115 ****
  	pci_chipset_tag_t pc = pa->pa_pc;
  	bus_space_tag_t memt = pa->pa_memt;
  	bus_space_handle_t memh;
- 	pci_intr_handle_t ih;
  	char *model;
- 	const char *intrstr = NULL;
  
  	if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
  	    &sc->iot, &sc->ioh, NULL, NULL)) {
--- 106,112 ----
***************
*** 129,135 ****
  
  	/* Map mem space. */
  	if (bus_space_map(memt, 0xd0000, 0x4000, 0, &memh))
! 		panic("pcic_isa_attach: can't map i/o space");
  
  	sc->membase = 0xd0000;
  	sc->subregionmask = (1 << (0x4000 / PCIC_MEM_PAGESIZE)) - 1;
--- 126,132 ----
  
  	/* Map mem space. */
  	if (bus_space_map(memt, 0xd0000, 0x4000, 0, &memh))
! 		panic("pcic_pci_attach: can't map i/o space");
  
  	sc->membase = 0xd0000;
  	sc->subregionmask = (1 << (0x4000 / PCIC_MEM_PAGESIZE)) - 1;
***************
*** 141,147 ****
  
  	/* end XXX */
  
- 	sc->intr_est = pc;
  	sc->pct = (pcmcia_chipset_tag_t) & pcic_pci_functions;
  
  	sc->memt = memt;
--- 138,143 ----
***************
*** 165,247 ****
  
  	pcic_attach(sc);
  
! 	/* Map and establish the interrupt. */
! 	if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
! 	    pa->pa_intrline, &ih)) {
! 		printf("%s: couldn't map interrupt\n", sc->dev.dv_xname);
! 		return;
! 	}
! 	intrstr = pci_intr_string(pc, ih);
! 	sc->ih = pci_intr_establish(pc, ih, IPL_NET, pcic_intr, sc);
! 	if (sc->ih == NULL) {
! 		printf("%s: couldn't establish interrupt",
  		       sc->dev.dv_xname);
- 		if (intrstr != NULL)
- 			printf(" at %s", intrstr);
- 		printf("\n");
  		return;
  	}
- 	printf("%s: interrupting at %s\n", sc->dev.dv_xname, intrstr);
- 
- 	pcic_attach_sockets(sc);
- }
- 
- /*
-  * XXX This is almost totally wrong!  We need to map to PCI interupts,
-  * XXX which themselves map to somthing else.
-  */
  
! #include <dev/isa/isareg.h>
! #include <dev/isa/isavar.h>
  
! void *
! pcic_pci_chip_intr_establish(pch, pf, ipl, fct, arg)
! 	pcmcia_chipset_handle_t pch;
! 	struct pcmcia_function *pf;
! 	int ipl;
! 	int (*fct) (void *);
! 	void *arg;
! {
! 	struct pcic_handle *h = (struct pcic_handle *) pch;
! 	pci_chipset_tag_t pc = h->sc->intr_est;
! 	int irq;
! 	pci_intr_handle_t piht;
! 	void *ih;
! 	int reg;
  
  	/*
! 	 * XXX this will work for x86, but is guaranteed to lose elsewhere.
! 	 * Hopefully Jason can bail me out of this one, too.
  	 */
! 
! 	isa_intr_alloc(NULL, 0xffff, IST_PULSE, &irq);
! 
! 	if (pci_intr_map(pc, pci_make_tag(NULL, 0, 0, 0),
! 	    1, irq, &piht)) {
! 		printf("%s: couldn't map interrupt\n", h->sc->dev.dv_xname);
! 		return (NULL);
! 	}
! 	if ((ih = pci_intr_establish(pc, piht, ipl, fct,
! 	    arg)) == NULL)
! 		return (NULL);
! 
! 	reg = pcic_read(h, PCIC_INTR);
! 	reg |= PCIC_INTR_ENABLE;
! 	reg |= irq;
! 	pcic_write(h, PCIC_INTR, reg);
! 
! 	printf("%s: card irq %d\n", h->pcmcia->dv_xname, irq);
! 
! 	return (ih);
  }
  
! void 
! pcic_pci_chip_intr_disestablish(pch, ih)
! 	pcmcia_chipset_handle_t pch;
! 	void *ih;
  {
! 	struct pcic_handle *h = (struct pcic_handle *) pch;
! 	pci_chipset_tag_t pc = h->sc->intr_est;
  
! 	pci_intr_disestablish(pc, ih);
  }
--- 161,204 ----
  
  	pcic_attach(sc);
  
! 	/*
! 	 * Check to see if we're using PCI or ISA interrupts. I don't
! 	 * know of any i386 systems that use the 6729 in PCI interrupt
! 	 * mode, but maybe when the PCMCIA code runs on other platforms
! 	 * we'll need to fix this.
! 	 */
! 	pcic_write(&sc->handle[0], PCIC_CIRRUS_EXTENDED_INDEX,
! 		   PCIC_CIRRUS_EXT_CONTROL_1);
! 	if (pcic_read(&sc->handle[0], PCIC_CIRRUS_EXTENDED_DATA) &
! 	    PCIC_CIRRUS_EXT_CONTROL_1_PCI_INTR_MASK) {
! 		printf("%s: PCI interrupts not supported\n",
  		       sc->dev.dv_xname);
  		return;
  	}
  
! 	sc->intr_est = pcic_pci_machdep_intr_est(pc);
  
! 	/* Map and establish the interrupt. */
! 	sc->ih = pcic_pci_machdep_pcic_intr_establish(sc, pcic_intr);
! 	if (sc->ih == NULL) {
! 		printf("%s: couldn't map interrupt\n", sc->dev.dv_xname);
! 		return;
! 	}
  
  	/*
! 	 * Defer configuration of children until ISA has had its chance
! 	 * to use up whatever IO space and IRQs it wants. XXX This will
! 	 * only work if ISA is attached to a pcib, AND the PCI probe finds
! 	 * and defers the ISA attachment before this one.
  	 */
! 	config_defer(self, pcic_pci_callback);
  }
  
! static void
! pcic_pci_callback(self)
! 	struct device *self;
  {
! 	struct pcic_softc *sc = (void *) self;
  
! 	pcic_attach_sockets(sc);
  }
*** src/sys/dev/pci/i82365_pcivar.h.orig	Fri Nov 13 11:18:38 1998
--- src/sys/dev/pci/i82365_pcivar.h	Thu Nov 12 12:43:50 1998
***************
*** 0 ****
--- 1,50 ----
+ /*	$NetBSD$	*/
+ 
+ /*
+  * Copyright (c) 1998 The NetBSD Foundation, Inc.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *	This product includes software developed by the NetBSD
+  *	Foundation, Inc. and its contributors.
+  * 4. Neither the name of The NetBSD Foundation nor the names of its
+  *    contributors may be used to endorse or promote products derived
+  *    from this software without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  * POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+ /* 
+  * Establish/disestablish interrupts for PCMCIA functions.
+  */
+ 
+ void *pcic_pci_machdep_intr_est __P((pci_chipset_tag_t));
+ 
+ void *pcic_pci_machdep_pcic_intr_establish __P((struct pcic_softc *,
+ 						int (*) __P((void *))));
+ 
+ void *pcic_pci_machdep_chip_intr_establish __P((pcmcia_chipset_handle_t,
+ 						struct pcmcia_function *,
+ 						int, int (*) __P((void *)),
+ 						void *));
+ void pcic_pci_machdep_chip_intr_disestablish __P((pcmcia_chipset_handle_t,
+ 						  void *));
*** src/sys/dev/ic/i82365reg.h.orig	Fri Oct 17 14:36:45 1997
--- src/sys/dev/ic/i82365reg.h	Thu Nov 12 12:44:58 1998
***************
*** 330,332 ****
--- 330,337 ----
  #define	PCIC_CIRRUS_CHIP_INFO_CHIP_ID		0xC0
  #define	PCIC_CIRRUS_CHIP_INFO_SLOTS		0x20
  #define	PCIC_CIRRUS_CHIP_INFO_REV		0x1F
+ 
+ #define PCIC_CIRRUS_EXTENDED_INDEX		0x2E
+ #define PCIC_CIRRUS_EXTENDED_DATA		0x2F
+ #define PCIC_CIRRUS_EXT_CONTROL_1		0x03
+ #define PCIC_CIRRUS_EXT_CONTROL_1_PCI_INTR_MASK	0x18
*** src/sys/dev/ic/i82365.c.orig	Mon Nov  9 07:14:20 1998
--- src/sys/dev/ic/i82365.c	Thu Nov 12 12:44:57 1998
***************
*** 129,135 ****
  				return (PCIC_VENDOR_CIRRUS_PD6710);
  		}
  	}
- 	/* XXX how do I identify the GD6729? */
  
  	reg = pcic_read(h, PCIC_IDENT);
  
--- 129,134 ----
***************
*** 198,224 ****
  
  	DPRINTF((" 0x%02x", reg));
  
  	sc->handle[2].sc = sc;
  	sc->handle[2].sock = C1SA;
! 	if (pcic_ident_ok(reg = pcic_read(&sc->handle[2], PCIC_IDENT))) {
! 		sc->handle[2].flags = PCIC_FLAG_SOCKETP;
! 		count++;
! 	} else {
! 		sc->handle[2].flags = 0;
! 	}
  
! 	DPRINTF((" 0x%02x", reg));
! 
! 	sc->handle[3].sc = sc;
! 	sc->handle[3].sock = C1SB;
! 	if (pcic_ident_ok(reg = pcic_read(&sc->handle[3], PCIC_IDENT))) {
! 		sc->handle[3].flags = PCIC_FLAG_SOCKETP;
! 		count++;
! 	} else {
! 		sc->handle[3].flags = 0;
  	}
- 
- 	DPRINTF((" 0x%02x\n", reg));
  
  	if (count == 0)
  		panic("pcic_attach: attach found no sockets");
--- 197,233 ----
  
  	DPRINTF((" 0x%02x", reg));
  
+ 	/*
+ 	 * The CL-PD6729 has only one controller and always returns 0
+ 	 * if you try to read from the second one. Maybe pcic_ident_ok
+ 	 * shouldn't accept 0?
+ 	 */
  	sc->handle[2].sc = sc;
  	sc->handle[2].sock = C1SA;
! 	if (pcic_vendor(&sc->handle[0]) != PCIC_VENDOR_CIRRUS_PD672X ||
! 	    pcic_read(&sc->handle[2], PCIC_IDENT) != 0) {
! 		if (pcic_ident_ok(reg = pcic_read(&sc->handle[2],
! 						  PCIC_IDENT))) {
! 			sc->handle[2].flags = PCIC_FLAG_SOCKETP;
! 			count++;
! 		} else {
! 			sc->handle[2].flags = 0;
! 		}
! 
! 		DPRINTF((" 0x%02x", reg));
! 
! 		sc->handle[3].sc = sc;
! 		sc->handle[3].sock = C1SB;
! 		if (pcic_ident_ok(reg = pcic_read(&sc->handle[3],
! 						  PCIC_IDENT))) {
! 			sc->handle[3].flags = PCIC_FLAG_SOCKETP;
! 			count++;
! 		} else {
! 			sc->handle[3].flags = 0;
! 		}
  
! 		DPRINTF((" 0x%02x\n", reg));
  	}
  
  	if (count == 0)
  		panic("pcic_attach: attach found no sockets");
*** src/sys/arch/i386/conf/GENERIC.orig	Wed Nov 11 07:16:13 1998
--- src/sys/arch/i386/conf/GENERIC	Thu Nov 12 12:42:05 1998
***************
*** 185,190 ****
--- 185,193 ----
  pcic0	at isa? port 0x3e0 iomem 0xd0000 iosiz 0x4000
  pcic1	at isa? port 0x3e2 iomem 0xd4000 iosiz 0x4000
  
+ # PCI PCMCIA controllers
+ pcic0	at pci? dev? function ?
+ 
  # ISA Plug-and-Play bus support
  isapnp0	at isa?
  
*** src/sys/arch/i386/conf/files.i386.orig	Wed Oct 14 07:10:18 1998
--- src/sys/arch/i386/conf/files.i386	Thu Nov 12 12:42:05 1998
***************
*** 99,104 ****
--- 99,105 ----
  include "dev/pci/files.pci"
  file	arch/i386/pci/pci_machdep.c	pci
  file	arch/i386/pci/pciide_machdep.c	pciide
+ file	arch/i386/pci/pcic_pci_machdep.c	pcic_pci
  
  # PCI-Host bridge chipsets
  device	pchb: pcibus
***************
*** 286,292 ****
  file	dev/isapnp/i82365_isapnp.c	pcic_isapnp
  
  # Code common to ISA and ISAPnP attachments
! file	dev/isa/i82365_isasubr.c	pcic_isa | pcic_isapnp
  
  # this wants to be probed as late as possible.
  #
--- 287,293 ----
  file	dev/isapnp/i82365_isapnp.c	pcic_isapnp
  
  # Code common to ISA and ISAPnP attachments
! file	dev/isa/i82365_isasubr.c	pcic_isa | pcic_isapnp | pcic_pci
  
  # this wants to be probed as late as possible.
  #
*** src/sys/arch/i386/pci/pcic_pci_machdep.c.orig	Fri Nov 13 11:18:10 1998
--- src/sys/arch/i386/pci/pcic_pci_machdep.c	Thu Nov 12 12:43:26 1998
***************
*** 0 ****
--- 1,89 ----
+ /*	$NetBSD$	*/
+ 
+ /*
+  * Copyright (c) 1998 The NetBSD Foundation, Inc.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *	This product includes software developed by the NetBSD
+  *	Foundation, Inc. and its contributors.
+  * 4. Neither the name of The NetBSD Foundation nor the names of its
+  *    contributors may be used to endorse or promote products derived
+  *    from this software without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  * POSSIBILITY OF SUCH DAMAGE.
+  */
+ 
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/device.h>
+ 
+ #include <dev/pcmcia/pcmciachip.h>
+ #include <dev/ic/i82365reg.h>
+ #include <dev/ic/i82365var.h>
+ 
+ #include <dev/isa/isavar.h>
+ #include <dev/isa/i82365_isavar.h>
+ 
+ #include <dev/pci/pcivar.h>
+ #include <dev/pci/i82365_pcivar.h>
+ 
+ extern int pcic_isa_intr_alloc_mask;
+ 
+ void *
+ pcic_pci_machdep_intr_est(pc)
+ 	pci_chipset_tag_t pc;
+ {
+ 	return NULL;
+ }
+ 
+ void *
+ pcic_pci_machdep_pcic_intr_establish(sc, fct)
+ 	struct pcic_softc *sc;
+ 	int (*fct) __P((void *));
+ {
+ 	if (isa_intr_alloc(NULL, PCIC_CSC_INTR_IRQ_VALIDMASK &
+ 			   pcic_isa_intr_alloc_mask, IST_EDGE, &(sc->irq)))
+ 		return (NULL);
+ 	printf("%s: interrupting at irq %d\n", sc->dev.dv_xname, sc->irq);
+ 	return (isa_intr_establish(NULL, sc->irq, IST_EDGE, IPL_TTY,
+ 				   fct, sc));
+ }
+ 
+ void *
+ pcic_pci_machdep_chip_intr_establish(pch, pf, ipl, fct, arg)
+ 	pcmcia_chipset_handle_t pch;
+ 	struct pcmcia_function *pf;
+ 	int ipl;
+ 	int (*fct) __P((void *));
+ 	void *arg;
+ {
+ 	return (pcic_isa_chip_intr_establish(pch, pf, ipl, fct, arg));
+ }
+ 
+ void
+ pcic_pci_machdep_chip_intr_disestablish(pch, ih)
+ 	pcmcia_chipset_handle_t pch;
+ 	void *ih;
+ {
+ 	pcic_isa_chip_intr_disestablish(pch, ih);
+ }

>Audit-Trail:
>Unformatted: