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