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