WIP: PAS16.

See above, currently very WIP.
This commit is contained in:
TC1995
2024-03-18 17:10:36 +01:00
parent d2c5420a34
commit 27e78da4ec
8 changed files with 381 additions and 320 deletions

117
src/pit.c
View File

@@ -94,13 +94,15 @@ pit_log(const char *fmt, ...)
#endif
static void
ctr_set_out(ctr_t *ctr, int out)
ctr_set_out(ctr_t *ctr, int out, void *priv)
{
pit_t *pit = (pit_t *)priv;
if (ctr == NULL)
return;
if (ctr->out_func != NULL)
ctr->out_func(out, ctr->out);
ctr->out_func(out, ctr->out, pit);
ctr->out = out;
}
@@ -146,8 +148,9 @@ ctr_load_count(ctr_t *ctr)
}
static void
ctr_tick(ctr_t *ctr)
ctr_tick(ctr_t *ctr, void *priv)
{
pit_t *pit = (pit_t *)priv;
uint8_t state = ctr->state;
if ((state & 0x03) == 0x01) {
@@ -155,7 +158,7 @@ ctr_tick(ctr_t *ctr)
ctr_load_count(ctr);
ctr->state++;
if (((ctr->m & 0x07) == 0x01) && (ctr->state == 2))
ctr_set_out(ctr, 0);
ctr_set_out(ctr, 0, pit);
} else switch (ctr->m & 0x07) {
case 0:
/* Interrupt on terminal count */
@@ -165,7 +168,7 @@ ctr_tick(ctr_t *ctr)
ctr_decrease_count(ctr);
if (ctr->count < 1) {
ctr->state = 3;
ctr_set_out(ctr, 1);
ctr_set_out(ctr, 1, pit);
}
}
break;
@@ -185,7 +188,7 @@ ctr_tick(ctr_t *ctr)
ctr_decrease_count(ctr);
if (ctr->count < 1) {
ctr->state = 3;
ctr_set_out(ctr, 1);
ctr_set_out(ctr, 1, pit);
}
}
break;
@@ -205,7 +208,7 @@ ctr_tick(ctr_t *ctr)
case 3:
ctr_load_count(ctr);
ctr->state = 2;
ctr_set_out(ctr, 1);
ctr_set_out(ctr, 1, pit);
break;
case 2:
if (ctr->gate == 0)
@@ -214,7 +217,7 @@ ctr_tick(ctr_t *ctr)
ctr_decrease_count(ctr);
if (ctr->count < 2) {
ctr->state = 3;
ctr_set_out(ctr, 0);
ctr_set_out(ctr, 0, pit);
}
}
break;
@@ -240,7 +243,7 @@ ctr_tick(ctr_t *ctr)
if (ctr->count < 0) {
ctr_load_count(ctr);
ctr->state = 3;
ctr_set_out(ctr, 0);
ctr_set_out(ctr, 0, pit);
} else if (ctr->newcount)
ctr->newcount = 0;
}
@@ -259,7 +262,7 @@ ctr_tick(ctr_t *ctr)
if (ctr->count < 0) {
ctr_load_count(ctr);
ctr->state = 2;
ctr_set_out(ctr, 1);
ctr_set_out(ctr, 1, pit);
} else if (ctr->newcount)
ctr->newcount = 0;
}
@@ -284,13 +287,13 @@ ctr_tick(ctr_t *ctr)
ctr_decrease_count(ctr);
if (ctr->count < 1) {
ctr->state = 3;
ctr_set_out(ctr, 0);
ctr_set_out(ctr, 0, pit);
}
}
break;
case 3:
ctr->state = 0;
ctr_set_out(ctr, 1);
ctr_set_out(ctr, 1, pit);
break;
default:
@@ -316,7 +319,7 @@ ctr_clock(void *data, int counter_id)
if (ctr->using_timer)
return;
ctr_tick(ctr);
ctr_tick(ctr, pit);
}
static void
@@ -351,7 +354,7 @@ ctr_load(ctr_t *ctr)
if (ctr->load_func != NULL)
ctr->load_func(ctr->m, ctr->l ? ctr->l : 0x10000);
pit_log("Counter loaded, state = %i, gate = %i\n", ctr->state, ctr->gate);
pclog("Counter loaded, state = %i, gate = %i, latch = %i\n", ctr->state, ctr->gate, ctr->latch);
}
static __inline void
@@ -390,7 +393,7 @@ ctr_latch_count(ctr_t *ctr)
break;
}
pit_log("latched counter = %04X\n", ctr->rl & 0xffff);
pclog("rm = %x, latched counter = %04X\n", ctr->rm & 0x03, ctr->rl & 0xffff);
}
uint16_t
@@ -415,7 +418,7 @@ pit_ctr_set_load_func(void *data, int counter_id, void (*func)(uint8_t new_m, in
}
void
pit_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out))
pit_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out, void *priv))
{
if (data == NULL)
return;
@@ -448,14 +451,14 @@ pit_ctr_set_gate(void *data, int counter_id, int gate)
/* Here we handle the rising edges. */
if (mode & 1) {
if (mode != 1)
ctr_set_out(ctr, 1);
ctr_set_out(ctr, 1, pit);
ctr->state = 1;
} else if (mode == 2)
ctr->state = 3;
} else if (old && !gate) {
/* Here we handle the lowering edges. */
if (mode & 2)
ctr_set_out(ctr, 1);
ctr_set_out(ctr, 1, pit);
}
break;
@@ -465,8 +468,9 @@ pit_ctr_set_gate(void *data, int counter_id, int gate)
}
static __inline void
pit_ctr_set_clock_common(ctr_t *ctr, int clock)
pit_ctr_set_clock_common(ctr_t *ctr, int clock, void *priv)
{
pit_t *pit = (pit_t *)priv;
int old = ctr->clock;
ctr->clock = clock;
@@ -484,18 +488,18 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock)
ctr->s1_det++; /* Falling edge. */
if (ctr->s1_det >= 2) {
ctr->s1_det = 0;
ctr_tick(ctr);
ctr_tick(ctr, pit);
}
}
} else if (old && !ctr->clock)
ctr_tick(ctr);
ctr_tick(ctr, pit);
}
}
void
pit_ctr_set_clock(ctr_t *ctr, int clock)
pit_ctr_set_clock(ctr_t *ctr, int clock, void *priv)
{
pit_ctr_set_clock_common(ctr, clock);
pit_ctr_set_clock_common(ctr, clock, priv);
}
void
@@ -516,7 +520,10 @@ pit_timer_over(void *priv)
dev->clock ^= 1;
for (uint8_t i = 0; i < 3; i++)
pit_ctr_set_clock_common(&dev->counters[i], dev->clock);
pit_ctr_set_clock_common(&dev->counters[i], dev->clock, dev);
if (dev->dev_timer != NULL)
dev->dev_timer(dev);
timer_advance_u64(&dev->callback_timer, PITCONST >> 1ULL);
}
@@ -528,7 +535,8 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
int t = (addr & 3);
ctr_t *ctr;
pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
pclog("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
switch (addr & 3) {
case 3: /* control */
@@ -544,7 +552,8 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
ctr_latch_count(&dev->counters[1]);
if (val & 8)
ctr_latch_count(&dev->counters[2]);
pit_log("PIT %i: Initiated readback command\n", t);
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
pclog("PIT %i: Initiated readback command\n", t);
}
if (!(val & 0x10)) {
if (val & 2)
@@ -561,7 +570,8 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
if (!(dev->ctrl & 0x30)) {
ctr_latch_count(ctr);
pit_log("PIT %i: Initiated latched read, %i bytes latched\n",
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
pclog("PIT %i: Initiated latched read, %i bytes latched\n",
t, ctr->latched);
} else {
ctr->ctrl = val;
@@ -571,14 +581,16 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
ctr->m &= 3;
ctr->null_count = 1;
ctr->bcd = (ctr->ctrl & 0x01);
ctr_set_out(ctr, !!ctr->m);
ctr_set_out(ctr, !!ctr->m, dev);
ctr->state = 0;
if (ctr->latched) {
pit_log("PIT %i: Reload while counter is latched\n", t);
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
pclog("PIT %i: Reload while counter is latched\n", t);
ctr->rl--;
}
pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out);
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
pclog("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out);
}
}
break;
@@ -595,30 +607,31 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
case 1:
ctr->l = val;
if (ctr->m == 0)
ctr_set_out(ctr, 0);
ctr_set_out(ctr, 0, dev);
ctr_load(ctr);
break;
case 2:
ctr->l = (val << 8);
if (ctr->m == 0)
ctr_set_out(ctr, 0);
ctr_set_out(ctr, 0, dev);
ctr_load(ctr);
break;
case 3:
case 0x83:
if (ctr->wm & 0x80) {
ctr->l = (ctr->l & 0x00ff) | (val << 8);
pit_log("PIT %i: Written high byte %02X, latch now %04X\n", t, val, ctr->l);
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
pclog("PIT %i: Written high byte %02X, latch now %04X\n", t, val, ctr->l);
ctr_load(ctr);
} else {
ctr->l = (ctr->l & 0xff00) | val;
pit_log("PIT %i: Written low byte %02X, latch now %04X\n", t, val, ctr->l);
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
pclog("PIT %i: Written low byte %02X, latch now %04X\n", t, val, ctr->l);
if (ctr->m == 0) {
ctr->state = 0;
ctr_set_out(ctr, 0);
ctr_set_out(ctr, 0, dev);
}
}
if (ctr->wm & 0x80)
ctr->wm &= ~0x80;
else
@@ -749,13 +762,14 @@ pit_read(uint16_t addr, void *priv)
break;
}
pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
if ((dev->flags & (PIT_8254 | PIT_EXT_IO)))
pclog("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
return ret;
}
void
pit_irq0_timer_ps2(int new_out, int old_out)
pit_irq0_timer_ps2(int new_out, int old_out, UNUSED(void *priv))
{
if (new_out && !old_out) {
picint(1);
@@ -770,21 +784,21 @@ pit_irq0_timer_ps2(int new_out, int old_out)
}
void
pit_refresh_timer_xt(int new_out, int old_out)
pit_refresh_timer_xt(int new_out, int old_out, UNUSED(void *priv))
{
if (new_out && !old_out)
dma_channel_read(0);
}
void
pit_refresh_timer_at(int new_out, int old_out)
pit_refresh_timer_at(int new_out, int old_out, UNUSED(void *priv))
{
if (refresh_at_enable && new_out && !old_out)
ppi.pb ^= 0x10;
}
void
pit_speaker_timer(int new_out, UNUSED(int old_out))
pit_speaker_timer(int new_out, UNUSED(int old_out), UNUSED(void *priv))
{
int l;
@@ -804,7 +818,7 @@ pit_speaker_timer(int new_out, UNUSED(int old_out))
}
void
pit_nmi_timer_ps2(int new_out, UNUSED(int old_out))
pit_nmi_timer_ps2(int new_out, UNUSED(int old_out), UNUSED(void *priv))
{
nmi = new_out;
@@ -882,6 +896,9 @@ pit_init(const device_t *info)
pit_read, NULL, NULL, pit_write, NULL, NULL, dev);
}
dev->dev_priv = NULL;
dev->dev_timer = NULL;
return dev;
}
@@ -899,6 +916,20 @@ const device_t i8253_device = {
.config = NULL
};
const device_t i8253_ext_io_device = {
.name = "Intel 8253 Programmable Interval Timer (External I/O)",
.internal_name = "i8253_ext_io",
.flags = DEVICE_ISA,
.local = PIT_8253 | PIT_EXT_IO,
.init = pit_init,
.close = pit_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t i8254_device = {
.name = "Intel 8254 Programmable Interval Timer",
.internal_name = "i8254",
@@ -956,7 +987,7 @@ const device_t i8254_ps2_device = {
};
pit_t *
pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out))
pit_common_init(int type, void (*out0)(int new_out, int old_out, void *priv), void (*out1)(int new_out, int old_out, void *priv))
{
void *pit;