qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

or-irq.c (4392B)


      1 /*
      2  * QEMU IRQ/GPIO common code.
      3  *
      4  * Copyright (c) 2016 Alistair Francis <alistair@alistair23.me>.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 
     25 #include "qemu/osdep.h"
     26 #include "hw/irq.h"
     27 #include "hw/or-irq.h"
     28 #include "hw/qdev-properties.h"
     29 #include "migration/vmstate.h"
     30 #include "qemu/module.h"
     31 
     32 static void or_irq_handler(void *opaque, int n, int level)
     33 {
     34     qemu_or_irq *s = OR_IRQ(opaque);
     35     int or_level = 0;
     36     int i;
     37 
     38     s->levels[n] = level;
     39 
     40     for (i = 0; i < s->num_lines; i++) {
     41         or_level |= s->levels[i];
     42     }
     43 
     44     qemu_set_irq(s->out_irq, or_level);
     45 }
     46 
     47 static void or_irq_reset(DeviceState *dev)
     48 {
     49     qemu_or_irq *s = OR_IRQ(dev);
     50     int i;
     51 
     52     for (i = 0; i < MAX_OR_LINES; i++) {
     53         s->levels[i] = false;
     54     }
     55 }
     56 
     57 static void or_irq_realize(DeviceState *dev, Error **errp)
     58 {
     59     qemu_or_irq *s = OR_IRQ(dev);
     60 
     61     assert(s->num_lines <= MAX_OR_LINES);
     62 
     63     qdev_init_gpio_in(dev, or_irq_handler, s->num_lines);
     64 }
     65 
     66 static void or_irq_init(Object *obj)
     67 {
     68     qemu_or_irq *s = OR_IRQ(obj);
     69 
     70     qdev_init_gpio_out(DEVICE(obj), &s->out_irq, 1);
     71 }
     72 
     73 /* The original version of this device had a fixed 16 entries in its
     74  * VMState array; devices with more inputs than this need to
     75  * migrate the extra lines via a subsection.
     76  * The subsection migrates as much of the levels[] array as is needed
     77  * (including repeating the first 16 elements), to avoid the awkwardness
     78  * of splitting it in two to meet the requirements of VMSTATE_VARRAY_UINT16.
     79  */
     80 #define OLD_MAX_OR_LINES 16
     81 #if MAX_OR_LINES < OLD_MAX_OR_LINES
     82 #error MAX_OR_LINES must be at least 16 for migration compatibility
     83 #endif
     84 
     85 static bool vmstate_extras_needed(void *opaque)
     86 {
     87     qemu_or_irq *s = OR_IRQ(opaque);
     88 
     89     return s->num_lines >= OLD_MAX_OR_LINES;
     90 }
     91 
     92 static const VMStateDescription vmstate_or_irq_extras = {
     93     .name = "or-irq-extras",
     94     .version_id = 1,
     95     .minimum_version_id = 1,
     96     .needed = vmstate_extras_needed,
     97     .fields = (VMStateField[]) {
     98         VMSTATE_VARRAY_UINT16_UNSAFE(levels, qemu_or_irq, num_lines, 0,
     99                                      vmstate_info_bool, bool),
    100         VMSTATE_END_OF_LIST(),
    101     },
    102 };
    103 
    104 static const VMStateDescription vmstate_or_irq = {
    105     .name = TYPE_OR_IRQ,
    106     .version_id = 1,
    107     .minimum_version_id = 1,
    108     .fields = (VMStateField[]) {
    109         VMSTATE_BOOL_SUB_ARRAY(levels, qemu_or_irq, 0, OLD_MAX_OR_LINES),
    110         VMSTATE_END_OF_LIST(),
    111     },
    112     .subsections = (const VMStateDescription*[]) {
    113         &vmstate_or_irq_extras,
    114         NULL
    115     },
    116 };
    117 
    118 static Property or_irq_properties[] = {
    119     DEFINE_PROP_UINT16("num-lines", qemu_or_irq, num_lines, 1),
    120     DEFINE_PROP_END_OF_LIST(),
    121 };
    122 
    123 static void or_irq_class_init(ObjectClass *klass, void *data)
    124 {
    125     DeviceClass *dc = DEVICE_CLASS(klass);
    126 
    127     dc->reset = or_irq_reset;
    128     device_class_set_props(dc, or_irq_properties);
    129     dc->realize = or_irq_realize;
    130     dc->vmsd = &vmstate_or_irq;
    131 
    132     /* Reason: Needs to be wired up to work, e.g. see stm32f205_soc.c */
    133     dc->user_creatable = false;
    134 }
    135 
    136 static const TypeInfo or_irq_type_info = {
    137    .name = TYPE_OR_IRQ,
    138    .parent = TYPE_DEVICE,
    139    .instance_size = sizeof(qemu_or_irq),
    140    .instance_init = or_irq_init,
    141    .class_init = or_irq_class_init,
    142 };
    143 
    144 static void or_irq_register_types(void)
    145 {
    146     type_register_static(&or_irq_type_info);
    147 }
    148 
    149 type_init(or_irq_register_types)