From nobody Tue Feb 10 20:57:24 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1646824695166555.2914316601955; Wed, 9 Mar 2022 03:18:15 -0800 (PST) Received: from localhost ([::1]:50168 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nRuKb-0004GH-GE for importer@patchew.org; Wed, 09 Mar 2022 06:18:13 -0500 Received: from eggs.gnu.org ([209.51.188.92]:41038) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nRuCC-0006d7-RL for qemu-devel@nongnu.org; Wed, 09 Mar 2022 06:09:32 -0500 Received: from [2001:41c9:1:41f::167] (port=35736 helo=mail.default.ilande.bv.iomart.io) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nRuCA-0005GO-RS for qemu-devel@nongnu.org; Wed, 09 Mar 2022 06:09:32 -0500 Received: from [2a00:23c4:8ba0:ca00:d4eb:dbd5:5a41:aefe] (helo=kentang.home) by mail.default.ilande.bv.iomart.io with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nRuBQ-000CWr-GN; Wed, 09 Mar 2022 11:08:48 +0000 From: Mark Cave-Ayland To: peter.maydell@linaro.org, laurent@vivier.eu, qemu-devel@nongnu.org Date: Wed, 9 Mar 2022 11:08:20 +0000 Message-Id: <20220309110831.18443-12-mark.cave-ayland@ilande.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220309110831.18443-1-mark.cave-ayland@ilande.co.uk> References: <20220309110831.18443-1-mark.cave-ayland@ilande.co.uk> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a00:23c4:8ba0:ca00:d4eb:dbd5:5a41:aefe X-SA-Exim-Mail-From: mark.cave-ayland@ilande.co.uk Subject: [PULL 11/22] mos6522: implement edge-triggering for CA1/2 and CB1/2 control line IRQs X-SA-Exim-Version: 4.2.1 (built Wed, 08 May 2019 21:11:16 +0000) X-SA-Exim-Scanned: Yes (on mail.default.ilande.bv.iomart.io) X-Host-Lookup-Failed: Reverse DNS lookup failed for 2001:41c9:1:41f::167 (failed) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:41c9:1:41f::167; envelope-from=mark.cave-ayland@ilande.co.uk; helo=mail.default.ilande.bv.iomart.io X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZM-MESSAGEID: 1646824696335100001 Content-Type: text/plain; charset="utf-8" The mos6522 datasheet describes how the control lines IRQs are edge-trigger= ed according to the configuration in the PCR register. Implement the logic acc= ording to the datasheet so that the interrupt bits in IFR are latched when the edg= e is detected, and cleared when reading portA/portB or writing to IFR as necessa= ry. To maintain bisectibility this change also updates the SCSI, SCSI data, Nub= us and VIA2 60Hz/1Hz clocks in the q800 machine to be negative edge-triggered = as confirmed by the PCR programming in all of Linux, NetBSD and MacOS. Signed-off-by: Mark Cave-Ayland Reviewed-by: Laurent Vivier Message-Id: <20220305150957.5053-12-mark.cave-ayland@ilande.co.uk> Signed-off-by: Mark Cave-Ayland --- hw/m68k/q800.c | 9 +++-- hw/misc/mac_via.c | 15 +++++-- hw/misc/mos6522.c | 82 +++++++++++++++++++++++++++++++++++++-- include/hw/misc/mos6522.h | 15 +++++++ 4 files changed, 109 insertions(+), 12 deletions(-) diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index 55dfe5036f..66ca5c0df6 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -533,10 +533,11 @@ static void q800_init(MachineState *machine) =20 sysbus =3D 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_de= v, + VIA2_IRQ_SCSI_BIT))); + sysbus_connect_irq(sysbus, 1, qemu_irq_invert(qdev_get_gpio_in(via2_de= v, + VIA2_IRQ_SCSI_DATA_BIT))= ); sysbus_mmio_map(sysbus, 0, ESP_BASE); sysbus_mmio_map(sysbus, 1, ESP_PDMA); =20 diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c index d8b35e6ca6..525e38ce93 100644 --- a/hw/misc/mac_via.c +++ b/hw/misc/mac_via.c @@ -327,7 +327,9 @@ static void via1_sixty_hz(void *opaque) MOS6522State *s =3D MOS6522(v1s); qemu_irq irq =3D qdev_get_gpio_in(DEVICE(s), VIA1_IRQ_60HZ_BIT); =20 - qemu_set_irq(irq, 1); + /* Negative edge trigger */ + qemu_irq_lower(irq); + qemu_irq_raise(irq); =20 via1_sixty_hz_update(v1s); } @@ -338,7 +340,9 @@ static void via1_one_second(void *opaque) MOS6522State *s =3D MOS6522(v1s); qemu_irq irq =3D qdev_get_gpio_in(DEVICE(s), VIA1_IRQ_ONE_SECOND_BIT); =20 - qemu_set_irq(irq, 1); + /* Negative edge trigger */ + qemu_irq_lower(irq); + qemu_irq_raise(irq); =20 via1_one_second_update(v1s); } @@ -917,9 +921,11 @@ static uint64_t mos6522_q800_via2_read(void *opaque, h= waddr addr, unsigned size) * 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 &=3D ~VIA2_IRQ_SCSI_DATA; - val |=3D (ms->last_irq_levels & VIA2_IRQ_SCSI_DATA); + val |=3D (~ms->last_irq_levels & VIA2_IRQ_SCSI_DATA); break; } =20 @@ -1146,7 +1152,8 @@ static void via2_nubus_irq_request(void *opaque, int = n, int level) s->a |=3D (1 << n); } =20 - qemu_set_irq(irq, level); + /* Negative edge trigger */ + qemu_set_irq(irq, !level); } =20 static void mos6522_q800_via2_init(Object *obj) diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c index c67123f864..f9e646350e 100644 --- a/hw/misc/mos6522.c +++ b/hw/misc/mos6522.c @@ -64,14 +64,62 @@ static void mos6522_update_irq(MOS6522State *s) static void mos6522_set_irq(void *opaque, int n, int level) { MOS6522State *s =3D MOS6522(opaque); + int last_level =3D !!(s->last_irq_levels & (1 << n)); + uint8_t last_ifr =3D s->ifr; + bool positive_edge =3D 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 !=3D SR_INT_BIT && level =3D=3D last_level) { + return; + } =20 - if (level) { + /* Detect negative edge trigger */ + if (last_level =3D=3D 1 && level =3D=3D 0) { + positive_edge =3D false; + } + + switch (n) { + case CA2_INT_BIT: + ctrl =3D (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT; + if ((positive_edge && (ctrl & C2_POS)) || + (!positive_edge && !(ctrl & C2_POS))) { + s->ifr |=3D 1 << n; + } + break; + case CA1_INT_BIT: + ctrl =3D (s->pcr & CA1_CTRL_MASK) >> CA1_CTRL_SHIFT; + if ((positive_edge && (ctrl & C1_POS)) || + (!positive_edge && !(ctrl & C1_POS))) { + s->ifr |=3D 1 << n; + } + break; + case SR_INT_BIT: s->ifr |=3D 1 << n; - } else { - s->ifr &=3D ~(1 << n); + break; + case CB2_INT_BIT: + ctrl =3D (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT; + if ((positive_edge && (ctrl & C2_POS)) || + (!positive_edge && !(ctrl & C2_POS))) { + s->ifr |=3D 1 << n; + } + break; + case CB1_INT_BIT: + ctrl =3D (s->pcr & CB1_CTRL_MASK) >> CB1_CTRL_SHIFT; + if ((positive_edge && (ctrl & C1_POS)) || + (!positive_edge && !(ctrl & C1_POS))) { + s->ifr |=3D 1 << n; + } + break; } =20 - mos6522_update_irq(s); + if (s->ifr !=3D last_ifr) { + mos6522_update_irq(s); + } =20 if (level) { s->last_irq_levels |=3D 1 << n; @@ -250,6 +298,7 @@ uint64_t mos6522_read(void *opaque, hwaddr addr, unsign= ed size) { MOS6522State *s =3D opaque; uint32_t val; + int ctrl; int64_t now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); =20 if (now >=3D s->timers[0].next_irq_time) { @@ -263,12 +312,24 @@ uint64_t mos6522_read(void *opaque, hwaddr addr, unsi= gned size) switch (addr) { case VIA_REG_B: val =3D s->b; + ctrl =3D (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT; + if (!(ctrl & C2_IND)) { + s->ifr &=3D ~CB2_INT; + } + s->ifr &=3D ~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 =3D s->a; + ctrl =3D (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT; + if (!(ctrl & C2_IND)) { + s->ifr &=3D ~CA2_INT; + } + s->ifr &=3D ~CA1_INT; + mos6522_update_irq(s); break; case VIA_REG_DIRB: val =3D s->dirb; @@ -335,6 +396,7 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t = val, unsigned size) { MOS6522State *s =3D opaque; MOS6522DeviceClass *mdc =3D MOS6522_GET_CLASS(s); + int ctrl; =20 trace_mos6522_write(addr, mos6522_reg_names[addr], val); =20 @@ -342,6 +404,12 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t= val, unsigned size) case VIA_REG_B: s->b =3D (s->b & ~s->dirb) | (val & s->dirb); mdc->portB_write(s); + ctrl =3D (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT; + if (!(ctrl & C2_IND)) { + s->ifr &=3D ~CB2_INT; + } + s->ifr &=3D ~CB1_INT; + mos6522_update_irq(s); break; case VIA_REG_A: qemu_log_mask(LOG_UNIMP, "Write access to register A with handshake= "); @@ -349,6 +417,12 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t= val, unsigned size) case VIA_REG_ANH: s->a =3D (s->a & ~s->dira) | (val & s->dira); mdc->portA_write(s); + ctrl =3D (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT; + if (!(ctrl & C2_IND)) { + s->ifr &=3D ~CA2_INT; + } + s->ifr &=3D ~CA1_INT; + mos6522_update_irq(s); break; case VIA_REG_DIRB: s->dirb =3D val; diff --git a/include/hw/misc/mos6522.h b/include/hw/misc/mos6522.h index babea99e06..0bc22a8395 100644 --- a/include/hw/misc/mos6522.h +++ b/include/hw/misc/mos6522.h @@ -65,6 +65,21 @@ #define T1MODE 0xc0 /* Timer 1 mode */ #define T1MODE_CONT 0x40 /* continuous interrupts */ =20 +/* 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 --=20 2.20.1