149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini * QEMU IRQ/GPIO common code.
349ab747fSPaolo Bonzini *
449ab747fSPaolo Bonzini * Copyright (c) 2007 CodeSourcery.
549ab747fSPaolo Bonzini *
649ab747fSPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
749ab747fSPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
849ab747fSPaolo Bonzini * in the Software without restriction, including without limitation the rights
949ab747fSPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1049ab747fSPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
1149ab747fSPaolo Bonzini * furnished to do so, subject to the following conditions:
1249ab747fSPaolo Bonzini *
1349ab747fSPaolo Bonzini * The above copyright notice and this permission notice shall be included in
1449ab747fSPaolo Bonzini * all copies or substantial portions of the Software.
1549ab747fSPaolo Bonzini *
1649ab747fSPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1749ab747fSPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1849ab747fSPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1949ab747fSPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2049ab747fSPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2149ab747fSPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2249ab747fSPaolo Bonzini * THE SOFTWARE.
2349ab747fSPaolo Bonzini */
2418c86e2bSPeter Maydell #include "qemu/osdep.h"
258d04fb55SJan Kiszka #include "qemu/main-loop.h"
2649ab747fSPaolo Bonzini #include "hw/irq.h"
27615c4895SAndreas Färber #include "qom/object.h"
28615c4895SAndreas Färber
qemu_set_irq(qemu_irq irq,int level)2949ab747fSPaolo Bonzini void qemu_set_irq(qemu_irq irq, int level)
3049ab747fSPaolo Bonzini {
3149ab747fSPaolo Bonzini if (!irq)
3249ab747fSPaolo Bonzini return;
3349ab747fSPaolo Bonzini
3449ab747fSPaolo Bonzini irq->handler(irq->opaque, irq->n, level);
3549ab747fSPaolo Bonzini }
3649ab747fSPaolo Bonzini
init_irq_fields(IRQState * irq,qemu_irq_handler handler,void * opaque,int n)37*89d94c04SMatheus Tavares Bernardino static void init_irq_fields(IRQState *irq, qemu_irq_handler handler,
38*89d94c04SMatheus Tavares Bernardino void *opaque, int n)
39*89d94c04SMatheus Tavares Bernardino {
40*89d94c04SMatheus Tavares Bernardino irq->handler = handler;
41*89d94c04SMatheus Tavares Bernardino irq->opaque = opaque;
42*89d94c04SMatheus Tavares Bernardino irq->n = n;
43*89d94c04SMatheus Tavares Bernardino }
44*89d94c04SMatheus Tavares Bernardino
qemu_init_irq(IRQState * irq,qemu_irq_handler handler,void * opaque,int n)45e72a7f65SBALATON Zoltan void qemu_init_irq(IRQState *irq, qemu_irq_handler handler, void *opaque,
46e72a7f65SBALATON Zoltan int n)
47e72a7f65SBALATON Zoltan {
48e72a7f65SBALATON Zoltan object_initialize(irq, sizeof(*irq), TYPE_IRQ);
49*89d94c04SMatheus Tavares Bernardino init_irq_fields(irq, handler, opaque, n);
50e72a7f65SBALATON Zoltan }
51e72a7f65SBALATON Zoltan
qemu_extend_irqs(qemu_irq * old,int n_old,qemu_irq_handler handler,void * opaque,int n)5249ab747fSPaolo Bonzini qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
5349ab747fSPaolo Bonzini void *opaque, int n)
5449ab747fSPaolo Bonzini {
5549ab747fSPaolo Bonzini qemu_irq *s;
5649ab747fSPaolo Bonzini int i;
5749ab747fSPaolo Bonzini
5849ab747fSPaolo Bonzini if (!old) {
5949ab747fSPaolo Bonzini n_old = 0;
6049ab747fSPaolo Bonzini }
6149ab747fSPaolo Bonzini s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n);
62f173d57aSPeter Crosthwaite for (i = n_old; i < n + n_old; i++) {
63f173d57aSPeter Crosthwaite s[i] = qemu_allocate_irq(handler, opaque, i);
6449ab747fSPaolo Bonzini }
6549ab747fSPaolo Bonzini return s;
6649ab747fSPaolo Bonzini }
6749ab747fSPaolo Bonzini
qemu_allocate_irqs(qemu_irq_handler handler,void * opaque,int n)6849ab747fSPaolo Bonzini qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
6949ab747fSPaolo Bonzini {
7049ab747fSPaolo Bonzini return qemu_extend_irqs(NULL, 0, handler, opaque, n);
7149ab747fSPaolo Bonzini }
7249ab747fSPaolo Bonzini
qemu_allocate_irq(qemu_irq_handler handler,void * opaque,int n)73a8a9d30bSMarcel Apfelbaum qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n)
74a8a9d30bSMarcel Apfelbaum {
75*89d94c04SMatheus Tavares Bernardino IRQState *irq = IRQ(object_new(TYPE_IRQ));
76*89d94c04SMatheus Tavares Bernardino init_irq_fields(irq, handler, opaque, n);
77a8a9d30bSMarcel Apfelbaum return irq;
78a8a9d30bSMarcel Apfelbaum }
7949ab747fSPaolo Bonzini
qemu_free_irqs(qemu_irq * s,int n)80f173d57aSPeter Crosthwaite void qemu_free_irqs(qemu_irq *s, int n)
8149ab747fSPaolo Bonzini {
82f173d57aSPeter Crosthwaite int i;
83f173d57aSPeter Crosthwaite for (i = 0; i < n; i++) {
84f173d57aSPeter Crosthwaite qemu_free_irq(s[i]);
85f173d57aSPeter Crosthwaite }
8649ab747fSPaolo Bonzini g_free(s);
8749ab747fSPaolo Bonzini }
8849ab747fSPaolo Bonzini
qemu_free_irq(qemu_irq irq)89a8a9d30bSMarcel Apfelbaum void qemu_free_irq(qemu_irq irq)
90a8a9d30bSMarcel Apfelbaum {
91615c4895SAndreas Färber object_unref(OBJECT(irq));
92a8a9d30bSMarcel Apfelbaum }
93a8a9d30bSMarcel Apfelbaum
qemu_notirq(void * opaque,int line,int level)9449ab747fSPaolo Bonzini static void qemu_notirq(void *opaque, int line, int level)
9549ab747fSPaolo Bonzini {
964703f6c2SPhilippe Mathieu-Daudé IRQState *irq = opaque;
9749ab747fSPaolo Bonzini
9849ab747fSPaolo Bonzini irq->handler(irq->opaque, irq->n, !level);
9949ab747fSPaolo Bonzini }
10049ab747fSPaolo Bonzini
qemu_irq_invert(qemu_irq irq)10149ab747fSPaolo Bonzini qemu_irq qemu_irq_invert(qemu_irq irq)
10249ab747fSPaolo Bonzini {
10349ab747fSPaolo Bonzini /* The default state for IRQs is low, so raise the output now. */
10449ab747fSPaolo Bonzini qemu_irq_raise(irq);
105f3c7d038SAndreas Färber return qemu_allocate_irq(qemu_notirq, irq, 0);
10649ab747fSPaolo Bonzini }
10749ab747fSPaolo Bonzini
qemu_irq_intercept_in(qemu_irq * gpio_in,qemu_irq_handler handler,int n)10849ab747fSPaolo Bonzini void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
10949ab747fSPaolo Bonzini {
11049ab747fSPaolo Bonzini int i;
11149ab747fSPaolo Bonzini qemu_irq *old_irqs = qemu_allocate_irqs(NULL, NULL, n);
11249ab747fSPaolo Bonzini for (i = 0; i < n; i++) {
11349ab747fSPaolo Bonzini *old_irqs[i] = *gpio_in[i];
11449ab747fSPaolo Bonzini gpio_in[i]->handler = handler;
11560a79016SPeter Crosthwaite gpio_in[i]->opaque = &old_irqs[i];
11649ab747fSPaolo Bonzini }
11749ab747fSPaolo Bonzini }
11849ab747fSPaolo Bonzini
119615c4895SAndreas Färber static const TypeInfo irq_type_info = {
120615c4895SAndreas Färber .name = TYPE_IRQ,
121615c4895SAndreas Färber .parent = TYPE_OBJECT,
1224703f6c2SPhilippe Mathieu-Daudé .instance_size = sizeof(IRQState),
123615c4895SAndreas Färber };
124615c4895SAndreas Färber
irq_register_types(void)125615c4895SAndreas Färber static void irq_register_types(void)
126615c4895SAndreas Färber {
127615c4895SAndreas Färber type_register_static(&irq_type_info);
128615c4895SAndreas Färber }
129615c4895SAndreas Färber
130615c4895SAndreas Färber type_init(irq_register_types)
131