Home | History | Annotate | Line # | Download | only in pci
      1 /*	$NetBSD: pcib.c,v 1.29 2026/05/10 14:56:40 tls Exp $	*/
      2 
      3 /*
      4  * Copyright 2002 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Simon Burge for Wasabi Systems, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *      This product includes software developed for the NetBSD Project by
     20  *      Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 #include <sys/cdefs.h>
     39 __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.29 2026/05/10 14:56:40 tls Exp $");
     40 
     41 #include <sys/param.h>
     42 #include <sys/systm.h>
     43 #include <sys/kernel.h>
     44 #include <sys/device.h>
     45 #include <sys/endian.h>
     46 #include <sys/kmem.h>
     47 
     48 #include <uvm/uvm_extern.h>
     49 
     50 #include <sys/bus.h>
     51 #include <evbmips/malta/maltareg.h>
     52 #include <evbmips/malta/maltavar.h>
     53 #include <evbmips/malta/dev/gtreg.h>
     54 #include <evbmips/malta/pci/pcibvar.h>
     55 
     56 #include <dev/isa/isareg.h>
     57 #include <dev/isa/isavar.h>
     58 
     59 #include <dev/pci/pcireg.h>
     60 #include <dev/pci/pcivar.h>
     61 #include <dev/pci/pcidevs.h>
     62 
     63 #include <dev/ic/i8259reg.h>
     64 
     65 
     66 #define	ICU_LEN		16	/* number of ISA IRQs */
     67 
     68 const char * const isa_intrnames[ICU_LEN] = {
     69 	"timer",
     70 	"keyboard",
     71 	"reserved",		/* by South Bridge (for cascading) */
     72 	"com1",
     73 	"com0",
     74 	"not used",
     75 	"floppy",
     76 	"centronics",
     77 	"mcclock",
     78 	"i2c",
     79 	"pci A,B",		/* PCI slots 1..4, ethernet */
     80 	"pci C,D",		/* PCI slots 1..4, audio, usb */
     81 	"mouse",
     82 	"reserved",
     83 	"ide primary",
     84 	"ide secondary",	/* and compact flash connector */
     85 };
     86 
     87 struct pcib_intrhead {
     88 	LIST_HEAD(, evbmips_intrhand) intr_q;
     89 	struct evcnt intr_count;
     90 	int intr_type;
     91 };
     92 
     93 struct pcib_softc {
     94 	device_t sc_dev;
     95 
     96 	bus_space_tag_t sc_memt;
     97 	bus_space_tag_t sc_iot;
     98 	bus_space_handle_t sc_ioh_icu1;
     99 	bus_space_handle_t sc_ioh_icu2;
    100 	bus_space_handle_t sc_ioh_elcr;
    101 
    102 	bus_dma_tag_t sc_dmat;
    103 
    104 	struct mips_isa_chipset sc_ic;
    105 
    106 	struct pcib_intrhead sc_intrtab[ICU_LEN];
    107 
    108 	u_int16_t	sc_imask;
    109 	u_int16_t	sc_elcr;
    110 
    111 	u_int16_t	sc_reserved;
    112 
    113 	void *sc_ih;
    114 };
    115 
    116 /*
    117  * XXX
    118  *	There is only one pci-isa bridge, and all external interrupts
    119  *	are routed through it, so we need to remember the softc when
    120  *	called from other interrupt handling code.
    121  */
    122 static struct pcib_softc *my_sc;
    123 struct mips_isa_chipset *pcib_ic;
    124 
    125 static int	pcib_match(device_t, cfdata_t, void *);
    126 static void	pcib_attach(device_t, device_t, void *);
    127 static int	pcib_intr(void *v);
    128 static void	pcib_bridge_callback(device_t);
    129 static void	pcib_set_icus(struct pcib_softc *sc);
    130 static void	pcib_cleanup(void *arg);
    131 
    132 static const struct evcnt *
    133 		pcib_isa_intr_evcnt(void *, int);
    134 static void	*pcib_isa_intr_establish(void *, int, int, int,
    135 		    int (*)(void *), void *);
    136 static void	pcib_isa_intr_disestablish(void *, void *);
    137 static void	pcib_isa_attach_hook(device_t, device_t,
    138 		    struct isabus_attach_args *);
    139 static void	pcib_isa_detach_hook(isa_chipset_tag_t, device_t);
    140 static int	pcib_isa_intr_alloc(void *, int, int, int *);
    141 static const char *
    142 		pcib_isa_intr_string(void *, int, char *, size_t);
    143 
    144 CFATTACH_DECL_NEW(pcib, sizeof(struct pcib_softc),
    145     pcib_match, pcib_attach, NULL, NULL);
    146 
    147 static int
    148 malta_isa_dma_may_bounce(bus_dma_tag_t t, bus_dmamap_t map, int flags,
    149 	int *cookieflagsp)
    150 {
    151         if (((map->_dm_size / PAGE_SIZE) + 1) > map->_dm_segcnt)
    152                 *cookieflagsp |= _BUS_DMA_MIGHT_NEED_BOUNCE;
    153 
    154 	return 0;
    155 }
    156 
    157 static int
    158 pcib_match(device_t parent, cfdata_t match, void *aux)
    159 {
    160 	struct pci_attach_args *pa = aux;
    161 
    162 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
    163 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA)
    164 		return (1);
    165 
    166 	return (0);
    167 }
    168 
    169 static void
    170 pcib_attach(device_t parent, device_t self, void *aux)
    171 {
    172 	struct pci_attach_args * const pa = aux;
    173 	struct pcib_softc * const sc = device_private(self);
    174 	const char * const xname = device_xname(self);
    175 	char devinfo[256];
    176 	int error;
    177 
    178 	printf("\n");
    179 
    180 	if (my_sc != NULL)
    181 		panic("pcib_attach: already attached!");
    182 	my_sc = sc;
    183 	sc->sc_dev = self;
    184 
    185 	/*
    186 	 * Just print out a description and defer configuration
    187 	 * until all PCI devices have been attached.
    188 	 */
    189 	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
    190 	printf("%s: %s, (rev . 0x%02x)\n", xname, devinfo,
    191 	    PCI_REVISION(pa->pa_class));
    192 
    193 	sc->sc_memt = pa->pa_memt;
    194 	sc->sc_iot = pa->pa_iot;
    195 
    196 	/*
    197 	 * Initialize the DMA tag used for ISA DMA.
    198 	 */
    199 	error = bus_dmatag_subregion(pa->pa_dmat, MALTA_DMA_ISA_PHYSBASE,
    200 	    MALTA_DMA_ISA_PHYSBASE + MALTA_DMA_ISA_SIZE - 1, &sc->sc_dmat, 0);
    201 	if (error)
    202 		panic("malta_dma_init: failed to create ISA dma tag: %d",
    203 		    error);
    204 	sc->sc_dmat->_may_bounce = malta_isa_dma_may_bounce;
    205 
    206 	/*
    207 	 * Map the PIC/ELCR registers.
    208 	 */
    209 	if (bus_space_map(sc->sc_iot, 0x4d0, 2, 0, &sc->sc_ioh_elcr) != 0)
    210 		printf("%s: unable to map ELCR registers\n", xname);
    211 	if (bus_space_map(sc->sc_iot, IO_ICU1, 2, 0, &sc->sc_ioh_icu1) != 0)
    212 		printf("%s: unable to map ICU1 registers\n", xname);
    213 	if (bus_space_map(sc->sc_iot, IO_ICU2, 2, 0, &sc->sc_ioh_icu2) != 0)
    214 		printf("%s: unable to map ICU2 registers\n", xname);
    215 
    216 	/* All interrupts default to "masked off". */
    217 	sc->sc_imask = 0xffff;
    218 
    219 	/* All interrupts default to edge-triggered. */
    220 	sc->sc_elcr = 0;
    221 
    222 	/*
    223 	 * Initialize the 8259s.
    224 	 */
    225 	/* reset, program device, 4 bytes */
    226 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW1,
    227 	    ICW1_SELECT | ICW1_IC4);
    228 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW2,
    229 	    ICW2_VECTOR(0)/*XXX*/);
    230 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW3,
    231 	    ICW3_CASCADE(2));
    232 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW4,
    233 	    ICW4_8086);
    234 
    235 	/* mask all interrupts */
    236 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1,
    237 	    sc->sc_imask & 0xff);
    238 
    239 	/* enable special mask mode */
    240 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
    241 	    OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
    242 
    243 	/* read IRR by default */
    244 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
    245 	    OCW3_SELECT | OCW3_RR);
    246 
    247 	/* reset, program device, 4 bytes */
    248 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW1,
    249 	    ICW1_SELECT | ICW1_IC4);
    250 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW2,
    251 	    ICW2_VECTOR(0)/*XXX*/);
    252 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW3,
    253 	    ICW3_CASCADE(2));
    254 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW4,
    255 	    ICW4_8086);
    256 
    257 	/* mask all interrupts */
    258 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
    259 	    sc->sc_imask & 0xff);
    260 
    261 	/* enable special mask mode */
    262 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3,
    263 	    OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
    264 
    265 	/* read IRR by default */
    266 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3,
    267 	    OCW3_SELECT | OCW3_RR);
    268 
    269 	/*
    270 	 * Default all interrupts to edge-triggered.
    271 	 */
    272 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
    273 	    sc->sc_elcr & 0xff);
    274 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
    275 	    (sc->sc_elcr >> 8) & 0xff);
    276 
    277 	/*
    278 	 * Some ISA interrupts are reserved for devices that
    279 	 * we know are hard-wired to certain IRQs.
    280 	 */
    281 	sc->sc_reserved =
    282 		(1U << 0) |     /* timer */
    283 		(1U << 1) |     /* keyboard controller (keyboard) */
    284 		(1U << 2) |     /* PIC cascade */
    285 		(1U << 3) |     /* COM 2 */
    286 		(1U << 4) |     /* COM 1 */
    287 		(1U << 6) |     /* floppy */
    288 		(1U << 7) |     /* centronics */
    289 		(1U << 8) |     /* RTC */
    290 		(1U << 9) |	/* I2C */
    291 		(1U << 12) |    /* keyboard controller (mouse) */
    292 		(1U << 14) |    /* IDE primary */
    293 		(1U << 15);     /* IDE secondary */
    294 
    295 	/* Set up our ISA chipset. */
    296 	sc->sc_ic.ic_v = sc;
    297 	sc->sc_ic.ic_intr_evcnt = pcib_isa_intr_evcnt;
    298 	sc->sc_ic.ic_intr_establish = pcib_isa_intr_establish;
    299 	sc->sc_ic.ic_intr_disestablish = pcib_isa_intr_disestablish;
    300 	sc->sc_ic.ic_intr_alloc = pcib_isa_intr_alloc;
    301 	sc->sc_ic.ic_intr_string = pcib_isa_intr_string;
    302 
    303 	pcib_ic = &sc->sc_ic;	/* XXX for external use */
    304 
    305 	/* Initialize our interrupt table. */
    306 	for (size_t i = 0; i < ICU_LEN; i++) {
    307 #if 0
    308 		char irqstr[8];		/* 4 + 2 + NULL + sanity */
    309 
    310 		snprintf(irqstr, sizeof(irqstr), "irq %d", i);
    311 		evcnt_attach_dynamic(&sc->sc_intrtab[i].intr_count,
    312 		    EVCNT_TYPE_INTR, NULL, "pcib", irqstr);
    313 #else
    314 		evcnt_attach_dynamic(&sc->sc_intrtab[i].intr_count,
    315 		    EVCNT_TYPE_INTR, NULL, "pcib", isa_intrnames[i]);
    316 #endif
    317 		LIST_INIT(&sc->sc_intrtab[i].intr_q);
    318 		sc->sc_intrtab[i].intr_type = IST_NONE;
    319 	}
    320 
    321 	/* Hook up our interrupt handler. */
    322 	sc->sc_ih = evbmips_intr_establish(MALTA_SOUTHBRIDGE_INTR, pcib_intr, sc);
    323 	if (sc->sc_ih == NULL)
    324 		printf("%s: WARNING: unable to register interrupt handler\n",
    325 		    xname);
    326 
    327 
    328 	/*
    329 	 * Disable ISA interrupts before returning to YAMON.
    330 	 */
    331 	if (shutdownhook_establish(pcib_cleanup, sc) == NULL)
    332 		panic("pcib_attach: could not establish shutdown hook");
    333 
    334 	config_defer(self, pcib_bridge_callback);
    335 }
    336 
    337 static void
    338 pcib_bridge_callback(device_t self)
    339 {
    340 	struct pcib_softc *sc = device_private(self);
    341 	struct isabus_attach_args iba;
    342 
    343 	/*
    344 	 * Attach the ISA bus behind this bridge.
    345 	 */
    346 	memset(&iba, 0, sizeof(iba));
    347 
    348 	iba.iba_iot = sc->sc_iot;
    349 	iba.iba_memt = sc->sc_memt;
    350 	iba.iba_dmat = sc->sc_dmat;
    351 
    352 	iba.iba_ic = &sc->sc_ic;
    353 	iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook;
    354 	iba.iba_ic->ic_detach_hook = pcib_isa_detach_hook;
    355 
    356 	isabus_attach(self, &iba);
    357 }
    358 
    359 static void
    360 pcib_isa_attach_hook(device_t parent, device_t self,
    361     struct isabus_attach_args *iba)
    362 {
    363 
    364 	/* Nothing to do. */
    365 }
    366 
    367 static void
    368 pcib_isa_detach_hook(isa_chipset_tag_t ic, device_t self)
    369 {
    370 
    371 	/* Nothing to do. */
    372 }
    373 
    374 static void
    375 pcib_set_icus(struct pcib_softc *sc)
    376 {
    377 
    378 	/* Enable the cascade IRQ (2) if 8-15 is enabled. */
    379 	if ((sc->sc_imask & 0xff00) != 0xff00)
    380 		sc->sc_imask &= ~(1U << 2);
    381 	else
    382 		sc->sc_imask |= (1U << 2);
    383 
    384 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1,
    385 	    sc->sc_imask & 0xff);
    386 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
    387 	    (sc->sc_imask >> 8) & 0xff);
    388 
    389 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
    390 	    sc->sc_elcr & 0xff);
    391 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
    392 	    (sc->sc_elcr >> 8) & 0xff);
    393 }
    394 
    395 static int
    396 pcib_intr(void *v)
    397 {
    398 	struct pcib_softc *sc = v;
    399 	struct evbmips_intrhand *ih;
    400 	int irq;
    401 
    402 	for (;;) {
    403 #if 1
    404 		bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
    405 		    OCW3_SELECT | OCW3_POLL);
    406 		irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3);
    407 		if ((irq & OCW3_POLL_PENDING) == 0)
    408 			return (1);
    409 
    410 		irq = OCW3_POLL_IRQ(irq);
    411 
    412 		if (irq == 2) {
    413 			bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
    414 			    PIC_OCW3, OCW3_SELECT | OCW3_POLL);
    415 			irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2,
    416 			    PIC_OCW3);
    417 			if (irq & OCW3_POLL_PENDING)
    418 				irq = OCW3_POLL_IRQ(irq) + 8;
    419 			else
    420 				irq = 2;
    421 		}
    422 #else
    423 		/* XXX - should be a function call to gt.c? */
    424 		irq = le32toh(GT_REGVAL(GT_PCI0_INTR_ACK)) & 0xff;
    425 
    426 		/*
    427 		 * From YAMON source code:
    428 		 *
    429 		 * IRQ7 is used to detect spurious interrupts.
    430 		 * The interrupt acknowledge cycle returns IRQ7, if no
    431 		 * interrupts is requested.
    432 		 * We can differentiate between this situation and a
    433 		 * "Normal" IRQ7 by reading the ISR.
    434 		 */
    435 
    436 		if (irq == 7) {
    437 			int reg;
    438 
    439 			bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
    440 			    OCW3_SELECT | OCW3_RR | OCW3_RIS);
    441 			reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1,
    442 			    PIC_OCW3);
    443 			if (!(reg & (1 << 7)))
    444 				break;	/* spurious interrupt */
    445 		}
    446 #endif
    447 
    448 		sc->sc_intrtab[irq].intr_count.ev_count++;
    449 		LIST_FOREACH(ih, &sc->sc_intrtab[irq].intr_q, ih_q)
    450 			(*ih->ih_func)(ih->ih_arg);
    451 
    452 		/* Send a specific EOI to the 8259. */
    453 		if (irq > 7) {
    454 			bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
    455 			    PIC_OCW2, OCW2_SELECT | OCW2_EOI | OCW2_SL |
    456 			    OCW2_ILS(irq & 7));
    457 			irq = 2;
    458 		}
    459 
    460 		bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW2,
    461 		    OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(irq));
    462 	}
    463 }
    464 
    465 const char *
    466 pcib_isa_intr_string(void *v, int irq, char *buf, size_t len)
    467 {
    468 	if (irq == 0 || irq >= ICU_LEN || irq == 2)
    469 		panic("%s: bogus isa irq 0x%x", __func__, irq);
    470 
    471 	snprintf(buf, len, "isa irq %d", irq);
    472 	return buf;
    473 }
    474 
    475 const struct evcnt *
    476 pcib_isa_intr_evcnt(void *v, int irq)
    477 {
    478 
    479 	if (irq == 0 || irq >= ICU_LEN || irq == 2)
    480 		panic("pcib_isa_intr_evcnt: bogus isa irq 0x%x", irq);
    481 
    482 	return (&my_sc->sc_intrtab[irq].intr_count);
    483 }
    484 
    485 void *
    486 pcib_isa_intr_establish(void *v, int irq, int type, int level,
    487     int (*func)(void *), void *arg)
    488 {
    489 	struct evbmips_intrhand *ih;
    490 	int s;
    491 
    492 	if (irq >= ICU_LEN || irq == 2 || type == IST_NONE)
    493 		panic("pcib_isa_intr_establish: bad irq or type");
    494 
    495 	switch (my_sc->sc_intrtab[irq].intr_type) {
    496 	case IST_NONE:
    497 		my_sc->sc_intrtab[irq].intr_type = type;
    498 		break;
    499 
    500 	case IST_EDGE:
    501 	case IST_LEVEL:
    502 		if (type == my_sc->sc_intrtab[irq].intr_type)
    503 			break;
    504 		/* FALLTHROUGH */
    505 	case IST_PULSE:
    506 		/*
    507 		 * We can't share interrupts in this case.
    508 		 */
    509 		return (NULL);
    510 	}
    511 
    512 	ih = kmem_alloc(sizeof(*ih), KM_SLEEP);
    513 	ih->ih_func = func;
    514 	ih->ih_arg = arg;
    515 	ih->ih_irq = irq;
    516 
    517 	s = splhigh();
    518 
    519 	/* Insert the handler into the table. */
    520 	LIST_INSERT_HEAD(&my_sc->sc_intrtab[irq].intr_q, ih, ih_q);
    521 	my_sc->sc_intrtab[irq].intr_type = type;
    522 
    523 	/* Enable it, set trigger mode. */
    524 	my_sc->sc_imask &= ~(1 << irq);
    525 	if (my_sc->sc_intrtab[irq].intr_type == IST_LEVEL)
    526 		my_sc->sc_elcr |= (1 << irq);
    527 	else
    528 		my_sc->sc_elcr &= ~(1 << irq);
    529 
    530 	pcib_set_icus(my_sc);
    531 
    532 	splx(s);
    533 
    534 	return (ih);
    535 }
    536 
    537 void
    538 pcib_isa_intr_disestablish(void *v, void *arg)
    539 {
    540 	struct evbmips_intrhand *ih = arg;
    541 	int s;
    542 
    543 	s = splhigh();
    544 
    545 	LIST_REMOVE(ih, ih_q);
    546 
    547 	/* If there are no more handlers on this IRQ, disable it. */
    548 	if (LIST_FIRST(&my_sc->sc_intrtab[ih->ih_irq].intr_q) == NULL) {
    549 		my_sc->sc_imask |= (1 << ih->ih_irq);
    550 		pcib_set_icus(my_sc);
    551 	}
    552 
    553 	splx(s);
    554 
    555 	kmem_free(ih, sizeof(*ih));
    556 }
    557 
    558 static int
    559 pcib_isa_intr_alloc(void *v, int mask, int type, int *irq)
    560 {
    561 	int i, tmp, bestirq, count;
    562 	struct evbmips_intrhand *ih;
    563 
    564 	if (type == IST_NONE)
    565 		panic("pcib_intr_alloc: bogus type");
    566 
    567 	bestirq = -1;
    568 	count = -1;
    569 
    570 	mask &= ~my_sc->sc_reserved;
    571 
    572 	for (i = 0; i < ICU_LEN; i++) {
    573 		if ((mask & (1 << i)) == 0)
    574 			continue;
    575 
    576 		switch (my_sc->sc_intrtab[i].intr_type) {
    577 		case IST_NONE:
    578 			/*
    579 			 * If nothing's using the IRQ, just return it.
    580 			 */
    581 			*irq = i;
    582 			return (0);
    583 
    584 		case IST_EDGE:
    585 		case IST_LEVEL:
    586 			if (type != my_sc->sc_intrtab[i].intr_type)
    587 				continue;
    588 			/*
    589 			 * If the IRQ is shareable, count the number of
    590 			 * other handlers, and if it's smaller than the
    591 			 * last IRQ like this, remember it.
    592 			 */
    593 			tmp = 0;
    594 			for (ih = LIST_FIRST(&my_sc->sc_intrtab[i].intr_q);
    595 				ih != NULL; ih = LIST_NEXT(ih, ih_q))
    596 			tmp++;
    597 			if (bestirq == -1 || count > tmp) {
    598 				bestirq = i;
    599 				count = tmp;
    600 			}
    601 			break;
    602 
    603 		case IST_PULSE:
    604 		/* This just isn't shareable. */
    605 		continue;
    606 		}
    607 	}
    608 
    609 	if (bestirq == -1)
    610 		return (1);
    611 
    612 	*irq = bestirq;
    613 	return (0);
    614 }
    615 
    616 static void
    617 pcib_cleanup(void *arg)
    618 {
    619 
    620 	my_sc->sc_imask = 0xffff;
    621 	pcib_set_icus(my_sc);
    622 }
    623