Home | History | Annotate | Line # | Download | only in isa
isabus.c revision 1.25
      1 /*	$NetBSD: isabus.c,v 1.25 2003/08/07 16:26:50 agc Exp $	*/
      2 /*	$OpenBSD: isabus.c,v 1.15 1998/03/16 09:38:46 pefo Exp $	*/
      3 /*	NetBSD: isa.c,v 1.33 1995/06/28 04:30:51 cgd Exp 	*/
      4 
      5 /*-
      6  * Copyright (c) 1990 The Regents of the University of California.
      7  * All rights reserved.
      8  *
      9  * This code is derived from software contributed to Berkeley by
     10  * William Jolitz and Don Ahn.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  *	@(#)isa.c	7.2 (Berkeley) 5/12/91
     37  */
     38 /*-
     39  * Copyright (c) 1995 Per Fogelstrom
     40  * Copyright (c) 1993, 1994 Charles M. Hannum.
     41  *
     42  * This code is derived from software contributed to Berkeley by
     43  * William Jolitz and Don Ahn.
     44  *
     45  * Redistribution and use in source and binary forms, with or without
     46  * modification, are permitted provided that the following conditions
     47  * are met:
     48  * 1. Redistributions of source code must retain the above copyright
     49  *    notice, this list of conditions and the following disclaimer.
     50  * 2. Redistributions in binary form must reproduce the above copyright
     51  *    notice, this list of conditions and the following disclaimer in the
     52  *    documentation and/or other materials provided with the distribution.
     53  * 3. All advertising materials mentioning features or use of this software
     54  *    must display the following acknowledgement:
     55  *	This product includes software developed by the University of
     56  *	California, Berkeley and its contributors.
     57  * 4. Neither the name of the University nor the names of its contributors
     58  *    may be used to endorse or promote products derived from this software
     59  *    without specific prior written permission.
     60  *
     61  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     62  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     63  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     64  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     65  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     66  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     67  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     68  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     69  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     70  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     71  * SUCH DAMAGE.
     72  *
     73  *	@(#)isa.c	7.2 (Berkeley) 5/12/91
     74  */
     75 /*
     76  * Mach Operating System
     77  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
     78  * All Rights Reserved.
     79  *
     80  * Permission to use, copy, modify and distribute this software and its
     81  * documentation is hereby granted, provided that both the copyright
     82  * notice and this permission notice appear in all copies of the
     83  * software, derivative works or modified versions, and any portions
     84  * thereof, and that both notices appear in supporting documentation.
     85  *
     86  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     87  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     88  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     89  *
     90  * Carnegie Mellon requests users of this software to return to
     91  *
     92  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     93  *  School of Computer Science
     94  *  Carnegie Mellon University
     95  *  Pittsburgh PA 15213-3890
     96  *
     97  * any improvements or extensions that they make and grant Carnegie Mellon
     98  * the rights to redistribute these changes.
     99  */
    100 /*
    101   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
    102 
    103 		All Rights Reserved
    104 
    105 Permission to use, copy, modify, and distribute this software and
    106 its documentation for any purpose and without fee is hereby
    107 granted, provided that the above copyright notice appears in all
    108 copies and that both the copyright notice and this permission notice
    109 appear in supporting documentation, and that the name of Intel
    110 not be used in advertising or publicity pertaining to distribution
    111 of the software without specific, written prior permission.
    112 
    113 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
    114 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
    115 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
    116 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    117 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
    118 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
    119 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    120 */
    121 
    122 #include <sys/cdefs.h>
    123 __KERNEL_RCSID(0, "$NetBSD: isabus.c,v 1.25 2003/08/07 16:26:50 agc Exp $");
    124 
    125 #include <sys/param.h>
    126 #include <sys/proc.h>
    127 #include <sys/user.h>
    128 #include <sys/systm.h>
    129 #include <sys/callout.h>
    130 #include <sys/time.h>
    131 #include <sys/kernel.h>
    132 #include <sys/device.h>
    133 #include <sys/malloc.h>
    134 #include <sys/extent.h>
    135 
    136 #include <uvm/uvm_extern.h>
    137 
    138 #include <machine/cpu.h>
    139 #include <machine/pio.h>
    140 #include <machine/autoconf.h>
    141 #include <machine/intr.h>
    142 
    143 #include <dev/ic/i8253reg.h>
    144 #include <dev/isa/isareg.h>
    145 #include <dev/isa/isavar.h>
    146 #include <arc/isa/isabrvar.h>
    147 #include <arc/isa/spkrreg.h>
    148 
    149 static int beeping;
    150 static struct callout sysbeep_ch = CALLOUT_INITIALIZER;
    151 
    152 static long isa_mem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)];
    153 static long isa_io_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)];
    154 
    155 #define	IRQ_SLAVE	2
    156 
    157 /* Definition of the driver for autoconfig. */
    158 int	isabrprint(void *, const char *);
    159 
    160 extern struct arc_bus_space arc_bus_io, arc_bus_mem;
    161 
    162 void	isabr_attach_hook __P((struct device *, struct device *,
    163 			struct isabus_attach_args *));
    164 const struct evcnt *isabr_intr_evcnt __P((isa_chipset_tag_t, int));
    165 void	*isabr_intr_establish __P((isa_chipset_tag_t, int, int, int,
    166 			int (*)(void *), void *));
    167 void	isabr_intr_disestablish __P((isa_chipset_tag_t, void*));
    168 int	isabr_iointr __P((unsigned int, struct clockframe *));
    169 void	isabr_initicu __P((void));
    170 void	intr_calculatemasks __P((void));
    171 int	fakeintr __P((void *a));
    172 
    173 struct isabr_config *isabr_conf = NULL;
    174 u_int32_t imask[_IPL_N];	/* XXX */
    175 
    176 void
    177 isabrattach(sc)
    178 	struct isabr_softc *sc;
    179 {
    180 	struct isabus_attach_args iba;
    181 
    182 	if (isabr_conf == NULL)
    183 		panic("isabr_conf isn't initialized");
    184 
    185 	printf("\n");
    186 
    187 	/* Initialize interrupt controller */
    188 	isabr_initicu();
    189 
    190 /*XXX we may remove the abus part of the softc struct... */
    191 	sc->sc_bus.ab_dv = (struct device *)sc;
    192 	sc->sc_bus.ab_type = BUS_ISABR;
    193 
    194 	sc->arc_isa_cs.ic_attach_hook = isabr_attach_hook;
    195 	sc->arc_isa_cs.ic_intr_evcnt = isabr_intr_evcnt;
    196 	sc->arc_isa_cs.ic_intr_establish = isabr_intr_establish;
    197 	sc->arc_isa_cs.ic_intr_disestablish = isabr_intr_disestablish;
    198 
    199 	arc_bus_space_init_extent(&arc_bus_mem, (caddr_t)isa_mem_ex_storage,
    200 	    sizeof(isa_mem_ex_storage));
    201 	arc_bus_space_init_extent(&arc_bus_io, (caddr_t)isa_io_ex_storage,
    202 	    sizeof(isa_io_ex_storage));
    203 
    204 	iba.iba_busname = "isa";
    205 	iba.iba_iot = &arc_bus_io;
    206 	iba.iba_memt = &arc_bus_mem;
    207 	iba.iba_dmat = &sc->sc_dmat;
    208 	iba.iba_ic = &sc->arc_isa_cs;
    209 	config_found(&sc->sc_dev, &iba, isabrprint);
    210 }
    211 
    212 int
    213 isabrprint(aux, pnp)
    214 	void *aux;
    215 	const char *pnp;
    216 {
    217 	struct confargs *ca = aux;
    218 
    219         if (pnp)
    220                 aprint_normal("%s at %s", ca->ca_name, pnp);
    221         aprint_verbose(" isa_io_base 0x%lx isa_mem_base 0x%lx",
    222 		arc_bus_io.bs_vbase, arc_bus_mem.bs_vbase);
    223         return (UNCONF);
    224 }
    225 
    226 
    227 /*
    228  *	Interrupt system driver code
    229  *	============================
    230  */
    231 #define LEGAL_IRQ(x)    ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
    232 
    233 int	imen;
    234 int	intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
    235 struct intrhand *intrhand[ICU_LEN];
    236 
    237 int fakeintr(a)
    238 	void *a;
    239 {
    240 	return 0;
    241 }
    242 
    243 /*
    244  * Recalculate the interrupt masks from scratch.
    245  * We could code special registry and deregistry versions of this function that
    246  * would be faster, but the code would be nastier, and we don't expect this to
    247  * happen very much anyway.
    248  */
    249 void
    250 intr_calculatemasks()
    251 {
    252 	int irq, level;
    253 	struct intrhand *q;
    254 
    255 	/* First, figure out which levels each IRQ uses. */
    256 	for (irq = 0; irq < ICU_LEN; irq++) {
    257 		int levels = 0;
    258 		for (q = intrhand[irq]; q; q = q->ih_next)
    259 			levels |= 1 << q->ih_level;
    260 		intrlevel[irq] = levels;
    261 	}
    262 
    263 	/* Then figure out which IRQs use each level. */
    264 	for (level = 0; level < _IPL_N; level++) {
    265 		int irqs = 0;
    266 		for (irq = 0; irq < ICU_LEN; irq++)
    267 			if (intrlevel[irq] & (1 << level))
    268 				irqs |= 1 << irq;
    269 		imask[level] = irqs;
    270 	}
    271 
    272 	imask[IPL_NONE] = 0;
    273 
    274 	imask[IPL_SOFT] |= imask[IPL_NONE];
    275 	imask[IPL_SOFTCLOCK] |= imask[IPL_SOFT];
    276 	imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK];
    277 	imask[IPL_SOFTSERIAL] |= imask[IPL_SOFTNET];
    278 
    279 	/*
    280 	 * Enforce a hierarchy that gives slow devices a better chance at not
    281 	 * dropping data.
    282 	 */
    283 	imask[IPL_BIO] |= imask[IPL_SOFTSERIAL];
    284 	imask[IPL_NET] |= imask[IPL_BIO];
    285 	imask[IPL_TTY] |= imask[IPL_NET];
    286 
    287 	/*
    288 	 * Since run queues may be manipulated by both the statclock and tty,
    289 	 * network, and diskdrivers, clock > tty.
    290 	 */
    291 	imask[IPL_CLOCK] |= imask[IPL_TTY];
    292 	imask[IPL_STATCLOCK] |= imask[IPL_CLOCK];
    293 
    294 	/*
    295 	 * IPL_HIGH must block everything that can manipulate a run queue.
    296 	 */
    297 	imask[IPL_HIGH] |= imask[IPL_STATCLOCK];
    298 
    299 	/* And eventually calculate the complete masks. */
    300 	for (irq = 0; irq < ICU_LEN; irq++) {
    301 		int irqs = 1 << irq;
    302 		for (q = intrhand[irq]; q; q = q->ih_next)
    303 			irqs |= imask[q->ih_level];
    304 		intrmask[irq] = irqs;
    305 	}
    306 
    307 	/* Lastly, determine which IRQs are actually in use. */
    308 	{
    309 		int irqs = 0;
    310 		for (irq = 0; irq < ICU_LEN; irq++)
    311 			if (intrhand[irq])
    312 				irqs |= 1 << irq;
    313 		if (irqs >= 0x100) /* any IRQs >= 8 in use */
    314 			irqs |= 1 << IRQ_SLAVE;
    315 		imen = ~irqs;
    316 		isa_outb(IO_ICU1 + 1, imen);
    317 		isa_outb(IO_ICU2 + 1, imen >> 8);
    318 	}
    319 }
    320 
    321 void
    322 isabr_attach_hook(parent, self, iba)
    323 	struct device *parent, *self;
    324 	struct isabus_attach_args *iba;
    325 {
    326 
    327 	/* Nothing to do. */
    328 }
    329 
    330 const struct evcnt *
    331 isabr_intr_evcnt(ic, irq)
    332 	isa_chipset_tag_t ic;
    333 	int irq;
    334 {
    335 
    336 	/* XXX for now, no evcnt parent reported */
    337 	return NULL;
    338 }
    339 
    340 /*
    341  *	Establish a ISA bus interrupt.
    342  */
    343 void *
    344 isabr_intr_establish(ic, irq, type, level, ih_fun, ih_arg)
    345         isa_chipset_tag_t ic;
    346         int irq;
    347         int type;
    348         int level;
    349         int (*ih_fun) __P((void *));
    350         void *ih_arg;
    351 {
    352 	struct intrhand **p, *q, *ih;
    353 	static struct intrhand fakehand = {NULL, fakeintr};
    354 
    355 	/* no point in sleeping unless someone can free memory. */
    356 	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    357 	if (ih == NULL)
    358 		panic("isa_intr_establish: can't malloc handler info");
    359 
    360 	if (!LEGAL_IRQ(irq) || type == IST_NONE)
    361 		panic("intr_establish: bogus irq or type");
    362 
    363 	switch (intrtype[irq]) {
    364 	case IST_NONE:
    365 		intrtype[irq] = type;
    366 		break;
    367 	case IST_EDGE:
    368 	case IST_LEVEL:
    369 		if (type == intrtype[irq])
    370 			break;
    371 	case IST_PULSE:
    372 		if (type != IST_NONE)
    373 			panic("intr_establish: can't share %s with %s",
    374 			    isa_intr_typename(intrtype[irq]),
    375 			    isa_intr_typename(type));
    376 		break;
    377 	}
    378 
    379 	/*
    380 	 * Figure out where to put the handler.
    381 	 * This is O(N^2), but we want to preserve the order, and N is
    382 	 * generally small.
    383 	 */
    384 	for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
    385 		;
    386 
    387 	/*
    388 	 * Actually install a fake handler momentarily, since we might be doing
    389 	 * this with interrupts enabled and don't want the real routine called
    390 	 * until masking is set up.
    391 	 */
    392 	fakehand.ih_level = level;
    393 	*p = &fakehand;
    394 
    395 	intr_calculatemasks();
    396 
    397 	/*
    398 	 * Poke the real handler in now.
    399 	 */
    400 	ih->ih_fun = ih_fun;
    401 	ih->ih_arg = ih_arg;
    402 	ih->ih_count = 0;
    403 	ih->ih_next = NULL;
    404 	ih->ih_level = level;
    405 	ih->ih_irq = irq;
    406 	ih->ih_what = ""; /* XXX - should be eliminated */
    407 	*p = ih;
    408 
    409 	return (ih);
    410 }
    411 
    412 void
    413 isabr_intr_disestablish(ic, arg)
    414         isa_chipset_tag_t ic;
    415         void *arg;
    416 {
    417 
    418 }
    419 
    420 /*
    421  *	Process an interrupt from the ISA bus.
    422  */
    423 int
    424 isabr_iointr(mask, cf)
    425         unsigned mask;
    426         struct clockframe *cf;
    427 {
    428 	struct intrhand *ih;
    429 	int isa_vector;
    430 	int o_imen;
    431 
    432 	isa_vector = (*isabr_conf->ic_intr_status)();
    433 	if (isa_vector < 0)
    434 		return (~0);
    435 
    436 	o_imen = imen;
    437 	imen |= 1 << (isa_vector & (ICU_LEN - 1));
    438 	if(isa_vector & 0x08) {
    439 		isa_inb(IO_ICU2 + 1);
    440 		isa_outb(IO_ICU2 + 1, imen >> 8);
    441 		isa_outb(IO_ICU2, 0x60 + (isa_vector & 7));
    442 		isa_outb(IO_ICU1, 0x60 + IRQ_SLAVE);
    443 	}
    444 	else {
    445 		isa_inb(IO_ICU1 + 1);
    446 		isa_outb(IO_ICU1 + 1, imen);
    447 		isa_outb(IO_ICU1, 0x60 + isa_vector);
    448 	}
    449 	ih = intrhand[isa_vector];
    450 	if(isa_vector == 0) {	/* Clock */	/*XXX*/
    451 		(*ih->ih_fun)(cf);
    452 		ih = ih->ih_next;
    453 	}
    454 	while(ih) {
    455 		(*ih->ih_fun)(ih->ih_arg);
    456 		ih = ih->ih_next;
    457 	}
    458 	imen = o_imen;
    459 	isa_inb(IO_ICU1 + 1);
    460 	isa_inb(IO_ICU2 + 1);
    461 	isa_outb(IO_ICU1 + 1, imen);
    462 	isa_outb(IO_ICU2 + 1, imen >> 8);
    463 
    464 	return(~0);  /* Dont reenable */
    465 }
    466 
    467 
    468 /*
    469  * Initialize the Interrupt controller logic.
    470  */
    471 void
    472 isabr_initicu()
    473 {
    474 
    475 	int i;
    476 
    477 	for (i = 0; i < ICU_LEN; i++) {
    478 		switch (i) {
    479 		case 2:
    480 		case 8:
    481 			intrtype[i] = IST_EDGE;
    482 			break;
    483 		default:
    484 			intrtype[i] = IST_NONE;
    485 			break;
    486 		}
    487 	}
    488 
    489 	isa_outb(IO_ICU1, 0x11);		/* reset; program device, four bytes */
    490 	isa_outb(IO_ICU1+1, 0);			/* starting at this vector index */
    491 	isa_outb(IO_ICU1+1, 1 << IRQ_SLAVE);	/* slave on line 2 */
    492 	isa_outb(IO_ICU1+1, 1);			/* 8086 mode */
    493 	isa_outb(IO_ICU1+1, 0xff);		/* leave interrupts masked */
    494 	isa_outb(IO_ICU1, 0x68);		/* special mask mode (if available) */
    495 	isa_outb(IO_ICU1, 0x0a);		/* Read IRR by default. */
    496 #ifdef REORDER_IRQ
    497 	isa_outb(IO_ICU1, 0xc0 | (3 - 1));	/* pri order 3-7, 0-2 (com2 first) */
    498 #endif
    499 
    500 	isa_outb(IO_ICU2, 0x11);		/* reset; program device, four bytes */
    501 	isa_outb(IO_ICU2+1, 8);			/* staring at this vector index */
    502 	isa_outb(IO_ICU2+1, IRQ_SLAVE);
    503 	isa_outb(IO_ICU2+1, 1);			/* 8086 mode */
    504 	isa_outb(IO_ICU2+1, 0xff);		/* leave interrupts masked */
    505 	isa_outb(IO_ICU2, 0x68);		/* special mask mode (if available) */
    506 	isa_outb(IO_ICU2, 0x0a);		/* Read IRR by default. */
    507 }
    508 
    509 
    510 /*
    511  *	SPEAKER BEEPER...
    512  */
    513 void
    514 sysbeepstop(arg)
    515 	void *arg;
    516 {
    517 	int s;
    518 
    519 	/* disable counter 2 */
    520 	s = splhigh();
    521 	isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) & ~PIT_SPKR);
    522 	splx(s);
    523 	beeping = 0;
    524 }
    525 
    526 void
    527 sysbeep(pitch, period)
    528 	int pitch, period;
    529 {
    530 	static int last_pitch, last_period;
    531 	int s;
    532 
    533 	if (cold)
    534 		return;		/* Can't beep yet. */
    535 
    536 	if (beeping)
    537 		callout_stop(&sysbeep_ch);
    538 	if (!beeping || last_pitch != pitch) {
    539 		s = splhigh();
    540 		isa_outb(IO_TIMER1 + TIMER_MODE,
    541 		    TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
    542 		isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) % 256);
    543 		isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) / 256);
    544 		isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) | PIT_SPKR);
    545 		splx(s);
    546 	}
    547 	last_pitch = pitch;
    548 	beeping = last_period = period;
    549 	callout_reset(&sysbeep_ch, period, sysbeepstop, NULL);
    550 }
    551 
    552 int
    553 isa_intr_alloc(isa_chipset_tag_t c, int mask, int type, int *irq_p)
    554 {
    555 	int irq;
    556 	int maybe_irq = -1;
    557 	int shared_depth = 0;
    558 	mask &= 0x8b28; /* choose from 3, 5, 8, 9, 11, 15 XXX */
    559 	for (irq = 0; mask != 0; mask >>= 1, irq++) {
    560 		if ((mask & 1) == 0)
    561 			continue;
    562 		if (intrtype[irq] == IST_NONE) {
    563 			*irq_p = irq;
    564 			return 0;
    565 		}
    566 		/* Level interrupts can be shared */
    567 		if (type == IST_LEVEL && intrtype[irq] == IST_LEVEL) {
    568 			struct intrhand *ih = intrhand[irq];
    569 			int depth;
    570 			if (maybe_irq == -1) {
    571  				maybe_irq = irq;
    572 				continue;
    573 			}
    574 			for (depth = 0; ih != NULL; ih = ih->ih_next)
    575 				depth++;
    576 			if (depth < shared_depth) {
    577 				maybe_irq = irq;
    578 				shared_depth = depth;
    579 			}
    580 		}
    581 	}
    582 	if (maybe_irq != -1) {
    583 		*irq_p = maybe_irq;
    584 		return 0;
    585 	}
    586 	return 1;
    587 }
    588