Slight PIT fixes and optimizations and the forgotten updated Super I/O chip include.
This commit is contained in:
@@ -21,13 +21,25 @@
|
||||
typedef struct {
|
||||
uint8_t m, ctrl,
|
||||
read_status, latch,
|
||||
s1_det, l_det;
|
||||
s1_det, l_det,
|
||||
bcd, pad;
|
||||
|
||||
uint16_t rl;
|
||||
|
||||
int rm, wm, gate, out,
|
||||
newcount, count, using_timer, latched,
|
||||
state, null_count, do_read_status, clock;
|
||||
newcount, clock, using_timer, latched,
|
||||
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;
|
||||
|
||||
|
@@ -22,6 +22,7 @@ extern const device_t acc3221_device;
|
||||
extern const device_t f82c710_device;
|
||||
extern const device_t fdc37c661_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_ide_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_ide_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 prime3b_device;
|
||||
extern const device_t prime3b_ide_device;
|
||||
|
209
src/pit.c
209
src/pit.c
@@ -106,47 +106,26 @@ ctr_set_out(ctr_t *ctr, int out)
|
||||
static void
|
||||
ctr_decrease_count(ctr_t *ctr)
|
||||
{
|
||||
uint8_t units, tens, hundreds, thousands, myriads;
|
||||
int dec_cnt = 1;
|
||||
|
||||
if (ctr->ctrl & 0x01) {
|
||||
units = ctr->count & 0x0f;
|
||||
tens = (ctr->count >> 4) & 0x0f;
|
||||
hundreds = (ctr->count >> 8) & 0x0f;
|
||||
thousands = (ctr->count >> 12) & 0x0f;
|
||||
myriads = (ctr->count >> 16) & 0x0f;
|
||||
|
||||
dec_cnt -= units;
|
||||
units = (10 - dec_cnt % 10) % 10;
|
||||
|
||||
dec_cnt = (dec_cnt + 9) / 10; /* The +9 is so we get a carry if dec_cnt % 10 was not a 0. */
|
||||
if (dec_cnt <= tens)
|
||||
tens -= dec_cnt;
|
||||
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;
|
||||
if (ctr->bcd) {
|
||||
ctr->units--;
|
||||
if (ctr->units == 0xff) {
|
||||
ctr->units = 9;
|
||||
ctr->tens--;
|
||||
if (ctr->tens == 0xff) {
|
||||
ctr->tens = 9;
|
||||
ctr->hundreds--;
|
||||
if (ctr->hundreds == 0xff) {
|
||||
ctr->hundreds = 9;
|
||||
ctr->thousands--;
|
||||
if (ctr->thousands == 0xff) {
|
||||
ctr->thousands = 9;
|
||||
ctr->myriads--;
|
||||
if (ctr->myriads == 0xff)
|
||||
ctr->myriads = 0; /* 0 - 1 should wrap around to 9999. */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctr->count = (myriads << 16) | (thousands << 12) | (hundreds << 8) | (tens << 4) | units;
|
||||
} else
|
||||
ctr->count = (ctr->count - 1) & 0xffff;
|
||||
}
|
||||
@@ -167,14 +146,19 @@ ctr_load_count(ctr_t *ctr)
|
||||
static void
|
||||
ctr_tick(ctr_t *ctr)
|
||||
{
|
||||
uint8_t state = ctr->state;
|
||||
|
||||
if (state == 1) {
|
||||
/* This is true for all modes */
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ctr->m & 0x07) {
|
||||
case 0:
|
||||
/*Interrupt on terminal count*/
|
||||
switch (ctr->state) {
|
||||
case 1:
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 2;
|
||||
break;
|
||||
/* Interrupt on terminal count */
|
||||
switch (state) {
|
||||
case 2:
|
||||
if (ctr->gate && (ctr->count >= 1)) {
|
||||
ctr_decrease_count(ctr);
|
||||
@@ -190,8 +174,8 @@ ctr_tick(ctr_t *ctr)
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
/*Hardware retriggerable one-shot*/
|
||||
switch (ctr->state) {
|
||||
/* Hardware retriggerable one-shot */
|
||||
switch (state) {
|
||||
case 1:
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 2;
|
||||
@@ -212,13 +196,12 @@ ctr_tick(ctr_t *ctr)
|
||||
}
|
||||
break;
|
||||
case 2: case 6:
|
||||
/*Rate generator*/
|
||||
switch (ctr->state) {
|
||||
case 1: case 3:
|
||||
/* Rate generator */
|
||||
switch (state) {
|
||||
case 3:
|
||||
ctr_load_count(ctr);
|
||||
if (ctr->state == 3)
|
||||
ctr_set_out(ctr, 1);
|
||||
ctr->state = 2;
|
||||
ctr_set_out(ctr, 1);
|
||||
break;
|
||||
case 2:
|
||||
if (ctr->gate == 0)
|
||||
@@ -234,17 +217,18 @@ ctr_tick(ctr_t *ctr)
|
||||
}
|
||||
break;
|
||||
case 3: case 7:
|
||||
/*Square wave mode*/
|
||||
switch (ctr->state) {
|
||||
case 1:
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 2;
|
||||
break;
|
||||
/* Square wave mode */
|
||||
switch (state) {
|
||||
case 2:
|
||||
if (ctr->gate == 0)
|
||||
break;
|
||||
else if (ctr->count >= 0) {
|
||||
ctr->count -= (ctr->newcount ? 1 : 2);
|
||||
if (ctr->bcd) {
|
||||
ctr_decrease_count(ctr);
|
||||
if (!ctr->newcount)
|
||||
ctr_decrease_count(ctr);
|
||||
} else
|
||||
ctr->count -= (ctr->newcount ? 1 : 2);
|
||||
if (ctr->count < 0) {
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 3;
|
||||
@@ -257,7 +241,13 @@ ctr_tick(ctr_t *ctr)
|
||||
if (ctr->gate == 0)
|
||||
break;
|
||||
else if (ctr->count >= 0) {
|
||||
ctr->count -= (ctr->newcount ? 3 : 2);
|
||||
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);
|
||||
if (ctr->count < 0) {
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 2;
|
||||
@@ -269,17 +259,13 @@ ctr_tick(ctr_t *ctr)
|
||||
}
|
||||
break;
|
||||
case 4: case 5:
|
||||
/*Software triggered strobe*/
|
||||
/*Hardware triggered strobe*/
|
||||
/* Software triggered strobe */
|
||||
/* Hardware triggered strobe */
|
||||
if ((ctr->gate != 0) || (ctr->m != 4)) {
|
||||
switch(ctr->state) {
|
||||
switch(state) {
|
||||
case 0:
|
||||
ctr_decrease_count(ctr);
|
||||
break;
|
||||
case 1:
|
||||
ctr_load_count(ctr);
|
||||
ctr->state = 2;
|
||||
break;
|
||||
case 2:
|
||||
if (ctr->count >= 1) {
|
||||
ctr_decrease_count(ctr);
|
||||
@@ -319,18 +305,10 @@ ctr_clock(ctr_t *ctr)
|
||||
static void
|
||||
ctr_set_state_1(ctr_t *ctr)
|
||||
{
|
||||
switch (ctr->m) {
|
||||
case 0: case 4:
|
||||
/*Interrupt on terminal count*/
|
||||
ctr->state = 1;
|
||||
break;
|
||||
case 2: case 3:
|
||||
/*Rate generator*/
|
||||
/*Square wave mode*/
|
||||
if (ctr->state == 0)
|
||||
ctr->state = 1;
|
||||
break;
|
||||
}
|
||||
uint8_t mode = (ctr->m & 0x03);
|
||||
|
||||
if ((mode == 0) || ((mode > 1) && (ctr->state == 0)))
|
||||
ctr->state = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -427,32 +405,24 @@ void
|
||||
pit_ctr_set_gate(ctr_t *ctr, int gate)
|
||||
{
|
||||
int old = ctr->gate;
|
||||
uint8_t mode = ctr->m & 3;
|
||||
|
||||
ctr->gate = gate;
|
||||
|
||||
switch (ctr->m & 0x07) {
|
||||
switch (mode) {
|
||||
case 1: case 2: case 3: case 5: case 6: case 7:
|
||||
if (!old && gate) {
|
||||
/* Here we handle the rising edges. */
|
||||
switch (ctr->m) {
|
||||
case 1:
|
||||
ctr->state = 1;
|
||||
break;
|
||||
case 2: case 6:
|
||||
ctr->state = 3;
|
||||
break;
|
||||
case 3: case 5: case 7:
|
||||
if (mode & 1) {
|
||||
if (mode != 1)
|
||||
ctr_set_out(ctr, 1);
|
||||
ctr->state = 1;
|
||||
break;
|
||||
}
|
||||
ctr->state = 1;
|
||||
} else if (mode == 2)
|
||||
ctr->state = 3;
|
||||
} else if (old && !gate) {
|
||||
/* Here we handle the lowering edges. */
|
||||
switch (ctr->m) {
|
||||
case 2: case 3: case 6: case 7:
|
||||
ctr_set_out(ctr, 1);
|
||||
break;
|
||||
}
|
||||
if (mode & 2)
|
||||
ctr_set_out(ctr, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -477,13 +447,10 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock)
|
||||
ctr->s1_det = 1; /* Rising edge. */
|
||||
else if (old && !ctr->clock) {
|
||||
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_tick(ctr);
|
||||
ctr_tick(ctr);
|
||||
}
|
||||
}
|
||||
} else if (old && !ctr->clock)
|
||||
ctr_tick(ctr);
|
||||
@@ -536,26 +503,25 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
t = val >> 6;
|
||||
|
||||
if (t == 3) {
|
||||
if (!(dev->flags & PIT_8254))
|
||||
break;
|
||||
|
||||
/* This is 8254-only. */
|
||||
if (!(val & 0x20)) {
|
||||
if (val & 2)
|
||||
ctr_latch_count(&dev->counters[0]);
|
||||
if (val & 4)
|
||||
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 (!(val & 0x10)) {
|
||||
if (val & 2)
|
||||
ctr_latch_status(&dev->counters[0]);
|
||||
if (val & 4)
|
||||
ctr_latch_status(&dev->counters[1]);
|
||||
if (val & 8)
|
||||
ctr_latch_status(&dev->counters[2]);
|
||||
if (dev->flags & PIT_8254) {
|
||||
/* This is 8254-only. */
|
||||
if (!(val & 0x20)) {
|
||||
if (val & 2)
|
||||
ctr_latch_count(&dev->counters[0]);
|
||||
if (val & 4)
|
||||
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 (!(val & 0x10)) {
|
||||
if (val & 2)
|
||||
ctr_latch_status(&dev->counters[0]);
|
||||
if (val & 4)
|
||||
ctr_latch_status(&dev->counters[1]);
|
||||
if (val & 8)
|
||||
ctr_latch_status(&dev->counters[2]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dev->ctrl = val;
|
||||
@@ -572,6 +538,7 @@ pit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
if (ctr->m > 5)
|
||||
ctr->m &= 3;
|
||||
ctr->null_count = 1;
|
||||
ctr->bcd = (ctr->ctrl & 0x01);
|
||||
ctr_set_out(ctr, !!ctr->m);
|
||||
ctr->state = 0;
|
||||
if (ctr->latched) {
|
||||
|
Reference in New Issue
Block a user