X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2F8254.c;h=2f589e5edd1a769fb756a86261151ad132af7453;hp=b11fb7e3637f484a9f55ee6f971a3b852e8607ef;hb=90b8236597004a37a9d5acb33a1b1f987fe9070c;hpb=d8fc6aa4bc2a5d9cec50923e9d2bd30f867dd50a diff --git a/palacios/src/devices/8254.c b/palacios/src/devices/8254.c index b11fb7e..2f589e5 100644 --- a/palacios/src/devices/8254.c +++ b/palacios/src/devices/8254.c @@ -29,56 +29,203 @@ struct channel { channel_op_mode_t op_mode; + + // Time til interrupt trigger - ullong_t ns; - uint_t ctr; - uint_t prg_ctr; + ushort_t counter; + ushort_t reload_value; + + uint_t output_pin : 1; + uint_t gate_input_pin : 1; }; struct pit { + ullong_t pit_counter; + ullong_t pit_reload; + + struct channel ch_0; struct channel ch_1; struct channel ch_2; }; -struct pit_cmd { - uint_t channel : 2; - uint_t access_mode : 2; - uint_t op_mode : 3; + +struct pit_cmd_word { uint_t bcd_mode : 1; + uint_t op_mode : 3; + uint_t access_mode : 2; + uint_t channel : 2; +}; + +struct pit_rdb_cmd_word { + uint_t rsvd : 1; // SBZ + uint_t ch_0 : 1; + uint_t ch_1 : 1; + uint_t ch_2 : 1; + uint_t latch_status : 1; + uint_t latch_count : 1; + uint_t readback_cmd : 2; // Must Be 0x3 }; +struct pit_rdb_status_word { + uint_t bcd_mode : 1; + uint_t op_mode : 3; + uint_t access_mode : 2; + uint_t null_count : 1; + uint_t pin_state : 1; +}; static void pit_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) { - + PrintDebug("Adding %d cycles\n", cpu_cycles); + return; } +static int handle_channel_write(struct channel * ch, char val) { + // switch (ch->access_mode) { + + + //} + + + return -1; +} + + +static int handle_channel_read(struct channel * ch, char * val) { + return -1; +} + + + + + +static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) { + ch->op_mode = cmd.op_mode; + ch->access_mode = cmd.access_mode; + + switch (cmd.access_mode) { + case LATCH_COUNT: + return -1; + break; + case HIBYTE_ONLY: + ch->access_state = WAITING_HIBYTE; + break; + case LOBYTE_ONLY: + case LOBYTE_HIBYTE: + ch->access_state = WAITING_LOBYTE; + break; + } + + + switch (cmd.op_mode) { + case IRQ_ON_TERM_CNT: + ch->output_pin = 0; + break; + case ONE_SHOT: + ch->output_pin = 1; + break; + case RATE_GEN: + ch->output_pin = 1; + break; + default: + return -1; + } + + return 0; + +} + + + static int pit_read_channel(ushort_t port, void * dst, uint_t length, struct vm_device * dev) { + struct pit * state = (struct pit *)dev->private_data; + char * val = (char *)dst; + + if (length != 1) { + PrintDebug("8254 PIT: Invalid Read Write length \n"); + return -1; + } + PrintDebug("8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT); + + switch (port) { + case CHANNEL0_PORT: + if (handle_channel_read(&(state->ch_0), val) == -1) { + return -1; + } + break; + case CHANNEL1_PORT: + if (handle_channel_read(&(state->ch_1), val) == -1) { + return -1; + } + break; + case CHANNEL2_PORT: + if (handle_channel_read(&(state->ch_2), val) == -1) { + return -1; + } + break; + default: + PrintDebug("8254 PIT: Read from invalid port (%d)\n", port); + return -1; + } + return length; } static int pit_write_channel(ushort_t port, void * src, uint_t length, struct vm_device * dev) { + struct pit * state = (struct pit *)dev->private_data; + char val = *(char *)src; + + if (length != 1) { + PrintDebug("8254 PIT: Invalid Write Length\n"); + return -1; + } + PrintDebug("8254 PIT: Write to PIT Channel %d\n", port - CHANNEL0_PORT); + + + switch (port) { + case CHANNEL0_PORT: + if (handle_channel_write(&(state->ch_0), val) == -1) { + return -1; + } + break; + case CHANNEL1_PORT: + if (handle_channel_write(&(state->ch_1), val) == -1) { + return -1; + } + break; + case CHANNEL2_PORT: + if (handle_channel_write(&(state->ch_2), val) == -1) { + return -1; + } + break; + default: + PrintDebug("8254 PIT: Write to invalid port (%d)\n", port); + return -1; + } + return length; } + + static int pit_write_command(ushort_t port, void * src, uint_t length, struct vm_device * dev) { struct pit * state = (struct pit *)dev->private_data; - struct pit_cmd * cmd = (struct pit_cmd *)src; + struct pit_cmd_word * cmd = (struct pit_cmd_word *)src; PrintDebug("8254 PIT: Write to PIT Command port\n"); @@ -89,11 +236,23 @@ static int pit_write_command(ushort_t port, void * src, uint_t length, struct vm switch (cmd->channel) { case 0: - state->ch_0.op_mode = cmd->op_mode; + if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) { + return -1; + } break; case 1: + if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) { + return -1; + } break; case 2: + if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) { + return -1; + } + break; + case 3: + // Read Back command + return -1; break; default: break; @@ -120,6 +279,9 @@ static int pit_init(struct vm_device * dev) { v3_add_timer(dev->vm, &timer_ops, dev); + // Get cpu frequency and calculate the global pit oscilattor counter/cycle + + return 0; }