-/* $OpenBSD: i8253.c,v 1.13 2017/04/08 19:06:04 mlarkin Exp $ */
+/* $OpenBSD: i8253.c,v 1.14 2017/04/28 08:14:48 mlarkin Exp $ */
/*
* Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
*
extern char *__progname;
/*
- * Counter 0 is used to generate the legacy hardclock interrupt (HZ).
- * Counters 1 and 2 are not connected to any output (although someone
- * could hook counter 2 up to an emulated pcppi(4) at some point).
+ * Channel 0 is used to generate the legacy hardclock interrupt (HZ).
+ * Channels 1 and 2 are not connected to any output (although someone
+ * could hook channel 2 up to an emulated pcppi(4) at some point).
*/
-struct i8253_counter i8253_counter[3];
+struct i8253_channel i8253_channel[3];
/*
* i8253_init
void
i8253_init(uint32_t vm_id)
{
- memset(&i8253_counter, 0, sizeof(struct i8253_counter));
- gettimeofday(&i8253_counter[0].tv, NULL);
- i8253_counter[0].start = 0xFFFF;
- i8253_counter[0].mode = TIMER_INTTC;
- i8253_counter[0].last_r = 1;
- i8253_counter[0].vm_id = vm_id;
-
- i8253_counter[1].start = 0xFFFF;
- i8253_counter[1].mode = TIMER_INTTC;
- i8253_counter[1].last_r = 1;
- i8253_counter[1].vm_id = vm_id;
-
- i8253_counter[2].start = 0xFFFF;
- i8253_counter[2].mode = TIMER_INTTC;
- i8253_counter[2].last_r = 1;
- i8253_counter[2].vm_id = vm_id;
-
- evtimer_set(&i8253_counter[0].timer, i8253_fire, &i8253_counter[0]);
- evtimer_set(&i8253_counter[1].timer, i8253_fire, &i8253_counter[1]);
- evtimer_set(&i8253_counter[2].timer, i8253_fire, &i8253_counter[2]);
+ memset(&i8253_channel, 0, sizeof(struct i8253_channel));
+ gettimeofday(&i8253_channel[0].tv, NULL);
+ i8253_channel[0].start = 0xFFFF;
+ i8253_channel[0].mode = TIMER_INTTC;
+ i8253_channel[0].last_r = 1;
+ i8253_channel[0].vm_id = vm_id;
+
+ i8253_channel[1].start = 0xFFFF;
+ i8253_channel[1].mode = TIMER_INTTC;
+ i8253_channel[1].last_r = 1;
+ i8253_channel[1].vm_id = vm_id;
+
+ i8253_channel[2].start = 0xFFFF;
+ i8253_channel[2].mode = TIMER_INTTC;
+ i8253_channel[2].last_r = 1;
+ i8253_channel[2].vm_id = vm_id;
+
+ evtimer_set(&i8253_channel[0].timer, i8253_fire, &i8253_channel[0]);
+ evtimer_set(&i8253_channel[1].timer, i8253_fire, &i8253_channel[1]);
+ evtimer_set(&i8253_channel[2].timer, i8253_fire, &i8253_channel[2]);
}
/*
/* bits are inverted here - !TIMER_RB_STATUS == enable chan readback */
if (data & ~TIMER_RB_STATUS) {
- i8253_counter[0].rbs = (data & TIMER_RB_C0) ? 1 : 0;
- i8253_counter[1].rbs = (data & TIMER_RB_C1) ? 1 : 0;
- i8253_counter[2].rbs = (data & TIMER_RB_C2) ? 1 : 0;
+ i8253_channel[0].rbs = (data & TIMER_RB_C0) ? 1 : 0;
+ i8253_channel[1].rbs = (data & TIMER_RB_C1) ? 1 : 0;
+ i8253_channel[2].rbs = (data & TIMER_RB_C2) ? 1 : 0;
}
/* !TIMER_RB_COUNT == enable counter readback */
if (data & ~TIMER_RB_COUNT) {
if (data & TIMER_RB_C0) {
gettimeofday(&now, NULL);
- delta.tv_sec = now.tv_sec - i8253_counter[0].tv.tv_sec;
+ delta.tv_sec = now.tv_sec - i8253_channel[0].tv.tv_sec;
delta.tv_usec = now.tv_usec -
- i8253_counter[0].tv.tv_usec;
+ i8253_channel[0].tv.tv_usec;
if (delta.tv_usec < 0) {
delta.tv_sec--;
delta.tv_usec += 1000000;
}
ns = delta.tv_usec * 1000 + delta.tv_sec * 1000000000;
ticks = ns / NS_PER_TICK;
- if (i8253_counter[0].start)
- i8253_counter[0].olatch =
- i8253_counter[0].start -
- ticks % i8253_counter[0].start;
+ if (i8253_channel[0].start)
+ i8253_channel[0].olatch =
+ i8253_channel[0].start -
+ ticks % i8253_channel[0].start;
else
- i8253_counter[0].olatch = 0;
+ i8253_channel[0].olatch = 0;
}
if (data & TIMER_RB_C1) {
gettimeofday(&now, NULL);
- delta.tv_sec = now.tv_sec - i8253_counter[1].tv.tv_sec;
+ delta.tv_sec = now.tv_sec - i8253_channel[1].tv.tv_sec;
delta.tv_usec = now.tv_usec -
- i8253_counter[1].tv.tv_usec;
+ i8253_channel[1].tv.tv_usec;
if (delta.tv_usec < 0) {
delta.tv_sec--;
delta.tv_usec += 1000000;
}
ns = delta.tv_usec * 1000 + delta.tv_sec * 1000000000;
ticks = ns / NS_PER_TICK;
- if (i8253_counter[1].start)
- i8253_counter[1].olatch =
- i8253_counter[1].start -
- ticks % i8253_counter[1].start;
+ if (i8253_channel[1].start)
+ i8253_channel[1].olatch =
+ i8253_channel[1].start -
+ ticks % i8253_channel[1].start;
else
- i8253_counter[1].olatch = 0;
+ i8253_channel[1].olatch = 0;
}
if (data & TIMER_RB_C2) {
gettimeofday(&now, NULL);
- delta.tv_sec = now.tv_sec - i8253_counter[2].tv.tv_sec;
+ delta.tv_sec = now.tv_sec - i8253_channel[2].tv.tv_sec;
delta.tv_usec = now.tv_usec -
- i8253_counter[2].tv.tv_usec;
+ i8253_channel[2].tv.tv_usec;
if (delta.tv_usec < 0) {
delta.tv_sec--;
delta.tv_usec += 1000000;
}
ns = delta.tv_usec * 1000 + delta.tv_sec * 1000000000;
ticks = ns / NS_PER_TICK;
- if (i8253_counter[2].start)
- i8253_counter[2].olatch =
- i8253_counter[2].start -
- ticks % i8253_counter[2].start;
+ if (i8253_channel[2].start)
+ i8253_channel[2].olatch =
+ i8253_channel[2].start -
+ ticks % i8253_channel[2].start;
else
- i8253_counter[2].olatch = 0;
+ i8253_channel[2].olatch = 0;
}
}
}
* vcpu_exit_i8253
*
* Handles emulated i8253 PIT access (in/out instruction to PIT ports).
- * We don't emulate all the modes of the i8253, just the basic squarewave
- * "rategen" clock.
*
* Parameters:
* vrp: vm run parameters containing exit information for the I/O
if (rw == TIMER_LATCH) {
gettimeofday(&now, NULL);
delta.tv_sec = now.tv_sec -
- i8253_counter[sel].tv.tv_sec;
+ i8253_channel[sel].tv.tv_sec;
delta.tv_usec = now.tv_usec -
- i8253_counter[sel].tv.tv_usec;
+ i8253_channel[sel].tv.tv_usec;
if (delta.tv_usec < 0) {
delta.tv_sec--;
delta.tv_usec += 1000000;
ns = delta.tv_usec * 1000 +
delta.tv_sec * 1000000000;
ticks = ns / NS_PER_TICK;
- if (i8253_counter[sel].start) {
- i8253_counter[sel].olatch =
- i8253_counter[sel].start -
- ticks % i8253_counter[sel].start;
+ if (i8253_channel[sel].start) {
+ i8253_channel[sel].olatch =
+ i8253_channel[sel].start -
+ ticks % i8253_channel[sel].start;
} else
- i8253_counter[sel].olatch = 0;
+ i8253_channel[sel].olatch = 0;
goto ret;
} else if (rw != TIMER_16BIT) {
log_warnx("%s: i8253 PIT: unsupported counter "
sel = vei->vei.vei_port - (TIMER_CNTR0 + TIMER_BASE);
if (vei->vei.vei_dir == VEI_DIR_OUT) { /* OUT instruction */
- if (i8253_counter[sel].last_w == 0) {
- i8253_counter[sel].ilatch |= (out_data & 0xff);
- i8253_counter[sel].last_w = 1;
+ if (i8253_channel[sel].last_w == 0) {
+ i8253_channel[sel].ilatch |= (out_data & 0xff);
+ i8253_channel[sel].last_w = 1;
} else {
- i8253_counter[sel].ilatch |= ((out_data & 0xff) << 8);
- i8253_counter[sel].start =
- i8253_counter[sel].ilatch;
- i8253_counter[sel].last_w = 0;
+ i8253_channel[sel].ilatch |= ((out_data & 0xff) << 8);
+ i8253_channel[sel].start =
+ i8253_channel[sel].ilatch;
+ i8253_channel[sel].last_w = 0;
mode = (out_data & 0xe) >> 1;
- if (i8253_counter[sel].start == 0)
- i8253_counter[sel].start = 0xffff;
+ if (i8253_channel[sel].start == 0)
+ i8253_channel[sel].start = 0xffff;
log_debug("%s: channel %d reset, mode=%d, start=%d", __func__,
- sel, mode, i8253_counter[sel].start);
- i8253_counter[sel].mode = mode;
+ sel, mode, i8253_channel[sel].start);
+ i8253_channel[sel].mode = mode;
i8253_reset(sel);
}
} else {
- if (i8253_counter[sel].rbs) {
- i8253_counter[sel].rbs = 0;
- data = i8253_counter[sel].mode << 1;
+ if (i8253_channel[sel].rbs) {
+ i8253_channel[sel].rbs = 0;
+ data = i8253_channel[sel].mode << 1;
data |= TIMER_16BIT;
set_return_data(vei, data);
goto ret;
}
- if (i8253_counter[sel].last_r == 0) {
- data = i8253_counter[sel].olatch >> 8;
+ if (i8253_channel[sel].last_r == 0) {
+ data = i8253_channel[sel].olatch >> 8;
set_return_data(vei, data);
- i8253_counter[sel].last_r = 1;
+ i8253_channel[sel].last_r = 1;
} else {
- data = i8253_counter[sel].olatch & 0xFF;
+ data = i8253_channel[sel].olatch & 0xFF;
set_return_data(vei, data);
- i8253_counter[sel].last_r = 0;
+ i8253_channel[sel].last_r = 0;
}
}
}
{
struct timeval tv;
- evtimer_del(&i8253_counter[chn].timer);
+ evtimer_del(&i8253_channel[chn].timer);
timerclear(&tv);
- tv.tv_usec = (i8253_counter[chn].start * NS_PER_TICK) / 1000;
- evtimer_add(&i8253_counter[chn].timer, &tv);
+ tv.tv_usec = (i8253_channel[chn].start * NS_PER_TICK) / 1000;
+ evtimer_add(&i8253_channel[chn].timer, &tv);
}
/*
i8253_fire(int fd, short type, void *arg)
{
struct timeval tv;
- struct i8253_counter *ctr = (struct i8253_counter *)arg;
+ struct i8253_channel *ctr = (struct i8253_channel *)arg;
timerclear(&tv);
tv.tv_usec = (ctr->start * NS_PER_TICK) / 1000;