Commit ec844b96c083340a4c04849c2c1cdc09e85e0595
1 parent
f72e8ff4
pit fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@781 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
175 additions
and
88 deletions
Changelog
| @@ -3,6 +3,7 @@ version 0.5.5: | @@ -3,6 +3,7 @@ version 0.5.5: | ||
| 3 | - SDL full screen support (initial patch by malc) | 3 | - SDL full screen support (initial patch by malc) |
| 4 | - VGA support on PowerPC PREP | 4 | - VGA support on PowerPC PREP |
| 5 | - VBE fixes (Matthew Mastracci) | 5 | - VBE fixes (Matthew Mastracci) |
| 6 | + - PIT fixes (aka Win98 hardware probe and timer bug) | ||
| 6 | 7 | ||
| 7 | version 0.5.4: | 8 | version 0.5.4: |
| 8 | 9 |
hw/i8254.c
| @@ -25,14 +25,36 @@ | @@ -25,14 +25,36 @@ | ||
| 25 | 25 | ||
| 26 | //#define DEBUG_PIT | 26 | //#define DEBUG_PIT |
| 27 | 27 | ||
| 28 | -#define RW_STATE_LSB 0 | ||
| 29 | -#define RW_STATE_MSB 1 | ||
| 30 | -#define RW_STATE_WORD0 2 | ||
| 31 | -#define RW_STATE_WORD1 3 | ||
| 32 | -#define RW_STATE_LATCHED_WORD0 4 | ||
| 33 | -#define RW_STATE_LATCHED_WORD1 5 | 28 | +#define RW_STATE_LSB 1 |
| 29 | +#define RW_STATE_MSB 2 | ||
| 30 | +#define RW_STATE_WORD0 3 | ||
| 31 | +#define RW_STATE_WORD1 4 | ||
| 34 | 32 | ||
| 35 | -PITChannelState pit_channels[3]; | 33 | +typedef struct PITChannelState { |
| 34 | + int count; /* can be 65536 */ | ||
| 35 | + uint16_t latched_count; | ||
| 36 | + uint8_t count_latched; | ||
| 37 | + uint8_t status_latched; | ||
| 38 | + uint8_t status; | ||
| 39 | + uint8_t read_state; | ||
| 40 | + uint8_t write_state; | ||
| 41 | + uint8_t write_latch; | ||
| 42 | + uint8_t rw_mode; | ||
| 43 | + uint8_t mode; | ||
| 44 | + uint8_t bcd; /* not supported */ | ||
| 45 | + uint8_t gate; /* timer start */ | ||
| 46 | + int64_t count_load_time; | ||
| 47 | + /* irq handling */ | ||
| 48 | + int64_t next_transition_time; | ||
| 49 | + QEMUTimer *irq_timer; | ||
| 50 | + int irq; | ||
| 51 | +} PITChannelState; | ||
| 52 | + | ||
| 53 | +struct PITState { | ||
| 54 | + PITChannelState channels[3]; | ||
| 55 | +}; | ||
| 56 | + | ||
| 57 | +static PITState pit_state; | ||
| 36 | 58 | ||
| 37 | static void pit_irq_timer_update(PITChannelState *s, int64_t current_time); | 59 | static void pit_irq_timer_update(PITChannelState *s, int64_t current_time); |
| 38 | 60 | ||
| @@ -61,7 +83,7 @@ static int pit_get_count(PITChannelState *s) | @@ -61,7 +83,7 @@ static int pit_get_count(PITChannelState *s) | ||
| 61 | } | 83 | } |
| 62 | 84 | ||
| 63 | /* get pit output bit */ | 85 | /* get pit output bit */ |
| 64 | -int pit_get_out(PITChannelState *s, int64_t current_time) | 86 | +static int pit_get_out1(PITChannelState *s, int64_t current_time) |
| 65 | { | 87 | { |
| 66 | uint64_t d; | 88 | uint64_t d; |
| 67 | int out; | 89 | int out; |
| @@ -92,6 +114,12 @@ int pit_get_out(PITChannelState *s, int64_t current_time) | @@ -92,6 +114,12 @@ int pit_get_out(PITChannelState *s, int64_t current_time) | ||
| 92 | return out; | 114 | return out; |
| 93 | } | 115 | } |
| 94 | 116 | ||
| 117 | +int pit_get_out(PITState *pit, int channel, int64_t current_time) | ||
| 118 | +{ | ||
| 119 | + PITChannelState *s = &pit->channels[channel]; | ||
| 120 | + return pit_get_out1(s, current_time); | ||
| 121 | +} | ||
| 122 | + | ||
| 95 | /* return -1 if no transition will occur. */ | 123 | /* return -1 if no transition will occur. */ |
| 96 | static int64_t pit_get_next_transition_time(PITChannelState *s, | 124 | static int64_t pit_get_next_transition_time(PITChannelState *s, |
| 97 | int64_t current_time) | 125 | int64_t current_time) |
| @@ -144,8 +172,10 @@ static int64_t pit_get_next_transition_time(PITChannelState *s, | @@ -144,8 +172,10 @@ static int64_t pit_get_next_transition_time(PITChannelState *s, | ||
| 144 | } | 172 | } |
| 145 | 173 | ||
| 146 | /* val must be 0 or 1 */ | 174 | /* val must be 0 or 1 */ |
| 147 | -void pit_set_gate(PITChannelState *s, int val) | 175 | +void pit_set_gate(PITState *pit, int channel, int val) |
| 148 | { | 176 | { |
| 177 | + PITChannelState *s = &pit->channels[channel]; | ||
| 178 | + | ||
| 149 | switch(s->mode) { | 179 | switch(s->mode) { |
| 150 | default: | 180 | default: |
| 151 | case 0: | 181 | case 0: |
| @@ -173,6 +203,12 @@ void pit_set_gate(PITChannelState *s, int val) | @@ -173,6 +203,12 @@ void pit_set_gate(PITChannelState *s, int val) | ||
| 173 | s->gate = val; | 203 | s->gate = val; |
| 174 | } | 204 | } |
| 175 | 205 | ||
| 206 | +int pit_get_gate(PITState *pit, int channel) | ||
| 207 | +{ | ||
| 208 | + PITChannelState *s = &pit->channels[channel]; | ||
| 209 | + return s->gate; | ||
| 210 | +} | ||
| 211 | + | ||
| 176 | static inline void pit_load_count(PITChannelState *s, int val) | 212 | static inline void pit_load_count(PITChannelState *s, int val) |
| 177 | { | 213 | { |
| 178 | if (val == 0) | 214 | if (val == 0) |
| @@ -182,33 +218,62 @@ static inline void pit_load_count(PITChannelState *s, int val) | @@ -182,33 +218,62 @@ static inline void pit_load_count(PITChannelState *s, int val) | ||
| 182 | pit_irq_timer_update(s, s->count_load_time); | 218 | pit_irq_timer_update(s, s->count_load_time); |
| 183 | } | 219 | } |
| 184 | 220 | ||
| 221 | +/* if already latched, do not latch again */ | ||
| 222 | +static void pit_latch_count(PITChannelState *s) | ||
| 223 | +{ | ||
| 224 | + if (!s->count_latched) { | ||
| 225 | + s->latched_count = pit_get_count(s); | ||
| 226 | + s->count_latched = s->rw_mode; | ||
| 227 | + } | ||
| 228 | +} | ||
| 229 | + | ||
| 185 | static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) | 230 | static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 186 | { | 231 | { |
| 232 | + PITState *pit = opaque; | ||
| 187 | int channel, access; | 233 | int channel, access; |
| 188 | PITChannelState *s; | 234 | PITChannelState *s; |
| 189 | 235 | ||
| 190 | addr &= 3; | 236 | addr &= 3; |
| 191 | if (addr == 3) { | 237 | if (addr == 3) { |
| 192 | channel = val >> 6; | 238 | channel = val >> 6; |
| 193 | - if (channel == 3) | ||
| 194 | - return; | ||
| 195 | - s = &pit_channels[channel]; | ||
| 196 | - access = (val >> 4) & 3; | ||
| 197 | - switch(access) { | ||
| 198 | - case 0: | ||
| 199 | - s->latched_count = pit_get_count(s); | ||
| 200 | - s->rw_state = RW_STATE_LATCHED_WORD0; | ||
| 201 | - break; | ||
| 202 | - default: | ||
| 203 | - s->mode = (val >> 1) & 7; | ||
| 204 | - s->bcd = val & 1; | ||
| 205 | - s->rw_state = access - 1 + RW_STATE_LSB; | ||
| 206 | - /* XXX: update irq timer ? */ | ||
| 207 | - break; | 239 | + if (channel == 3) { |
| 240 | + /* read back command */ | ||
| 241 | + for(channel = 0; channel < 3; channel++) { | ||
| 242 | + s = &pit->channels[channel]; | ||
| 243 | + if (val & (2 << channel)) { | ||
| 244 | + if (!(val & 0x20)) { | ||
| 245 | + pit_latch_count(s); | ||
| 246 | + } | ||
| 247 | + if (!(val & 0x10) && !s->status_latched) { | ||
| 248 | + /* status latch */ | ||
| 249 | + /* XXX: add BCD and null count */ | ||
| 250 | + s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) | | ||
| 251 | + (s->rw_mode << 4) | | ||
| 252 | + (s->mode << 1) | | ||
| 253 | + s->bcd; | ||
| 254 | + s->status_latched = 1; | ||
| 255 | + } | ||
| 256 | + } | ||
| 257 | + } | ||
| 258 | + } else { | ||
| 259 | + s = &pit->channels[channel]; | ||
| 260 | + access = (val >> 4) & 3; | ||
| 261 | + if (access == 0) { | ||
| 262 | + pit_latch_count(s); | ||
| 263 | + } else { | ||
| 264 | + s->rw_mode = access; | ||
| 265 | + s->read_state = access; | ||
| 266 | + s->write_state = access; | ||
| 267 | + | ||
| 268 | + s->mode = (val >> 1) & 7; | ||
| 269 | + s->bcd = val & 1; | ||
| 270 | + /* XXX: update irq timer ? */ | ||
| 271 | + } | ||
| 208 | } | 272 | } |
| 209 | } else { | 273 | } else { |
| 210 | - s = &pit_channels[addr]; | ||
| 211 | - switch(s->rw_state) { | 274 | + s = &pit->channels[addr]; |
| 275 | + switch(s->write_state) { | ||
| 276 | + default: | ||
| 212 | case RW_STATE_LSB: | 277 | case RW_STATE_LSB: |
| 213 | pit_load_count(s, val); | 278 | pit_load_count(s, val); |
| 214 | break; | 279 | break; |
| @@ -216,13 +281,12 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -216,13 +281,12 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
| 216 | pit_load_count(s, val << 8); | 281 | pit_load_count(s, val << 8); |
| 217 | break; | 282 | break; |
| 218 | case RW_STATE_WORD0: | 283 | case RW_STATE_WORD0: |
| 284 | + s->write_latch = val; | ||
| 285 | + s->write_state = RW_STATE_WORD1; | ||
| 286 | + break; | ||
| 219 | case RW_STATE_WORD1: | 287 | case RW_STATE_WORD1: |
| 220 | - if (s->rw_state & 1) { | ||
| 221 | - pit_load_count(s, (s->latched_count & 0xff) | (val << 8)); | ||
| 222 | - } else { | ||
| 223 | - s->latched_count = val; | ||
| 224 | - } | ||
| 225 | - s->rw_state ^= 1; | 288 | + pit_load_count(s, s->write_latch | (val << 8)); |
| 289 | + s->write_state = RW_STATE_WORD0; | ||
| 226 | break; | 290 | break; |
| 227 | } | 291 | } |
| 228 | } | 292 | } |
| @@ -230,33 +294,53 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -230,33 +294,53 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
| 230 | 294 | ||
| 231 | static uint32_t pit_ioport_read(void *opaque, uint32_t addr) | 295 | static uint32_t pit_ioport_read(void *opaque, uint32_t addr) |
| 232 | { | 296 | { |
| 297 | + PITState *pit = opaque; | ||
| 233 | int ret, count; | 298 | int ret, count; |
| 234 | PITChannelState *s; | 299 | PITChannelState *s; |
| 235 | 300 | ||
| 236 | addr &= 3; | 301 | addr &= 3; |
| 237 | - s = &pit_channels[addr]; | ||
| 238 | - switch(s->rw_state) { | ||
| 239 | - case RW_STATE_LSB: | ||
| 240 | - case RW_STATE_MSB: | ||
| 241 | - case RW_STATE_WORD0: | ||
| 242 | - case RW_STATE_WORD1: | ||
| 243 | - count = pit_get_count(s); | ||
| 244 | - if (s->rw_state & 1) | ||
| 245 | - ret = (count >> 8) & 0xff; | ||
| 246 | - else | ||
| 247 | - ret = count & 0xff; | ||
| 248 | - if (s->rw_state & 2) | ||
| 249 | - s->rw_state ^= 1; | ||
| 250 | - break; | ||
| 251 | - default: | ||
| 252 | - case RW_STATE_LATCHED_WORD0: | ||
| 253 | - case RW_STATE_LATCHED_WORD1: | ||
| 254 | - if (s->rw_state & 1) | 302 | + s = &pit->channels[addr]; |
| 303 | + if (s->status_latched) { | ||
| 304 | + s->status_latched = 0; | ||
| 305 | + ret = s->status; | ||
| 306 | + } else if (s->count_latched) { | ||
| 307 | + switch(s->count_latched) { | ||
| 308 | + default: | ||
| 309 | + case RW_STATE_LSB: | ||
| 310 | + ret = s->latched_count & 0xff; | ||
| 311 | + s->count_latched = 0; | ||
| 312 | + break; | ||
| 313 | + case RW_STATE_MSB: | ||
| 255 | ret = s->latched_count >> 8; | 314 | ret = s->latched_count >> 8; |
| 256 | - else | 315 | + s->count_latched = 0; |
| 316 | + break; | ||
| 317 | + case RW_STATE_WORD0: | ||
| 257 | ret = s->latched_count & 0xff; | 318 | ret = s->latched_count & 0xff; |
| 258 | - s->rw_state ^= 1; | ||
| 259 | - break; | 319 | + s->count_latched = RW_STATE_MSB; |
| 320 | + break; | ||
| 321 | + } | ||
| 322 | + } else { | ||
| 323 | + switch(s->read_state) { | ||
| 324 | + default: | ||
| 325 | + case RW_STATE_LSB: | ||
| 326 | + count = pit_get_count(s); | ||
| 327 | + ret = count & 0xff; | ||
| 328 | + break; | ||
| 329 | + case RW_STATE_MSB: | ||
| 330 | + count = pit_get_count(s); | ||
| 331 | + ret = (count >> 8) & 0xff; | ||
| 332 | + break; | ||
| 333 | + case RW_STATE_WORD0: | ||
| 334 | + count = pit_get_count(s); | ||
| 335 | + ret = count & 0xff; | ||
| 336 | + s->read_state = RW_STATE_WORD1; | ||
| 337 | + break; | ||
| 338 | + case RW_STATE_WORD1: | ||
| 339 | + count = pit_get_count(s); | ||
| 340 | + ret = (count >> 8) & 0xff; | ||
| 341 | + s->read_state = RW_STATE_WORD0; | ||
| 342 | + break; | ||
| 343 | + } | ||
| 260 | } | 344 | } |
| 261 | return ret; | 345 | return ret; |
| 262 | } | 346 | } |
| @@ -269,7 +353,7 @@ static void pit_irq_timer_update(PITChannelState *s, int64_t current_time) | @@ -269,7 +353,7 @@ static void pit_irq_timer_update(PITChannelState *s, int64_t current_time) | ||
| 269 | if (!s->irq_timer) | 353 | if (!s->irq_timer) |
| 270 | return; | 354 | return; |
| 271 | expire_time = pit_get_next_transition_time(s, current_time); | 355 | expire_time = pit_get_next_transition_time(s, current_time); |
| 272 | - irq_level = pit_get_out(s, current_time); | 356 | + irq_level = pit_get_out1(s, current_time); |
| 273 | pic_set_irq(s->irq, irq_level); | 357 | pic_set_irq(s->irq, irq_level); |
| 274 | #ifdef DEBUG_PIT | 358 | #ifdef DEBUG_PIT |
| 275 | printf("irq_level=%d next_delay=%f\n", | 359 | printf("irq_level=%d next_delay=%f\n", |
| @@ -292,14 +376,21 @@ static void pit_irq_timer(void *opaque) | @@ -292,14 +376,21 @@ static void pit_irq_timer(void *opaque) | ||
| 292 | 376 | ||
| 293 | static void pit_save(QEMUFile *f, void *opaque) | 377 | static void pit_save(QEMUFile *f, void *opaque) |
| 294 | { | 378 | { |
| 379 | + PITState *pit = opaque; | ||
| 295 | PITChannelState *s; | 380 | PITChannelState *s; |
| 296 | int i; | 381 | int i; |
| 297 | 382 | ||
| 298 | for(i = 0; i < 3; i++) { | 383 | for(i = 0; i < 3; i++) { |
| 299 | - s = &pit_channels[i]; | 384 | + s = &pit->channels[i]; |
| 300 | qemu_put_be32s(f, &s->count); | 385 | qemu_put_be32s(f, &s->count); |
| 301 | qemu_put_be16s(f, &s->latched_count); | 386 | qemu_put_be16s(f, &s->latched_count); |
| 302 | - qemu_put_8s(f, &s->rw_state); | 387 | + qemu_put_8s(f, &s->count_latched); |
| 388 | + qemu_put_8s(f, &s->status_latched); | ||
| 389 | + qemu_put_8s(f, &s->status); | ||
| 390 | + qemu_put_8s(f, &s->read_state); | ||
| 391 | + qemu_put_8s(f, &s->write_state); | ||
| 392 | + qemu_put_8s(f, &s->write_latch); | ||
| 393 | + qemu_put_8s(f, &s->rw_mode); | ||
| 303 | qemu_put_8s(f, &s->mode); | 394 | qemu_put_8s(f, &s->mode); |
| 304 | qemu_put_8s(f, &s->bcd); | 395 | qemu_put_8s(f, &s->bcd); |
| 305 | qemu_put_8s(f, &s->gate); | 396 | qemu_put_8s(f, &s->gate); |
| @@ -313,6 +404,7 @@ static void pit_save(QEMUFile *f, void *opaque) | @@ -313,6 +404,7 @@ static void pit_save(QEMUFile *f, void *opaque) | ||
| 313 | 404 | ||
| 314 | static int pit_load(QEMUFile *f, void *opaque, int version_id) | 405 | static int pit_load(QEMUFile *f, void *opaque, int version_id) |
| 315 | { | 406 | { |
| 407 | + PITState *pit = opaque; | ||
| 316 | PITChannelState *s; | 408 | PITChannelState *s; |
| 317 | int i; | 409 | int i; |
| 318 | 410 | ||
| @@ -320,10 +412,16 @@ static int pit_load(QEMUFile *f, void *opaque, int version_id) | @@ -320,10 +412,16 @@ static int pit_load(QEMUFile *f, void *opaque, int version_id) | ||
| 320 | return -EINVAL; | 412 | return -EINVAL; |
| 321 | 413 | ||
| 322 | for(i = 0; i < 3; i++) { | 414 | for(i = 0; i < 3; i++) { |
| 323 | - s = &pit_channels[i]; | 415 | + s = &pit->channels[i]; |
| 324 | qemu_get_be32s(f, &s->count); | 416 | qemu_get_be32s(f, &s->count); |
| 325 | qemu_get_be16s(f, &s->latched_count); | 417 | qemu_get_be16s(f, &s->latched_count); |
| 326 | - qemu_get_8s(f, &s->rw_state); | 418 | + qemu_get_8s(f, &s->count_latched); |
| 419 | + qemu_get_8s(f, &s->status_latched); | ||
| 420 | + qemu_get_8s(f, &s->status); | ||
| 421 | + qemu_get_8s(f, &s->read_state); | ||
| 422 | + qemu_get_8s(f, &s->write_state); | ||
| 423 | + qemu_get_8s(f, &s->write_latch); | ||
| 424 | + qemu_get_8s(f, &s->rw_mode); | ||
| 327 | qemu_get_8s(f, &s->mode); | 425 | qemu_get_8s(f, &s->mode); |
| 328 | qemu_get_8s(f, &s->bcd); | 426 | qemu_get_8s(f, &s->bcd); |
| 329 | qemu_get_8s(f, &s->gate); | 427 | qemu_get_8s(f, &s->gate); |
| @@ -336,13 +434,14 @@ static int pit_load(QEMUFile *f, void *opaque, int version_id) | @@ -336,13 +434,14 @@ static int pit_load(QEMUFile *f, void *opaque, int version_id) | ||
| 336 | return 0; | 434 | return 0; |
| 337 | } | 435 | } |
| 338 | 436 | ||
| 339 | -void pit_init(int base, int irq) | 437 | +PITState *pit_init(int base, int irq) |
| 340 | { | 438 | { |
| 439 | + PITState *pit = &pit_state; | ||
| 341 | PITChannelState *s; | 440 | PITChannelState *s; |
| 342 | int i; | 441 | int i; |
| 343 | 442 | ||
| 344 | for(i = 0;i < 3; i++) { | 443 | for(i = 0;i < 3; i++) { |
| 345 | - s = &pit_channels[i]; | 444 | + s = &pit->channels[i]; |
| 346 | if (i == 0) { | 445 | if (i == 0) { |
| 347 | /* the timer 0 is connected to an IRQ */ | 446 | /* the timer 0 is connected to an IRQ */ |
| 348 | s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s); | 447 | s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s); |
| @@ -353,9 +452,9 @@ void pit_init(int base, int irq) | @@ -353,9 +452,9 @@ void pit_init(int base, int irq) | ||
| 353 | pit_load_count(s, 0); | 452 | pit_load_count(s, 0); |
| 354 | } | 453 | } |
| 355 | 454 | ||
| 356 | - register_savevm("i8254", base, 1, pit_save, pit_load, NULL); | 455 | + register_savevm("i8254", base, 1, pit_save, pit_load, pit); |
| 357 | 456 | ||
| 358 | - register_ioport_write(base, 4, 1, pit_ioport_write, NULL); | ||
| 359 | - register_ioport_read(base, 3, 1, pit_ioport_read, NULL); | 457 | + register_ioport_write(base, 4, 1, pit_ioport_write, pit); |
| 458 | + register_ioport_read(base, 3, 1, pit_ioport_read, pit); | ||
| 459 | + return pit; | ||
| 360 | } | 460 | } |
| 361 | - |
hw/pc.c
| @@ -39,6 +39,7 @@ int speaker_data_on; | @@ -39,6 +39,7 @@ int speaker_data_on; | ||
| 39 | int dummy_refresh_clock; | 39 | int dummy_refresh_clock; |
| 40 | static fdctrl_t *floppy_controller; | 40 | static fdctrl_t *floppy_controller; |
| 41 | static RTCState *rtc_state; | 41 | static RTCState *rtc_state; |
| 42 | +static PITState *pit; | ||
| 42 | 43 | ||
| 43 | static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) | 44 | static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) |
| 44 | { | 45 | { |
| @@ -169,15 +170,15 @@ static void cmos_init(int ram_size, int boot_device) | @@ -169,15 +170,15 @@ static void cmos_init(int ram_size, int boot_device) | ||
| 169 | static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) | 170 | static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 170 | { | 171 | { |
| 171 | speaker_data_on = (val >> 1) & 1; | 172 | speaker_data_on = (val >> 1) & 1; |
| 172 | - pit_set_gate(&pit_channels[2], val & 1); | 173 | + pit_set_gate(pit, 2, val & 1); |
| 173 | } | 174 | } |
| 174 | 175 | ||
| 175 | static uint32_t speaker_ioport_read(void *opaque, uint32_t addr) | 176 | static uint32_t speaker_ioport_read(void *opaque, uint32_t addr) |
| 176 | { | 177 | { |
| 177 | int out; | 178 | int out; |
| 178 | - out = pit_get_out(&pit_channels[2], qemu_get_clock(vm_clock)); | 179 | + out = pit_get_out(pit, 2, qemu_get_clock(vm_clock)); |
| 179 | dummy_refresh_clock ^= 1; | 180 | dummy_refresh_clock ^= 1; |
| 180 | - return (speaker_data_on << 1) | pit_channels[2].gate | (out << 5) | | 181 | + return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) | |
| 181 | (dummy_refresh_clock << 4); | 182 | (dummy_refresh_clock << 4); |
| 182 | } | 183 | } |
| 183 | 184 | ||
| @@ -381,7 +382,7 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, | @@ -381,7 +382,7 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, | ||
| 381 | register_ioport_write(0x92, 1, 1, ioport92_write, NULL); | 382 | register_ioport_write(0x92, 1, 1, ioport92_write, NULL); |
| 382 | 383 | ||
| 383 | pic_init(); | 384 | pic_init(); |
| 384 | - pit_init(0x40, 0); | 385 | + pit = pit_init(0x40, 0); |
| 385 | 386 | ||
| 386 | fd = serial_open_device(); | 387 | fd = serial_open_device(); |
| 387 | serial_init(0x3f8, 4, fd); | 388 | serial_init(0x3f8, 4, fd); |
vl.h
| @@ -481,26 +481,12 @@ void pic_info(void); | @@ -481,26 +481,12 @@ void pic_info(void); | ||
| 481 | 481 | ||
| 482 | #define PIT_FREQ 1193182 | 482 | #define PIT_FREQ 1193182 |
| 483 | 483 | ||
| 484 | -typedef struct PITChannelState { | ||
| 485 | - int count; /* can be 65536 */ | ||
| 486 | - uint16_t latched_count; | ||
| 487 | - uint8_t rw_state; | ||
| 488 | - uint8_t mode; | ||
| 489 | - uint8_t bcd; /* not supported */ | ||
| 490 | - uint8_t gate; /* timer start */ | ||
| 491 | - int64_t count_load_time; | ||
| 492 | - /* irq handling */ | ||
| 493 | - int64_t next_transition_time; | ||
| 494 | - QEMUTimer *irq_timer; | ||
| 495 | - int irq; | ||
| 496 | -} PITChannelState; | ||
| 497 | - | ||
| 498 | -extern PITChannelState pit_channels[3]; | ||
| 499 | - | ||
| 500 | -void pit_init(int base, int irq); | ||
| 501 | -void pit_set_gate(PITChannelState *s, int val); | ||
| 502 | -int pit_get_out(PITChannelState *s, int64_t current_time); | ||
| 503 | -int pit_get_out_edges(PITChannelState *s); | 484 | +typedef struct PITState PITState; |
| 485 | + | ||
| 486 | +PITState *pit_init(int base, int irq); | ||
| 487 | +void pit_set_gate(PITState *pit, int channel, int val); | ||
| 488 | +int pit_get_gate(PITState *pit, int channel); | ||
| 489 | +int pit_get_out(PITState *pit, int channel, int64_t current_time); | ||
| 504 | 490 | ||
| 505 | /* pc.c */ | 491 | /* pc.c */ |
| 506 | void pc_init(int ram_size, int vga_ram_size, int boot_device, | 492 | void pc_init(int ram_size, int vga_ram_size, int boot_device, |