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