X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2F8254.c;h=69fe0e702bd1343b414c060233abc2e3b04d9a17;hb=fc4b7290edb57a3528a26f95c4478fe07d45a581;hp=fcde0a1f9d921d57fd7da709cb4bb0507bf1a788;hpb=ee05d4a828862fb4e79616585c15be0aee11ea50;p=palacios.git diff --git a/palacios/src/devices/8254.c b/palacios/src/devices/8254.c index fcde0a1..69fe0e7 100644 --- a/palacios/src/devices/8254.c +++ b/palacios/src/devices/8254.c @@ -133,7 +133,7 @@ static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t osc uint_t channel_cycles = 0; uint_t output_changed = 0; - // PrintDebug("8254 PIT (channel %d): %d crystal tics\n", + // PrintDebug(info->vm_info, info, "8254 PIT (channel %d): %d crystal tics\n", // ch - pit->ch0, oscillations); if (ch->run_state == PENDING) { oscillations--; @@ -149,9 +149,9 @@ static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t osc } /* - PrintDebug("8254 PIT: Channel Run State = %d, counter=", ch->run_state); + PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Channel Run State = %d, counter=", ch->run_state); PrintTraceLL(ch->counter); - PrintDebug("\n"); + PrintDebug(VM_NONE, VCORE_NONE, "\n"); */ if (ch->op_mode == SQR_WAVE) { oscillations *= 2; @@ -159,7 +159,7 @@ static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t osc if (ch->counter > oscillations) { ch->counter -= oscillations; - //PrintDebug("8254 PIT: Counter at %u after %u oscillations.\n", + //PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Counter at %u after %u oscillations.\n", // (unsigned int)ch->counter, oscillations); return output_changed; } else { @@ -177,22 +177,23 @@ static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t osc reload_val -= reload_val % 2; } - // TODO: Check this.... - // Is this correct??? if (reload_val == 0) { - reload_val = 1; + // This means the value is being set to 0x10000 + // but due to the tick after the reload, it wraps + // down to 0xffff + reload_val = 0xffff; } channel_cycles += oscillations / reload_val; oscillations = oscillations % reload_val; ch->counter = reload_val - oscillations; - // PrintDebug("8254 PIT: Counter reset to %u.\n", + // PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Counter reset to %u.\n", // (unsigned int)ch->counter); } - //PrintDebug("8254 PIT: Channel %ld (mode = %u) Cycles: %d\n", + //PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Channel %ld (mode = %u) Cycles: %d\n", //(ch - &pit->ch_0), ch->op_mode, channel_cycles); switch (ch->op_mode) { @@ -202,7 +203,7 @@ static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t osc ch->output_pin = 1; output_changed = 1; } else { - // PrintDebug("8254: Output not changed in TERM_CNT mode.\n"); + // PrintDebug(VM_NONE, VCORE_NONE, "8254: Output not changed in TERM_CNT mode.\n"); } } break; @@ -212,7 +213,7 @@ static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t osc ch->output_pin = 1; output_changed = 1; } else { - // PrintDebug("8254: Output not changed in ONE_SHOT mode.\n"); + // PrintDebug(VM_NONE, VCORE_NONE, "8254: Output not changed in ONE_SHOT mode.\n"); } } break; @@ -241,7 +242,7 @@ static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t osc } break; case HW_STROBE: - PrintError("Hardware strobe not implemented\n"); + PrintError(VM_NONE, VCORE_NONE, "Hardware strobe not implemented\n"); return -1; break; default: @@ -262,17 +263,17 @@ static void pit_update_timer(struct guest_info * info, ullong_t cpu_cycles, ullo /* - PrintDebug("updating cpu_cycles="); + PrintDebug(info->vm_info, info, "updating cpu_cycles="); PrintTraceLL(cpu_cycles); - PrintDebug("\n"); + PrintDebug(info->vm_info, info, "\n"); - PrintDebug("pit_counter="); + PrintDebug(info->vm_info, info, "pit_counter="); PrintTraceLL(state->pit_counter); - PrintDebug("\n"); + PrintDebug(info->vm_info, info, "\n"); - PrintDebug("pit_reload="); + PrintDebug(info->vm_info, info, "pit_reload="); PrintTraceLL(state->pit_reload); - PrintDebug("\n"); + PrintDebug(info->vm_info, info, "\n"); */ if (state->pit_counter > cpu_cycles) { @@ -288,12 +289,12 @@ static void pit_update_timer(struct guest_info * info, ullong_t cpu_cycles, ullo if (cpu_cycles > state->pit_reload) { // how many full oscillations - //PrintError("cpu_cycles = %p, reload = %p...\n", + //PrintError(info->vm_info, info, "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) { + if (reload_val == 0) { reload_val = 1; } @@ -301,10 +302,10 @@ static void pit_update_timer(struct guest_info * info, ullong_t cpu_cycles, ullo #ifdef __V3_64BIT__ - cpu_cycles = tmp_cycles % state->pit_reload; - tmp_cycles = tmp_cycles / state->pit_reload; + cpu_cycles = tmp_cycles % reload_val; + tmp_cycles = tmp_cycles / reload_val; #else - cpu_cycles = do_divll(tmp_cycles, state->pit_reload); + cpu_cycles = do_divll(tmp_cycles, reload_val); #endif oscillations += tmp_cycles; @@ -314,11 +315,11 @@ static void pit_update_timer(struct guest_info * info, ullong_t cpu_cycles, ullo state->pit_counter = state->pit_reload - cpu_cycles; if (oscillations) { - // PrintDebug("8254 PIT: Handling %d crystal tics\n", oscillations); + // PrintDebug(info->vm_info, info, "8254 PIT: Handling %d crystal tics\n", oscillations); if (handle_crystal_tics(state, &(state->ch_0), oscillations) == 1) { // raise interrupt - PrintDebug("8254 PIT: Injecting Timer interrupt to guest (run_state = %d)\n", + PrintDebug(info->vm_info, info, "8254 PIT: Injecting Timer interrupt to guest (run_state = %d)\n", state->ch_0.run_state); v3_raise_irq(info->vm_info, 0); } @@ -351,8 +352,8 @@ static int handle_channel_write(struct channel * ch, char val) { ch->access_state = WAITING_LOBYTE; } - PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value); - PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state); + PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: updated channel counter: %d\n", ch->reload_value); + PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Channel Run State=%d\n", ch->run_state); break; } case WAITING_LOBYTE: @@ -365,11 +366,11 @@ static int handle_channel_write(struct channel * ch, char val) { ch->run_state = PENDING; } - PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value); - PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state); + PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: updated channel counter: %d\n", ch->reload_value); + PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Channel Run State=%d\n", ch->run_state); break; default: - PrintError("Invalid Access state\n"); + PrintError(VM_NONE, VCORE_NONE, "Invalid Access state\n"); return -1; } @@ -391,7 +392,7 @@ static int handle_channel_write(struct channel * ch, char val) { ch->output_pin = 1; break; default: - PrintError("Invalid OP_MODE: %d\n", ch->op_mode); + PrintError(VM_NONE, VCORE_NONE, "Invalid OP_MODE: %d\n", ch->op_mode); return -1; break; } @@ -444,7 +445,7 @@ static int handle_speaker_write(uint8_t *speaker, struct channel * ch, char val) static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) { if (cmd.op_mode != ch->op_mode) { - PrintDebug("8254 PIT: Changing channel from op mode %d to op mode %d.\n", + PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Changing channel from op mode %d to op mode %d.\n", ch->op_mode, cmd.op_mode); } @@ -453,7 +454,7 @@ static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) { } if (cmd.access_mode != ch->access_mode) { - PrintDebug("8254 PIT: Changing channel from access mode %d to access mode %d.\n", + PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Changing channel from access mode %d to access mode %d.\n", ch->access_mode, cmd.access_mode); } ch->access_mode = cmd.access_mode; @@ -492,7 +493,7 @@ static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) { ch->output_pin = 1; break; default: - PrintError("Invalid OP_MODE: %d\n", cmd.op_mode); + PrintError(VM_NONE, VCORE_NONE, "Invalid OP_MODE: %d\n", cmd.op_mode); return -1; } @@ -508,39 +509,39 @@ static int pit_read_channel(struct guest_info * core, ushort_t port, void * dst, char * val = (char *)dst; if (length != 1) { - PrintError("8254 PIT: Invalid Read Write length \n"); + PrintError(core->vm_info, core, "8254 PIT: Invalid Read Write length \n"); return -1; } - PrintDebug("8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT); + PrintDebug(core->vm_info, core, "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) { - PrintError("CHANNEL0 read error\n"); + PrintError(core->vm_info, core, "CHANNEL0 read error\n"); return -1; } break; case CHANNEL1_PORT: if (handle_channel_read(&(state->ch_1), val) == -1) { - PrintError("CHANNEL1 read error\n"); + PrintError(core->vm_info, core, "CHANNEL1 read error\n"); return -1; } break; case CHANNEL2_PORT: if (handle_channel_read(&(state->ch_2), val) == -1) { - PrintError("CHANNEL2 read error\n"); + PrintError(core->vm_info, core, "CHANNEL2 read error\n"); return -1; } break; case SPEAKER_PORT: if (handle_speaker_read(&state->speaker, &(state->ch_2), val) == -1) { - PrintError("SPEAKER read error\n"); + PrintError(core->vm_info, core, "SPEAKER read error\n"); return -1; } break; default: - PrintError("8254 PIT: Read from invalid port (%d)\n", port); + PrintError(core->vm_info, core, "8254 PIT: Read from invalid port (%d)\n", port); return -1; } @@ -554,40 +555,40 @@ static int pit_write_channel(struct guest_info * core, ushort_t port, void * src char val = *(char *)src; if (length != 1) { - PrintError("8254 PIT: Invalid Write Length\n"); + PrintError(core->vm_info, core, "8254 PIT: Invalid Write Length\n"); return -1; } - PrintDebug("8254 PIT: Write to PIT Channel %d (%x)\n", port - CHANNEL0_PORT, *(char*)src); + PrintDebug(core->vm_info, core, "8254 PIT: Write to PIT Channel %d (%x)\n", port - CHANNEL0_PORT, *(char*)src); switch (port) { case CHANNEL0_PORT: if (handle_channel_write(&(state->ch_0), val) == -1) { - PrintError("CHANNEL0 write error\n"); + PrintError(core->vm_info, core, "CHANNEL0 write error\n"); return -1; } break; case CHANNEL1_PORT: if (handle_channel_write(&(state->ch_1), val) == -1) { - PrintError("CHANNEL1 write error\n"); + PrintError(core->vm_info, core, "CHANNEL1 write error\n"); return -1; } break; case CHANNEL2_PORT: if (handle_channel_write(&(state->ch_2), val) == -1) { - PrintError("CHANNEL2 write error\n"); + PrintError(core->vm_info, core, "CHANNEL2 write error\n"); return -1; } break; case SPEAKER_PORT: if (handle_speaker_write(&state->speaker, &(state->ch_2), val) == -1) { - PrintError("SPEAKER write error\n"); + PrintError(core->vm_info, core, "SPEAKER write error\n"); return -1; } break; default: - PrintError("8254 PIT: Write to invalid port (%d)\n", port); + PrintError(core->vm_info, core, "8254 PIT: Write to invalid port (%d)\n", port); return -1; } @@ -601,40 +602,35 @@ static int pit_write_command(struct guest_info * core, ushort_t port, void * src struct pit * state = (struct pit *)priv_data; struct pit_cmd_word * cmd = (struct pit_cmd_word *)src; - 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); + PrintDebug(core->vm_info, core, "8254 PIT: Write to PIT Command port\n"); + PrintDebug(core->vm_info, core, "8254 PIT: Writing to channel %d (access_mode = %d, op_mode = %d)\n", cmd->channel, cmd->access_mode, cmd->op_mode); if (length != 1) { - PrintError("8254 PIT: Write of Invalid length to command port\n"); + PrintError(core->vm_info, core, "8254 PIT: Write of Invalid length to command port\n"); return -1; } - if (cmd->op_mode == 0) { - V3_Print("SETTING PIT MODE TO 0!!!!!\n"); - v3_print_guest_state(core); - } - switch (cmd->channel) { case 0: if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) { - PrintError("CHANNEL0 command error\n"); + PrintError(core->vm_info, core, "CHANNEL0 command error\n"); return -1; } break; case 1: if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) { - PrintError("CHANNEL1 command error\n"); + PrintError(core->vm_info, core, "CHANNEL1 command error\n"); return -1; } break; case 2: if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) { - PrintError("CHANNEL2 command error\n"); + PrintError(core->vm_info, core, "CHANNEL2 command error\n"); return -1; } break; case 3: // Read Back command - PrintError("Read back command not implemented\n"); + PrintError(core->vm_info, core, "Read back command not implemented\n"); return -1; break; default: @@ -687,65 +683,129 @@ static int pit_free(void * private_data) { return 0; } -#ifdef V3_CONFIG_KEYED_STREAMS -static int pit_checkpoint(struct vm_device *dev, v3_keyed_stream_t stream) -{ - struct pit *p = (struct pit *) (dev->private_data); +#ifdef V3_CONFIG_CHECKPOINT - v3_keyed_stream_key_t ks; +#include - ks = v3_keyed_stream_open_key(stream,dev->name); +#define KEY_MAX 128 +#define MAKE_KEY(x) snprintf(key,KEY_MAX,"PIT_CH%d_%s",i,x) - if (!ks) { - return -1; - } +static int pit_save(struct v3_chkpt_ctx * ctx, void * private_data) { + struct pit * pit_state = (struct pit *)private_data; + int i; + char key[KEY_MAX]; + + V3_CHKPT_SAVE(ctx, "PIT_COUNTER", pit_state->pit_counter,savefailout); + V3_CHKPT_SAVE(ctx, "PIT_RELOAD", pit_state->pit_reload,savefailout); - STD_SAVE(stream,ks,p->pit_counter); - STD_SAVE(stream,ks,p->pit_reload); - STD_SAVE(stream,ks,p->ch_0); - STD_SAVE(stream,ks,p->ch_1); - STD_SAVE(stream,ks,p->ch_2); - STD_SAVE(stream,ks,p->speaker); + for (i=0;i<3;i++) { + struct channel *c; + uint8_t pins; - v3_keyed_stream_close_key(stream,ks); + if (i==0) { + c=&(pit_state->ch_0); + } else if (i==1) { + c=&(pit_state->ch_1); + } else { + c=&(pit_state->ch_2); + } + + MAKE_KEY("ACCESS_MODE"); + V3_CHKPT_SAVE(ctx, key, c->access_mode, savefailout); + MAKE_KEY("ACCESS_STATE"); + V3_CHKPT_SAVE(ctx, key, c->access_state, savefailout); + MAKE_KEY("RUN_STATE"); + V3_CHKPT_SAVE(ctx, key, c->run_state, savefailout); + MAKE_KEY("OP_MODE"); + V3_CHKPT_SAVE(ctx, key, c->op_mode, savefailout); + MAKE_KEY("COUNTER"); + V3_CHKPT_SAVE(ctx, key, c->counter, savefailout); + MAKE_KEY("RELOAD_VALUE"); + V3_CHKPT_SAVE(ctx, key, c->reload_value, savefailout); + + MAKE_KEY("LATCH_VALUE"); + V3_CHKPT_SAVE(ctx, key, c->latched_value, savefailout); + + MAKE_KEY("LATCH_STATE"); + V3_CHKPT_SAVE(ctx, key, c->latch_state, savefailout); + MAKE_KEY("READ_STATE"); + V3_CHKPT_SAVE(ctx, key, c->read_state, savefailout); + + pins = (c->output_pin) | (c->gate_input_pin << 1); + MAKE_KEY("PINS"); + V3_CHKPT_SAVE(ctx, key, pins, savefailout); + } + + V3_CHKPT_SAVE(ctx, "PIT_SPEAKER", pit_state->speaker,savefailout); return 0; - + savefailout: + PrintError(VM_NONE, VCORE_NONE, "Failed to save pit\n"); + return -1; } -static int pit_restore(struct vm_device *dev, v3_keyed_stream_t stream) -{ - struct pit *p = (struct pit *) (dev->private_data); - - v3_keyed_stream_key_t ks; - - ks = v3_keyed_stream_open_key(stream,dev->name); - - if (!ks) { - return -1; +static int pit_load(struct v3_chkpt_ctx * ctx, void * private_data) { + struct pit * pit_state = (struct pit *)private_data; + int i; + char key[KEY_MAX]; + + V3_CHKPT_LOAD(ctx, "PIT_COUNTER", pit_state->pit_counter,loadfailout); + V3_CHKPT_LOAD(ctx, "PIT_RELOAD", pit_state->pit_reload,loadfailout); + + for (i=0;i<3;i++) { + struct channel *c; + uint8_t pins; + + if (i==0) { + c=&(pit_state->ch_0); + } else if (i==1) { + c=&(pit_state->ch_1); + } else { + c=&(pit_state->ch_2); + } + + MAKE_KEY("ACCESS_MODE"); + V3_CHKPT_LOAD(ctx, key, c->access_mode, loadfailout); + MAKE_KEY("ACCESS_STATE"); + V3_CHKPT_LOAD(ctx, key, c->access_state, loadfailout); + MAKE_KEY("RUN_STATE"); + V3_CHKPT_LOAD(ctx, key, c->run_state, loadfailout); + MAKE_KEY("OP_MODE"); + V3_CHKPT_LOAD(ctx, key, c->op_mode, loadfailout); + MAKE_KEY("COUNTER"); + V3_CHKPT_LOAD(ctx, key, c->counter, loadfailout); + MAKE_KEY("RELOAD_VALUE"); + V3_CHKPT_LOAD(ctx, key, c->reload_value, loadfailout); + + MAKE_KEY("LATCH_VALUE"); + V3_CHKPT_LOAD(ctx, key, c->latched_value, loadfailout); + + MAKE_KEY("LATCH_STATE"); + V3_CHKPT_LOAD(ctx, key, c->latch_state, loadfailout); + MAKE_KEY("READ_STATE"); + V3_CHKPT_LOAD(ctx, key, c->read_state, loadfailout); + + pins = (c->output_pin) | (c->gate_input_pin << 1); + MAKE_KEY("PINS"); + V3_CHKPT_LOAD(ctx, key, pins, loadfailout); } - - STD_LOAD(stream,ks,p->pit_counter); - STD_LOAD(stream,ks,p->pit_reload); - STD_LOAD(stream,ks,p->ch_0); - STD_LOAD(stream,ks,p->ch_1); - STD_LOAD(stream,ks,p->ch_2); - STD_LOAD(stream,ks,p->speaker); - - v3_keyed_stream_close_key(stream,ks); - return 0; + V3_CHKPT_LOAD(ctx, "PIT_SPEAKER", pit_state->speaker,loadfailout); + return 0; + loadfailout: + PrintError(VM_NONE, VCORE_NONE, "Failed to load pit\n"); + return -1; } #endif static struct v3_device_ops dev_ops = { .free = (int (*)(void *))pit_free, -#ifdef V3_CONFIG_KEYED_STREAMS - .checkpoint = pit_checkpoint, - .restore = pit_restore, +#ifdef V3_CONFIG_CHECKPOINT + .save = pit_save, + .load = pit_load, #endif }; @@ -766,14 +826,18 @@ static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { pit_state = (struct pit *)V3_Malloc(sizeof(struct pit)); - V3_ASSERT(pit_state != NULL); + if (!pit_state) { + PrintError(info->vm_info, info, "Cannot allocate in init\n"); + return -1; + } + pit_state->speaker = 0; pit_state->vm = vm; dev = v3_add_device(vm, dev_id, &dev_ops, pit_state); if (dev == NULL) { - PrintError("Could not attach device %s\n", dev_id); + PrintError(info->vm_info, info, "Could not attach device %s\n", dev_id); V3_Free(pit_state); return -1; } @@ -785,15 +849,15 @@ static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { ret |= v3_dev_hook_io(dev, SPEAKER_PORT, &pit_read_channel, &pit_write_channel); if (ret != 0) { - PrintError("8254 PIT: Failed to hook IO ports\n"); + PrintError(info->vm_info, info, "8254 PIT: Failed to hook IO ports\n"); v3_remove_device(dev); return -1; } #ifdef V3_CONFIG_DEBUG_PIT - PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ); + PrintDebug(info->vm_info, info, "8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ); //PrintTrace(reload_val); - PrintDebug("\n"); + PrintDebug(info->vm_info, info, "\n"); #endif @@ -807,7 +871,7 @@ static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { // Get cpu frequency and calculate the global pit oscilattor counter/cycle - do_divll(reload_val, OSC_HZ); + do_divll(reload_val, OSC_HZ); // this is a floor, but will be >=1 for any machine faster than 1.2 MHz pit_state->pit_counter = reload_val; pit_state->pit_reload = reload_val; @@ -817,9 +881,9 @@ static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { init_channel(&(pit_state->ch_2)); #ifdef V3_CONFIG_DEBUG_PIT - PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000); + PrintDebug(info->vm_info, info, "8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000); //PrintTraceLL(pit_state->pit_counter); - PrintDebug("\n"); + PrintDebug(info->vm_info, info, "\n"); #endif return 0;