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