2 * Copyright (c) 1991 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
37 * $Id: intr_machdep.c,v 1.22 1999/05/22 09:39:31 peter Exp $
40 * This file contains an aggregated module marked:
41 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
42 * All rights reserved.
43 * See the notice for details.
46 #include "opt_auto_eoi.h"
48 #include <sys/param.h>
50 #include <machine/lock.h>
52 #include <sys/systm.h>
53 #include <sys/syslog.h>
54 #include <sys/malloc.h>
55 #include <sys/errno.h>
56 #include <sys/interrupt.h>
57 #include <machine/ipl.h>
58 #include <machine/md_var.h>
59 #include <machine/segments.h>
63 #include <machine/smp.h>
64 #include <machine/smptests.h> /** FAST_HI */
67 #include <pc98/pc98/pc98.h>
68 #include <pc98/pc98/pc98_machdep.h>
69 #include <pc98/pc98/epsonio.h>
71 #include <i386/isa/isa.h>
73 #include <i386/isa/icu.h>
75 #include <isa/isavar.h>
76 #include <i386/isa/intr_machdep.h>
77 #include <sys/interrupt.h>
79 #include <machine/clock.h>
82 /* XXX should be in suitable include files */
84 #define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */
87 #define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */
93 * This is to accommodate "mixed-mode" programming for
94 * motherboards that don't connect the 8254 to the IO APIC.
99 #define NR_INTRNAMES (1 + ICU_LEN + 2 * ICU_LEN)
101 u_long *intr_countp[ICU_LEN];
102 inthand2_t *intr_handler[ICU_LEN];
103 u_int intr_mask[ICU_LEN];
104 static u_int* intr_mptr[ICU_LEN];
105 void *intr_unit[ICU_LEN];
107 static inthand_t *fastintr[ICU_LEN] = {
108 &IDTVEC(fastintr0), &IDTVEC(fastintr1),
109 &IDTVEC(fastintr2), &IDTVEC(fastintr3),
110 &IDTVEC(fastintr4), &IDTVEC(fastintr5),
111 &IDTVEC(fastintr6), &IDTVEC(fastintr7),
112 &IDTVEC(fastintr8), &IDTVEC(fastintr9),
113 &IDTVEC(fastintr10), &IDTVEC(fastintr11),
114 &IDTVEC(fastintr12), &IDTVEC(fastintr13),
115 &IDTVEC(fastintr14), &IDTVEC(fastintr15),
117 &IDTVEC(fastintr16), &IDTVEC(fastintr17),
118 &IDTVEC(fastintr18), &IDTVEC(fastintr19),
119 &IDTVEC(fastintr20), &IDTVEC(fastintr21),
120 &IDTVEC(fastintr22), &IDTVEC(fastintr23),
124 static inthand_t *slowintr[ICU_LEN] = {
125 &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3),
126 &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
127 &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
128 &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15),
130 &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19),
131 &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23),
135 static inthand2_t isa_strayintr;
138 #define NMI_PARITY 0x04
139 #define NMI_EPARITY 0x02
141 #define NMI_PARITY (1 << 7)
142 #define NMI_IOCHAN (1 << 6)
143 #define ENMI_WATCHDOG (1 << 7)
144 #define ENMI_BUSTIMER (1 << 6)
145 #define ENMI_IOSTATUS (1 << 5)
149 * Handle a NMI, possibly a machine check.
150 * return true to panic system, false to ignore.
157 int port = inb(0x33);
158 if (epson_machine_id == 0x20)
159 epson_outb(0xc16, epson_inb(0xc16) | 0x1);
160 if (port & NMI_PARITY) {
161 panic("BASE RAM parity error, likely hardware failure.");
162 } else if (port & NMI_EPARITY) {
163 panic("EXTENDED RAM parity error, likely hardware failure.");
165 printf("\nNMI Resume ??\n");
169 int isa_port = inb(0x61);
170 int eisa_port = inb(0x461);
172 if (isa_port & NMI_PARITY)
173 panic("RAM parity error, likely hardware failure.");
175 if (isa_port & NMI_IOCHAN)
176 panic("I/O channel check, likely hardware failure.");
179 * On a real EISA machine, this will never happen. However it can
180 * happen on ISA machines which implement XT style floating point
181 * error handling (very rare). Save them from a meaningless panic.
183 if (eisa_port == 0xff)
186 if (eisa_port & ENMI_WATCHDOG)
187 panic("EISA watchdog timer expired, likely hardware failure.");
189 if (eisa_port & ENMI_BUSTIMER)
190 panic("EISA bus timeout, likely hardware failure.");
192 if (eisa_port & ENMI_IOSTATUS)
193 panic("EISA I/O port status error.");
195 printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port);
201 * Fill in default interrupt table (in case of spuruious interrupt
202 * during configuration of kernel, setup interrupt control unit
210 for (i = 0; i < ICU_LEN; i++)
211 icu_unset(i, (inthand2_t *)NULL);
213 /* initialize 8259's */
214 outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
216 outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */
217 outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */
220 outb(IO_ICU1+ICU_IMR_OFFSET, 0x1f); /* (master) auto EOI, 8086 mode */
222 outb(IO_ICU1+ICU_IMR_OFFSET, 0x1d); /* (master) 8086 mode */
226 outb(IO_ICU1+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */
228 outb(IO_ICU1+ICU_IMR_OFFSET, 1); /* 8086 mode */
231 outb(IO_ICU1+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */
232 outb(IO_ICU1, 0x0a); /* default to IRR on read */
234 outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
237 outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
238 outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */
239 outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */
241 outb(IO_ICU2+ICU_IMR_OFFSET,9); /* 8086 mode */
244 outb(IO_ICU2+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */
246 outb(IO_ICU2+ICU_IMR_OFFSET,1); /* 8086 mode */
249 outb(IO_ICU2+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */
250 outb(IO_ICU2, 0x0a); /* default to IRR on read */
254 * Caught a stray interrupt, notify
257 isa_strayintr(vcookiep)
260 int intr = (void **)vcookiep - &intr_unit[0];
262 /* DON'T BOTHER FOR NOW! */
263 /* for some reason, we get bursts of intr #7, even if not enabled! */
265 * Well the reason you got bursts of intr #7 is because someone
266 * raised an interrupt line and dropped it before the 8259 could
267 * prioritize it. This is documented in the intel data book. This
268 * means you have BAD hardware! I have changed this so that only
269 * the first 5 get logged, then it quits logging them, and puts
270 * out a special message. rgrimes 3/25/1993
273 * XXX TODO print a different message for #7 if it is for a
274 * glitch. Glitches can be distinguished from real #7's by
275 * testing that the in-service bit is _not_ set. The test
276 * must be done before sending an EOI so it can't be done if
277 * we are using AUTO_EOI_1.
279 if (intrcnt[1 + intr] <= 5)
280 log(LOG_ERR, "stray irq %d\n", intr);
281 if (intrcnt[1 + intr] == 5)
283 "too many stray irq %d's; not logging any more\n", intr);
287 * Return a bitmap of the current interrupt requests. This is 8259-specific
288 * and is only suitable for use at probe time.
298 return ((irr2 << 8) | irr1);
302 update_intr_masks(void)
307 for (intr=0; intr < ICU_LEN; intr ++) {
309 /* no 8259 SLAVE to ignore */
311 if (intr==ICU_SLAVEID) continue; /* ignore 8259 SLAVE output */
313 maskptr = intr_mptr[intr];
316 *maskptr |= SWI_CLOCK_MASK | (1 << intr);
318 if (mask != intr_mask[intr]) {
320 printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n",
321 intr, intr_mask[intr], mask, maskptr);
323 intr_mask[intr]=mask;
332 update_intrname(int intr, char *name)
336 int name_index, off, strayintr;
339 * Initialise strings for bitbucket and stray interrupt counters.
340 * These have statically allocated indices 0 and 1 through ICU_LEN.
342 if (intrnames[0] == '\0') {
343 off = sprintf(intrnames, "???") + 1;
344 for (strayintr = 0; strayintr < ICU_LEN; strayintr++)
345 off += sprintf(intrnames + off, "stray irq%d",
351 if (snprintf(buf, sizeof(buf), "%s irq%d", name, intr) >= sizeof(buf))
355 * Search for `buf' in `intrnames'. In the usual case when it is
356 * not found, append it to the end if there is enough space (the \0
357 * terminator for the previous string, if any, becomes a separator).
359 for (cp = intrnames, name_index = 0;
360 cp != eintrnames && name_index < NR_INTRNAMES;
361 cp += strlen(cp) + 1, name_index++) {
363 if (strlen(buf) >= eintrnames - cp)
368 if (strcmp(cp, buf) == 0)
373 printf("update_intrname: counting %s irq%d as %s\n", name, intr,
377 intr_countp[intr] = &intrcnt[name_index];
381 icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags)
384 int select; /* the select register is 8 bits */
386 u_int32_t value; /* the window register is 32 bits */
389 u_int mask = (maskptr ? *maskptr : 0);
392 if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */
394 if ((u_int)intr >= ICU_LEN || intr == ICU_SLAVEID)
396 if (intr_handler[intr] != isa_strayintr)
401 intr_handler[intr] = handler;
402 intr_mptr[intr] = maskptr;
403 intr_mask[intr] = mask | SWI_CLOCK_MASK | (1 << intr);
404 intr_unit[intr] = arg;
406 if (flags & INTR_FAST) {
407 vector = TPR_FAST_INTS + intr;
408 setidt(vector, fastintr[intr],
409 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
412 vector = TPR_SLOW_INTS + intr;
413 #ifdef APIC_INTR_REORDER
414 #ifdef APIC_INTR_HIGHPRI_CLOCK
415 /* XXX: Hack (kludge?) for more accurate clock. */
416 if (intr == apic_8254_intr || intr == 8) {
417 vector = TPR_FAST_INTS + intr;
421 setidt(vector, slowintr[intr],
422 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
424 #ifdef APIC_INTR_REORDER
425 set_lapic_isrloc(intr, vector);
428 * Reprogram the vector in the IO APIC.
430 if (int_to_apicintpin[intr].ioapic >= 0) {
431 select = int_to_apicintpin[intr].redirindex;
432 value = io_apic_read(int_to_apicintpin[intr].ioapic,
433 select) & ~IOART_INTVEC;
434 io_apic_write(int_to_apicintpin[intr].ioapic,
435 select, value | vector);
438 setidt(ICU_OFFSET + intr,
439 flags & INTR_FAST ? fastintr[intr] : slowintr[intr],
440 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
449 icu_unset(intr, handler)
455 if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr])
461 intr_countp[intr] = &intrcnt[1 + intr];
462 intr_handler[intr] = isa_strayintr;
463 intr_mptr[intr] = NULL;
464 intr_mask[intr] = HWI_MASK | SWI_MASK;
465 intr_unit[intr] = &intr_unit[intr];
467 /* XXX how do I re-create dvp here? */
468 setidt(flags & INTR_FAST ? TPR_FAST_INTS + intr : TPR_SLOW_INTS + intr,
469 slowintr[intr], SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
471 #ifdef APIC_INTR_REORDER
472 set_lapic_isrloc(intr, ICU_OFFSET + intr);
474 setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
475 GSEL(GCODE_SEL, SEL_KPL));
482 /* The following notice applies beyond this point in the file */
485 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
486 * All rights reserved.
488 * Redistribution and use in source and binary forms, with or without
489 * modification, are permitted provided that the following conditions
491 * 1. Redistributions of source code must retain the above copyright
492 * notice unmodified, this list of conditions, and the following
494 * 2. Redistributions in binary form must reproduce the above copyright
495 * notice, this list of conditions and the following disclaimer in the
496 * documentation and/or other materials provided with the distribution.
498 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
499 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
500 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
501 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
502 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
503 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
504 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
505 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
506 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
507 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
509 * $Id: intr_machdep.c,v 1.22 1999/05/22 09:39:31 peter Exp $
513 typedef struct intrec {
524 static intrec *intreclist_head[ICU_LEN];
526 typedef struct isarec {
528 ointhand2_t *id_handler;
531 static isarec *isareclist[ICU_LEN];
534 * The interrupt multiplexer calls each of the handlers in turn. The
535 * ipl is initially quite low. It is raised as necessary for each call
536 * and lowered after the call. Thus out of order handling is possible
537 * even for interrupts of the same type. This is probably no more
538 * harmful than out of order handling in general (not harmful except
539 * for real time response which we don't support anyway).
547 for (p = arg; p != NULL; p = p->next) {
548 oldspl = splq(p->mask);
549 p->handler(p->argument);
555 isa_intr_wrap(void *cookie)
557 isarec *irec = (isarec *)cookie;
559 irec->id_handler(irec->id_unit);
563 find_idesc(unsigned *maskptr, int irq)
565 intrec *p = intreclist_head[irq];
567 while (p && p->maskptr != maskptr)
574 find_pred(intrec *idesc, int irq)
576 intrec **pp = &intreclist_head[irq];
589 * Both the low level handler and the shared interrupt multiplexer
590 * block out further interrupts as set in the handlers "mask", while
591 * the handler is running. In fact *maskptr should be used for this
592 * purpose, but since this requires one more pointer dereference on
593 * each interrupt, we rather bother update "mask" whenever *maskptr
594 * changes. The function "update_masks" should be called **after**
595 * all manipulation of the linked list of interrupt handlers hung
596 * off of intrdec_head[irq] is complete, since the chain of handlers
597 * will both determine the *maskptr values and the instances of mask
598 * that are fixed. This function should be called with the irq for
599 * which a new handler has been add blocked, since the masks may not
600 * yet know about the use of this irq for a device of a certain class.
604 update_mux_masks(void)
607 for (irq = 0; irq < ICU_LEN; irq++) {
608 intrec *idesc = intreclist_head[irq];
609 while (idesc != NULL) {
610 if (idesc->maskptr != NULL) {
611 /* our copy of *maskptr may be stale, refresh */
612 idesc->mask = *idesc->maskptr;
620 update_masks(intrmask_t *maskptr, int irq)
622 intrmask_t mask = 1 << irq;
627 if (find_idesc(maskptr, irq) == NULL) {
628 /* no reference to this maskptr was found in this irq's chain */
629 if ((*maskptr & mask) == 0)
631 /* the irq was included in the classes mask, remove it */
632 INTRUNMASK(*maskptr, mask);
634 /* a reference to this maskptr was found in this irq's chain */
635 if ((*maskptr & mask) != 0)
637 /* put the irq into the classes mask */
638 INTRMASK(*maskptr, mask);
640 /* we need to update all values in the intr_mask[irq] array */
642 /* update mask in chains of the interrupt multiplex handler as well */
647 * Add interrupt handler to linked list hung off of intreclist_head[irq]
648 * and install shared interrupt multiplex handler, if necessary
652 add_intrdesc(intrec *idesc)
654 int irq = idesc->intr;
656 intrec *head = intreclist_head[irq];
659 /* first handler for this irq, just install it */
660 if (icu_setup(irq, idesc->handler, idesc->argument,
661 idesc->maskptr, idesc->flags) != 0)
664 update_intrname(irq, idesc->name);
666 intreclist_head[irq] = idesc;
668 if ((idesc->flags & INTR_EXCL) != 0
669 || (head->flags & INTR_EXCL) != 0) {
671 * can't append new handler, if either list head or
672 * new handler do not allow interrupts to be shared
675 printf("\tdevice combination doesn't support "
676 "shared irq%d\n", irq);
679 if (head->next == NULL) {
681 * second handler for this irq, replace device driver's
682 * handler by shared interrupt multiplexer function
684 icu_unset(irq, head->handler);
685 if (icu_setup(irq, intr_mux, head, 0, 0) != 0)
688 printf("\tusing shared irq%d.\n", irq);
689 update_intrname(irq, "mux");
691 /* just append to the end of the chain */
692 while (head->next != NULL)
696 update_masks(idesc->maskptr, irq);
701 * Create and activate an interrupt handler descriptor data structure.
703 * The dev_instance pointer is required for resource management, and will
704 * only be passed through to resource_claim().
706 * There will be functions that derive a driver and unit name from a
707 * dev_instance variable, and those functions will be used to maintain the
708 * interrupt counter label array referenced by systat and vmstat to report
709 * device interrupt rates (->update_intrlabels).
711 * Add the interrupt handler descriptor data structure created by an
712 * earlier call of create_intr() to the linked list for its irq and
713 * adjust the interrupt masks if necessary.
717 inthand_add(const char *name, int irq, inthand2_t handler, void *arg,
718 intrmask_t *maskptr, int flags)
724 if (ICU_LEN > 8 * sizeof *maskptr) {
725 printf("create_intr: ICU_LEN of %d too high for %d bit intrmask\n",
726 ICU_LEN, 8 * sizeof *maskptr);
729 if ((unsigned)irq >= ICU_LEN) {
730 printf("create_intr: requested irq%d too high, limit is %d\n",
735 idesc = malloc(sizeof *idesc, M_DEVBUF, M_WAITOK);
738 bzero(idesc, sizeof *idesc);
742 idesc->name = malloc(strlen(name) + 1, M_DEVBUF, M_WAITOK);
743 if (idesc->name == NULL) {
744 free(idesc, M_DEVBUF);
747 strcpy(idesc->name, name);
749 idesc->handler = handler;
750 idesc->argument = arg;
751 idesc->maskptr = maskptr;
753 idesc->flags = flags;
756 oldspl = splq(1 << irq);
758 /* add irq to class selected by maskptr */
759 errcode = add_intrdesc(idesc);
764 printf("\tintr_connect(irq%d) failed, result=%d\n",
766 free(idesc->name, M_DEVBUF);
767 free(idesc, M_DEVBUF);
775 * Deactivate and remove the interrupt handler descriptor data connected
776 * created by an earlier call of intr_connect() from the linked list and
777 * adjust theinterrupt masks if necessary.
779 * Return the memory held by the interrupt handler descriptor data structure
780 * to the system. Make sure, the handler is not actively used anymore, before.
784 inthand_remove(intrec *idesc)
786 intrec **hook, *head;
796 /* find pointer that keeps the reference to this interrupt descriptor */
797 hook = find_pred(idesc, irq);
801 /* make copy of original list head, the line after may overwrite it */
802 head = intreclist_head[irq];
804 /* unlink: make predecessor point to idesc->next instead of to idesc */
807 /* now check whether the element we removed was the list head */
810 oldspl = splq(1 << irq);
812 /* check whether the new list head is the only element on list */
813 head = intreclist_head[irq];
815 icu_unset(irq, intr_mux);
816 if (head->next != NULL) {
817 /* install the multiplex handler with new list head as argument */
818 errcode = icu_setup(irq, intr_mux, head, 0, 0);
820 update_intrname(irq, NULL);
822 /* install the one remaining handler for this irq */
823 errcode = icu_setup(irq, head->handler,
825 head->maskptr, head->flags);
827 update_intrname(irq, head->name);
830 /* revert to old handler, eg: strayintr */
831 icu_unset(irq, idesc->handler);
835 update_masks(idesc->maskptr, irq);
836 free(idesc, M_DEVBUF);
841 * Emulate the register_intr() call previously defined as low level function.
842 * That function (now icu_setup()) may no longer be directly called, since
843 * a conflict between an ISA and PCI interrupt might go by unnocticed, else.
847 register_intr(int intr, int device_id, u_int flags,
848 ointhand2_t handler, u_int *maskptr, int unit)
853 irec = malloc(sizeof *irec, M_DEVBUF, M_WAITOK);
856 bzero(irec, sizeof *irec);
857 irec->id_unit = unit;
858 irec->id_handler = handler;
861 idesc = inthand_add("old", intr, isa_intr_wrap, irec, maskptr, flags);
863 free(irec, M_DEVBUF);
866 isareclist[intr] = irec;
871 * Emulate the old unregister_intr() low level function.
872 * Make sure there is just one interrupt, that it was
873 * registered as non-shared, and that the handlers match.
877 unregister_intr(int intr, ointhand2_t handler)
879 intrec *p = intreclist_head[intr];
881 if (p != NULL && (p->flags & INTR_EXCL) != 0 &&
882 p->handler == isa_intr_wrap && isareclist[intr] != NULL &&
883 isareclist[intr]->id_handler == handler) {
884 free(isareclist[intr], M_DEVBUF);
885 isareclist[intr] = NULL;
886 return (inthand_remove(p));