qemu

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

m68k_irqc.c (2934B)


      1 /*
      2  * SPDX-License-Identifier: GPL-2.0-or-later
      3  *
      4  * QEMU Motorola 680x0 IRQ Controller
      5  *
      6  * (c) 2020 Laurent Vivier <laurent@vivier.eu>
      7  *
      8  */
      9 
     10 #include "qemu/osdep.h"
     11 #include "cpu.h"
     12 #include "migration/vmstate.h"
     13 #include "monitor/monitor.h"
     14 #include "hw/nmi.h"
     15 #include "hw/intc/intc.h"
     16 #include "hw/intc/m68k_irqc.h"
     17 
     18 
     19 static bool m68k_irqc_get_statistics(InterruptStatsProvider *obj,
     20                                      uint64_t **irq_counts, unsigned int *nb_irqs)
     21 {
     22     M68KIRQCState *s = M68K_IRQC(obj);
     23 
     24     *irq_counts = s->stats_irq_count;
     25     *nb_irqs = ARRAY_SIZE(s->stats_irq_count);
     26     return true;
     27 }
     28 
     29 static void m68k_irqc_print_info(InterruptStatsProvider *obj, Monitor *mon)
     30 {
     31     M68KIRQCState *s = M68K_IRQC(obj);
     32     monitor_printf(mon, "m68k-irqc: ipr=0x%x\n", s->ipr);
     33 }
     34 
     35 static void m68k_set_irq(void *opaque, int irq, int level)
     36 {
     37     M68KIRQCState *s = opaque;
     38     M68kCPU *cpu = M68K_CPU(first_cpu);
     39     int i;
     40 
     41     if (level) {
     42         s->ipr |= 1 << irq;
     43         s->stats_irq_count[irq]++;
     44     } else {
     45         s->ipr &= ~(1 << irq);
     46     }
     47 
     48     for (i = M68K_IRQC_LEVEL_7; i >= M68K_IRQC_LEVEL_1; i--) {
     49         if ((s->ipr >> i) & 1) {
     50             m68k_set_irq_level(cpu, i + 1, i + M68K_IRQC_AUTOVECTOR_BASE);
     51             return;
     52         }
     53     }
     54     m68k_set_irq_level(cpu, 0, 0);
     55 }
     56 
     57 static void m68k_irqc_reset(DeviceState *d)
     58 {
     59     M68KIRQCState *s = M68K_IRQC(d);
     60     int i;
     61 
     62     s->ipr = 0;
     63     for (i = 0; i < ARRAY_SIZE(s->stats_irq_count); i++) {
     64         s->stats_irq_count[i] = 0;
     65     }
     66 }
     67 
     68 static void m68k_irqc_instance_init(Object *obj)
     69 {
     70     qdev_init_gpio_in(DEVICE(obj), m68k_set_irq, M68K_IRQC_LEVEL_NUM);
     71 }
     72 
     73 static void m68k_nmi(NMIState *n, int cpu_index, Error **errp)
     74 {
     75     m68k_set_irq(n, M68K_IRQC_LEVEL_7, 1);
     76 }
     77 
     78 static const VMStateDescription vmstate_m68k_irqc = {
     79     .name = "m68k-irqc",
     80     .version_id = 1,
     81     .minimum_version_id = 1,
     82     .fields = (VMStateField[]) {
     83         VMSTATE_UINT8(ipr, M68KIRQCState),
     84         VMSTATE_END_OF_LIST()
     85     }
     86 };
     87 
     88 static void m68k_irqc_class_init(ObjectClass *oc, void *data)
     89  {
     90     DeviceClass *dc = DEVICE_CLASS(oc);
     91     NMIClass *nc = NMI_CLASS(oc);
     92     InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(oc);
     93 
     94     nc->nmi_monitor_handler = m68k_nmi;
     95     dc->reset = m68k_irqc_reset;
     96     dc->vmsd = &vmstate_m68k_irqc;
     97     ic->get_statistics = m68k_irqc_get_statistics;
     98     ic->print_info = m68k_irqc_print_info;
     99 }
    100 
    101 static const TypeInfo m68k_irqc_type_info = {
    102     .name = TYPE_M68K_IRQC,
    103     .parent = TYPE_SYS_BUS_DEVICE,
    104     .instance_size = sizeof(M68KIRQCState),
    105     .instance_init = m68k_irqc_instance_init,
    106     .class_init = m68k_irqc_class_init,
    107     .interfaces = (InterfaceInfo[]) {
    108          { TYPE_NMI },
    109          { TYPE_INTERRUPT_STATS_PROVIDER },
    110          { }
    111     },
    112 };
    113 
    114 static void q800_irq_register_types(void)
    115 {
    116     type_register_static(&m68k_irqc_type_info);
    117 }
    118 
    119 type_init(q800_irq_register_types);