Fix linux-user build on ppc
[qemu-kvm/fedora.git] / hw / i8254.c
blob34a716c1ba924d61c6081812c25349d13fa30740
1 /*
2 * QEMU 8253/8254 interval timer emulation
4 * Copyright (c) 2003-2004 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
24 #include "hw.h"
25 #include "pc.h"
26 #include "isa.h"
27 #include "qemu-timer.h"
28 #include "qemu-kvm.h"
29 #include "i8254.h"
31 //#define DEBUG_PIT
33 static PITState pit_state;
35 static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
37 static int pit_get_count(PITChannelState *s)
39 uint64_t d;
40 int counter;
42 d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec);
43 switch(s->mode) {
44 case 0:
45 case 1:
46 case 4:
47 case 5:
48 counter = (s->count - d) & 0xffff;
49 break;
50 case 3:
51 /* XXX: may be incorrect for odd counts */
52 counter = s->count - ((2 * d) % s->count);
53 break;
54 default:
55 counter = s->count - (d % s->count);
56 break;
58 return counter;
61 /* get pit output bit */
62 static int pit_get_out1(PITChannelState *s, int64_t current_time)
64 uint64_t d;
65 int out;
67 d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
68 switch(s->mode) {
69 default:
70 case 0:
71 out = (d >= s->count);
72 break;
73 case 1:
74 out = (d < s->count);
75 break;
76 case 2:
77 if ((d % s->count) == 0 && d != 0)
78 out = 1;
79 else
80 out = 0;
81 break;
82 case 3:
83 out = (d % s->count) < ((s->count + 1) >> 1);
84 break;
85 case 4:
86 case 5:
87 out = (d == s->count);
88 break;
90 return out;
93 int pit_get_out(PITState *pit, int channel, int64_t current_time)
95 PITChannelState *s = &pit->channels[channel];
96 return pit_get_out1(s, current_time);
99 /* return -1 if no transition will occur. */
100 static int64_t pit_get_next_transition_time(PITChannelState *s,
101 int64_t current_time)
103 uint64_t d, next_time, base;
104 int period2;
106 d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
107 switch(s->mode) {
108 default:
109 case 0:
110 case 1:
111 if (d < s->count)
112 next_time = s->count;
113 else
114 return -1;
115 break;
116 case 2:
117 base = (d / s->count) * s->count;
118 if ((d - base) == 0 && d != 0)
119 next_time = base + s->count;
120 else
121 next_time = base + s->count + 1;
122 break;
123 case 3:
124 base = (d / s->count) * s->count;
125 period2 = ((s->count + 1) >> 1);
126 if ((d - base) < period2)
127 next_time = base + period2;
128 else
129 next_time = base + s->count;
130 break;
131 case 4:
132 case 5:
133 if (d < s->count)
134 next_time = s->count;
135 else if (d == s->count)
136 next_time = s->count + 1;
137 else
138 return -1;
139 break;
141 /* convert to timer units */
142 next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ);
143 /* fix potential rounding problems */
144 /* XXX: better solution: use a clock at PIT_FREQ Hz */
145 if (next_time <= current_time)
146 next_time = current_time + 1;
147 return next_time;
150 /* val must be 0 or 1 */
151 void pit_set_gate(PITState *pit, int channel, int val)
153 PITChannelState *s = &pit->channels[channel];
155 switch(s->mode) {
156 default:
157 case 0:
158 case 4:
159 /* XXX: just disable/enable counting */
160 break;
161 case 1:
162 case 5:
163 if (s->gate < val) {
164 /* restart counting on rising edge */
165 s->count_load_time = qemu_get_clock(vm_clock);
166 pit_irq_timer_update(s, s->count_load_time);
168 break;
169 case 2:
170 case 3:
171 if (s->gate < val) {
172 /* restart counting on rising edge */
173 s->count_load_time = qemu_get_clock(vm_clock);
174 pit_irq_timer_update(s, s->count_load_time);
176 /* XXX: disable/enable counting */
177 break;
179 s->gate = val;
182 int pit_get_gate(PITState *pit, int channel)
184 PITChannelState *s = &pit->channels[channel];
185 return s->gate;
188 int pit_get_initial_count(PITState *pit, int channel)
190 PITChannelState *s = &pit->channels[channel];
191 return s->count;
194 int pit_get_mode(PITState *pit, int channel)
196 PITChannelState *s = &pit->channels[channel];
197 return s->mode;
200 static inline void pit_load_count(PITState *s, int val, int chan)
202 if (val == 0)
203 val = 0x10000;
204 s->channels[chan].count_load_time = qemu_get_clock(vm_clock);
205 s->channels[chan].count = val;
206 #ifdef TARGET_I386
207 if (chan == 0 && pit_state.flags & PIT_FLAGS_HPET_LEGACY) {
208 return;
210 #endif
211 pit_irq_timer_update(&s->channels[chan], s->channels[chan].count_load_time);
214 /* if already latched, do not latch again */
215 static void pit_latch_count(PITChannelState *s)
217 if (!s->count_latched) {
218 s->latched_count = pit_get_count(s);
219 s->count_latched = s->rw_mode;
223 static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
225 PITState *pit = opaque;
226 int channel, access;
227 PITChannelState *s;
229 addr &= 3;
230 if (addr == 3) {
231 channel = val >> 6;
232 if (channel == 3) {
233 /* read back command */
234 for(channel = 0; channel < 3; channel++) {
235 s = &pit->channels[channel];
236 if (val & (2 << channel)) {
237 if (!(val & 0x20)) {
238 pit_latch_count(s);
240 if (!(val & 0x10) && !s->status_latched) {
241 /* status latch */
242 /* XXX: add BCD and null count */
243 s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) |
244 (s->rw_mode << 4) |
245 (s->mode << 1) |
246 s->bcd;
247 s->status_latched = 1;
251 } else {
252 s = &pit->channels[channel];
253 access = (val >> 4) & 3;
254 if (access == 0) {
255 pit_latch_count(s);
256 } else {
257 s->rw_mode = access;
258 s->read_state = access;
259 s->write_state = access;
261 s->mode = (val >> 1) & 7;
262 s->bcd = val & 1;
263 /* XXX: update irq timer ? */
266 } else {
267 s = &pit->channels[addr];
268 switch(s->write_state) {
269 default:
270 case RW_STATE_LSB:
271 pit_load_count(pit, val, addr);
272 break;
273 case RW_STATE_MSB:
274 pit_load_count(pit, val << 8, addr);
275 break;
276 case RW_STATE_WORD0:
277 s->write_latch = val;
278 s->write_state = RW_STATE_WORD1;
279 break;
280 case RW_STATE_WORD1:
281 pit_load_count(pit, s->write_latch | (val << 8), addr);
282 s->write_state = RW_STATE_WORD0;
283 break;
288 static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
290 PITState *pit = opaque;
291 int ret, count;
292 PITChannelState *s;
294 addr &= 3;
295 s = &pit->channels[addr];
296 if (s->status_latched) {
297 s->status_latched = 0;
298 ret = s->status;
299 } else if (s->count_latched) {
300 switch(s->count_latched) {
301 default:
302 case RW_STATE_LSB:
303 ret = s->latched_count & 0xff;
304 s->count_latched = 0;
305 break;
306 case RW_STATE_MSB:
307 ret = s->latched_count >> 8;
308 s->count_latched = 0;
309 break;
310 case RW_STATE_WORD0:
311 ret = s->latched_count & 0xff;
312 s->count_latched = RW_STATE_MSB;
313 break;
315 } else {
316 switch(s->read_state) {
317 default:
318 case RW_STATE_LSB:
319 count = pit_get_count(s);
320 ret = count & 0xff;
321 break;
322 case RW_STATE_MSB:
323 count = pit_get_count(s);
324 ret = (count >> 8) & 0xff;
325 break;
326 case RW_STATE_WORD0:
327 count = pit_get_count(s);
328 ret = count & 0xff;
329 s->read_state = RW_STATE_WORD1;
330 break;
331 case RW_STATE_WORD1:
332 count = pit_get_count(s);
333 ret = (count >> 8) & 0xff;
334 s->read_state = RW_STATE_WORD0;
335 break;
338 return ret;
341 /* global counters for time-drift fix */
342 int64_t timer_acks=0, timer_interrupts=0, timer_ints_to_push=0;
344 extern int time_drift_fix;
346 static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
348 int64_t expire_time;
349 int irq_level;
351 if (!s->irq_timer)
352 return;
353 expire_time = pit_get_next_transition_time(s, current_time);
354 irq_level = pit_get_out1(s, current_time);
355 qemu_set_irq(s->irq, irq_level);
356 if (time_drift_fix && irq_level==1) {
357 /* FIXME: fine tune timer_max_fix (max fix per tick).
358 * Should it be 1 (double time), 2 , 4, 10 ?
359 * Currently setting it to 5% of PIT-ticks-per-second (per PIT-tick)
361 const long pit_ticks_per_sec = (s->count>0) ? (PIT_FREQ/s->count) : 0;
362 const long timer_max_fix = pit_ticks_per_sec/20;
363 const long delta = timer_interrupts - timer_acks;
364 const long max_delta = pit_ticks_per_sec * 60; /* one minute */
365 if ((delta > max_delta) && (pit_ticks_per_sec > 0)) {
366 printf("time drift is too long, %ld seconds were lost\n", delta/pit_ticks_per_sec);
367 timer_acks = timer_interrupts;
368 timer_ints_to_push = 0;
369 } else if (delta > 0) {
370 timer_ints_to_push = MIN(delta, timer_max_fix);
372 timer_interrupts++;
374 #ifdef DEBUG_PIT
375 printf("irq_level=%d next_delay=%f\n",
376 irq_level,
377 (double)(expire_time - current_time) / ticks_per_sec);
378 #endif
379 s->next_transition_time = expire_time;
380 if (expire_time != -1) {
381 qemu_mod_timer(s->irq_timer, expire_time);
382 } else {
383 qemu_del_timer(s->irq_timer);
387 static void pit_irq_timer(void *opaque)
389 PITChannelState *s = opaque;
391 pit_irq_timer_update(s, s->next_transition_time);
394 void pit_save(QEMUFile *f, void *opaque)
396 PITState *pit = opaque;
397 PITChannelState *s;
398 int i;
400 qemu_put_be32(f, pit->flags);
401 for(i = 0; i < 3; i++) {
402 s = &pit->channels[i];
403 qemu_put_be32(f, s->count);
404 qemu_put_be16s(f, &s->latched_count);
405 qemu_put_8s(f, &s->count_latched);
406 qemu_put_8s(f, &s->status_latched);
407 qemu_put_8s(f, &s->status);
408 qemu_put_8s(f, &s->read_state);
409 qemu_put_8s(f, &s->write_state);
410 qemu_put_8s(f, &s->write_latch);
411 qemu_put_8s(f, &s->rw_mode);
412 qemu_put_8s(f, &s->mode);
413 qemu_put_8s(f, &s->bcd);
414 qemu_put_8s(f, &s->gate);
415 qemu_put_be64(f, s->count_load_time);
416 if (s->irq_timer) {
417 qemu_put_be64(f, s->next_transition_time);
418 qemu_put_timer(f, s->irq_timer);
423 int pit_load(QEMUFile *f, void *opaque, int version_id)
425 PITState *pit = opaque;
426 PITChannelState *s;
427 int i;
429 if (version_id != PIT_SAVEVM_VERSION)
430 return -EINVAL;
432 pit->flags = qemu_get_be32(f);
433 for(i = 0; i < 3; i++) {
434 s = &pit->channels[i];
435 s->count=qemu_get_be32(f);
436 qemu_get_be16s(f, &s->latched_count);
437 qemu_get_8s(f, &s->count_latched);
438 qemu_get_8s(f, &s->status_latched);
439 qemu_get_8s(f, &s->status);
440 qemu_get_8s(f, &s->read_state);
441 qemu_get_8s(f, &s->write_state);
442 qemu_get_8s(f, &s->write_latch);
443 qemu_get_8s(f, &s->rw_mode);
444 qemu_get_8s(f, &s->mode);
445 qemu_get_8s(f, &s->bcd);
446 qemu_get_8s(f, &s->gate);
447 s->count_load_time=qemu_get_be64(f);
448 if (s->irq_timer) {
449 s->next_transition_time=qemu_get_be64(f);
450 qemu_get_timer(f, s->irq_timer);
454 return 0;
457 void pit_reset(void *opaque)
459 PITState *pit = opaque;
460 PITChannelState *s;
461 int i;
463 #ifdef TARGET_I386
464 pit->flags &= ~PIT_FLAGS_HPET_LEGACY;
465 #endif
466 for(i = 0;i < 3; i++) {
467 s = &pit->channels[i];
468 s->mode = 3;
469 s->gate = (i != 2);
470 pit_load_count(pit, 0, i);
474 #ifdef TARGET_I386
475 /* When HPET is operating in legacy mode, i8254 timer0 is disabled */
477 void hpet_disable_pit(void)
479 PITChannelState *s = &pit_state.channels[0];
481 if (kvm_enabled() && qemu_kvm_pit_in_kernel()) {
482 if (qemu_kvm_has_pit_state2()) {
483 kvm_hpet_disable_kpit();
484 } else {
485 fprintf(stderr, "%s: kvm does not support pit_state2!\n", __FUNCTION__);
486 exit(1);
488 } else {
489 pit_state.flags |= PIT_FLAGS_HPET_LEGACY;
490 if (s->irq_timer) {
491 qemu_del_timer(s->irq_timer);
496 /* When HPET is reset or leaving legacy mode, it must reenable i8254
497 * timer 0
500 void hpet_enable_pit(void)
502 PITState *pit = &pit_state;
503 PITChannelState *s = &pit->channels[0];
505 if (kvm_enabled() && qemu_kvm_pit_in_kernel()) {
506 if (qemu_kvm_has_pit_state2()) {
507 kvm_hpet_enable_kpit();
508 } else {
509 fprintf(stderr, "%s: kvm does not support pit_state2!\n", __FUNCTION__);
510 exit(1);
512 } else {
513 pit_state.flags &= ~PIT_FLAGS_HPET_LEGACY;
514 pit_load_count(pit, s->count, 0);
517 #endif
519 PITState *pit_init(int base, qemu_irq irq)
521 PITState *pit = &pit_state;
522 PITChannelState *s;
524 s = &pit->channels[0];
525 /* the timer 0 is connected to an IRQ */
526 s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
527 s->irq = irq;
529 register_savevm(PIT_SAVEVM_NAME, base, PIT_SAVEVM_VERSION,
530 pit_save, pit_load, pit);
532 qemu_register_reset(pit_reset, pit);
533 register_ioport_write(base, 4, 1, pit_ioport_write, pit);
534 register_ioport_read(base, 3, 1, pit_ioport_read, pit);
536 pit_reset(pit);
538 return pit;