Home | History | Annotate | Line # | Download | only in pci
pcib.c revision 1.8
      1 /*	$NetBSD: pcib.c,v 1.8 2003/07/15 01:37:34 lukem 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.8 2003/07/15 01:37:34 lukem 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/malloc.h>
     46 
     47 #include <machine/bus.h>
     48 #include <evbmips/malta/maltareg.h>
     49 #include <evbmips/malta/maltavar.h>
     50 #include <evbmips/malta/dev/gtreg.h>
     51 #include <evbmips/malta/pci/pcibvar.h>
     52 
     53 #include <dev/isa/isareg.h>
     54 #include <dev/isa/isavar.h>
     55 
     56 #include <dev/pci/pcireg.h>
     57 #include <dev/pci/pcivar.h>
     58 #include <dev/pci/pcidevs.h>
     59 
     60 #include <dev/ic/i8259reg.h>
     61 
     62 
     63 #define	ICU_LEN		16	/* number of ISA IRQs */
     64 
     65 const char *isa_intrnames[ICU_LEN] = {
     66 	"timer",
     67 	"keyboard",
     68 	"reserved",		/* by South Bridge (for cascading) */
     69 	"com1",
     70 	"com0",
     71 	"not used",
     72 	"floppy",
     73 	"centronics",
     74 	"mcclock",
     75 	"i2c",
     76 	"pci A,B",		/* PCI slots 1..4, ethernet */
     77 	"pci C,D",		/* PCI slots 1..4, audio, usb */
     78 	"mouse",
     79 	"reserved",
     80 	"ide primary",
     81 	"ide secondary",	/* and compact flash connector */
     82 };
     83 
     84 struct pcib_intrhead {
     85 	LIST_HEAD(, evbmips_intrhand) intr_q;
     86 	struct evcnt intr_count;
     87 	int intr_type;
     88 };
     89 
     90 struct pcib_softc {
     91 	struct device sc_dev;
     92 
     93 	bus_space_tag_t sc_iot;
     94 	bus_space_handle_t sc_ioh_icu1;
     95 	bus_space_handle_t sc_ioh_icu2;
     96 	bus_space_handle_t sc_ioh_elcr;
     97 
     98 	struct mips_isa_chipset sc_ic;
     99 
    100 	struct pcib_intrhead sc_intrtab[ICU_LEN];
    101 
    102 	u_int16_t	sc_imask;
    103 	u_int16_t	sc_elcr;
    104 
    105 	u_int16_t	sc_reserved;
    106 
    107 	void *sc_ih;
    108 };
    109 
    110 /*
    111  * XXX
    112  *	There is only one pci-isa bridge, and all external interrupts
    113  *	are routed through it, so we need to remember the softc when
    114  *	called from other interrupt handling code.
    115  */
    116 static struct pcib_softc *my_sc;
    117 struct mips_isa_chipset *pcib_ic;
    118 
    119 static int	pcib_match(struct device *, struct cfdata *, void *);
    120 static void	pcib_attach(struct device *, struct device *, void *);
    121 static int	pcib_intr(void *v);
    122 static void	pcib_bridge_callback(struct device *);
    123 static int	pcib_print(void *, const char *);
    124 static void	pcib_set_icus(struct pcib_softc *sc);
    125 static void	pcib_cleanup(void *arg);
    126 
    127 static const struct evcnt *
    128 		pcib_isa_intr_evcnt(void *, int);
    129 static void	*pcib_isa_intr_establish(void *, int, int, int,
    130 		    int (*)(void *), void *);
    131 static void	pcib_isa_intr_disestablish(void *, void *);
    132 static void	pcib_isa_attach_hook(struct device *, struct device *,
    133 		    struct isabus_attach_args *);
    134 static int	pcib_isa_intr_alloc(void *, int, int, int *);
    135 static const char *
    136 		pcib_isa_intr_string(void *, int);
    137 
    138 CFATTACH_DECL(pcib, sizeof(struct pcib_softc),
    139     pcib_match, pcib_attach, NULL, NULL);
    140 
    141 static int
    142 pcib_match(struct device *parent, struct cfdata *match, void *aux)
    143 {
    144 	struct pci_attach_args *pa = aux;
    145 
    146 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
    147 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA)
    148 		return (1);
    149 
    150 	return (0);
    151 }
    152 
    153 static void
    154 pcib_attach(struct device *parent, struct device *self, void *aux)
    155 {
    156 	struct pci_attach_args *pa = aux;
    157 	char devinfo[256];
    158 	int i;
    159 
    160 	printf("\n");
    161 
    162 	if (my_sc != NULL)
    163 		panic("pcib_attach: already attached!");
    164 	my_sc = (void *)self;
    165 
    166 	/*
    167 	 * Just print out a description and defer configuration
    168 	 * until all PCI devices have been attached.
    169 	 */
    170 	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
    171 	printf("%s: %s, (rev . 0x%02x)\n", self->dv_xname, devinfo,
    172 	    PCI_REVISION(pa->pa_class));
    173 
    174 	my_sc->sc_iot = pa->pa_iot;
    175 
    176 	/*
    177 	 * Map the PIC/ELCR registers.
    178 	 */
    179 	if (bus_space_map(my_sc->sc_iot, 0x4d0, 2, 0, &my_sc->sc_ioh_elcr) != 0)
    180 		printf("%s: unable to map ELCR registers\n",
    181 		    my_sc->sc_dev.dv_xname);
    182 	if (bus_space_map(my_sc->sc_iot, IO_ICU1, 2, 0, &my_sc->sc_ioh_icu1) != 0)
    183 		printf("%s: unable to map ICU1 registers\n",
    184 		    my_sc->sc_dev.dv_xname);
    185 	if (bus_space_map(my_sc->sc_iot, IO_ICU2, 2, 0, &my_sc->sc_ioh_icu2) != 0)
    186 		printf("%s: unable to map ICU2 registers\n",
    187 		    my_sc->sc_dev.dv_xname);
    188 
    189 	/* All interrupts default to "masked off". */
    190 	my_sc->sc_imask = 0xffff;
    191 
    192 	/* All interrupts default to edge-triggered. */
    193 	my_sc->sc_elcr = 0;
    194 
    195 	/*
    196 	 * Initialize the 8259s.
    197 	 */
    198 	/* reset, program device, 4 bytes */
    199 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW1,
    200 	    ICW1_SELECT | ICW1_IC4);
    201 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW2,
    202 	    ICW2_VECTOR(0)/*XXX*/);
    203 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW3,
    204 	    ICW3_CASCADE(2));
    205 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_ICW4,
    206 	    ICW4_8086);
    207 
    208 	/* mask all interrupts */
    209 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_OCW1,
    210 	    my_sc->sc_imask & 0xff);
    211 
    212 	/* enable special mask mode */
    213 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_OCW3,
    214 	    OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
    215 
    216 	/* read IRR by default */
    217 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu1, PIC_OCW3,
    218 	    OCW3_SELECT | OCW3_RR);
    219 
    220 	/* reset, program device, 4 bytes */
    221 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW1,
    222 	    ICW1_SELECT | ICW1_IC4);
    223 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW2,
    224 	    ICW2_VECTOR(0)/*XXX*/);
    225 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW3,
    226 	    ICW3_CASCADE(2));
    227 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_ICW4,
    228 	    ICW4_8086);
    229 
    230 	/* mask all interrupts */
    231 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_OCW1,
    232 	    my_sc->sc_imask & 0xff);
    233 
    234 	/* enable special mask mode */
    235 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_OCW3,
    236 	    OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
    237 
    238 	/* read IRR by default */
    239 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_icu2, PIC_OCW3,
    240 	    OCW3_SELECT | OCW3_RR);
    241 
    242 	/*
    243 	 * Default all interrupts to edge-triggered.
    244 	 */
    245 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_elcr, 0,
    246 	    my_sc->sc_elcr & 0xff);
    247 	bus_space_write_1(my_sc->sc_iot, my_sc->sc_ioh_elcr, 1,
    248 	    (my_sc->sc_elcr >> 8) & 0xff);
    249 
    250 	/*
    251 	 * Some ISA interrupts are reserved for devices that
    252 	 * we know are hard-wired to certain IRQs.
    253 	 */
    254 	my_sc->sc_reserved =
    255 		(1U << 0) |     /* timer */
    256 		(1U << 1) |     /* keyboard controller (keyboard) */
    257 		(1U << 2) |     /* PIC cascade */
    258 		(1U << 3) |     /* COM 2 */
    259 		(1U << 4) |     /* COM 1 */
    260 		(1U << 6) |     /* floppy */
    261 		(1U << 7) |     /* centronics */
    262 		(1U << 8) |     /* RTC */
    263 		(1U << 9) |	/* I2C */
    264 		(1U << 12) |    /* keyboard controller (mouse) */
    265 		(1U << 14) |    /* IDE primary */
    266 		(1U << 15);     /* IDE secondary */
    267 
    268 	/* Set up our ISA chipset. */
    269 	my_sc->sc_ic.ic_v = my_sc;
    270 	my_sc->sc_ic.ic_intr_evcnt = pcib_isa_intr_evcnt;
    271 	my_sc->sc_ic.ic_intr_establish = pcib_isa_intr_establish;
    272 	my_sc->sc_ic.ic_intr_disestablish = pcib_isa_intr_disestablish;
    273 	my_sc->sc_ic.ic_intr_alloc = pcib_isa_intr_alloc;
    274 	my_sc->sc_ic.ic_intr_string = pcib_isa_intr_string;
    275 
    276 	pcib_ic = &my_sc->sc_ic;	/* XXX for external use */
    277 
    278 	/* Initialize our interrupt table. */
    279 	for (i = 0; i < ICU_LEN; i++) {
    280 #if 0
    281 		char irqstr[8];		/* 4 + 2 + NULL + sanity */
    282 
    283 		sprintf(irqstr, "irq %d", i);
    284 		evcnt_attach_dynamic(&my_sc->sc_intrtab[i].intr_count,
    285 		    EVCNT_TYPE_INTR, NULL, "pcib", irqstr);
    286 #else
    287 		evcnt_attach_dynamic(&my_sc->sc_intrtab[i].intr_count,
    288 		    EVCNT_TYPE_INTR, NULL, "pcib", isa_intrnames[i]);
    289 #endif
    290 		LIST_INIT(&my_sc->sc_intrtab[i].intr_q);
    291 		my_sc->sc_intrtab[i].intr_type = IST_NONE;
    292 	}
    293 
    294 	/* Hook up our interrupt handler. */
    295 	my_sc->sc_ih = evbmips_intr_establish(MALTA_SOUTHBRIDGE_INTR, pcib_intr, my_sc);
    296 	if (my_sc->sc_ih == NULL)
    297 		printf("%s: WARNING: unable to register interrupt handler\n",
    298 		    my_sc->sc_dev.dv_xname);
    299 
    300 
    301 	/*
    302 	 * Disable ISA interrupts before returning to YAMON.
    303 	 */
    304 	if (shutdownhook_establish(pcib_cleanup, my_sc) == NULL)
    305 		panic("pcib_attach: could not establish shutdown hook");
    306 
    307 	config_defer(self, pcib_bridge_callback);
    308 }
    309 
    310 static void
    311 pcib_bridge_callback(struct device *self)
    312 {
    313 	struct pcib_softc *sc = (void *)self;
    314 	struct malta_config *mcp = &malta_configuration;
    315 	struct isabus_attach_args iba;
    316 
    317 	/*
    318 	 * Attach the ISA bus behind this bridge.
    319 	 */
    320 	memset(&iba, 0, sizeof(iba));
    321 
    322 	iba.iba_busname = "isa";
    323 	iba.iba_iot = &mcp->mc_iot;
    324 	iba.iba_memt = &mcp->mc_memt;
    325 	iba.iba_dmat = &mcp->mc_isa_dmat;
    326 
    327 	iba.iba_ic = &sc->sc_ic;
    328 	iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook;
    329 
    330 	config_found(&sc->sc_dev, &iba, pcib_print);
    331 }
    332 
    333 static int
    334 pcib_print(void *aux, const char *pnp)
    335 {
    336 
    337 	/* Only ISAs can attach to pcib's; easy. */
    338 	if (pnp)
    339 		aprint_normal("isa at %s", pnp);
    340 	return (UNCONF);
    341 }
    342 
    343 static void
    344 pcib_isa_attach_hook(struct device *parent, struct device *self,
    345     struct isabus_attach_args *iba)
    346 {
    347 
    348 	/* Nothing to do. */
    349 }
    350 
    351 static void
    352 pcib_set_icus(struct pcib_softc *sc)
    353 {
    354 
    355 	/* Enable the cascade IRQ (2) if 8-15 is enabled. */
    356 	if ((sc->sc_imask & 0xff00) != 0xff00)
    357 		sc->sc_imask &= ~(1U << 2);
    358 	else
    359 		sc->sc_imask |= (1U << 2);
    360 
    361 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1,
    362 	    sc->sc_imask & 0xff);
    363 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
    364 	    (sc->sc_imask >> 8) & 0xff);
    365 
    366 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
    367 	    sc->sc_elcr & 0xff);
    368 	bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
    369 	    (sc->sc_elcr >> 8) & 0xff);
    370 }
    371 
    372 static int
    373 pcib_intr(void *v)
    374 {
    375 	struct pcib_softc *sc = v;
    376 	struct evbmips_intrhand *ih;
    377 	int irq;
    378 
    379 	for (;;) {
    380 #if 1
    381 		bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
    382 		    OCW3_SELECT | OCW3_POLL);
    383 		irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3);
    384 		if ((irq & OCW3_POLL_PENDING) == 0)
    385 			return (1);
    386 
    387 		irq = OCW3_POLL_IRQ(irq);
    388 
    389 		if (irq == 2) {
    390 			bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
    391 			    PIC_OCW3, OCW3_SELECT | OCW3_POLL);
    392 			irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2,
    393 			    PIC_OCW3);
    394 			if (irq & OCW3_POLL_PENDING)
    395 				irq = OCW3_POLL_IRQ(irq) + 8;
    396 			else
    397 				irq = 2;
    398 		}
    399 #else
    400 		/* XXX - should be a function call to gt.c? */
    401 		irq = GT_REGVAL(GT_PCI0_INTR_ACK) & 0xff;
    402 
    403 		/*
    404 		 * From YAMON source code:
    405 		 *
    406 		 * IRQ7 is used to detect spurious interrupts.
    407 		 * The interrupt acknowledge cycle returns IRQ7, if no
    408 		 * interrupts is requested.
    409 		 * We can differentiate between this situation and a
    410 		 * "Normal" IRQ7 by reading the ISR.
    411 		 */
    412 
    413 		if (irq == 7) {
    414 			int reg;
    415 
    416 			bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
    417 			    OCW3_SELECT | OCW3_RR | OCW3_RIS);
    418 			reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1,
    419 			    PIC_OCW3);
    420 			if (!(reg & (1 << 7)))
    421 				break;	/* spurious interrupt */
    422 		}
    423 #endif
    424 
    425 		sc->sc_intrtab[irq].intr_count.ev_count++;
    426 		LIST_FOREACH(ih, &sc->sc_intrtab[irq].intr_q, ih_q)
    427 			(*ih->ih_func)(ih->ih_arg);
    428 
    429 		/* Send a specific EOI to the 8259. */
    430 		if (irq > 7) {
    431 			bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
    432 			    PIC_OCW2, OCW2_SELECT | OCW3_EOI | OCW3_SL |
    433 			    OCW2_ILS(irq & 7));
    434 			irq = 2;
    435 		}
    436 
    437 		bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW2,
    438 		    OCW2_SELECT | OCW3_EOI | OCW3_SL | OCW2_ILS(irq));
    439 	}
    440 }
    441 
    442 const char *
    443 pcib_isa_intr_string(void *v, int irq)
    444 {
    445 	static char irqstr[12];		/* 8 + 2 + NULL + sanity */
    446 
    447 	if (irq == 0 || irq >= ICU_LEN || irq == 2)
    448 		panic("pcib_isa_intr_string: bogus isa irq 0x%x", irq);
    449 
    450 	sprintf(irqstr, "isa irq %d", irq);
    451 	return (irqstr);
    452 }
    453 
    454 const struct evcnt *
    455 pcib_isa_intr_evcnt(void *v, int irq)
    456 {
    457 
    458 	if (irq == 0 || irq >= ICU_LEN || irq == 2)
    459 		panic("pcib_isa_intr_evcnt: bogus isa irq 0x%x", irq);
    460 
    461 	return (&my_sc->sc_intrtab[irq].intr_count);
    462 }
    463 
    464 void *
    465 pcib_isa_intr_establish(void *v, int irq, int type, int level,
    466     int (*func)(void *), void *arg)
    467 {
    468 	struct evbmips_intrhand *ih;
    469 	int s;
    470 
    471 	if (irq >= ICU_LEN || irq == 2 || type == IST_NONE)
    472 		panic("pcib_isa_intr_establish: bad irq or type");
    473 
    474 	switch (my_sc->sc_intrtab[irq].intr_type) {
    475 	case IST_NONE:
    476 		my_sc->sc_intrtab[irq].intr_type = type;
    477 		break;
    478 
    479 	case IST_EDGE:
    480 	case IST_LEVEL:
    481 		if (type == my_sc->sc_intrtab[irq].intr_type)
    482 			break;
    483 		/* FALLTHROUGH */
    484 	case IST_PULSE:
    485 		/*
    486 		 * We can't share interrupts in this case.
    487 		 */
    488 		return (NULL);
    489 	}
    490 
    491 	ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
    492 	if (ih == NULL)
    493 		return (NULL);
    494 
    495 	ih->ih_func = func;
    496 	ih->ih_arg = arg;
    497 	ih->ih_irq = irq;
    498 
    499 	s = splhigh();
    500 
    501 	/* Insert the handler into the table. */
    502 	LIST_INSERT_HEAD(&my_sc->sc_intrtab[irq].intr_q, ih, ih_q);
    503 	my_sc->sc_intrtab[irq].intr_type = type;
    504 
    505 	/* Enable it, set trigger mode. */
    506 	my_sc->sc_imask &= ~(1 << irq);
    507 	if (my_sc->sc_intrtab[irq].intr_type == IST_LEVEL)
    508 		my_sc->sc_elcr |= (1 << irq);
    509 	else
    510 		my_sc->sc_elcr &= ~(1 << irq);
    511 
    512 	pcib_set_icus(my_sc);
    513 
    514 	splx(s);
    515 
    516 	return (ih);
    517 }
    518 
    519 void
    520 pcib_isa_intr_disestablish(void *v, void *arg)
    521 {
    522 	struct evbmips_intrhand *ih = arg;
    523 	int s;
    524 
    525 	s = splhigh();
    526 
    527 	LIST_REMOVE(ih, ih_q);
    528 
    529 	/* If there are no more handlers on this IRQ, disable it. */
    530 	if (LIST_FIRST(&my_sc->sc_intrtab[ih->ih_irq].intr_q) == NULL) {
    531 		my_sc->sc_imask |= (1 << ih->ih_irq);
    532 		pcib_set_icus(my_sc);
    533 	}
    534 
    535 	splx(s);
    536 
    537 	free(ih, M_DEVBUF);
    538 }
    539 
    540 static int
    541 pcib_isa_intr_alloc(void *v, int mask, int type, int *irq)
    542 {
    543 	int i, tmp, bestirq, count;
    544 	struct evbmips_intrhand *ih;
    545 
    546 	if (type == IST_NONE)
    547 		panic("pcib_intr_alloc: bogus type");
    548 
    549 	bestirq = -1;
    550 	count = -1;
    551 
    552 	mask &= ~my_sc->sc_reserved;
    553 
    554 	for (i = 0; i < ICU_LEN; i++) {
    555 		if ((mask & (1 << i)) == 0)
    556 			continue;
    557 
    558 		switch (my_sc->sc_intrtab[i].intr_type) {
    559 		case IST_NONE:
    560 			/*
    561 			 * If nothing's using the IRQ, just return it.
    562 			 */
    563 			*irq = i;
    564 			return (0);
    565 
    566 		case IST_EDGE:
    567 		case IST_LEVEL:
    568 			if (type != my_sc->sc_intrtab[i].intr_type)
    569 				continue;
    570 			/*
    571 			 * If the IRQ is sharable, count the number of
    572 			 * other handlers, and if it's smaller than the
    573 			 * last IRQ like this, remember it.
    574 			 */
    575 			tmp = 0;
    576 			for (ih = LIST_FIRST(&my_sc->sc_intrtab[i].intr_q);
    577 				ih != NULL; ih = LIST_NEXT(ih, ih_q))
    578 			tmp++;
    579 			if (bestirq == -1 || count > tmp) {
    580 				bestirq = i;
    581 				count = tmp;
    582 			}
    583 			break;
    584 
    585 		case IST_PULSE:
    586 		/* This just isn't sharable. */
    587 		continue;
    588 		}
    589 	}
    590 
    591 	if (bestirq == -1)
    592 		return (1);
    593 
    594 	*irq = bestirq;
    595 	return (0);
    596 }
    597 
    598 static void
    599 pcib_cleanup(void *arg)
    600 {
    601 
    602 	my_sc->sc_imask = 0xffff;
    603 	pcib_set_icus(my_sc);
    604 }
    605