@@ -47,6 +47,7 @@
uint8_t bcd; /* not supported */
uint8_t gate; /* timer start */
int64_t count_load_time;
+ uint64_t frequency;
/* irq handling */
int64_t next_transition_time;
QEMUTimer *irq_timer;
@@ -66,7 +67,7 @@
uint64_t d;
int counter;
- d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec);
+ d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, s->frequency, ticks_per_sec);
switch(s->mode) {
case 0:
case 1:
@@ -91,7 +92,7 @@
uint64_t d;
int out;
- d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
+ d = muldiv64(current_time - s->count_load_time, s->frequency, ticks_per_sec);
switch(s->mode) {
default:
case 0:
@@ -130,7 +131,7 @@
uint64_t d, next_time, base;
int period2;
- d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
+ d = muldiv64(current_time - s->count_load_time, s->frequency, ticks_per_sec);
switch(s->mode) {
default:
case 0:
@@ -166,7 +167,7 @@
break;
}
/* convert to timer units */
- next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ);
+ next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, s->frequency);
/* fix potential rounding problems */
/* XXX: better solution: use a clock at PIT_FREQ Hz */
if (next_time <= current_time)
@@ -494,22 +495,65 @@
pit_load_count(s, 0);
}
-PITState *pit_init(int base, qemu_irq irq)
+static void pit_init_common(PITState *pit, int base, qemu_irq irq, uint64_t frequency)
{
- PITState *pit = &pit_state;
PITChannelState *s;
+ int i;
s = &pit->channels[0];
/* the timer 0 is connected to an IRQ */
s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
s->irq = irq;
+ for (i = 0; i < 3; i++) {
+ pit->channels[i].frequency = frequency;
+ }
+
vmstate_register(base, &vmstate_pit, pit);
qemu_register_reset(pit_reset, pit);
+
+ pit_reset(pit);
+}
+
+PITState *pit_init(int base, qemu_irq irq)
+{
+ PITState *pit = &pit_state;
+
+ pit_init_common(pit, base, irq, PIT_FREQ);
+
register_ioport_write(base, 4, 1, pit_ioport_write, pit);
register_ioport_read(base, 3, 1, pit_ioport_read, pit);
- pit_reset(pit);
+ return pit;
+}
+
+/* NEC PC-98x1 */
+
+static void pc98_pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ pit_ioport_write(opaque, addr >> 1, val);
+}
+
+static uint32_t pc98_pit_ioport_read(void *opaque, uint32_t addr)
+{
+ return pit_ioport_read(opaque, addr >> 1);
+}
+
+PITState *pc98_pit_init(int base, qemu_irq irq)
+{
+ PITState *pit = &pit_state;
+ int i;
+
+ pit_init_common(pit, base, irq, PIT_FREQ);
+
+ for (i = 0; i < 4; i++) {
+ register_ioport_write(0x71 + (i << 1), 1, 1, pc98_pit_ioport_write, pit);
+ register_ioport_write(0x3fd9 + (i << 1), 1, 1, pc98_pit_ioport_write, pit);
+ }
+ for (i = 0; i < 3; i++) {
+ register_ioport_read(0x71 + (i << 1), 1, 1, pc98_pit_ioport_read, pit);
+ register_ioport_read(0x3fd9 + (i << 1), 1, 1, pc98_pit_ioport_read, pit);
+ }
return pit;
}