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