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