|
@@ -1001,6 +1001,8 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
|
|
|
{
|
|
|
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
|
|
|
MOS6522State *ms = MOS6522(v1s);
|
|
|
+ int oldstate, state;
|
|
|
+ int oldsr = ms->sr;
|
|
|
|
|
|
addr = (addr >> 9) & 0xf;
|
|
|
|
|
@@ -1016,6 +1018,38 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
|
|
|
|
|
|
v1s->last_b = ms->b;
|
|
|
break;
|
|
|
+
|
|
|
+ case VIA_REG_SR:
|
|
|
+ {
|
|
|
+ /*
|
|
|
+ * NetBSD assumes it can send its first ADB command after sending
|
|
|
+ * the ADB_BUSRESET command in ADB_STATE_NEW without changing the
|
|
|
+ * state back to ADB_STATE_IDLE first as detailed in the ADB
|
|
|
+ * protocol.
|
|
|
+ *
|
|
|
+ * Add a workaround to detect this condition at the start of ADB
|
|
|
+ * enumeration and send the next command written to SR after a
|
|
|
+ * ADB_BUSRESET onto the bus regardless, even if we don't detect a
|
|
|
+ * state transition to ADB_STATE_NEW.
|
|
|
+ *
|
|
|
+ * Note that in my tests the NetBSD state machine takes one ADB
|
|
|
+ * operation to recover which means the probe for an ADB device at
|
|
|
+ * address 1 always fails. However since the first device is at
|
|
|
+ * address 2 then this will work fine, without having to come up
|
|
|
+ * with a more complicated and invasive solution.
|
|
|
+ */
|
|
|
+ oldstate = (v1s->last_b & VIA1B_vADB_StateMask) >>
|
|
|
+ VIA1B_vADB_StateShift;
|
|
|
+ state = (ms->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift;
|
|
|
+
|
|
|
+ if (oldstate == ADB_STATE_NEW && state == ADB_STATE_NEW &&
|
|
|
+ (ms->acr & VIA1ACR_vShiftOut) &&
|
|
|
+ oldsr == 0 /* ADB_BUSRESET */) {
|
|
|
+ trace_via1_adb_netbsd_enum_hack();
|
|
|
+ adb_via_send(v1s, state, ms->sr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|