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 {
|
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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
163
src/pit.c
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user