aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-01-04 16:07:06 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-01-04 16:07:06 +0000
commitc2655080670e25f13756d00ab1548a364b7ddd01 (patch)
treee9d6ecaa60e7e0bc2acd5674ee36c09ad4f21017
parentdd4e27d8101425b807df672df754eaa242c64351 (diff)
more precise PIT gate emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@499 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--vl.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/vl.c b/vl.c
index 830b5462d5..9b1a3fcc7b 100644
--- a/vl.c
+++ b/vl.c
@@ -1002,6 +1002,10 @@ static int pit_get_count(PITChannelState *s)
case 5:
counter = (s->count - d) & 0xffff;
break;
+ case 3:
+ /* XXX: may be incorrect for odd counts */
+ counter = s->count - ((2 * d) % s->count);
+ break;
default:
counter = s->count - (d % s->count);
break;
@@ -1031,7 +1035,7 @@ static int pit_get_out(PITChannelState *s)
out = 0;
break;
case 3:
- out = (d % s->count) < (s->count >> 1);
+ out = (d % s->count) < ((s->count + 1) >> 1);
break;
case 4:
case 5:
@@ -1074,7 +1078,7 @@ static int pit_get_out_edges(PITChannelState *s)
ret = d2 - d1;
break;
case 3:
- v = s->count - (s->count >> 1);
+ v = s->count - ((s->count + 1) >> 1);
d1 = (d1 + v) / s->count;
d2 = (d2 + v) / s->count;
ret = d2 - d1;
@@ -1090,6 +1094,36 @@ static int pit_get_out_edges(PITChannelState *s)
return ret;
}
+/* val must be 0 or 1 */
+static inline void pit_set_gate(PITChannelState *s, int val)
+{
+ switch(s->mode) {
+ default:
+ case 0:
+ case 4:
+ /* XXX: just disable/enable counting */
+ break;
+ case 1:
+ case 5:
+ if (s->gate < val) {
+ /* restart counting on rising edge */
+ s->count_load_time = cpu_get_ticks();
+ s->count_last_edge_check_time = s->count_load_time;
+ }
+ break;
+ case 2:
+ case 3:
+ if (s->gate < val) {
+ /* restart counting on rising edge */
+ s->count_load_time = cpu_get_ticks();
+ s->count_last_edge_check_time = s->count_load_time;
+ }
+ /* XXX: disable/enable counting */
+ break;
+ }
+ s->gate = val;
+}
+
static inline void pit_load_count(PITChannelState *s, int val)
{
if (val == 0)
@@ -1185,7 +1219,7 @@ uint32_t pit_ioport_read(CPUX86State *env, uint32_t addr)
void speaker_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
{
speaker_data_on = (val >> 1) & 1;
- pit_channels[2].gate = val & 1;
+ pit_set_gate(&pit_channels[2], val & 1);
}
uint32_t speaker_ioport_read(CPUX86State *env, uint32_t addr)
@@ -1463,7 +1497,6 @@ void serial_received_byte(SerialState *s, int ch)
serial_update_irq();
break;
case 'd':
- // tb_flush();
cpu_set_log(CPU_LOG_ALL);
break;
case TERM_ESCAPE:
@@ -2128,7 +2161,7 @@ uint32_t kbd_read_status(CPUX86State *env, uint32_t addr)
KBDState *s = &kbd_state;
int val;
val = s->status;
-#if defined(DEBUG_KBD)
+#if defined(DEBUG_KBD) && 0
printf("kbd: read status=0x%02x\n", val);
#endif
return val;