1/*
2 * QEMU 8253/8254 interval timer emulation
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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.
23 */
24#include "hw/hw.h"
25#include "hw/i386/pc.h"
26#include "hw/isa/isa.h"
27#include "qemu/timer.h"
28
29//#define DEBUG_PIT
30
31#define RW_STATE_LSB 1
32#define RW_STATE_MSB 2
33#define RW_STATE_WORD0 3
34#define RW_STATE_WORD1 4
35
36typedef struct PITChannelState {
37    int count; /* can be 65536 */
38    uint16_t latched_count;
39    uint8_t count_latched;
40    uint8_t status_latched;
41    uint8_t status;
42    uint8_t read_state;
43    uint8_t write_state;
44    uint8_t write_latch;
45    uint8_t rw_mode;
46    uint8_t mode;
47    uint8_t bcd; /* not supported */
48    uint8_t gate; /* timer start */
49    int64_t count_load_time;
50    /* irq handling */
51    int64_t next_transition_time;
52    QEMUTimer *irq_timer;
53    qemu_irq irq;
54} PITChannelState;
55
56struct PITState {
57    PITChannelState channels[3];
58};
59
60static PITState pit_state;
61
62static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
63
64static int pit_get_count(PITChannelState *s)
65{
66    uint64_t d;
67    int counter;
68
69    d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->count_load_time, PIT_FREQ, get_ticks_per_sec());
70    switch(s->mode) {
71    case 0:
72    case 1:
73    case 4:
74    case 5:
75        counter = (s->count - d) & 0xffff;
76        break;
77    case 3:
78        /* XXX: may be incorrect for odd counts */
79        counter = s->count - ((2 * d) % s->count);
80        break;
81    default:
82        counter = s->count - (d % s->count);
83        break;
84    }
85    return counter;
86}
87
88/* get pit output bit */
89static int pit_get_out1(PITChannelState *s, int64_t current_time)
90{
91    uint64_t d;
92    int out;
93
94    d = muldiv64(current_time - s->count_load_time, PIT_FREQ, get_ticks_per_sec());
95    switch(s->mode) {
96    default:
97    case 0:
98        out = (d >= s->count);
99        break;
100    case 1:
101        out = (d < s->count);
102        break;
103    case 2:
104        if ((d % s->count) == 0 && d != 0)
105            out = 1;
106        else
107            out = 0;
108        break;
109    case 3:
110        out = (d % s->count) < ((s->count + 1) >> 1);
111        break;
112    case 4:
113    case 5:
114        out = (d == s->count);
115        break;
116    }
117    return out;
118}
119
120int pit_get_out(PITState *pit, int channel, int64_t current_time)
121{
122    PITChannelState *s = &pit->channels[channel];
123    return pit_get_out1(s, current_time);
124}
125
126/* return -1 if no transition will occur.  */
127static int64_t pit_get_next_transition_time(PITChannelState *s,
128                                            int64_t current_time)
129{
130    uint64_t d, next_time, base;
131    int period2;
132
133    d = muldiv64(current_time - s->count_load_time, PIT_FREQ, get_ticks_per_sec());
134    switch(s->mode) {
135    default:
136    case 0:
137    case 1:
138        if (d < s->count)
139            next_time = s->count;
140        else
141            return -1;
142        break;
143    case 2:
144        base = (d / s->count) * s->count;
145        if ((d - base) == 0 && d != 0)
146            next_time = base + s->count;
147        else
148            next_time = base + s->count + 1;
149        break;
150    case 3:
151        base = (d / s->count) * s->count;
152        period2 = ((s->count + 1) >> 1);
153        if ((d - base) < period2)
154            next_time = base + period2;
155        else
156            next_time = base + s->count;
157        break;
158    case 4:
159    case 5:
160        if (d < s->count)
161            next_time = s->count;
162        else if (d == s->count)
163            next_time = s->count + 1;
164        else
165            return -1;
166        break;
167    }
168    /* convert to timer units */
169    next_time = s->count_load_time + muldiv64(next_time, get_ticks_per_sec(), PIT_FREQ);
170    /* fix potential rounding problems */
171    /* XXX: better solution: use a clock at PIT_FREQ Hz */
172    if (next_time <= current_time)
173        next_time = current_time + 1;
174    return next_time;
175}
176
177/* val must be 0 or 1 */
178void pit_set_gate(PITState *pit, int channel, int val)
179{
180    PITChannelState *s = &pit->channels[channel];
181
182    switch(s->mode) {
183    default:
184    case 0:
185    case 4:
186        /* XXX: just disable/enable counting */
187        break;
188    case 1:
189    case 5:
190        if (s->gate < val) {
191            /* restart counting on rising edge */
192            s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
193            pit_irq_timer_update(s, s->count_load_time);
194        }
195        break;
196    case 2:
197    case 3:
198        if (s->gate < val) {
199            /* restart counting on rising edge */
200            s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
201            pit_irq_timer_update(s, s->count_load_time);
202        }
203        /* XXX: disable/enable counting */
204        break;
205    }
206    s->gate = val;
207}
208
209int pit_get_gate(PITState *pit, int channel)
210{
211    PITChannelState *s = &pit->channels[channel];
212    return s->gate;
213}
214
215int pit_get_initial_count(PITState *pit, int channel)
216{
217    PITChannelState *s = &pit->channels[channel];
218    return s->count;
219}
220
221int pit_get_mode(PITState *pit, int channel)
222{
223    PITChannelState *s = &pit->channels[channel];
224    return s->mode;
225}
226
227static inline void pit_load_count(PITChannelState *s, int val)
228{
229    if (val == 0)
230        val = 0x10000;
231    s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
232    s->count = val;
233    pit_irq_timer_update(s, s->count_load_time);
234}
235
236/* if already latched, do not latch again */
237static void pit_latch_count(PITChannelState *s)
238{
239    if (!s->count_latched) {
240        s->latched_count = pit_get_count(s);
241        s->count_latched = s->rw_mode;
242    }
243}
244
245static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
246{
247    PITState *pit = opaque;
248    int channel, access;
249    PITChannelState *s;
250
251    addr &= 3;
252    if (addr == 3) {
253        channel = val >> 6;
254        if (channel == 3) {
255            /* read back command */
256            for(channel = 0; channel < 3; channel++) {
257                s = &pit->channels[channel];
258                if (val & (2 << channel)) {
259                    if (!(val & 0x20)) {
260                        pit_latch_count(s);
261                    }
262                    if (!(val & 0x10) && !s->status_latched) {
263                        /* status latch */
264                        /* XXX: add BCD and null count */
265                        s->status =  (pit_get_out1(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) << 7) |
266                            (s->rw_mode << 4) |
267                            (s->mode << 1) |
268                            s->bcd;
269                        s->status_latched = 1;
270                    }
271                }
272            }
273        } else {
274            s = &pit->channels[channel];
275            access = (val >> 4) & 3;
276            if (access == 0) {
277                pit_latch_count(s);
278            } else {
279                s->rw_mode = access;
280                s->read_state = access;
281                s->write_state = access;
282
283                s->mode = (val >> 1) & 7;
284                s->bcd = val & 1;
285                /* XXX: update irq timer ? */
286            }
287        }
288    } else {
289        s = &pit->channels[addr];
290        switch(s->write_state) {
291        default:
292        case RW_STATE_LSB:
293            pit_load_count(s, val);
294            break;
295        case RW_STATE_MSB:
296            pit_load_count(s, val << 8);
297            break;
298        case RW_STATE_WORD0:
299            s->write_latch = val;
300            s->write_state = RW_STATE_WORD1;
301            break;
302        case RW_STATE_WORD1:
303            pit_load_count(s, s->write_latch | (val << 8));
304            s->write_state = RW_STATE_WORD0;
305            break;
306        }
307    }
308}
309
310static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
311{
312    PITState *pit = opaque;
313    int ret, count;
314    PITChannelState *s;
315
316    addr &= 3;
317    s = &pit->channels[addr];
318    if (s->status_latched) {
319        s->status_latched = 0;
320        ret = s->status;
321    } else if (s->count_latched) {
322        switch(s->count_latched) {
323        default:
324        case RW_STATE_LSB:
325            ret = s->latched_count & 0xff;
326            s->count_latched = 0;
327            break;
328        case RW_STATE_MSB:
329            ret = s->latched_count >> 8;
330            s->count_latched = 0;
331            break;
332        case RW_STATE_WORD0:
333            ret = s->latched_count & 0xff;
334            s->count_latched = RW_STATE_MSB;
335            break;
336        }
337    } else {
338        switch(s->read_state) {
339        default:
340        case RW_STATE_LSB:
341            count = pit_get_count(s);
342            ret = count & 0xff;
343            break;
344        case RW_STATE_MSB:
345            count = pit_get_count(s);
346            ret = (count >> 8) & 0xff;
347            break;
348        case RW_STATE_WORD0:
349            count = pit_get_count(s);
350            ret = count & 0xff;
351            s->read_state = RW_STATE_WORD1;
352            break;
353        case RW_STATE_WORD1:
354            count = pit_get_count(s);
355            ret = (count >> 8) & 0xff;
356            s->read_state = RW_STATE_WORD0;
357            break;
358        }
359    }
360    return ret;
361}
362
363static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
364{
365    int64_t expire_time;
366    int irq_level;
367
368    if (!s->irq_timer)
369        return;
370    expire_time = pit_get_next_transition_time(s, current_time);
371    irq_level = pit_get_out1(s, current_time);
372    qemu_set_irq(s->irq, irq_level);
373#ifdef DEBUG_PIT
374    printf("irq_level=%d next_delay=%f\n",
375           irq_level,
376           (double)(expire_time - current_time) / get_ticks_per_sec());
377#endif
378    s->next_transition_time = expire_time;
379    if (expire_time != -1)
380        timer_mod(s->irq_timer, expire_time);
381    else
382        timer_del(s->irq_timer);
383}
384
385static void pit_irq_timer(void *opaque)
386{
387    PITChannelState *s = opaque;
388
389    pit_irq_timer_update(s, s->next_transition_time);
390}
391
392static void pit_save(QEMUFile *f, void *opaque)
393{
394    PITState *pit = opaque;
395    PITChannelState *s;
396    int i;
397
398    for(i = 0; i < 3; i++) {
399        s = &pit->channels[i];
400        qemu_put_be32(f, s->count);
401        qemu_put_be16s(f, &s->latched_count);
402        qemu_put_8s(f, &s->count_latched);
403        qemu_put_8s(f, &s->status_latched);
404        qemu_put_8s(f, &s->status);
405        qemu_put_8s(f, &s->read_state);
406        qemu_put_8s(f, &s->write_state);
407        qemu_put_8s(f, &s->write_latch);
408        qemu_put_8s(f, &s->rw_mode);
409        qemu_put_8s(f, &s->mode);
410        qemu_put_8s(f, &s->bcd);
411        qemu_put_8s(f, &s->gate);
412        qemu_put_be64(f, s->count_load_time);
413        if (s->irq_timer) {
414            qemu_put_be64(f, s->next_transition_time);
415            timer_put(f, s->irq_timer);
416        }
417    }
418}
419
420static int pit_load(QEMUFile *f, void *opaque, int version_id)
421{
422    PITState *pit = opaque;
423    PITChannelState *s;
424    int i;
425
426    if (version_id != 1)
427        return -EINVAL;
428
429    for(i = 0; i < 3; i++) {
430        s = &pit->channels[i];
431        s->count=qemu_get_be32(f);
432        qemu_get_be16s(f, &s->latched_count);
433        qemu_get_8s(f, &s->count_latched);
434        qemu_get_8s(f, &s->status_latched);
435        qemu_get_8s(f, &s->status);
436        qemu_get_8s(f, &s->read_state);
437        qemu_get_8s(f, &s->write_state);
438        qemu_get_8s(f, &s->write_latch);
439        qemu_get_8s(f, &s->rw_mode);
440        qemu_get_8s(f, &s->mode);
441        qemu_get_8s(f, &s->bcd);
442        qemu_get_8s(f, &s->gate);
443        s->count_load_time=qemu_get_be64(f);
444        if (s->irq_timer) {
445            s->next_transition_time=qemu_get_be64(f);
446            timer_get(f, s->irq_timer);
447        }
448    }
449    return 0;
450}
451
452static void pit_reset(void *opaque)
453{
454    PITState *pit = opaque;
455    PITChannelState *s;
456    int i;
457
458    for(i = 0;i < 3; i++) {
459        s = &pit->channels[i];
460        s->mode = 3;
461        s->gate = (i != 2);
462        pit_load_count(s, 0);
463    }
464}
465
466/* When HPET is operating in legacy mode, i8254 timer0 is disabled */
467void hpet_pit_disable(void) {
468    PITChannelState *s;
469    s = &pit_state.channels[0];
470    if (s->irq_timer)
471        timer_del(s->irq_timer);
472}
473
474/* When HPET is reset or leaving legacy mode, it must reenable i8254
475 * timer 0
476 */
477
478void hpet_pit_enable(void)
479{
480    PITState *pit = &pit_state;
481    PITChannelState *s;
482    s = &pit->channels[0];
483    s->mode = 3;
484    s->gate = 1;
485    pit_load_count(s, 0);
486}
487
488PITState *pit_init(int base, qemu_irq irq)
489{
490    PITState *pit = &pit_state;
491    PITChannelState *s;
492
493    s = &pit->channels[0];
494    /* the timer 0 is connected to an IRQ */
495    s->irq_timer = timer_new(QEMU_CLOCK_VIRTUAL, SCALE_NS, pit_irq_timer, s);
496    s->irq = irq;
497
498    register_savevm(NULL, "i8254", base, 1, pit_save, pit_load, pit);
499
500    qemu_register_reset(pit_reset, 0, pit);
501    register_ioport_write(base, 4, 1, pit_ioport_write, pit);
502    register_ioport_read(base, 3, 1, pit_ioport_read, pit);
503
504    pit_reset(pit);
505
506    return pit;
507}
508