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