From: Laurent Vivier <laurent@vivier.eu>
To: qemu-devel@nongnu.org
Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>,
Laurent Vivier <laurent@vivier.eu>
Subject: [PULL 13/20] swim: update IWM/ISM register block decoding
Date: Sun, 8 Oct 2023 08:23:42 +0200 [thread overview]
Message-ID: <20231008062349.2733552-14-laurent@vivier.eu> (raw)
In-Reply-To: <20231008062349.2733552-1-laurent@vivier.eu>
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Update the IWM/ISM register block decoding to match the description given in the
"SWIM Chip Users Reference". This allows us to validate the device response to
the guest OS which currently only does just enough to indicate that the floppy
drive is unavailable.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-ID: <20231004083806.757242-14-mark.cave-ayland@ilande.co.uk>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
include/hw/block/swim.h | 8 +-
hw/block/swim.c | 212 +++++++++++++++++++++++++---------------
hw/block/trace-events | 7 +-
3 files changed, 143 insertions(+), 84 deletions(-)
diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h
index 1bc7635d0212..5f567e8d5957 100644
--- a/include/hw/block/swim.h
+++ b/include/hw/block/swim.h
@@ -50,13 +50,15 @@ struct SWIMCtrl {
int mode;
/* IWM mode */
int iwm_switch;
- uint8_t iwmregs[16];
- uint8_t iwm_data;
- uint8_t iwm_mode;
+ uint8_t iwm_latches;
+ uint8_t iwmregs[8];
/* SWIM mode */
uint8_t ismregs[16];
uint8_t swim_phase;
uint8_t swim_mode;
+ uint8_t swim_status;
+ uint8_t pram[16];
+ uint8_t pram_idx;
SWIMBus bus;
};
diff --git a/hw/block/swim.c b/hw/block/swim.c
index 505718bdae3f..fd65c59f8a10 100644
--- a/hw/block/swim.c
+++ b/hw/block/swim.c
@@ -21,24 +21,28 @@
#include "hw/qdev-properties.h"
#include "trace.h"
+
+/* IWM latch bits */
+
+#define IWMLB_PHASE0 0
+#define IWMLB_PHASE1 1
+#define IWMLB_PHASE2 2
+#define IWMLB_PHASE3 3
+#define IWMLB_MOTORON 4
+#define IWMLB_DRIVESEL 5
+#define IWMLB_L6 6
+#define IWMLB_L7 7
+
/* IWM registers */
-#define IWM_PH0L 0
-#define IWM_PH0H 1
-#define IWM_PH1L 2
-#define IWM_PH1H 3
-#define IWM_PH2L 4
-#define IWM_PH2H 5
-#define IWM_PH3L 6
-#define IWM_PH3H 7
-#define IWM_MTROFF 8
-#define IWM_MTRON 9
-#define IWM_INTDRIVE 10
-#define IWM_EXTDRIVE 11
-#define IWM_Q6L 12
-#define IWM_Q6H 13
-#define IWM_Q7L 14
-#define IWM_Q7H 15
+#define IWM_READALLONES 0
+#define IWM_READDATA 1
+#define IWM_READSTATUS0 2
+#define IWM_READSTATUS1 3
+#define IWM_READWHANDSHAKE0 4
+#define IWM_READWHANDSHAKE1 5
+#define IWM_WRITESETMODE 6
+#define IWM_WRITEDATA 7
/* SWIM registers */
@@ -62,8 +66,9 @@
#define REG_SHIFT 9
-#define SWIM_MODE_IWM 0
-#define SWIM_MODE_SWIM 1
+#define SWIM_MODE_STATUS_BIT 6
+#define SWIM_MODE_IWM 0
+#define SWIM_MODE_ISM 1
/* bits in phase register */
@@ -127,10 +132,8 @@
#define SWIM_MOTON 0x80
static const char *iwm_reg_names[] = {
- "PH0L", "PH0H", "PH1L", "PH1H",
- "PH2L", "PH2H", "PH3L", "PH3H",
- "MTROFF", "MTRON", "INTDRIVE", "EXTDRIVE",
- "Q6L", "Q6H", "Q7L", "Q7H"
+ "READALLONES", "READDATA", "READSTATUS0", "READSTATUS1",
+ "READWHANDSHAKE0", "READWHANDSHAKE1", "WRITESETMODE", "WRITEDATA"
};
static const char *ism_reg_names[] = {
@@ -274,68 +277,99 @@ static const TypeInfo swim_bus_info = {
.instance_size = sizeof(SWIMBus),
};
-static void iwmctrl_write(void *opaque, hwaddr reg, uint64_t value,
+static void iwmctrl_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
SWIMCtrl *swimctrl = opaque;
+ uint8_t latch, reg, ism_bit;
- reg >>= REG_SHIFT;
+ addr >>= REG_SHIFT;
+
+ /* A3-A1 select a latch, A0 specifies the value */
+ latch = (addr >> 1) & 7;
+ if (addr & 1) {
+ swimctrl->iwm_latches |= (1 << latch);
+ } else {
+ swimctrl->iwm_latches &= ~(1 << latch);
+ }
+
+ reg = (swimctrl->iwm_latches & 0xc0) >> 5 |
+ (swimctrl->iwm_latches & 0x10) >> 4;
swimctrl->iwmregs[reg] = value;
trace_swim_iwmctrl_write(reg, iwm_reg_names[reg], size, value);
- if (swimctrl->iwmregs[IWM_Q7H]) {
- if (swimctrl->iwmregs[IWM_MTRON]) {
- /* data register */
- swimctrl->iwm_data = value;
- } else {
- /* mode register */
- swimctrl->iwm_mode = value;
- /* detect sequence to switch from IWM mode to SWIM mode */
- switch (swimctrl->iwm_switch) {
- case 0:
- if (value == 0x57) {
- swimctrl->iwm_switch++;
- }
- break;
- case 1:
- if (value == 0x17) {
- swimctrl->iwm_switch++;
- }
- break;
- case 2:
- if (value == 0x57) {
- swimctrl->iwm_switch++;
- }
- break;
- case 3:
- if (value == 0x57) {
- swimctrl->mode = SWIM_MODE_SWIM;
- swimctrl->iwm_switch = 0;
- trace_swim_iwm_switch();
-
- /* Switch to ISM registers */
- memory_region_del_subregion(&swimctrl->swim,
- &swimctrl->iwm);
- memory_region_add_subregion(&swimctrl->swim, 0x0,
- &swimctrl->ism);
- }
- break;
+ switch (reg) {
+ case IWM_WRITESETMODE:
+ /* detect sequence to switch from IWM mode to SWIM mode */
+ ism_bit = (value & (1 << SWIM_MODE_STATUS_BIT));
+
+ switch (swimctrl->iwm_switch) {
+ case 0:
+ if (ism_bit) { /* 1 */
+ swimctrl->iwm_switch++;
+ }
+ break;
+ case 1:
+ if (!ism_bit) { /* 0 */
+ swimctrl->iwm_switch++;
+ }
+ break;
+ case 2:
+ if (ism_bit) { /* 1 */
+ swimctrl->iwm_switch++;
}
+ break;
+ case 3:
+ if (ism_bit) { /* 1 */
+ swimctrl->iwm_switch++;
+
+ swimctrl->mode = SWIM_MODE_ISM;
+ swimctrl->swim_mode |= (1 << SWIM_MODE_STATUS_BIT);
+ swimctrl->iwm_switch = 0;
+ trace_swim_switch_to_ism();
+
+ /* Switch to ISM registers */
+ memory_region_del_subregion(&swimctrl->swim, &swimctrl->iwm);
+ memory_region_add_subregion(&swimctrl->swim, 0x0,
+ &swimctrl->ism);
+ }
+ break;
}
+ break;
+ default:
+ break;
}
}
-static uint64_t iwmctrl_read(void *opaque, hwaddr reg, unsigned size)
+static uint64_t iwmctrl_read(void *opaque, hwaddr addr, unsigned size)
{
SWIMCtrl *swimctrl = opaque;
- uint8_t value;
+ uint8_t latch, reg, value;
- reg >>= REG_SHIFT;
+ addr >>= REG_SHIFT;
- value = swimctrl->iwmregs[reg];
- trace_swim_iwmctrl_read(reg, iwm_reg_names[reg], size, value);
+ /* A3-A1 select a latch, A0 specifies the value */
+ latch = (addr >> 1) & 7;
+ if (addr & 1) {
+ swimctrl->iwm_latches |= (1 << latch);
+ } else {
+ swimctrl->iwm_latches &= ~(1 << latch);
+ }
+
+ reg = (swimctrl->iwm_latches & 0xc0) >> 5 |
+ (swimctrl->iwm_latches & 0x10) >> 4;
+
+ switch (reg) {
+ case IWM_READALLONES:
+ value = 0xff;
+ break;
+ default:
+ value = 0;
+ break;
+ }
+ trace_swim_iwmctrl_read(reg, iwm_reg_names[reg], size, value);
return value;
}
@@ -352,7 +386,7 @@ static void ismctrl_write(void *opaque, hwaddr reg, uint64_t value,
reg >>= REG_SHIFT;
- trace_swim_swimctrl_write(reg, ism_reg_names[reg], size, value);
+ trace_swim_ismctrl_write(reg, ism_reg_names[reg], size, value);
switch (reg) {
case SWIM_WRITE_PHASE:
@@ -360,14 +394,31 @@ static void ismctrl_write(void *opaque, hwaddr reg, uint64_t value,
break;
case SWIM_WRITE_MODE0:
swimctrl->swim_mode &= ~value;
+ /* Any access to MODE0 register resets PRAM index */
+ swimctrl->pram_idx = 0;
+
+ if (!(swimctrl->swim_mode & (1 << SWIM_MODE_STATUS_BIT))) {
+ /* Clearing the mode bit switches to IWM mode */
+ swimctrl->mode = SWIM_MODE_IWM;
+ swimctrl->iwm_latches = 0;
+ trace_swim_switch_to_iwm();
+
+ /* Switch to IWM registers */
+ memory_region_del_subregion(&swimctrl->swim, &swimctrl->ism);
+ memory_region_add_subregion(&swimctrl->swim, 0x0,
+ &swimctrl->iwm);
+ }
break;
case SWIM_WRITE_MODE1:
swimctrl->swim_mode |= value;
break;
+ case SWIM_WRITE_PARAMETER:
+ swimctrl->pram[swimctrl->pram_idx++] = value;
+ swimctrl->pram_idx &= 0xf;
+ break;
case SWIM_WRITE_DATA:
case SWIM_WRITE_MARK:
case SWIM_WRITE_CRC:
- case SWIM_WRITE_PARAMETER:
case SWIM_WRITE_SETUP:
break;
}
@@ -390,16 +441,24 @@ static uint64_t ismctrl_read(void *opaque, hwaddr reg, unsigned size)
value = SWIM_SENSE;
}
break;
+ case SWIM_READ_PARAMETER:
+ value = swimctrl->pram[swimctrl->pram_idx++];
+ swimctrl->pram_idx &= 0xf;
+ break;
+ case SWIM_READ_STATUS:
+ value = swimctrl->swim_status & ~(1 << SWIM_MODE_STATUS_BIT);
+ if (swimctrl->swim_mode == SWIM_MODE_ISM) {
+ value |= (1 << SWIM_MODE_STATUS_BIT);
+ }
+ break;
case SWIM_READ_DATA:
case SWIM_READ_MARK:
case SWIM_READ_ERROR:
- case SWIM_READ_PARAMETER:
case SWIM_READ_SETUP:
- case SWIM_READ_STATUS:
break;
}
- trace_swim_swimctrl_read(reg, ism_reg_names[reg], size, value);
+ trace_swim_ismctrl_read(reg, ism_reg_names[reg], size, value);
return value;
}
@@ -417,13 +476,11 @@ static void sysbus_swim_reset(DeviceState *d)
ctrl->mode = 0;
ctrl->iwm_switch = 0;
- ctrl->iwm_data = 0;
- ctrl->iwm_mode = 0;
- memset(ctrl->iwmregs, 0, 16);
+ memset(ctrl->iwmregs, 0, sizeof(ctrl->iwmregs));
ctrl->swim_phase = 0;
ctrl->swim_mode = 0;
- memset(ctrl->ismregs, 0, 16);
+ memset(ctrl->ismregs, 0, sizeof(ctrl->ismregs));
for (i = 0; i < SWIM_MAX_FD; i++) {
fd_recalibrate(&ctrl->drives[i]);
}
@@ -472,9 +529,8 @@ static const VMStateDescription vmstate_swim = {
VMSTATE_INT32(mode, SWIMCtrl),
/* IWM mode */
VMSTATE_INT32(iwm_switch, SWIMCtrl),
- VMSTATE_UINT8_ARRAY(iwmregs, SWIMCtrl, 16),
- VMSTATE_UINT8(iwm_data, SWIMCtrl),
- VMSTATE_UINT8(iwm_mode, SWIMCtrl),
+ VMSTATE_UINT8(iwm_latches, SWIMCtrl),
+ VMSTATE_UINT8_ARRAY(iwmregs, SWIMCtrl, 8),
/* SWIM mode */
VMSTATE_UINT8_ARRAY(ismregs, SWIMCtrl, 16),
VMSTATE_UINT8(swim_phase, SWIMCtrl),
diff --git a/hw/block/trace-events b/hw/block/trace-events
index ea84ad6c77ed..bab21d3a1ca8 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -92,8 +92,9 @@ m25p80_binding(void *s) "[%p] Binding to IF_MTD drive"
m25p80_binding_no_bdrv(void *s) "[%p] No BDRV - binding to RAM"
# swim.c
-swim_swimctrl_read(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
-swim_swimctrl_write(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
+swim_ismctrl_read(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
+swim_ismctrl_write(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
swim_iwmctrl_read(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
swim_iwmctrl_write(int reg, const char *name, unsigned size, uint64_t value) "reg=%d [%s] size=%u value=0x%"PRIx64
-swim_iwm_switch(void) "switch from IWM to SWIM mode"
+swim_switch_to_ism(void) "switch from IWM to ISM mode"
+swim_switch_to_iwm(void) "switch from ISM to IWM mode"
--
2.41.0
next prev parent reply other threads:[~2023-10-08 6:25 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-08 6:23 [PULL 00/20] Q800 for 8.2 patches Laurent Vivier
2023-10-08 6:23 ` [PULL 01/20] q800-glue.c: convert to Resettable interface Laurent Vivier
2023-10-08 6:23 ` [PULL 02/20] q800: add djMEMC memory controller Laurent Vivier
2023-10-08 6:23 ` [PULL 03/20] q800: add machine id register Laurent Vivier
2023-10-08 6:23 ` [PULL 04/20] q800: implement additional machine id bits on VIA1 port A Laurent Vivier
2023-10-08 6:23 ` [PULL 05/20] q800: add IOSB subsystem Laurent Vivier
2023-10-08 6:23 ` [PULL 06/20] q800: allow accesses to RAM area even if less memory is available Laurent Vivier
2023-10-08 6:23 ` [PULL 07/20] audio: add Apple Sound Chip (ASC) emulation Laurent Vivier
2023-10-08 6:23 ` [PULL 08/20] asc: generate silence if FIFO empty but engine still running Laurent Vivier
2023-10-08 6:23 ` [PULL 09/20] q800: add Apple Sound Chip (ASC) audio to machine Laurent Vivier
2023-10-08 6:23 ` [PULL 10/20] q800: add easc bool machine class property to switch between ASC and EASC Laurent Vivier
2023-10-08 6:23 ` [PULL 11/20] swim: add trace events for IWM and ISM registers Laurent Vivier
2023-10-08 6:23 ` [PULL 12/20] swim: split into separate IWM and ISM register blocks Laurent Vivier
2023-10-08 6:23 ` Laurent Vivier [this message]
2023-10-08 6:23 ` [PULL 14/20] mac_via: work around underflow in TimeDBRA timing loop in SETUPTIMEK Laurent Vivier
2023-10-08 6:23 ` [PULL 15/20] mac_via: workaround NetBSD ADB bus enumeration issue Laurent Vivier
2023-10-08 6:23 ` [PULL 16/20] mac_via: implement ADB_STATE_IDLE state if shift register in input mode Laurent Vivier
2023-10-08 6:23 ` [PULL 17/20] mac_via: always clear ADB interrupt when switching to A/UX mode Laurent Vivier
2023-10-08 6:23 ` [PULL 18/20] q800: add ESCC alias at 0xc000 Laurent Vivier
2023-10-08 6:23 ` [PULL 19/20] q800: add alias for MacOS toolbox ROM at 0x40000000 Laurent Vivier
2023-10-08 6:23 ` [PULL 20/20] mac_via: extend timer calibration hack to work with A/UX Laurent Vivier
2023-10-10 1:29 ` [PULL 00/20] Q800 for 8.2 patches Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231008062349.2733552-14-laurent@vivier.eu \
--to=laurent@vivier.eu \
--cc=mark.cave-ayland@ilande.co.uk \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).