+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
#include <devices/8254.h>
#include <palacios/vmm.h>
#include <palacios/vmm_time.h>
-
+#ifndef DEBUG_PIT
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
return output_changed;
} else {
ushort_t reload_val = ch->reload_value;
+
+ // TODO: Check this....
+ // Is this correct???
+ if (reload_val == 0) {
+ reload_val = 1;
+ }
+
oscillations -= ch->counter;
ch->counter = 0;
channel_cycles = 1;
-
if (ch->op_mode == SQR_WAVE) {
reload_val -= reload_val % 2;
}
-
+
channel_cycles += oscillations / reload_val;
oscillations = oscillations % reload_val;
// Easy...
state->pit_counter -= cpu_cycles;
} else {
-
+ ushort_t reload_val = state->pit_reload;
// Take off the first part
cpu_cycles -= state->pit_counter;
state->pit_counter = 0;
if (cpu_cycles > state->pit_reload) {
// how many full oscillations
+
+ // PrintError("cpu_cycles = %p, reload = %p...\n",
+ // (void *)(addr_t)cpu_cycles,
+ // (void *)(addr_t)state->pit_reload);
+
+ // How do we check for a one shot....
+ if (state->pit_reload == 0) {
+ reload_val = 1;
+ }
+
tmp_cycles = cpu_cycles;
+
+#ifdef __V3_64BIT__
+ cpu_cycles = tmp_cycles / state->pit_reload;
+ tmp_cycles = tmp_cycles % state->pit_reload;
+#else
cpu_cycles = do_divll(tmp_cycles, state->pit_reload);
-
+#endif
+
oscillations += tmp_cycles;
}
char * val = (char *)dst;
if (length != 1) {
- PrintDebug("8254 PIT: Invalid Read Write length \n");
+ PrintError("8254 PIT: Invalid Read Write length \n");
return -1;
}
}
break;
default:
- PrintDebug("8254 PIT: Read from invalid port (%d)\n", port);
+ PrintError("8254 PIT: Read from invalid port (%d)\n", port);
return -1;
}
char val = *(char *)src;
if (length != 1) {
- PrintDebug("8254 PIT: Invalid Write Length\n");
+ PrintError("8254 PIT: Invalid Write Length\n");
return -1;
}
}
break;
default:
- PrintDebug("8254 PIT: Write to invalid port (%d)\n", port);
+ PrintError("8254 PIT: Write to invalid port (%d)\n", port);
return -1;
}
PrintDebug("8254 PIT: Write to PIT Command port\n");
PrintDebug("8254 PIT: Writing to channel %d (access_mode = %d, op_mode = %d)\n", cmd->channel, cmd->access_mode, cmd->op_mode);
if (length != 1) {
- PrintDebug("8254 PIT: Write of Invalid length to command port\n");
+ PrintError("8254 PIT: Write of Invalid length to command port\n");
return -1;
}
uint_t cpu_khz = V3_CPU_KHZ();
ullong_t reload_val = (ullong_t)cpu_khz * 1000;
- dev_hook_io(dev, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel);
- dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
- dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
- dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
+ v3_dev_hook_io(dev, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel);
+ v3_dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
+ v3_dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
+ v3_dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
+#ifdef DEBUG_PIT
PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
PrintTraceLL(reload_val);
PrintDebug("\n");
-
+#endif
v3_add_timer(dev->vm, &timer_ops, dev);
init_channel(&(state->ch_1));
init_channel(&(state->ch_2));
+#ifdef DEBUG_PIT
PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
PrintTraceLL(state->pit_counter);
PrintDebug("\n");
+#endif
return 0;
}
};
-struct vm_device * create_pit() {
+struct vm_device * v3_create_pit() {
struct pit * pit_state = NULL;
pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
V3_ASSERT(pit_state != NULL);
- struct vm_device * dev = create_device("PIT", &dev_ops, pit_state);
+ struct vm_device * dev = v3_create_device("PIT", &dev_ops, pit_state);
return dev;
}