sio_pic.c revision 1.46.6.1 1 /* $NetBSD: sio_pic.c,v 1.46.6.1 2021/05/13 00:47:21 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.46.6.1 2021/05/13 00:47:21 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 static bus_space_tag_t sio_iot;
106 static pci_chipset_tag_t sio_pc;
107 static 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 static 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