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