2 * Copyright (c) 2018 François Tigeot
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <linux/interrupt.h>
28 #include <linux/device.h>
32 #include <bus/pci/pcivar.h>
37 irq_handler_t handler
;
40 struct resource
*resource
;
42 struct lwkt_serialize irq_lock
;
43 SLIST_ENTRY(irq_data
) id_irq_entries
;
46 SLIST_HEAD(irq_data_list_head
, irq_data
) irq_list
= SLIST_HEAD_INITIALIZER(irq_list
);
48 /* DragonFly irq handler, used to invoke Linux ones */
50 linux_irq_handler(void *arg
)
52 struct irq_data
*irq_entry
= arg
;
54 irq_entry
->handler(irq_entry
->irq
, irq_entry
->dev_id
);
58 * dev is a struct drm_device*
59 * returns: zero on success, non-zero on failure
62 request_irq(unsigned int irq
, irq_handler_t handler
,
63 unsigned long flags
, const char *name
, void *dev
)
66 struct irq_data
*irq_entry
;
67 struct drm_device
*ddev
= dev
;
68 device_t bdev
= ddev
->dev
->bsddev
;
70 irq_entry
= kmalloc(sizeof(*irq_entry
), M_DRM
, M_WAITOK
);
72 /* From drm_init_pdev() */
73 irq_entry
->rid
= ddev
->pdev
->_irqrid
;
74 irq_entry
->resource
= ddev
->pdev
->_irqr
;
77 irq_entry
->dev_id
= dev
;
78 irq_entry
->handler
= handler
;
79 irq_entry
->name
= name
;
80 lwkt_serialize_init(&irq_entry
->irq_lock
);
82 error
= bus_setup_intr(bdev
, irq_entry
->resource
, INTR_MPSAFE
,
83 linux_irq_handler
, irq_entry
, &irq_entry
->cookiep
,
84 &irq_entry
->irq_lock
);
86 kprintf("request_irq: failed in bus_setup_intr()\n");
87 bus_release_resource(bdev
, SYS_RES_IRQ
,
88 irq_entry
->rid
, irq_entry
->resource
);
92 SLIST_INSERT_HEAD(&irq_list
, irq_entry
, id_irq_entries
);
97 /* dev_id is a struct drm_device* */
99 free_irq(unsigned int irq
, void *dev_id
)
101 struct irq_data
*irq_entry
, *tmp_ie
;
102 struct drm_device
*ddev
= dev_id
;
103 device_t bsddev
= ddev
->dev
->bsddev
;
104 struct resource
*res
= ddev
->pdev
->_irqr
;
107 SLIST_FOREACH_MUTABLE(irq_entry
, &irq_list
, id_irq_entries
, tmp_ie
) {
108 if ((irq_entry
->irq
== irq
) && (irq_entry
->dev_id
== dev_id
)) {
115 kprintf("free_irq: irq %d for dev_id %p was not registered\n",
120 bus_teardown_intr(bsddev
, res
, irq_entry
->cookiep
);
121 bus_release_resource(bsddev
, SYS_RES_IRQ
, irq_entry
->rid
, res
);
122 if (ddev
->pdev
->_irq_type
== PCI_INTR_TYPE_MSI
)
123 pci_release_msi(bsddev
);
125 SLIST_REMOVE(&irq_list
, irq_entry
, irq_data
, id_irq_entries
);