Home | History | Annotate | Line # | Download | only in pci
pcib.c revision 1.5
      1  1.5  thorpej /*	$NetBSD: pcib.c,v 1.5 2001/06/15 04:01:41 thorpej Exp $	*/
      2  1.1  thorpej 
      3  1.1  thorpej /*-
      4  1.1  thorpej  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
      5  1.1  thorpej  * All rights reserved.
      6  1.1  thorpej  *
      7  1.1  thorpej  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  thorpej  * by Jason R. Thorpe.
      9  1.1  thorpej  *
     10  1.1  thorpej  * Redistribution and use in source and binary forms, with or without
     11  1.1  thorpej  * modification, are permitted provided that the following conditions
     12  1.1  thorpej  * are met:
     13  1.1  thorpej  * 1. Redistributions of source code must retain the above copyright
     14  1.1  thorpej  *    notice, this list of conditions and the following disclaimer.
     15  1.1  thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  thorpej  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  thorpej  *    documentation and/or other materials provided with the distribution.
     18  1.1  thorpej  * 3. All advertising materials mentioning features or use of this software
     19  1.1  thorpej  *    must display the following acknowledgement:
     20  1.1  thorpej  *	This product includes software developed by the NetBSD
     21  1.1  thorpej  *	Foundation, Inc. and its contributors.
     22  1.1  thorpej  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.1  thorpej  *    contributors may be used to endorse or promote products derived
     24  1.1  thorpej  *    from this software without specific prior written permission.
     25  1.1  thorpej  *
     26  1.1  thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.1  thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.1  thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.1  thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.1  thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.1  thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.1  thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.1  thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.1  thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.1  thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.1  thorpej  * POSSIBILITY OF SUCH DAMAGE.
     37  1.1  thorpej  */
     38  1.1  thorpej 
     39  1.1  thorpej #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     40  1.1  thorpej 
     41  1.5  thorpej __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.5 2001/06/15 04:01:41 thorpej Exp $");
     42  1.1  thorpej 
     43  1.1  thorpej #include "opt_algor_p5064.h"
     44  1.1  thorpej #include "opt_algor_p6032.h"
     45  1.1  thorpej 
     46  1.1  thorpej #include <sys/param.h>
     47  1.1  thorpej #include <sys/systm.h>
     48  1.1  thorpej #include <sys/kernel.h>
     49  1.1  thorpej #include <sys/device.h>
     50  1.1  thorpej #include <sys/malloc.h>
     51  1.1  thorpej 
     52  1.1  thorpej #include <machine/intr.h>
     53  1.1  thorpej #include <machine/bus.h>
     54  1.1  thorpej 
     55  1.3  thorpej #include <dev/isa/isareg.h>
     56  1.1  thorpej #include <dev/isa/isavar.h>
     57  1.1  thorpej 
     58  1.1  thorpej #include <dev/pci/pcireg.h>
     59  1.1  thorpej #include <dev/pci/pcivar.h>
     60  1.1  thorpej #include <dev/pci/pcidevs.h>
     61  1.1  thorpej 
     62  1.1  thorpej #ifdef ALGOR_P5064
     63  1.1  thorpej #include <algor/algor/algor_p5064var.h>
     64  1.1  thorpej #endif
     65  1.1  thorpej 
     66  1.1  thorpej #ifdef ALGOR_P6032
     67  1.1  thorpej #include <algor/algor/algor_p6032var.h>
     68  1.1  thorpej #endif
     69  1.1  thorpej 
     70  1.3  thorpej const char *pcib_intrnames[16] = {
     71  1.3  thorpej 	"irq 0",
     72  1.3  thorpej 	"irq 1",
     73  1.3  thorpej 	"irq 2",
     74  1.3  thorpej 	"irq 3",
     75  1.3  thorpej 	"irq 4",
     76  1.3  thorpej 	"irq 5",
     77  1.3  thorpej 	"irq 6",
     78  1.3  thorpej 	"irq 7",
     79  1.3  thorpej 	"irq 8",
     80  1.3  thorpej 	"irq 9",
     81  1.3  thorpej 	"irq 10",
     82  1.3  thorpej 	"irq 11",
     83  1.3  thorpej 	"irq 12",
     84  1.3  thorpej 	"irq 13",
     85  1.3  thorpej 	"irq 14",
     86  1.3  thorpej 	"irq 15",
     87  1.3  thorpej };
     88  1.3  thorpej 
     89  1.3  thorpej struct pcib_intrhead {
     90  1.3  thorpej 	LIST_HEAD(, algor_intrhand) intr_q;
     91  1.3  thorpej 	struct evcnt intr_count;
     92  1.3  thorpej 	int intr_type;
     93  1.3  thorpej };
     94  1.1  thorpej 
     95  1.1  thorpej struct pcib_softc {
     96  1.1  thorpej 	struct device	sc_dev;
     97  1.3  thorpej 
     98  1.3  thorpej 	bus_space_tag_t	sc_iot;
     99  1.3  thorpej 	bus_space_handle_t sc_ioh_icu1;
    100  1.3  thorpej 	bus_space_handle_t sc_ioh_icu2;
    101  1.3  thorpej 	bus_space_handle_t sc_ioh_elcr;
    102  1.3  thorpej 
    103  1.3  thorpej 	struct algor_isa_chipset sc_ic;
    104  1.3  thorpej 
    105  1.3  thorpej 	struct pcib_intrhead sc_intrtab[16];
    106  1.3  thorpej 
    107  1.3  thorpej 	u_int16_t	sc_inten;
    108  1.3  thorpej 	u_int16_t	sc_elcr;
    109  1.3  thorpej 
    110  1.3  thorpej #if defined(ALGOR_P5064)
    111  1.3  thorpej 	isa_chipset_tag_t sc_parent_ic;
    112  1.3  thorpej 	u_int16_t	sc_reserved;
    113  1.3  thorpej #endif
    114  1.3  thorpej 
    115  1.3  thorpej 	void		*sc_ih;
    116  1.1  thorpej };
    117  1.1  thorpej 
    118  1.1  thorpej int	pcib_match(struct device *, struct cfdata *, void *);
    119  1.1  thorpej void	pcib_attach(struct device *, struct device *, void *);
    120  1.1  thorpej 
    121  1.1  thorpej struct cfattach pcib_ca = {
    122  1.1  thorpej 	sizeof(struct pcib_softc), pcib_match, pcib_attach,
    123  1.1  thorpej };
    124  1.1  thorpej 
    125  1.1  thorpej int	pcib_print(void *, const char *pnp);
    126  1.1  thorpej void	pcib_isa_attach_hook(struct device *, struct device *,
    127  1.1  thorpej 	    struct isabus_attach_args *);
    128  1.1  thorpej 
    129  1.3  thorpej int	pcib_intr(void *);
    130  1.3  thorpej 
    131  1.1  thorpej void	pcib_bridge_callback(struct device *);
    132  1.1  thorpej 
    133  1.3  thorpej const struct evcnt *pcib_isa_intr_evcnt(void *, int);
    134  1.3  thorpej void	*pcib_isa_intr_establish(void *, int, int, int,
    135  1.3  thorpej 	    int (*)(void *), void *);
    136  1.3  thorpej void	pcib_isa_intr_disestablish(void *, void *);
    137  1.3  thorpej int	pcib_isa_intr_alloc(void *, int, int, int *);
    138  1.3  thorpej 
    139  1.3  thorpej void	pcib_set_icus(struct pcib_softc *);
    140  1.3  thorpej 
    141  1.1  thorpej int
    142  1.1  thorpej pcib_match(struct device *parent, struct cfdata *match, void *aux)
    143  1.1  thorpej {
    144  1.1  thorpej 	struct pci_attach_args *pa = aux;
    145  1.1  thorpej 
    146  1.1  thorpej 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
    147  1.1  thorpej 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA)
    148  1.1  thorpej 		return (1);
    149  1.1  thorpej 
    150  1.1  thorpej 	return (0);
    151  1.1  thorpej }
    152  1.1  thorpej 
    153  1.1  thorpej void
    154  1.1  thorpej pcib_attach(struct device *parent, struct device *self, void *aux)
    155  1.1  thorpej {
    156  1.3  thorpej 	struct pcib_softc *sc = (void *) self;
    157  1.1  thorpej 	struct pci_attach_args *pa = aux;
    158  1.1  thorpej 	char devinfo[256];
    159  1.3  thorpej 	int i;
    160  1.1  thorpej 
    161  1.1  thorpej 	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
    162  1.1  thorpej 	printf(": %s (rev. 0x%02x)\n", devinfo,
    163  1.1  thorpej 	    PCI_REVISION(pa->pa_class));
    164  1.1  thorpej 
    165  1.3  thorpej 	sc->sc_iot = pa->pa_iot;
    166  1.3  thorpej 
    167  1.3  thorpej 	/*
    168  1.3  thorpej 	 * Map the PIC/ELCR registers.
    169  1.3  thorpej 	 */
    170  1.3  thorpej 	if (bus_space_map(sc->sc_iot, 0x4d0, 2, 0, &sc->sc_ioh_elcr) != 0)
    171  1.3  thorpej 		printf("%s: unable to map ELCR registers\n",
    172  1.3  thorpej 		    sc->sc_dev.dv_xname);
    173  1.3  thorpej 	if (bus_space_map(sc->sc_iot, IO_ICU1, 2, 0, &sc->sc_ioh_icu1) != 0)
    174  1.3  thorpej 		printf("%s: unable to map ICU1 registers\n",
    175  1.3  thorpej 		    sc->sc_dev.dv_xname);
    176  1.3  thorpej 	if (bus_space_map(sc->sc_iot, IO_ICU2, 2, 0, &sc->sc_ioh_icu2) != 0)
    177  1.3  thorpej 		printf("%s: unable to map ICU2 registers\n",
    178  1.3  thorpej 		    sc->sc_dev.dv_xname);
    179  1.3  thorpej 
    180  1.3  thorpej 	/*
    181  1.3  thorpej 	 * Initialize the 8259s.
    182  1.3  thorpej 	 */
    183  1.3  thorpej 
    184  1.3  thorpej 	/* ICW1: reset; program device, 4 bytes */
    185  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 0, 0x11);
    186  1.3  thorpej 
    187  1.3  thorpej 	/* ICW2: vector base address */
    188  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1, 32/*XXX*/);
    189  1.3  thorpej 
    190  1.3  thorpej 	/* ICW3: cascade mode */
    191  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1, 0x04);
    192  1.3  thorpej 
    193  1.3  thorpej 	/* ICW4: 8086 mode */
    194  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1, 0x01);
    195  1.3  thorpej 
    196  1.3  thorpej 	/* OCW1: mask all interrupts */
    197  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1,
    198  1.3  thorpej 	    ~sc->sc_inten & 0xff);
    199  1.3  thorpej 
    200  1.3  thorpej 	/* OCW3: enable special mask mode */
    201  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 0, 0x68);
    202  1.3  thorpej 
    203  1.3  thorpej 	/* OCW3: read IRR by default */
    204  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 0, 0x0a);
    205  1.3  thorpej 
    206  1.3  thorpej 
    207  1.3  thorpej 	/* ICW1: reset; program device, 4 bytes */
    208  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 0, 0x11);
    209  1.3  thorpej 
    210  1.3  thorpej 	/* ICW2: vector base address */
    211  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1, 32+8/*XXX*/);
    212  1.3  thorpej 
    213  1.3  thorpej 	/* ICW3: slave ID code */
    214  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1, 0x02);
    215  1.3  thorpej 
    216  1.3  thorpej 	/* ICW4: 8086 mode */
    217  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1, 0x01);
    218  1.3  thorpej 
    219  1.3  thorpej 	/* OCW1: mask all interrupts */
    220  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1,
    221  1.3  thorpej 	    (~sc->sc_inten >> 8) & 0xff);
    222  1.3  thorpej 
    223  1.3  thorpej 	/* OCW3: enable special mask mode */
    224  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 0, 0x68);
    225  1.3  thorpej 
    226  1.3  thorpej 	/* OCW3: read IRR by default */
    227  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 0, 0x0a);
    228  1.3  thorpej 
    229  1.3  thorpej 	/*
    230  1.3  thorpej 	 * Default all interrupts to edge-triggered.
    231  1.3  thorpej 	 */
    232  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
    233  1.3  thorpej 	    sc->sc_elcr & 0xff);
    234  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
    235  1.3  thorpej 	    (sc->sc_elcr >> 8) & 0xff);
    236  1.3  thorpej 
    237  1.3  thorpej #if defined(ALGOR_P5064)
    238  1.3  thorpej 	/*
    239  1.3  thorpej 	 * Some "ISA" interrupts are a little wacky, wired up directly
    240  1.3  thorpej 	 * to the P-5064 interrupt controller.
    241  1.3  thorpej 	 */
    242  1.3  thorpej 	sc->sc_reserved =
    243  1.3  thorpej 		(1 << 1) |
    244  1.3  thorpej 		(1 << 3) |
    245  1.3  thorpej 		(1 << 4) |
    246  1.3  thorpej 		(1 << 6) |
    247  1.3  thorpej 		(1 << 7) |
    248  1.3  thorpej 		(1 << 8) |
    249  1.3  thorpej 		(1 << 12) |
    250  1.3  thorpej 		(1 << 14) |
    251  1.3  thorpej 		(1 << 15);
    252  1.3  thorpej 
    253  1.3  thorpej 	sc->sc_parent_ic = &p5064_configuration.ac_ic;
    254  1.3  thorpej #endif /* ALGOR_P5064 */
    255  1.3  thorpej 
    256  1.3  thorpej 	/* Set up our ISA chipset. */
    257  1.3  thorpej 	sc->sc_ic.ic_v = sc;
    258  1.3  thorpej 	sc->sc_ic.ic_intr_evcnt = pcib_isa_intr_evcnt;
    259  1.3  thorpej 	sc->sc_ic.ic_intr_establish = pcib_isa_intr_establish;
    260  1.3  thorpej 	sc->sc_ic.ic_intr_disestablish = pcib_isa_intr_disestablish;
    261  1.3  thorpej 	sc->sc_ic.ic_intr_alloc = pcib_isa_intr_alloc;
    262  1.3  thorpej 
    263  1.3  thorpej 	/* Initialize our interrupt table. */
    264  1.3  thorpej 	for (i = 0; i < 16; i++) {
    265  1.3  thorpej 		LIST_INIT(&sc->sc_intrtab[i].intr_q);
    266  1.3  thorpej 		evcnt_attach_dynamic(&sc->sc_intrtab[i].intr_count,
    267  1.3  thorpej 		    EVCNT_TYPE_INTR, NULL, "pcib", pcib_intrnames[i]);
    268  1.3  thorpej 		sc->sc_intrtab[i].intr_type = IST_NONE;
    269  1.3  thorpej 	}
    270  1.3  thorpej 
    271  1.3  thorpej 	/* Hook up our interrupt handler. */
    272  1.3  thorpej #if defined(ALGOR_P5064)
    273  1.5  thorpej 	sc->sc_ih = (*algor_intr_establish)(P5064_IRQ_ISABRIDGE,
    274  1.5  thorpej 	    pcib_intr, sc);
    275  1.3  thorpej #elif defined(ALGOR_P6032)
    276  1.5  thorpej 	sc->sc_ih = (*algor_intr_establish)(XXX,
    277  1.3  thorpej 	    pcib_intr, sc);
    278  1.3  thorpej #endif
    279  1.3  thorpej 	if (sc->sc_ih == NULL)
    280  1.3  thorpej 		printf("%s: WARNING: unable to register interrupt handler\n",
    281  1.3  thorpej 		    sc->sc_dev.dv_xname);
    282  1.3  thorpej 
    283  1.1  thorpej 	config_defer(self, pcib_bridge_callback);
    284  1.1  thorpej }
    285  1.1  thorpej 
    286  1.1  thorpej void
    287  1.1  thorpej pcib_bridge_callback(self)
    288  1.1  thorpej 	struct device *self;
    289  1.1  thorpej {
    290  1.1  thorpej 	struct pcib_softc *sc = (struct pcib_softc *)self;
    291  1.1  thorpej 	struct isabus_attach_args iba;
    292  1.1  thorpej 
    293  1.1  thorpej 	memset(&iba, 0, sizeof(iba));
    294  1.1  thorpej 
    295  1.1  thorpej 	iba.iba_busname = "isa";
    296  1.2  thorpej #if defined(ALGOR_P5064)
    297  1.1  thorpej 	    {
    298  1.1  thorpej 		struct p5064_config *acp = &p5064_configuration;
    299  1.1  thorpej 
    300  1.1  thorpej 		iba.iba_iot = &acp->ac_iot;
    301  1.1  thorpej 		iba.iba_memt = &acp->ac_memt;
    302  1.1  thorpej 		iba.iba_dmat = &acp->ac_isa_dmat;
    303  1.1  thorpej 		iba.iba_ic = &acp->ac_ic;
    304  1.1  thorpej 	    }
    305  1.1  thorpej #elif defined(ALGOR_P6032)
    306  1.1  thorpej 	    {
    307  1.1  thorpej 		/* XXX */
    308  1.1  thorpej 	    }
    309  1.1  thorpej #endif
    310  1.1  thorpej 
    311  1.1  thorpej 	iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook;
    312  1.1  thorpej 
    313  1.1  thorpej 	(void) config_found(&sc->sc_dev, &iba, pcib_print);
    314  1.1  thorpej }
    315  1.1  thorpej 
    316  1.1  thorpej int
    317  1.1  thorpej pcib_print(void *aux, const char *pnp)
    318  1.1  thorpej {
    319  1.1  thorpej 	struct isabus_attach_args *iba;
    320  1.1  thorpej 
    321  1.1  thorpej 	if (pnp)
    322  1.1  thorpej 		printf("%s at %s", iba->iba_busname, pnp);
    323  1.1  thorpej 	return (UNCONF);
    324  1.1  thorpej }
    325  1.1  thorpej 
    326  1.1  thorpej void
    327  1.1  thorpej pcib_isa_attach_hook(struct device *parent, struct device *self,
    328  1.1  thorpej     struct isabus_attach_args *iba)
    329  1.1  thorpej {
    330  1.1  thorpej 
    331  1.1  thorpej 	/* Nothing to do. */
    332  1.3  thorpej }
    333  1.3  thorpej 
    334  1.3  thorpej void
    335  1.3  thorpej pcib_set_icus(struct pcib_softc *sc)
    336  1.3  thorpej {
    337  1.3  thorpej 
    338  1.3  thorpej 	/* Enable the cascade IRQ (2) if 8-15 is enabled. */
    339  1.3  thorpej 	if (sc->sc_inten & 0xff00)
    340  1.3  thorpej 		sc->sc_inten |= (1 << 2);
    341  1.3  thorpej 	else
    342  1.3  thorpej 		sc->sc_inten &= ~(1 << 2);
    343  1.3  thorpej 
    344  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 1,
    345  1.3  thorpej 	    ~sc->sc_inten & 0xff);
    346  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, 1,
    347  1.3  thorpej 	    (~sc->sc_inten >> 8) & 0xff);
    348  1.3  thorpej 
    349  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
    350  1.3  thorpej 	    sc->sc_elcr & 0xff);
    351  1.3  thorpej 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
    352  1.3  thorpej 	    (sc->sc_elcr >> 8) & 0xff);
    353  1.3  thorpej }
    354  1.3  thorpej 
    355  1.3  thorpej int
    356  1.3  thorpej pcib_intr(void *v)
    357  1.3  thorpej {
    358  1.3  thorpej 	struct pcib_softc *sc = v;
    359  1.3  thorpej 	struct algor_intrhand *ih;
    360  1.3  thorpej 	u_int16_t ipending;
    361  1.3  thorpej 	int i;
    362  1.3  thorpej 
    363  1.3  thorpej 	ipending = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, 0) |
    364  1.3  thorpej 	    (bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2, 0) << 8);
    365  1.3  thorpej 	ipending &= (sc->sc_inten & ~0x02);
    366  1.3  thorpej 	if (ipending == 0)
    367  1.3  thorpej 		return (0);
    368  1.3  thorpej 
    369  1.3  thorpej 	for (i = 0; i < 16; i++) {
    370  1.3  thorpej 		if ((ipending & (1 << i)) == 0)
    371  1.3  thorpej 			continue;
    372  1.3  thorpej 		sc->sc_intrtab[i].intr_count.ev_count++;
    373  1.3  thorpej 		for (ih = LIST_FIRST(&sc->sc_intrtab[i].intr_q);
    374  1.3  thorpej 		     ih != NULL; ih = LIST_NEXT(ih, ih_q)) {
    375  1.3  thorpej 			(*ih->ih_func)(ih->ih_arg);
    376  1.3  thorpej 		}
    377  1.3  thorpej 
    378  1.3  thorpej 		/* Send a specific EOI to the 8259. */
    379  1.3  thorpej 		if (i > 7)
    380  1.3  thorpej 			bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
    381  1.3  thorpej 			    0, 0x20 | (i & 0x07));
    382  1.3  thorpej 		bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, 0,
    383  1.3  thorpej 		    0x20 | (i > 7 ? 2 : i));
    384  1.3  thorpej 	}
    385  1.3  thorpej 
    386  1.3  thorpej 	return (1);
    387  1.3  thorpej }
    388  1.3  thorpej 
    389  1.3  thorpej const struct evcnt *
    390  1.3  thorpej pcib_isa_intr_evcnt(void *v, int irq)
    391  1.3  thorpej {
    392  1.3  thorpej 	struct pcib_softc *sc = v;
    393  1.4  thorpej 
    394  1.4  thorpej #if defined(ALGOR_P5064)
    395  1.4  thorpej 	if (sc->sc_reserved & (1 << irq))
    396  1.4  thorpej 		return (isa_intr_evcnt(sc->sc_parent_ic, irq));
    397  1.4  thorpej #endif
    398  1.3  thorpej 
    399  1.3  thorpej 	return (&sc->sc_intrtab[irq].intr_count);
    400  1.3  thorpej }
    401  1.3  thorpej 
    402  1.3  thorpej void *
    403  1.3  thorpej pcib_isa_intr_establish(void *v, int irq, int type, int level,
    404  1.3  thorpej     int (*func)(void *), void *arg)
    405  1.3  thorpej {
    406  1.3  thorpej 	struct pcib_softc *sc = v;
    407  1.3  thorpej 	struct algor_intrhand *ih;
    408  1.3  thorpej 	int s;
    409  1.3  thorpej 
    410  1.3  thorpej 	if (irq > 15 || irq == 2 || type == IST_NONE)
    411  1.3  thorpej 		panic("pcib_isa_intr_establish: bad irq or type");
    412  1.3  thorpej 
    413  1.3  thorpej #if defined(ALGOR_P5064)
    414  1.3  thorpej 	if (sc->sc_reserved & (1 << irq)) {
    415  1.3  thorpej 		ih = isa_intr_establish(sc->sc_parent_ic, irq, type,
    416  1.3  thorpej 		    level, func, arg);
    417  1.3  thorpej 		if (ih != NULL)
    418  1.3  thorpej 			ih->ih_irq = irq;
    419  1.3  thorpej 	}
    420  1.3  thorpej #endif
    421  1.3  thorpej 
    422  1.3  thorpej 	switch (sc->sc_intrtab[irq].intr_type) {
    423  1.3  thorpej 	case IST_NONE:
    424  1.3  thorpej 		sc->sc_intrtab[irq].intr_type = type;
    425  1.3  thorpej 		break;
    426  1.3  thorpej 
    427  1.3  thorpej 	case IST_EDGE:
    428  1.3  thorpej 	case IST_LEVEL:
    429  1.3  thorpej 		if (type == sc->sc_intrtab[irq].intr_type)
    430  1.3  thorpej 			break;
    431  1.3  thorpej 		/* FALLTHROUGH */
    432  1.3  thorpej 	case IST_PULSE:
    433  1.3  thorpej 		/*
    434  1.3  thorpej 		 * We can't share interrupts in this case.
    435  1.3  thorpej 		 */
    436  1.3  thorpej 		return (NULL);
    437  1.3  thorpej 	}
    438  1.3  thorpej 
    439  1.3  thorpej 	ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
    440  1.3  thorpej 	if (ih == NULL)
    441  1.3  thorpej 		return (NULL);
    442  1.3  thorpej 
    443  1.3  thorpej 	ih->ih_func = func;
    444  1.3  thorpej 	ih->ih_arg = arg;
    445  1.3  thorpej 	ih->ih_irq = irq;
    446  1.3  thorpej 	ih->ih_irqmap = NULL;
    447  1.3  thorpej 
    448  1.3  thorpej 	s = splhigh();
    449  1.3  thorpej 
    450  1.3  thorpej 	/* Insert the handler into the table. */
    451  1.3  thorpej 	LIST_INSERT_HEAD(&sc->sc_intrtab[irq].intr_q, ih, ih_q);
    452  1.3  thorpej 	sc->sc_intrtab[irq].intr_type = type;
    453  1.3  thorpej 
    454  1.3  thorpej 	/* Enable it, set trigger mode. */
    455  1.3  thorpej 	sc->sc_inten |= (1 << irq);
    456  1.3  thorpej 	if (sc->sc_intrtab[irq].intr_type == IST_LEVEL)
    457  1.3  thorpej 		sc->sc_elcr |= (1 << irq);
    458  1.3  thorpej 	else
    459  1.3  thorpej 		sc->sc_elcr &= ~(1 << irq);
    460  1.3  thorpej 
    461  1.3  thorpej 	pcib_set_icus(sc);
    462  1.3  thorpej 
    463  1.3  thorpej 	splx(s);
    464  1.3  thorpej 
    465  1.3  thorpej 	return (ih);
    466  1.3  thorpej }
    467  1.3  thorpej 
    468  1.3  thorpej void
    469  1.3  thorpej pcib_isa_intr_disestablish(void *v, void *arg)
    470  1.3  thorpej {
    471  1.3  thorpej 	struct pcib_softc *sc = v;
    472  1.3  thorpej 	struct algor_intrhand *ih = arg;
    473  1.3  thorpej 	int s;
    474  1.3  thorpej 
    475  1.3  thorpej #if defined(ALGOR_P5064)
    476  1.3  thorpej 	if (sc->sc_reserved & (1 << ih->ih_irq)) {
    477  1.3  thorpej 		isa_intr_disestablish(sc->sc_parent_ic, ih);
    478  1.3  thorpej 		return;
    479  1.3  thorpej 	}
    480  1.3  thorpej #endif
    481  1.3  thorpej 
    482  1.3  thorpej 	s = splhigh();
    483  1.3  thorpej 
    484  1.3  thorpej 	LIST_REMOVE(ih, ih_q);
    485  1.3  thorpej 
    486  1.3  thorpej 	/* If there are no more handlers on this IRQ, disable it. */
    487  1.3  thorpej 	if (LIST_FIRST(&sc->sc_intrtab[ih->ih_irq].intr_q) == NULL) {
    488  1.3  thorpej 		sc->sc_inten &= ~(1 << ih->ih_irq);
    489  1.3  thorpej 		pcib_set_icus(sc);
    490  1.3  thorpej 	}
    491  1.3  thorpej 
    492  1.3  thorpej 	splx(s);
    493  1.3  thorpej 
    494  1.3  thorpej 	free(ih, M_DEVBUF);
    495  1.3  thorpej }
    496  1.3  thorpej 
    497  1.3  thorpej int
    498  1.3  thorpej pcib_isa_intr_alloc(void *v, int mask, int type, int *irq)
    499  1.3  thorpej {
    500  1.3  thorpej 	struct pcib_softc *sc = v;
    501  1.3  thorpej 	int i, tmp, bestirq, count;
    502  1.3  thorpej 	struct algor_intrhand *ih;
    503  1.3  thorpej 
    504  1.3  thorpej 	if (type == IST_NONE)
    505  1.3  thorpej 		panic("pcib_intr_alloc: bogus type");
    506  1.3  thorpej 
    507  1.3  thorpej 	bestirq = -1;
    508  1.3  thorpej 	count = -1;
    509  1.3  thorpej 
    510  1.3  thorpej #if defined(ALGOR_P5064)
    511  1.3  thorpej 	mask &= ~sc->sc_reserved;
    512  1.3  thorpej #endif
    513  1.3  thorpej 
    514  1.3  thorpej 	for (i = 0; i < 16; i++) {
    515  1.3  thorpej 		if (i == 2 || (mask & (1 << i)) == 0)
    516  1.3  thorpej 			continue;
    517  1.3  thorpej 
    518  1.3  thorpej 		switch (sc->sc_intrtab[i].intr_type) {
    519  1.3  thorpej 		case IST_NONE:
    520  1.3  thorpej 			/*
    521  1.3  thorpej 			 * If nothing's using the IRQ, just return it.
    522  1.3  thorpej 			 */
    523  1.3  thorpej 			*irq = i;
    524  1.3  thorpej 			return (0);
    525  1.3  thorpej 
    526  1.3  thorpej 		case IST_EDGE:
    527  1.3  thorpej 		case IST_LEVEL:
    528  1.3  thorpej 			if (type != sc->sc_intrtab[i].intr_type)
    529  1.3  thorpej 				continue;
    530  1.3  thorpej 			/*
    531  1.3  thorpej 			 * If the IRQ is sharable, count the number of
    532  1.3  thorpej 			 * other handlers, and if it's smaller than the
    533  1.3  thorpej 			 * last IRQ like this, remember it.
    534  1.3  thorpej 			 */
    535  1.3  thorpej 			tmp = 0;
    536  1.3  thorpej 			for (ih = LIST_FIRST(&sc->sc_intrtab[i].intr_q);
    537  1.3  thorpej 			     ih != NULL; ih = LIST_NEXT(ih, ih_q))
    538  1.3  thorpej 				tmp++;
    539  1.3  thorpej 			if (bestirq == -1 || count > tmp) {
    540  1.3  thorpej 				bestirq = i;
    541  1.3  thorpej 				count = tmp;
    542  1.3  thorpej 			}
    543  1.3  thorpej 			break;
    544  1.3  thorpej 
    545  1.3  thorpej 		case IST_PULSE:
    546  1.3  thorpej 			/* This just isn't sharable. */
    547  1.3  thorpej 			continue;
    548  1.3  thorpej 		}
    549  1.3  thorpej 	}
    550  1.3  thorpej 
    551  1.3  thorpej 	if (bestirq == -1)
    552  1.3  thorpej 		return (1);
    553  1.3  thorpej 
    554  1.3  thorpej 	*irq = bestirq;
    555  1.3  thorpej 	return (0);
    556  1.1  thorpej }
    557