1425f9fdaSStefan Eßer /* 2425f9fdaSStefan Eßer * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3425f9fdaSStefan Eßer * All rights reserved. 4425f9fdaSStefan Eßer * 5425f9fdaSStefan Eßer * Redistribution and use in source and binary forms, with or without 6425f9fdaSStefan Eßer * modification, are permitted provided that the following conditions 7425f9fdaSStefan Eßer * are met: 8425f9fdaSStefan Eßer * 1. Redistributions of source code must retain the above copyright 9425f9fdaSStefan Eßer * notice unmodified, this list of conditions, and the following 10425f9fdaSStefan Eßer * disclaimer. 11425f9fdaSStefan Eßer * 2. Redistributions in binary form must reproduce the above copyright 12425f9fdaSStefan Eßer * notice, this list of conditions and the following disclaimer in the 13425f9fdaSStefan Eßer * documentation and/or other materials provided with the distribution. 14425f9fdaSStefan Eßer * 15425f9fdaSStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16425f9fdaSStefan Eßer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17425f9fdaSStefan Eßer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18425f9fdaSStefan Eßer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19425f9fdaSStefan Eßer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20425f9fdaSStefan Eßer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21425f9fdaSStefan Eßer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22425f9fdaSStefan Eßer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23425f9fdaSStefan Eßer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24425f9fdaSStefan Eßer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25425f9fdaSStefan Eßer * 2668352337SDoug Rabson * $Id: kern_intr.c,v 1.4 1997/06/01 16:05:13 peter Exp $ 27425f9fdaSStefan Eßer * 28425f9fdaSStefan Eßer */ 29425f9fdaSStefan Eßer 30425f9fdaSStefan Eßer #include <sys/types.h> 31425f9fdaSStefan Eßer #include <sys/malloc.h> 32425f9fdaSStefan Eßer #include <sys/time.h> 33425f9fdaSStefan Eßer #include <sys/systm.h> 34425f9fdaSStefan Eßer #include <sys/errno.h> 35425f9fdaSStefan Eßer #ifdef RESOURCE_CHECK 36425f9fdaSStefan Eßer #include <sys/drvresource.h> 37425f9fdaSStefan Eßer #endif /* RESOURCE_CHECK */ 38425f9fdaSStefan Eßer 39425f9fdaSStefan Eßer #include <i386/isa/icu.h> 4068352337SDoug Rabson #include <i386/isa/intr_machdep.h> 4168352337SDoug Rabson #include <sys/interrupt.h> 42425f9fdaSStefan Eßer 434407ec71SPeter Wemm #include <machine/ipl.h> 44425f9fdaSStefan Eßer 45425f9fdaSStefan Eßer #include <stddef.h> 46425f9fdaSStefan Eßer 47425f9fdaSStefan Eßer #include "vector.h" 48425f9fdaSStefan Eßer 498c046d14SPeter Wemm typedef struct intrec { 508c046d14SPeter Wemm intrmask_t mask; 518c046d14SPeter Wemm inthand2_t *handler; 528c046d14SPeter Wemm void *argument; 538c046d14SPeter Wemm struct intrec *next; 548c046d14SPeter Wemm void *devdata; 558c046d14SPeter Wemm int intr; 568c046d14SPeter Wemm intrmask_t *maskptr; 578c046d14SPeter Wemm int flags; 588c046d14SPeter Wemm #define INTR_FAST 0x00000001 /* fast interrupt handler */ 598c046d14SPeter Wemm #define INTR_EXCL 0x00010000 /* excl. intr, default is shared */ 608c046d14SPeter Wemm } intrec; 618c046d14SPeter Wemm 62425f9fdaSStefan Eßer /* 63425f9fdaSStefan Eßer * The interrupt multiplexer calls each of the handlers in turn, 64425f9fdaSStefan Eßer * and applies the associated interrupt mask to "cpl", which is 65425f9fdaSStefan Eßer * defined as a ".long" in /sys/i386/isa/icu.s 66425f9fdaSStefan Eßer */ 67425f9fdaSStefan Eßer 684407ec71SPeter Wemm static inline intrmask_t 694407ec71SPeter Wemm splq(intrmask_t mask) 70425f9fdaSStefan Eßer { 714407ec71SPeter Wemm intrmask_t tmp = cpl; 72425f9fdaSStefan Eßer cpl |= mask; 73425f9fdaSStefan Eßer return (tmp); 74425f9fdaSStefan Eßer } 75425f9fdaSStefan Eßer 76425f9fdaSStefan Eßer static void 77425f9fdaSStefan Eßer intr_mux(void *arg) 78425f9fdaSStefan Eßer { 79425f9fdaSStefan Eßer intrec *p = arg; 80425f9fdaSStefan Eßer 81425f9fdaSStefan Eßer while (p != NULL) { 82425f9fdaSStefan Eßer int oldspl = splq(p->mask); 83425f9fdaSStefan Eßer /* inthand2_t should take (void*) argument */ 84425f9fdaSStefan Eßer p->handler(p->argument); 85425f9fdaSStefan Eßer splx(oldspl); 86425f9fdaSStefan Eßer p = p->next; 87425f9fdaSStefan Eßer } 88425f9fdaSStefan Eßer } 89425f9fdaSStefan Eßer 90425f9fdaSStefan Eßer /* XXX better use NHWI from <machine/ipl.h> for array size ??? */ 91425f9fdaSStefan Eßer static intrec *intreclist_head[ICU_LEN]; 92425f9fdaSStefan Eßer 93425f9fdaSStefan Eßer static intrec* 94425f9fdaSStefan Eßer find_idesc(unsigned *maskptr, int irq) 95425f9fdaSStefan Eßer { 96425f9fdaSStefan Eßer intrec *p = intreclist_head[irq]; 97425f9fdaSStefan Eßer 98425f9fdaSStefan Eßer while (p && p->maskptr != maskptr) 99425f9fdaSStefan Eßer p = p->next; 100425f9fdaSStefan Eßer 101425f9fdaSStefan Eßer return (p); 102425f9fdaSStefan Eßer } 103425f9fdaSStefan Eßer 104425f9fdaSStefan Eßer static intrec** 105425f9fdaSStefan Eßer find_pred(intrec *idesc, int irq) 106425f9fdaSStefan Eßer { 107425f9fdaSStefan Eßer intrec **pp = &intreclist_head[irq]; 108425f9fdaSStefan Eßer intrec *p = *pp; 109425f9fdaSStefan Eßer 110425f9fdaSStefan Eßer while (p != idesc) { 111425f9fdaSStefan Eßer if (p == NULL) 112425f9fdaSStefan Eßer return (NULL); 113425f9fdaSStefan Eßer pp = &p->next; 114425f9fdaSStefan Eßer p = *pp; 115425f9fdaSStefan Eßer } 116425f9fdaSStefan Eßer return (pp); 117425f9fdaSStefan Eßer } 118425f9fdaSStefan Eßer 119425f9fdaSStefan Eßer /* 120425f9fdaSStefan Eßer * Both the low level handler and the shared interrupt multiplexer 121425f9fdaSStefan Eßer * block out further interrupts as set in the handlers "mask", while 122425f9fdaSStefan Eßer * the handler is running. In fact *maskptr should be used for this 123425f9fdaSStefan Eßer * purpose, but since this requires one more pointer dereference on 124425f9fdaSStefan Eßer * each interrupt, we rather bother update "mask" whenever *maskptr 125425f9fdaSStefan Eßer * changes. The function "update_masks" should be called **after** 126425f9fdaSStefan Eßer * all manipulation of the linked list of interrupt handlers hung 127425f9fdaSStefan Eßer * off of intrdec_head[irq] is complete, since the chain of handlers 128425f9fdaSStefan Eßer * will both determine the *maskptr values and the instances of mask 129425f9fdaSStefan Eßer * that are fixed. This function should be called with the irq for 130425f9fdaSStefan Eßer * which a new handler has been add blocked, since the masks may not 131425f9fdaSStefan Eßer * yet know about the use of this irq for a device of a certain class. 132425f9fdaSStefan Eßer */ 133425f9fdaSStefan Eßer 134425f9fdaSStefan Eßer static void 135425f9fdaSStefan Eßer update_mux_masks(void) 136425f9fdaSStefan Eßer { 137425f9fdaSStefan Eßer int irq; 138425f9fdaSStefan Eßer for (irq = 0; irq < ICU_LEN; irq++) { 139425f9fdaSStefan Eßer intrec *idesc = intreclist_head[irq]; 140425f9fdaSStefan Eßer while (idesc != NULL) { 141425f9fdaSStefan Eßer if (idesc->maskptr != NULL) { 142425f9fdaSStefan Eßer /* our copy of *maskptr may be stale, refresh */ 143425f9fdaSStefan Eßer idesc->mask = *idesc->maskptr; 144425f9fdaSStefan Eßer } 145425f9fdaSStefan Eßer idesc = idesc->next; 146425f9fdaSStefan Eßer } 147425f9fdaSStefan Eßer } 148425f9fdaSStefan Eßer } 149425f9fdaSStefan Eßer 150425f9fdaSStefan Eßer static void 1514407ec71SPeter Wemm update_masks(intrmask_t *maskptr, int irq) 152425f9fdaSStefan Eßer { 1534407ec71SPeter Wemm intrmask_t mask = 1 << irq; 154425f9fdaSStefan Eßer 155425f9fdaSStefan Eßer if (maskptr == NULL) 156425f9fdaSStefan Eßer return; 157425f9fdaSStefan Eßer 158425f9fdaSStefan Eßer if (find_idesc(maskptr, irq) == NULL) { 159425f9fdaSStefan Eßer /* no reference to this maskptr was found in this irq's chain */ 160425f9fdaSStefan Eßer if ((*maskptr & mask) == 0) 161425f9fdaSStefan Eßer return; 162425f9fdaSStefan Eßer /* the irq was included in the classes mask, remove it */ 163425f9fdaSStefan Eßer INTRUNMASK(*maskptr, mask); 164425f9fdaSStefan Eßer } else { 165425f9fdaSStefan Eßer /* a reference to this maskptr was found in this irq's chain */ 166425f9fdaSStefan Eßer if ((*maskptr & mask) != 0) 167425f9fdaSStefan Eßer return; 168425f9fdaSStefan Eßer /* put the irq into the classes mask */ 169425f9fdaSStefan Eßer INTRMASK(*maskptr, mask); 170425f9fdaSStefan Eßer } 171425f9fdaSStefan Eßer /* we need to update all values in the intr_mask[irq] array */ 172425f9fdaSStefan Eßer update_intr_masks(); 173425f9fdaSStefan Eßer /* update mask in chains of the interrupt multiplex handler as well */ 174425f9fdaSStefan Eßer update_mux_masks(); 175425f9fdaSStefan Eßer } 176425f9fdaSStefan Eßer 177425f9fdaSStefan Eßer /* 178425f9fdaSStefan Eßer * Add interrupt handler to linked list hung off of intreclist_head[irq] 179425f9fdaSStefan Eßer * and install shared interrupt multiplex handler, if necessary 180425f9fdaSStefan Eßer */ 181425f9fdaSStefan Eßer 182425f9fdaSStefan Eßer static int 183425f9fdaSStefan Eßer add_intrdesc(intrec *idesc) 184425f9fdaSStefan Eßer { 185425f9fdaSStefan Eßer int irq = idesc->intr; 186425f9fdaSStefan Eßer 187425f9fdaSStefan Eßer intrec *head = intreclist_head[irq]; 188425f9fdaSStefan Eßer 189425f9fdaSStefan Eßer if (head == NULL) { 190425f9fdaSStefan Eßer /* first handler for this irq, just install it */ 191425f9fdaSStefan Eßer if (icu_setup(irq, idesc->handler, idesc->argument, 192425f9fdaSStefan Eßer idesc->maskptr, idesc->flags) != 0) 193425f9fdaSStefan Eßer return (-1); 194425f9fdaSStefan Eßer 195425f9fdaSStefan Eßer update_intrname(irq, idesc->devdata); 196425f9fdaSStefan Eßer /* keep reference */ 197425f9fdaSStefan Eßer intreclist_head[irq] = idesc; 198425f9fdaSStefan Eßer } else { 199425f9fdaSStefan Eßer if ((idesc->flags & INTR_EXCL) != 0 200425f9fdaSStefan Eßer || (head->flags & INTR_EXCL) != 0) { 201425f9fdaSStefan Eßer /* 202425f9fdaSStefan Eßer * can't append new handler, if either list head or 203425f9fdaSStefan Eßer * new handler do not allow interrupts to be shared 204425f9fdaSStefan Eßer */ 205425f9fdaSStefan Eßer printf("\tdevice combination doesn't support shared irq%d\n", 206425f9fdaSStefan Eßer irq); 207425f9fdaSStefan Eßer return (-1); 208425f9fdaSStefan Eßer } 209425f9fdaSStefan Eßer if (head->next == NULL) { 210425f9fdaSStefan Eßer /* 211425f9fdaSStefan Eßer * second handler for this irq, replace device driver's 212425f9fdaSStefan Eßer * handler by shared interrupt multiplexer function 213425f9fdaSStefan Eßer */ 214425f9fdaSStefan Eßer icu_unset(irq, head->handler); 215425f9fdaSStefan Eßer if (icu_setup(irq, intr_mux, head, 0, 0) != 0) 216425f9fdaSStefan Eßer return (-1); 217425f9fdaSStefan Eßer if (bootverbose) 218425f9fdaSStefan Eßer printf("\tusing shared irq%d.\n", irq); 219425f9fdaSStefan Eßer update_intrname(irq, -1); 220425f9fdaSStefan Eßer } 221425f9fdaSStefan Eßer /* just append to the end of the chain */ 222425f9fdaSStefan Eßer while (head->next != NULL) 223425f9fdaSStefan Eßer head = head->next; 224425f9fdaSStefan Eßer head->next = idesc; 225425f9fdaSStefan Eßer } 226425f9fdaSStefan Eßer update_masks(idesc->maskptr, irq); 227425f9fdaSStefan Eßer return (0); 228425f9fdaSStefan Eßer } 229425f9fdaSStefan Eßer 230425f9fdaSStefan Eßer /* 231425f9fdaSStefan Eßer * Add the interrupt handler descriptor data structure created by an 232425f9fdaSStefan Eßer * earlier call of create_intr() to the linked list for its irq and 233425f9fdaSStefan Eßer * adjust the interrupt masks if necessary. 234425f9fdaSStefan Eßer * 235425f9fdaSStefan Eßer * This function effectively activates the handler. 236425f9fdaSStefan Eßer */ 237425f9fdaSStefan Eßer 238425f9fdaSStefan Eßer int 239425f9fdaSStefan Eßer intr_connect(intrec *idesc) 240425f9fdaSStefan Eßer { 241425f9fdaSStefan Eßer int errcode = -1; 242425f9fdaSStefan Eßer int irq; 243425f9fdaSStefan Eßer 244425f9fdaSStefan Eßer #ifdef RESOURCE_CHECK 245425f9fdaSStefan Eßer int resflag; 246425f9fdaSStefan Eßer #endif /* RESOURCE_CHECK */ 247425f9fdaSStefan Eßer 248425f9fdaSStefan Eßer if (idesc == NULL) 249425f9fdaSStefan Eßer return (-1); 250425f9fdaSStefan Eßer 251425f9fdaSStefan Eßer irq = idesc->intr; 252425f9fdaSStefan Eßer #ifdef RESOURCE_CHECK 253425f9fdaSStefan Eßer resflag = (idesc->flags & INTR_EXCL) ? RESF_NONE : RESF_SHARED; 254425f9fdaSStefan Eßer if (resource_claim(idesc->devdata, REST_INT, resflag, irq, irq) == 0) 255425f9fdaSStefan Eßer #endif /* RESOURCE_CHECK */ 256425f9fdaSStefan Eßer { 257425f9fdaSStefan Eßer /* block this irq */ 2584407ec71SPeter Wemm intrmask_t oldspl = splq(1 << irq); 259425f9fdaSStefan Eßer 260425f9fdaSStefan Eßer /* add irq to class selected by maskptr */ 261425f9fdaSStefan Eßer errcode = add_intrdesc(idesc); 262425f9fdaSStefan Eßer splx(oldspl); 263425f9fdaSStefan Eßer } 264425f9fdaSStefan Eßer if (errcode != 0) 265425f9fdaSStefan Eßer printf("\tintr_connect(irq%d) failed, result=%d\n", 266425f9fdaSStefan Eßer irq, errcode); 267425f9fdaSStefan Eßer 268425f9fdaSStefan Eßer return (errcode); 269425f9fdaSStefan Eßer } 270425f9fdaSStefan Eßer 271425f9fdaSStefan Eßer /* 272425f9fdaSStefan Eßer * Remove the interrupt handler descriptor data connected created by an 273425f9fdaSStefan Eßer * earlier call of intr_connect() from the linked list and adjust the 274425f9fdaSStefan Eßer * interrupt masks if necessary. 275425f9fdaSStefan Eßer * 276425f9fdaSStefan Eßer * This function deactivates the handler. 277425f9fdaSStefan Eßer */ 278425f9fdaSStefan Eßer 279425f9fdaSStefan Eßer int 280425f9fdaSStefan Eßer intr_disconnect(intrec *idesc) 281425f9fdaSStefan Eßer { 282425f9fdaSStefan Eßer intrec **hook, *head; 283425f9fdaSStefan Eßer int irq; 284425f9fdaSStefan Eßer int errcode = 0; 285425f9fdaSStefan Eßer 286425f9fdaSStefan Eßer if (idesc == NULL) 287425f9fdaSStefan Eßer return (-1); 288425f9fdaSStefan Eßer 289425f9fdaSStefan Eßer irq = idesc->intr; 290425f9fdaSStefan Eßer 291425f9fdaSStefan Eßer /* find pointer that keeps the reference to this interrupt descriptor */ 292425f9fdaSStefan Eßer hook = find_pred(idesc, irq); 293425f9fdaSStefan Eßer if (hook == NULL) 294425f9fdaSStefan Eßer return (-1); 295425f9fdaSStefan Eßer 296425f9fdaSStefan Eßer /* make copy of original list head, the line after may overwrite it */ 297425f9fdaSStefan Eßer head = intreclist_head[irq]; 298425f9fdaSStefan Eßer 299425f9fdaSStefan Eßer /* unlink: make predecessor point to idesc->next instead of to idesc */ 300425f9fdaSStefan Eßer *hook = idesc->next; 301425f9fdaSStefan Eßer 302425f9fdaSStefan Eßer /* now check whether the element we removed was the list head */ 303425f9fdaSStefan Eßer if (idesc == head) { 3044407ec71SPeter Wemm intrmask_t oldspl = splq(1 << irq); 305425f9fdaSStefan Eßer 306425f9fdaSStefan Eßer /* we want to remove the list head, which was known to intr_mux */ 307425f9fdaSStefan Eßer icu_unset(irq, intr_mux); 308425f9fdaSStefan Eßer 309425f9fdaSStefan Eßer /* check whether the new list head is the only element on list */ 310425f9fdaSStefan Eßer head = intreclist_head[irq]; 311f9220cdeSStefan Eßer if (head != NULL) { 312425f9fdaSStefan Eßer if (head->next != NULL) { 313425f9fdaSStefan Eßer /* install the multiplex handler with new list head as argument */ 314425f9fdaSStefan Eßer errcode = icu_setup(irq, intr_mux, head, 0, 0); 315425f9fdaSStefan Eßer if (errcode == 0) 316425f9fdaSStefan Eßer update_intrname(irq, -1); 317f9220cdeSStefan Eßer } else { 318425f9fdaSStefan Eßer /* install the one remaining handler for this irq */ 319f9220cdeSStefan Eßer errcode = icu_setup(irq, head->handler, 320f9220cdeSStefan Eßer head->argument, 321425f9fdaSStefan Eßer head->maskptr, head->flags); 322425f9fdaSStefan Eßer if (errcode == 0) 323425f9fdaSStefan Eßer update_intrname(irq, head->devdata); 324425f9fdaSStefan Eßer } 325f9220cdeSStefan Eßer } 326425f9fdaSStefan Eßer splx(oldspl); 327425f9fdaSStefan Eßer } 328425f9fdaSStefan Eßer update_masks(idesc->maskptr, irq); 329425f9fdaSStefan Eßer #ifdef RESOURCE_CHECK 330425f9fdaSStefan Eßer resource_free(idesc->devdata); 331425f9fdaSStefan Eßer #endif /* RESOURCE_CHECK */ 332425f9fdaSStefan Eßer return (0); 333425f9fdaSStefan Eßer } 334425f9fdaSStefan Eßer 335425f9fdaSStefan Eßer /* 336425f9fdaSStefan Eßer * Create an interrupt handler descriptor data structure, which later can 337425f9fdaSStefan Eßer * be activated or deactivated at will by calls of [dis]connect(intrec*). 338425f9fdaSStefan Eßer * 339425f9fdaSStefan Eßer * The dev_instance pointer is required for resource management, and will 340425f9fdaSStefan Eßer * only be passed through to resource_claim(). 341425f9fdaSStefan Eßer * 342425f9fdaSStefan Eßer * The interrupt handler takes an argument of type (void*), which is not 343425f9fdaSStefan Eßer * what is currently used for ISA devices. But since the unit number passed 344425f9fdaSStefan Eßer * to an ISA interrupt handler can be stored in a (void*) variable, this 345425f9fdaSStefan Eßer * causes no problems. Eventually all the ISA interrupt handlers should be 346425f9fdaSStefan Eßer * modified to accept the pointer to their private data, too, instead of 347425f9fdaSStefan Eßer * an integer index. 348425f9fdaSStefan Eßer * 349425f9fdaSStefan Eßer * There will be functions that derive a driver and unit name from a 350425f9fdaSStefan Eßer * dev_instance variable, and those functions will be used to maintain the 351425f9fdaSStefan Eßer * interrupt counter label array referenced by systat and vmstat to report 352425f9fdaSStefan Eßer * device interrupt rates (->update_intrlabels). 353425f9fdaSStefan Eßer */ 354425f9fdaSStefan Eßer 355425f9fdaSStefan Eßer intrec * 356425f9fdaSStefan Eßer intr_create(void *dev_instance, int irq, inthand2_t handler, void *arg, 3574407ec71SPeter Wemm intrmask_t *maskptr, int flags) 358425f9fdaSStefan Eßer { 359425f9fdaSStefan Eßer intrec *idesc; 360425f9fdaSStefan Eßer 361425f9fdaSStefan Eßer if (ICU_LEN > 8 * sizeof *maskptr) { 362425f9fdaSStefan Eßer printf("create_intr: ICU_LEN of %d too high for %d bit intrmask\n", 363425f9fdaSStefan Eßer ICU_LEN, 8 * sizeof *maskptr); 364425f9fdaSStefan Eßer return (NULL); 365425f9fdaSStefan Eßer } 366425f9fdaSStefan Eßer if ((unsigned)irq >= ICU_LEN) { 367425f9fdaSStefan Eßer printf("create_intr: requested irq%d too high, limit is %d\n", 368425f9fdaSStefan Eßer irq, ICU_LEN -1); 369425f9fdaSStefan Eßer return (NULL); 370425f9fdaSStefan Eßer } 371425f9fdaSStefan Eßer 372425f9fdaSStefan Eßer idesc = malloc(sizeof *idesc, M_DEVBUF, M_WAITOK); 373425f9fdaSStefan Eßer if (idesc) { 374425f9fdaSStefan Eßer idesc->next = NULL; 375425f9fdaSStefan Eßer bzero(idesc, sizeof *idesc); 376425f9fdaSStefan Eßer 377425f9fdaSStefan Eßer idesc->devdata = dev_instance; 378425f9fdaSStefan Eßer idesc->handler = handler; 379425f9fdaSStefan Eßer idesc->argument = arg; 380425f9fdaSStefan Eßer idesc->maskptr = maskptr; 381425f9fdaSStefan Eßer idesc->intr = irq; 382425f9fdaSStefan Eßer idesc->flags = flags; 383425f9fdaSStefan Eßer } 384425f9fdaSStefan Eßer return (idesc); 385425f9fdaSStefan Eßer } 386425f9fdaSStefan Eßer 387425f9fdaSStefan Eßer /* 388425f9fdaSStefan Eßer * Return the memory held by the interrupt handler descriptor data structure 389425f9fdaSStefan Eßer * to the system. Make sure, the handler is not actively used anymore, before. 390425f9fdaSStefan Eßer */ 391425f9fdaSStefan Eßer 392425f9fdaSStefan Eßer int 393425f9fdaSStefan Eßer intr_destroy(intrec *rec) 394425f9fdaSStefan Eßer { 395425f9fdaSStefan Eßer if (intr_disconnect(rec) != 0) 396425f9fdaSStefan Eßer return (-1); 397425f9fdaSStefan Eßer free(rec, M_DEVBUF); 398425f9fdaSStefan Eßer return (0); 399425f9fdaSStefan Eßer } 400425f9fdaSStefan Eßer 401425f9fdaSStefan Eßer /* 402425f9fdaSStefan Eßer * Emulate the register_intr() call previously defined as low level function. 403425f9fdaSStefan Eßer * That function (now icu_setup()) may no longer be directly called, since 404425f9fdaSStefan Eßer * a conflict between an ISA and PCI interrupt might go by unnocticed, else. 405425f9fdaSStefan Eßer */ 406425f9fdaSStefan Eßer 407425f9fdaSStefan Eßer int 408425f9fdaSStefan Eßer register_intr(int intr, int device_id, u_int flags, 409425f9fdaSStefan Eßer inthand2_t handler, u_int *maskptr, int unit) 410425f9fdaSStefan Eßer { 411425f9fdaSStefan Eßer /* XXX modify to include isa_device instead of device_id */ 412425f9fdaSStefan Eßer intrec *idesc; 413425f9fdaSStefan Eßer 414425f9fdaSStefan Eßer flags |= INTR_EXCL; 415425f9fdaSStefan Eßer idesc = intr_create((void *)device_id, intr, handler, 416425f9fdaSStefan Eßer (void*)unit, maskptr, flags); 417425f9fdaSStefan Eßer return (intr_connect(idesc)); 418425f9fdaSStefan Eßer } 419425f9fdaSStefan Eßer 420425f9fdaSStefan Eßer /* 421425f9fdaSStefan Eßer * Emulate the old unregister_intr() low level function. 422425f9fdaSStefan Eßer * Make sure there is just one interrupt, that it was 423425f9fdaSStefan Eßer * registered as non-shared, and that the handlers match. 424425f9fdaSStefan Eßer */ 425425f9fdaSStefan Eßer 426425f9fdaSStefan Eßer int 427425f9fdaSStefan Eßer unregister_intr(int intr, inthand2_t handler) 428425f9fdaSStefan Eßer { 429425f9fdaSStefan Eßer intrec *p = intreclist_head[intr]; 430425f9fdaSStefan Eßer 431425f9fdaSStefan Eßer if (p != NULL && (p->flags & INTR_EXCL) != 0 && p->handler == handler) 432425f9fdaSStefan Eßer return (intr_destroy(p)); 433425f9fdaSStefan Eßer return (EINVAL); 434425f9fdaSStefan Eßer } 435