qemu

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

lasi.c (6494B)


      1 /*
      2  * HP-PARISC Lasi chipset emulation.
      3  *
      4  * (C) 2019 by Helge Deller <deller@gmx.de>
      5  *
      6  * This work is licensed under the GNU GPL license version 2 or later.
      7  *
      8  * Documentation available at:
      9  * https://parisc.wiki.kernel.org/images-parisc/7/79/Lasi_ers.pdf
     10  */
     11 
     12 #include "qemu/osdep.h"
     13 #include "qemu/units.h"
     14 #include "qemu/log.h"
     15 #include "qapi/error.h"
     16 #include "trace.h"
     17 #include "hw/irq.h"
     18 #include "sysemu/sysemu.h"
     19 #include "sysemu/runstate.h"
     20 #include "migration/vmstate.h"
     21 #include "qom/object.h"
     22 #include "hw/misc/lasi.h"
     23 
     24 
     25 static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
     26                                 unsigned size, bool is_write,
     27                                 MemTxAttrs attrs)
     28 {
     29     bool ret = false;
     30 
     31     switch (addr) {
     32     case LASI_IRR:
     33     case LASI_IMR:
     34     case LASI_IPR:
     35     case LASI_ICR:
     36     case LASI_IAR:
     37 
     38     case LASI_LPT:
     39     case LASI_UART:
     40     case LASI_LAN:
     41     case LASI_RTC:
     42 
     43     case LASI_PCR ... LASI_AMR:
     44         ret = true;
     45     }
     46 
     47     trace_lasi_chip_mem_valid(addr, ret);
     48     return ret;
     49 }
     50 
     51 static MemTxResult lasi_chip_read_with_attrs(void *opaque, hwaddr addr,
     52                                              uint64_t *data, unsigned size,
     53                                              MemTxAttrs attrs)
     54 {
     55     LasiState *s = opaque;
     56     MemTxResult ret = MEMTX_OK;
     57     uint32_t val;
     58 
     59     switch (addr) {
     60     case LASI_IRR:
     61         val = s->irr;
     62         break;
     63     case LASI_IMR:
     64         val = s->imr;
     65         break;
     66     case LASI_IPR:
     67         val = s->ipr;
     68         /* Any read to IPR clears the register.  */
     69         s->ipr = 0;
     70         break;
     71     case LASI_ICR:
     72         val = s->icr & ICR_BUS_ERROR_BIT; /* bus_error */
     73         break;
     74     case LASI_IAR:
     75         val = s->iar;
     76         break;
     77 
     78     case LASI_LPT:
     79     case LASI_UART:
     80     case LASI_LAN:
     81         val = 0;
     82         break;
     83     case LASI_RTC:
     84         val = time(NULL);
     85         val += s->rtc_ref;
     86         break;
     87 
     88     case LASI_PCR:
     89     case LASI_VER:      /* only version 0 existed. */
     90     case LASI_IORESET:
     91         val = 0;
     92         break;
     93     case LASI_ERRLOG:
     94         val = s->errlog;
     95         break;
     96     case LASI_AMR:
     97         val = s->amr;
     98         break;
     99 
    100     default:
    101         /* Controlled by lasi_chip_mem_valid above. */
    102         g_assert_not_reached();
    103     }
    104 
    105     trace_lasi_chip_read(addr, val);
    106 
    107     *data = val;
    108     return ret;
    109 }
    110 
    111 static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr,
    112                                               uint64_t val, unsigned size,
    113                                               MemTxAttrs attrs)
    114 {
    115     LasiState *s = opaque;
    116 
    117     trace_lasi_chip_write(addr, val);
    118 
    119     switch (addr) {
    120     case LASI_IRR:
    121         /* read-only.  */
    122         break;
    123     case LASI_IMR:
    124         s->imr = val;
    125         if (((val & LASI_IRQ_BITS) != val) && (val != 0xffffffff)) {
    126             qemu_log_mask(LOG_GUEST_ERROR,
    127                 "LASI: tried to set invalid %lx IMR value.\n",
    128                 (unsigned long) val);
    129         }
    130         break;
    131     case LASI_IPR:
    132         /* Any write to IPR clears the register. */
    133         s->ipr = 0;
    134         break;
    135     case LASI_ICR:
    136         s->icr = val;
    137         /* if (val & ICR_TOC_BIT) issue_toc(); */
    138         break;
    139     case LASI_IAR:
    140         s->iar = val;
    141         break;
    142 
    143     case LASI_LPT:
    144         /* XXX: reset parallel port */
    145         break;
    146     case LASI_UART:
    147         /* XXX: reset serial port */
    148         break;
    149     case LASI_LAN:
    150         /* XXX: reset LAN card */
    151         break;
    152     case LASI_RTC:
    153         s->rtc_ref = val - time(NULL);
    154         break;
    155 
    156     case LASI_PCR:
    157         if (val == 0x02) { /* immediately power off */
    158             qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
    159         }
    160         break;
    161     case LASI_ERRLOG:
    162         s->errlog = val;
    163         break;
    164     case LASI_VER:
    165         /* read-only.  */
    166         break;
    167     case LASI_IORESET:
    168         break;  /* XXX: TODO: Reset various devices. */
    169     case LASI_AMR:
    170         s->amr = val;
    171         break;
    172 
    173     default:
    174         /* Controlled by lasi_chip_mem_valid above. */
    175         g_assert_not_reached();
    176     }
    177     return MEMTX_OK;
    178 }
    179 
    180 static const MemoryRegionOps lasi_chip_ops = {
    181     .read_with_attrs = lasi_chip_read_with_attrs,
    182     .write_with_attrs = lasi_chip_write_with_attrs,
    183     .endianness = DEVICE_BIG_ENDIAN,
    184     .valid = {
    185         .min_access_size = 1,
    186         .max_access_size = 4,
    187         .accepts = lasi_chip_mem_valid,
    188     },
    189     .impl = {
    190         .min_access_size = 1,
    191         .max_access_size = 4,
    192     },
    193 };
    194 
    195 static const VMStateDescription vmstate_lasi = {
    196     .name = "Lasi",
    197     .version_id = 1,
    198     .minimum_version_id = 1,
    199     .fields = (VMStateField[]) {
    200         VMSTATE_UINT32(irr, LasiState),
    201         VMSTATE_UINT32(imr, LasiState),
    202         VMSTATE_UINT32(ipr, LasiState),
    203         VMSTATE_UINT32(icr, LasiState),
    204         VMSTATE_UINT32(iar, LasiState),
    205         VMSTATE_UINT32(errlog, LasiState),
    206         VMSTATE_UINT32(amr, LasiState),
    207         VMSTATE_END_OF_LIST()
    208     }
    209 };
    210 
    211 
    212 static void lasi_set_irq(void *opaque, int irq, int level)
    213 {
    214     LasiState *s = opaque;
    215     uint32_t bit = 1u << irq;
    216 
    217     if (level) {
    218         s->ipr |= bit;
    219         if (bit & s->imr) {
    220             uint32_t iar = s->iar;
    221             s->irr |= bit;
    222             if ((s->icr & ICR_BUS_ERROR_BIT) == 0) {
    223                 stl_be_phys(&address_space_memory, iar & -32, iar & 31);
    224             }
    225         }
    226     }
    227 }
    228 
    229 static void lasi_reset(DeviceState *dev)
    230 {
    231     LasiState *s = LASI_CHIP(dev);
    232 
    233     s->iar = 0xFFFB0000 + 3; /* CPU_HPA + 3 */
    234 
    235     /* Real time clock (RTC), it's only one 32-bit counter @9000 */
    236     s->rtc = time(NULL);
    237     s->rtc_ref = 0;
    238 }
    239 
    240 static void lasi_init(Object *obj)
    241 {
    242     LasiState *s = LASI_CHIP(obj);
    243     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    244 
    245     memory_region_init_io(&s->this_mem, OBJECT(s), &lasi_chip_ops,
    246                           s, "lasi", 0x100000);
    247 
    248     sysbus_init_mmio(sbd, &s->this_mem);
    249 
    250     qdev_init_gpio_in(DEVICE(obj), lasi_set_irq, LASI_IRQS);
    251 }
    252 
    253 static void lasi_class_init(ObjectClass *klass, void *data)
    254 {
    255     DeviceClass *dc = DEVICE_CLASS(klass);
    256 
    257     dc->reset = lasi_reset;
    258     dc->vmsd = &vmstate_lasi;
    259 }
    260 
    261 static const TypeInfo lasi_pcihost_info = {
    262     .name          = TYPE_LASI_CHIP,
    263     .parent        = TYPE_SYS_BUS_DEVICE,
    264     .instance_init = lasi_init,
    265     .instance_size = sizeof(LasiState),
    266     .class_init    = lasi_class_init,
    267 };
    268 
    269 static void lasi_register_types(void)
    270 {
    271     type_register_static(&lasi_pcihost_info);
    272 }
    273 
    274 type_init(lasi_register_types)