xref: /netbsd-src/sys/arch/alpha/pci/sio_pic.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /* $NetBSD: sio_pic.c,v 1.53 2021/07/15 01:29:23 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@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.53 2021/07/15 01:29:23 thorpej Exp $");
63 
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/device.h>
67 #include <sys/cpu.h>
68 #include <sys/syslog.h>
69 
70 #include <machine/alpha.h>
71 #include <machine/intr.h>
72 #include <sys/bus.h>
73 
74 #include <dev/pci/pcireg.h>
75 #include <dev/pci/pcivar.h>
76 #include <dev/pci/pcidevs.h>
77 
78 #include <dev/pci/pciidereg.h>
79 #include <dev/pci/pciidevar.h>
80 
81 #include <dev/ic/i8259reg.h>
82 
83 #include <dev/pci/cy82c693reg.h>
84 #include <dev/pci/cy82c693var.h>
85 
86 #include <dev/isa/isareg.h>
87 #include <dev/isa/isavar.h>
88 #include <alpha/pci/sioreg.h>
89 #include <alpha/pci/siovar.h>
90 
91 #include "sio.h"
92 
93 /*
94  * To add to the long history of wonderful PROM console traits,
95  * AlphaStation PROMs don't reset themselves completely on boot!
96  * Therefore, if an interrupt was turned on when the kernel was
97  * started, we're not going to EVER turn it off...  I don't know
98  * what will happen if new interrupts (that the PROM console doesn't
99  * want) are turned on.  I'll burn that bridge when I come to it.
100  */
101 #define	BROKEN_PROM_CONSOLE
102 
103 /*
104  * Private functions and variables.
105  */
106 
107 static bus_space_tag_t sio_iot;
108 static pci_chipset_tag_t sio_pc;
109 static bus_space_handle_t sio_ioh_icu1, sio_ioh_icu2;
110 
111 #define	ICU_LEN		16		/* number of ISA IRQs */
112 
113 static struct alpha_shared_intr *sio_intr;
114 
115 #ifndef STRAY_MAX
116 #define	STRAY_MAX	5
117 #endif
118 
119 #ifdef BROKEN_PROM_CONSOLE
120 /*
121  * If prom console is broken, must remember the initial interrupt
122  * settings and enforce them.  WHEE!
123  */
124 static uint8_t initial_ocw1[2];
125 static uint8_t initial_elcr[2];
126 #endif
127 
128 static void	sio_setirqstat(int, int, int);
129 
130 static uint8_t	(*sio_read_elcr)(int);
131 static void	(*sio_write_elcr)(int, uint8_t);
132 static void	specific_eoi(int);
133 #ifdef BROKEN_PROM_CONSOLE
134 static void	sio_intr_shutdown(void *);
135 #endif
136 
137 /******************** i82378 SIO ELCR functions ********************/
138 
139 static bus_space_handle_t sio_ioh_elcr;
140 
141 static uint8_t	i82378_read_elcr(int);
142 static void	i82378_write_elcr(int, uint8_t);
143 
144 static int
145 i82378_setup_elcr(void)
146 {
147 	int rv;
148 
149 	/*
150 	 * We could probe configuration space to see that there's
151 	 * actually an SIO present, but we are using this as a
152 	 * fall-back in case nothing else matches.
153 	 */
154 
155 	rv = bus_space_map(sio_iot, SIO_REG_ICU1ELC, 2, 0, &sio_ioh_elcr);
156 
157 	if (rv == 0) {
158 		sio_read_elcr = i82378_read_elcr;
159 		sio_write_elcr = i82378_write_elcr;
160 	}
161 
162 	return (rv);
163 }
164 
165 static uint8_t
166 i82378_read_elcr(int elcr)
167 {
168 
169 	return (bus_space_read_1(sio_iot, sio_ioh_elcr, elcr));
170 }
171 
172 static void
173 i82378_write_elcr(int elcr, uint8_t val)
174 {
175 
176 	bus_space_write_1(sio_iot, sio_ioh_elcr, elcr, val);
177 }
178 
179 /******************** Cypress CY82C693 ELCR functions ********************/
180 
181 static const struct cy82c693_handle *sio_cy82c693_handle;
182 
183 static uint8_t	cy82c693_read_elcr(int);
184 static void	cy82c693_write_elcr(int, uint8_t);
185 
186 static int
187 cy82c693_setup_elcr(void)
188 {
189 	int device, maxndevs;
190 	pcitag_t tag;
191 	pcireg_t id;
192 
193 	/*
194 	 * Search PCI configuration space for a Cypress CY82C693.
195 	 *
196 	 * Note we can make some assumptions about our bus number
197 	 * here, because:
198 	 *
199 	 *	(1) there can be at most one ISA/EISA bridge per PCI bus, and
200 	 *
201 	 *	(2) any ISA/EISA bridges must be attached to primary PCI
202 	 *	    busses (i.e. bus zero).
203 	 */
204 
205 	maxndevs = pci_bus_maxdevs(sio_pc, 0);
206 
207 	for (device = 0; device < maxndevs; device++) {
208 		tag = pci_make_tag(sio_pc, 0, device, 0);
209 		id = pci_conf_read(sio_pc, tag, PCI_ID_REG);
210 
211 		/* Invalid vendor ID value? */
212 		if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
213 			continue;
214 		/* XXX Not invalid, but we've done this ~forever. */
215 		if (PCI_VENDOR(id) == 0)
216 			continue;
217 
218 		if (PCI_VENDOR(id) != PCI_VENDOR_CONTAQ ||
219 		    PCI_PRODUCT(id) != PCI_PRODUCT_CONTAQ_82C693)
220 			continue;
221 
222 		/*
223 		 * Found one!
224 		 */
225 
226 #if 0
227 		printf("cy82c693_setup_elcr: found 82C693 at device %d\n",
228 		    device);
229 #endif
230 
231 		sio_cy82c693_handle = cy82c693_init(sio_iot);
232 		sio_read_elcr = cy82c693_read_elcr;
233 		sio_write_elcr = cy82c693_write_elcr;
234 
235 		return (0);
236 	}
237 
238 	/*
239 	 * Didn't find a CY82C693.
240 	 */
241 	return (ENODEV);
242 }
243 
244 static uint8_t
245 cy82c693_read_elcr(int elcr)
246 {
247 
248 	return (cy82c693_read(sio_cy82c693_handle, CONFIG_ELCR1 + elcr));
249 }
250 
251 static void
252 cy82c693_write_elcr(int elcr, uint8_t val)
253 {
254 
255 	cy82c693_write(sio_cy82c693_handle, CONFIG_ELCR1 + elcr, val);
256 }
257 
258 /******************** ELCR access function configuration ********************/
259 
260 /*
261  * Put the Intel SIO at the end, so we fall back on it if we don't
262  * find anything else.  If any of the non-Intel functions find a
263  * matching device, but are unable to map it for whatever reason,
264  * they should panic.
265  */
266 
267 static int (*const sio_elcr_setup_funcs[])(void) = {
268 	cy82c693_setup_elcr,
269 	i82378_setup_elcr,
270 	NULL,
271 };
272 
273 /******************** Shared SIO/Cypress functions ********************/
274 
275 static inline void
276 specific_eoi(int irq)
277 {
278 	if (irq > 7) {
279 		bus_space_write_1(sio_iot, sio_ioh_icu2, PIC_OCW2,
280 		    OCW2_EOI | OCW2_SL | (irq & 0x07));	/* XXX */
281 	}
282 	bus_space_write_1(sio_iot, sio_ioh_icu1, PIC_OCW2,
283 	    OCW2_EOI | OCW2_SL | (irq > 7 ? 2 : irq));
284 }
285 
286 static void
287 sio_setirqstat(int irq, int enabled, int type)
288 {
289 	uint8_t ocw1[2], elcr[2];
290 	int icu, bit;
291 
292 #if 0
293 	printf("sio_setirqstat: irq %d: %s, %s\n", irq,
294 	    enabled ? "enabled" : "disabled", isa_intr_typename(type));
295 #endif
296 
297 	icu = irq / 8;
298 	bit = irq % 8;
299 
300 	ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, PIC_OCW1);
301 	ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, PIC_OCW1);
302 	elcr[0] = (*sio_read_elcr)(0);				/* XXX */
303 	elcr[1] = (*sio_read_elcr)(1);				/* XXX */
304 
305 	/*
306 	 * interrupt enable: set bit to mask (disable) interrupt.
307 	 */
308 	if (enabled)
309 		ocw1[icu] &= ~(1 << bit);
310 	else
311 		ocw1[icu] |= 1 << bit;
312 
313 	/*
314 	 * interrupt type select: set bit to get level-triggered.
315 	 */
316 	if (type == IST_LEVEL)
317 		elcr[icu] |= 1 << bit;
318 	else
319 		elcr[icu] &= ~(1 << bit);
320 
321 #ifdef not_here
322 	/* see the init function... */
323 	ocw1[0] &= ~0x04;		/* always enable IRQ2 on first PIC */
324 	elcr[0] &= ~0x07;		/* IRQ[0-2] must be edge-triggered */
325 	elcr[1] &= ~0x21;		/* IRQ[13,8] must be edge-triggered */
326 #endif
327 
328 	bus_space_write_1(sio_iot, sio_ioh_icu1, 1, ocw1[0]);
329 	bus_space_write_1(sio_iot, sio_ioh_icu2, 1, ocw1[1]);
330 	(*sio_write_elcr)(0, elcr[0]);				/* XXX */
331 	(*sio_write_elcr)(1, elcr[1]);				/* XXX */
332 }
333 
334 void
335 sio_intr_setup(pci_chipset_tag_t pc, bus_space_tag_t iot)
336 {
337 	struct evcnt *ev;
338 	const char *cp;
339 	int i;
340 
341 	sio_iot = iot;
342 	sio_pc = pc;
343 
344 	if (bus_space_map(sio_iot, IO_ICU1, 2, 0, &sio_ioh_icu1) ||
345 	    bus_space_map(sio_iot, IO_ICU2, 2, 0, &sio_ioh_icu2))
346 		panic("sio_intr_setup: can't map ICU I/O ports");
347 
348 	for (i = 0; sio_elcr_setup_funcs[i] != NULL; i++)
349 		if ((*sio_elcr_setup_funcs[i])() == 0)
350 			break;
351 	if (sio_elcr_setup_funcs[i] == NULL)
352 		panic("sio_intr_setup: can't map ELCR");
353 
354 #ifdef BROKEN_PROM_CONSOLE
355 	/*
356 	 * Remember the initial values, so we can restore them later.
357 	 */
358 	initial_ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
359 	initial_ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
360 	initial_elcr[0] = (*sio_read_elcr)(0);			/* XXX */
361 	initial_elcr[1] = (*sio_read_elcr)(1);			/* XXX */
362 	shutdownhook_establish(sio_intr_shutdown, 0);
363 #endif
364 
365 	sio_intr = alpha_shared_intr_alloc(ICU_LEN);
366 
367 	/*
368 	 * set up initial values for interrupt enables.
369 	 */
370 	for (i = 0; i < ICU_LEN; i++) {
371 		alpha_shared_intr_set_maxstrays(sio_intr, i, STRAY_MAX);
372 
373 		ev = alpha_shared_intr_evcnt(sio_intr, i);
374 		cp = alpha_shared_intr_string(sio_intr, i);
375 
376 		evcnt_attach_dynamic(ev, EVCNT_TYPE_INTR, NULL, "isa", cp);
377 
378 		switch (i) {
379 		case 0:
380 		case 1:
381 		case 8:
382 		case 13:
383 			/*
384 			 * IRQs 0, 1, 8, and 13 must always be
385 			 * edge-triggered.
386 			 */
387 			sio_setirqstat(i, 0, IST_EDGE);
388 			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
389 			    IST_EDGE);
390 			specific_eoi(i);
391 			break;
392 
393 		case 2:
394 			/*
395 			 * IRQ 2 must be edge-triggered, and should be
396 			 * enabled (otherwise IRQs 8-15 are ignored).
397 			 */
398 			sio_setirqstat(i, 1, IST_EDGE);
399 			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
400 			    IST_UNUSABLE);
401 			break;
402 
403 		default:
404 			/*
405 			 * Otherwise, disable the IRQ and set its
406 			 * type to (effectively) "unknown."
407 			 */
408 			sio_setirqstat(i, 0, IST_NONE);
409 			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
410 			    IST_NONE);
411 			specific_eoi(i);
412 			break;
413 		}
414 	}
415 }
416 
417 #ifdef BROKEN_PROM_CONSOLE
418 static void
419 sio_intr_shutdown(void *arg)
420 {
421 	/*
422 	 * Restore the initial values, to make the PROM happy.
423 	 */
424 	bus_space_write_1(sio_iot, sio_ioh_icu1, 1, initial_ocw1[0]);
425 	bus_space_write_1(sio_iot, sio_ioh_icu2, 1, initial_ocw1[1]);
426 	(*sio_write_elcr)(0, initial_elcr[0]);			/* XXX */
427 	(*sio_write_elcr)(1, initial_elcr[1]);			/* XXX */
428 }
429 #endif
430 
431 const char *
432 sio_intr_string(void *v, int irq, char *buf, size_t len)
433 {
434 	if (irq == 0 || irq >= ICU_LEN || irq == 2)
435 		panic("%s: bogus isa irq 0x%x", __func__, irq);
436 
437 	snprintf(buf, len, "isa irq %d", irq);
438 	return buf;
439 }
440 
441 const struct evcnt *
442 sio_intr_evcnt(void *v, int irq)
443 {
444 
445 	if (irq == 0 || irq >= ICU_LEN || irq == 2)
446 		panic("%s: bogus isa irq 0x%x", __func__, irq);
447 
448 	return (alpha_shared_intr_evcnt(sio_intr, irq));
449 }
450 
451 void *
452 sio_intr_establish(void *v, int irq, int type, int level, int flags,
453     int (*fn)(void *), void *arg)
454 {
455 	void *cookie;
456 
457 	if (irq > ICU_LEN || type == IST_NONE)
458 		panic("sio_intr_establish: bogus irq or type");
459 
460 	cookie = alpha_shared_intr_alloc_intrhand(sio_intr, irq, type, level,
461 	    flags, fn, arg, "isa");
462 
463 	if (cookie == NULL)
464 		return NULL;
465 
466 	mutex_enter(&cpu_lock);
467 
468 	if (! alpha_shared_intr_link(sio_intr, cookie, "isa")) {
469 		mutex_exit(&cpu_lock);
470 		alpha_shared_intr_free_intrhand(cookie);
471 		return NULL;
472 	}
473 
474 	if (alpha_shared_intr_firstactive(sio_intr, irq)) {
475 		scb_set(0x800 + SCB_IDXTOVEC(irq), sio_iointr, NULL);
476 		sio_setirqstat(irq, 1,
477 		    alpha_shared_intr_get_sharetype(sio_intr, irq));
478 
479 		/*
480 		 * I've obsesrved stray ISA interrupts when interacting
481 		 * with the serial console under Qemu.  Work around that
482 		 * for now by suppressing stray interrupt reporting for
483 		 * edge-triggered interrupts.
484 		 */
485 		if (alpha_is_qemu && type == IST_EDGE) {
486 			alpha_shared_intr_set_maxstrays(sio_intr, irq, 0);
487 		}
488 	}
489 
490 	mutex_exit(&cpu_lock);
491 
492 	return cookie;
493 }
494 
495 void
496 sio_intr_disestablish(void *v, void *cookie)
497 {
498 	struct alpha_shared_intrhand *ih = cookie;
499 	int ist, irq = ih->ih_num;
500 
501 	mutex_enter(&cpu_lock);
502 
503 	/*
504 	 * Decide if we should disable the interrupt.  We must ensure
505 	 * that:
506 	 *
507 	 *	- An initially-enabled interrupt is never disabled.
508 	 *	- An initially-LT interrupt is never untyped.
509 	 */
510 	if (alpha_shared_intr_firstactive(sio_intr, irq)) {
511 		/*
512 		 * IRQs 0, 1, 8, and 13 must always be edge-triggered
513 		 * (see setup).
514 		 */
515 		switch (irq) {
516 		case 0:
517 		case 1:
518 		case 8:
519 		case 13:
520 			/*
521 			 * If the interrupt was initially level-triggered
522 			 * a warning was printed in setup.
523 			 */
524 			ist = IST_EDGE;
525 			break;
526 
527 		default:
528 			ist = IST_NONE;
529 			break;
530 		}
531 		sio_setirqstat(irq, 0, ist);
532 		alpha_shared_intr_set_dfltsharetype(sio_intr, irq, ist);
533 		alpha_shared_intr_set_maxstrays(sio_intr, irq, STRAY_MAX);
534 
535 		/* Release our SCB vector. */
536 		scb_free(0x800 + SCB_IDXTOVEC(irq));
537 	}
538 
539 	/* Remove it from the link. */
540 	alpha_shared_intr_unlink(sio_intr, cookie, "isa");
541 
542 	mutex_exit(&cpu_lock);
543 
544 	alpha_shared_intr_free_intrhand(cookie);
545 }
546 
547 /* XXX All known Alpha systems with Intel i82378 have it at device 7. */
548 #define	SIO_I82378_DEV		7
549 
550 int
551 sio_pirq_intr_map(pci_chipset_tag_t pc, int pirq, pci_intr_handle_t *ihp)
552 {
553 	KASSERT(pirq >= 0 && pirq <= 3);
554 	KASSERT(pc == sio_pc);
555 
556 	const pcireg_t rtctrl =
557 	    pci_conf_read(sio_pc, pci_make_tag(sio_pc, 0, SIO_I82378_DEV, 0),
558 			  SIO_PCIREG_PIRQ_RTCTRL);
559 	const pcireg_t pirqreg = PIRQ_RTCTRL_PIRQx(rtctrl, pirq);
560 
561 	if (pirqreg & PIRQ_RTCTRL_NOT_ROUTED) {
562 		/* not routed -> no mapping */
563 		return 1;
564 	}
565 
566 	const int irq = __SHIFTOUT(pirqreg, PIRQ_RTCTRL_IRQ);
567 
568 #if 0
569 	printf("sio_pirq_intr_map: pirq %d -> ISA irq %d, rtctl = 0x%08x\n",
570 	    pirq, irq, rtctrl);
571 #endif
572 
573 	alpha_pci_intr_handle_init(ihp, irq, 0);
574 	return 0;
575 }
576 
577 const char *
578 sio_pci_intr_string(pci_chipset_tag_t const pc, pci_intr_handle_t const ih,
579     char * const buf, size_t const len)
580 {
581 	const u_int irq = alpha_pci_intr_handle_get_irq(&ih);
582 
583 	return sio_intr_string(NULL /*XXX*/, irq, buf, len);
584 }
585 
586 const struct evcnt *
587 sio_pci_intr_evcnt(pci_chipset_tag_t const pc, pci_intr_handle_t const ih)
588 {
589 	const u_int irq = alpha_pci_intr_handle_get_irq(&ih);
590 
591 	return sio_intr_evcnt(NULL /*XXX*/, irq);
592 }
593 
594 void *
595 sio_pci_intr_establish(pci_chipset_tag_t const pc, pci_intr_handle_t ih,
596     int const level, int (*func)(void *), void *arg)
597 {
598 	const u_int irq = alpha_pci_intr_handle_get_irq(&ih);
599 	const u_int flags = alpha_pci_intr_handle_get_flags(&ih);
600 
601 	return sio_intr_establish(NULL /*XXX*/, irq, IST_LEVEL, level, flags,
602 	    func, arg);
603 }
604 
605 void
606 sio_pci_intr_disestablish(pci_chipset_tag_t const pc, void *cookie)
607 {
608 	sio_intr_disestablish(NULL /*XXX*/, cookie);
609 }
610 
611 void *
612 sio_pciide_compat_intr_establish(device_t const dev,
613     const struct pci_attach_args * const pa,
614     int const chan, int (*func)(void *), void *arg)
615 {
616 	pci_chipset_tag_t const pc = pa->pa_pc;
617 	void *cookie;
618 	int bus, irq;
619 	char buf[64];
620 	int flags = 0;	/* XXX How to pass MPSAFE? */
621 
622 	pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL);
623 
624 	/*
625 	 * If this isn't PCI bus #0, all bets are off.
626 	 */
627 	if (bus != 0)
628 		return NULL;
629 
630 	irq = PCIIDE_COMPAT_IRQ(chan);
631 	cookie = sio_intr_establish(NULL /*XXX*/, irq, IST_EDGE, IPL_BIO,
632 	    flags, func, arg);
633 	if (cookie == NULL)
634 		return NULL;
635 
636 	aprint_normal_dev(dev, "%s channel interrupting at %s\n",
637 	    PCIIDE_CHANNEL_NAME(chan),
638 	    sio_intr_string(NULL /*XXX*/, irq, buf, sizeof(buf)));
639 
640 	return cookie;
641 }
642 
643 void *
644 sio_isa_intr_establish(void *v, int irq, int type, int level,
645     int (*fn)(void *), void *arg)
646 {
647 	return sio_intr_establish(v, irq, type, level, 0, fn, arg);
648 }
649 
650 void
651 sio_iointr(void *arg, unsigned long vec)
652 {
653 	int irq;
654 
655 	irq = SCB_VECTOIDX(vec - 0x800);
656 
657 #ifdef DIAGNOSTIC
658 	if (irq > ICU_LEN || irq < 0)
659 		panic("sio_iointr: irq out of range (%d)", irq);
660 #endif
661 
662 	if (!alpha_shared_intr_dispatch(sio_intr, irq))
663 		alpha_shared_intr_stray(sio_intr, irq, "isa");
664 	else
665 		alpha_shared_intr_reset_strays(sio_intr, irq);
666 
667 	/*
668 	 * Some versions of the machines which use the SIO
669 	 * (or is it some PALcode revisions on those machines?)
670 	 * require the non-specific EOI to be fed to the PIC(s)
671 	 * by the interrupt handler.
672 	 */
673 	specific_eoi(irq);
674 }
675 
676 #define	LEGAL_IRQ(x)	((x) >= 0 && (x) < ICU_LEN && (x) != 2)
677 
678 int
679 sio_intr_alloc(void *v, int mask, int type, int *irq)
680 {
681 	int i, tmp, bestirq, count;
682 	struct alpha_shared_intrhand **p, *q;
683 
684 	if (type == IST_NONE)
685 		panic("intr_alloc: bogus type");
686 
687 	bestirq = -1;
688 	count = -1;
689 
690 	/* some interrupts should never be dynamically allocated */
691 	mask &= 0xdef8;
692 
693 	/*
694 	 * XXX some interrupts will be used later (6 for fdc, 12 for pms).
695 	 * the right answer is to do "breadth-first" searching of devices.
696 	 */
697 	mask &= 0xefbf;
698 
699 	for (i = 0; i < ICU_LEN; i++) {
700 		if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
701 			continue;
702 
703 		switch(sio_intr[i].intr_sharetype) {
704 		case IST_NONE:
705 			/*
706 			 * if nothing's using the irq, just return it
707 			 */
708 			*irq = i;
709 			return (0);
710 
711 		case IST_EDGE:
712 		case IST_LEVEL:
713 			if (type != sio_intr[i].intr_sharetype)
714 				continue;
715 			/*
716 			 * if the irq is shareable, count the number of other
717 			 * handlers, and if it's smaller than the last irq like
718 			 * this, remember it
719 			 *
720 			 * XXX We should probably also consider the
721 			 * interrupt level and stick IPL_TTY with other
722 			 * IPL_TTY, etc.
723 			 */
724 			for (p = &TAILQ_FIRST(&sio_intr[i].intr_q), tmp = 0;
725 			     (q = *p) != NULL; p = &TAILQ_NEXT(q, ih_q), tmp++)
726 				;
727 			if ((bestirq == -1) || (count > tmp)) {
728 				bestirq = i;
729 				count = tmp;
730 			}
731 			break;
732 
733 		case IST_PULSE:
734 			/* this just isn't shareable */
735 			continue;
736 		}
737 	}
738 
739 	if (bestirq == -1)
740 		return (1);
741 
742 	*irq = bestirq;
743 
744 	return (0);
745 }
746