diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2022-03-10 13:16:37 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-03-10 13:16:37 +0000 |
commit | 1416688c53be6535be755b44c15fb2eb9defd20f (patch) | |
tree | c30cbaf37fd58e75bd31009cbe44366e82e56a8b | |
parent | 2048c4eba2b40c850e58616c7033f88a2607b89d (diff) | |
parent | a7a2208862bee2bc4fe55adfd947dc4a15ad0216 (diff) | |
download | qemu-1416688c53be6535be755b44c15fb2eb9defd20f.zip qemu-1416688c53be6535be755b44c15fb2eb9defd20f.tar.gz qemu-1416688c53be6535be755b44c15fb2eb9defd20f.tar.bz2 |
Merge remote-tracking branch 'remotes/mcayland/tags/q800-updates-for-7.0-20220309' into staging
q800-updates-for-7.0 queue
# gpg: Signature made Wed 09 Mar 2022 10:57:07 GMT
# gpg: using RSA key CC621AB98E82200D915CC9C45BC2C56FAE0F321F
# gpg: issuer "mark.cave-ayland@ilande.co.uk"
# gpg: Good signature from "Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>" [full]
# Primary key fingerprint: CC62 1AB9 8E82 200D 915C C9C4 5BC2 C56F AE0F 321F
* remotes/mcayland/tags/q800-updates-for-7.0-20220309: (22 commits)
esp: recreate ESPState current_req after migration
esp: include the current PDMA callback in the migration stream
esp: convert ESPState pdma_cb from a function pointer to an integer
esp: introduce esp_pdma_cb() function
esp: introduce esp_set_pdma_cb() function
macfb: set initial value of mode control registers in macfb_common_realize()
macfb: add VMStateDescription fields for display type and VBL timer
macfb: increase number of registers saved in MacfbState
macfb: don't use special irq_state and irq_mask variables in MacfbState
macfb: add VMStateDescription for MacfbNubusState and MacfbSysBusState
macio/pmu.c: remove redundant code
mos6522: implement edge-triggering for CA1/2 and CB1/2 control line IRQs
mac_via: make SCSI_DATA (DRQ) bit live rather than latched
mos6522: record last_irq_levels in mos6522_set_irq()
mos6522: add "info via" HMP command for debugging
mos6522: add register names to register read/write trace events
mos6522: use device_class_set_parent_reset() to propagate reset to parent
mos6522: remove update_irq() and set_sr_int() methods from MOS6522DeviceClass
mos6522: switch over to use qdev gpios for IRQs
mac_via: use IFR bit flag constants for VIA2 IRQs
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hmp-commands-info.hx | 15 | ||||
-rw-r--r-- | hw/display/macfb.c | 57 | ||||
-rw-r--r-- | hw/m68k/q800.c | 9 | ||||
-rw-r--r-- | hw/misc/mac_via.c | 87 | ||||
-rw-r--r-- | hw/misc/macio/cuda.c | 8 | ||||
-rw-r--r-- | hw/misc/macio/pmu.c | 40 | ||||
-rw-r--r-- | hw/misc/mos6522.c | 226 | ||||
-rw-r--r-- | hw/misc/trace-events | 4 | ||||
-rw-r--r-- | hw/scsi/esp.c | 87 | ||||
-rw-r--r-- | include/hw/display/macfb.h | 5 | ||||
-rw-r--r-- | include/hw/misc/mac_via.h | 46 | ||||
-rw-r--r-- | include/hw/misc/macio/pmu.h | 2 | ||||
-rw-r--r-- | include/hw/misc/mos6522.h | 46 | ||||
-rw-r--r-- | include/hw/scsi/esp.h | 11 | ||||
-rw-r--r-- | include/monitor/hmp-target.h | 1 |
15 files changed, 474 insertions, 170 deletions
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index e90f20a..adfa085 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -879,3 +879,18 @@ SRST ``info sgx`` Show intel SGX information. ERST + +#if defined(TARGET_M68K) || defined(TARGET_PPC) + { + .name = "via", + .args_type = "", + .params = "", + .help = "show guest mos6522 VIA devices", + .cmd = hmp_info_via, + }, +#endif + +SRST + ``info via`` + Show guest mos6522 VIA devices. +ERST diff --git a/hw/display/macfb.c b/hw/display/macfb.c index c9b468c..2f8e016 100644 --- a/hw/display/macfb.c +++ b/hw/display/macfb.c @@ -476,7 +476,8 @@ static void macfb_update_display(void *opaque) static void macfb_update_irq(MacfbState *s) { - uint32_t irq_state = s->irq_state & s->irq_mask; + uint32_t irq_state = s->regs[DAFB_INTR_STAT >> 2] & + s->regs[DAFB_INTR_MASK >> 2]; if (irq_state) { qemu_irq_raise(s->irq); @@ -496,7 +497,7 @@ static void macfb_vbl_timer(void *opaque) MacfbState *s = opaque; int64_t next_vbl; - s->irq_state |= DAFB_INTR_VBL; + s->regs[DAFB_INTR_STAT >> 2] |= DAFB_INTR_VBL; macfb_update_irq(s); /* 60 Hz irq */ @@ -530,14 +531,16 @@ static uint64_t macfb_ctrl_read(void *opaque, case DAFB_MODE_VADDR2: case DAFB_MODE_CTRL1: case DAFB_MODE_CTRL2: - val = s->regs[addr >> 2]; - break; case DAFB_INTR_STAT: - val = s->irq_state; + val = s->regs[addr >> 2]; break; case DAFB_MODE_SENSE: val = macfb_sense_read(s); break; + default: + if (addr < MACFB_CTRL_TOPADDR) { + val = s->regs[addr >> 2]; + } } trace_macfb_ctrl_read(addr, val, size); @@ -568,7 +571,7 @@ static void macfb_ctrl_write(void *opaque, macfb_sense_write(s, val); break; case DAFB_INTR_MASK: - s->irq_mask = val; + s->regs[addr >> 2] = val; if (val & DAFB_INTR_VBL) { next_vbl = macfb_next_vbl(); timer_mod(s->vbl_timer, next_vbl); @@ -577,12 +580,12 @@ static void macfb_ctrl_write(void *opaque, } break; case DAFB_INTR_CLEAR: - s->irq_state &= ~DAFB_INTR_VBL; + s->regs[DAFB_INTR_STAT >> 2] &= ~DAFB_INTR_VBL; macfb_update_irq(s); break; case DAFB_RESET: s->palette_current = 0; - s->irq_state &= ~DAFB_INTR_VBL; + s->regs[DAFB_INTR_STAT >> 2] &= ~DAFB_INTR_VBL; macfb_update_irq(s); break; case DAFB_LUT: @@ -593,6 +596,10 @@ static void macfb_ctrl_write(void *opaque, macfb_invalidate_display(s); } break; + default: + if (addr < MACFB_CTRL_TOPADDR) { + s->regs[addr >> 2] = val; + } } trace_macfb_ctrl_write(addr, val, size); @@ -618,9 +625,11 @@ static const VMStateDescription vmstate_macfb = { .minimum_version_id = 1, .post_load = macfb_post_load, .fields = (VMStateField[]) { + VMSTATE_UINT8(type, MacfbState), VMSTATE_UINT8_ARRAY(color_palette, MacfbState, 256 * 3), VMSTATE_UINT32(palette_current, MacfbState), VMSTATE_UINT32_ARRAY(regs, MacfbState, MACFB_NUM_REGS), + VMSTATE_TIMER_PTR(vbl_timer, MacfbState), VMSTATE_END_OF_LIST() } }; @@ -646,6 +655,14 @@ static bool macfb_common_realize(DeviceState *dev, MacfbState *s, Error **errp) return false; } + /* + * Set mode control registers to match the mode found above so that + * macfb_mode_write() does the right thing if no MacOS toolbox ROM + * is present to initialise them + */ + s->regs[DAFB_MODE_CTRL1 >> 2] = s->mode->mode_ctrl1; + s->regs[DAFB_MODE_CTRL2 >> 2] = s->mode->mode_ctrl2; + s->con = graphic_console_init(dev, 0, &macfb_ops, s); surface = qemu_console_surface(s->con); @@ -746,6 +763,16 @@ static Property macfb_sysbus_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static const VMStateDescription vmstate_macfb_sysbus = { + .name = "macfb-sysbus", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(macfb, MacfbSysBusState, 1, vmstate_macfb, MacfbState), + VMSTATE_END_OF_LIST() + } +}; + static Property macfb_nubus_properties[] = { DEFINE_PROP_UINT32("width", MacfbNubusState, macfb.width, 640), DEFINE_PROP_UINT32("height", MacfbNubusState, macfb.height, 480), @@ -755,6 +782,16 @@ static Property macfb_nubus_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static const VMStateDescription vmstate_macfb_nubus = { + .name = "macfb-nubus", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(macfb, MacfbNubusState, 1, vmstate_macfb, MacfbState), + VMSTATE_END_OF_LIST() + } +}; + static void macfb_sysbus_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -762,7 +799,7 @@ static void macfb_sysbus_class_init(ObjectClass *klass, void *data) dc->realize = macfb_sysbus_realize; dc->desc = "SysBus Macintosh framebuffer"; dc->reset = macfb_sysbus_reset; - dc->vmsd = &vmstate_macfb; + dc->vmsd = &vmstate_macfb_sysbus; device_class_set_props(dc, macfb_sysbus_properties); } @@ -777,7 +814,7 @@ static void macfb_nubus_class_init(ObjectClass *klass, void *data) &ndc->parent_unrealize); dc->desc = "Nubus Macintosh framebuffer"; dc->reset = macfb_nubus_reset; - dc->vmsd = &vmstate_macfb; + dc->vmsd = &vmstate_macfb_nubus; set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); device_class_set_props(dc, macfb_nubus_properties); } diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index 55dfe50..66ca5c0 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -533,10 +533,11 @@ static void q800_init(MachineState *machine) sysbus = SYS_BUS_DEVICE(dev); sysbus_realize_and_unref(sysbus, &error_fatal); - sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(via2_dev, - VIA2_IRQ_SCSI_BIT)); - sysbus_connect_irq(sysbus, 1, qdev_get_gpio_in(via2_dev, - VIA2_IRQ_SCSI_DATA_BIT)); + /* SCSI and SCSI data IRQs are negative edge triggered */ + sysbus_connect_irq(sysbus, 0, qemu_irq_invert(qdev_get_gpio_in(via2_dev, + VIA2_IRQ_SCSI_BIT))); + sysbus_connect_irq(sysbus, 1, qemu_irq_invert(qdev_get_gpio_in(via2_dev, + VIA2_IRQ_SCSI_DATA_BIT))); sysbus_mmio_map(sysbus, 0, ESP_BASE); sysbus_mmio_map(sysbus, 1, ESP_PDMA); diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c index 71b74c3..525e38c 100644 --- a/hw/misc/mac_via.c +++ b/hw/misc/mac_via.c @@ -325,10 +325,11 @@ static void via1_sixty_hz(void *opaque) { MOS6522Q800VIA1State *v1s = opaque; MOS6522State *s = MOS6522(v1s); - MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); + qemu_irq irq = qdev_get_gpio_in(DEVICE(s), VIA1_IRQ_60HZ_BIT); - s->ifr |= VIA1_IRQ_60HZ; - mdc->update_irq(s); + /* Negative edge trigger */ + qemu_irq_lower(irq); + qemu_irq_raise(irq); via1_sixty_hz_update(v1s); } @@ -337,44 +338,15 @@ static void via1_one_second(void *opaque) { MOS6522Q800VIA1State *v1s = opaque; MOS6522State *s = MOS6522(v1s); - MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); + qemu_irq irq = qdev_get_gpio_in(DEVICE(s), VIA1_IRQ_ONE_SECOND_BIT); - s->ifr |= VIA1_IRQ_ONE_SECOND; - mdc->update_irq(s); + /* Negative edge trigger */ + qemu_irq_lower(irq); + qemu_irq_raise(irq); via1_one_second_update(v1s); } -static void via1_irq_request(void *opaque, int irq, int level) -{ - MOS6522Q800VIA1State *v1s = opaque; - MOS6522State *s = MOS6522(v1s); - MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); - - if (level) { - s->ifr |= 1 << irq; - } else { - s->ifr &= ~(1 << irq); - } - - mdc->update_irq(s); -} - -static void via2_irq_request(void *opaque, int irq, int level) -{ - MOS6522Q800VIA2State *v2s = opaque; - MOS6522State *s = MOS6522(v2s); - MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); - - if (level) { - s->ifr |= 1 << irq; - } else { - s->ifr &= ~(1 << irq); - } - - mdc->update_irq(s); -} - static void pram_update(MOS6522Q800VIA1State *v1s) { @@ -938,9 +910,26 @@ static uint64_t mos6522_q800_via2_read(void *opaque, hwaddr addr, unsigned size) { MOS6522Q800VIA2State *s = MOS6522_Q800_VIA2(opaque); MOS6522State *ms = MOS6522(s); + uint64_t val; addr = (addr >> 9) & 0xf; - return mos6522_read(ms, addr, size); + val = mos6522_read(ms, addr, size); + + switch (addr) { + case VIA_REG_IFR: + /* + * On a Q800 an emulated VIA2 is integrated into the onboard logic. The + * expectation of most OSs is that the DRQ bit is live, rather than + * latched as it would be on a real VIA so do the same here. + * + * Note: DRQ is negative edge triggered + */ + val &= ~VIA2_IRQ_SCSI_DATA; + val |= (~ms->last_irq_levels & VIA2_IRQ_SCSI_DATA); + break; + } + + return val; } static void mos6522_q800_via2_write(void *opaque, hwaddr addr, uint64_t val, @@ -1061,8 +1050,6 @@ static void mos6522_q800_via1_init(Object *obj) qbus_init((BusState *)&v1s->adb_bus, sizeof(v1s->adb_bus), TYPE_ADB_BUS, DEVICE(v1s), "adb.0"); - qdev_init_gpio_in(DEVICE(obj), via1_irq_request, VIA1_IRQ_NB); - /* A/UX mode */ qdev_init_gpio_out(DEVICE(obj), &v1s->auxmode_irq, 1); } @@ -1110,9 +1097,11 @@ static Property mos6522_q800_via1_properties[] = { static void mos6522_q800_via1_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + MOS6522DeviceClass *mdc = MOS6522_CLASS(oc); dc->realize = mos6522_q800_via1_realize; - dc->reset = mos6522_q800_via1_reset; + device_class_set_parent_reset(dc, mos6522_q800_via1_reset, + &mdc->parent_reset); dc->vmsd = &vmstate_q800_via1; device_class_set_props(dc, mos6522_q800_via1_properties); } @@ -1150,22 +1139,21 @@ static void mos6522_q800_via2_reset(DeviceState *dev) ms->a = 0x7f; } -static void via2_nubus_irq_request(void *opaque, int irq, int level) +static void via2_nubus_irq_request(void *opaque, int n, int level) { MOS6522Q800VIA2State *v2s = opaque; MOS6522State *s = MOS6522(v2s); - MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); + qemu_irq irq = qdev_get_gpio_in(DEVICE(s), VIA2_IRQ_NUBUS_BIT); if (level) { /* Port A nubus IRQ inputs are active LOW */ - s->a &= ~(1 << irq); - s->ifr |= 1 << VIA2_IRQ_NUBUS_BIT; + s->a &= ~(1 << n); } else { - s->a |= (1 << irq); - s->ifr &= ~(1 << VIA2_IRQ_NUBUS_BIT); + s->a |= (1 << n); } - mdc->update_irq(s); + /* Negative edge trigger */ + qemu_set_irq(irq, !level); } static void mos6522_q800_via2_init(Object *obj) @@ -1177,8 +1165,6 @@ static void mos6522_q800_via2_init(Object *obj) "via2", VIA_SIZE); sysbus_init_mmio(sbd, &v2s->via_mem); - qdev_init_gpio_in(DEVICE(obj), via2_irq_request, VIA2_IRQ_NB); - qdev_init_gpio_in_named(DEVICE(obj), via2_nubus_irq_request, "nubus-irq", VIA2_NUBUS_IRQ_NB); } @@ -1199,7 +1185,8 @@ static void mos6522_q800_via2_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); MOS6522DeviceClass *mdc = MOS6522_CLASS(oc); - dc->reset = mos6522_q800_via2_reset; + device_class_set_parent_reset(dc, mos6522_q800_via2_reset, + &mdc->parent_reset); dc->vmsd = &vmstate_q800_via2; mdc->portB_write = mos6522_q800_via2_portB_write; } diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index 233daf1..1498113 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -24,6 +24,7 @@ */ #include "qemu/osdep.h" +#include "hw/irq.h" #include "hw/ppc/mac.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" @@ -96,9 +97,9 @@ static void cuda_set_sr_int(void *opaque) CUDAState *s = opaque; MOS6522CUDAState *mcs = &s->mos6522_cuda; MOS6522State *ms = MOS6522(mcs); - MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms); + qemu_irq irq = qdev_get_gpio_in(DEVICE(ms), SR_INT_BIT); - mdc->set_sr_int(ms); + qemu_set_irq(irq, 1); } static void cuda_delay_set_sr_int(CUDAState *s) @@ -605,7 +606,8 @@ static void mos6522_cuda_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); MOS6522DeviceClass *mdc = MOS6522_CLASS(oc); - dc->reset = mos6522_cuda_reset; + device_class_set_parent_reset(dc, mos6522_cuda_reset, + &mdc->parent_reset); mdc->portB_write = mos6522_cuda_portB_write; mdc->get_timer1_counter_value = cuda_get_counter_value; mdc->get_timer2_counter_value = cuda_get_counter_value; diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c index 76c608e..336502a 100644 --- a/hw/misc/macio/pmu.c +++ b/hw/misc/macio/pmu.c @@ -57,27 +57,14 @@ #define VIA_TIMER_FREQ (4700000 / 6) -static void via_update_irq(PMUState *s) -{ - MOS6522PMUState *mps = MOS6522_PMU(&s->mos6522_pmu); - MOS6522State *ms = MOS6522(mps); - - bool new_state = !!(ms->ifr & ms->ier & (SR_INT | T1_INT | T2_INT)); - - if (new_state != s->via_irq_state) { - s->via_irq_state = new_state; - qemu_set_irq(s->via_irq, new_state); - } -} - static void via_set_sr_int(void *opaque) { PMUState *s = opaque; MOS6522PMUState *mps = MOS6522_PMU(&s->mos6522_pmu); MOS6522State *ms = MOS6522(mps); - MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms); + qemu_irq irq = qdev_get_gpio_in(DEVICE(ms), SR_INT_BIT); - mdc->set_sr_int(ms); + qemu_set_irq(irq, 1); } static void pmu_update_extirq(PMUState *s) @@ -808,28 +795,9 @@ static void mos6522_pmu_portB_write(MOS6522State *s) MOS6522PMUState *mps = container_of(s, MOS6522PMUState, parent_obj); PMUState *ps = container_of(mps, PMUState, mos6522_pmu); - if ((s->pcr & 0xe0) == 0x20 || (s->pcr & 0xe0) == 0x60) { - s->ifr &= ~CB2_INT; - } - s->ifr &= ~CB1_INT; - - via_update_irq(ps); pmu_update(ps); } -static void mos6522_pmu_portA_write(MOS6522State *s) -{ - MOS6522PMUState *mps = container_of(s, MOS6522PMUState, parent_obj); - PMUState *ps = container_of(mps, PMUState, mos6522_pmu); - - if ((s->pcr & 0x0e) == 0x02 || (s->pcr & 0x0e) == 0x06) { - s->ifr &= ~CA2_INT; - } - s->ifr &= ~CA1_INT; - - via_update_irq(ps); -} - static void mos6522_pmu_reset(DeviceState *dev) { MOS6522State *ms = MOS6522(dev); @@ -850,9 +818,9 @@ static void mos6522_pmu_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); MOS6522DeviceClass *mdc = MOS6522_CLASS(oc); - dc->reset = mos6522_pmu_reset; + device_class_set_parent_reset(dc, mos6522_pmu_reset, + &mdc->parent_reset); mdc->portB_write = mos6522_pmu_portB_write; - mdc->portA_write = mos6522_pmu_portA_write; } static const TypeInfo mos6522_pmu_type_info = { diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c index 1c57332..f9e6463 100644 --- a/hw/misc/mos6522.c +++ b/hw/misc/mos6522.c @@ -30,12 +30,21 @@ #include "hw/misc/mos6522.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "monitor/monitor.h" +#include "monitor/hmp.h" +#include "qapi/type-helpers.h" #include "qemu/timer.h" #include "qemu/cutils.h" #include "qemu/log.h" #include "qemu/module.h" #include "trace.h" + +static const char *mos6522_reg_names[MOS6522_NUM_REGS] = { + "ORB", "ORA", "DDRB", "DDRA", "T1CL", "T1CH", "T1LL", "T1LH", + "T2CL", "T2CH", "SR", "ACR", "PCR", "IFR", "IER", "ANH" +}; + /* XXX: implement all timer modes */ static void mos6522_timer1_update(MOS6522State *s, MOS6522Timer *ti, @@ -52,6 +61,73 @@ static void mos6522_update_irq(MOS6522State *s) } } +static void mos6522_set_irq(void *opaque, int n, int level) +{ + MOS6522State *s = MOS6522(opaque); + int last_level = !!(s->last_irq_levels & (1 << n)); + uint8_t last_ifr = s->ifr; + bool positive_edge = true; + int ctrl; + + /* + * SR_INT is managed by mos6522 instances and cleared upon SR + * read. It is only the external CA1/2 and CB1/2 lines that + * are edge-triggered and latched in IFR + */ + if (n != SR_INT_BIT && level == last_level) { + return; + } + + /* Detect negative edge trigger */ + if (last_level == 1 && level == 0) { + positive_edge = false; + } + + switch (n) { + case CA2_INT_BIT: + ctrl = (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT; + if ((positive_edge && (ctrl & C2_POS)) || + (!positive_edge && !(ctrl & C2_POS))) { + s->ifr |= 1 << n; + } + break; + case CA1_INT_BIT: + ctrl = (s->pcr & CA1_CTRL_MASK) >> CA1_CTRL_SHIFT; + if ((positive_edge && (ctrl & C1_POS)) || + (!positive_edge && !(ctrl & C1_POS))) { + s->ifr |= 1 << n; + } + break; + case SR_INT_BIT: + s->ifr |= 1 << n; + break; + case CB2_INT_BIT: + ctrl = (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT; + if ((positive_edge && (ctrl & C2_POS)) || + (!positive_edge && !(ctrl & C2_POS))) { + s->ifr |= 1 << n; + } + break; + case CB1_INT_BIT: + ctrl = (s->pcr & CB1_CTRL_MASK) >> CB1_CTRL_SHIFT; + if ((positive_edge && (ctrl & C1_POS)) || + (!positive_edge && !(ctrl & C1_POS))) { + s->ifr |= 1 << n; + } + break; + } + + if (s->ifr != last_ifr) { + mos6522_update_irq(s); + } + + if (level) { + s->last_irq_levels |= 1 << n; + } else { + s->last_irq_levels &= ~(1 << n); + } +} + static uint64_t get_counter_value(MOS6522State *s, MOS6522Timer *ti) { MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); @@ -195,13 +271,6 @@ static void mos6522_timer2(void *opaque) mos6522_update_irq(s); } -static void mos6522_set_sr_int(MOS6522State *s) -{ - trace_mos6522_set_sr_int(); - s->ifr |= SR_INT; - mos6522_update_irq(s); -} - static uint64_t mos6522_get_counter_value(MOS6522State *s, MOS6522Timer *ti) { return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ti->load_time, @@ -229,6 +298,7 @@ uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size) { MOS6522State *s = opaque; uint32_t val; + int ctrl; int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); if (now >= s->timers[0].next_irq_time) { @@ -242,12 +312,24 @@ uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size) switch (addr) { case VIA_REG_B: val = s->b; + ctrl = (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT; + if (!(ctrl & C2_IND)) { + s->ifr &= ~CB2_INT; + } + s->ifr &= ~CB1_INT; + mos6522_update_irq(s); break; case VIA_REG_A: qemu_log_mask(LOG_UNIMP, "Read access to register A with handshake"); /* fall through */ case VIA_REG_ANH: val = s->a; + ctrl = (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT; + if (!(ctrl & C2_IND)) { + s->ifr &= ~CA2_INT; + } + s->ifr &= ~CA1_INT; + mos6522_update_irq(s); break; case VIA_REG_DIRB: val = s->dirb; @@ -304,7 +386,7 @@ uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size) } if (addr != VIA_REG_IFR || val != 0) { - trace_mos6522_read(addr, val); + trace_mos6522_read(addr, mos6522_reg_names[addr], val); } return val; @@ -314,13 +396,20 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { MOS6522State *s = opaque; MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s); + int ctrl; - trace_mos6522_write(addr, val); + trace_mos6522_write(addr, mos6522_reg_names[addr], val); switch (addr) { case VIA_REG_B: s->b = (s->b & ~s->dirb) | (val & s->dirb); mdc->portB_write(s); + ctrl = (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT; + if (!(ctrl & C2_IND)) { + s->ifr &= ~CB2_INT; + } + s->ifr &= ~CB1_INT; + mos6522_update_irq(s); break; case VIA_REG_A: qemu_log_mask(LOG_UNIMP, "Write access to register A with handshake"); @@ -328,6 +417,12 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) case VIA_REG_ANH: s->a = (s->a & ~s->dira) | (val & s->dira); mdc->portA_write(s); + ctrl = (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT; + if (!(ctrl & C2_IND)) { + s->ifr &= ~CA2_INT; + } + s->ifr &= ~CA1_INT; + mos6522_update_irq(s); break; case VIA_REG_DIRB: s->dirb = val; @@ -403,6 +498,106 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) } } +static int qmp_x_query_via_foreach(Object *obj, void *opaque) +{ + GString *buf = opaque; + + if (object_dynamic_cast(obj, TYPE_MOS6522)) { + MOS6522State *s = MOS6522(obj); + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint16_t t1counter = get_counter(s, &s->timers[0]); + uint16_t t2counter = get_counter(s, &s->timers[1]); + + g_string_append_printf(buf, "%s:\n", object_get_typename(obj)); + + g_string_append_printf(buf, " Registers:\n"); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[0], s->b); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[1], s->a); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[2], s->dirb); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[3], s->dira); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[4], t1counter & 0xff); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[5], t1counter >> 8); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[6], + s->timers[0].latch & 0xff); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[7], + s->timers[0].latch >> 8); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[8], t2counter & 0xff); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[9], t2counter >> 8); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[10], s->sr); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[11], s->acr); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[12], s->pcr); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[13], s->ifr); + g_string_append_printf(buf, " %-*s: 0x%x\n", 4, + mos6522_reg_names[14], s->ier); + + g_string_append_printf(buf, " Timers:\n"); + g_string_append_printf(buf, " Using current time now(ns)=%"PRId64 + "\n", now); + g_string_append_printf(buf, " T1 freq(hz)=%"PRId64 + " mode=%s" + " counter=0x%x" + " latch=0x%x\n" + " load_time(ns)=%"PRId64 + " next_irq_time(ns)=%"PRId64 "\n", + s->timers[0].frequency, + ((s->acr & T1MODE) == T1MODE_CONT) ? "continuous" + : "one-shot", + t1counter, + s->timers[0].latch, + s->timers[0].load_time, + get_next_irq_time(s, &s->timers[0], now)); + g_string_append_printf(buf, " T2 freq(hz)=%"PRId64 + " mode=%s" + " counter=0x%x" + " latch=0x%x\n" + " load_time(ns)=%"PRId64 + " next_irq_time(ns)=%"PRId64 "\n", + s->timers[1].frequency, + "one-shot", + t2counter, + s->timers[1].latch, + s->timers[1].load_time, + get_next_irq_time(s, &s->timers[1], now)); + } + + return 0; +} + +static HumanReadableText *qmp_x_query_via(Error **errp) +{ + g_autoptr(GString) buf = g_string_new(""); + + object_child_foreach_recursive(object_get_root(), + qmp_x_query_via_foreach, buf); + + return human_readable_text_from_str(buf); +} + +void hmp_info_via(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + g_autoptr(HumanReadableText) info = qmp_x_query_via(&err); + + if (hmp_handle_error(mon, err)) { + return; + } + monitor_printf(mon, "%s", info->human_readable_text); +} + static const MemoryRegionOps mos6522_ops = { .read = mos6522_read, .write = mos6522_write, @@ -429,8 +624,8 @@ static const VMStateDescription vmstate_mos6522_timer = { const VMStateDescription vmstate_mos6522 = { .name = "mos6522", - .version_id = 0, - .minimum_version_id = 0, + .version_id = 1, + .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_UINT8(a, MOS6522State), VMSTATE_UINT8(b, MOS6522State), @@ -441,6 +636,7 @@ const VMStateDescription vmstate_mos6522 = { VMSTATE_UINT8(pcr, MOS6522State), VMSTATE_UINT8(ifr, MOS6522State), VMSTATE_UINT8(ier, MOS6522State), + VMSTATE_UINT8(last_irq_levels, MOS6522State), VMSTATE_STRUCT_ARRAY(timers, MOS6522State, 2, 0, vmstate_mos6522_timer, MOS6522Timer), VMSTATE_END_OF_LIST() @@ -478,7 +674,8 @@ static void mos6522_init(Object *obj) MOS6522State *s = MOS6522(obj); int i; - memory_region_init_io(&s->mem, obj, &mos6522_ops, s, "mos6522", 0x10); + memory_region_init_io(&s->mem, obj, &mos6522_ops, s, "mos6522", + MOS6522_NUM_REGS); sysbus_init_mmio(sbd, &s->mem); sysbus_init_irq(sbd, &s->irq); @@ -488,6 +685,8 @@ static void mos6522_init(Object *obj) s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, mos6522_timer1, s); s->timers[1].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, mos6522_timer2, s); + + qdev_init_gpio_in(DEVICE(obj), mos6522_set_irq, VIA_NUM_INTS); } static void mos6522_finalize(Object *obj) @@ -511,11 +710,8 @@ static void mos6522_class_init(ObjectClass *oc, void *data) dc->reset = mos6522_reset; dc->vmsd = &vmstate_mos6522; device_class_set_props(dc, mos6522_properties); - mdc->parent_reset = dc->reset; - mdc->set_sr_int = mos6522_set_sr_int; mdc->portB_write = mos6522_portB_write; mdc->portA_write = mos6522_portA_write; - mdc->update_irq = mos6522_update_irq; mdc->get_timer1_counter_value = mos6522_get_counter_value; mdc->get_timer2_counter_value = mos6522_get_counter_value; mdc->get_timer1_load_time = mos6522_get_load_time; diff --git a/hw/misc/trace-events b/hw/misc/trace-events index fb5a389..bd52cfc 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -95,8 +95,8 @@ imx7_gpr_write(uint64_t offset, uint64_t value) "addr 0x%08" PRIx64 "value 0x%08 mos6522_set_counter(int index, unsigned int val) "T%d.counter=%d" mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta) "latch=%d counter=0x%"PRId64 " delta_next=0x%"PRId64 mos6522_set_sr_int(void) "set sr_int" -mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64 -mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x" +mos6522_write(uint64_t addr, const char *name, uint64_t val) "reg=0x%"PRIx64 " [%s] val=0x%"PRIx64 +mos6522_read(uint64_t addr, const char *name, unsigned val) "reg=0x%"PRIx64 " [%s] val=0x%x" # npcm7xx_clk.c npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 58d0edb..2d3c649 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -195,6 +195,11 @@ static void esp_pdma_write(ESPState *s, uint8_t val) esp_set_tc(s, dmalen); } +static void esp_set_pdma_cb(ESPState *s, enum pdma_cb cb) +{ + s->pdma_cb = cb; +} + static int esp_select(ESPState *s) { int target; @@ -356,7 +361,7 @@ static void handle_satn(ESPState *s) s->dma_cb = handle_satn; return; } - s->pdma_cb = satn_pdma_cb; + esp_set_pdma_cb(s, SATN_PDMA_CB); cmdlen = get_cmd(s, ESP_CMDFIFO_SZ); if (cmdlen > 0) { s->cmdfifo_cdb_offset = 1; @@ -387,7 +392,7 @@ static void handle_s_without_atn(ESPState *s) s->dma_cb = handle_s_without_atn; return; } - s->pdma_cb = s_without_satn_pdma_cb; + esp_set_pdma_cb(s, S_WITHOUT_SATN_PDMA_CB); cmdlen = get_cmd(s, ESP_CMDFIFO_SZ); if (cmdlen > 0) { s->cmdfifo_cdb_offset = 0; @@ -422,7 +427,7 @@ static void handle_satn_stop(ESPState *s) s->dma_cb = handle_satn_stop; return; } - s->pdma_cb = satn_stop_pdma_cb; + esp_set_pdma_cb(s, SATN_STOP_PDMA_CB); cmdlen = get_cmd(s, 1); if (cmdlen > 0) { trace_esp_handle_satn_stop(fifo8_num_used(&s->cmdfifo)); @@ -464,7 +469,7 @@ static void write_response(ESPState *s) s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; s->rregs[ESP_RSEQ] = SEQ_CD; } else { - s->pdma_cb = write_response_pdma_cb; + esp_set_pdma_cb(s, WRITE_RESPONSE_PDMA_CB); esp_raise_drq(s); return; } @@ -604,7 +609,7 @@ static void esp_do_dma(ESPState *s) s->dma_memory_read(s->dma_opaque, buf, len); fifo8_push_all(&s->cmdfifo, buf, len); } else { - s->pdma_cb = do_dma_pdma_cb; + esp_set_pdma_cb(s, DO_DMA_PDMA_CB); esp_raise_drq(s); return; } @@ -646,7 +651,7 @@ static void esp_do_dma(ESPState *s) if (s->dma_memory_read) { s->dma_memory_read(s->dma_opaque, s->async_buf, len); } else { - s->pdma_cb = do_dma_pdma_cb; + esp_set_pdma_cb(s, DO_DMA_PDMA_CB); esp_raise_drq(s); return; } @@ -678,7 +683,7 @@ static void esp_do_dma(ESPState *s) } esp_set_tc(s, esp_get_tc(s) - len); - s->pdma_cb = do_dma_pdma_cb; + esp_set_pdma_cb(s, DO_DMA_PDMA_CB); esp_raise_drq(s); /* Indicate transfer to FIFO is complete */ @@ -777,6 +782,29 @@ static void esp_do_nodma(ESPState *s) esp_raise_irq(s); } +static void esp_pdma_cb(ESPState *s) +{ + switch (s->pdma_cb) { + case SATN_PDMA_CB: + satn_pdma_cb(s); + break; + case S_WITHOUT_SATN_PDMA_CB: + s_without_satn_pdma_cb(s); + break; + case SATN_STOP_PDMA_CB: + satn_stop_pdma_cb(s); + break; + case WRITE_RESPONSE_PDMA_CB: + write_response_pdma_cb(s); + break; + case DO_DMA_PDMA_CB: + do_dma_pdma_cb(s); + break; + default: + g_assert_not_reached(); + } +} + void esp_command_complete(SCSIRequest *req, size_t resid) { ESPState *s = req->hba_private; @@ -1181,6 +1209,33 @@ static int esp_post_load(void *opaque, int version_id) return 0; } +/* + * PDMA (or pseudo-DMA) is only used on the Macintosh and requires the + * guest CPU to perform the transfers between the SCSI bus and memory + * itself. This is indicated by the dma_memory_read and dma_memory_write + * functions being NULL (in contrast to the ESP PCI device) whilst + * dma_enabled is still set. + */ + +static bool esp_pdma_needed(void *opaque) +{ + ESPState *s = ESP(opaque); + + return s->dma_memory_read == NULL && s->dma_memory_write == NULL && + s->dma_enabled; +} + +static const VMStateDescription vmstate_esp_pdma = { + .name = "esp/pdma", + .version_id = 0, + .minimum_version_id = 0, + .needed = esp_pdma_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT8(pdma_cb, ESPState), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_esp = { .name = "esp", .version_id = 6, @@ -1215,6 +1270,10 @@ const VMStateDescription vmstate_esp = { VMSTATE_UINT8_TEST(lun, ESPState, esp_is_version_6), VMSTATE_END_OF_LIST() }, + .subsections = (const VMStateDescription * []) { + &vmstate_esp_pdma, + NULL + } }; static void sysbus_esp_mem_write(void *opaque, hwaddr addr, @@ -1263,7 +1322,7 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr addr, esp_pdma_write(s, val); break; } - s->pdma_cb(s); + esp_pdma_cb(s); } static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr addr, @@ -1285,11 +1344,20 @@ static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr addr, break; } if (fifo8_num_used(&s->fifo) < 2) { - s->pdma_cb(s); + esp_pdma_cb(s); } return val; } +static void *esp_load_request(QEMUFile *f, SCSIRequest *req) +{ + ESPState *s = container_of(req->bus, ESPState, bus); + + scsi_req_ref(req); + s->current_req = req; + return s; +} + static const MemoryRegionOps sysbus_esp_pdma_ops = { .read = sysbus_esp_pdma_read, .write = sysbus_esp_pdma_write, @@ -1305,6 +1373,7 @@ static const struct SCSIBusInfo esp_scsi_info = { .max_target = ESP_MAX_DEVS, .max_lun = 7, + .load_request = esp_load_request, .transfer_data = esp_transfer_data, .complete = esp_command_complete, .cancel = esp_request_cancelled diff --git a/include/hw/display/macfb.h b/include/hw/display/macfb.h index e52775a..55a50d3 100644 --- a/include/hw/display/macfb.h +++ b/include/hw/display/macfb.h @@ -48,7 +48,8 @@ typedef struct MacFbMode { uint32_t offset; } MacFbMode; -#define MACFB_NUM_REGS 8 +#define MACFB_CTRL_TOPADDR 0x200 +#define MACFB_NUM_REGS (MACFB_CTRL_TOPADDR / sizeof(uint32_t)) typedef struct MacfbState { MemoryRegion mem_vram; @@ -66,8 +67,6 @@ typedef struct MacfbState { uint32_t regs[MACFB_NUM_REGS]; MacFbMode *mode; - uint32_t irq_state; - uint32_t irq_mask; QEMUTimer *vbl_timer; qemu_irq irq; } MacfbState; diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h index b445565..5fe7a7f 100644 --- a/include/hw/misc/mac_via.h +++ b/include/hw/misc/mac_via.h @@ -18,19 +18,17 @@ #define VIA_SIZE 0x2000 /* VIA 1 */ -#define VIA1_IRQ_ONE_SECOND_BIT 0 -#define VIA1_IRQ_60HZ_BIT 1 -#define VIA1_IRQ_ADB_READY_BIT 2 -#define VIA1_IRQ_ADB_DATA_BIT 3 -#define VIA1_IRQ_ADB_CLOCK_BIT 4 +#define VIA1_IRQ_ONE_SECOND_BIT CA2_INT_BIT +#define VIA1_IRQ_60HZ_BIT CA1_INT_BIT +#define VIA1_IRQ_ADB_READY_BIT SR_INT_BIT +#define VIA1_IRQ_ADB_DATA_BIT CB2_INT_BIT +#define VIA1_IRQ_ADB_CLOCK_BIT CB1_INT_BIT -#define VIA1_IRQ_NB 8 - -#define VIA1_IRQ_ONE_SECOND (1 << VIA1_IRQ_ONE_SECOND_BIT) -#define VIA1_IRQ_60HZ (1 << VIA1_IRQ_60HZ_BIT) -#define VIA1_IRQ_ADB_READY (1 << VIA1_IRQ_ADB_READY_BIT) -#define VIA1_IRQ_ADB_DATA (1 << VIA1_IRQ_ADB_DATA_BIT) -#define VIA1_IRQ_ADB_CLOCK (1 << VIA1_IRQ_ADB_CLOCK_BIT) +#define VIA1_IRQ_ONE_SECOND BIT(VIA1_IRQ_ONE_SECOND_BIT) +#define VIA1_IRQ_60HZ BIT(VIA1_IRQ_60HZ_BIT) +#define VIA1_IRQ_ADB_READY BIT(VIA1_IRQ_ADB_READY_BIT) +#define VIA1_IRQ_ADB_DATA BIT(VIA1_IRQ_ADB_DATA_BIT) +#define VIA1_IRQ_ADB_CLOCK BIT(VIA1_IRQ_ADB_CLOCK_BIT) #define TYPE_MOS6522_Q800_VIA1 "mos6522-q800-via1" @@ -42,7 +40,6 @@ struct MOS6522Q800VIA1State { MemoryRegion via_mem; - qemu_irq irqs[VIA1_IRQ_NB]; qemu_irq auxmode_irq; uint8_t last_b; @@ -80,19 +77,16 @@ struct MOS6522Q800VIA1State { /* VIA 2 */ -#define VIA2_IRQ_SCSI_DATA_BIT 0 -#define VIA2_IRQ_NUBUS_BIT 1 -#define VIA2_IRQ_UNUSED_BIT 2 -#define VIA2_IRQ_SCSI_BIT 3 -#define VIA2_IRQ_ASC_BIT 4 - -#define VIA2_IRQ_NB 8 - -#define VIA2_IRQ_SCSI_DATA (1 << VIA2_IRQ_SCSI_DATA_BIT) -#define VIA2_IRQ_NUBUS (1 << VIA2_IRQ_NUBUS_BIT) -#define VIA2_IRQ_UNUSED (1 << VIA2_IRQ_SCSI_BIT) -#define VIA2_IRQ_SCSI (1 << VIA2_IRQ_UNUSED_BIT) -#define VIA2_IRQ_ASC (1 << VIA2_IRQ_ASC_BIT) +#define VIA2_IRQ_SCSI_DATA_BIT CA2_INT_BIT +#define VIA2_IRQ_NUBUS_BIT CA1_INT_BIT +#define VIA2_IRQ_SCSI_BIT CB2_INT_BIT +#define VIA2_IRQ_ASC_BIT CB1_INT_BIT + +#define VIA2_IRQ_SCSI_DATA BIT(VIA2_IRQ_SCSI_DATA_BIT) +#define VIA2_IRQ_NUBUS BIT(VIA2_IRQ_NUBUS_BIT) +#define VIA2_IRQ_UNUSED BIT(VIA2_IRQ_SCSI_BIT) +#define VIA2_IRQ_SCSI BIT(VIA2_IRQ_UNUSED_BIT) +#define VIA2_IRQ_ASC BIT(VIA2_IRQ_ASC_BIT) #define VIA2_NUBUS_IRQ_NB 7 diff --git a/include/hw/misc/macio/pmu.h b/include/hw/misc/macio/pmu.h index 78237d9..00fcdd2 100644 --- a/include/hw/misc/macio/pmu.h +++ b/include/hw/misc/macio/pmu.h @@ -193,8 +193,6 @@ struct PMUState { MemoryRegion mem; uint64_t frequency; - qemu_irq via_irq; - bool via_irq_state; /* PMU state */ MOS6522PMUState mos6522_pmu; diff --git a/include/hw/misc/mos6522.h b/include/hw/misc/mos6522.h index fc95d22..0bc22a8 100644 --- a/include/hw/misc/mos6522.h +++ b/include/hw/misc/mos6522.h @@ -32,6 +32,8 @@ #include "hw/input/adb.h" #include "qom/object.h" +#define MOS6522_NUM_REGS 16 + /* Bits in ACR */ #define SR_CTRL 0x1c /* Shift register control bits */ #define SR_EXT 0x0c /* Shift on external clock */ @@ -41,18 +43,43 @@ #define IER_SET 0x80 /* set bits in IER */ #define IER_CLR 0 /* clear bits in IER */ -#define CA2_INT 0x01 -#define CA1_INT 0x02 -#define SR_INT 0x04 /* Shift register full/empty */ -#define CB2_INT 0x08 -#define CB1_INT 0x10 -#define T2_INT 0x20 /* Timer 2 interrupt */ -#define T1_INT 0x40 /* Timer 1 interrupt */ +#define CA2_INT_BIT 0 +#define CA1_INT_BIT 1 +#define SR_INT_BIT 2 /* Shift register full/empty */ +#define CB2_INT_BIT 3 +#define CB1_INT_BIT 4 +#define T2_INT_BIT 5 /* Timer 2 interrupt */ +#define T1_INT_BIT 6 /* Timer 1 interrupt */ + +#define CA2_INT BIT(CA2_INT_BIT) +#define CA1_INT BIT(CA1_INT_BIT) +#define SR_INT BIT(SR_INT_BIT) +#define CB2_INT BIT(CB2_INT_BIT) +#define CB1_INT BIT(CB1_INT_BIT) +#define T2_INT BIT(T2_INT_BIT) +#define T1_INT BIT(T1_INT_BIT) + +#define VIA_NUM_INTS 5 /* Bits in ACR */ #define T1MODE 0xc0 /* Timer 1 mode */ #define T1MODE_CONT 0x40 /* continuous interrupts */ +/* Bits in PCR */ +#define CB2_CTRL_MASK 0xe0 +#define CB2_CTRL_SHIFT 5 +#define CB1_CTRL_MASK 0x10 +#define CB1_CTRL_SHIFT 4 +#define CA2_CTRL_MASK 0x0e +#define CA2_CTRL_SHIFT 1 +#define CA1_CTRL_MASK 0x1 +#define CA1_CTRL_SHIFT 0 + +#define C2_POS 0x2 +#define C2_IND 0x1 + +#define C1_POS 0x1 + /* VIA registers */ #define VIA_REG_B 0x00 #define VIA_REG_A 0x01 @@ -121,6 +148,7 @@ struct MOS6522State { uint64_t frequency; qemu_irq irq; + uint8_t last_irq_levels; }; #define TYPE_MOS6522 "mos6522" @@ -130,10 +158,8 @@ struct MOS6522DeviceClass { DeviceClass parent_class; DeviceReset parent_reset; - void (*set_sr_int)(MOS6522State *dev); void (*portB_write)(MOS6522State *dev); void (*portA_write)(MOS6522State *dev); - void (*update_irq)(MOS6522State *dev); /* These are used to influence the CUDA MacOS timebase calibration */ uint64_t (*get_timer1_counter_value)(MOS6522State *dev, MOS6522Timer *ti); uint64_t (*get_timer2_counter_value)(MOS6522State *dev, MOS6522Timer *ti); @@ -147,4 +173,6 @@ extern const VMStateDescription vmstate_mos6522; uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size); void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size); +void hmp_info_via(Monitor *mon, const QDict *qdict); + #endif /* MOS6522_H */ diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index b1ec276..13b1749 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -51,7 +51,7 @@ struct ESPState { ESPDMAMemoryReadWriteFunc dma_memory_write; void *dma_opaque; void (*dma_cb)(ESPState *s); - void (*pdma_cb)(ESPState *s); + uint8_t pdma_cb; uint8_t mig_version_id; @@ -150,6 +150,15 @@ struct SysBusESPState { #define TCHI_FAS100A 0x4 #define TCHI_AM53C974 0x12 +/* PDMA callbacks */ +enum pdma_cb { + SATN_PDMA_CB = 0, + S_WITHOUT_SATN_PDMA_CB = 1, + SATN_STOP_PDMA_CB = 2, + WRITE_RESPONSE_PDMA_CB = 3, + DO_DMA_PDMA_CB = 4 +}; + void esp_dma_enable(ESPState *s, int irq, int level); void esp_request_cancelled(SCSIRequest *req); void esp_command_complete(SCSIRequest *req, size_t resid); diff --git a/include/monitor/hmp-target.h b/include/monitor/hmp-target.h index ffdc15a..1891a19 100644 --- a/include/monitor/hmp-target.h +++ b/include/monitor/hmp-target.h @@ -50,5 +50,6 @@ void hmp_mce(Monitor *mon, const QDict *qdict); void hmp_info_local_apic(Monitor *mon, const QDict *qdict); void hmp_info_sev(Monitor *mon, const QDict *qdict); void hmp_info_sgx(Monitor *mon, const QDict *qdict); +void hmp_info_via(Monitor *mon, const QDict *qdict); #endif /* MONITOR_HMP_TARGET_H */ |