#define CHANNEL1_PORT 0x41
#define CHANNEL2_PORT 0x42
#define COMMAND_PORT 0x43
+#define SPEAKER_PORT 0x61
#define PIT_INTR_NUM 0
+#define PIT_SPEAKER_GATE 0x01
/* The order of these typedefs is important because the numerical values correspond to the
* values coming from the io ports
struct channel ch_0;
struct channel ch_1;
struct channel ch_2;
+ uint8_t speaker;
};
reload_val = 0xffff;
}
- // TODO: Check this....
- // Is this correct???
- if (reload_val == 0) {
- reload_val = 1;
- }
-
oscillations -= ch->counter;
ch->counter = 0;
channel_cycles = 1;
reload_val -= reload_val % 2;
}
+ // TODO: Check this....
+ // Is this correct???
+ if (reload_val == 0) {
+ reload_val = 1;
+ }
+
channel_cycles += oscillations / reload_val;
oscillations = oscillations % reload_val;
#include <palacios/vm_guest.h>
-static void pit_update_time(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) {
+static void pit_update_timer(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) {
struct vm_device * dev = (struct vm_device *)private_data;
struct pit * state = (struct pit *)dev->private_data;
// ullong_t tmp_ctr = state->pit_counter;
}
//handle_crystal_tics(dev, &(state->ch_1), oscillations);
- //handle_crystal_tics(dev, &(state->ch_2), oscillations);
+ handle_crystal_tics(dev, &(state->ch_2), oscillations);
}
return;
}
-
-static void pit_advance_time(struct guest_info * core, void * private_data) {
-
- v3_raise_irq(core->vm_info, 0);
-}
-
-
-
/* This should call out to handle_SQR_WAVE_write, etc...
*/
static int handle_channel_write(struct channel * ch, char val) {
}
+static int handle_speaker_read(uint8_t *speaker, struct channel * ch, char * val) {
+ *val = *speaker;
+ if ((*speaker & PIT_SPEAKER_GATE)) {
+ *val |= (ch->output_pin << 5);
+ }
+
+ return 0;
+}
-
+static int handle_speaker_write(uint8_t *speaker, struct channel * ch, char val) {
+ *speaker = (val & ~0x20);
+ return 0;
+}
static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
ch->op_mode = cmd.op_mode;
return -1;
}
break;
+ case SPEAKER_PORT:
+ if (handle_speaker_read(&state->speaker, &(state->ch_2), val) == -1) {
+ PrintError("SPEAKER read error\n");
+ return -1;
+ }
+ break;
default:
PrintError("8254 PIT: Read from invalid port (%d)\n", port);
return -1;
return -1;
}
break;
+ case SPEAKER_PORT:
+ if (handle_speaker_write(&state->speaker, &(state->ch_2), val) == -1) {
+ PrintError("SPEAKER write error\n");
+ return -1;
+ }
+ break;
default:
PrintError("8254 PIT: Write to invalid port (%d)\n", port);
return -1;
static struct vm_timer_ops timer_ops = {
- .update_time = pit_update_time,
- .advance_timer = pit_advance_time,
+ .update_timer = pit_update_timer,
};
static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct pit * pit_state = NULL;
struct vm_device * dev = NULL;
- char * name = v3_cfg_val(cfg, "name");
+ char * dev_id = v3_cfg_val(cfg, "ID");
// PIT is only usable in non-multicore environments
// just hardcode the core context
pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
V3_ASSERT(pit_state != NULL);
+ pit_state->speaker = 0;
- dev = v3_allocate_device(name, &dev_ops, pit_state);
+ dev = v3_allocate_device(dev_id, &dev_ops, pit_state);
if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", name);
+ PrintError("Could not attach device %s\n", dev_id);
return -1;
}
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);
+ v3_dev_hook_io(dev, SPEAKER_PORT, &pit_read_channel, &pit_write_channel);
#ifdef CONFIG_DEBUG_PIT
PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);