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 * 26425f9fdaSStefan Eßer * $Id$ 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> 40425f9fdaSStefan Eßer #include <i386/isa/isa_device.h> 41425f9fdaSStefan Eßer #include <sys/interrupt.h> /* XXX needs inthand2_t from isa_device.h */ 42425f9fdaSStefan Eßer 43425f9fdaSStefan Eßer #include <machine/spl.h> 44425f9fdaSStefan Eßer 45425f9fdaSStefan Eßer #include <stddef.h> 46425f9fdaSStefan Eßer 47425f9fdaSStefan Eßer #include "vector.h" 48425f9fdaSStefan Eßer 49425f9fdaSStefan Eßer /* 50425f9fdaSStefan Eßer * The interrupt multiplexer calls each of the handlers in turn, 51425f9fdaSStefan Eßer * and applies the associated interrupt mask to "cpl", which is 52425f9fdaSStefan Eßer * defined as a ".long" in /sys/i386/isa/icu.s 53425f9fdaSStefan Eßer */ 54425f9fdaSStefan Eßer 55425f9fdaSStefan Eßer static inline intrmask 56425f9fdaSStefan Eßer splq(intrmask mask) 57425f9fdaSStefan Eßer { 58425f9fdaSStefan Eßer intrmask tmp = cpl; 59425f9fdaSStefan Eßer cpl |= mask; 60425f9fdaSStefan Eßer return (tmp); 61425f9fdaSStefan Eßer } 62425f9fdaSStefan Eßer 63425f9fdaSStefan Eßer static void 64425f9fdaSStefan Eßer intr_mux(void *arg) 65425f9fdaSStefan Eßer { 66425f9fdaSStefan Eßer intrec *p = arg; 67425f9fdaSStefan Eßer 68425f9fdaSStefan Eßer while (p != NULL) { 69425f9fdaSStefan Eßer int oldspl = splq(p->mask); 70425f9fdaSStefan Eßer /* inthand2_t should take (void*) argument */ 71425f9fdaSStefan Eßer p->handler(p->argument); 72425f9fdaSStefan Eßer splx(oldspl); 73425f9fdaSStefan Eßer p = p->next; 74425f9fdaSStefan Eßer } 75425f9fdaSStefan Eßer } 76425f9fdaSStefan Eßer 77425f9fdaSStefan Eßer /* XXX better use NHWI from <machine/ipl.h> for array size ??? */ 78425f9fdaSStefan Eßer static intrec *intreclist_head[ICU_LEN]; 79425f9fdaSStefan Eßer 80425f9fdaSStefan Eßer static intrec* 81425f9fdaSStefan Eßer find_idesc(unsigned *maskptr, int irq) 82425f9fdaSStefan Eßer { 83425f9fdaSStefan Eßer intrec *p = intreclist_head[irq]; 84425f9fdaSStefan Eßer 85425f9fdaSStefan Eßer while (p && p->maskptr != maskptr) 86425f9fdaSStefan Eßer p = p->next; 87425f9fdaSStefan Eßer 88425f9fdaSStefan Eßer return (p); 89425f9fdaSStefan Eßer } 90425f9fdaSStefan Eßer 91425f9fdaSStefan Eßer static intrec** 92425f9fdaSStefan Eßer find_pred(intrec *idesc, int irq) 93425f9fdaSStefan Eßer { 94425f9fdaSStefan Eßer intrec **pp = &intreclist_head[irq]; 95425f9fdaSStefan Eßer intrec *p = *pp; 96425f9fdaSStefan Eßer 97425f9fdaSStefan Eßer while (p != idesc) { 98425f9fdaSStefan Eßer if (p == NULL) 99425f9fdaSStefan Eßer return (NULL); 100425f9fdaSStefan Eßer pp = &p->next; 101425f9fdaSStefan Eßer p = *pp; 102425f9fdaSStefan Eßer } 103425f9fdaSStefan Eßer return (pp); 104425f9fdaSStefan Eßer } 105425f9fdaSStefan Eßer 106425f9fdaSStefan Eßer /* 107425f9fdaSStefan Eßer * Both the low level handler and the shared interrupt multiplexer 108425f9fdaSStefan Eßer * block out further interrupts as set in the handlers "mask", while 109425f9fdaSStefan Eßer * the handler is running. In fact *maskptr should be used for this 110425f9fdaSStefan Eßer * purpose, but since this requires one more pointer dereference on 111425f9fdaSStefan Eßer * each interrupt, we rather bother update "mask" whenever *maskptr 112425f9fdaSStefan Eßer * changes. The function "update_masks" should be called **after** 113425f9fdaSStefan Eßer * all manipulation of the linked list of interrupt handlers hung 114425f9fdaSStefan Eßer * off of intrdec_head[irq] is complete, since the chain of handlers 115425f9fdaSStefan Eßer * will both determine the *maskptr values and the instances of mask 116425f9fdaSStefan Eßer * that are fixed. This function should be called with the irq for 117425f9fdaSStefan Eßer * which a new handler has been add blocked, since the masks may not 118425f9fdaSStefan Eßer * yet know about the use of this irq for a device of a certain class. 119425f9fdaSStefan Eßer */ 120425f9fdaSStefan Eßer 121425f9fdaSStefan Eßer static void 122425f9fdaSStefan Eßer update_mux_masks(void) 123425f9fdaSStefan Eßer { 124425f9fdaSStefan Eßer int irq; 125425f9fdaSStefan Eßer for (irq = 0; irq < ICU_LEN; irq++) { 126425f9fdaSStefan Eßer intrec *idesc = intreclist_head[irq]; 127425f9fdaSStefan Eßer while (idesc != NULL) { 128425f9fdaSStefan Eßer if (idesc->maskptr != NULL) { 129425f9fdaSStefan Eßer /* our copy of *maskptr may be stale, refresh */ 130425f9fdaSStefan Eßer idesc->mask = *idesc->maskptr; 131425f9fdaSStefan Eßer } 132425f9fdaSStefan Eßer idesc = idesc->next; 133425f9fdaSStefan Eßer } 134425f9fdaSStefan Eßer } 135425f9fdaSStefan Eßer } 136425f9fdaSStefan Eßer 137425f9fdaSStefan Eßer static void 138425f9fdaSStefan Eßer update_masks(intrmask *maskptr, int irq) 139425f9fdaSStefan Eßer { 140425f9fdaSStefan Eßer intrmask mask = 1 << irq; 141425f9fdaSStefan Eßer 142425f9fdaSStefan Eßer if (maskptr == NULL) 143425f9fdaSStefan Eßer return; 144425f9fdaSStefan Eßer 145425f9fdaSStefan Eßer if (find_idesc(maskptr, irq) == NULL) { 146425f9fdaSStefan Eßer /* no reference to this maskptr was found in this irq's chain */ 147425f9fdaSStefan Eßer if ((*maskptr & mask) == 0) 148425f9fdaSStefan Eßer return; 149425f9fdaSStefan Eßer /* the irq was included in the classes mask, remove it */ 150425f9fdaSStefan Eßer INTRUNMASK(*maskptr, mask); 151425f9fdaSStefan Eßer } else { 152425f9fdaSStefan Eßer /* a reference to this maskptr was found in this irq's chain */ 153425f9fdaSStefan Eßer if ((*maskptr & mask) != 0) 154425f9fdaSStefan Eßer return; 155425f9fdaSStefan Eßer /* put the irq into the classes mask */ 156425f9fdaSStefan Eßer INTRMASK(*maskptr, mask); 157425f9fdaSStefan Eßer } 158425f9fdaSStefan Eßer /* we need to update all values in the intr_mask[irq] array */ 159425f9fdaSStefan Eßer update_intr_masks(); 160425f9fdaSStefan Eßer /* update mask in chains of the interrupt multiplex handler as well */ 161425f9fdaSStefan Eßer update_mux_masks(); 162425f9fdaSStefan Eßer } 163425f9fdaSStefan Eßer 164425f9fdaSStefan Eßer /* 165425f9fdaSStefan Eßer * Add interrupt handler to linked list hung off of intreclist_head[irq] 166425f9fdaSStefan Eßer * and install shared interrupt multiplex handler, if necessary 167425f9fdaSStefan Eßer */ 168425f9fdaSStefan Eßer 169425f9fdaSStefan Eßer static int 170425f9fdaSStefan Eßer add_intrdesc(intrec *idesc) 171425f9fdaSStefan Eßer { 172425f9fdaSStefan Eßer int irq = idesc->intr; 173425f9fdaSStefan Eßer 174425f9fdaSStefan Eßer intrec *head = intreclist_head[irq]; 175425f9fdaSStefan Eßer 176425f9fdaSStefan Eßer if (head == NULL) { 177425f9fdaSStefan Eßer /* first handler for this irq, just install it */ 178425f9fdaSStefan Eßer if (icu_setup(irq, idesc->handler, idesc->argument, 179425f9fdaSStefan Eßer idesc->maskptr, idesc->flags) != 0) 180425f9fdaSStefan Eßer return (-1); 181425f9fdaSStefan Eßer 182425f9fdaSStefan Eßer update_intrname(irq, idesc->devdata); 183425f9fdaSStefan Eßer /* keep reference */ 184425f9fdaSStefan Eßer intreclist_head[irq] = idesc; 185425f9fdaSStefan Eßer } else { 186425f9fdaSStefan Eßer if ((idesc->flags & INTR_EXCL) != 0 187425f9fdaSStefan Eßer || (head->flags & INTR_EXCL) != 0) { 188425f9fdaSStefan Eßer /* 189425f9fdaSStefan Eßer * can't append new handler, if either list head or 190425f9fdaSStefan Eßer * new handler do not allow interrupts to be shared 191425f9fdaSStefan Eßer */ 192425f9fdaSStefan Eßer printf("\tdevice combination doesn't support shared irq%d\n", 193425f9fdaSStefan Eßer irq); 194425f9fdaSStefan Eßer return (-1); 195425f9fdaSStefan Eßer } 196425f9fdaSStefan Eßer if (head->next == NULL) { 197425f9fdaSStefan Eßer /* 198425f9fdaSStefan Eßer * second handler for this irq, replace device driver's 199425f9fdaSStefan Eßer * handler by shared interrupt multiplexer function 200425f9fdaSStefan Eßer */ 201425f9fdaSStefan Eßer icu_unset(irq, head->handler); 202425f9fdaSStefan Eßer if (icu_setup(irq, intr_mux, head, 0, 0) != 0) 203425f9fdaSStefan Eßer return (-1); 204425f9fdaSStefan Eßer if (bootverbose) 205425f9fdaSStefan Eßer printf("\tusing shared irq%d.\n", irq); 206425f9fdaSStefan Eßer update_intrname(irq, -1); 207425f9fdaSStefan Eßer } 208425f9fdaSStefan Eßer /* just append to the end of the chain */ 209425f9fdaSStefan Eßer while (head->next != NULL) 210425f9fdaSStefan Eßer head = head->next; 211425f9fdaSStefan Eßer head->next = idesc; 212425f9fdaSStefan Eßer } 213425f9fdaSStefan Eßer update_masks(idesc->maskptr, irq); 214425f9fdaSStefan Eßer return (0); 215425f9fdaSStefan Eßer } 216425f9fdaSStefan Eßer 217425f9fdaSStefan Eßer /* 218425f9fdaSStefan Eßer * Add the interrupt handler descriptor data structure created by an 219425f9fdaSStefan Eßer * earlier call of create_intr() to the linked list for its irq and 220425f9fdaSStefan Eßer * adjust the interrupt masks if necessary. 221425f9fdaSStefan Eßer * 222425f9fdaSStefan Eßer * This function effectively activates the handler. 223425f9fdaSStefan Eßer */ 224425f9fdaSStefan Eßer 225425f9fdaSStefan Eßer int 226425f9fdaSStefan Eßer intr_connect(intrec *idesc) 227425f9fdaSStefan Eßer { 228425f9fdaSStefan Eßer int errcode = -1; 229425f9fdaSStefan Eßer int irq; 230425f9fdaSStefan Eßer 231425f9fdaSStefan Eßer #ifdef RESOURCE_CHECK 232425f9fdaSStefan Eßer int resflag; 233425f9fdaSStefan Eßer #endif /* RESOURCE_CHECK */ 234425f9fdaSStefan Eßer 235425f9fdaSStefan Eßer if (idesc == NULL) 236425f9fdaSStefan Eßer return (-1); 237425f9fdaSStefan Eßer 238425f9fdaSStefan Eßer irq = idesc->intr; 239425f9fdaSStefan Eßer #ifdef RESOURCE_CHECK 240425f9fdaSStefan Eßer resflag = (idesc->flags & INTR_EXCL) ? RESF_NONE : RESF_SHARED; 241425f9fdaSStefan Eßer if (resource_claim(idesc->devdata, REST_INT, resflag, irq, irq) == 0) 242425f9fdaSStefan Eßer #endif /* RESOURCE_CHECK */ 243425f9fdaSStefan Eßer { 244425f9fdaSStefan Eßer /* block this irq */ 245425f9fdaSStefan Eßer intrmask oldspl = splq(1 << irq); 246425f9fdaSStefan Eßer 247425f9fdaSStefan Eßer /* add irq to class selected by maskptr */ 248425f9fdaSStefan Eßer errcode = add_intrdesc(idesc); 249425f9fdaSStefan Eßer splx(oldspl); 250425f9fdaSStefan Eßer } 251425f9fdaSStefan Eßer if (errcode != 0) 252425f9fdaSStefan Eßer printf("\tintr_connect(irq%d) failed, result=%d\n", 253425f9fdaSStefan Eßer irq, errcode); 254425f9fdaSStefan Eßer 255425f9fdaSStefan Eßer return (errcode); 256425f9fdaSStefan Eßer } 257425f9fdaSStefan Eßer 258425f9fdaSStefan Eßer /* 259425f9fdaSStefan Eßer * Remove the interrupt handler descriptor data connected created by an 260425f9fdaSStefan Eßer * earlier call of intr_connect() from the linked list and adjust the 261425f9fdaSStefan Eßer * interrupt masks if necessary. 262425f9fdaSStefan Eßer * 263425f9fdaSStefan Eßer * This function deactivates the handler. 264425f9fdaSStefan Eßer */ 265425f9fdaSStefan Eßer 266425f9fdaSStefan Eßer int 267425f9fdaSStefan Eßer intr_disconnect(intrec *idesc) 268425f9fdaSStefan Eßer { 269425f9fdaSStefan Eßer intrec **hook, *head; 270425f9fdaSStefan Eßer int irq; 271425f9fdaSStefan Eßer int errcode = 0; 272425f9fdaSStefan Eßer 273425f9fdaSStefan Eßer if (idesc == NULL) 274425f9fdaSStefan Eßer return (-1); 275425f9fdaSStefan Eßer 276425f9fdaSStefan Eßer irq = idesc->intr; 277425f9fdaSStefan Eßer 278425f9fdaSStefan Eßer /* find pointer that keeps the reference to this interrupt descriptor */ 279425f9fdaSStefan Eßer hook = find_pred(idesc, irq); 280425f9fdaSStefan Eßer if (hook == NULL) 281425f9fdaSStefan Eßer return (-1); 282425f9fdaSStefan Eßer 283425f9fdaSStefan Eßer /* make copy of original list head, the line after may overwrite it */ 284425f9fdaSStefan Eßer head = intreclist_head[irq]; 285425f9fdaSStefan Eßer 286425f9fdaSStefan Eßer /* unlink: make predecessor point to idesc->next instead of to idesc */ 287425f9fdaSStefan Eßer *hook = idesc->next; 288425f9fdaSStefan Eßer 289425f9fdaSStefan Eßer /* now check whether the element we removed was the list head */ 290425f9fdaSStefan Eßer if (idesc == head) { 291425f9fdaSStefan Eßer intrmask oldspl = splq(1 << irq); 292425f9fdaSStefan Eßer 293425f9fdaSStefan Eßer /* we want to remove the list head, which was known to intr_mux */ 294425f9fdaSStefan Eßer icu_unset(irq, intr_mux); 295425f9fdaSStefan Eßer 296425f9fdaSStefan Eßer /* check whether the new list head is the only element on list */ 297425f9fdaSStefan Eßer head = intreclist_head[irq]; 298425f9fdaSStefan Eßer if (head->next != NULL) { 299425f9fdaSStefan Eßer /* install the multiplex handler with new list head as argument */ 300425f9fdaSStefan Eßer errcode = icu_setup(irq, intr_mux, head, 0, 0); 301425f9fdaSStefan Eßer if (errcode == 0) 302425f9fdaSStefan Eßer update_intrname(irq, -1); 303425f9fdaSStefan Eßer } else if (head != NULL) { 304425f9fdaSStefan Eßer /* install the one remaining handler for this irq */ 305425f9fdaSStefan Eßer errcode = icu_setup(irq, head->handler, head->argument, 306425f9fdaSStefan Eßer head->maskptr, head->flags); 307425f9fdaSStefan Eßer if (errcode == 0) 308425f9fdaSStefan Eßer update_intrname(irq, head->devdata); 309425f9fdaSStefan Eßer } 310425f9fdaSStefan Eßer splx(oldspl); 311425f9fdaSStefan Eßer } 312425f9fdaSStefan Eßer update_masks(idesc->maskptr, irq); 313425f9fdaSStefan Eßer #ifdef RESOURCE_CHECK 314425f9fdaSStefan Eßer resource_free(idesc->devdata); 315425f9fdaSStefan Eßer #endif /* RESOURCE_CHECK */ 316425f9fdaSStefan Eßer return (0); 317425f9fdaSStefan Eßer } 318425f9fdaSStefan Eßer 319425f9fdaSStefan Eßer /* 320425f9fdaSStefan Eßer * Create an interrupt handler descriptor data structure, which later can 321425f9fdaSStefan Eßer * be activated or deactivated at will by calls of [dis]connect(intrec*). 322425f9fdaSStefan Eßer * 323425f9fdaSStefan Eßer * The dev_instance pointer is required for resource management, and will 324425f9fdaSStefan Eßer * only be passed through to resource_claim(). 325425f9fdaSStefan Eßer * 326425f9fdaSStefan Eßer * The interrupt handler takes an argument of type (void*), which is not 327425f9fdaSStefan Eßer * what is currently used for ISA devices. But since the unit number passed 328425f9fdaSStefan Eßer * to an ISA interrupt handler can be stored in a (void*) variable, this 329425f9fdaSStefan Eßer * causes no problems. Eventually all the ISA interrupt handlers should be 330425f9fdaSStefan Eßer * modified to accept the pointer to their private data, too, instead of 331425f9fdaSStefan Eßer * an integer index. 332425f9fdaSStefan Eßer * 333425f9fdaSStefan Eßer * There will be functions that derive a driver and unit name from a 334425f9fdaSStefan Eßer * dev_instance variable, and those functions will be used to maintain the 335425f9fdaSStefan Eßer * interrupt counter label array referenced by systat and vmstat to report 336425f9fdaSStefan Eßer * device interrupt rates (->update_intrlabels). 337425f9fdaSStefan Eßer */ 338425f9fdaSStefan Eßer 339425f9fdaSStefan Eßer intrec * 340425f9fdaSStefan Eßer intr_create(void *dev_instance, int irq, inthand2_t handler, void *arg, 341425f9fdaSStefan Eßer intrmask *maskptr, int flags) 342425f9fdaSStefan Eßer { 343425f9fdaSStefan Eßer intrec *idesc; 344425f9fdaSStefan Eßer 345425f9fdaSStefan Eßer if (ICU_LEN > 8 * sizeof *maskptr) { 346425f9fdaSStefan Eßer printf("create_intr: ICU_LEN of %d too high for %d bit intrmask\n", 347425f9fdaSStefan Eßer ICU_LEN, 8 * sizeof *maskptr); 348425f9fdaSStefan Eßer return (NULL); 349425f9fdaSStefan Eßer } 350425f9fdaSStefan Eßer if ((unsigned)irq >= ICU_LEN) { 351425f9fdaSStefan Eßer printf("create_intr: requested irq%d too high, limit is %d\n", 352425f9fdaSStefan Eßer irq, ICU_LEN -1); 353425f9fdaSStefan Eßer return (NULL); 354425f9fdaSStefan Eßer } 355425f9fdaSStefan Eßer 356425f9fdaSStefan Eßer idesc = malloc(sizeof *idesc, M_DEVBUF, M_WAITOK); 357425f9fdaSStefan Eßer if (idesc) { 358425f9fdaSStefan Eßer idesc->next = NULL; 359425f9fdaSStefan Eßer bzero(idesc, sizeof *idesc); 360425f9fdaSStefan Eßer 361425f9fdaSStefan Eßer idesc->devdata = dev_instance; 362425f9fdaSStefan Eßer idesc->handler = handler; 363425f9fdaSStefan Eßer idesc->argument = arg; 364425f9fdaSStefan Eßer idesc->maskptr = maskptr; 365425f9fdaSStefan Eßer idesc->intr = irq; 366425f9fdaSStefan Eßer idesc->flags = flags; 367425f9fdaSStefan Eßer } 368425f9fdaSStefan Eßer return (idesc); 369425f9fdaSStefan Eßer } 370425f9fdaSStefan Eßer 371425f9fdaSStefan Eßer /* 372425f9fdaSStefan Eßer * Return the memory held by the interrupt handler descriptor data structure 373425f9fdaSStefan Eßer * to the system. Make sure, the handler is not actively used anymore, before. 374425f9fdaSStefan Eßer */ 375425f9fdaSStefan Eßer 376425f9fdaSStefan Eßer int 377425f9fdaSStefan Eßer intr_destroy(intrec *rec) 378425f9fdaSStefan Eßer { 379425f9fdaSStefan Eßer if (intr_disconnect(rec) != 0) 380425f9fdaSStefan Eßer return (-1); 381425f9fdaSStefan Eßer free(rec, M_DEVBUF); 382425f9fdaSStefan Eßer return (0); 383425f9fdaSStefan Eßer } 384425f9fdaSStefan Eßer 385425f9fdaSStefan Eßer /* 386425f9fdaSStefan Eßer * Emulate the register_intr() call previously defined as low level function. 387425f9fdaSStefan Eßer * That function (now icu_setup()) may no longer be directly called, since 388425f9fdaSStefan Eßer * a conflict between an ISA and PCI interrupt might go by unnocticed, else. 389425f9fdaSStefan Eßer */ 390425f9fdaSStefan Eßer 391425f9fdaSStefan Eßer int 392425f9fdaSStefan Eßer register_intr(int intr, int device_id, u_int flags, 393425f9fdaSStefan Eßer inthand2_t handler, u_int *maskptr, int unit) 394425f9fdaSStefan Eßer { 395425f9fdaSStefan Eßer /* XXX modify to include isa_device instead of device_id */ 396425f9fdaSStefan Eßer intrec *idesc; 397425f9fdaSStefan Eßer 398425f9fdaSStefan Eßer flags |= INTR_EXCL; 399425f9fdaSStefan Eßer idesc = intr_create((void *)device_id, intr, handler, 400425f9fdaSStefan Eßer (void*)unit, maskptr, flags); 401425f9fdaSStefan Eßer return (intr_connect(idesc)); 402425f9fdaSStefan Eßer } 403425f9fdaSStefan Eßer 404425f9fdaSStefan Eßer /* 405425f9fdaSStefan Eßer * Emulate the old unregister_intr() low level function. 406425f9fdaSStefan Eßer * Make sure there is just one interrupt, that it was 407425f9fdaSStefan Eßer * registered as non-shared, and that the handlers match. 408425f9fdaSStefan Eßer */ 409425f9fdaSStefan Eßer 410425f9fdaSStefan Eßer int 411425f9fdaSStefan Eßer unregister_intr(int intr, inthand2_t handler) 412425f9fdaSStefan Eßer { 413425f9fdaSStefan Eßer intrec *p = intreclist_head[intr]; 414425f9fdaSStefan Eßer 415425f9fdaSStefan Eßer if (p != NULL && (p->flags & INTR_EXCL) != 0 && p->handler == handler) 416425f9fdaSStefan Eßer return (intr_destroy(p)); 417425f9fdaSStefan Eßer return (EINVAL); 418425f9fdaSStefan Eßer } 419