Home | History | Annotate | Line # | Download | only in isa
isabus.c revision 1.44
      1 /*	$NetBSD: isabus.c,v 1.44 2008/07/05 08:46:25 tsutsui 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.44 2008/07/05 08:46:25 tsutsui 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 <mips/locore.h>
    144 
    145 #include <dev/ic/i8253reg.h>
    146 #include <dev/ic/i8259reg.h>
    147 #include <dev/isa/isareg.h>
    148 #include <dev/isa/isavar.h>
    149 #include <arc/isa/isabrvar.h>
    150 #include <arc/isa/spkrreg.h>
    151 
    152 #include <arc/arc/timervar.h>
    153 
    154 static int beeping;
    155 static callout_t sysbeep_ch;
    156 
    157 static long isa_mem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)];
    158 static long isa_io_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)];
    159 
    160 #define	IRQ_SLAVE	2
    161 
    162 /* Definition of the driver for autoconfig. */
    163 static int isabrprint(void *, const char *);
    164 
    165 extern struct arc_bus_space arc_bus_io, arc_bus_mem;
    166 
    167 static void isabr_attach_hook(device_t , device_t,
    168     struct isabus_attach_args *);
    169 static const struct evcnt *isabr_intr_evcnt(isa_chipset_tag_t, int);
    170 static void *isabr_intr_establish(isa_chipset_tag_t, int, int, int,
    171     int (*)(void *), void *);
    172 static void isabr_intr_disestablish(isa_chipset_tag_t, void*);
    173 static void isabr_initicu(void);
    174 static void intr_calculatemasks(void);
    175 static int fakeintr(void *a);
    176 
    177 struct isabr_config *isabr_conf = NULL;
    178 uint32_t imask[_IPL_N];	/* XXX */
    179 
    180 void
    181 isabrattach(struct isabr_softc *sc)
    182 {
    183 	struct isabus_attach_args iba;
    184 
    185 	callout_init(&sysbeep_ch, 0);
    186 
    187 	if (isabr_conf == NULL)
    188 		panic("isabr_conf isn't initialized");
    189 
    190 	aprint_normal("\n");
    191 
    192 	/* Initialize interrupt controller */
    193 	isabr_initicu();
    194 
    195 	sc->arc_isa_cs.ic_attach_hook = isabr_attach_hook;
    196 	sc->arc_isa_cs.ic_intr_evcnt = isabr_intr_evcnt;
    197 	sc->arc_isa_cs.ic_intr_establish = isabr_intr_establish;
    198 	sc->arc_isa_cs.ic_intr_disestablish = isabr_intr_disestablish;
    199 
    200 	arc_bus_space_init_extent(&arc_bus_mem, (void *)isa_mem_ex_storage,
    201 	    sizeof(isa_mem_ex_storage));
    202 	arc_bus_space_init_extent(&arc_bus_io, (void *)isa_io_ex_storage,
    203 	    sizeof(isa_io_ex_storage));
    204 
    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_ia(sc->sc_dev, "isabus", &iba, isabrprint);
    210 }
    211 
    212 static int
    213 isabrprint(void *aux, const char *pnp)
    214 {
    215 
    216         if (pnp)
    217                 aprint_normal("isa at %s", pnp);
    218         aprint_verbose(" isa_io_base 0x%lx isa_mem_base 0x%lx",
    219 	    arc_bus_io.bs_vbase, arc_bus_mem.bs_vbase);
    220         return UNCONF;
    221 }
    222 
    223 
    224 /*
    225  *	Interrupt system driver code
    226  *	============================
    227  */
    228 #define LEGAL_IRQ(x)    ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
    229 
    230 int	imen;
    231 int	intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
    232 struct isa_intrhand *isa_intrhand[ICU_LEN];
    233 
    234 static int
    235 fakeintr(void *a)
    236 {
    237 
    238 	return 0;
    239 }
    240 
    241 /*
    242  * Recalculate the interrupt masks from scratch.
    243  * We could code special registry and deregistry versions of this function that
    244  * would be faster, but the code would be nastier, and we don't expect this to
    245  * happen very much anyway.
    246  */
    247 static void
    248 intr_calculatemasks(void)
    249 {
    250 	int irq, level;
    251 	struct isa_intrhand *q;
    252 
    253 	/* First, figure out which levels each IRQ uses. */
    254 	for (irq = 0; irq < ICU_LEN; irq++) {
    255 		int levels = 0;
    256 		for (q = isa_intrhand[irq]; q; q = q->ih_next)
    257 			levels |= 1 << q->ih_level;
    258 		intrlevel[irq] = levels;
    259 	}
    260 
    261 	/* Then figure out which IRQs use each level. */
    262 	for (level = 0; level < _IPL_N; level++) {
    263 		int irqs = 0;
    264 		for (irq = 0; irq < ICU_LEN; irq++)
    265 			if (intrlevel[irq] & (1 << level))
    266 				irqs |= 1 << irq;
    267 		imask[level] = irqs;
    268 	}
    269 
    270 	imask[IPL_NONE] = 0;
    271 
    272 	imask[IPL_SOFTCLOCK] |= imask[IPL_NONE];
    273 	imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK];
    274 
    275 	/*
    276 	 * Enforce a hierarchy that gives slow devices a better chance at not
    277 	 * dropping data.
    278 	 */
    279 	imask[IPL_VM] |= imask[IPL_SOFTNET];
    280 
    281 	/*
    282 	 * Since run queues may be manipulated by both the statclock and tty,
    283 	 * network, and diskdrivers, clock > tty.
    284 	 */
    285 	imask[IPL_SCHED] |= imask[IPL_VM];
    286 
    287 	/* And eventually calculate the complete masks. */
    288 	for (irq = 0; irq < ICU_LEN; irq++) {
    289 		int irqs = 1 << irq;
    290 		for (q = isa_intrhand[irq]; q; q = q->ih_next)
    291 			irqs |= imask[q->ih_level];
    292 		intrmask[irq] = irqs;
    293 	}
    294 
    295 	/* Lastly, determine which IRQs are actually in use. */
    296 	{
    297 		int irqs = 0;
    298 		for (irq = 0; irq < ICU_LEN; irq++)
    299 			if (isa_intrhand[irq])
    300 				irqs |= 1 << irq;
    301 		if (irqs >= 0x100) /* any IRQs >= 8 in use */
    302 			irqs |= 1 << IRQ_SLAVE;
    303 		imen = ~irqs;
    304 		isa_outb(IO_ICU1 + PIC_OCW1, imen);
    305 		isa_outb(IO_ICU2 + PIC_OCW1, imen >> 8);
    306 	}
    307 }
    308 
    309 static void
    310 isabr_attach_hook(struct device *parent, struct device *self,
    311     struct isabus_attach_args *iba)
    312 {
    313 
    314 	/* Nothing to do. */
    315 }
    316 
    317 static const struct evcnt *
    318 isabr_intr_evcnt(isa_chipset_tag_t ic, int irq)
    319 {
    320 
    321 	/* XXX for now, no evcnt parent reported */
    322 	return NULL;
    323 }
    324 
    325 /*
    326  *	Establish a ISA bus interrupt.
    327  */
    328 static void *
    329 isabr_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level,
    330     int (*ih_fun)(void *), void *ih_arg)
    331 {
    332 	struct isa_intrhand **p, *q, *ih;
    333 	static struct isa_intrhand fakehand = {NULL, fakeintr};
    334 
    335 	/* no point in sleeping unless someone can free memory. */
    336 	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    337 	if (ih == NULL)
    338 		panic("isa_intr_establish: can't malloc handler info");
    339 
    340 	if (!LEGAL_IRQ(irq) || type == IST_NONE)
    341 		panic("intr_establish: bogus irq or type");
    342 
    343 	switch (intrtype[irq]) {
    344 	case IST_NONE:
    345 		intrtype[irq] = type;
    346 		break;
    347 	case IST_EDGE:
    348 	case IST_LEVEL:
    349 		if (type == intrtype[irq])
    350 			break;
    351 	case IST_PULSE:
    352 		if (type != IST_NONE)
    353 			panic("intr_establish: can't share %s with %s",
    354 			    isa_intr_typename(intrtype[irq]),
    355 			    isa_intr_typename(type));
    356 		break;
    357 	}
    358 
    359 	/*
    360 	 * Figure out where to put the handler.
    361 	 * This is O(N^2), but we want to preserve the order, and N is
    362 	 * generally small.
    363 	 */
    364 	for (p = &isa_intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
    365 		;
    366 
    367 	/*
    368 	 * Actually install a fake handler momentarily, since we might be doing
    369 	 * this with interrupts enabled and don't want the real routine called
    370 	 * until masking is set up.
    371 	 */
    372 	fakehand.ih_level = level;
    373 	*p = &fakehand;
    374 
    375 	intr_calculatemasks();
    376 
    377 	/*
    378 	 * Poke the real handler in now.
    379 	 */
    380 	ih->ih_fun = ih_fun;
    381 	ih->ih_arg = ih_arg;
    382 	ih->ih_count = 0;
    383 	ih->ih_next = NULL;
    384 	ih->ih_level = level;
    385 	ih->ih_irq = irq;
    386 	snprintf(ih->ih_evname, sizeof(ih->ih_evname), "irq %d", irq);
    387 	evcnt_attach_dynamic(&ih->ih_evcnt, EVCNT_TYPE_INTR, NULL, "isa",
    388 	    ih->ih_evname);
    389 	*p = ih;
    390 
    391 	return ih;
    392 }
    393 
    394 static void
    395 isabr_intr_disestablish(isa_chipset_tag_t ic, void *arg)
    396 {
    397 
    398 }
    399 
    400 /*
    401  *	Process an interrupt from the ISA bus.
    402  */
    403 uint32_t
    404 isabr_iointr(uint32_t mask, struct clockframe *cf)
    405 {
    406 	struct isa_intrhand *ih;
    407 	int isa_vector;
    408 	int o_imen;
    409 
    410 	isa_vector = (*isabr_conf->ic_intr_status)();
    411 	if (isa_vector < 0)
    412 		return 0;
    413 
    414 	o_imen = imen;
    415 	imen |= 1 << (isa_vector & (ICU_LEN - 1));
    416 	if (isa_vector & 0x08) {
    417 		isa_inb(IO_ICU2 + PIC_OCW1);
    418 		isa_outb(IO_ICU2 + PIC_OCW1, imen >> 8);
    419 		isa_outb(IO_ICU2 + PIC_OCW2,
    420 		    OCW2_SELECT | OCW2_EOI | OCW2_SL |
    421 		    OCW2_ILS((isa_vector & 7)));
    422 		isa_outb(IO_ICU1,
    423 		    OCW2_SELECT | OCW2_EOI | OCW2_SL | IRQ_SLAVE);
    424 	} else {
    425 		isa_inb(IO_ICU1 + PIC_OCW1);
    426 		isa_outb(IO_ICU1 + PIC_OCW1, imen);
    427 		isa_outb(IO_ICU1 + PIC_OCW2,
    428 		    OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(isa_vector));
    429 	}
    430 	ih = isa_intrhand[isa_vector];
    431 	if (isa_vector == 0 && ih) {	/* Clock */	/*XXX*/
    432 		last_cp0_count = mips3_cp0_count_read();
    433 		/* XXX: spllowerclock() not allowed */
    434 		cf->sr &= ~MIPS_SR_INT_IE;
    435 		if ((*ih->ih_fun)(cf))
    436 			ih->ih_evcnt.ev_count++;
    437 		ih = ih->ih_next;
    438 	}
    439 	while (ih) {
    440 		if ((*ih->ih_fun)(ih->ih_arg))
    441 			ih->ih_evcnt.ev_count++;
    442 		ih = ih->ih_next;
    443 	}
    444 	imen = o_imen;
    445 	isa_inb(IO_ICU1 + PIC_OCW1);
    446 	isa_inb(IO_ICU2 + PIC_OCW1);
    447 	isa_outb(IO_ICU1 + PIC_OCW1, imen);
    448 	isa_outb(IO_ICU2 + PIC_OCW1, imen >> 8);
    449 
    450 	return MIPS_INT_MASK_2;
    451 }
    452 
    453 
    454 /*
    455  * Initialize the Interrupt controller logic.
    456  */
    457 static void
    458 isabr_initicu(void)
    459 {
    460 
    461 	int i;
    462 
    463 	for (i = 0; i < ICU_LEN; i++) {
    464 		switch (i) {
    465 		case 2:
    466 		case 8:
    467 			intrtype[i] = IST_EDGE;
    468 			break;
    469 		default:
    470 			intrtype[i] = IST_NONE;
    471 			break;
    472 		}
    473 	}
    474 
    475 	/* reset; program device, four bytes */
    476 	isa_outb(IO_ICU1 + PIC_ICW1, ICW1_SELECT | ICW1_IC4);
    477 	/* starting at this vector index */
    478 	isa_outb(IO_ICU1 + PIC_ICW2, 0);
    479 	/* slave on line 2 */
    480 	isa_outb(IO_ICU1 + PIC_ICW3, ICW3_CASCADE(IRQ_SLAVE));
    481 	/* 8086 mode */
    482 	isa_outb(IO_ICU1 + PIC_ICW4, ICW4_8086);
    483 
    484 	/* leave interrupts masked */
    485 	isa_outb(IO_ICU1 + PIC_OCW1, 0xff);
    486 
    487 	/* special mask mode (if available) */
    488 	isa_outb(IO_ICU1 + PIC_OCW3, OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
    489 	/* Read IRR by default. */
    490 	isa_outb(IO_ICU1 + PIC_OCW3, OCW3_SELECT | OCW3_RR);
    491 #ifdef REORDER_IRQ
    492 	/* pri order 3-7, 0-2 (com2 first) */
    493 	isa_outb(IO_ICU1 + PIC_OCW2,
    494 	    OCW2_SELECT | OCW2_R | OCW2_SL OCW2_ILS(3 - 1));
    495 #endif
    496 
    497 	/* reset; program device, four bytes */
    498 	isa_outb(IO_ICU2 + PIC_ICW1, ICW1_SELECT | ICW1_IC4);
    499 	/* staring at this vector index */
    500 	isa_outb(IO_ICU2 + PIC_ICW2, 8);
    501 	/* slave connected to line 2 of master */
    502 	isa_outb(IO_ICU2 + PIC_ICW3, ICW3_SIC(IRQ_SLAVE));
    503 	/* 8086 mode */
    504 	isa_outb(IO_ICU2 + PIC_ICW4, ICW4_8086);
    505 
    506 	/* leave interrupts masked */
    507 	isa_outb(IO_ICU2 + PIC_OCW1, 0xff);
    508 
    509 	/* special mask mode (if available) */
    510 	isa_outb(IO_ICU2 + PIC_OCW3, OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
    511 	/* Read IRR by default. */
    512 	isa_outb(IO_ICU2 + PIC_OCW3, OCW3_SELECT | OCW3_RR);
    513 }
    514 
    515 
    516 /*
    517  *	SPEAKER BEEPER...
    518  */
    519 void
    520 sysbeepstop(void *arg)
    521 {
    522 	int s;
    523 
    524 	/* disable counter 2 */
    525 	s = splhigh();
    526 	isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) & ~PIT_SPKR);
    527 	splx(s);
    528 	beeping = 0;
    529 }
    530 
    531 void
    532 sysbeep(int pitch, int period)
    533 {
    534 	static int last_pitch, last_period;
    535 	int s;
    536 
    537 	if (cold)
    538 		return;		/* Can't beep yet. */
    539 
    540 	if (beeping)
    541 		callout_stop(&sysbeep_ch);
    542 	if (!beeping || last_pitch != pitch) {
    543 		s = splhigh();
    544 		isa_outb(IO_TIMER1 + TIMER_MODE,
    545 		    TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
    546 		isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) % 256);
    547 		isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) / 256);
    548 		isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) | PIT_SPKR);
    549 		splx(s);
    550 	}
    551 	last_pitch = pitch;
    552 	beeping = last_period = period;
    553 	callout_reset(&sysbeep_ch, period, sysbeepstop, NULL);
    554 }
    555 
    556 int
    557 isa_intr_alloc(isa_chipset_tag_t c, int mask, int type, int *irq_p)
    558 {
    559 	int irq;
    560 	int maybe_irq = -1;
    561 	int shared_depth = 0;
    562 	mask &= 0x8b28; /* choose from 3, 5, 8, 9, 11, 15 XXX */
    563 	for (irq = 0; mask != 0; mask >>= 1, irq++) {
    564 		if ((mask & 1) == 0)
    565 			continue;
    566 		if (intrtype[irq] == IST_NONE) {
    567 			*irq_p = irq;
    568 			return 0;
    569 		}
    570 		/* Level interrupts can be shared */
    571 		if (type == IST_LEVEL && intrtype[irq] == IST_LEVEL) {
    572 			struct isa_intrhand *ih = isa_intrhand[irq];
    573 			int depth;
    574 			if (maybe_irq == -1) {
    575  				maybe_irq = irq;
    576 				continue;
    577 			}
    578 			for (depth = 0; ih != NULL; ih = ih->ih_next)
    579 				depth++;
    580 			if (depth < shared_depth) {
    581 				maybe_irq = irq;
    582 				shared_depth = depth;
    583 			}
    584 		}
    585 	}
    586 	if (maybe_irq != -1) {
    587 		*irq_p = maybe_irq;
    588 		return 0;
    589 	}
    590 	return 1;
    591 }
    592