X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2F8254.c;h=7c0de12cea197b03e84175c9689b9efb707f4de4;hb=20885b915c6caf47c8bd78d7b5b492fef388ac2d;hp=60ae891dea80d07ab57e99f455849099e1421bb1;hpb=a4b341afa075a6620dd087ee3a8ed850730c05c7;p=palacios-OLD.git diff --git a/palacios/src/devices/8254.c b/palacios/src/devices/8254.c index 60ae891..7c0de12 100644 --- a/palacios/src/devices/8254.c +++ b/palacios/src/devices/8254.c @@ -2,6 +2,7 @@ #include #include #include +#include @@ -44,6 +45,12 @@ struct channel { ushort_t counter; ushort_t reload_value; + ushort_t latched_value; + + enum {NOTLATCHED, LATCHED} latch_state; + + enum {LSB, MSB} read_state; + uint_t output_pin : 1; uint_t gate_input_pin : 1; }; @@ -233,7 +240,7 @@ static void pit_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * priva if (handle_crystal_tics(dev, &(state->ch_0), oscillations) == 1) { // raise interrupt PrintDebug("8254 PIT: Injecting Timer interrupt to guest\n"); - dev->vm->vm_ops.raise_irq(dev->vm, 0); + v3_raise_irq(dev->vm, 0); } //handle_crystal_tics(dev, &(state->ch_1), oscillations); @@ -314,7 +321,28 @@ static int handle_channel_write(struct channel * ch, char val) { static int handle_channel_read(struct channel * ch, char * val) { - return -1; + + ushort_t * myval; + + if (ch->latch_state == NOTLATCHED) { + myval = &(ch->counter); + } else { + myval = &(ch->latched_value); + } + + if (ch->read_state == LSB) { + *val = ((char*)myval)[0]; // little endian + ch->read_state = MSB; + } else { + *val = ((char*)myval)[1]; + ch->read_state = LSB; + if (ch->latch_state == LATCHED) { + ch->latch_state = NOTLATCHED; + } + } + + return 0; + } @@ -330,7 +358,10 @@ static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) { switch (cmd.access_mode) { case LATCH_COUNT: - return -1; + if (ch->latch_state == NOTLATCHED) { + ch->latched_value = ch->counter; + ch->latch_state = LATCHED; + } break; case HIBYTE_ONLY: ch->access_state = WAITING_HIBYTE; @@ -500,6 +531,10 @@ static void init_channel(struct channel * ch) { ch->output_pin = 0; ch->gate_input_pin = 0; + ch->latched_value = 0; + ch->latch_state = NOTLATCHED; + ch->read_state = LSB; + return; }