Commit ec844b96c083340a4c04849c2c1cdc09e85e0595

Authored by bellard
1 parent f72e8ff4

pit fixes


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@781 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
... ... @@ -3,6 +3,7 @@ version 0.5.5:
3 3 - SDL full screen support (initial patch by malc)
4 4 - VGA support on PowerPC PREP
5 5 - VBE fixes (Matthew Mastracci)
  6 + - PIT fixes (aka Win98 hardware probe and timer bug)
6 7  
7 8 version 0.5.4:
8 9  
... ...
hw/i8254.c
... ... @@ -25,14 +25,36 @@
25 25  
26 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 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 83 }
62 84  
63 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 88 uint64_t d;
67 89 int out;
... ... @@ -92,6 +114,12 @@ int pit_get_out(PITChannelState *s, int64_t current_time)
92 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 123 /* return -1 if no transition will occur. */
96 124 static int64_t pit_get_next_transition_time(PITChannelState *s,
97 125 int64_t current_time)
... ... @@ -144,8 +172,10 @@ static int64_t pit_get_next_transition_time(PITChannelState *s,
144 172 }
145 173  
146 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 179 switch(s->mode) {
150 180 default:
151 181 case 0:
... ... @@ -173,6 +203,12 @@ void pit_set_gate(PITChannelState *s, int val)
173 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 212 static inline void pit_load_count(PITChannelState *s, int val)
177 213 {
178 214 if (val == 0)
... ... @@ -182,33 +218,62 @@ static inline void pit_load_count(PITChannelState *s, int val)
182 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 230 static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
186 231 {
  232 + PITState *pit = opaque;
187 233 int channel, access;
188 234 PITChannelState *s;
189 235  
190 236 addr &= 3;
191 237 if (addr == 3) {
192 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 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 277 case RW_STATE_LSB:
213 278 pit_load_count(s, val);
214 279 break;
... ... @@ -216,13 +281,12 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
216 281 pit_load_count(s, val << 8);
217 282 break;
218 283 case RW_STATE_WORD0:
  284 + s->write_latch = val;
  285 + s->write_state = RW_STATE_WORD1;
  286 + break;
219 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 290 break;
227 291 }
228 292 }
... ... @@ -230,33 +294,53 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
230 294  
231 295 static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
232 296 {
  297 + PITState *pit = opaque;
233 298 int ret, count;
234 299 PITChannelState *s;
235 300  
236 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 314 ret = s->latched_count >> 8;
256   - else
  315 + s->count_latched = 0;
  316 + break;
  317 + case RW_STATE_WORD0:
257 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 345 return ret;
262 346 }
... ... @@ -269,7 +353,7 @@ static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
269 353 if (!s->irq_timer)
270 354 return;
271 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 357 pic_set_irq(s->irq, irq_level);
274 358 #ifdef DEBUG_PIT
275 359 printf("irq_level=%d next_delay=%f\n",
... ... @@ -292,14 +376,21 @@ static void pit_irq_timer(void *opaque)
292 376  
293 377 static void pit_save(QEMUFile *f, void *opaque)
294 378 {
  379 + PITState *pit = opaque;
295 380 PITChannelState *s;
296 381 int i;
297 382  
298 383 for(i = 0; i < 3; i++) {
299   - s = &pit_channels[i];
  384 + s = &pit->channels[i];
300 385 qemu_put_be32s(f, &s->count);
301 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 394 qemu_put_8s(f, &s->mode);
304 395 qemu_put_8s(f, &s->bcd);
305 396 qemu_put_8s(f, &s->gate);
... ... @@ -313,6 +404,7 @@ static void pit_save(QEMUFile *f, void *opaque)
313 404  
314 405 static int pit_load(QEMUFile *f, void *opaque, int version_id)
315 406 {
  407 + PITState *pit = opaque;
316 408 PITChannelState *s;
317 409 int i;
318 410  
... ... @@ -320,10 +412,16 @@ static int pit_load(QEMUFile *f, void *opaque, int version_id)
320 412 return -EINVAL;
321 413  
322 414 for(i = 0; i < 3; i++) {
323   - s = &pit_channels[i];
  415 + s = &pit->channels[i];
324 416 qemu_get_be32s(f, &s->count);
325 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 425 qemu_get_8s(f, &s->mode);
328 426 qemu_get_8s(f, &s->bcd);
329 427 qemu_get_8s(f, &s->gate);
... ... @@ -336,13 +434,14 @@ static int pit_load(QEMUFile *f, void *opaque, int version_id)
336 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 440 PITChannelState *s;
342 441 int i;
343 442  
344 443 for(i = 0;i < 3; i++) {
345   - s = &pit_channels[i];
  444 + s = &pit->channels[i];
346 445 if (i == 0) {
347 446 /* the timer 0 is connected to an IRQ */
348 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 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   -
... ...
... ... @@ -39,6 +39,7 @@ int speaker_data_on;
39 39 int dummy_refresh_clock;
40 40 static fdctrl_t *floppy_controller;
41 41 static RTCState *rtc_state;
  42 +static PITState *pit;
42 43  
43 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 170 static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
170 171 {
171 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 176 static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
176 177 {
177 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 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 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 382 register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
382 383  
383 384 pic_init();
384   - pit_init(0x40, 0);
  385 + pit = pit_init(0x40, 0);
385 386  
386 387 fd = serial_open_device();
387 388 serial_init(0x3f8, 4, fd);
... ...
... ... @@ -481,26 +481,12 @@ void pic_info(void);
481 481  
482 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 491 /* pc.c */
506 492 void pc_init(int ram_size, int vga_ram_size, int boot_device,
... ...