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