WIP: PAS16.
See above, currently very WIP.
This commit is contained in:
117
src/pit.c
117
src/pit.c
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user