Commit c2655080670e25f13756d00ab1548a364b7ddd01
1 parent
dd4e27d8
more precise PIT gate emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@499 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
38 additions
and
5 deletions
vl.c
... | ... | @@ -1002,6 +1002,10 @@ static int pit_get_count(PITChannelState *s) |
1002 | 1002 | case 5: |
1003 | 1003 | counter = (s->count - d) & 0xffff; |
1004 | 1004 | break; |
1005 | + case 3: | |
1006 | + /* XXX: may be incorrect for odd counts */ | |
1007 | + counter = s->count - ((2 * d) % s->count); | |
1008 | + break; | |
1005 | 1009 | default: |
1006 | 1010 | counter = s->count - (d % s->count); |
1007 | 1011 | break; |
... | ... | @@ -1031,7 +1035,7 @@ static int pit_get_out(PITChannelState *s) |
1031 | 1035 | out = 0; |
1032 | 1036 | break; |
1033 | 1037 | case 3: |
1034 | - out = (d % s->count) < (s->count >> 1); | |
1038 | + out = (d % s->count) < ((s->count + 1) >> 1); | |
1035 | 1039 | break; |
1036 | 1040 | case 4: |
1037 | 1041 | case 5: |
... | ... | @@ -1074,7 +1078,7 @@ static int pit_get_out_edges(PITChannelState *s) |
1074 | 1078 | ret = d2 - d1; |
1075 | 1079 | break; |
1076 | 1080 | case 3: |
1077 | - v = s->count - (s->count >> 1); | |
1081 | + v = s->count - ((s->count + 1) >> 1); | |
1078 | 1082 | d1 = (d1 + v) / s->count; |
1079 | 1083 | d2 = (d2 + v) / s->count; |
1080 | 1084 | ret = d2 - d1; |
... | ... | @@ -1090,6 +1094,36 @@ static int pit_get_out_edges(PITChannelState *s) |
1090 | 1094 | return ret; |
1091 | 1095 | } |
1092 | 1096 | |
1097 | +/* val must be 0 or 1 */ | |
1098 | +static inline void pit_set_gate(PITChannelState *s, int val) | |
1099 | +{ | |
1100 | + switch(s->mode) { | |
1101 | + default: | |
1102 | + case 0: | |
1103 | + case 4: | |
1104 | + /* XXX: just disable/enable counting */ | |
1105 | + break; | |
1106 | + case 1: | |
1107 | + case 5: | |
1108 | + if (s->gate < val) { | |
1109 | + /* restart counting on rising edge */ | |
1110 | + s->count_load_time = cpu_get_ticks(); | |
1111 | + s->count_last_edge_check_time = s->count_load_time; | |
1112 | + } | |
1113 | + break; | |
1114 | + case 2: | |
1115 | + case 3: | |
1116 | + if (s->gate < val) { | |
1117 | + /* restart counting on rising edge */ | |
1118 | + s->count_load_time = cpu_get_ticks(); | |
1119 | + s->count_last_edge_check_time = s->count_load_time; | |
1120 | + } | |
1121 | + /* XXX: disable/enable counting */ | |
1122 | + break; | |
1123 | + } | |
1124 | + s->gate = val; | |
1125 | +} | |
1126 | + | |
1093 | 1127 | static inline void pit_load_count(PITChannelState *s, int val) |
1094 | 1128 | { |
1095 | 1129 | if (val == 0) |
... | ... | @@ -1185,7 +1219,7 @@ uint32_t pit_ioport_read(CPUX86State *env, uint32_t addr) |
1185 | 1219 | void speaker_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
1186 | 1220 | { |
1187 | 1221 | speaker_data_on = (val >> 1) & 1; |
1188 | - pit_channels[2].gate = val & 1; | |
1222 | + pit_set_gate(&pit_channels[2], val & 1); | |
1189 | 1223 | } |
1190 | 1224 | |
1191 | 1225 | uint32_t speaker_ioport_read(CPUX86State *env, uint32_t addr) |
... | ... | @@ -1463,7 +1497,6 @@ void serial_received_byte(SerialState *s, int ch) |
1463 | 1497 | serial_update_irq(); |
1464 | 1498 | break; |
1465 | 1499 | case 'd': |
1466 | - // tb_flush(); | |
1467 | 1500 | cpu_set_log(CPU_LOG_ALL); |
1468 | 1501 | break; |
1469 | 1502 | case TERM_ESCAPE: |
... | ... | @@ -2128,7 +2161,7 @@ uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) |
2128 | 2161 | KBDState *s = &kbd_state; |
2129 | 2162 | int val; |
2130 | 2163 | val = s->status; |
2131 | -#if defined(DEBUG_KBD) | |
2164 | +#if defined(DEBUG_KBD) && 0 | |
2132 | 2165 | printf("kbd: read status=0x%02x\n", val); |
2133 | 2166 | #endif |
2134 | 2167 | return val; | ... | ... |