Home | History | Annotate | Line # | Download | only in isa
      1  1.54   thorpej /*	$NetBSD: isabus.c,v 1.54 2023/12/07 03:46:10 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.25       agc  * Copyright (c) 1990 The Regents of the University of California.
      7  1.25       agc  * All rights reserved.
      8  1.25       agc  *
      9  1.25       agc  * This code is derived from software contributed to Berkeley by
     10  1.25       agc  * William Jolitz and Don Ahn.
     11  1.25       agc  *
     12  1.25       agc  * Redistribution and use in source and binary forms, with or without
     13  1.25       agc  * modification, are permitted provided that the following conditions
     14  1.25       agc  * are met:
     15  1.25       agc  * 1. Redistributions of source code must retain the above copyright
     16  1.25       agc  *    notice, this list of conditions and the following disclaimer.
     17  1.25       agc  * 2. Redistributions in binary form must reproduce the above copyright
     18  1.25       agc  *    notice, this list of conditions and the following disclaimer in the
     19  1.25       agc  *    documentation and/or other materials provided with the distribution.
     20  1.25       agc  * 3. Neither the name of the University nor the names of its contributors
     21  1.25       agc  *    may be used to endorse or promote products derived from this software
     22  1.25       agc  *    without specific prior written permission.
     23  1.25       agc  *
     24  1.25       agc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  1.25       agc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  1.25       agc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  1.25       agc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  1.25       agc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  1.25       agc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  1.25       agc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  1.25       agc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  1.25       agc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  1.25       agc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  1.25       agc  * SUCH DAMAGE.
     35  1.25       agc  *
     36  1.25       agc  *	@(#)isa.c	7.2 (Berkeley) 5/12/91
     37  1.25       agc  */
     38  1.25       agc /*-
     39   1.1  jonathan  * Copyright (c) 1995 Per Fogelstrom
     40   1.3   mycroft  * Copyright (c) 1993, 1994 Charles M. Hannum.
     41   1.1  jonathan  *
     42   1.1  jonathan  * This code is derived from software contributed to Berkeley by
     43   1.1  jonathan  * William Jolitz and Don Ahn.
     44   1.1  jonathan  *
     45   1.1  jonathan  * Redistribution and use in source and binary forms, with or without
     46   1.1  jonathan  * modification, are permitted provided that the following conditions
     47   1.1  jonathan  * are met:
     48   1.1  jonathan  * 1. Redistributions of source code must retain the above copyright
     49   1.1  jonathan  *    notice, this list of conditions and the following disclaimer.
     50   1.1  jonathan  * 2. Redistributions in binary form must reproduce the above copyright
     51   1.1  jonathan  *    notice, this list of conditions and the following disclaimer in the
     52   1.1  jonathan  *    documentation and/or other materials provided with the distribution.
     53   1.1  jonathan  * 3. All advertising materials mentioning features or use of this software
     54   1.1  jonathan  *    must display the following acknowledgement:
     55   1.1  jonathan  *	This product includes software developed by the University of
     56   1.1  jonathan  *	California, Berkeley and its contributors.
     57   1.1  jonathan  * 4. Neither the name of the University nor the names of its contributors
     58   1.1  jonathan  *    may be used to endorse or promote products derived from this software
     59   1.1  jonathan  *    without specific prior written permission.
     60   1.1  jonathan  *
     61   1.1  jonathan  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     62   1.1  jonathan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     63   1.1  jonathan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     64   1.1  jonathan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     65   1.1  jonathan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     66   1.1  jonathan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     67   1.1  jonathan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     68   1.1  jonathan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     69   1.1  jonathan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     70   1.1  jonathan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     71   1.1  jonathan  * SUCH DAMAGE.
     72   1.1  jonathan  *
     73   1.1  jonathan  *	@(#)isa.c	7.2 (Berkeley) 5/12/91
     74   1.1  jonathan  */
     75  1.48   tsutsui /*
     76   1.1  jonathan  * Mach Operating System
     77   1.1  jonathan  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
     78   1.1  jonathan  * All Rights Reserved.
     79  1.48   tsutsui  *
     80   1.1  jonathan  * Permission to use, copy, modify and distribute this software and its
     81   1.1  jonathan  * documentation is hereby granted, provided that both the copyright
     82   1.1  jonathan  * notice and this permission notice appear in all copies of the
     83   1.1  jonathan  * software, derivative works or modified versions, and any portions
     84   1.1  jonathan  * thereof, and that both notices appear in supporting documentation.
     85  1.48   tsutsui  *
     86   1.1  jonathan  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     87   1.1  jonathan  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     88   1.1  jonathan  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     89  1.48   tsutsui  *
     90   1.1  jonathan  * Carnegie Mellon requests users of this software to return to
     91  1.48   tsutsui  *
     92   1.1  jonathan  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     93   1.1  jonathan  *  School of Computer Science
     94   1.1  jonathan  *  Carnegie Mellon University
     95   1.1  jonathan  *  Pittsburgh PA 15213-3890
     96  1.48   tsutsui  *
     97   1.1  jonathan  * any improvements or extensions that they make and grant Carnegie Mellon
     98   1.1  jonathan  * the rights to redistribute these changes.
     99   1.1  jonathan  */
    100   1.1  jonathan /*
    101   1.1  jonathan   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
    102   1.1  jonathan 
    103   1.1  jonathan 		All Rights Reserved
    104   1.1  jonathan 
    105   1.1  jonathan Permission to use, copy, modify, and distribute this software and
    106   1.1  jonathan its documentation for any purpose and without fee is hereby
    107   1.1  jonathan granted, provided that the above copyright notice appears in all
    108   1.1  jonathan copies and that both the copyright notice and this permission notice
    109   1.1  jonathan appear in supporting documentation, and that the name of Intel
    110   1.1  jonathan not be used in advertising or publicity pertaining to distribution
    111   1.1  jonathan of the software without specific, written prior permission.
    112   1.1  jonathan 
    113   1.1  jonathan INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
    114   1.1  jonathan INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
    115   1.1  jonathan IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
    116   1.1  jonathan CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    117   1.1  jonathan LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
    118   1.1  jonathan NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
    119   1.1  jonathan WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    120   1.1  jonathan */
    121  1.24     lukem 
    122  1.24     lukem #include <sys/cdefs.h>
    123  1.54   thorpej __KERNEL_RCSID(0, "$NetBSD: isabus.c,v 1.54 2023/12/07 03:46:10 thorpej Exp $");
    124   1.1  jonathan 
    125   1.1  jonathan #include <sys/param.h>
    126   1.5      soda #include <sys/proc.h>
    127   1.1  jonathan #include <sys/systm.h>
    128   1.8   thorpej #include <sys/callout.h>
    129   1.1  jonathan #include <sys/time.h>
    130   1.1  jonathan #include <sys/kernel.h>
    131   1.1  jonathan #include <sys/device.h>
    132  1.51   thorpej #include <sys/kmem.h>
    133  1.54   thorpej #include <sys/vmem_impl.h>
    134  1.13       mrg 
    135  1.13       mrg #include <uvm/uvm_extern.h>
    136   1.1  jonathan 
    137   1.1  jonathan #include <machine/cpu.h>
    138   1.1  jonathan #include <machine/pio.h>
    139   1.1  jonathan #include <machine/autoconf.h>
    140   1.5      soda #include <machine/intr.h>
    141   1.1  jonathan 
    142  1.29   tsutsui #include <mips/locore.h>
    143  1.29   tsutsui 
    144  1.15      soda #include <dev/ic/i8253reg.h>
    145  1.36   tsutsui #include <dev/ic/i8259reg.h>
    146   1.1  jonathan #include <dev/isa/isareg.h>
    147   1.1  jonathan #include <dev/isa/isavar.h>
    148  1.15      soda #include <arc/isa/isabrvar.h>
    149   1.5      soda #include <arc/isa/spkrreg.h>
    150   1.5      soda 
    151  1.29   tsutsui #include <arc/arc/timervar.h>
    152  1.29   tsutsui 
    153   1.5      soda static int beeping;
    154  1.38        ad static callout_t sysbeep_ch;
    155   1.5      soda 
    156  1.54   thorpej #define	ISA_MEM_BTAG_COUNT	VMEM_EST_BTCOUNT(1, 16)
    157  1.54   thorpej #define	ISA_IO_BTAG_COUNT	VMEM_EST_BTCOUNT(1, 16)
    158  1.54   thorpej 
    159  1.54   thorpej static struct vmem isa_mem_arena_store;
    160  1.54   thorpej static struct vmem isa_io_arena_store;
    161  1.54   thorpej static struct vmem_btag isa_mem_btag_store[ISA_MEM_BTAG_COUNT];
    162  1.54   thorpej static struct vmem_btag isa_io_btag_store[ISA_IO_BTAG_COUNT];
    163  1.23   tsutsui 
    164   1.5      soda #define	IRQ_SLAVE	2
    165   1.5      soda 
    166   1.5      soda /* Definition of the driver for autoconfig. */
    167  1.44   tsutsui static int isabrprint(void *, const char *);
    168   1.5      soda 
    169  1.10      soda extern struct arc_bus_space arc_bus_io, arc_bus_mem;
    170  1.10      soda 
    171  1.44   tsutsui static void isabr_attach_hook(device_t , device_t,
    172  1.44   tsutsui     struct isabus_attach_args *);
    173  1.45    dyoung static void isabr_detach_hook(isa_chipset_tag_t, device_t);
    174  1.44   tsutsui static const struct evcnt *isabr_intr_evcnt(isa_chipset_tag_t, int);
    175  1.44   tsutsui static void *isabr_intr_establish(isa_chipset_tag_t, int, int, int,
    176  1.44   tsutsui     int (*)(void *), void *);
    177  1.44   tsutsui static void isabr_intr_disestablish(isa_chipset_tag_t, void*);
    178  1.44   tsutsui static void isabr_initicu(void);
    179  1.44   tsutsui static void intr_calculatemasks(void);
    180  1.44   tsutsui static int fakeintr(void *a);
    181   1.5      soda 
    182  1.15      soda struct isabr_config *isabr_conf = NULL;
    183  1.27   tsutsui uint32_t imask[_IPL_N];	/* XXX */
    184   1.5      soda 
    185   1.5      soda void
    186  1.27   tsutsui isabrattach(struct isabr_softc *sc)
    187   1.5      soda {
    188   1.5      soda 	struct isabus_attach_args iba;
    189   1.5      soda 
    190  1.39        he 	callout_init(&sysbeep_ch, 0);
    191  1.38        ad 
    192  1.15      soda 	if (isabr_conf == NULL)
    193  1.15      soda 		panic("isabr_conf isn't initialized");
    194  1.15      soda 
    195  1.44   tsutsui 	aprint_normal("\n");
    196   1.5      soda 
    197   1.5      soda 	/* Initialize interrupt controller */
    198   1.5      soda 	isabr_initicu();
    199   1.5      soda 
    200  1.11      soda 	sc->arc_isa_cs.ic_attach_hook = isabr_attach_hook;
    201  1.45    dyoung 	sc->arc_isa_cs.ic_detach_hook = isabr_detach_hook;
    202   1.9       cgd 	sc->arc_isa_cs.ic_intr_evcnt = isabr_intr_evcnt;
    203   1.5      soda 	sc->arc_isa_cs.ic_intr_establish = isabr_intr_establish;
    204   1.5      soda 	sc->arc_isa_cs.ic_intr_disestablish = isabr_intr_disestablish;
    205  1.23   tsutsui 
    206  1.54   thorpej 	arc_bus_space_init_arena(&arc_bus_mem, &isa_mem_arena_store,
    207  1.54   thorpej 	    isa_mem_btag_store, ISA_MEM_BTAG_COUNT);
    208  1.54   thorpej 	arc_bus_space_init_arena(&arc_bus_io, &isa_io_arena_store,
    209  1.54   thorpej 	    isa_io_btag_store, ISA_IO_BTAG_COUNT);
    210   1.5      soda 
    211  1.11      soda 	iba.iba_iot = &arc_bus_io;
    212  1.11      soda 	iba.iba_memt = &arc_bus_mem;
    213  1.11      soda 	iba.iba_dmat = &sc->sc_dmat;
    214   1.5      soda 	iba.iba_ic = &sc->arc_isa_cs;
    215  1.52   thorpej 	config_found(sc->sc_dev, &iba, isabrprint,
    216  1.53   thorpej 	    CFARGS(.iattr = "isabus"));
    217   1.5      soda }
    218   1.5      soda 
    219  1.44   tsutsui static int
    220  1.27   tsutsui isabrprint(void *aux, const char *pnp)
    221   1.5      soda {
    222   1.5      soda 
    223   1.5      soda         if (pnp)
    224  1.26  drochner                 aprint_normal("isa at %s", pnp);
    225  1.47      matt         aprint_verbose(" isa_io_base 0x%"PRIxVADDR" isa_mem_base 0x%"PRIxVADDR,
    226  1.44   tsutsui 	    arc_bus_io.bs_vbase, arc_bus_mem.bs_vbase);
    227  1.44   tsutsui         return UNCONF;
    228   1.5      soda }
    229   1.5      soda 
    230   1.5      soda 
    231   1.5      soda /*
    232   1.5      soda  *	Interrupt system driver code
    233   1.5      soda  *	============================
    234   1.5      soda  */
    235   1.5      soda #define LEGAL_IRQ(x)    ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
    236   1.5      soda 
    237   1.5      soda int	imen;
    238   1.5      soda int	intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
    239  1.32   tsutsui struct isa_intrhand *isa_intrhand[ICU_LEN];
    240   1.5      soda 
    241  1.44   tsutsui static int
    242  1.44   tsutsui fakeintr(void *a)
    243   1.5      soda {
    244  1.27   tsutsui 
    245   1.5      soda 	return 0;
    246   1.5      soda }
    247   1.5      soda 
    248   1.5      soda /*
    249   1.5      soda  * Recalculate the interrupt masks from scratch.
    250   1.5      soda  * We could code special registry and deregistry versions of this function that
    251   1.5      soda  * would be faster, but the code would be nastier, and we don't expect this to
    252   1.5      soda  * happen very much anyway.
    253   1.5      soda  */
    254  1.44   tsutsui static void
    255  1.27   tsutsui intr_calculatemasks(void)
    256   1.5      soda {
    257   1.5      soda 	int irq, level;
    258  1.32   tsutsui 	struct isa_intrhand *q;
    259   1.5      soda 
    260   1.5      soda 	/* First, figure out which levels each IRQ uses. */
    261   1.5      soda 	for (irq = 0; irq < ICU_LEN; irq++) {
    262  1.19   tsutsui 		int levels = 0;
    263  1.32   tsutsui 		for (q = isa_intrhand[irq]; q; q = q->ih_next)
    264   1.5      soda 			levels |= 1 << q->ih_level;
    265   1.5      soda 		intrlevel[irq] = levels;
    266   1.5      soda 	}
    267   1.5      soda 
    268   1.5      soda 	/* Then figure out which IRQs use each level. */
    269  1.20   tsutsui 	for (level = 0; level < _IPL_N; level++) {
    270  1.19   tsutsui 		int irqs = 0;
    271   1.5      soda 		for (irq = 0; irq < ICU_LEN; irq++)
    272   1.5      soda 			if (intrlevel[irq] & (1 << level))
    273   1.5      soda 				irqs |= 1 << irq;
    274  1.20   tsutsui 		imask[level] = irqs;
    275   1.5      soda 	}
    276   1.5      soda 
    277  1.20   tsutsui 	imask[IPL_NONE] = 0;
    278  1.20   tsutsui 
    279  1.41        ad 	imask[IPL_SOFTCLOCK] |= imask[IPL_NONE];
    280  1.20   tsutsui 	imask[IPL_SOFTNET] |= imask[IPL_SOFTCLOCK];
    281   1.5      soda 
    282   1.5      soda 	/*
    283   1.5      soda 	 * Enforce a hierarchy that gives slow devices a better chance at not
    284   1.5      soda 	 * dropping data.
    285   1.5      soda 	 */
    286  1.41        ad 	imask[IPL_VM] |= imask[IPL_SOFTNET];
    287  1.20   tsutsui 
    288  1.20   tsutsui 	/*
    289  1.20   tsutsui 	 * Since run queues may be manipulated by both the statclock and tty,
    290  1.20   tsutsui 	 * network, and diskdrivers, clock > tty.
    291  1.20   tsutsui 	 */
    292  1.41        ad 	imask[IPL_SCHED] |= imask[IPL_VM];
    293   1.5      soda 
    294   1.5      soda 	/* And eventually calculate the complete masks. */
    295   1.5      soda 	for (irq = 0; irq < ICU_LEN; irq++) {
    296  1.19   tsutsui 		int irqs = 1 << irq;
    297  1.32   tsutsui 		for (q = isa_intrhand[irq]; q; q = q->ih_next)
    298   1.5      soda 			irqs |= imask[q->ih_level];
    299  1.20   tsutsui 		intrmask[irq] = irqs;
    300   1.5      soda 	}
    301   1.5      soda 
    302   1.5      soda 	/* Lastly, determine which IRQs are actually in use. */
    303   1.5      soda 	{
    304  1.19   tsutsui 		int irqs = 0;
    305   1.5      soda 		for (irq = 0; irq < ICU_LEN; irq++)
    306  1.32   tsutsui 			if (isa_intrhand[irq])
    307   1.5      soda 				irqs |= 1 << irq;
    308   1.5      soda 		if (irqs >= 0x100) /* any IRQs >= 8 in use */
    309   1.5      soda 			irqs |= 1 << IRQ_SLAVE;
    310   1.5      soda 		imen = ~irqs;
    311  1.36   tsutsui 		isa_outb(IO_ICU1 + PIC_OCW1, imen);
    312  1.36   tsutsui 		isa_outb(IO_ICU2 + PIC_OCW1, imen >> 8);
    313   1.5      soda 	}
    314  1.11      soda }
    315  1.11      soda 
    316  1.44   tsutsui static void
    317  1.49       chs isabr_attach_hook(device_t parent, device_t self,
    318  1.27   tsutsui     struct isabus_attach_args *iba)
    319  1.11      soda {
    320  1.11      soda 
    321  1.11      soda 	/* Nothing to do. */
    322   1.9       cgd }
    323   1.9       cgd 
    324  1.45    dyoung static void
    325  1.45    dyoung isabr_detach_hook(isa_chipset_tag_t ic, device_t self)
    326  1.45    dyoung {
    327  1.45    dyoung 
    328  1.45    dyoung 	/* Nothing to do. */
    329  1.45    dyoung }
    330  1.45    dyoung 
    331  1.44   tsutsui static const struct evcnt *
    332  1.27   tsutsui isabr_intr_evcnt(isa_chipset_tag_t ic, int irq)
    333   1.9       cgd {
    334   1.9       cgd 
    335   1.9       cgd 	/* XXX for now, no evcnt parent reported */
    336   1.9       cgd 	return NULL;
    337   1.5      soda }
    338   1.5      soda 
    339   1.5      soda /*
    340   1.5      soda  *	Establish a ISA bus interrupt.
    341   1.5      soda  */
    342  1.44   tsutsui static void *
    343  1.27   tsutsui isabr_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level,
    344  1.27   tsutsui     int (*ih_fun)(void *), void *ih_arg)
    345   1.5      soda {
    346  1.32   tsutsui 	struct isa_intrhand **p, *q, *ih;
    347  1.32   tsutsui 	static struct isa_intrhand fakehand = {NULL, fakeintr};
    348   1.5      soda 
    349  1.51   thorpej 	ih = kmem_alloc(sizeof *ih, KM_SLEEP);
    350   1.5      soda 
    351   1.5      soda 	if (!LEGAL_IRQ(irq) || type == IST_NONE)
    352   1.5      soda 		panic("intr_establish: bogus irq or type");
    353   1.5      soda 
    354   1.5      soda 	switch (intrtype[irq]) {
    355  1.22   tsutsui 	case IST_NONE:
    356  1.22   tsutsui 		intrtype[irq] = type;
    357  1.22   tsutsui 		break;
    358   1.5      soda 	case IST_EDGE:
    359   1.5      soda 	case IST_LEVEL:
    360   1.5      soda 		if (type == intrtype[irq])
    361   1.5      soda 			break;
    362   1.5      soda 	case IST_PULSE:
    363   1.5      soda 		if (type != IST_NONE)
    364   1.5      soda 			panic("intr_establish: can't share %s with %s",
    365   1.5      soda 			    isa_intr_typename(intrtype[irq]),
    366   1.5      soda 			    isa_intr_typename(type));
    367   1.5      soda 		break;
    368   1.5      soda 	}
    369   1.5      soda 
    370   1.5      soda 	/*
    371   1.5      soda 	 * Figure out where to put the handler.
    372   1.5      soda 	 * This is O(N^2), but we want to preserve the order, and N is
    373   1.5      soda 	 * generally small.
    374   1.5      soda 	 */
    375  1.32   tsutsui 	for (p = &isa_intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
    376   1.5      soda 		;
    377   1.5      soda 
    378   1.5      soda 	/*
    379   1.5      soda 	 * Actually install a fake handler momentarily, since we might be doing
    380   1.5      soda 	 * this with interrupts enabled and don't want the real routine called
    381   1.5      soda 	 * until masking is set up.
    382   1.5      soda 	 */
    383   1.5      soda 	fakehand.ih_level = level;
    384   1.5      soda 	*p = &fakehand;
    385   1.5      soda 
    386   1.5      soda 	intr_calculatemasks();
    387   1.5      soda 
    388   1.5      soda 	/*
    389   1.5      soda 	 * Poke the real handler in now.
    390   1.5      soda 	 */
    391   1.5      soda 	ih->ih_fun = ih_fun;
    392   1.5      soda 	ih->ih_arg = ih_arg;
    393   1.5      soda 	ih->ih_count = 0;
    394   1.5      soda 	ih->ih_next = NULL;
    395   1.5      soda 	ih->ih_level = level;
    396   1.5      soda 	ih->ih_irq = irq;
    397  1.33   tsutsui 	snprintf(ih->ih_evname, sizeof(ih->ih_evname), "irq %d", irq);
    398  1.33   tsutsui 	evcnt_attach_dynamic(&ih->ih_evcnt, EVCNT_TYPE_INTR, NULL, "isa",
    399  1.33   tsutsui 	    ih->ih_evname);
    400   1.5      soda 	*p = ih;
    401   1.5      soda 
    402  1.27   tsutsui 	return ih;
    403   1.5      soda }
    404   1.5      soda 
    405  1.44   tsutsui static void
    406  1.27   tsutsui isabr_intr_disestablish(isa_chipset_tag_t ic, void *arg)
    407  1.18   tsutsui {
    408   1.5      soda 
    409   1.5      soda }
    410   1.5      soda 
    411   1.5      soda /*
    412   1.5      soda  *	Process an interrupt from the ISA bus.
    413   1.5      soda  */
    414  1.28   tsutsui uint32_t
    415  1.28   tsutsui isabr_iointr(uint32_t mask, struct clockframe *cf)
    416   1.5      soda {
    417  1.32   tsutsui 	struct isa_intrhand *ih;
    418   1.5      soda 	int isa_vector;
    419   1.5      soda 	int o_imen;
    420   1.7      soda 
    421  1.15      soda 	isa_vector = (*isabr_conf->ic_intr_status)();
    422  1.15      soda 	if (isa_vector < 0)
    423  1.43   tsutsui 		return 0;
    424   1.5      soda 
    425   1.5      soda 	o_imen = imen;
    426   1.5      soda 	imen |= 1 << (isa_vector & (ICU_LEN - 1));
    427  1.27   tsutsui 	if (isa_vector & 0x08) {
    428  1.36   tsutsui 		isa_inb(IO_ICU2 + PIC_OCW1);
    429  1.36   tsutsui 		isa_outb(IO_ICU2 + PIC_OCW1, imen >> 8);
    430  1.36   tsutsui 		isa_outb(IO_ICU2 + PIC_OCW2,
    431  1.36   tsutsui 		    OCW2_SELECT | OCW2_EOI | OCW2_SL |
    432  1.36   tsutsui 		    OCW2_ILS((isa_vector & 7)));
    433  1.36   tsutsui 		isa_outb(IO_ICU1,
    434  1.36   tsutsui 		    OCW2_SELECT | OCW2_EOI | OCW2_SL | IRQ_SLAVE);
    435  1.27   tsutsui 	} else {
    436  1.36   tsutsui 		isa_inb(IO_ICU1 + PIC_OCW1);
    437  1.36   tsutsui 		isa_outb(IO_ICU1 + PIC_OCW1, imen);
    438  1.36   tsutsui 		isa_outb(IO_ICU1 + PIC_OCW2,
    439  1.36   tsutsui 		    OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(isa_vector));
    440   1.5      soda 	}
    441  1.32   tsutsui 	ih = isa_intrhand[isa_vector];
    442  1.31   tsutsui 	if (isa_vector == 0 && ih) {	/* Clock */	/*XXX*/
    443  1.29   tsutsui 		last_cp0_count = mips3_cp0_count_read();
    444  1.34   tsutsui 		/* XXX: spllowerclock() not allowed */
    445  1.34   tsutsui 		cf->sr &= ~MIPS_SR_INT_IE;
    446  1.33   tsutsui 		if ((*ih->ih_fun)(cf))
    447  1.33   tsutsui 			ih->ih_evcnt.ev_count++;
    448   1.5      soda 		ih = ih->ih_next;
    449   1.5      soda 	}
    450  1.27   tsutsui 	while (ih) {
    451  1.33   tsutsui 		if ((*ih->ih_fun)(ih->ih_arg))
    452  1.33   tsutsui 			ih->ih_evcnt.ev_count++;
    453   1.5      soda 		ih = ih->ih_next;
    454   1.5      soda 	}
    455   1.5      soda 	imen = o_imen;
    456  1.36   tsutsui 	isa_inb(IO_ICU1 + PIC_OCW1);
    457  1.36   tsutsui 	isa_inb(IO_ICU2 + PIC_OCW1);
    458  1.36   tsutsui 	isa_outb(IO_ICU1 + PIC_OCW1, imen);
    459  1.36   tsutsui 	isa_outb(IO_ICU2 + PIC_OCW1, imen >> 8);
    460   1.5      soda 
    461  1.42   tsutsui 	return MIPS_INT_MASK_2;
    462   1.5      soda }
    463   1.5      soda 
    464   1.5      soda 
    465  1.18   tsutsui /*
    466   1.5      soda  * Initialize the Interrupt controller logic.
    467   1.5      soda  */
    468  1.44   tsutsui static void
    469  1.27   tsutsui isabr_initicu(void)
    470  1.18   tsutsui {
    471  1.22   tsutsui 
    472  1.22   tsutsui 	int i;
    473  1.22   tsutsui 
    474  1.22   tsutsui 	for (i = 0; i < ICU_LEN; i++) {
    475  1.22   tsutsui 		switch (i) {
    476  1.22   tsutsui 		case 2:
    477  1.22   tsutsui 		case 8:
    478  1.22   tsutsui 			intrtype[i] = IST_EDGE;
    479  1.22   tsutsui 			break;
    480  1.22   tsutsui 		default:
    481  1.22   tsutsui 			intrtype[i] = IST_NONE;
    482  1.22   tsutsui 			break;
    483  1.22   tsutsui 		}
    484  1.22   tsutsui 	}
    485   1.5      soda 
    486  1.36   tsutsui 	/* reset; program device, four bytes */
    487  1.36   tsutsui 	isa_outb(IO_ICU1 + PIC_ICW1, ICW1_SELECT | ICW1_IC4);
    488  1.36   tsutsui 	/* starting at this vector index */
    489  1.36   tsutsui 	isa_outb(IO_ICU1 + PIC_ICW2, 0);
    490  1.36   tsutsui 	/* slave on line 2 */
    491  1.36   tsutsui 	isa_outb(IO_ICU1 + PIC_ICW3, ICW3_CASCADE(IRQ_SLAVE));
    492  1.36   tsutsui 	/* 8086 mode */
    493  1.36   tsutsui 	isa_outb(IO_ICU1 + PIC_ICW4, ICW4_8086);
    494  1.36   tsutsui 
    495  1.36   tsutsui 	/* leave interrupts masked */
    496  1.36   tsutsui 	isa_outb(IO_ICU1 + PIC_OCW1, 0xff);
    497  1.36   tsutsui 
    498  1.36   tsutsui 	/* special mask mode (if available) */
    499  1.36   tsutsui 	isa_outb(IO_ICU1 + PIC_OCW3, OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
    500  1.36   tsutsui 	/* Read IRR by default. */
    501  1.36   tsutsui 	isa_outb(IO_ICU1 + PIC_OCW3, OCW3_SELECT | OCW3_RR);
    502  1.18   tsutsui #ifdef REORDER_IRQ
    503  1.36   tsutsui 	/* pri order 3-7, 0-2 (com2 first) */
    504  1.36   tsutsui 	isa_outb(IO_ICU1 + PIC_OCW2,
    505  1.36   tsutsui 	    OCW2_SELECT | OCW2_R | OCW2_SL OCW2_ILS(3 - 1));
    506   1.2  jonathan #endif
    507   1.1  jonathan 
    508  1.36   tsutsui 	/* reset; program device, four bytes */
    509  1.36   tsutsui 	isa_outb(IO_ICU2 + PIC_ICW1, ICW1_SELECT | ICW1_IC4);
    510  1.36   tsutsui 	/* staring at this vector index */
    511  1.36   tsutsui 	isa_outb(IO_ICU2 + PIC_ICW2, 8);
    512  1.36   tsutsui 	/* slave connected to line 2 of master */
    513  1.36   tsutsui 	isa_outb(IO_ICU2 + PIC_ICW3, ICW3_SIC(IRQ_SLAVE));
    514  1.36   tsutsui 	/* 8086 mode */
    515  1.36   tsutsui 	isa_outb(IO_ICU2 + PIC_ICW4, ICW4_8086);
    516  1.36   tsutsui 
    517  1.36   tsutsui 	/* leave interrupts masked */
    518  1.36   tsutsui 	isa_outb(IO_ICU2 + PIC_OCW1, 0xff);
    519  1.36   tsutsui 
    520  1.36   tsutsui 	/* special mask mode (if available) */
    521  1.36   tsutsui 	isa_outb(IO_ICU2 + PIC_OCW3, OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
    522  1.36   tsutsui 	/* Read IRR by default. */
    523  1.36   tsutsui 	isa_outb(IO_ICU2 + PIC_OCW3, OCW3_SELECT | OCW3_RR);
    524  1.18   tsutsui }
    525   1.1  jonathan 
    526   1.1  jonathan 
    527   1.5      soda /*
    528   1.5      soda  *	SPEAKER BEEPER...
    529   1.5      soda  */
    530   1.1  jonathan void
    531  1.27   tsutsui sysbeepstop(void *arg)
    532   1.1  jonathan {
    533   1.1  jonathan 	int s;
    534   1.1  jonathan 
    535   1.1  jonathan 	/* disable counter 2 */
    536   1.1  jonathan 	s = splhigh();
    537   1.1  jonathan 	isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) & ~PIT_SPKR);
    538   1.1  jonathan 	splx(s);
    539   1.1  jonathan 	beeping = 0;
    540   1.1  jonathan }
    541   1.1  jonathan 
    542   1.1  jonathan void
    543  1.27   tsutsui sysbeep(int pitch, int period)
    544   1.1  jonathan {
    545   1.1  jonathan 	static int last_pitch, last_period;
    546   1.1  jonathan 	int s;
    547   1.5      soda 
    548   1.5      soda 	if (cold)
    549   1.5      soda 		return;		/* Can't beep yet. */
    550   1.1  jonathan 
    551   1.1  jonathan 	if (beeping)
    552   1.8   thorpej 		callout_stop(&sysbeep_ch);
    553   1.1  jonathan 	if (!beeping || last_pitch != pitch) {
    554   1.1  jonathan 		s = splhigh();
    555   1.5      soda 		isa_outb(IO_TIMER1 + TIMER_MODE,
    556   1.5      soda 		    TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
    557   1.5      soda 		isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) % 256);
    558   1.5      soda 		isa_outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) / 256);
    559   1.1  jonathan 		isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) | PIT_SPKR);
    560   1.1  jonathan 		splx(s);
    561   1.1  jonathan 	}
    562   1.1  jonathan 	last_pitch = pitch;
    563   1.1  jonathan 	beeping = last_period = period;
    564   1.8   thorpej 	callout_reset(&sysbeep_ch, period, sysbeepstop, NULL);
    565  1.21   tsutsui }
    566  1.21   tsutsui 
    567  1.21   tsutsui int
    568  1.21   tsutsui isa_intr_alloc(isa_chipset_tag_t c, int mask, int type, int *irq_p)
    569  1.21   tsutsui {
    570  1.21   tsutsui 	int irq;
    571  1.21   tsutsui 	int maybe_irq = -1;
    572  1.21   tsutsui 	int shared_depth = 0;
    573  1.21   tsutsui 	mask &= 0x8b28; /* choose from 3, 5, 8, 9, 11, 15 XXX */
    574  1.21   tsutsui 	for (irq = 0; mask != 0; mask >>= 1, irq++) {
    575  1.21   tsutsui 		if ((mask & 1) == 0)
    576  1.21   tsutsui 			continue;
    577  1.21   tsutsui 		if (intrtype[irq] == IST_NONE) {
    578  1.21   tsutsui 			*irq_p = irq;
    579  1.21   tsutsui 			return 0;
    580  1.21   tsutsui 		}
    581  1.21   tsutsui 		/* Level interrupts can be shared */
    582  1.21   tsutsui 		if (type == IST_LEVEL && intrtype[irq] == IST_LEVEL) {
    583  1.32   tsutsui 			struct isa_intrhand *ih = isa_intrhand[irq];
    584  1.21   tsutsui 			int depth;
    585  1.21   tsutsui 			if (maybe_irq == -1) {
    586  1.21   tsutsui  				maybe_irq = irq;
    587  1.21   tsutsui 				continue;
    588  1.21   tsutsui 			}
    589  1.21   tsutsui 			for (depth = 0; ih != NULL; ih = ih->ih_next)
    590  1.21   tsutsui 				depth++;
    591  1.21   tsutsui 			if (depth < shared_depth) {
    592  1.21   tsutsui 				maybe_irq = irq;
    593  1.21   tsutsui 				shared_depth = depth;
    594  1.21   tsutsui 			}
    595  1.21   tsutsui 		}
    596  1.21   tsutsui 	}
    597  1.21   tsutsui 	if (maybe_irq != -1) {
    598  1.21   tsutsui 		*irq_p = maybe_irq;
    599  1.21   tsutsui 		return 0;
    600  1.21   tsutsui 	}
    601  1.21   tsutsui 	return 1;
    602   1.1  jonathan }
    603