mac_via: extend timer calibration hack to work with A/UX
The A/UX timer calibration loop runs continuously until 2 consecutive iterations differ by at least 0x492 timer ticks. Modern hosts execute the timer calibration loop so fast that this situation never occurs causing a hang on boot. Use a similar method to Shoebill which is to randomly add 0x500 to the T2 counter value during calibration to enable it to eventually succeed. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-ID: <20231004083806.757242-21-mark.cave-ayland@ilande.co.uk> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
parent
9d35c6ade5
commit
b4d3a83b89
|
@ -983,6 +983,44 @@ static void via1_timer_calibration_hack(MOS6522Q800VIA1State *v1s, int addr,
|
||||||
/* Looks like there has been a reset? */
|
/* Looks like there has been a reset? */
|
||||||
v1s->timer_hack_state = 1;
|
v1s->timer_hack_state = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addr == VIA_REG_T2CL && val == 0xf0) {
|
||||||
|
/* VIA_REG_T2CL: low byte of counter (A/UX) */
|
||||||
|
v1s->timer_hack_state = 5;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
if (addr == VIA_REG_T2CH && val == 0x3c) {
|
||||||
|
/*
|
||||||
|
* VIA_REG_T2CH: high byte of counter (A/UX). We are now extremely
|
||||||
|
* likely to be in the A/UX timer calibration routine, so move to
|
||||||
|
* the next state where we enable the calibration hack.
|
||||||
|
*/
|
||||||
|
v1s->timer_hack_state = 6;
|
||||||
|
} else if ((addr == VIA_REG_IER && val == 0x20) ||
|
||||||
|
addr == VIA_REG_T2CH) {
|
||||||
|
/* We're doing something else with the timer, not calibration */
|
||||||
|
v1s->timer_hack_state = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
if ((addr == VIA_REG_IER && val == 0x20) || addr == VIA_REG_T2CH) {
|
||||||
|
/* End of A/UX timer calibration routine, or another write */
|
||||||
|
v1s->timer_hack_state = 7;
|
||||||
|
} else {
|
||||||
|
v1s->timer_hack_state = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
/*
|
||||||
|
* This is the normal post-calibration timer state once both the
|
||||||
|
* MacOS toolbox and A/UX have been calibrated, until we see a write
|
||||||
|
* to VIA_REG_PCR to suggest a reset
|
||||||
|
*/
|
||||||
|
if (addr == VIA_REG_PCR && val == 0x22) {
|
||||||
|
/* Looks like there has been a reset? */
|
||||||
|
v1s->timer_hack_state = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
|
@ -998,6 +1036,7 @@ static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
MOS6522Q800VIA1State *s = MOS6522_Q800_VIA1(opaque);
|
MOS6522Q800VIA1State *s = MOS6522_Q800_VIA1(opaque);
|
||||||
MOS6522State *ms = MOS6522(s);
|
MOS6522State *ms = MOS6522(s);
|
||||||
uint64_t ret;
|
uint64_t ret;
|
||||||
|
int64_t now;
|
||||||
|
|
||||||
addr = (addr >> 9) & 0xf;
|
addr = (addr >> 9) & 0xf;
|
||||||
ret = mos6522_read(ms, addr, size);
|
ret = mos6522_read(ms, addr, size);
|
||||||
|
@ -1007,6 +1046,23 @@ static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
/* Quadra 800 Id */
|
/* Quadra 800 Id */
|
||||||
ret = (ret & ~VIA1A_CPUID_MASK) | VIA1A_CPUID_Q800;
|
ret = (ret & ~VIA1A_CPUID_MASK) | VIA1A_CPUID_Q800;
|
||||||
break;
|
break;
|
||||||
|
case VIA_REG_T2CH:
|
||||||
|
if (s->timer_hack_state == 6) {
|
||||||
|
/*
|
||||||
|
* The A/UX timer calibration loop runs continuously until 2
|
||||||
|
* consecutive iterations differ by at least 0x492 timer ticks.
|
||||||
|
* Modern hosts execute the timer calibration loop so fast that
|
||||||
|
* this situation never occurs causing a hang on boot. Use a
|
||||||
|
* similar method to Shoebill which is to randomly add 0x500 to
|
||||||
|
* the T2 counter value during calibration to enable it to
|
||||||
|
* eventually succeed.
|
||||||
|
*/
|
||||||
|
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
|
if (now & 1) {
|
||||||
|
ret += 0x5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue