On 02/07/2026 03:29, Matt Jacobson wrote:
Switch the Quadra 800 machine to the working SWIM2 floppy controller.
Hook up the HeadSel bit on the VIA to control the head selection (the
IWM does not handle this part itself).
Signed-off-by: Matt Jacobson <[email protected]>
---
hw/m68k/q800.c | 5 +++--
hw/misc/mac_via.c | 16 ++++++++++++++++
include/hw/m68k/q800.h | 4 ++--
include/hw/misc/mac_via.h | 3 +++
4 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index ab64250c47..a6997ef802 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -47,7 +47,7 @@
#include "hw/audio/asc.h"
#include "hw/nubus/mac-nubus-bridge.h"
#include "hw/display/macfb.h"
-#include "hw/block/swim.h"
+#include "hw/block/swim2.h"
#include "net/net.h"
#include "net/util.h"
#include "qapi/error.h"
@@ -338,6 +338,7 @@ static void q800_machine_init(MachineState *machine)
/* VIA 1 */
object_initialize_child(OBJECT(machine), "via1", &m->via1,
TYPE_MOS6522_Q800_VIA1);
+ m->via1.swim = &m->swim;
This doesn't look right: in general we should avoid accessing a device state struct
directly unless it is absolutely unavoidable.
dinfo = drive_get(IF_MTD, 0, 0);
if (dinfo) {
qdev_prop_set_drive(DEVICE(&m->via1), "drive",
@@ -511,7 +512,7 @@ static void q800_machine_init(MachineState *machine)
/* SWIM floppy controller */
object_initialize_child(OBJECT(machine), "swim", &m->swim,
- TYPE_SWIM);
+ TYPE_SWIM2);
sysbus = SYS_BUS_DEVICE(&m->swim);
sysbus_realize(sysbus, &error_fatal);
memory_region_add_subregion(&m->macio, SWIM_BASE - IO_BASE,
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 26ee230dcc..09197fe519 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -31,6 +31,7 @@
#include "hw/core/qdev-properties-system.h"
#include "system/block-backend.h"
#include "system/rtc.h"
+#include "hw/block/swim2.h"
#include "trace.h"
#include "qemu/log.h"
@@ -1080,6 +1081,17 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
mos6522_write(ms, addr, val, size);
switch (addr) {
+ case VIA_REG_A:
+ case VIA_REG_ANH: {
+ const bool sel = (ms->a & VIA1A_vHeadSel) != 0;
+
+ if (v1s->swim) {
+ swim2_set_sel(v1s->swim, sel);
+ }
+
+ break;
+ }
Can you move this into a separate via1_swim_update(v1s) function as done for the rtc
and adb devices as below? If possible I'd like to minimise the per-device logic in
mos6522_q800_via1_write().
case VIA_REG_B:
via1_rtc_update(v1s);
via1_adb_update(v1s);
@@ -1224,6 +1236,10 @@ static void mos6522_q800_via1_reset_hold(Object *obj,
ResetType type)
/* Timer calibration hack */
v1s->timer_hack_state = 0;
+
+ if (v1s->swim) {
+ swim2_set_sel(v1s->swim, false);
+ }
Given that SWIM2 is also a TYPE_DEVICE, you should be able to expose the sel signal
as a GPIO on the SWIM2 device in a similar way as to how "nubus-irq" is defined in
mos6522_q800_via2_init() but with just 1 signal. This allows you to connect the
signal with qdev_connect_gpio_out() (see hw/m68k/q800.c) and drive it using the qemu
IRQ functions, which should avoid having to reference the SWIM2 device itself
directly at all.
}
static void mos6522_q800_via1_realize(DeviceState *dev, Error **errp)
diff --git a/include/hw/m68k/q800.h b/include/hw/m68k/q800.h
index 77551b9592..2a20314d57 100644
--- a/include/hw/m68k/q800.h
+++ b/include/hw/m68k/q800.h
@@ -33,7 +33,7 @@
#include "hw/char/escc.h"
#include "hw/core/or-irq.h"
#include "hw/scsi/esp.h"
-#include "hw/block/swim.h"
+#include "hw/block/swim2.h"
#include "hw/nubus/mac-nubus-bridge.h"
#include "hw/display/macfb.h"
#include "hw/misc/djmemc.h"
@@ -59,7 +59,7 @@ struct Q800MachineState {
ESCCState escc;
OrIRQState escc_orgate;
SysBusESPState esp;
- Swim swim;
+ SWIM2State swim;
MacNubusBridge mac_nubus_bridge;
MacfbNubusState macfb;
DJMEMCState djmemc;
diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h
index 114f41db4c..e23735b47c 100644
--- a/include/hw/misc/mac_via.h
+++ b/include/hw/misc/mac_via.h
@@ -13,6 +13,7 @@
#include "hw/core/sysbus.h"
#include "hw/misc/mos6522.h"
#include "hw/input/adb.h"
+#include "hw/block/swim2.h"
#include "qom/object.h"
@@ -77,6 +78,8 @@ struct MOS6522Q800VIA1State {
/* SETUPTIMEK hack */
int timer_hack_state;
+
+ SWIM2State *swim;
};
ATB,
Mark.