186797937017f52bff088d02edf64fb931177a7eaJun Nakajima/*
286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * QEMU 8253/8254 interval timer emulation
386797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
486797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Copyright (c) 2003-2004 Fabrice Bellard
586797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Permission is hereby granted, free of charge, to any person obtaining a copy
786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * of this software and associated documentation files (the "Software"), to deal
886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * in the Software without restriction, including without limitation the rights
986797937017f52bff088d02edf64fb931177a7eaJun Nakajima * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1086797937017f52bff088d02edf64fb931177a7eaJun Nakajima * copies of the Software, and to permit persons to whom the Software is
1186797937017f52bff088d02edf64fb931177a7eaJun Nakajima * furnished to do so, subject to the following conditions:
1286797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
1386797937017f52bff088d02edf64fb931177a7eaJun Nakajima * The above copyright notice and this permission notice shall be included in
1486797937017f52bff088d02edf64fb931177a7eaJun Nakajima * all copies or substantial portions of the Software.
1586797937017f52bff088d02edf64fb931177a7eaJun Nakajima *
1686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1986797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2086797937017f52bff088d02edf64fb931177a7eaJun Nakajima * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2186797937017f52bff088d02edf64fb931177a7eaJun Nakajima * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE SOFTWARE.
2386797937017f52bff088d02edf64fb931177a7eaJun Nakajima */
242ec695af7284adbedcdbc08a22d818b6bdd8990cDavid 'Digit' Turner#include "hw/hw.h"
252ec695af7284adbedcdbc08a22d818b6bdd8990cDavid 'Digit' Turner#include "hw/i386/pc.h"
262ec695af7284adbedcdbc08a22d818b6bdd8990cDavid 'Digit' Turner#include "hw/isa/isa.h"
277a78db75ad42aea283f5073f51891464104a9fc3David 'Digit' Turner#include "qemu/timer.h"
2886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
2986797937017f52bff088d02edf64fb931177a7eaJun Nakajima//#define DEBUG_PIT
3086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
3186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define RW_STATE_LSB 1
3286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define RW_STATE_MSB 2
3386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define RW_STATE_WORD0 3
3486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#define RW_STATE_WORD1 4
3586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
3686797937017f52bff088d02edf64fb931177a7eaJun Nakajimatypedef struct PITChannelState {
3786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int count; /* can be 65536 */
3886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint16_t latched_count;
3986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t count_latched;
4086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t status_latched;
4186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t status;
4286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t read_state;
4386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t write_state;
4486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t write_latch;
4586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t rw_mode;
4686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t mode;
4786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t bcd; /* not supported */
4886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint8_t gate; /* timer start */
4986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int64_t count_load_time;
5086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* irq handling */
5186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int64_t next_transition_time;
5286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    QEMUTimer *irq_timer;
5386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_irq irq;
5486797937017f52bff088d02edf64fb931177a7eaJun Nakajima} PITChannelState;
5586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
5686797937017f52bff088d02edf64fb931177a7eaJun Nakajimastruct PITState {
5786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState channels[3];
5886797937017f52bff088d02edf64fb931177a7eaJun Nakajima};
5986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
6086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic PITState pit_state;
6186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
6286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
6386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
6486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int pit_get_count(PITChannelState *s)
6586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
6686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint64_t d;
6786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int counter;
6886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
69dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->count_load_time, PIT_FREQ, get_ticks_per_sec());
7086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch(s->mode) {
7186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0:
7286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 1:
7386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 4:
7486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 5:
7586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        counter = (s->count - d) & 0xffff;
7686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
7786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 3:
7886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* XXX: may be incorrect for odd counts */
7986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        counter = s->count - ((2 * d) % s->count);
8086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
8186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    default:
8286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        counter = s->count - (d % s->count);
8386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
8486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
8586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return counter;
8686797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
8786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
8886797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* get pit output bit */
8986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int pit_get_out1(PITChannelState *s, int64_t current_time)
9086797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
9186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint64_t d;
9286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int out;
9386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
9486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    d = muldiv64(current_time - s->count_load_time, PIT_FREQ, get_ticks_per_sec());
9586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch(s->mode) {
9686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    default:
9786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0:
9886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        out = (d >= s->count);
9986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
10086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 1:
10186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        out = (d < s->count);
10286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
10386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 2:
10486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if ((d % s->count) == 0 && d != 0)
10586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            out = 1;
10686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        else
10786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            out = 0;
10886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
10986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 3:
11086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        out = (d % s->count) < ((s->count + 1) >> 1);
11186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
11286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 4:
11386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 5:
11486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        out = (d == s->count);
11586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
11686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
11786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return out;
11886797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
11986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
12086797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint pit_get_out(PITState *pit, int channel, int64_t current_time)
12186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
12286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s = &pit->channels[channel];
12386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return pit_get_out1(s, current_time);
12486797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
12586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
12686797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* return -1 if no transition will occur.  */
12786797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int64_t pit_get_next_transition_time(PITChannelState *s,
12886797937017f52bff088d02edf64fb931177a7eaJun Nakajima                                            int64_t current_time)
12986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
13086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    uint64_t d, next_time, base;
13186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int period2;
13286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
13386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    d = muldiv64(current_time - s->count_load_time, PIT_FREQ, get_ticks_per_sec());
13486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch(s->mode) {
13586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    default:
13686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0:
13786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 1:
13886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (d < s->count)
13986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            next_time = s->count;
14086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        else
14186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return -1;
14286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
14386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 2:
14486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        base = (d / s->count) * s->count;
14586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if ((d - base) == 0 && d != 0)
14686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            next_time = base + s->count;
14786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        else
14886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            next_time = base + s->count + 1;
14986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
15086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 3:
15186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        base = (d / s->count) * s->count;
15286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        period2 = ((s->count + 1) >> 1);
15386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if ((d - base) < period2)
15486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            next_time = base + period2;
15586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        else
15686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            next_time = base + s->count;
15786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
15886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 4:
15986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 5:
16086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (d < s->count)
16186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            next_time = s->count;
16286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        else if (d == s->count)
16386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            next_time = s->count + 1;
16486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        else
16586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            return -1;
16686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
16786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
16886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* convert to timer units */
16986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    next_time = s->count_load_time + muldiv64(next_time, get_ticks_per_sec(), PIT_FREQ);
17086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* fix potential rounding problems */
17186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* XXX: better solution: use a clock at PIT_FREQ Hz */
17286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (next_time <= current_time)
17386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        next_time = current_time + 1;
17486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return next_time;
17586797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
17686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
17786797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* val must be 0 or 1 */
17886797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid pit_set_gate(PITState *pit, int channel, int val)
17986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
18086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s = &pit->channels[channel];
18186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
18286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    switch(s->mode) {
18386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    default:
18486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 0:
18586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 4:
18686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* XXX: just disable/enable counting */
18786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
18886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 1:
18986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 5:
19086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (s->gate < val) {
19186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            /* restart counting on rising edge */
192dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
19386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            pit_irq_timer_update(s, s->count_load_time);
19486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
19586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
19686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 2:
19786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    case 3:
19886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (s->gate < val) {
19986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            /* restart counting on rising edge */
200dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
20186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            pit_irq_timer_update(s, s->count_load_time);
20286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
20386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        /* XXX: disable/enable counting */
20486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        break;
20586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
20686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->gate = val;
20786797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
20886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
20986797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint pit_get_gate(PITState *pit, int channel)
21086797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
21186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s = &pit->channels[channel];
21286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return s->gate;
21386797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
21486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
21586797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint pit_get_initial_count(PITState *pit, int channel)
21686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
21786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s = &pit->channels[channel];
21886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return s->count;
21986797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
22086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
22186797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint pit_get_mode(PITState *pit, int channel)
22286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
22386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s = &pit->channels[channel];
22486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return s->mode;
22586797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
22686797937017f52bff088d02edf64fb931177a7eaJun Nakajima
22786797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic inline void pit_load_count(PITChannelState *s, int val)
22886797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
22986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (val == 0)
23086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        val = 0x10000;
231dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
23286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->count = val;
23386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    pit_irq_timer_update(s, s->count_load_time);
23486797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
23586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
23686797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* if already latched, do not latch again */
23786797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pit_latch_count(PITChannelState *s)
23886797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
23986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!s->count_latched) {
24086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->latched_count = pit_get_count(s);
24186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->count_latched = s->rw_mode;
24286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
24386797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
24486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
24586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
24686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
24786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITState *pit = opaque;
24886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int channel, access;
24986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s;
25086797937017f52bff088d02edf64fb931177a7eaJun Nakajima
25186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    addr &= 3;
25286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (addr == 3) {
25386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        channel = val >> 6;
25486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (channel == 3) {
25586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            /* read back command */
25686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            for(channel = 0; channel < 3; channel++) {
25786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s = &pit->channels[channel];
25886797937017f52bff088d02edf64fb931177a7eaJun Nakajima                if (val & (2 << channel)) {
25986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    if (!(val & 0x20)) {
26086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        pit_latch_count(s);
26186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    }
26286797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    if (!(val & 0x10) && !s->status_latched) {
26386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        /* status latch */
26486797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        /* XXX: add BCD and null count */
265dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner                        s->status =  (pit_get_out1(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) << 7) |
26686797937017f52bff088d02edf64fb931177a7eaJun Nakajima                            (s->rw_mode << 4) |
26786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                            (s->mode << 1) |
26886797937017f52bff088d02edf64fb931177a7eaJun Nakajima                            s->bcd;
26986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                        s->status_latched = 1;
27086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                    }
27186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                }
27286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            }
27386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        } else {
27486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s = &pit->channels[channel];
27586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            access = (val >> 4) & 3;
27686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            if (access == 0) {
27786797937017f52bff088d02edf64fb931177a7eaJun Nakajima                pit_latch_count(s);
27886797937017f52bff088d02edf64fb931177a7eaJun Nakajima            } else {
27986797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->rw_mode = access;
28086797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->read_state = access;
28186797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->write_state = access;
28286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
28386797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->mode = (val >> 1) & 7;
28486797937017f52bff088d02edf64fb931177a7eaJun Nakajima                s->bcd = val & 1;
28586797937017f52bff088d02edf64fb931177a7eaJun Nakajima                /* XXX: update irq timer ? */
28686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            }
28786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
28886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    } else {
28986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s = &pit->channels[addr];
29086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        switch(s->write_state) {
29186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        default:
29286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_LSB:
29386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            pit_load_count(s, val);
29486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
29586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_MSB:
29686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            pit_load_count(s, val << 8);
29786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
29886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_WORD0:
29986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->write_latch = val;
30086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->write_state = RW_STATE_WORD1;
30186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
30286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_WORD1:
30386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            pit_load_count(s, s->write_latch | (val << 8));
30486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->write_state = RW_STATE_WORD0;
30586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
30686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
30786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
30886797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
30986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
31086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint32_t pit_ioport_read(void *opaque, uint32_t addr)
31186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
31286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITState *pit = opaque;
31386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int ret, count;
31486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s;
31586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
31686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    addr &= 3;
31786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s = &pit->channels[addr];
31886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (s->status_latched) {
31986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->status_latched = 0;
32086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        ret = s->status;
32186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    } else if (s->count_latched) {
32286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        switch(s->count_latched) {
32386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        default:
32486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_LSB:
32586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ret = s->latched_count & 0xff;
32686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->count_latched = 0;
32786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
32886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_MSB:
32986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ret = s->latched_count >> 8;
33086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->count_latched = 0;
33186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
33286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_WORD0:
33386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ret = s->latched_count & 0xff;
33486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->count_latched = RW_STATE_MSB;
33586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
33686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
33786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    } else {
33886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        switch(s->read_state) {
33986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        default:
34086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_LSB:
34186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            count = pit_get_count(s);
34286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ret = count & 0xff;
34386797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
34486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_MSB:
34586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            count = pit_get_count(s);
34686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ret = (count >> 8) & 0xff;
34786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
34886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_WORD0:
34986797937017f52bff088d02edf64fb931177a7eaJun Nakajima            count = pit_get_count(s);
35086797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ret = count & 0xff;
35186797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->read_state = RW_STATE_WORD1;
35286797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
35386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        case RW_STATE_WORD1:
35486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            count = pit_get_count(s);
35586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            ret = (count >> 8) & 0xff;
35686797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->read_state = RW_STATE_WORD0;
35786797937017f52bff088d02edf64fb931177a7eaJun Nakajima            break;
35886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
35986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
36086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return ret;
36186797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
36286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
36386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
36486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
36586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int64_t expire_time;
36686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int irq_level;
36786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
36886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (!s->irq_timer)
36986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return;
37086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    expire_time = pit_get_next_transition_time(s, current_time);
37186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    irq_level = pit_get_out1(s, current_time);
37286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_set_irq(s->irq, irq_level);
37386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_PIT
37486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    printf("irq_level=%d next_delay=%f\n",
37586797937017f52bff088d02edf64fb931177a7eaJun Nakajima           irq_level,
37686797937017f52bff088d02edf64fb931177a7eaJun Nakajima           (double)(expire_time - current_time) / get_ticks_per_sec());
37786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif
37886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->next_transition_time = expire_time;
37986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (expire_time != -1)
380dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_mod(s->irq_timer, expire_time);
38186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    else
382dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_del(s->irq_timer);
38386797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
38486797937017f52bff088d02edf64fb931177a7eaJun Nakajima
38586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pit_irq_timer(void *opaque)
38686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
38786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s = opaque;
38886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
38986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    pit_irq_timer_update(s, s->next_transition_time);
39086797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
39186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
39286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pit_save(QEMUFile *f, void *opaque)
39386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
39486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITState *pit = opaque;
39586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s;
39686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i;
39786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
39886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for(i = 0; i < 3; i++) {
39986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s = &pit->channels[i];
40086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_be32(f, s->count);
40186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_be16s(f, &s->latched_count);
40286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->count_latched);
40386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->status_latched);
40486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->status);
40586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->read_state);
40686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->write_state);
40786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->write_latch);
40886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->rw_mode);
40986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->mode);
41086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->bcd);
41186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_8s(f, &s->gate);
41286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_put_be64(f, s->count_load_time);
41386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (s->irq_timer) {
41486797937017f52bff088d02edf64fb931177a7eaJun Nakajima            qemu_put_be64(f, s->next_transition_time);
415dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            timer_put(f, s->irq_timer);
41686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
41786797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
41886797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
41986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
42086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int pit_load(QEMUFile *f, void *opaque, int version_id)
42186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
42286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITState *pit = opaque;
42386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s;
42486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i;
42586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
42686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (version_id != 1)
42786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        return -EINVAL;
42886797937017f52bff088d02edf64fb931177a7eaJun Nakajima
42986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for(i = 0; i < 3; i++) {
43086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s = &pit->channels[i];
43186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->count=qemu_get_be32(f);
43286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_be16s(f, &s->latched_count);
43386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->count_latched);
43486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->status_latched);
43586797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->status);
43686797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->read_state);
43786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->write_state);
43886797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->write_latch);
43986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->rw_mode);
44086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->mode);
44186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->bcd);
44286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        qemu_get_8s(f, &s->gate);
44386797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->count_load_time=qemu_get_be64(f);
44486797937017f52bff088d02edf64fb931177a7eaJun Nakajima        if (s->irq_timer) {
44586797937017f52bff088d02edf64fb931177a7eaJun Nakajima            s->next_transition_time=qemu_get_be64(f);
446dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner            timer_get(f, s->irq_timer);
44786797937017f52bff088d02edf64fb931177a7eaJun Nakajima        }
44886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
44986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return 0;
45086797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
45186797937017f52bff088d02edf64fb931177a7eaJun Nakajima
45286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pit_reset(void *opaque)
45386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
45486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITState *pit = opaque;
45586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s;
45686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    int i;
45786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
45886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    for(i = 0;i < 3; i++) {
45986797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s = &pit->channels[i];
46086797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->mode = 3;
46186797937017f52bff088d02edf64fb931177a7eaJun Nakajima        s->gate = (i != 2);
46286797937017f52bff088d02edf64fb931177a7eaJun Nakajima        pit_load_count(s, 0);
46386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    }
46486797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
46586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
46686797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* When HPET is operating in legacy mode, i8254 timer0 is disabled */
46786797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid hpet_pit_disable(void) {
46886797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s;
46986797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s = &pit_state.channels[0];
47086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    if (s->irq_timer)
471dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_del(s->irq_timer);
47286797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
47386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
47486797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* When HPET is reset or leaving legacy mode, it must reenable i8254
47586797937017f52bff088d02edf64fb931177a7eaJun Nakajima * timer 0
47686797937017f52bff088d02edf64fb931177a7eaJun Nakajima */
47786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
47886797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid hpet_pit_enable(void)
47986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
48086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITState *pit = &pit_state;
48186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s;
48286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s = &pit->channels[0];
48386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->mode = 3;
48486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->gate = 1;
48586797937017f52bff088d02edf64fb931177a7eaJun Nakajima    pit_load_count(s, 0);
48686797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
48786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
48886797937017f52bff088d02edf64fb931177a7eaJun NakajimaPITState *pit_init(int base, qemu_irq irq)
48986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{
49086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITState *pit = &pit_state;
49186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    PITChannelState *s;
49286797937017f52bff088d02edf64fb931177a7eaJun Nakajima
49386797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s = &pit->channels[0];
49486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    /* the timer 0 is connected to an IRQ */
495dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    s->irq_timer = timer_new(QEMU_CLOCK_VIRTUAL, SCALE_NS, pit_irq_timer, s);
49686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    s->irq = irq;
49786797937017f52bff088d02edf64fb931177a7eaJun Nakajima
4985cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner    register_savevm(NULL, "i8254", base, 1, pit_save, pit_load, pit);
49986797937017f52bff088d02edf64fb931177a7eaJun Nakajima
50086797937017f52bff088d02edf64fb931177a7eaJun Nakajima    qemu_register_reset(pit_reset, 0, pit);
50186797937017f52bff088d02edf64fb931177a7eaJun Nakajima    register_ioport_write(base, 4, 1, pit_ioport_write, pit);
50286797937017f52bff088d02edf64fb931177a7eaJun Nakajima    register_ioport_read(base, 3, 1, pit_ioport_read, pit);
50386797937017f52bff088d02edf64fb931177a7eaJun Nakajima
50486797937017f52bff088d02edf64fb931177a7eaJun Nakajima    pit_reset(pit);
50586797937017f52bff088d02edf64fb931177a7eaJun Nakajima
50686797937017f52bff088d02edf64fb931177a7eaJun Nakajima    return pit;
50786797937017f52bff088d02edf64fb931177a7eaJun Nakajima}
508