Slight PIT fixes and optimizations and the forgotten updated Super I/O chip include.

This commit is contained in:
OBattler
2021-04-06 07:35:03 +02:00
parent edace2282a
commit 4dae3c7338
3 changed files with 106 additions and 125 deletions

View File

@@ -21,13 +21,25 @@
typedef struct { typedef struct {
uint8_t m, ctrl, uint8_t m, ctrl,
read_status, latch, read_status, latch,
s1_det, l_det; s1_det, l_det,
bcd, pad;
uint16_t rl; uint16_t rl;
int rm, wm, gate, out, int rm, wm, gate, out,
newcount, count, using_timer, latched, newcount, clock, using_timer, latched,
state, null_count, do_read_status, clock; state, null_count, do_read_status;
union {
int count;
struct {
int units :4;
int tens :4;
int hundreds :4;
int thousands :4;
int myriads :4;
};
};
uint32_t l; uint32_t l;

View File

@@ -22,6 +22,7 @@ extern const device_t acc3221_device;
extern const device_t f82c710_device; extern const device_t f82c710_device;
extern const device_t fdc37c661_device; extern const device_t fdc37c661_device;
extern const device_t fdc37c663_device; extern const device_t fdc37c663_device;
extern const device_t fdc37c663_ide_device;
extern const device_t fdc37c665_device; extern const device_t fdc37c665_device;
extern const device_t fdc37c665_ide_device; extern const device_t fdc37c665_ide_device;
extern const device_t fdc37c666_device; extern const device_t fdc37c666_device;
@@ -48,7 +49,8 @@ extern const device_t pc87310_ide_device;
extern const device_t pc87311_device; extern const device_t pc87311_device;
extern const device_t pc87311_ide_device; extern const device_t pc87311_ide_device;
extern const device_t pc87332_device; extern const device_t pc87332_device;
extern const device_t pc87332_ps1_device; extern const device_t pc87332_398_device;
extern const device_t pc87332_398_ide_device;
extern const device_t pc97307_device; extern const device_t pc97307_device;
extern const device_t prime3b_device; extern const device_t prime3b_device;
extern const device_t prime3b_ide_device; extern const device_t prime3b_ide_device;

163
src/pit.c
View File

@@ -106,47 +106,26 @@ ctr_set_out(ctr_t *ctr, int out)
static void static void
ctr_decrease_count(ctr_t *ctr) ctr_decrease_count(ctr_t *ctr)
{ {
uint8_t units, tens, hundreds, thousands, myriads; if (ctr->bcd) {
int dec_cnt = 1; ctr->units--;
if (ctr->units == 0xff) {
if (ctr->ctrl & 0x01) { ctr->units = 9;
units = ctr->count & 0x0f; ctr->tens--;
tens = (ctr->count >> 4) & 0x0f; if (ctr->tens == 0xff) {
hundreds = (ctr->count >> 8) & 0x0f; ctr->tens = 9;
thousands = (ctr->count >> 12) & 0x0f; ctr->hundreds--;
myriads = (ctr->count >> 16) & 0x0f; if (ctr->hundreds == 0xff) {
ctr->hundreds = 9;
dec_cnt -= units; ctr->thousands--;
units = (10 - dec_cnt % 10) % 10; if (ctr->thousands == 0xff) {
ctr->thousands = 9;
dec_cnt = (dec_cnt + 9) / 10; /* The +9 is so we get a carry if dec_cnt % 10 was not a 0. */ ctr->myriads--;
if (dec_cnt <= tens) if (ctr->myriads == 0xff)
tens -= dec_cnt; ctr->myriads = 0; /* 0 - 1 should wrap around to 9999. */
else { }
dec_cnt -= tens;
tens = (10 - dec_cnt % 10) % 10;
dec_cnt = (dec_cnt + 9) / 10;
if (dec_cnt <= hundreds)
hundreds -= dec_cnt;
else {
dec_cnt -= hundreds;
hundreds = (10 - dec_cnt % 10) % 10;
dec_cnt = (dec_cnt + 9) / 10;
if (dec_cnt <= thousands)
thousands -= dec_cnt;
else {
dec_cnt -= thousands;
thousands = (10 - dec_cnt % 10) % 10;
dec_cnt = (dec_cnt + 9) / 10;
myriads = (10 + myriads - dec_cnt % 10) % 10;
} }
} }
} }
ctr->count = (myriads << 16) | (thousands << 12) | (hundreds << 8) | (tens << 4) | units;
} else } else
ctr->count = (ctr->count - 1) & 0xffff; ctr->count = (ctr->count - 1) & 0xffff;
} }
@@ -167,14 +146,19 @@ ctr_load_count(ctr_t *ctr)
static void static void
ctr_tick(ctr_t *ctr) ctr_tick(ctr_t *ctr)
{ {
switch(ctr->m & 0x07) { uint8_t state = ctr->state;
case 0:
/*Interrupt on terminal count*/ if (state == 1) {
switch (ctr->state) { /* This is true for all modes */
case 1:
ctr_load_count(ctr); ctr_load_count(ctr);
ctr->state = 2; ctr->state = 2;
break; return;
}
switch(ctr->m & 0x07) {
case 0:
/* Interrupt on terminal count */
switch (state) {
case 2: case 2:
if (ctr->gate && (ctr->count >= 1)) { if (ctr->gate && (ctr->count >= 1)) {
ctr_decrease_count(ctr); ctr_decrease_count(ctr);
@@ -190,8 +174,8 @@ ctr_tick(ctr_t *ctr)
} }
break; break;
case 1: case 1:
/*Hardware retriggerable one-shot*/ /* Hardware retriggerable one-shot */
switch (ctr->state) { switch (state) {
case 1: case 1:
ctr_load_count(ctr); ctr_load_count(ctr);
ctr->state = 2; ctr->state = 2;
@@ -212,13 +196,12 @@ ctr_tick(ctr_t *ctr)
} }
break; break;
case 2: case 6: case 2: case 6:
/*Rate generator*/ /* Rate generator */
switch (ctr->state) { switch (state) {
case 1: case 3: case 3:
ctr_load_count(ctr); ctr_load_count(ctr);
if (ctr->state == 3)
ctr_set_out(ctr, 1);
ctr->state = 2; ctr->state = 2;
ctr_set_out(ctr, 1);
break; break;
case 2: case 2:
if (ctr->gate == 0) if (ctr->gate == 0)
@@ -234,16 +217,17 @@ ctr_tick(ctr_t *ctr)
} }
break; break;
case 3: case 7: case 3: case 7:
/*Square wave mode*/ /* Square wave mode */
switch (ctr->state) { switch (state) {
case 1:
ctr_load_count(ctr);
ctr->state = 2;
break;
case 2: case 2:
if (ctr->gate == 0) if (ctr->gate == 0)
break; break;
else if (ctr->count >= 0) { else if (ctr->count >= 0) {
if (ctr->bcd) {
ctr_decrease_count(ctr);
if (!ctr->newcount)
ctr_decrease_count(ctr);
} else
ctr->count -= (ctr->newcount ? 1 : 2); ctr->count -= (ctr->newcount ? 1 : 2);
if (ctr->count < 0) { if (ctr->count < 0) {
ctr_load_count(ctr); ctr_load_count(ctr);
@@ -257,6 +241,12 @@ ctr_tick(ctr_t *ctr)
if (ctr->gate == 0) if (ctr->gate == 0)
break; break;
else if (ctr->count >= 0) { else if (ctr->count >= 0) {
if (ctr->bcd) {
ctr_decrease_count(ctr);
ctr_decrease_count(ctr);
if (ctr->newcount)
ctr_decrease_count(ctr);
} else
ctr->count -= (ctr->newcount ? 3 : 2); ctr->count -= (ctr->newcount ? 3 : 2);
if (ctr->count < 0) { if (ctr->count < 0) {
ctr_load_count(ctr); ctr_load_count(ctr);
@@ -269,17 +259,13 @@ ctr_tick(ctr_t *ctr)
} }
break; break;
case 4: case 5: case 4: case 5:
/*Software triggered strobe*/ /* Software triggered strobe */
/*Hardware triggered strobe*/ /* Hardware triggered strobe */
if ((ctr->gate != 0) || (ctr->m != 4)) { if ((ctr->gate != 0) || (ctr->m != 4)) {
switch(ctr->state) { switch(state) {
case 0: case 0:
ctr_decrease_count(ctr); ctr_decrease_count(ctr);
break; break;
case 1:
ctr_load_count(ctr);
ctr->state = 2;
break;
case 2: case 2:
if (ctr->count >= 1) { if (ctr->count >= 1) {
ctr_decrease_count(ctr); ctr_decrease_count(ctr);
@@ -319,18 +305,10 @@ ctr_clock(ctr_t *ctr)
static void static void
ctr_set_state_1(ctr_t *ctr) ctr_set_state_1(ctr_t *ctr)
{ {
switch (ctr->m) { uint8_t mode = (ctr->m & 0x03);
case 0: case 4:
/*Interrupt on terminal count*/ if ((mode == 0) || ((mode > 1) && (ctr->state == 0)))
ctr->state = 1; ctr->state = 1;
break;
case 2: case 3:
/*Rate generator*/
/*Square wave mode*/
if (ctr->state == 0)
ctr->state = 1;
break;
}
} }
@@ -427,32 +405,24 @@ void
pit_ctr_set_gate(ctr_t *ctr, int gate) pit_ctr_set_gate(ctr_t *ctr, int gate)
{ {
int old = ctr->gate; int old = ctr->gate;
uint8_t mode = ctr->m & 3;
ctr->gate = gate; ctr->gate = gate;
switch (ctr->m & 0x07) { switch (mode) {
case 1: case 2: case 3: case 5: case 6: case 7: case 1: case 2: case 3: case 5: case 6: case 7:
if (!old && gate) { if (!old && gate) {
/* Here we handle the rising edges. */ /* Here we handle the rising edges. */
switch (ctr->m) { if (mode & 1) {
case 1: if (mode != 1)
ctr->state = 1;
break;
case 2: case 6:
ctr->state = 3;
break;
case 3: case 5: case 7:
ctr_set_out(ctr, 1); ctr_set_out(ctr, 1);
ctr->state = 1; ctr->state = 1;
break; } else if (mode == 2)
} ctr->state = 3;
} else if (old && !gate) { } else if (old && !gate) {
/* Here we handle the lowering edges. */ /* Here we handle the lowering edges. */
switch (ctr->m) { if (mode & 2)
case 2: case 3: case 6: case 7:
ctr_set_out(ctr, 1); ctr_set_out(ctr, 1);
break;
}
} }
break; break;
} }
@@ -477,14 +447,11 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock)
ctr->s1_det = 1; /* Rising edge. */ ctr->s1_det = 1; /* Rising edge. */
else if (old && !ctr->clock) { else if (old && !ctr->clock) {
ctr->s1_det++; /* Falling edge. */ ctr->s1_det++; /* Falling edge. */
if (ctr->s1_det != 2) if (ctr->s1_det >= 2) {
ctr->s1_det = 0;
}
if (ctr->s1_det == 2) {
ctr->s1_det = 0; ctr->s1_det = 0;
ctr_tick(ctr); ctr_tick(ctr);
} }
}
} else if (old && !ctr->clock) } else if (old && !ctr->clock)
ctr_tick(ctr); ctr_tick(ctr);
} }
@@ -536,9 +503,7 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
t = val >> 6; t = val >> 6;
if (t == 3) { if (t == 3) {
if (!(dev->flags & PIT_8254)) if (dev->flags & PIT_8254) {
break;
/* This is 8254-only. */ /* This is 8254-only. */
if (!(val & 0x20)) { if (!(val & 0x20)) {
if (val & 2) if (val & 2)
@@ -557,6 +522,7 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
if (val & 8) if (val & 8)
ctr_latch_status(&dev->counters[2]); ctr_latch_status(&dev->counters[2]);
} }
}
} else { } else {
dev->ctrl = val; dev->ctrl = val;
ctr = &dev->counters[t]; ctr = &dev->counters[t];
@@ -572,6 +538,7 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
if (ctr->m > 5) if (ctr->m > 5)
ctr->m &= 3; ctr->m &= 3;
ctr->null_count = 1; ctr->null_count = 1;
ctr->bcd = (ctr->ctrl & 0x01);
ctr_set_out(ctr, !!ctr->m); ctr_set_out(ctr, !!ctr->m);
ctr->state = 0; ctr->state = 0;
if (ctr->latched) { if (ctr->latched) {