Home | History | Annotate | Line # | Download | only in pci
sio_pic.c revision 1.47
      1 /* $NetBSD: sio_pic.c,v 1.47 2021/05/07 16:58:34 thorpej Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1998, 2000, 2020 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 /*
     34  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
     35  * All rights reserved.
     36  *
     37  * Author: Chris G. Demetriou
     38  *
     39  * Permission to use, copy, modify and distribute this software and
     40  * its documentation is hereby granted, provided that both the copyright
     41  * notice and this permission notice appear in all copies of the
     42  * software, derivative works or modified versions, and any portions
     43  * thereof, and that both notices appear in supporting documentation.
     44  *
     45  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     46  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     47  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     48  *
     49  * Carnegie Mellon requests users of this software to return to
     50  *
     51  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     52  *  School of Computer Science
     53  *  Carnegie Mellon University
     54  *  Pittsburgh PA 15213-3890
     55  *
     56  * any improvements or extensions that they make and grant Carnegie the
     57  * rights to redistribute these changes.
     58  */
     59 
     60 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     61 
     62 __KERNEL_RCSID(0, "$NetBSD: sio_pic.c,v 1.47 2021/05/07 16:58:34 thorpej Exp $");
     63 
     64 #include <sys/param.h>
     65 #include <sys/systm.h>
     66 #include <sys/device.h>
     67 #include <sys/malloc.h>
     68 #include <sys/cpu.h>
     69 #include <sys/syslog.h>
     70 
     71 #include <machine/alpha.h>
     72 #include <machine/intr.h>
     73 #include <sys/bus.h>
     74 
     75 #include <dev/pci/pcireg.h>
     76 #include <dev/pci/pcivar.h>
     77 #include <dev/pci/pcidevs.h>
     78 
     79 #include <dev/pci/pciidereg.h>
     80 #include <dev/pci/pciidevar.h>
     81 
     82 #include <dev/pci/cy82c693reg.h>
     83 #include <dev/pci/cy82c693var.h>
     84 
     85 #include <dev/isa/isareg.h>
     86 #include <dev/isa/isavar.h>
     87 #include <alpha/pci/siovar.h>
     88 
     89 #include "sio.h"
     90 
     91 /*
     92  * To add to the long history of wonderful PROM console traits,
     93  * AlphaStation PROMs don't reset themselves completely on boot!
     94  * Therefore, if an interrupt was turned on when the kernel was
     95  * started, we're not going to EVER turn it off...  I don't know
     96  * what will happen if new interrupts (that the PROM console doesn't
     97  * want) are turned on.  I'll burn that bridge when I come to it.
     98  */
     99 #define	BROKEN_PROM_CONSOLE
    100 
    101 /*
    102  * Private functions and variables.
    103  */
    104 
    105 bus_space_tag_t sio_iot;
    106 pci_chipset_tag_t sio_pc;
    107 bus_space_handle_t sio_ioh_icu1, sio_ioh_icu2;
    108 
    109 #define	ICU_LEN		16		/* number of ISA IRQs */
    110 
    111 static struct alpha_shared_intr *sio_intr;
    112 
    113 #ifndef STRAY_MAX
    114 #define	STRAY_MAX	5
    115 #endif
    116 
    117 #ifdef BROKEN_PROM_CONSOLE
    118 /*
    119  * If prom console is broken, must remember the initial interrupt
    120  * settings and enforce them.  WHEE!
    121  */
    122 static uint8_t initial_ocw1[2];
    123 static uint8_t initial_elcr[2];
    124 #endif
    125 
    126 static void	sio_setirqstat(int, int, int);
    127 
    128 static uint8_t	(*sio_read_elcr)(int);
    129 static void	(*sio_write_elcr)(int, uint8_t);
    130 static void	specific_eoi(int);
    131 #ifdef BROKEN_PROM_CONSOLE
    132 static void	sio_intr_shutdown(void *);
    133 #endif
    134 
    135 /******************** i82378 SIO ELCR functions ********************/
    136 
    137 static bus_space_handle_t sio_ioh_elcr;
    138 
    139 static uint8_t	i82378_read_elcr(int);
    140 static void	i82378_write_elcr(int, uint8_t);
    141 
    142 static int
    143 i82378_setup_elcr(void)
    144 {
    145 	int rv;
    146 
    147 	/*
    148 	 * We could probe configuration space to see that there's
    149 	 * actually an SIO present, but we are using this as a
    150 	 * fall-back in case nothing else matches.
    151 	 */
    152 
    153 	rv = bus_space_map(sio_iot, 0x4d0, 2, 0, &sio_ioh_elcr);
    154 
    155 	if (rv == 0) {
    156 		sio_read_elcr = i82378_read_elcr;
    157 		sio_write_elcr = i82378_write_elcr;
    158 	}
    159 
    160 	return (rv);
    161 }
    162 
    163 static uint8_t
    164 i82378_read_elcr(int elcr)
    165 {
    166 
    167 	return (bus_space_read_1(sio_iot, sio_ioh_elcr, elcr));
    168 }
    169 
    170 static void
    171 i82378_write_elcr(int elcr, uint8_t val)
    172 {
    173 
    174 	bus_space_write_1(sio_iot, sio_ioh_elcr, elcr, val);
    175 }
    176 
    177 /******************** Cypress CY82C693 ELCR functions ********************/
    178 
    179 static const struct cy82c693_handle *sio_cy82c693_handle;
    180 
    181 static uint8_t	cy82c693_read_elcr(int);
    182 static void	cy82c693_write_elcr(int, uint8_t);
    183 
    184 static int
    185 cy82c693_setup_elcr(void)
    186 {
    187 	int device, maxndevs;
    188 	pcitag_t tag;
    189 	pcireg_t id;
    190 
    191 	/*
    192 	 * Search PCI configuration space for a Cypress CY82C693.
    193 	 *
    194 	 * Note we can make some assumptions about our bus number
    195 	 * here, because:
    196 	 *
    197 	 *	(1) there can be at most one ISA/EISA bridge per PCI bus, and
    198 	 *
    199 	 *	(2) any ISA/EISA bridges must be attached to primary PCI
    200 	 *	    busses (i.e. bus zero).
    201 	 */
    202 
    203 	maxndevs = pci_bus_maxdevs(sio_pc, 0);
    204 
    205 	for (device = 0; device < maxndevs; device++) {
    206 		tag = pci_make_tag(sio_pc, 0, device, 0);
    207 		id = pci_conf_read(sio_pc, tag, PCI_ID_REG);
    208 
    209 		/* Invalid vendor ID value? */
    210 		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
    211 			continue;
    212 		/* XXX Not invalid, but we've done this ~forever. */
    213 		if (PCI_VENDOR(id) == 0)
    214 			continue;
    215 
    216 		if (PCI_VENDOR(id) != PCI_VENDOR_CONTAQ ||
    217 		    PCI_PRODUCT(id) != PCI_PRODUCT_CONTAQ_82C693)
    218 			continue;
    219 
    220 		/*
    221 		 * Found one!
    222 		 */
    223 
    224 #if 0
    225 		printf("cy82c693_setup_elcr: found 82C693 at device %d\n",
    226 		    device);
    227 #endif
    228 
    229 		sio_cy82c693_handle = cy82c693_init(sio_iot);
    230 		sio_read_elcr = cy82c693_read_elcr;
    231 		sio_write_elcr = cy82c693_write_elcr;
    232 
    233 		return (0);
    234 	}
    235 
    236 	/*
    237 	 * Didn't find a CY82C693.
    238 	 */
    239 	return (ENODEV);
    240 }
    241 
    242 static uint8_t
    243 cy82c693_read_elcr(int elcr)
    244 {
    245 
    246 	return (cy82c693_read(sio_cy82c693_handle, CONFIG_ELCR1 + elcr));
    247 }
    248 
    249 static void
    250 cy82c693_write_elcr(int elcr, uint8_t val)
    251 {
    252 
    253 	cy82c693_write(sio_cy82c693_handle, CONFIG_ELCR1 + elcr, val);
    254 }
    255 
    256 /******************** ELCR access function configuration ********************/
    257 
    258 /*
    259  * Put the Intel SIO at the end, so we fall back on it if we don't
    260  * find anything else.  If any of the non-Intel functions find a
    261  * matching device, but are unable to map it for whatever reason,
    262  * they should panic.
    263  */
    264 
    265 int (*const sio_elcr_setup_funcs[])(void) = {
    266 	cy82c693_setup_elcr,
    267 	i82378_setup_elcr,
    268 	NULL,
    269 };
    270 
    271 /******************** Shared SIO/Cypress functions ********************/
    272 
    273 static void
    274 sio_setirqstat(int irq, int enabled, int type)
    275 {
    276 	uint8_t ocw1[2], elcr[2];
    277 	int icu, bit;
    278 
    279 #if 0
    280 	printf("sio_setirqstat: irq %d: %s, %s\n", irq,
    281 	    enabled ? "enabled" : "disabled", isa_intr_typename(type));
    282 #endif
    283 
    284 	icu = irq / 8;
    285 	bit = irq % 8;
    286 
    287 	ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
    288 	ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
    289 	elcr[0] = (*sio_read_elcr)(0);				/* XXX */
    290 	elcr[1] = (*sio_read_elcr)(1);				/* XXX */
    291 
    292 	/*
    293 	 * interrupt enable: set bit to mask (disable) interrupt.
    294 	 */
    295 	if (enabled)
    296 		ocw1[icu] &= ~(1 << bit);
    297 	else
    298 		ocw1[icu] |= 1 << bit;
    299 
    300 	/*
    301 	 * interrupt type select: set bit to get level-triggered.
    302 	 */
    303 	if (type == IST_LEVEL)
    304 		elcr[icu] |= 1 << bit;
    305 	else
    306 		elcr[icu] &= ~(1 << bit);
    307 
    308 #ifdef not_here
    309 	/* see the init function... */
    310 	ocw1[0] &= ~0x04;		/* always enable IRQ2 on first PIC */
    311 	elcr[0] &= ~0x07;		/* IRQ[0-2] must be edge-triggered */
    312 	elcr[1] &= ~0x21;		/* IRQ[13,8] must be edge-triggered */
    313 #endif
    314 
    315 	bus_space_write_1(sio_iot, sio_ioh_icu1, 1, ocw1[0]);
    316 	bus_space_write_1(sio_iot, sio_ioh_icu2, 1, ocw1[1]);
    317 	(*sio_write_elcr)(0, elcr[0]);				/* XXX */
    318 	(*sio_write_elcr)(1, elcr[1]);				/* XXX */
    319 }
    320 
    321 void
    322 sio_intr_setup(pci_chipset_tag_t pc, bus_space_tag_t iot)
    323 {
    324 	char *cp;
    325 	int i;
    326 
    327 	sio_iot = iot;
    328 	sio_pc = pc;
    329 
    330 	if (bus_space_map(sio_iot, IO_ICU1, 2, 0, &sio_ioh_icu1) ||
    331 	    bus_space_map(sio_iot, IO_ICU2, 2, 0, &sio_ioh_icu2))
    332 		panic("sio_intr_setup: can't map ICU I/O ports");
    333 
    334 	for (i = 0; sio_elcr_setup_funcs[i] != NULL; i++)
    335 		if ((*sio_elcr_setup_funcs[i])() == 0)
    336 			break;
    337 	if (sio_elcr_setup_funcs[i] == NULL)
    338 		panic("sio_intr_setup: can't map ELCR");
    339 
    340 #ifdef BROKEN_PROM_CONSOLE
    341 	/*
    342 	 * Remember the initial values, so we can restore them later.
    343 	 */
    344 	initial_ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
    345 	initial_ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
    346 	initial_elcr[0] = (*sio_read_elcr)(0);			/* XXX */
    347 	initial_elcr[1] = (*sio_read_elcr)(1);			/* XXX */
    348 	shutdownhook_establish(sio_intr_shutdown, 0);
    349 #endif
    350 
    351 #define PCI_SIO_IRQ_STR	8
    352 	sio_intr = alpha_shared_intr_alloc(ICU_LEN, PCI_SIO_IRQ_STR);
    353 
    354 	/*
    355 	 * set up initial values for interrupt enables.
    356 	 */
    357 	for (i = 0; i < ICU_LEN; i++) {
    358 		alpha_shared_intr_set_maxstrays(sio_intr, i, STRAY_MAX);
    359 
    360 		cp = alpha_shared_intr_string(sio_intr, i);
    361 		snprintf(cp, PCI_SIO_IRQ_STR, "irq %d", i);
    362 		evcnt_attach_dynamic(alpha_shared_intr_evcnt(sio_intr, i),
    363 		    EVCNT_TYPE_INTR, NULL, "isa", cp);
    364 
    365 		switch (i) {
    366 		case 0:
    367 		case 1:
    368 		case 8:
    369 		case 13:
    370 			/*
    371 			 * IRQs 0, 1, 8, and 13 must always be
    372 			 * edge-triggered.
    373 			 */
    374 			sio_setirqstat(i, 0, IST_EDGE);
    375 			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
    376 			    IST_EDGE);
    377 			specific_eoi(i);
    378 			break;
    379 
    380 		case 2:
    381 			/*
    382 			 * IRQ 2 must be edge-triggered, and should be
    383 			 * enabled (otherwise IRQs 8-15 are ignored).
    384 			 */
    385 			sio_setirqstat(i, 1, IST_EDGE);
    386 			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
    387 			    IST_UNUSABLE);
    388 			break;
    389 
    390 		default:
    391 			/*
    392 			 * Otherwise, disable the IRQ and set its
    393 			 * type to (effectively) "unknown."
    394 			 */
    395 			sio_setirqstat(i, 0, IST_NONE);
    396 			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
    397 			    IST_NONE);
    398 			specific_eoi(i);
    399 			break;
    400 		}
    401 	}
    402 }
    403 
    404 #ifdef BROKEN_PROM_CONSOLE
    405 static void
    406 sio_intr_shutdown(void *arg)
    407 {
    408 	/*
    409 	 * Restore the initial values, to make the PROM happy.
    410 	 */
    411 	bus_space_write_1(sio_iot, sio_ioh_icu1, 1, initial_ocw1[0]);
    412 	bus_space_write_1(sio_iot, sio_ioh_icu2, 1, initial_ocw1[1]);
    413 	(*sio_write_elcr)(0, initial_elcr[0]);			/* XXX */
    414 	(*sio_write_elcr)(1, initial_elcr[1]);			/* XXX */
    415 }
    416 #endif
    417 
    418 const char *
    419 sio_intr_string(void *v, int irq, char *buf, size_t len)
    420 {
    421 	if (irq == 0 || irq >= ICU_LEN || irq == 2)
    422 		panic("%s: bogus isa irq 0x%x", __func__, irq);
    423 
    424 	snprintf(buf, len, "isa irq %d", irq);
    425 	return buf;
    426 }
    427 
    428 const struct evcnt *
    429 sio_intr_evcnt(void *v, int irq)
    430 {
    431 
    432 	if (irq == 0 || irq >= ICU_LEN || irq == 2)
    433 		panic("%s: bogus isa irq 0x%x", __func__, irq);
    434 
    435 	return (alpha_shared_intr_evcnt(sio_intr, irq));
    436 }
    437 
    438 void *
    439 sio_intr_establish(void *v, int irq, int type, int level, int flags,
    440     int (*fn)(void *), void *arg)
    441 {
    442 	void *cookie;
    443 
    444 	if (irq > ICU_LEN || type == IST_NONE)
    445 		panic("sio_intr_establish: bogus irq or type");
    446 
    447 	cookie = alpha_shared_intr_alloc_intrhand(sio_intr, irq, type, level,
    448 	    flags, fn, arg, "isa irq");
    449 
    450 	if (cookie == NULL)
    451 		return NULL;
    452 
    453 	mutex_enter(&cpu_lock);
    454 
    455 	if (! alpha_shared_intr_link(sio_intr, cookie, "isa irq")) {
    456 		mutex_exit(&cpu_lock);
    457 		alpha_shared_intr_free_intrhand(cookie);
    458 		return NULL;
    459 	}
    460 
    461 	if (alpha_shared_intr_firstactive(sio_intr, irq)) {
    462 		scb_set(0x800 + SCB_IDXTOVEC(irq), sio_iointr, NULL);
    463 		sio_setirqstat(irq, 1,
    464 		    alpha_shared_intr_get_sharetype(sio_intr, irq));
    465 
    466 		/*
    467 		 * I've obsesrved stray ISA interrupts when interacting
    468 		 * with the serial console under Qemu.  Work around that
    469 		 * for now by suppressing stray interrupt reporting for
    470 		 * edge-triggered interrupts.
    471 		 */
    472 		if (alpha_is_qemu && type == IST_EDGE) {
    473 			alpha_shared_intr_set_maxstrays(sio_intr, irq, 0);
    474 		}
    475 	}
    476 
    477 	mutex_exit(&cpu_lock);
    478 
    479 	return cookie;
    480 }
    481 
    482 void
    483 sio_intr_disestablish(void *v, void *cookie)
    484 {
    485 	struct alpha_shared_intrhand *ih = cookie;
    486 	int ist, irq = ih->ih_num;
    487 
    488 	mutex_enter(&cpu_lock);
    489 
    490 	/*
    491 	 * Decide if we should disable the interrupt.  We must ensure
    492 	 * that:
    493 	 *
    494 	 *	- An initially-enabled interrupt is never disabled.
    495 	 *	- An initially-LT interrupt is never untyped.
    496 	 */
    497 	if (alpha_shared_intr_firstactive(sio_intr, irq)) {
    498 		/*
    499 		 * IRQs 0, 1, 8, and 13 must always be edge-triggered
    500 		 * (see setup).
    501 		 */
    502 		switch (irq) {
    503 		case 0:
    504 		case 1:
    505 		case 8:
    506 		case 13:
    507 			/*
    508 			 * If the interrupt was initially level-triggered
    509 			 * a warning was printed in setup.
    510 			 */
    511 			ist = IST_EDGE;
    512 			break;
    513 
    514 		default:
    515 			ist = IST_NONE;
    516 			break;
    517 		}
    518 		sio_setirqstat(irq, 0, ist);
    519 		alpha_shared_intr_set_dfltsharetype(sio_intr, irq, ist);
    520 		alpha_shared_intr_set_maxstrays(sio_intr, irq, STRAY_MAX);
    521 
    522 		/* Release our SCB vector. */
    523 		scb_free(0x800 + SCB_IDXTOVEC(irq));
    524 	}
    525 
    526 	/* Remove it from the link. */
    527 	alpha_shared_intr_unlink(sio_intr, cookie, "isa irq");
    528 
    529 	mutex_exit(&cpu_lock);
    530 
    531 	alpha_shared_intr_free_intrhand(cookie);
    532 }
    533 
    534 const char *
    535 sio_pci_intr_string(pci_chipset_tag_t const pc, pci_intr_handle_t const ih,
    536     char * const buf, size_t const len)
    537 {
    538 	const u_int irq = alpha_pci_intr_handle_get_irq(&ih);
    539 
    540 	return sio_intr_string(NULL /*XXX*/, irq, buf, len);
    541 }
    542 
    543 const struct evcnt *
    544 sio_pci_intr_evcnt(pci_chipset_tag_t const pc, pci_intr_handle_t const ih)
    545 {
    546 	const u_int irq = alpha_pci_intr_handle_get_irq(&ih);
    547 
    548 	return sio_intr_evcnt(NULL /*XXX*/, irq);
    549 }
    550 
    551 void *
    552 sio_pci_intr_establish(pci_chipset_tag_t const pc, pci_intr_handle_t ih,
    553     int const level, int (*func)(void *), void *arg)
    554 {
    555 	const u_int irq = alpha_pci_intr_handle_get_irq(&ih);
    556 	const u_int flags = alpha_pci_intr_handle_get_flags(&ih);
    557 
    558 	return sio_intr_establish(NULL /*XXX*/, irq, IST_LEVEL, level, flags,
    559 	    func, arg);
    560 }
    561 
    562 void
    563 sio_pci_intr_disestablish(pci_chipset_tag_t const pc, void *cookie)
    564 {
    565 	sio_intr_disestablish(NULL /*XXX*/, cookie);
    566 }
    567 
    568 void *
    569 sio_pciide_compat_intr_establish(device_t const dev,
    570     const struct pci_attach_args * const pa,
    571     int const chan, int (*func)(void *), void *arg)
    572 {
    573 	pci_chipset_tag_t const pc = pa->pa_pc;
    574 	void *cookie;
    575 	int bus, irq;
    576 	char buf[64];
    577 	int flags = 0;	/* XXX How to pass MPSAFE? */
    578 
    579 	pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL);
    580 
    581 	/*
    582 	 * If this isn't PCI bus #0, all bets are off.
    583 	 */
    584 	if (bus != 0)
    585 		return NULL;
    586 
    587 	irq = PCIIDE_COMPAT_IRQ(chan);
    588 	cookie = sio_intr_establish(NULL /*XXX*/, irq, IST_EDGE, IPL_BIO,
    589 	    flags, func, arg);
    590 	if (cookie == NULL)
    591 		return NULL;
    592 
    593 	aprint_normal_dev(dev, "%s channel interrupting at %s\n",
    594 	    PCIIDE_CHANNEL_NAME(chan),
    595 	    sio_intr_string(NULL /*XXX*/, irq, buf, sizeof(buf)));
    596 
    597 	return cookie;
    598 }
    599 
    600 void *
    601 sio_isa_intr_establish(void *v, int irq, int type, int level,
    602     int (*fn)(void *), void *arg)
    603 {
    604 	return sio_intr_establish(v, irq, type, level, 0, fn, arg);
    605 }
    606 
    607 void
    608 sio_iointr(void *arg, unsigned long vec)
    609 {
    610 	int irq;
    611 
    612 	irq = SCB_VECTOIDX(vec - 0x800);
    613 
    614 #ifdef DIAGNOSTIC
    615 	if (irq > ICU_LEN || irq < 0)
    616 		panic("sio_iointr: irq out of range (%d)", irq);
    617 #endif
    618 
    619 	if (!alpha_shared_intr_dispatch(sio_intr, irq))
    620 		alpha_shared_intr_stray(sio_intr, irq, "isa irq");
    621 	else
    622 		alpha_shared_intr_reset_strays(sio_intr, irq);
    623 
    624 	/*
    625 	 * Some versions of the machines which use the SIO
    626 	 * (or is it some PALcode revisions on those machines?)
    627 	 * require the non-specific EOI to be fed to the PIC(s)
    628 	 * by the interrupt handler.
    629 	 */
    630 	specific_eoi(irq);
    631 }
    632 
    633 #define	LEGAL_IRQ(x)	((x) >= 0 && (x) < ICU_LEN && (x) != 2)
    634 
    635 int
    636 sio_intr_alloc(void *v, int mask, int type, int *irq)
    637 {
    638 	int i, tmp, bestirq, count;
    639 	struct alpha_shared_intrhand **p, *q;
    640 
    641 	if (type == IST_NONE)
    642 		panic("intr_alloc: bogus type");
    643 
    644 	bestirq = -1;
    645 	count = -1;
    646 
    647 	/* some interrupts should never be dynamically allocated */
    648 	mask &= 0xdef8;
    649 
    650 	/*
    651 	 * XXX some interrupts will be used later (6 for fdc, 12 for pms).
    652 	 * the right answer is to do "breadth-first" searching of devices.
    653 	 */
    654 	mask &= 0xefbf;
    655 
    656 	for (i = 0; i < ICU_LEN; i++) {
    657 		if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
    658 			continue;
    659 
    660 		switch(sio_intr[i].intr_sharetype) {
    661 		case IST_NONE:
    662 			/*
    663 			 * if nothing's using the irq, just return it
    664 			 */
    665 			*irq = i;
    666 			return (0);
    667 
    668 		case IST_EDGE:
    669 		case IST_LEVEL:
    670 			if (type != sio_intr[i].intr_sharetype)
    671 				continue;
    672 			/*
    673 			 * if the irq is shareable, count the number of other
    674 			 * handlers, and if it's smaller than the last irq like
    675 			 * this, remember it
    676 			 *
    677 			 * XXX We should probably also consider the
    678 			 * interrupt level and stick IPL_TTY with other
    679 			 * IPL_TTY, etc.
    680 			 */
    681 			for (p = &TAILQ_FIRST(&sio_intr[i].intr_q), tmp = 0;
    682 			     (q = *p) != NULL; p = &TAILQ_NEXT(q, ih_q), tmp++)
    683 				;
    684 			if ((bestirq == -1) || (count > tmp)) {
    685 				bestirq = i;
    686 				count = tmp;
    687 			}
    688 			break;
    689 
    690 		case IST_PULSE:
    691 			/* this just isn't shareable */
    692 			continue;
    693 		}
    694 	}
    695 
    696 	if (bestirq == -1)
    697 		return (1);
    698 
    699 	*irq = bestirq;
    700 
    701 	return (0);
    702 }
    703 
    704 static void
    705 specific_eoi(int irq)
    706 {
    707 	if (irq > 7)
    708 		bus_space_write_1(sio_iot,
    709 		    sio_ioh_icu2, 0, 0x60 | (irq & 0x07));	/* XXX */
    710 	bus_space_write_1(sio_iot, sio_ioh_icu1, 0, 0x60 | (irq > 7 ? 2 : irq));
    711 }
    712