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