struct dma_state {
- int tmp;
-
+ int tmp
};
static int dma_init(struct vm_device * dev) {
-
- return 0;
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = dma_init,
- .deinit = NULL,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = dma_init,
+ .deinit = NULL,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_dma() {
- struct dma_state * dma = NULL;
+ struct dma_state * dma = NULL;
- dma = (struct dma_state *)V3_Malloc(sizeof(struct dma_state));
- V3_ASSERT(dma != NULL);
+ dma = (struct dma_state *)V3_Malloc(sizeof(struct dma_state));
+ V3_ASSERT(dma != NULL);
- struct vm_device * dev = v3_create_device("DMA", &dev_ops, dma);
+ struct vm_device * dev = v3_create_device("DMA", &dev_ops, dma);
- return dma;
+ return dma;
}
struct channel {
- channel_access_mode_t access_mode;
- channel_access_state_t access_state;
- channel_run_state_t run_state;
+ channel_access_mode_t access_mode;
+ channel_access_state_t access_state;
+ channel_run_state_t run_state;
- channel_op_mode_t op_mode;
+ channel_op_mode_t op_mode;
- // Time til interrupt trigger
+ // Time til interrupt trigger
- ushort_t counter;
- ushort_t reload_value;
+ ushort_t counter;
+ ushort_t reload_value;
- ushort_t latched_value;
+ ushort_t latched_value;
- enum {NOTLATCHED, LATCHED} latch_state;
+ enum {NOTLATCHED, LATCHED} latch_state;
- enum {LSB, MSB} read_state;
+ enum {LSB, MSB} read_state;
- uint_t output_pin : 1;
- uint_t gate_input_pin : 1;
+ uint_t output_pin : 1;
+ uint_t gate_input_pin : 1;
};
struct pit {
- ullong_t pit_counter;
- ullong_t pit_reload;
+ ullong_t pit_counter;
+ ullong_t pit_reload;
- struct channel ch_0;
- struct channel ch_1;
- struct channel ch_2;
+ struct channel ch_0;
+ struct channel ch_1;
+ struct channel ch_2;
};
struct pit_cmd_word {
- uint_t bcd_mode : 1;
- uint_t op_mode : 3;
- uint_t access_mode : 2;
- uint_t channel : 2;
+ 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
+ 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;
+ 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;
};
*/
// Returns true if the the output signal changed state
static int handle_crystal_tics(struct vm_device * dev, struct channel * ch, uint_t oscillations) {
- uint_t channel_cycles = 0;
- uint_t output_changed = 0;
+ uint_t channel_cycles = 0;
+ uint_t output_changed = 0;
- // PrintDebug("8254 PIT: %d crystal tics\n", oscillations);
- if (ch->run_state == PENDING) {
- oscillations--;
- ch->counter = ch->reload_value;
+ // PrintDebug("8254 PIT: %d crystal tics\n", oscillations);
+ if (ch->run_state == PENDING) {
+ oscillations--;
+ ch->counter = ch->reload_value;
- if (ch->op_mode == SQR_WAVE) {
- ch->counter -= ch->counter % 2;
- }
-
- ch->run_state = RUNNING;
- } else if (ch->run_state != RUNNING) {
- return output_changed;
- }
-
- /*
- PrintDebug("8254 PIT: Channel Run State = %d, counter=", ch->run_state);
- PrintTraceLL(ch->counter);
- PrintDebug("\n");
- */
- if (ch->op_mode == SQR_WAVE) {
- oscillations *= 2;
- }
-
- if (ch->counter > oscillations) {
- ch->counter -= oscillations;
- return output_changed;
- } else {
- ushort_t reload_val = ch->reload_value;
+ if (ch->op_mode == SQR_WAVE) {
+ ch->counter -= ch->counter % 2;
+ }
- // TODO: Check this....
- // Is this correct???
- if (reload_val == 0) {
- reload_val = 1;
+ ch->run_state = RUNNING;
+ } else if (ch->run_state != RUNNING) {
+ return output_changed;
}
- oscillations -= ch->counter;
- ch->counter = 0;
- channel_cycles = 1;
-
+ /*
+ PrintDebug("8254 PIT: Channel Run State = %d, counter=", ch->run_state);
+ PrintTraceLL(ch->counter);
+ PrintDebug("\n");
+ */
if (ch->op_mode == SQR_WAVE) {
- reload_val -= reload_val % 2;
+ oscillations *= 2;
}
- channel_cycles += oscillations / reload_val;
- oscillations = oscillations % reload_val;
+ if (ch->counter > oscillations) {
+ ch->counter -= oscillations;
+ return output_changed;
+ } else {
+ ushort_t reload_val = ch->reload_value;
- ch->counter = reload_val - oscillations;
- }
+ // TODO: Check this....
+ // Is this correct???
+ if (reload_val == 0) {
+ reload_val = 1;
+ }
- // PrintDebug("8254 PIT: Channel Cycles: %d\n", channel_cycles);
-
+ oscillations -= ch->counter;
+ ch->counter = 0;
+ channel_cycles = 1;
+ if (ch->op_mode == SQR_WAVE) {
+ reload_val -= reload_val % 2;
+ }
- switch (ch->op_mode) {
- case IRQ_ON_TERM_CNT:
- if ((channel_cycles > 0) && (ch->output_pin == 0)) {
- ch->output_pin = 1;
- output_changed = 1;
- }
- break;
- case ONE_SHOT:
- if ((channel_cycles > 0) && (ch->output_pin == 0)) {
- ch->output_pin = 1;
- output_changed = 1;
- }
- break;
- case RATE_GEN:
- // See the data sheet: we ignore the output pin cycle...
- if (channel_cycles > 0) {
- output_changed = 1;
+ channel_cycles += oscillations / reload_val;
+ oscillations = oscillations % reload_val;
+
+ ch->counter = reload_val - oscillations;
}
- break;
- case SQR_WAVE:
- ch->output_pin = (ch->output_pin + 1) % 2;
- if (ch->output_pin == 1) {
- output_changed = 1;
+ // PrintDebug("8254 PIT: Channel Cycles: %d\n", channel_cycles);
+
+
+
+ switch (ch->op_mode) {
+ case IRQ_ON_TERM_CNT:
+ if ((channel_cycles > 0) && (ch->output_pin == 0)) {
+ ch->output_pin = 1;
+ output_changed = 1;
+ }
+ break;
+ case ONE_SHOT:
+ if ((channel_cycles > 0) && (ch->output_pin == 0)) {
+ ch->output_pin = 1;
+ output_changed = 1;
+ }
+ break;
+ case RATE_GEN:
+ // See the data sheet: we ignore the output pin cycle...
+ if (channel_cycles > 0) {
+ output_changed = 1;
+ }
+ break;
+ case SQR_WAVE:
+ ch->output_pin = (ch->output_pin + 1) % 2;
+
+ if (ch->output_pin == 1) {
+ output_changed = 1;
+ }
+
+ break;
+ case SW_STROBE:
+ return -1;
+ break;
+ case HW_STROBE:
+ return -1;
+ break;
+ default:
+ break;
}
- break;
- case SW_STROBE:
- return -1;
- break;
- case HW_STROBE:
- return -1;
- break;
- default:
- break;
- }
-
- return output_changed;
+ return output_changed;
}
static void pit_update_time(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;
- ullong_t tmp_cycles;
- uint_t oscillations = 0;
+ struct vm_device * dev = (struct vm_device *)private_data;
+ struct pit * state = (struct pit *)dev->private_data;
+ // ullong_t tmp_ctr = state->pit_counter;
+ ullong_t tmp_cycles;
+ uint_t oscillations = 0;
- /*
- PrintDebug("updating cpu_cycles=");
- PrintTraceLL(cpu_cycles);
- PrintDebug("\n");
+ /*
+ PrintDebug("updating cpu_cycles=");
+ PrintTraceLL(cpu_cycles);
+ PrintDebug("\n");
- PrintDebug("pit_counter=");
- PrintTraceLL(state->pit_counter);
- PrintDebug("\n");
+ PrintDebug("pit_counter=");
+ PrintTraceLL(state->pit_counter);
+ PrintDebug("\n");
- PrintDebug("pit_reload=");
- PrintTraceLL(state->pit_reload);
- PrintDebug("\n");
- */
-
- if (state->pit_counter > cpu_cycles) {
- // 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;
- oscillations = 1;
+ PrintDebug("pit_reload=");
+ PrintTraceLL(state->pit_reload);
+ PrintDebug("\n");
+ */
+
+ if (state->pit_counter > cpu_cycles) {
+ // 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;
+ oscillations = 1;
- if (cpu_cycles > state->pit_reload) {
- // how many full oscillations
+ 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);
+ //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;
- }
+ // How do we check for a one shot....
+ if (state->pit_reload == 0) {
+ reload_val = 1;
+ }
- tmp_cycles = cpu_cycles;
+ tmp_cycles = cpu_cycles;
#ifdef __V3_64BIT__
- cpu_cycles = tmp_cycles % state->pit_reload;
- tmp_cycles = tmp_cycles / state->pit_reload;
+ cpu_cycles = tmp_cycles % state->pit_reload;
+ tmp_cycles = tmp_cycles / state->pit_reload;
#else
- cpu_cycles = do_divll(tmp_cycles, state->pit_reload);
+ cpu_cycles = do_divll(tmp_cycles, state->pit_reload);
#endif
- oscillations += tmp_cycles;
- }
+ oscillations += tmp_cycles;
+ }
- // update counter with remainder (mod reload)
- state->pit_counter = state->pit_reload - cpu_cycles;
+ // update counter with remainder (mod reload)
+ state->pit_counter = state->pit_reload - cpu_cycles;
- //PrintDebug("8254 PIT: Handling %d crystal tics\n", oscillations);
- if (handle_crystal_tics(dev, &(state->ch_0), oscillations) == 1) {
- // raise interrupt
- PrintDebug("8254 PIT: Injecting Timer interrupt to guest\n");
- v3_raise_irq(dev->vm, 0);
- }
+ //PrintDebug("8254 PIT: Handling %d crystal tics\n", oscillations);
+ if (handle_crystal_tics(dev, &(state->ch_0), oscillations) == 1) {
+ // raise interrupt
+ PrintDebug("8254 PIT: Injecting Timer interrupt to guest\n");
+ v3_raise_irq(dev->vm, 0);
+ }
- //handle_crystal_tics(dev, &(state->ch_1), oscillations);
- //handle_crystal_tics(dev, &(state->ch_2), oscillations);
- }
+ //handle_crystal_tics(dev, &(state->ch_1), oscillations);
+ //handle_crystal_tics(dev, &(state->ch_2), oscillations);
+ }
- return;
+ return;
}
static int handle_channel_write(struct channel * ch, char val) {
switch (ch->access_state) {
- case WAITING_HIBYTE:
- {
- ushort_t tmp_val = ((ushort_t)val) << 8;
- ch->reload_value &= 0x00ff;
- ch->reload_value |= tmp_val;
+ case WAITING_HIBYTE:
+ {
+ ushort_t tmp_val = ((ushort_t)val) << 8;
+ ch->reload_value &= 0x00ff;
+ ch->reload_value |= tmp_val;
- if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)){
- ch->run_state = PENDING;
- }
+ if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)){
+ ch->run_state = PENDING;
+ }
- if (ch->access_mode == LOBYTE_HIBYTE) {
- 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);
- break;
- }
- case WAITING_LOBYTE:
- ch->reload_value &= 0xff00;
- ch->reload_value |= val;
+ if (ch->access_mode == LOBYTE_HIBYTE) {
+ 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);
+ break;
+ }
+ case WAITING_LOBYTE:
+ ch->reload_value &= 0xff00;
+ ch->reload_value |= val;
- if (ch->access_mode == LOBYTE_HIBYTE) {
- ch->access_state = WAITING_HIBYTE;
- } else if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)) {
- ch->run_state = PENDING;
- }
+ if (ch->access_mode == LOBYTE_HIBYTE) {
+ ch->access_state = WAITING_HIBYTE;
+ } else if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)) {
+ 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);
- break;
- default:
- return -1;
+ PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);
+ PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
+ break;
+ default:
+ return -1;
}
switch (ch->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;
- case SQR_WAVE:
- ch->output_pin = 1;
- break;
- default:
- return -1;
- break;
+ 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;
+ case SQR_WAVE:
+ ch->output_pin = 1;
+ break;
+ default:
+ return -1;
+ break;
}
- return 0;
+ return 0;
}
static int handle_channel_read(struct channel * ch, char * val) {
- ushort_t * myval;
+ ushort_t * myval;
- if (ch->latch_state == NOTLATCHED) {
- myval = &(ch->counter);
- } else {
- myval = &(ch->latched_value);
- }
+ 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;
+ 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;
+ return 0;
}
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;
-
-
+ ch->op_mode = cmd.op_mode;
+ ch->access_mode = cmd.access_mode;
+
+
+
+
+ switch (cmd.access_mode) {
+ case LATCH_COUNT:
+ if (ch->latch_state == NOTLATCHED) {
+ ch->latched_value = ch->counter;
+ ch->latch_state = LATCHED;
+ }
+ break;
+ case HIBYTE_ONLY:
+ ch->access_state = WAITING_HIBYTE;
+ break;
+ case LOBYTE_ONLY:
+ case LOBYTE_HIBYTE:
+ ch->access_state = WAITING_LOBYTE;
+ break;
+ }
- switch (cmd.access_mode) {
- case LATCH_COUNT:
- if (ch->latch_state == NOTLATCHED) {
- ch->latched_value = ch->counter;
- ch->latch_state = LATCHED;
+ 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;
+ case SQR_WAVE:
+ ch->output_pin = 1;
+ break;
+ default:
+ 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;
- case SQR_WAVE:
- ch->output_pin = 1;
- break;
- default:
- return -1;
- }
-
- return 0;
+
+ 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) {
- PrintError("8254 PIT: Invalid Read Write length \n");
- return -1;
- }
+ struct pit * state = (struct pit *)dev->private_data;
+ char * val = (char *)dst;
- 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;
+ if (length != 1) {
+ PrintError("8254 PIT: Invalid Read Write length \n");
+ return -1;
}
- break;
- case CHANNEL2_PORT:
- if (handle_channel_read(&(state->ch_2), val) == -1) {
- 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:
+ PrintError("8254 PIT: Read from invalid port (%d)\n", port);
+ return -1;
}
- break;
- default:
- PrintError("8254 PIT: Read from invalid port (%d)\n", port);
- return -1;
- }
- return length;
+ 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) {
- PrintError("8254 PIT: Invalid Write Length\n");
- return -1;
- }
-
- PrintDebug("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) {
- return -1;
- }
- break;
- case CHANNEL1_PORT:
- if (handle_channel_write(&(state->ch_1), val) == -1) {
- return -1;
+ struct pit * state = (struct pit *)dev->private_data;
+ char val = *(char *)src;
+
+ if (length != 1) {
+ PrintError("8254 PIT: Invalid Write Length\n");
+ return -1;
}
- break;
- case CHANNEL2_PORT:
- if (handle_channel_write(&(state->ch_2), val) == -1) {
- return -1;
+
+ PrintDebug("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) {
+ 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:
+ PrintError("8254 PIT: Write to invalid port (%d)\n", port);
+ return -1;
}
- break;
- default:
- PrintError("8254 PIT: Write to invalid port (%d)\n", port);
- return -1;
- }
- return length;
+ 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_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);
- if (length != 1) {
- PrintError("8254 PIT: Write of Invalid length to command port\n");
- return -1;
- }
-
- switch (cmd->channel) {
- case 0:
- 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;
+ struct pit * state = (struct pit *)dev->private_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);
+ if (length != 1) {
+ PrintError("8254 PIT: Write of Invalid length to command port\n");
+ return -1;
}
- break;
- case 2:
- if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) {
- return -1;
+
+ switch (cmd->channel) {
+ case 0:
+ 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;
}
- break;
- case 3:
- // Read Back command
- return -1;
- break;
- default:
- break;
- }
- return length;
+ return length;
}
static struct vm_timer_ops timer_ops = {
- .update_time = pit_update_time,
+ .update_time = pit_update_time,
};
static void init_channel(struct channel * ch) {
- ch->run_state = NOT_RUNNING;
- ch->access_state = NOT_WAITING;
- ch->access_mode = 0;
- ch->op_mode = 0;
+ ch->run_state = NOT_RUNNING;
+ ch->access_state = NOT_WAITING;
+ ch->access_mode = 0;
+ ch->op_mode = 0;
- ch->counter = 0;
- ch->reload_value = 0;
- ch->output_pin = 0;
- ch->gate_input_pin = 0;
+ ch->counter = 0;
+ ch->reload_value = 0;
+ ch->output_pin = 0;
+ ch->gate_input_pin = 0;
- ch->latched_value = 0;
- ch->latch_state = NOTLATCHED;
- ch->read_state = LSB;
+ ch->latched_value = 0;
+ ch->latch_state = NOTLATCHED;
+ ch->read_state = LSB;
- return;
+ return;
}
static int pit_init(struct vm_device * dev) {
- struct pit * state = (struct pit *)dev->private_data;
- uint_t cpu_khz = V3_CPU_KHZ();
- ullong_t reload_val = (ullong_t)cpu_khz * 1000;
+ struct pit * state = (struct pit *)dev->private_data;
+ uint_t cpu_khz = V3_CPU_KHZ();
+ ullong_t reload_val = (ullong_t)cpu_khz * 1000;
- 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);
+ 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");
+ PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
+ PrintTraceLL(reload_val);
+ PrintDebug("\n");
#endif
- v3_add_timer(dev->vm, &timer_ops, dev);
+ v3_add_timer(dev->vm, &timer_ops, dev);
- // Get cpu frequency and calculate the global pit oscilattor counter/cycle
+ // Get cpu frequency and calculate the global pit oscilattor counter/cycle
- do_divll(reload_val, OSC_HZ);
- state->pit_counter = reload_val;
- state->pit_reload = reload_val;
+ do_divll(reload_val, OSC_HZ);
+ state->pit_counter = reload_val;
+ state->pit_reload = reload_val;
- init_channel(&(state->ch_0));
- init_channel(&(state->ch_1));
- init_channel(&(state->ch_2));
+ init_channel(&(state->ch_0));
+ 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");
+ PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
+ PrintTraceLL(state->pit_counter);
+ PrintDebug("\n");
#endif
- return 0;
+ return 0;
}
static int pit_deinit(struct vm_device * dev) {
- return 0;
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = pit_init,
- .deinit = pit_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = pit_init,
+ .deinit = pit_deinit,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
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 pit * pit_state = NULL;
+ pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
+ V3_ASSERT(pit_state != NULL);
- struct vm_device * dev = v3_create_device("PIT", &dev_ops, pit_state);
+ struct vm_device * dev = v3_create_device("PIT", &dev_ops, pit_state);
- return dev;
+ return dev;
}
struct icw1 {
- uint_t ic4 : 1; // ICW4 has to be read
- uint_t sngl : 1; // single (only one PIC)
- uint_t adi : 1; // call address interval
- uint_t ltim : 1; // level interrupt mode
- uint_t one : 1;
- uint_t rsvd : 3;
+ uint_t ic4 : 1; // ICW4 has to be read
+ uint_t sngl : 1; // single (only one PIC)
+ uint_t adi : 1; // call address interval
+ uint_t ltim : 1; // level interrupt mode
+ uint_t one : 1;
+ uint_t rsvd : 3;
};
struct icw2 {
- uint_t rsvd : 3;
- uint_t vector : 5;
+ uint_t rsvd : 3;
+ uint_t vector : 5;
};
// Each bit that is set indicates that the IR input has a slave
struct icw3_master {
- uint_t S0 : 1;
- uint_t S1 : 1;
- uint_t S2 : 1;
- uint_t S3 : 1;
- uint_t S4 : 1;
- uint_t S5 : 1;
- uint_t S6 : 1;
- uint_t S7 : 1;
+ uint_t S0 : 1;
+ uint_t S1 : 1;
+ uint_t S2 : 1;
+ uint_t S3 : 1;
+ uint_t S4 : 1;
+ uint_t S5 : 1;
+ uint_t S6 : 1;
+ uint_t S7 : 1;
};
// The ID is the Slave device ID
struct icw3_slave {
- uint_t id : 3;
- uint_t zeroes : 5;
+ uint_t id : 3;
+ uint_t zeroes : 5;
};
struct icw4 {
- uint_t uPM : 1; // 1=x86
- uint_t AEOI : 1; // Automatic End of Interrupt
- uint_t M_S : 1; // only if buffered 1=master,0=slave
- uint_t BUF : 1; // buffered mode
- uint_t SFNM : 1; // special fully nexted mode
- uint_t zeroes : 3;
+ uint_t uPM : 1; // 1=x86
+ uint_t AEOI : 1; // Automatic End of Interrupt
+ uint_t M_S : 1; // only if buffered 1=master,0=slave
+ uint_t BUF : 1; // buffered mode
+ uint_t SFNM : 1; // special fully nexted mode
+ uint_t zeroes : 3;
};
struct ocw1 {
- uint_t m0 : 1;
- uint_t m1 : 1;
- uint_t m2 : 1;
- uint_t m3 : 1;
- uint_t m4 : 1;
- uint_t m5 : 1;
- uint_t m6 : 1;
- uint_t m7 : 1;
+ uint_t m0 : 1;
+ uint_t m1 : 1;
+ uint_t m2 : 1;
+ uint_t m3 : 1;
+ uint_t m4 : 1;
+ uint_t m5 : 1;
+ uint_t m6 : 1;
+ uint_t m7 : 1;
};
struct ocw2 {
- uint_t level : 3;
- uint_t cw_code : 2; // should be 00
- uint_t EOI : 1;
- uint_t SL : 1;
- uint_t R : 1;
+ uint_t level : 3;
+ uint_t cw_code : 2; // should be 00
+ uint_t EOI : 1;
+ uint_t SL : 1;
+ uint_t R : 1;
};
struct ocw3 {
- uint_t RIS : 1;
- uint_t RR : 1;
- uint_t P : 1;
- uint_t cw_code : 2; // should be 01
- uint_t smm : 1;
- uint_t esmm : 1;
- uint_t zero2 : 1;
+ uint_t RIS : 1;
+ uint_t RR : 1;
+ uint_t P : 1;
+ uint_t cw_code : 2; // should be 01
+ uint_t smm : 1;
+ uint_t esmm : 1;
+ uint_t zero2 : 1;
};
struct pic_internal {
- uchar_t master_irr;
- uchar_t slave_irr;
+ uchar_t master_irr;
+ uchar_t slave_irr;
- uchar_t master_isr;
- uchar_t slave_isr;
+ uchar_t master_isr;
+ uchar_t slave_isr;
- uchar_t master_icw1;
- uchar_t master_icw2;
- uchar_t master_icw3;
- uchar_t master_icw4;
+ uchar_t master_icw1;
+ uchar_t master_icw2;
+ uchar_t master_icw3;
+ uchar_t master_icw4;
- uchar_t slave_icw1;
- uchar_t slave_icw2;
- uchar_t slave_icw3;
- uchar_t slave_icw4;
+ uchar_t slave_icw1;
+ uchar_t slave_icw2;
+ uchar_t slave_icw3;
+ uchar_t slave_icw4;
- uchar_t master_imr;
- uchar_t slave_imr;
- uchar_t master_ocw2;
- uchar_t master_ocw3;
- uchar_t slave_ocw2;
- uchar_t slave_ocw3;
+ uchar_t master_imr;
+ uchar_t slave_imr;
+ uchar_t master_ocw2;
+ uchar_t master_ocw3;
+ uchar_t slave_ocw2;
+ uchar_t slave_ocw3;
- pic_state_t master_state;
- pic_state_t slave_state;
+ pic_state_t master_state;
+ pic_state_t slave_state;
};
static void DumpPICState(struct pic_internal *p)
{
- PrintDebug("8259 PIC: master_state=0x%x\n",p->master_state);
- PrintDebug("8259 PIC: master_irr=0x%x\n",p->master_irr);
- PrintDebug("8259 PIC: master_isr=0x%x\n",p->master_isr);
- PrintDebug("8259 PIC: master_imr=0x%x\n",p->master_imr);
+ PrintDebug("8259 PIC: master_state=0x%x\n",p->master_state);
+ PrintDebug("8259 PIC: master_irr=0x%x\n",p->master_irr);
+ PrintDebug("8259 PIC: master_isr=0x%x\n",p->master_isr);
+ PrintDebug("8259 PIC: master_imr=0x%x\n",p->master_imr);
- PrintDebug("8259 PIC: master_ocw2=0x%x\n",p->master_ocw2);
- PrintDebug("8259 PIC: master_ocw3=0x%x\n",p->master_ocw3);
+ PrintDebug("8259 PIC: master_ocw2=0x%x\n",p->master_ocw2);
+ PrintDebug("8259 PIC: master_ocw3=0x%x\n",p->master_ocw3);
- PrintDebug("8259 PIC: master_icw1=0x%x\n",p->master_icw1);
- PrintDebug("8259 PIC: master_icw2=0x%x\n",p->master_icw2);
- PrintDebug("8259 PIC: master_icw3=0x%x\n",p->master_icw3);
- PrintDebug("8259 PIC: master_icw4=0x%x\n",p->master_icw4);
+ PrintDebug("8259 PIC: master_icw1=0x%x\n",p->master_icw1);
+ PrintDebug("8259 PIC: master_icw2=0x%x\n",p->master_icw2);
+ PrintDebug("8259 PIC: master_icw3=0x%x\n",p->master_icw3);
+ PrintDebug("8259 PIC: master_icw4=0x%x\n",p->master_icw4);
- PrintDebug("8259 PIC: slave_state=0x%x\n",p->slave_state);
- PrintDebug("8259 PIC: slave_irr=0x%x\n",p->slave_irr);
- PrintDebug("8259 PIC: slave_isr=0x%x\n",p->slave_isr);
- PrintDebug("8259 PIC: slave_imr=0x%x\n",p->slave_imr);
+ PrintDebug("8259 PIC: slave_state=0x%x\n",p->slave_state);
+ PrintDebug("8259 PIC: slave_irr=0x%x\n",p->slave_irr);
+ PrintDebug("8259 PIC: slave_isr=0x%x\n",p->slave_isr);
+ PrintDebug("8259 PIC: slave_imr=0x%x\n",p->slave_imr);
- PrintDebug("8259 PIC: slave_ocw2=0x%x\n",p->slave_ocw2);
- PrintDebug("8259 PIC: slave_ocw3=0x%x\n",p->slave_ocw3);
+ PrintDebug("8259 PIC: slave_ocw2=0x%x\n",p->slave_ocw2);
+ PrintDebug("8259 PIC: slave_ocw3=0x%x\n",p->slave_ocw3);
- PrintDebug("8259 PIC: slave_icw1=0x%x\n",p->slave_icw1);
- PrintDebug("8259 PIC: slave_icw2=0x%x\n",p->slave_icw2);
- PrintDebug("8259 PIC: slave_icw3=0x%x\n",p->slave_icw3);
- PrintDebug("8259 PIC: slave_icw4=0x%x\n",p->slave_icw4);
+ PrintDebug("8259 PIC: slave_icw1=0x%x\n",p->slave_icw1);
+ PrintDebug("8259 PIC: slave_icw2=0x%x\n",p->slave_icw2);
+ PrintDebug("8259 PIC: slave_icw3=0x%x\n",p->slave_icw3);
+ PrintDebug("8259 PIC: slave_icw4=0x%x\n",p->slave_icw4);
}
static int pic_raise_intr(void * private_data, int irq) {
- struct pic_internal * state = (struct pic_internal*)private_data;
+ struct pic_internal * state = (struct pic_internal*)private_data;
- if (irq == 2) {
- irq = 9;
- state->master_irr |= 0x04; // PAD
- }
+ if (irq == 2) {
+ irq = 9;
+ state->master_irr |= 0x04; // PAD
+ }
- PrintDebug("8259 PIC: Raising irq %d in the PIC\n", irq);
+ PrintDebug("8259 PIC: Raising irq %d in the PIC\n", irq);
- if (irq <= 7) {
- state->master_irr |= 0x01 << irq;
- } else if ((irq > 7) && (irq < 16)) {
- state->slave_irr |= 0x01 << (irq - 8); // PAD if -7 then irq 15=no irq
- } else {
- PrintError("8259 PIC: Invalid IRQ raised (%d)\n", irq);
- return -1;
- }
+ if (irq <= 7) {
+ state->master_irr |= 0x01 << irq;
+ } else if ((irq > 7) && (irq < 16)) {
+ state->slave_irr |= 0x01 << (irq - 8); // PAD if -7 then irq 15=no irq
+ } else {
+ PrintError("8259 PIC: Invalid IRQ raised (%d)\n", irq);
+ return -1;
+ }
- return 0;
+ return 0;
}
static int pic_lower_intr(void *private_data, int irq) {
- struct pic_internal *state = (struct pic_internal*)private_data;
+ struct pic_internal *state = (struct pic_internal*)private_data;
- PrintDebug("[pic_lower_intr] IRQ line %d now low\n", irq);
- if (irq <= 7) {
+ PrintDebug("[pic_lower_intr] IRQ line %d now low\n", irq);
+ if (irq <= 7) {
- state->master_irr &= ~(1 << irq);
- if ((state->master_irr & ~(state->master_imr)) == 0) {
- PrintDebug("\t\tFIXME: Master maybe should do sth\n");
- }
- } else if ((irq > 7) && (irq < 16)) {
+ state->master_irr &= ~(1 << irq);
+ if ((state->master_irr & ~(state->master_imr)) == 0) {
+ PrintDebug("\t\tFIXME: Master maybe should do sth\n");
+ }
+ } else if ((irq > 7) && (irq < 16)) {
- state->slave_irr &= ~(1 << (irq - 8));
- if ((state->slave_irr & (~(state->slave_imr))) == 0) {
- PrintDebug("\t\tFIXME: Slave maybe should do sth\n");
+ state->slave_irr &= ~(1 << (irq - 8));
+ if ((state->slave_irr & (~(state->slave_imr))) == 0) {
+ PrintDebug("\t\tFIXME: Slave maybe should do sth\n");
+ }
}
- }
- return 0;
+ return 0;
}
static int pic_intr_pending(void * private_data) {
- struct pic_internal * state = (struct pic_internal*)private_data;
+ struct pic_internal * state = (struct pic_internal*)private_data;
- if ((state->master_irr & ~(state->master_imr)) ||
- (state->slave_irr & ~(state->slave_imr))) {
- return 1;
- }
+ if ((state->master_irr & ~(state->master_imr)) ||
+ (state->slave_irr & ~(state->slave_imr))) {
+ return 1;
+ }
- return 0;
+ return 0;
}
static int pic_get_intr_number(void * private_data) {
- struct pic_internal * state = (struct pic_internal *)private_data;
- int i = 0;
- int irq = -1;
-
- PrintDebug("8259 PIC: getnum: master_irr: 0x%x master_imr: 0x%x\n", state->master_irr, state->master_imr);
- PrintDebug("8259 PIC: getnum: slave_irr: 0x%x slave_imr: 0x%x\n", state->slave_irr, state->slave_imr);
-
- for (i = 0; i < 16; i++) {
- if (i <= 7) {
- if (((state->master_irr & ~(state->master_imr)) >> i) == 0x01) {
- //state->master_isr |= (0x1 << i);
- // reset the irr
- //state->master_irr &= ~(0x1 << i);
- PrintDebug("8259 PIC: IRQ: %d, master_icw2: %x\n", i, state->master_icw2);
- irq= i + state->master_icw2;
- break;
- }
- } else {
- if (((state->slave_irr & ~(state->slave_imr)) >> (i - 8)) == 0x01) {
- //state->slave_isr |= (0x1 << (i - 8));
- //state->slave_irr &= ~(0x1 << (i - 8));
- PrintDebug("8259 PIC: IRQ: %d, slave_icw2: %x\n", i, state->slave_icw2);
- irq= (i - 8) + state->slave_icw2;
- break;
- }
+ struct pic_internal * state = (struct pic_internal *)private_data;
+ int i = 0;
+ int irq = -1;
+
+ PrintDebug("8259 PIC: getnum: master_irr: 0x%x master_imr: 0x%x\n", state->master_irr, state->master_imr);
+ PrintDebug("8259 PIC: getnum: slave_irr: 0x%x slave_imr: 0x%x\n", state->slave_irr, state->slave_imr);
+
+ for (i = 0; i < 16; i++) {
+ if (i <= 7) {
+ if (((state->master_irr & ~(state->master_imr)) >> i) == 0x01) {
+ //state->master_isr |= (0x1 << i);
+ // reset the irr
+ //state->master_irr &= ~(0x1 << i);
+ PrintDebug("8259 PIC: IRQ: %d, master_icw2: %x\n", i, state->master_icw2);
+ irq= i + state->master_icw2;
+ break;
+ }
+ } else {
+ if (((state->slave_irr & ~(state->slave_imr)) >> (i - 8)) == 0x01) {
+ //state->slave_isr |= (0x1 << (i - 8));
+ //state->slave_irr &= ~(0x1 << (i - 8));
+ PrintDebug("8259 PIC: IRQ: %d, slave_icw2: %x\n", i, state->slave_icw2);
+ irq= (i - 8) + state->slave_icw2;
+ break;
+ }
+ }
}
- }
- if ((i == 15) || (i == 6)) {
- DumpPICState(state);
- }
+ if ((i == 15) || (i == 6)) {
+ DumpPICState(state);
+ }
- if (i == 16) {
- return -1;
- } else {
- return irq;
- }
+ if (i == 16) {
+ return -1;
+ } else {
+ return irq;
+ }
}
/* The IRQ number is the number returned by pic_get_intr_number(), not the pin number */
static int pic_begin_irq(void * private_data, int irq) {
- struct pic_internal * state = (struct pic_internal*)private_data;
-
- if ((irq >= state->master_icw2) && (irq <= state->master_icw2 + 7)) {
- irq &= 0x7;
- } else if ((irq >= state->slave_icw2) && (irq <= state->slave_icw2 + 7)) {
- irq &= 0x7;
- irq += 8;
- } else {
- // PrintError("8259 PIC: Could not find IRQ (0x%x) to Begin\n",irq);
- return -1;
- }
+ struct pic_internal * state = (struct pic_internal*)private_data;
- if (irq <= 7) {
- if (((state->master_irr & ~(state->master_imr)) >> irq) == 0x01) {
- state->master_isr |= (0x1 << irq);
- state->master_irr &= ~(0x1 << irq);
+ if ((irq >= state->master_icw2) && (irq <= state->master_icw2 + 7)) {
+ irq &= 0x7;
+ } else if ((irq >= state->slave_icw2) && (irq <= state->slave_icw2 + 7)) {
+ irq &= 0x7;
+ irq += 8;
+ } else {
+ // PrintError("8259 PIC: Could not find IRQ (0x%x) to Begin\n",irq);
+ return -1;
}
- } else {
- state->slave_isr |= (0x1 << (irq - 8));
- state->slave_irr &= ~(0x1 << (irq - 8));
- }
- return 0;
+ if (irq <= 7) {
+ if (((state->master_irr & ~(state->master_imr)) >> irq) == 0x01) {
+ state->master_isr |= (0x1 << irq);
+ state->master_irr &= ~(0x1 << irq);
+ }
+ } else {
+ state->slave_isr |= (0x1 << (irq - 8));
+ state->slave_irr &= ~(0x1 << (irq - 8));
+ }
+
+ return 0;
}
/*
-static int pic_end_irq(void * private_data, int irq) {
+ static int pic_end_irq(void * private_data, int irq) {
return 0;
-}
+ }
*/
static struct intr_ctrl_ops intr_ops = {
- .intr_pending = pic_intr_pending,
- .get_intr_number = pic_get_intr_number,
- .raise_intr = pic_raise_intr,
- .begin_irq = pic_begin_irq,
- .lower_intr = pic_lower_intr,
+ .intr_pending = pic_intr_pending,
+ .get_intr_number = pic_get_intr_number,
+ .raise_intr = pic_raise_intr,
+ .begin_irq = pic_begin_irq,
+ .lower_intr = pic_lower_intr,
};
static int read_master_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct pic_internal * state = (struct pic_internal*)dev->private_data;
+ struct pic_internal * state = (struct pic_internal*)dev->private_data;
- if (length != 1) {
- PrintError("8259 PIC: Invalid Read length (rd_Master1)\n");
- return -1;
- }
+ if (length != 1) {
+ PrintError("8259 PIC: Invalid Read length (rd_Master1)\n");
+ return -1;
+ }
- if ((state->master_ocw3 & 0x03) == 0x02) {
- *(uchar_t *)dst = state->master_irr;
- } else if ((state->master_ocw3 & 0x03) == 0x03) {
- *(uchar_t *)dst = state->master_isr;
- } else {
- *(uchar_t *)dst = 0;
- }
+ if ((state->master_ocw3 & 0x03) == 0x02) {
+ *(uchar_t *)dst = state->master_irr;
+ } else if ((state->master_ocw3 & 0x03) == 0x03) {
+ *(uchar_t *)dst = state->master_isr;
+ } else {
+ *(uchar_t *)dst = 0;
+ }
- return 1;
+ return 1;
}
static int read_master_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct pic_internal * state = (struct pic_internal*)dev->private_data;
+ struct pic_internal * state = (struct pic_internal*)dev->private_data;
- if (length != 1) {
- PrintError("8259 PIC: Invalid Read length (rd_Master2)\n");
- return -1;
- }
+ if (length != 1) {
+ PrintError("8259 PIC: Invalid Read length (rd_Master2)\n");
+ return -1;
+ }
- *(uchar_t *)dst = state->master_imr;
+ *(uchar_t *)dst = state->master_imr;
- return 1;
+ return 1;
}
static int read_slave_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct pic_internal * state = (struct pic_internal*)dev->private_data;
+ struct pic_internal * state = (struct pic_internal*)dev->private_data;
- if (length != 1) {
- PrintError("8259 PIC: Invalid Read length (rd_Slave1)\n");
- return -1;
- }
+ if (length != 1) {
+ PrintError("8259 PIC: Invalid Read length (rd_Slave1)\n");
+ return -1;
+ }
- if ((state->slave_ocw3 & 0x03) == 0x02) {
- *(uchar_t*)dst = state->slave_irr;
- } else if ((state->slave_ocw3 & 0x03) == 0x03) {
- *(uchar_t *)dst = state->slave_isr;
- } else {
- *(uchar_t *)dst = 0;
- }
+ if ((state->slave_ocw3 & 0x03) == 0x02) {
+ *(uchar_t*)dst = state->slave_irr;
+ } else if ((state->slave_ocw3 & 0x03) == 0x03) {
+ *(uchar_t *)dst = state->slave_isr;
+ } else {
+ *(uchar_t *)dst = 0;
+ }
- return 1;
+ return 1;
}
static int read_slave_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct pic_internal * state = (struct pic_internal*)dev->private_data;
+ struct pic_internal * state = (struct pic_internal*)dev->private_data;
- if (length != 1) {
- PrintError("8259 PIC: Invalid Read length (rd_Slave2)\n");
- return -1;
- }
+ if (length != 1) {
+ PrintError("8259 PIC: Invalid Read length (rd_Slave2)\n");
+ return -1;
+ }
- *(uchar_t *)dst = state->slave_imr;
+ *(uchar_t *)dst = state->slave_imr;
- return 1;
+ return 1;
}
static int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct pic_internal * state = (struct pic_internal*)dev->private_data;
- uchar_t cw = *(uchar_t *)src;
+ struct pic_internal * state = (struct pic_internal*)dev->private_data;
+ uchar_t cw = *(uchar_t *)src;
- PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
+ PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
- if (length != 1) {
- PrintError("8259 PIC: Invalid Write length (wr_Master1)\n");
- return -1;
- }
+ if (length != 1) {
+ PrintError("8259 PIC: Invalid Write length (wr_Master1)\n");
+ return -1;
+ }
- if (IS_ICW1(cw)) {
+ if (IS_ICW1(cw)) {
- PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Master1)\n", cw);
+ PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Master1)\n", cw);
- state->master_icw1 = cw;
- state->master_state = ICW2;
+ state->master_icw1 = cw;
+ state->master_state = ICW2;
- } else if (state->master_state == READY) {
- if (IS_OCW2(cw)) {
- // handle the EOI here
- struct ocw2 * cw2 = (struct ocw2*)&cw;
+ } else if (state->master_state == READY) {
+ if (IS_OCW2(cw)) {
+ // handle the EOI here
+ struct ocw2 * cw2 = (struct ocw2*)&cw;
- PrintDebug("8259 PIC: Handling OCW2 = %x (wr_Master1)\n", cw);
+ PrintDebug("8259 PIC: Handling OCW2 = %x (wr_Master1)\n", cw);
- if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
- // specific EOI;
- state->master_isr &= ~(0x01 << cw2->level);
- } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
- int i;
- // Non-specific EOI
- PrintDebug("8259 PIC: Pre ISR = %x (wr_Master1)\n", state->master_isr);
- for (i = 0; i < 8; i++) {
- if (state->master_isr & (0x01 << i)) {
- state->master_isr &= ~(0x01 << i);
- break;
- }
- }
- PrintDebug("8259 PIC: Post ISR = %x (wr_Master1)\n", state->master_isr);
- } else {
- PrintError("8259 PIC: Command not handled, or in error (wr_Master1)\n");
- return -1;
- }
-
- state->master_ocw2 = cw;
- } else if (IS_OCW3(cw)) {
- PrintDebug("8259 PIC: Handling OCW3 = %x (wr_Master1)\n", cw);
- state->master_ocw3 = cw;
+ if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
+ // specific EOI;
+ state->master_isr &= ~(0x01 << cw2->level);
+ } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
+ int i;
+ // Non-specific EOI
+ PrintDebug("8259 PIC: Pre ISR = %x (wr_Master1)\n", state->master_isr);
+ for (i = 0; i < 8; i++) {
+ if (state->master_isr & (0x01 << i)) {
+ state->master_isr &= ~(0x01 << i);
+ break;
+ }
+ }
+ PrintDebug("8259 PIC: Post ISR = %x (wr_Master1)\n", state->master_isr);
+ } else {
+ PrintError("8259 PIC: Command not handled, or in error (wr_Master1)\n");
+ return -1;
+ }
+
+ state->master_ocw2 = cw;
+ } else if (IS_OCW3(cw)) {
+ PrintDebug("8259 PIC: Handling OCW3 = %x (wr_Master1)\n", cw);
+ state->master_ocw3 = cw;
+ } else {
+ PrintError("8259 PIC: Invalid OCW to PIC (wr_Master1)\n");
+ PrintError("8259 PIC: CW=%x\n", cw);
+ return -1;
+ }
} else {
- PrintError("8259 PIC: Invalid OCW to PIC (wr_Master1)\n");
- PrintError("8259 PIC: CW=%x\n", cw);
- return -1;
+ PrintError("8259 PIC: Invalid PIC State (wr_Master1)\n");
+ PrintError("8259 PIC: CW=%x\n", cw);
+ return -1;
}
- } else {
- PrintError("8259 PIC: Invalid PIC State (wr_Master1)\n");
- PrintError("8259 PIC: CW=%x\n", cw);
- return -1;
- }
- return 1;
+ return 1;
}
static int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
if (length != 1) {
- PrintError("8259 PIC: Invalid Write length (wr_Master2)\n");
- return -1;
+ PrintError("8259 PIC: Invalid Write length (wr_Master2)\n");
+ return -1;
}
if (state->master_state == ICW2) {
- struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
+ struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
- PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Master2)\n", cw);
- state->master_icw2 = cw;
+ PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Master2)\n", cw);
+ state->master_icw2 = cw;
- if (cw1->sngl == 0) {
- state->master_state = ICW3;
- } else if (cw1->ic4 == 1) {
- state->master_state = ICW4;
- } else {
- state->master_state = READY;
- }
+ if (cw1->sngl == 0) {
+ state->master_state = ICW3;
+ } else if (cw1->ic4 == 1) {
+ state->master_state = ICW4;
+ } else {
+ state->master_state = READY;
+ }
} else if (state->master_state == ICW3) {
- struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
+ struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
- PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Master2)\n", cw);
+ PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Master2)\n", cw);
- state->master_icw3 = cw;
+ state->master_icw3 = cw;
- if (cw1->ic4 == 1) {
- state->master_state = ICW4;
- } else {
- state->master_state = READY;
- }
+ if (cw1->ic4 == 1) {
+ state->master_state = ICW4;
+ } else {
+ state->master_state = READY;
+ }
} else if (state->master_state == ICW4) {
- PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Master2)\n", cw);
- state->master_icw4 = cw;
- state->master_state = READY;
+ PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Master2)\n", cw);
+ state->master_icw4 = cw;
+ state->master_state = READY;
} else if (state->master_state == READY) {
- PrintDebug("8259 PIC: Setting IMR = %x (wr_Master2)\n", cw);
- state->master_imr = cw;
+ PrintDebug("8259 PIC: Setting IMR = %x (wr_Master2)\n", cw);
+ state->master_imr = cw;
} else {
- // error
- PrintError("8259 PIC: Invalid master PIC State (wr_Master2)\n");
- return -1;
+ // error
+ PrintError("8259 PIC: Invalid master PIC State (wr_Master2)\n");
+ return -1;
}
return 1;
}
static int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct pic_internal * state = (struct pic_internal*)dev->private_data;
- uchar_t cw = *(uchar_t *)src;
+ struct pic_internal * state = (struct pic_internal*)dev->private_data;
+ uchar_t cw = *(uchar_t *)src;
- PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
+ PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
- if (length != 1) {
- // error
- PrintError("8259 PIC: Invalid Write length (wr_Slave1)\n");
- return -1;
- }
+ if (length != 1) {
+ // error
+ PrintError("8259 PIC: Invalid Write length (wr_Slave1)\n");
+ return -1;
+ }
- if (IS_ICW1(cw)) {
- PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Slave1)\n", cw);
- state->slave_icw1 = cw;
- state->slave_state = ICW2;
- } else if (state->slave_state == READY) {
- if (IS_OCW2(cw)) {
- // handle the EOI here
- struct ocw2 * cw2 = (struct ocw2 *)&cw;
+ if (IS_ICW1(cw)) {
+ PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Slave1)\n", cw);
+ state->slave_icw1 = cw;
+ state->slave_state = ICW2;
+ } else if (state->slave_state == READY) {
+ if (IS_OCW2(cw)) {
+ // handle the EOI here
+ struct ocw2 * cw2 = (struct ocw2 *)&cw;
- PrintDebug("8259 PIC: Setting OCW2 = %x (wr_Slave1)\n", cw);
+ PrintDebug("8259 PIC: Setting OCW2 = %x (wr_Slave1)\n", cw);
- if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
- // specific EOI;
- state->slave_isr &= ~(0x01 << cw2->level);
- } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
- int i;
- // Non-specific EOI
- PrintDebug("8259 PIC: Pre ISR = %x (wr_Slave1)\n", state->slave_isr);
- for (i = 0; i < 8; i++) {
- if (state->slave_isr & (0x01 << i)) {
- state->slave_isr &= ~(0x01 << i);
- break;
- }
- }
- PrintDebug("8259 PIC: Post ISR = %x (wr_Slave1)\n", state->slave_isr);
- } else {
- PrintError("8259 PIC: Command not handled or invalid (wr_Slave1)\n");
- return -1;
- }
-
- state->slave_ocw2 = cw;
- } else if (IS_OCW3(cw)) {
- // Basically sets the IRR/ISR read flag
- PrintDebug("8259 PIC: Setting OCW3 = %x (wr_Slave1)\n", cw);
- state->slave_ocw3 = cw;
+ if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
+ // specific EOI;
+ state->slave_isr &= ~(0x01 << cw2->level);
+ } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
+ int i;
+ // Non-specific EOI
+ PrintDebug("8259 PIC: Pre ISR = %x (wr_Slave1)\n", state->slave_isr);
+ for (i = 0; i < 8; i++) {
+ if (state->slave_isr & (0x01 << i)) {
+ state->slave_isr &= ~(0x01 << i);
+ break;
+ }
+ }
+ PrintDebug("8259 PIC: Post ISR = %x (wr_Slave1)\n", state->slave_isr);
+ } else {
+ PrintError("8259 PIC: Command not handled or invalid (wr_Slave1)\n");
+ return -1;
+ }
+
+ state->slave_ocw2 = cw;
+ } else if (IS_OCW3(cw)) {
+ // Basically sets the IRR/ISR read flag
+ PrintDebug("8259 PIC: Setting OCW3 = %x (wr_Slave1)\n", cw);
+ state->slave_ocw3 = cw;
+ } else {
+ PrintError("8259 PIC: Invalid command work (wr_Slave1)\n");
+ return -1;
+ }
} else {
- PrintError("8259 PIC: Invalid command work (wr_Slave1)\n");
- return -1;
+ PrintError("8259 PIC: Invalid State writing (wr_Slave1)\n");
+ return -1;
}
- } else {
- PrintError("8259 PIC: Invalid State writing (wr_Slave1)\n");
- return -1;
- }
- return 1;
+ return 1;
}
static int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
if (length != 1) {
- PrintError("8259 PIC: Invalid write length (wr_Slave2)\n");
- return -1;
+ PrintError("8259 PIC: Invalid write length (wr_Slave2)\n");
+ return -1;
}
if (state->slave_state == ICW2) {
- struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
+ struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
- PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Slave2)\n", cw);
+ PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Slave2)\n", cw);
- state->slave_icw2 = cw;
+ state->slave_icw2 = cw;
- if (cw1->sngl == 0) {
- state->slave_state = ICW3;
- } else if (cw1->ic4 == 1) {
- state->slave_state = ICW4;
- } else {
- state->slave_state = READY;
- }
+ if (cw1->sngl == 0) {
+ state->slave_state = ICW3;
+ } else if (cw1->ic4 == 1) {
+ state->slave_state = ICW4;
+ } else {
+ state->slave_state = READY;
+ }
} else if (state->slave_state == ICW3) {
- struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
+ struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
- PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Slave2)\n", cw);
+ PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Slave2)\n", cw);
- state->slave_icw3 = cw;
+ state->slave_icw3 = cw;
- if (cw1->ic4 == 1) {
- state->slave_state = ICW4;
- } else {
- state->slave_state = READY;
- }
+ if (cw1->ic4 == 1) {
+ state->slave_state = ICW4;
+ } else {
+ state->slave_state = READY;
+ }
} else if (state->slave_state == ICW4) {
- PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Slave2)\n", cw);
- state->slave_icw4 = cw;
- state->slave_state = READY;
+ PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Slave2)\n", cw);
+ state->slave_icw4 = cw;
+ state->slave_state = READY;
} else if (state->slave_state == READY) {
- PrintDebug("8259 PIC: Setting IMR = %x (wr_Slave2)\n", cw);
- state->slave_imr = cw;
+ PrintDebug("8259 PIC: Setting IMR = %x (wr_Slave2)\n", cw);
+ state->slave_imr = cw;
} else {
- PrintError("8259 PIC: Invalid State at write (wr_Slave2)\n");
- return -1;
+ PrintError("8259 PIC: Invalid State at write (wr_Slave2)\n");
+ return -1;
}
return 1;
static int pic_init(struct vm_device * dev) {
- struct pic_internal * state = (struct pic_internal*)dev->private_data;
-
- v3_register_intr_controller(dev->vm, &intr_ops, state);
-
- state->master_irr = 0;
- state->master_isr = 0;
- state->master_icw1 = 0;
- state->master_icw2 = 0;
- state->master_icw3 = 0;
- state->master_icw4 = 0;
- state->master_imr = 0;
- state->master_ocw2 = 0;
- state->master_ocw3 = 0x02;
- state->master_state = ICW1;
-
-
- state->slave_irr = 0;
- state->slave_isr = 0;
- state->slave_icw1 = 0;
- state->slave_icw2 = 0;
- state->slave_icw3 = 0;
- state->slave_icw4 = 0;
- state->slave_imr = 0;
- state->slave_ocw2 = 0;
- state->slave_ocw3 = 0x02;
- state->slave_state = ICW1;
-
-
- v3_dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
- v3_dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
- v3_dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
- v3_dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
+ struct pic_internal * state = (struct pic_internal*)dev->private_data;
- return 0;
+ v3_register_intr_controller(dev->vm, &intr_ops, state);
+
+ state->master_irr = 0;
+ state->master_isr = 0;
+ state->master_icw1 = 0;
+ state->master_icw2 = 0;
+ state->master_icw3 = 0;
+ state->master_icw4 = 0;
+ state->master_imr = 0;
+ state->master_ocw2 = 0;
+ state->master_ocw3 = 0x02;
+ state->master_state = ICW1;
+
+
+ state->slave_irr = 0;
+ state->slave_isr = 0;
+ state->slave_icw1 = 0;
+ state->slave_icw2 = 0;
+ state->slave_icw3 = 0;
+ state->slave_icw4 = 0;
+ state->slave_imr = 0;
+ state->slave_ocw2 = 0;
+ state->slave_ocw3 = 0x02;
+ state->slave_state = ICW1;
+
+
+ v3_dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
+ v3_dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
+ v3_dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
+ v3_dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
+
+ return 0;
}
static int pic_deinit(struct vm_device * dev) {
- v3_dev_unhook_io(dev, MASTER_PORT1);
- v3_dev_unhook_io(dev, MASTER_PORT2);
- v3_dev_unhook_io(dev, SLAVE_PORT1);
- v3_dev_unhook_io(dev, SLAVE_PORT2);
+ v3_dev_unhook_io(dev, MASTER_PORT1);
+ v3_dev_unhook_io(dev, MASTER_PORT2);
+ v3_dev_unhook_io(dev, SLAVE_PORT1);
+ v3_dev_unhook_io(dev, SLAVE_PORT2);
- return 0;
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = pic_init,
- .deinit = pic_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = pic_init,
+ .deinit = pic_deinit,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_pic() {
- struct pic_internal * state = NULL;
- state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
- V3_ASSERT(state != NULL);
+ struct pic_internal * state = NULL;
+ state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
+ V3_ASSERT(state != NULL);
- struct vm_device *device = v3_create_device("8259A", &dev_ops, state);
+ struct vm_device *device = v3_create_device("8259A", &dev_ops, state);
- return device;
+ return device;
}
-
-
-
-
struct apic_msr {
- union {
- uint64_t val;
- struct {
- uchar_t rsvd;
- uint_t bootstrap_cpu : 1;
- uint_t rsvd2 : 2;
- uint_t apic_enable : 1;
- ullong_t base_addr : 40;
- uint_t rsvd3 : 12;
+ union {
+ uint64_t val;
+ struct {
+ uchar_t rsvd;
+ uint_t bootstrap_cpu : 1;
+ uint_t rsvd2 : 2;
+ uint_t apic_enable : 1;
+ ullong_t base_addr : 40;
+ uint_t rsvd3 : 12;
+ } __attribute__((packed));
} __attribute__((packed));
- } __attribute__((packed));
} __attribute__((packed));
struct apic_state {
- addr_t base_addr;
-
- /* MSRs */
- v3_msr_t base_addr_msr;
-
-
- /* memory map registers */
-
- struct lapic_id_reg lapic_id;
- struct apic_ver_reg apic_ver;
- struct ext_apic_ctrl_reg ext_apic_ctrl;
- struct local_vec_tbl_reg local_vec_tbl;
- struct tmr_vec_tbl_reg tmr_vec_tbl;
- struct tmr_div_cfg_reg tmr_div_cfg;
- struct lint_vec_tbl_reg lint0_vec_tbl;
- struct lint_vec_tbl_reg lint1_vec_tbl;
- struct perf_ctr_loc_vec_tbl_reg perf_ctr_loc_vec_tbl;
- struct therm_loc_vec_tbl_reg therm_loc_vec_tbl;
- struct err_vec_tbl_reg err_vec_tbl;
- struct err_status_reg err_status;
- struct spurious_int_reg spurious_int;
- struct int_cmd_reg int_cmd;
- struct log_dst_reg log_dst;
- struct dst_fmt_reg dst_fmt;
- struct arb_prio_reg arb_prio;
- struct task_prio_reg task_prio;
- struct proc_prio_reg proc_prio;
- struct ext_apic_feature_reg ext_apic_feature;
- struct spec_eoi_reg spec_eoi;
+ addr_t base_addr;
+
+ /* MSRs */
+ v3_msr_t base_addr_msr;
+
+
+ /* memory map registers */
+
+ struct lapic_id_reg lapic_id;
+ struct apic_ver_reg apic_ver;
+ struct ext_apic_ctrl_reg ext_apic_ctrl;
+ struct local_vec_tbl_reg local_vec_tbl;
+ struct tmr_vec_tbl_reg tmr_vec_tbl;
+ struct tmr_div_cfg_reg tmr_div_cfg;
+ struct lint_vec_tbl_reg lint0_vec_tbl;
+ struct lint_vec_tbl_reg lint1_vec_tbl;
+ struct perf_ctr_loc_vec_tbl_reg perf_ctr_loc_vec_tbl;
+ struct therm_loc_vec_tbl_reg therm_loc_vec_tbl;
+ struct err_vec_tbl_reg err_vec_tbl;
+ struct err_status_reg err_status;
+ struct spurious_int_reg spurious_int;
+ struct int_cmd_reg int_cmd;
+ struct log_dst_reg log_dst;
+ struct dst_fmt_reg dst_fmt;
+ struct arb_prio_reg arb_prio;
+ struct task_prio_reg task_prio;
+ struct proc_prio_reg proc_prio;
+ struct ext_apic_feature_reg ext_apic_feature;
+ struct spec_eoi_reg spec_eoi;
- uint32_t tmr_cur_cnt;
- uint32_t tmr_init_cnt;
+ uint32_t tmr_cur_cnt;
+ uint32_t tmr_init_cnt;
- uint32_t rem_rd_data;
+ uint32_t rem_rd_data;
- uchar_t int_req_reg[32];
- uchar_t int_svc_reg[32];
- uchar_t int_en_reg[32];
- uchar_t trig_mode_reg[32];
+ uchar_t int_req_reg[32];
+ uchar_t int_svc_reg[32];
+ uchar_t int_en_reg[32];
+ uchar_t trig_mode_reg[32];
- uint32_t eoi;
+ uint32_t eoi;
};
static void init_apic_state(struct apic_state * apic) {
- apic->base_addr = DEFAULT_BASE_ADDR;
- apic->base_addr_msr.value = 0x0000000000000900LL;
- apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR);
-
- PrintDebug("Sizeof Interrupt Request Register %d, should be 32\n",
- (uint_t)sizeof(apic->int_req_reg));
-
- memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
- memset(apic->int_svc_reg, 0, sizeof(apic->int_svc_reg));
- memset(apic->int_en_reg, 0xff, sizeof(apic->int_en_reg));
- memset(apic->trig_mode_reg, 0, sizeof(apic->trig_mode_reg));
-
- apic->eoi = 0x00000000;
- apic->rem_rd_data = 0x00000000;
- apic->tmr_init_cnt = 0x00000000;
- apic->tmr_cur_cnt = 0x00000000;
-
- // TODO:
- // We need to figure out what the APIC ID is....
- apic->lapic_id.val = 0x00000000;
-
- // The P6 has 6 LVT entries, so we set the value to (6-1)...
- apic->apic_ver.val = 0x80050010;
-
- apic->task_prio.val = 0x00000000;
- apic->arb_prio.val = 0x00000000;
- apic->proc_prio.val = 0x00000000;
- apic->log_dst.val = 0x00000000;
- apic->dst_fmt.val = 0xffffffff;
- apic->spurious_int.val = 0x000000ff;
- apic->err_status.val = 0x00000000;
- apic->int_cmd.val = 0x0000000000000000LL;
- apic->tmr_vec_tbl.val = 0x00010000;
- apic->therm_loc_vec_tbl.val = 0x00010000;
- apic->perf_ctr_loc_vec_tbl.val = 0x00010000;
- apic->lint0_vec_tbl.val = 0x00010000;
- apic->lint1_vec_tbl.val = 0x00010000;
- apic->err_vec_tbl.val = 0x00010000;
- apic->tmr_div_cfg.val = 0x00000000;
- apic->ext_apic_feature.val = 0x00040007;
- apic->ext_apic_ctrl.val = 0x00000000;
- apic->spec_eoi.val = 0x00000000;
+ apic->base_addr = DEFAULT_BASE_ADDR;
+ apic->base_addr_msr.value = 0x0000000000000900LL;
+ apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR);
+
+ PrintDebug("Sizeof Interrupt Request Register %d, should be 32\n",
+ (uint_t)sizeof(apic->int_req_reg));
+
+ memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
+ memset(apic->int_svc_reg, 0, sizeof(apic->int_svc_reg));
+ memset(apic->int_en_reg, 0xff, sizeof(apic->int_en_reg));
+ memset(apic->trig_mode_reg, 0, sizeof(apic->trig_mode_reg));
+
+ apic->eoi = 0x00000000;
+ apic->rem_rd_data = 0x00000000;
+ apic->tmr_init_cnt = 0x00000000;
+ apic->tmr_cur_cnt = 0x00000000;
+
+ // TODO:
+ // We need to figure out what the APIC ID is....
+ apic->lapic_id.val = 0x00000000;
+
+ // The P6 has 6 LVT entries, so we set the value to (6-1)...
+ apic->apic_ver.val = 0x80050010;
+
+ apic->task_prio.val = 0x00000000;
+ apic->arb_prio.val = 0x00000000;
+ apic->proc_prio.val = 0x00000000;
+ apic->log_dst.val = 0x00000000;
+ apic->dst_fmt.val = 0xffffffff;
+ apic->spurious_int.val = 0x000000ff;
+ apic->err_status.val = 0x00000000;
+ apic->int_cmd.val = 0x0000000000000000LL;
+ apic->tmr_vec_tbl.val = 0x00010000;
+ apic->therm_loc_vec_tbl.val = 0x00010000;
+ apic->perf_ctr_loc_vec_tbl.val = 0x00010000;
+ apic->lint0_vec_tbl.val = 0x00010000;
+ apic->lint1_vec_tbl.val = 0x00010000;
+ apic->err_vec_tbl.val = 0x00010000;
+ apic->tmr_div_cfg.val = 0x00000000;
+ apic->ext_apic_feature.val = 0x00040007;
+ apic->ext_apic_ctrl.val = 0x00000000;
+ apic->spec_eoi.val = 0x00000000;
}
static int read_apic_msr(uint_t msr, v3_msr_t * dst, void * priv_data) {
- struct vm_device * dev = (struct vm_device *)priv_data;
- struct apic_state * apic = (struct apic_state *)dev->private_data;
- PrintError("READING APIC BASE ADDR: HI=%x LO=%x\n", apic->base_addr_msr.hi, apic->base_addr_msr.lo);
+ struct vm_device * dev = (struct vm_device *)priv_data;
+ struct apic_state * apic = (struct apic_state *)dev->private_data;
+ PrintError("READING APIC BASE ADDR: HI=%x LO=%x\n", apic->base_addr_msr.hi, apic->base_addr_msr.lo);
- return -1;
+ return -1;
}
static int write_apic_msr(uint_t msr, v3_msr_t src, void * priv_data) {
- // struct vm_device * dev = (struct vm_device *)priv_data;
- // struct apic_state * apic = (struct apic_state *)dev->private_data;
+ // struct vm_device * dev = (struct vm_device *)priv_data;
+ // struct apic_state * apic = (struct apic_state *)dev->private_data;
- PrintError("WRITING APIC BASE ADDR: HI=%x LO=%x\n", src.hi, src.lo);
+ PrintError("WRITING APIC BASE ADDR: HI=%x LO=%x\n", src.hi, src.lo);
- return -1;
+ return -1;
}
// irq_num is the bit offset into a 256 bit buffer...
static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
- int major_offset = (irq_num & ~0x00000007) >> 3;
- int minor_offset = irq_num & 0x00000007;
- uchar_t * req_location = apic->int_req_reg + major_offset;
- uchar_t * en_location = apic->int_en_reg + major_offset;
- uchar_t flag = 0x1 << minor_offset;
-
- if (irq_num <= 15) {
- PrintError("Attempting to raise an invalid interrupt: %d\n", irq_num);
- return -1;
- }
+ int major_offset = (irq_num & ~0x00000007) >> 3;
+ int minor_offset = irq_num & 0x00000007;
+ uchar_t * req_location = apic->int_req_reg + major_offset;
+ uchar_t * en_location = apic->int_en_reg + major_offset;
+ uchar_t flag = 0x1 << minor_offset;
+
+ if (irq_num <= 15) {
+ PrintError("Attempting to raise an invalid interrupt: %d\n", irq_num);
+ return -1;
+ }
- PrintDebug("Raising APIC IRQ %d\n", irq_num);
+ PrintDebug("Raising APIC IRQ %d\n", irq_num);
- if (*en_location & flag) {
- *req_location |= flag;
- } else {
- PrintDebug("Interrupt not enabled... %.2x\n", *en_location);
- return 0;
- }
+ if (*en_location & flag) {
+ *req_location |= flag;
+ } else {
+ PrintDebug("Interrupt not enabled... %.2x\n", *en_location);
+ return 0;
+ }
- return 0;
+ return 0;
}
static int apic_do_eoi(struct apic_state * apic) {
- int i = 0, j = 0;
+ int i = 0, j = 0;
- // We iterate backwards to find the highest priority
- for (i = 31; i >= 0; i--) {
- uchar_t * svc_major = apic->int_svc_reg + i;
+ // We iterate backwards to find the highest priority
+ for (i = 31; i >= 0; i--) {
+ uchar_t * svc_major = apic->int_svc_reg + i;
- if ((*svc_major) & 0xff) {
- for (j = 7; j >= 0; j--) {
- uchar_t flag = 0x1 << j;
- if ((*svc_major) & flag) {
- *svc_major &= ~flag;
- return 0;
+ if ((*svc_major) & 0xff) {
+ for (j = 7; j >= 0; j--) {
+ uchar_t flag = 0x1 << j;
+ if ((*svc_major) & flag) {
+ *svc_major &= ~flag;
+ return 0;
+ }
+ }
}
- }
}
- }
- return 0;
+ return 0;
}
static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
- uint32_t vec_num = 0;
- uint32_t del_mode = 0;
- int masked = 0;
-
-
- switch (int_type) {
- case APIC_TMR_INT:
- vec_num = apic->tmr_vec_tbl.vec;
- del_mode = APIC_FIXED_DELIVERY;
- masked = apic->tmr_vec_tbl.mask;
- break;
- case APIC_THERM_INT:
- vec_num = apic->therm_loc_vec_tbl.vec;
- del_mode = apic->therm_loc_vec_tbl.msg_type;
- masked = apic->therm_loc_vec_tbl.mask;
- break;
- case APIC_PERF_INT:
- vec_num = apic->perf_ctr_loc_vec_tbl.vec;
- del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
- masked = apic->perf_ctr_loc_vec_tbl.mask;
- break;
- case APIC_LINT0_INT:
- vec_num = apic->lint0_vec_tbl.vec;
- del_mode = apic->lint0_vec_tbl.msg_type;
- masked = apic->lint0_vec_tbl.mask;
- break;
- case APIC_LINT1_INT:
- vec_num = apic->lint1_vec_tbl.vec;
- del_mode = apic->lint1_vec_tbl.msg_type;
- masked = apic->lint1_vec_tbl.mask;
- break;
- case APIC_ERR_INT:
- vec_num = apic->err_vec_tbl.vec;
- del_mode = APIC_FIXED_DELIVERY;
- masked = apic->err_vec_tbl.mask;
- break;
- default:
- PrintError("Invalid APIC interrupt type\n");
- return -1;
- }
+ uint32_t vec_num = 0;
+ uint32_t del_mode = 0;
+ int masked = 0;
+
+
+ switch (int_type) {
+ case APIC_TMR_INT:
+ vec_num = apic->tmr_vec_tbl.vec;
+ del_mode = APIC_FIXED_DELIVERY;
+ masked = apic->tmr_vec_tbl.mask;
+ break;
+ case APIC_THERM_INT:
+ vec_num = apic->therm_loc_vec_tbl.vec;
+ del_mode = apic->therm_loc_vec_tbl.msg_type;
+ masked = apic->therm_loc_vec_tbl.mask;
+ break;
+ case APIC_PERF_INT:
+ vec_num = apic->perf_ctr_loc_vec_tbl.vec;
+ del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
+ masked = apic->perf_ctr_loc_vec_tbl.mask;
+ break;
+ case APIC_LINT0_INT:
+ vec_num = apic->lint0_vec_tbl.vec;
+ del_mode = apic->lint0_vec_tbl.msg_type;
+ masked = apic->lint0_vec_tbl.mask;
+ break;
+ case APIC_LINT1_INT:
+ vec_num = apic->lint1_vec_tbl.vec;
+ del_mode = apic->lint1_vec_tbl.msg_type;
+ masked = apic->lint1_vec_tbl.mask;
+ break;
+ case APIC_ERR_INT:
+ vec_num = apic->err_vec_tbl.vec;
+ del_mode = APIC_FIXED_DELIVERY;
+ masked = apic->err_vec_tbl.mask;
+ break;
+ default:
+ PrintError("Invalid APIC interrupt type\n");
+ return -1;
+ }
- // interrupt is masked, don't send
- if (masked == 1) {
- PrintDebug("Inerrupt is masked\n");
- return 0;
- }
+ // interrupt is masked, don't send
+ if (masked == 1) {
+ PrintDebug("Inerrupt is masked\n");
+ return 0;
+ }
- if (del_mode == APIC_FIXED_DELIVERY) {
- //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
- return activate_apic_irq(apic, vec_num);
- } else {
- PrintError("Unhandled Delivery Mode\n");
- return -1;
- }
+ if (del_mode == APIC_FIXED_DELIVERY) {
+ //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
+ return activate_apic_irq(apic, vec_num);
+ } else {
+ PrintError("Unhandled Delivery Mode\n");
+ return -1;
+ }
}
static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
- struct vm_device * dev = (struct vm_device *)priv_data;
- struct apic_state * apic = (struct apic_state *)dev->private_data;
- addr_t reg_addr = guest_addr - apic->base_addr;
- struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
- uint32_t val = 0;
+ struct vm_device * dev = (struct vm_device *)priv_data;
+ struct apic_state * apic = (struct apic_state *)dev->private_data;
+ addr_t reg_addr = guest_addr - apic->base_addr;
+ struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
+ uint32_t val = 0;
- PrintDebug("Read apic address space (%p)\n",
- (void *)guest_addr);
+ PrintDebug("Read apic address space (%p)\n",
+ (void *)guest_addr);
- if (msr->apic_enable == 0) {
- PrintError("Write to APIC address space with disabled APIC\n");
- return -1;
- }
-
-
- /* Because "May not be supported" doesn't matter to Linux developers... */
- /* if (length != 4) { */
- /* PrintError("Invalid apic read length (%d)\n", length); */
- /* return -1; */
- /* } */
-
- switch (reg_addr & ~0x3) {
- case EOI_OFFSET:
- // Well, only an idiot would read from a architectural write only register
- // Oh, Hello Linux.
- // PrintError("Attempting to read from write only register\n");
- // return -1;
- break;
-
- // data registers
- case APIC_ID_OFFSET:
- val = apic->lapic_id.val;
- break;
- case APIC_VERSION_OFFSET:
- val = apic->apic_ver.val;
- break;
- case TPR_OFFSET:
- val = apic->task_prio.val;
- break;
- case APR_OFFSET:
- val = apic->arb_prio.val;
- break;
- case PPR_OFFSET:
- val = apic->proc_prio.val;
- break;
- case REMOTE_READ_OFFSET:
- val = apic->rem_rd_data;
- break;
- case LDR_OFFSET:
- val = apic->log_dst.val;
- break;
- case DFR_OFFSET:
- val = apic->dst_fmt.val;
- break;
- case SPURIOUS_INT_VEC_OFFSET:
- val = apic->spurious_int.val;
- break;
- case ESR_OFFSET:
- val = apic->err_status.val;
- break;
- case TMR_LOC_VEC_TBL_OFFSET:
- val = apic->tmr_vec_tbl.val;
- break;
- case LINT0_VEC_TBL_OFFSET:
- val = apic->lint0_vec_tbl.val;
- break;
- case LINT1_VEC_TBL_OFFSET:
- val = apic->lint1_vec_tbl.val;
- break;
- case ERR_VEC_TBL_OFFSET:
- val = apic->err_vec_tbl.val;
- break;
- case TMR_INIT_CNT_OFFSET:
- val = apic->tmr_init_cnt;
- break;
- case TMR_DIV_CFG_OFFSET:
- val = apic->tmr_div_cfg.val;
- break;
-
- case IER_OFFSET0:
- val = *(uint32_t *)(apic->int_en_reg);
- break;
- case IER_OFFSET1:
- val = *(uint32_t *)(apic->int_en_reg + 4);
- break;
- case IER_OFFSET2:
- val = *(uint32_t *)(apic->int_en_reg + 8);
- break;
- case IER_OFFSET3:
- val = *(uint32_t *)(apic->int_en_reg + 12);
- break;
- case IER_OFFSET4:
- val = *(uint32_t *)(apic->int_en_reg + 16);
- break;
- case IER_OFFSET5:
- val = *(uint32_t *)(apic->int_en_reg + 20);
- break;
- case IER_OFFSET6:
- val = *(uint32_t *)(apic->int_en_reg + 24);
- break;
- case IER_OFFSET7:
- val = *(uint32_t *)(apic->int_en_reg + 28);
- break;
-
- case ISR_OFFSET0:
- val = *(uint32_t *)(apic->int_svc_reg);
- break;
- case ISR_OFFSET1:
- val = *(uint32_t *)(apic->int_svc_reg + 4);
- break;
- case ISR_OFFSET2:
- val = *(uint32_t *)(apic->int_svc_reg + 8);
- break;
- case ISR_OFFSET3:
- val = *(uint32_t *)(apic->int_svc_reg + 12);
- break;
- case ISR_OFFSET4:
- val = *(uint32_t *)(apic->int_svc_reg + 16);
- break;
- case ISR_OFFSET5:
- val = *(uint32_t *)(apic->int_svc_reg + 20);
- break;
- case ISR_OFFSET6:
- val = *(uint32_t *)(apic->int_svc_reg + 24);
- break;
- case ISR_OFFSET7:
- val = *(uint32_t *)(apic->int_svc_reg + 28);
- break;
+ if (msr->apic_enable == 0) {
+ PrintError("Write to APIC address space with disabled APIC\n");
+ return -1;
+ }
+
+
+ /* Because "May not be supported" doesn't matter to Linux developers... */
+ /* if (length != 4) { */
+ /* PrintError("Invalid apic read length (%d)\n", length); */
+ /* return -1; */
+ /* } */
+
+ switch (reg_addr & ~0x3) {
+ case EOI_OFFSET:
+ // Well, only an idiot would read from a architectural write only register
+ // Oh, Hello Linux.
+ // PrintError("Attempting to read from write only register\n");
+ // return -1;
+ break;
+
+ // data registers
+ case APIC_ID_OFFSET:
+ val = apic->lapic_id.val;
+ break;
+ case APIC_VERSION_OFFSET:
+ val = apic->apic_ver.val;
+ break;
+ case TPR_OFFSET:
+ val = apic->task_prio.val;
+ break;
+ case APR_OFFSET:
+ val = apic->arb_prio.val;
+ break;
+ case PPR_OFFSET:
+ val = apic->proc_prio.val;
+ break;
+ case REMOTE_READ_OFFSET:
+ val = apic->rem_rd_data;
+ break;
+ case LDR_OFFSET:
+ val = apic->log_dst.val;
+ break;
+ case DFR_OFFSET:
+ val = apic->dst_fmt.val;
+ break;
+ case SPURIOUS_INT_VEC_OFFSET:
+ val = apic->spurious_int.val;
+ break;
+ case ESR_OFFSET:
+ val = apic->err_status.val;
+ break;
+ case TMR_LOC_VEC_TBL_OFFSET:
+ val = apic->tmr_vec_tbl.val;
+ break;
+ case LINT0_VEC_TBL_OFFSET:
+ val = apic->lint0_vec_tbl.val;
+ break;
+ case LINT1_VEC_TBL_OFFSET:
+ val = apic->lint1_vec_tbl.val;
+ break;
+ case ERR_VEC_TBL_OFFSET:
+ val = apic->err_vec_tbl.val;
+ break;
+ case TMR_INIT_CNT_OFFSET:
+ val = apic->tmr_init_cnt;
+ break;
+ case TMR_DIV_CFG_OFFSET:
+ val = apic->tmr_div_cfg.val;
+ break;
+
+ case IER_OFFSET0:
+ val = *(uint32_t *)(apic->int_en_reg);
+ break;
+ case IER_OFFSET1:
+ val = *(uint32_t *)(apic->int_en_reg + 4);
+ break;
+ case IER_OFFSET2:
+ val = *(uint32_t *)(apic->int_en_reg + 8);
+ break;
+ case IER_OFFSET3:
+ val = *(uint32_t *)(apic->int_en_reg + 12);
+ break;
+ case IER_OFFSET4:
+ val = *(uint32_t *)(apic->int_en_reg + 16);
+ break;
+ case IER_OFFSET5:
+ val = *(uint32_t *)(apic->int_en_reg + 20);
+ break;
+ case IER_OFFSET6:
+ val = *(uint32_t *)(apic->int_en_reg + 24);
+ break;
+ case IER_OFFSET7:
+ val = *(uint32_t *)(apic->int_en_reg + 28);
+ break;
+
+ case ISR_OFFSET0:
+ val = *(uint32_t *)(apic->int_svc_reg);
+ break;
+ case ISR_OFFSET1:
+ val = *(uint32_t *)(apic->int_svc_reg + 4);
+ break;
+ case ISR_OFFSET2:
+ val = *(uint32_t *)(apic->int_svc_reg + 8);
+ break;
+ case ISR_OFFSET3:
+ val = *(uint32_t *)(apic->int_svc_reg + 12);
+ break;
+ case ISR_OFFSET4:
+ val = *(uint32_t *)(apic->int_svc_reg + 16);
+ break;
+ case ISR_OFFSET5:
+ val = *(uint32_t *)(apic->int_svc_reg + 20);
+ break;
+ case ISR_OFFSET6:
+ val = *(uint32_t *)(apic->int_svc_reg + 24);
+ break;
+ case ISR_OFFSET7:
+ val = *(uint32_t *)(apic->int_svc_reg + 28);
+ break;
- case TRIG_OFFSET0:
- val = *(uint32_t *)(apic->trig_mode_reg);
- break;
- case TRIG_OFFSET1:
- val = *(uint32_t *)(apic->trig_mode_reg + 4);
- break;
- case TRIG_OFFSET2:
- val = *(uint32_t *)(apic->trig_mode_reg + 8);
- break;
- case TRIG_OFFSET3:
- val = *(uint32_t *)(apic->trig_mode_reg + 12);
- break;
- case TRIG_OFFSET4:
- val = *(uint32_t *)(apic->trig_mode_reg + 16);
- break;
- case TRIG_OFFSET5:
- val = *(uint32_t *)(apic->trig_mode_reg + 20);
- break;
- case TRIG_OFFSET6:
- val = *(uint32_t *)(apic->trig_mode_reg + 24);
- break;
- case TRIG_OFFSET7:
- val = *(uint32_t *)(apic->trig_mode_reg + 28);
- break;
-
- case IRR_OFFSET0:
- val = *(uint32_t *)(apic->int_req_reg);
- break;
- case IRR_OFFSET1:
- val = *(uint32_t *)(apic->int_req_reg + 4);
- break;
- case IRR_OFFSET2:
- val = *(uint32_t *)(apic->int_req_reg + 8);
- break;
- case IRR_OFFSET3:
- val = *(uint32_t *)(apic->int_req_reg + 12);
- break;
- case IRR_OFFSET4:
- val = *(uint32_t *)(apic->int_req_reg + 16);
- break;
- case IRR_OFFSET5:
- val = *(uint32_t *)(apic->int_req_reg + 20);
- break;
- case IRR_OFFSET6:
- val = *(uint32_t *)(apic->int_req_reg + 24);
- break;
- case IRR_OFFSET7:
- val = *(uint32_t *)(apic->int_req_reg + 28);
- break;
- case TMR_CUR_CNT_OFFSET:
- val = apic->tmr_cur_cnt;
- break;
-
- // We are not going to implement these....
- case THERM_LOC_VEC_TBL_OFFSET:
- val = apic->therm_loc_vec_tbl.val;
- break;
- case PERF_CTR_LOC_VEC_TBL_OFFSET:
- val = apic->perf_ctr_loc_vec_tbl.val;
- break;
+ case TRIG_OFFSET0:
+ val = *(uint32_t *)(apic->trig_mode_reg);
+ break;
+ case TRIG_OFFSET1:
+ val = *(uint32_t *)(apic->trig_mode_reg + 4);
+ break;
+ case TRIG_OFFSET2:
+ val = *(uint32_t *)(apic->trig_mode_reg + 8);
+ break;
+ case TRIG_OFFSET3:
+ val = *(uint32_t *)(apic->trig_mode_reg + 12);
+ break;
+ case TRIG_OFFSET4:
+ val = *(uint32_t *)(apic->trig_mode_reg + 16);
+ break;
+ case TRIG_OFFSET5:
+ val = *(uint32_t *)(apic->trig_mode_reg + 20);
+ break;
+ case TRIG_OFFSET6:
+ val = *(uint32_t *)(apic->trig_mode_reg + 24);
+ break;
+ case TRIG_OFFSET7:
+ val = *(uint32_t *)(apic->trig_mode_reg + 28);
+ break;
+
+ case IRR_OFFSET0:
+ val = *(uint32_t *)(apic->int_req_reg);
+ break;
+ case IRR_OFFSET1:
+ val = *(uint32_t *)(apic->int_req_reg + 4);
+ break;
+ case IRR_OFFSET2:
+ val = *(uint32_t *)(apic->int_req_reg + 8);
+ break;
+ case IRR_OFFSET3:
+ val = *(uint32_t *)(apic->int_req_reg + 12);
+ break;
+ case IRR_OFFSET4:
+ val = *(uint32_t *)(apic->int_req_reg + 16);
+ break;
+ case IRR_OFFSET5:
+ val = *(uint32_t *)(apic->int_req_reg + 20);
+ break;
+ case IRR_OFFSET6:
+ val = *(uint32_t *)(apic->int_req_reg + 24);
+ break;
+ case IRR_OFFSET7:
+ val = *(uint32_t *)(apic->int_req_reg + 28);
+ break;
+ case TMR_CUR_CNT_OFFSET:
+ val = apic->tmr_cur_cnt;
+ break;
+
+ // We are not going to implement these....
+ case THERM_LOC_VEC_TBL_OFFSET:
+ val = apic->therm_loc_vec_tbl.val;
+ break;
+ case PERF_CTR_LOC_VEC_TBL_OFFSET:
+ val = apic->perf_ctr_loc_vec_tbl.val;
+ break;
- // handled registers
- case INT_CMD_LO_OFFSET:
- val = apic->int_cmd.lo;
- break;
- case INT_CMD_HI_OFFSET:
- val = apic->int_cmd.hi;
- break;
-
- // handle current timer count
-
- // Unhandled Registers
- case EXT_INT_LOC_VEC_TBL_OFFSET0:
- case EXT_INT_LOC_VEC_TBL_OFFSET1:
- case EXT_INT_LOC_VEC_TBL_OFFSET2:
- case EXT_INT_LOC_VEC_TBL_OFFSET3:
- case EXT_APIC_FEATURE_OFFSET:
- case EXT_APIC_CMD_OFFSET:
- case SEOI_OFFSET:
-
- default:
- PrintError("Read from Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
- return -1;
- }
+ // handled registers
+ case INT_CMD_LO_OFFSET:
+ val = apic->int_cmd.lo;
+ break;
+ case INT_CMD_HI_OFFSET:
+ val = apic->int_cmd.hi;
+ break;
+
+ // handle current timer count
+
+ // Unhandled Registers
+ case EXT_INT_LOC_VEC_TBL_OFFSET0:
+ case EXT_INT_LOC_VEC_TBL_OFFSET1:
+ case EXT_INT_LOC_VEC_TBL_OFFSET2:
+ case EXT_INT_LOC_VEC_TBL_OFFSET3:
+ case EXT_APIC_FEATURE_OFFSET:
+ case EXT_APIC_CMD_OFFSET:
+ case SEOI_OFFSET:
+
+ default:
+ PrintError("Read from Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
+ return -1;
+ }
- if (length == 1) {
- uint_t byte_addr = reg_addr & 0x3;
- uint8_t * val_ptr = (uint8_t *)dst;
+ if (length == 1) {
+ uint_t byte_addr = reg_addr & 0x3;
+ uint8_t * val_ptr = (uint8_t *)dst;
- *val_ptr = *(((uint8_t *)&val) + byte_addr);
+ *val_ptr = *(((uint8_t *)&val) + byte_addr);
- } else if ((length == 2) &&
- ((reg_addr & 0x3) == 0x3)) {
- uint_t byte_addr = reg_addr & 0x3;
- uint16_t * val_ptr = (uint16_t *)dst;
- *val_ptr = *(((uint16_t *)&val) + byte_addr);
+ } else if ((length == 2) &&
+ ((reg_addr & 0x3) == 0x3)) {
+ uint_t byte_addr = reg_addr & 0x3;
+ uint16_t * val_ptr = (uint16_t *)dst;
+ *val_ptr = *(((uint16_t *)&val) + byte_addr);
- } else if (length == 4) {
- uint32_t * val_ptr = (uint32_t *)dst;
- *val_ptr = val;
+ } else if (length == 4) {
+ uint32_t * val_ptr = (uint32_t *)dst;
+ *val_ptr = val;
- } else {
- PrintError("Invalid apic read length (%d)\n", length);
- return -1;
- }
+ } else {
+ PrintError("Invalid apic read length (%d)\n", length);
+ return -1;
+ }
- PrintDebug("Read finished (val=%x)\n", *(uint32_t *)dst);
+ PrintDebug("Read finished (val=%x)\n", *(uint32_t *)dst);
- return length;
+ return length;
}
static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
- struct vm_device * dev = (struct vm_device *)priv_data;
- struct apic_state * apic = (struct apic_state *)dev->private_data;
- addr_t reg_addr = guest_addr - apic->base_addr;
- struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
- uint32_t op_val = *(uint32_t *)src;
-
- PrintDebug("Write to apic address space (%p) (val=%x)\n",
- (void *)guest_addr, *(uint32_t *)src);
+ struct vm_device * dev = (struct vm_device *)priv_data;
+ struct apic_state * apic = (struct apic_state *)dev->private_data;
+ addr_t reg_addr = guest_addr - apic->base_addr;
+ struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
+ uint32_t op_val = *(uint32_t *)src;
+
+ PrintDebug("Write to apic address space (%p) (val=%x)\n",
+ (void *)guest_addr, *(uint32_t *)src);
+
+ if (msr->apic_enable == 0) {
+ PrintError("Write to APIC address space with disabled APIC\n");
+ return -1;
+ }
- if (msr->apic_enable == 0) {
- PrintError("Write to APIC address space with disabled APIC\n");
- return -1;
- }
+ if (length != 4) {
+ PrintError("Invalid apic write length (%d)\n", length);
+ return -1;
+ }
- if (length != 4) {
- PrintError("Invalid apic write length (%d)\n", length);
- return -1;
- }
-
- switch (reg_addr) {
- case REMOTE_READ_OFFSET:
- case APIC_VERSION_OFFSET:
- case APR_OFFSET:
- case IRR_OFFSET0:
- case IRR_OFFSET1:
- case IRR_OFFSET2:
- case IRR_OFFSET3:
- case IRR_OFFSET4:
- case IRR_OFFSET5:
- case IRR_OFFSET6:
- case IRR_OFFSET7:
- case ISR_OFFSET0:
- case ISR_OFFSET1:
- case ISR_OFFSET2:
- case ISR_OFFSET3:
- case ISR_OFFSET4:
- case ISR_OFFSET5:
- case ISR_OFFSET6:
- case ISR_OFFSET7:
- case TRIG_OFFSET0:
- case TRIG_OFFSET1:
- case TRIG_OFFSET2:
- case TRIG_OFFSET3:
- case TRIG_OFFSET4:
- case TRIG_OFFSET5:
- case TRIG_OFFSET6:
- case TRIG_OFFSET7:
- case PPR_OFFSET:
- case EXT_APIC_FEATURE_OFFSET:
+ switch (reg_addr) {
+ case REMOTE_READ_OFFSET:
+ case APIC_VERSION_OFFSET:
+ case APR_OFFSET:
+ case IRR_OFFSET0:
+ case IRR_OFFSET1:
+ case IRR_OFFSET2:
+ case IRR_OFFSET3:
+ case IRR_OFFSET4:
+ case IRR_OFFSET5:
+ case IRR_OFFSET6:
+ case IRR_OFFSET7:
+ case ISR_OFFSET0:
+ case ISR_OFFSET1:
+ case ISR_OFFSET2:
+ case ISR_OFFSET3:
+ case ISR_OFFSET4:
+ case ISR_OFFSET5:
+ case ISR_OFFSET6:
+ case ISR_OFFSET7:
+ case TRIG_OFFSET0:
+ case TRIG_OFFSET1:
+ case TRIG_OFFSET2:
+ case TRIG_OFFSET3:
+ case TRIG_OFFSET4:
+ case TRIG_OFFSET5:
+ case TRIG_OFFSET6:
+ case TRIG_OFFSET7:
+ case PPR_OFFSET:
+ case EXT_APIC_FEATURE_OFFSET:
#if 1
- PrintError("Attempting to write to read only register %p (ignored)\n", (void *)reg_addr);
+ PrintError("Attempting to write to read only register %p (ignored)\n", (void *)reg_addr);
#else
- PrintError("Attempting to write to read only register %p (error)\n", (void *)reg_addr);
- return -1;
+ PrintError("Attempting to write to read only register %p (error)\n", (void *)reg_addr);
+ return -1;
#endif
- break;
-
- // Data registers
- case APIC_ID_OFFSET:
- apic->lapic_id.val = op_val;
- break;
- case TPR_OFFSET:
- apic->task_prio.val = op_val;
- break;
- case LDR_OFFSET:
- apic->log_dst.val = op_val;
- break;
- case DFR_OFFSET:
- apic->dst_fmt.val = op_val;
- break;
- case SPURIOUS_INT_VEC_OFFSET:
- apic->spurious_int.val = op_val;
- break;
- case ESR_OFFSET:
- apic->err_status.val = op_val;
- break;
- case TMR_LOC_VEC_TBL_OFFSET:
- apic->tmr_vec_tbl.val = op_val;
- break;
- case THERM_LOC_VEC_TBL_OFFSET:
- apic->therm_loc_vec_tbl.val = op_val;
- break;
- case PERF_CTR_LOC_VEC_TBL_OFFSET:
- apic->perf_ctr_loc_vec_tbl.val = op_val;
- break;
- case LINT0_VEC_TBL_OFFSET:
- apic->lint0_vec_tbl.val = op_val;
- break;
- case LINT1_VEC_TBL_OFFSET:
- apic->lint1_vec_tbl.val = op_val;
- break;
- case ERR_VEC_TBL_OFFSET:
- apic->err_vec_tbl.val = op_val;
- break;
- case TMR_INIT_CNT_OFFSET:
- apic->tmr_init_cnt = op_val;
- apic->tmr_cur_cnt = op_val;
- break;
- case TMR_CUR_CNT_OFFSET:
- apic->tmr_cur_cnt = op_val;
- break;
- case TMR_DIV_CFG_OFFSET:
- apic->tmr_div_cfg.val = op_val;
- break;
-
-
- // Enable mask (256 bits)
- case IER_OFFSET0:
- *(uint32_t *)(apic->int_en_reg) = op_val;
- break;
- case IER_OFFSET1:
- *(uint32_t *)(apic->int_en_reg + 4) = op_val;
- break;
- case IER_OFFSET2:
- *(uint32_t *)(apic->int_en_reg + 8) = op_val;
- break;
- case IER_OFFSET3:
- *(uint32_t *)(apic->int_en_reg + 12) = op_val;
- break;
- case IER_OFFSET4:
- *(uint32_t *)(apic->int_en_reg + 16) = op_val;
- break;
- case IER_OFFSET5:
- *(uint32_t *)(apic->int_en_reg + 20) = op_val;
- break;
- case IER_OFFSET6:
- *(uint32_t *)(apic->int_en_reg + 24) = op_val;
- break;
- case IER_OFFSET7:
- *(uint32_t *)(apic->int_en_reg + 28) = op_val;
- break;
+ break;
+
+ // Data registers
+ case APIC_ID_OFFSET:
+ apic->lapic_id.val = op_val;
+ break;
+ case TPR_OFFSET:
+ apic->task_prio.val = op_val;
+ break;
+ case LDR_OFFSET:
+ apic->log_dst.val = op_val;
+ break;
+ case DFR_OFFSET:
+ apic->dst_fmt.val = op_val;
+ break;
+ case SPURIOUS_INT_VEC_OFFSET:
+ apic->spurious_int.val = op_val;
+ break;
+ case ESR_OFFSET:
+ apic->err_status.val = op_val;
+ break;
+ case TMR_LOC_VEC_TBL_OFFSET:
+ apic->tmr_vec_tbl.val = op_val;
+ break;
+ case THERM_LOC_VEC_TBL_OFFSET:
+ apic->therm_loc_vec_tbl.val = op_val;
+ break;
+ case PERF_CTR_LOC_VEC_TBL_OFFSET:
+ apic->perf_ctr_loc_vec_tbl.val = op_val;
+ break;
+ case LINT0_VEC_TBL_OFFSET:
+ apic->lint0_vec_tbl.val = op_val;
+ break;
+ case LINT1_VEC_TBL_OFFSET:
+ apic->lint1_vec_tbl.val = op_val;
+ break;
+ case ERR_VEC_TBL_OFFSET:
+ apic->err_vec_tbl.val = op_val;
+ break;
+ case TMR_INIT_CNT_OFFSET:
+ apic->tmr_init_cnt = op_val;
+ apic->tmr_cur_cnt = op_val;
+ break;
+ case TMR_CUR_CNT_OFFSET:
+ apic->tmr_cur_cnt = op_val;
+ break;
+ case TMR_DIV_CFG_OFFSET:
+ apic->tmr_div_cfg.val = op_val;
+ break;
+
+
+ // Enable mask (256 bits)
+ case IER_OFFSET0:
+ *(uint32_t *)(apic->int_en_reg) = op_val;
+ break;
+ case IER_OFFSET1:
+ *(uint32_t *)(apic->int_en_reg + 4) = op_val;
+ break;
+ case IER_OFFSET2:
+ *(uint32_t *)(apic->int_en_reg + 8) = op_val;
+ break;
+ case IER_OFFSET3:
+ *(uint32_t *)(apic->int_en_reg + 12) = op_val;
+ break;
+ case IER_OFFSET4:
+ *(uint32_t *)(apic->int_en_reg + 16) = op_val;
+ break;
+ case IER_OFFSET5:
+ *(uint32_t *)(apic->int_en_reg + 20) = op_val;
+ break;
+ case IER_OFFSET6:
+ *(uint32_t *)(apic->int_en_reg + 24) = op_val;
+ break;
+ case IER_OFFSET7:
+ *(uint32_t *)(apic->int_en_reg + 28) = op_val;
+ break;
- // Action Registers
- case INT_CMD_LO_OFFSET:
- case INT_CMD_HI_OFFSET:
- case EOI_OFFSET:
- {
- // do eoi
- apic_do_eoi(apic);
- break;
-
+ // Action Registers
+ case INT_CMD_LO_OFFSET:
+ case INT_CMD_HI_OFFSET:
+ case EOI_OFFSET:
+ {
+ // do eoi
+ apic_do_eoi(apic);
+ break;
+ }
+ // Unhandled Registers
+ case EXT_INT_LOC_VEC_TBL_OFFSET0:
+ case EXT_INT_LOC_VEC_TBL_OFFSET1:
+ case EXT_INT_LOC_VEC_TBL_OFFSET2:
+ case EXT_INT_LOC_VEC_TBL_OFFSET3:
+ case EXT_APIC_CMD_OFFSET:
+ case SEOI_OFFSET:
+ default:
+ PrintError("Write to Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
+ return -1;
}
- // Unhandled Registers
- case EXT_INT_LOC_VEC_TBL_OFFSET0:
- case EXT_INT_LOC_VEC_TBL_OFFSET1:
- case EXT_INT_LOC_VEC_TBL_OFFSET2:
- case EXT_INT_LOC_VEC_TBL_OFFSET3:
- case EXT_APIC_CMD_OFFSET:
- case SEOI_OFFSET:
- default:
- PrintError("Write to Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
- return -1;
- }
- PrintDebug("Write finished\n");
+ PrintDebug("Write finished\n");
- return length;
+ return length;
}
/* Interrupt Controller Functions */
static int apic_intr_pending(void * private_data) {
- struct vm_device * dev = (struct vm_device *)private_data;
- struct apic_state * apic = (struct apic_state *)dev->private_data;
- int i = 0;
+ struct vm_device * dev = (struct vm_device *)private_data;
+ struct apic_state * apic = (struct apic_state *)dev->private_data;
+ int i = 0;
- // just scan the request register looking for any set bit
- // we should probably just do this with uint64 casts
- for (i = 0; i < 32; i++) {
- if (apic->int_req_reg[i] & 0xff) {
- return 1;
+ // just scan the request register looking for any set bit
+ // we should probably just do this with uint64 casts
+ for (i = 0; i < 32; i++) {
+ if (apic->int_req_reg[i] & 0xff) {
+ return 1;
+ }
}
- }
- return 0;
+ return 0;
}
static int apic_get_intr_number(void * private_data) {
- struct vm_device * dev = (struct vm_device *)private_data;
- struct apic_state * apic = (struct apic_state *)dev->private_data;
- int i = 0, j = 0;
+ struct vm_device * dev = (struct vm_device *)private_data;
+ struct apic_state * apic = (struct apic_state *)dev->private_data;
+ int i = 0, j = 0;
- // We iterate backwards to find the highest priority
- for (i = 31; i >= 0; i--) {
- uchar_t req_major = apic->int_req_reg[i];
+ // We iterate backwards to find the highest priority
+ for (i = 31; i >= 0; i--) {
+ uchar_t req_major = apic->int_req_reg[i];
- if (req_major & 0xff) {
- for (j = 7; j >= 0; j--) {
- if ((req_major >> j) == 0x1) {
- return (i * 8) + j;
+ if (req_major & 0xff) {
+ for (j = 7; j >= 0; j--) {
+ if ((req_major >> j) == 0x1) {
+ return (i * 8) + j;
+ }
+ }
}
- }
}
- }
- return -1;
+ return -1;
}
static int apic_raise_intr(void * private_data, int irq) {
- return 0;
+ return 0;
}
static int apic_lower_intr(void * private_data, int irq) {
- return 0;
+ return 0;
}
static int apic_begin_irq(void * private_data, int irq) {
- struct vm_device * dev = (struct vm_device *)private_data;
- struct apic_state * apic = (struct apic_state *)dev->private_data;
- int major_offset = (irq & ~0x00000007) >> 3;
- int minor_offset = irq & 0x00000007;
- uchar_t * req_location = apic->int_req_reg + major_offset;
- uchar_t * svc_location = apic->int_svc_reg + major_offset;
- uchar_t flag = 0x01 << minor_offset;
-
- *svc_location |= flag;
- *req_location &= ~flag;
-
- return 0;
+ struct vm_device * dev = (struct vm_device *)private_data;
+ struct apic_state * apic = (struct apic_state *)dev->private_data;
+ int major_offset = (irq & ~0x00000007) >> 3;
+ int minor_offset = irq & 0x00000007;
+ uchar_t * req_location = apic->int_req_reg + major_offset;
+ uchar_t * svc_location = apic->int_svc_reg + major_offset;
+ uchar_t flag = 0x01 << minor_offset;
+
+ *svc_location |= flag;
+ *req_location &= ~flag;
+
+ return 0;
}
int v3_apic_raise_intr(struct vm_device * apic_dev, int intr_num) {
- struct apic_state * apic = (struct apic_state *)apic_dev->private_data;
- return activate_apic_irq(apic, intr_num);
+ struct apic_state * apic = (struct apic_state *)apic_dev->private_data;
+ return activate_apic_irq(apic, intr_num);
}
/* Timer Functions */
static void apic_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
- struct vm_device * dev = (struct vm_device *)priv_data;
- struct apic_state * apic = (struct apic_state *)dev->private_data;
- // The 32 bit GCC runtime is a pile of shit
+ struct vm_device * dev = (struct vm_device *)priv_data;
+ struct apic_state * apic = (struct apic_state *)dev->private_data;
+ // The 32 bit GCC runtime is a pile of shit
#ifdef __V3_64BIT__
- uint64_t tmr_ticks = 0;
+ uint64_t tmr_ticks = 0;
#else
- uint32_t tmr_ticks = 0;
+ uint32_t tmr_ticks = 0;
#endif
- uchar_t tmr_div = *(uchar_t *)&(apic->tmr_div_cfg.val);
- uint_t shift_num = 0;
-
-
- // Check whether this is true:
- // -> If the Init count is zero then the timer is disabled
- // and doesn't just blitz interrupts to the CPU
- if ((apic->tmr_init_cnt == 0) ||
- ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
- (apic->tmr_cur_cnt == 0))) {
- //PrintDebug("APIC timer not yet initialized\n");
- return;
- }
-
-
- switch (tmr_div) {
- case APIC_TMR_DIV1:
- shift_num = 0;
- break;
- case APIC_TMR_DIV2:
- shift_num = 1;
- break;
- case APIC_TMR_DIV4:
- shift_num = 2;
- break;
- case APIC_TMR_DIV8:
- shift_num = 3;
- break;
- case APIC_TMR_DIV16:
- shift_num = 4;
- break;
- case APIC_TMR_DIV32:
- shift_num = 5;
- break;
- case APIC_TMR_DIV64:
- shift_num = 6;
- break;
- case APIC_TMR_DIV128:
- shift_num = 7;
- break;
- default:
- PrintError("Invalid Timer Divider configuration\n");
- return;
- }
-
- tmr_ticks = cpu_cycles >> shift_num;
- // PrintDebug("Timer Ticks: %p\n", (void *)tmr_ticks);
-
- if (tmr_ticks < apic->tmr_cur_cnt) {
- apic->tmr_cur_cnt -= tmr_ticks;
- } else {
- tmr_ticks -= apic->tmr_cur_cnt;
- apic->tmr_cur_cnt = 0;
-
- // raise irq
- PrintDebug("Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n",
- apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
- if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
- PrintError("Could not raise Timer interrupt\n");
+ uchar_t tmr_div = *(uchar_t *)&(apic->tmr_div_cfg.val);
+ uint_t shift_num = 0;
+
+
+ // Check whether this is true:
+ // -> If the Init count is zero then the timer is disabled
+ // and doesn't just blitz interrupts to the CPU
+ if ((apic->tmr_init_cnt == 0) ||
+ ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
+ (apic->tmr_cur_cnt == 0))) {
+ //PrintDebug("APIC timer not yet initialized\n");
+ return;
+ }
+
+
+ switch (tmr_div) {
+ case APIC_TMR_DIV1:
+ shift_num = 0;
+ break;
+ case APIC_TMR_DIV2:
+ shift_num = 1;
+ break;
+ case APIC_TMR_DIV4:
+ shift_num = 2;
+ break;
+ case APIC_TMR_DIV8:
+ shift_num = 3;
+ break;
+ case APIC_TMR_DIV16:
+ shift_num = 4;
+ break;
+ case APIC_TMR_DIV32:
+ shift_num = 5;
+ break;
+ case APIC_TMR_DIV64:
+ shift_num = 6;
+ break;
+ case APIC_TMR_DIV128:
+ shift_num = 7;
+ break;
+ default:
+ PrintError("Invalid Timer Divider configuration\n");
+ return;
}
+
+ tmr_ticks = cpu_cycles >> shift_num;
+ // PrintDebug("Timer Ticks: %p\n", (void *)tmr_ticks);
+
+ if (tmr_ticks < apic->tmr_cur_cnt) {
+ apic->tmr_cur_cnt -= tmr_ticks;
+ } else {
+ tmr_ticks -= apic->tmr_cur_cnt;
+ apic->tmr_cur_cnt = 0;
+
+ // raise irq
+ PrintDebug("Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n",
+ apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
+ if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
+ PrintError("Could not raise Timer interrupt\n");
+ }
- if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
- tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
- apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
+ if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
+ tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
+ apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
+ }
}
- }
}
static struct intr_ctrl_ops intr_ops = {
- .intr_pending = apic_intr_pending,
- .get_intr_number = apic_get_intr_number,
- .raise_intr = apic_raise_intr,
- .begin_irq = apic_begin_irq,
- .lower_intr = apic_lower_intr,
+ .intr_pending = apic_intr_pending,
+ .get_intr_number = apic_get_intr_number,
+ .raise_intr = apic_raise_intr,
+ .begin_irq = apic_begin_irq,
+ .lower_intr = apic_lower_intr,
};
static struct vm_timer_ops timer_ops = {
- .update_time = apic_update_time,
+ .update_time = apic_update_time,
};
static int apic_init(struct vm_device * dev) {
- struct guest_info * info = dev->vm;
- struct apic_state * apic = (struct apic_state *)(dev->private_data);
+ struct guest_info * info = dev->vm;
+ struct apic_state * apic = (struct apic_state *)(dev->private_data);
- v3_register_intr_controller(dev->vm, &intr_ops, dev);
- v3_add_timer(dev->vm, &timer_ops, dev);
+ v3_register_intr_controller(dev->vm, &intr_ops, dev);
+ v3_add_timer(dev->vm, &timer_ops, dev);
- init_apic_state(apic);
+ init_apic_state(apic);
- v3_hook_msr(info, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
+ v3_hook_msr(info, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
- v3_hook_full_mem(info, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev);
+ v3_hook_full_mem(info, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev);
- return 0;
+ return 0;
}
static int apic_deinit(struct vm_device * dev) {
- struct guest_info * info = dev->vm;
+ struct guest_info * info = dev->vm;
- v3_unhook_msr(info, BASE_ADDR_MSR);
+ v3_unhook_msr(info, BASE_ADDR_MSR);
- return 0;
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = apic_init,
- .deinit = apic_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = apic_init,
+ .deinit = apic_deinit,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_apic() {
- PrintDebug("Creating APIC\n");
+ PrintDebug("Creating APIC\n");
- struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state));
+ struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state));
- struct vm_device * device = v3_create_device("APIC", &dev_ops, apic);
+ struct vm_device * device = v3_create_device("APIC", &dev_ops, apic);
- return device;
+ return device;
}
struct debug_state {
- char debug_buf[BUF_SIZE];
- uint_t debug_offset;
+ char debug_buf[BUF_SIZE];
+ uint_t debug_offset;
- char info_buf[BUF_SIZE];
- uint_t info_offset;
+ char info_buf[BUF_SIZE];
+ uint_t info_offset;
};
static int handle_info_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct debug_state * state = (struct debug_state *)dev->private_data;
+ struct debug_state * state = (struct debug_state *)dev->private_data;
- state->info_buf[state->info_offset++] = *(char*)src;
+ state->info_buf[state->info_offset++] = *(char*)src;
- if ((*(char*)src == 0xa) || (state->info_offset == (BUF_SIZE - 1))) {
- PrintDebug("BOCHSINFO>%s", state->info_buf);
- memset(state->info_buf, 0, BUF_SIZE);
- state->info_offset = 0;
- }
+ if ((*(char*)src == 0xa) || (state->info_offset == (BUF_SIZE - 1))) {
+ PrintDebug("BOCHSINFO>%s", state->info_buf);
+ memset(state->info_buf, 0, BUF_SIZE);
+ state->info_offset = 0;
+ }
- return length;
+ return length;
}
static int handle_debug_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct debug_state * state = (struct debug_state *)dev->private_data;
+ struct debug_state * state = (struct debug_state *)dev->private_data;
- state->debug_buf[state->debug_offset++] = *(char*)src;
+ state->debug_buf[state->debug_offset++] = *(char*)src;
- if ((*(char*)src == 0xa) || (state->debug_offset == (BUF_SIZE - 1))) {
- PrintDebug("BOCHSDEBUG>%s", state->debug_buf);
- memset(state->debug_buf, 0, BUF_SIZE);
- state->debug_offset = 0;
- }
+ if ((*(char*)src == 0xa) || (state->debug_offset == (BUF_SIZE - 1))) {
+ PrintDebug("BOCHSDEBUG>%s", state->debug_buf);
+ memset(state->debug_buf, 0, BUF_SIZE);
+ state->debug_offset = 0;
+ }
- return length;
+ return length;
}
static int handle_gen_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- switch (length) {
- case 1:
- PrintDebug(">0x%.2x\n", *(uchar_t*)src);
- break;
- case 2:
- PrintDebug(">0x%.4x\n", *(ushort_t*)src);
- break;
- case 4:
- PrintDebug(">0x%.8x\n", *(uint_t*)src);
- break;
- default:
- PrintError("Invalid length in handle_gen_write\n");
- return -1;
- break;
- }
-
- return length;
+ switch (length) {
+ case 1:
+ PrintDebug(">0x%.2x\n", *(uchar_t*)src);
+ break;
+ case 2:
+ PrintDebug(">0x%.4x\n", *(ushort_t*)src);
+ break;
+ case 4:
+ PrintDebug(">0x%.8x\n", *(uint_t*)src);
+ break;
+ default:
+ PrintError("Invalid length in handle_gen_write\n");
+ return -1;
+ break;
+ }
+
+ return length;
}
static int debug_init(struct vm_device * dev) {
- struct debug_state * state = (struct debug_state *)dev->private_data;
+ struct debug_state * state = (struct debug_state *)dev->private_data;
- state->debug_offset = 0;
- state->info_offset = 0;
- memset(state->debug_buf, 0, BUF_SIZE);
- memset(state->info_buf, 0, BUF_SIZE);
+ state->debug_offset = 0;
+ state->info_offset = 0;
+ memset(state->debug_buf, 0, BUF_SIZE);
+ memset(state->info_buf, 0, BUF_SIZE);
- v3_dev_hook_io(dev, BOCHS_PORT1, NULL, &handle_gen_write);
- v3_dev_hook_io(dev, BOCHS_PORT2, NULL, &handle_gen_write);
- v3_dev_hook_io(dev, BOCHS_INFO_PORT, NULL, &handle_info_write);
- v3_dev_hook_io(dev, BOCHS_DEBUG_PORT, NULL, &handle_debug_write);
+ v3_dev_hook_io(dev, BOCHS_PORT1, NULL, &handle_gen_write);
+ v3_dev_hook_io(dev, BOCHS_PORT2, NULL, &handle_gen_write);
+ v3_dev_hook_io(dev, BOCHS_INFO_PORT, NULL, &handle_info_write);
+ v3_dev_hook_io(dev, BOCHS_DEBUG_PORT, NULL, &handle_debug_write);
- return 0;
+ return 0;
}
static int debug_deinit(struct vm_device * dev) {
- v3_dev_unhook_io(dev, BOCHS_PORT1);
- v3_dev_unhook_io(dev, BOCHS_PORT2);
- v3_dev_unhook_io(dev, BOCHS_INFO_PORT);
- v3_dev_unhook_io(dev, BOCHS_DEBUG_PORT);
+ v3_dev_unhook_io(dev, BOCHS_PORT1);
+ v3_dev_unhook_io(dev, BOCHS_PORT2);
+ v3_dev_unhook_io(dev, BOCHS_INFO_PORT);
+ v3_dev_unhook_io(dev, BOCHS_DEBUG_PORT);
- return 0;
+ return 0;
};
static struct vm_device_ops dev_ops = {
- .init = debug_init,
- .deinit = debug_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = debug_init,
+ .deinit = debug_deinit,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_bochs_debug() {
- struct debug_state * state = NULL;
+ struct debug_state * state = NULL;
- state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
+ state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
- V3_ASSERT(state != NULL);
+ V3_ASSERT(state != NULL);
- PrintDebug("Creating Bochs Debug Device\n");
- struct vm_device * device = v3_create_device("BOCHS Debug", &dev_ops, state);
+ PrintDebug("Creating Bochs Debug Device\n");
+ struct vm_device * device = v3_create_device("BOCHS Debug", &dev_ops, state);
- return device;
+ return device;
}
struct cdrom_state {
- uchar_t * image_addr; //memory address
- ulong_t capacity_in_bytes;
- ulong_t head; //current position
+ uchar_t * image_addr; //memory address
+ ulong_t capacity_in_bytes;
+ ulong_t head; //current position
- struct vm_device * ide_dev;
+ struct vm_device * ide_dev;
- uchar_t lba;
+ uchar_t lba;
};
*/
static rd_bool cdrom_insert(void * private_data) {
- PrintDebug("[cdrom_insert]\n");
- return 1;
+ PrintDebug("[cdrom_insert]\n");
+ return 1;
}
/*
* Logically eject the CD.
*/
static void cdrom_eject(void * private_data) {
- PrintDebug("[cdrom_eject]\n");
- return;
+ PrintDebug("[cdrom_eject]\n");
+ return;
}
/*
*/
static rd_bool cdrom_read_toc(void * private_data, uint8_t* buf, int* length, rd_bool msf, int start_track)
{
- *length = 4;
- PrintDebug("[cdrom_read_toc]\n");
- return 1;
+ *length = 4;
+ PrintDebug("[cdrom_read_toc]\n");
+ return 1;
}
/*
* Return CD-ROM capacity (in 2048 byte frames)
*/
static uint32_t cdrom_capacity(void * private_data) {
- struct cdrom_state * cdrom = (struct cdrom_state *)private_data;
-
- PrintDebug("[cdrom_capacity] s_ramdiskSize = %d\n", cdrom->capacity_in_bytes);
-
- if (cdrom->lba) {
- if (cdrom->capacity_in_bytes % 2048) {
- PrintDebug("\t\t capacity in LBA is %d\n", (cdrom->capacity_in_bytes / 2048) + 1);
- return (cdrom->capacity_in_bytes / 2048) + 1;
+ struct cdrom_state * cdrom = (struct cdrom_state *)private_data;
+
+ PrintDebug("[cdrom_capacity] s_ramdiskSize = %d\n", cdrom->capacity_in_bytes);
+
+ if (cdrom->lba) {
+ if (cdrom->capacity_in_bytes % 2048) {
+ PrintDebug("\t\t capacity in LBA is %d\n", (cdrom->capacity_in_bytes / 2048) + 1);
+ return (cdrom->capacity_in_bytes / 2048) + 1;
+ } else {
+ PrintDebug("\t\t capacity in LBA is %d\n", cdrom->capacity_in_bytes / 2048);
+ return cdrom->capacity_in_bytes / 2048;
+ }
} else {
- PrintDebug("\t\t capacity in LBA is %d\n", cdrom->capacity_in_bytes / 2048);
- return cdrom->capacity_in_bytes / 2048;
+ PrintError("Unsupported CDROM mode in capacity query\n");
+ //FIXME CHS mode
+ return 0;
}
- } else {
- PrintError("Unsupported CDROM mode in capacity query\n");
- //FIXME CHS mode
- return 0;
- }
}
/*
* Read a single block from the CD
*/
static void cdrom_read_block(void * private_data, uint8_t * buf, int lba)/* __attribute__(regparm(2)); */ {
- struct cdrom_state * cdrom = (struct cdrom_state *)private_data;
+ struct cdrom_state * cdrom = (struct cdrom_state *)private_data;
- V3_ASSERT(lba != 0);
+ V3_ASSERT(lba != 0);
- PrintDebug("[cdrom_read_block] lba = %d (cdrom_image_start=%x)\n", lba, cdrom->image_addr);
- memcpy(buf, (uchar_t *)(cdrom->image_addr + lba * 2048), 2048);
- //PrintDebug("Returning from read block\n");
- return;
+ PrintDebug("[cdrom_read_block] lba = %d (cdrom_image_start=%x)\n", lba, cdrom->image_addr);
+ memcpy(buf, (uchar_t *)(cdrom->image_addr + lba * 2048), 2048);
+ //PrintDebug("Returning from read block\n");
+ return;
}
static void set_LBA(void * private_data, uchar_t lba) {
- struct cdrom_state * cdrom = (struct cdrom_state *)private_data;
- cdrom->lba = lba;
+ struct cdrom_state * cdrom = (struct cdrom_state *)private_data;
+ cdrom->lba = lba;
}
* Start (spin up) the CD.
*/
static int cdrom_start(void * private_data) {
- PrintDebug("[cdrom_start]\n");
- return 1;
+ PrintDebug("[cdrom_start]\n");
+ return 1;
}
static struct cdrom_ops cd_ops = {
- .insert_cdrom = cdrom_insert,
- .eject_cdrom = cdrom_eject,
- .read_toc = cdrom_read_toc,
- .capacity = cdrom_capacity,
- .read_block = cdrom_read_block,
- .start_cdrom = cdrom_start,
- .set_LBA = set_LBA,
+ .insert_cdrom = cdrom_insert,
+ .eject_cdrom = cdrom_eject,
+ .read_toc = cdrom_read_toc,
+ .capacity = cdrom_capacity,
+ .read_block = cdrom_read_block,
+ .start_cdrom = cdrom_start,
+ .set_LBA = set_LBA,
};
static int cdrom_device_init(struct vm_device * dev) {
- struct cdrom_state * cdrom = (struct cdrom_state *)dev->private_data;
- PrintDebug("[cdrom_init]\n");
- PrintDebug("CDIMAGE located at: %x\n", cdrom->image_addr);
+ struct cdrom_state * cdrom = (struct cdrom_state *)dev->private_data;
+ PrintDebug("[cdrom_init]\n");
+ PrintDebug("CDIMAGE located at: %x\n", cdrom->image_addr);
- //FIXME:lba
- cdrom->lba = 1;
+ //FIXME:lba
+ cdrom->lba = 1;
- v3_ramdisk_register_cdrom(cdrom->ide_dev, 1, 0, &cd_ops, cdrom);
+ v3_ramdisk_register_cdrom(cdrom->ide_dev, 1, 0, &cd_ops, cdrom);
- return 0;
+ return 0;
}
static int cdrom_device_deinit(struct vm_device * dev) {
- return 0;
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = cdrom_device_init,
- .deinit = cdrom_device_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = cdrom_device_init,
+ .deinit = cdrom_device_deinit,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_cdrom(struct vm_device * ramdisk_dev, void * ramdisk, uint_t ramdisk_size){
- struct cdrom_state * cd = (struct cdrom_state *)V3_Malloc(sizeof(struct cdrom_state));
- V3_ASSERT(cd != NULL);
+ struct cdrom_state * cd = (struct cdrom_state *)V3_Malloc(sizeof(struct cdrom_state));
+ V3_ASSERT(cd != NULL);
- memset(cd, 0, sizeof(struct cdrom_state));
+ memset(cd, 0, sizeof(struct cdrom_state));
- cd->image_addr = (uchar_t *)V3_VAddr(ramdisk);
- cd->capacity_in_bytes = ramdisk_size;
- cd->ide_dev = ramdisk_dev;
+ cd->image_addr = (uchar_t *)V3_VAddr(ramdisk);
+ cd->capacity_in_bytes = ramdisk_size;
+ cd->ide_dev = ramdisk_dev;
- PrintDebug("Creating RamDISK CDROM\n");
+ PrintDebug("Creating RamDISK CDROM\n");
- struct vm_device * cd_dev = v3_create_device("Ram Based CD", &dev_ops, cd);
+ struct vm_device * cd_dev = v3_create_device("Ram Based CD", &dev_ops, cd);
- return cd_dev;
+ return cd_dev;
}
-
-
struct generic_internal {
- struct list_head port_list;
- uint_t num_port_ranges;
- struct list_head mem_list;
- uint_t num_mem_ranges;
- struct list_head irq_list;
- uint_t num_irq_ranges;
+ struct list_head port_list;
+ uint_t num_port_ranges;
+ struct list_head mem_list;
+ uint_t num_mem_ranges;
+ struct list_head irq_list;
+ uint_t num_irq_ranges;
};
struct port_range {
- uint_t start;
- uint_t end;
- uint_t type;
- struct list_head range_link;
+ uint_t start;
+ uint_t end;
+ uint_t type;
+ struct list_head range_link;
};
struct mem_range {
- void * start;
- void * end;
- uint_t type;
- struct list_head range_link;
+ void * start;
+ void * end;
+ uint_t type;
+ struct list_head range_link;
};
struct irq_range {
- uint_t start;
- uint_t end;
- uint_t type;
- struct list_head range_link;
+ uint_t start;
+ uint_t end;
+ uint_t type;
+ struct list_head range_link;
};
static int generic_reset_device(struct vm_device * dev) {
- PrintDebug("generic: reset device\n");
- return 0;
+ PrintDebug("generic: reset device\n");
+ return 0;
}
static int generic_start_device(struct vm_device * dev) {
- PrintDebug("generic: start device\n");
- return 0;
+ PrintDebug("generic: start device\n");
+ return 0;
}
static int generic_stop_device(struct vm_device * dev) {
- PrintDebug("generic: stop device\n");
- return 0;
+ PrintDebug("generic: stop device\n");
+ return 0;
}
void * src,
uint_t length,
struct vm_device * dev) {
- uint_t i;
+ uint_t i;
- PrintDebug("generic: writing 0x");
+ PrintDebug("generic: writing 0x");
- for (i = 0; i < length; i++) {
- PrintDebug("%x", ((uchar_t*)src)[i]);
- }
-
- PrintDebug(" to port 0x%x ... ", port);
-
-
- switch (length) {
- case 1:
- v3_outb(port,((uchar_t*)src)[0]);
- break;
- case 2:
- v3_outw(port,((ushort_t*)src)[0]);
- break;
- case 4:
- v3_outdw(port,((uint_t*)src)[0]);
- break;
- default:
for (i = 0; i < length; i++) {
- v3_outb(port, ((uchar_t*)src)[i]);
+ PrintDebug("%x", ((uchar_t*)src)[i]);
}
- } //switch length
+
+ PrintDebug(" to port 0x%x ... ", port);
- PrintDebug(" done\n");
+ switch (length) {
+ case 1:
+ v3_outb(port,((uchar_t*)src)[0]);
+ break;
+ case 2:
+ v3_outw(port,((ushort_t*)src)[0]);
+ break;
+ case 4:
+ v3_outdw(port,((uint_t*)src)[0]);
+ break;
+ default:
+ for (i = 0; i < length; i++) {
+ v3_outb(port, ((uchar_t*)src)[i]);
+ }
+ } //switch length
+
+
+ PrintDebug(" done\n");
- return length;
+ return length;
}
static int generic_read_port_passthrough(ushort_t port,
void * src,
uint_t length,
struct vm_device * dev) {
- uint_t i;
+ uint_t i;
- PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
+ PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
switch (length) {
- case 1:
- ((uchar_t*)src)[0] = v3_inb(port);
- break;
- case 2:
- ((ushort_t*)src)[0] = v3_inw(port);
- break;
- case 4:
- ((uint_t*)src)[0] = v3_indw(port);
- break;
- default:
- for (i = 0; i < length; i++) {
- ((uchar_t*)src)[i] = v3_inb(port);
- }
+ case 1:
+ ((uchar_t*)src)[0] = v3_inb(port);
+ break;
+ case 2:
+ ((ushort_t*)src)[0] = v3_inw(port);
+ break;
+ case 4:
+ ((uint_t*)src)[0] = v3_indw(port);
+ break;
+ default:
+ for (i = 0; i < length; i++) {
+ ((uchar_t*)src)[i] = v3_inb(port);
+ }
}//switch length
- PrintDebug(" done ... read 0x");
+ PrintDebug(" done ... read 0x");
- for (i = 0; i < length; i++) {
- PrintDebug("%x", ((uchar_t*)src)[i]);
- }
+ for (i = 0; i < length; i++) {
+ PrintDebug("%x", ((uchar_t*)src)[i]);
+ }
- PrintDebug("\n");
+ PrintDebug("\n");
- return length;
+ return length;
}
static int generic_write_port_ignore(ushort_t port,
void * src,
uint_t length,
struct vm_device * dev) {
- uint_t i;
+ uint_t i;
- PrintDebug("generic: writing 0x");
+ PrintDebug("generic: writing 0x");
- for (i = 0; i < length; i++) {
- PrintDebug("%x", ((uchar_t*)src)[i]);
- }
+ for (i = 0; i < length; i++) {
+ PrintDebug("%x", ((uchar_t*)src)[i]);
+ }
- PrintDebug(" to port 0x%x ... ignored\n", port);
+ PrintDebug(" to port 0x%x ... ignored\n", port);
- return length;
+ return length;
}
static int generic_read_port_ignore(ushort_t port,
uint_t length,
struct vm_device * dev) {
- PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
+ PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
- memset((char*)src, 0, length);
- PrintDebug(" ignored (return zeroed buffer)\n");
+ memset((char*)src, 0, length);
+ PrintDebug(" ignored (return zeroed buffer)\n");
- return length;
+ return length;
}
static int generic_interrupt(uint_t irq, struct vm_device * dev) {
- PrintDebug("generic: interrupt 0x%x - injecting into VM\n", irq);
+ PrintDebug("generic: interrupt 0x%x - injecting into VM\n", irq);
- v3_raise_irq(dev->vm, irq);
+ v3_raise_irq(dev->vm, irq);
- return 0;
+ return 0;
}
static int generic_init_device(struct vm_device * dev) {
- struct generic_internal * state = (struct generic_internal *)(dev->private_data);
+ struct generic_internal * state = (struct generic_internal *)(dev->private_data);
- PrintDebug("generic: init_device\n");
- generic_reset_device(dev);
+ PrintDebug("generic: init_device\n");
+ generic_reset_device(dev);
- if (PORT_HOOKS) { // This is a runtime conditional on a #define
- struct port_range * tmp = NULL;
+ if (PORT_HOOKS) { // This is a runtime conditional on a #define
+ struct port_range * tmp = NULL;
- list_for_each_entry(tmp, &(state->port_list), range_link) {
- uint_t i = 0;
+ list_for_each_entry(tmp, &(state->port_list), range_link) {
+ uint_t i = 0;
- PrintDebug("generic: hooking ports 0x%x to 0x%x as %x\n",
- tmp->start, tmp->end,
- (tmp->type == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
+ PrintDebug("generic: hooking ports 0x%x to 0x%x as %x\n",
+ tmp->start, tmp->end,
+ (tmp->type == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
- for (i = tmp->start; i <= tmp->end; i++) {
- if (tmp->type == GENERIC_PRINT_AND_PASSTHROUGH) {
+ for (i = tmp->start; i <= tmp->end; i++) {
+ if (tmp->type == GENERIC_PRINT_AND_PASSTHROUGH) {
- if (v3_dev_hook_io(dev, i, &generic_read_port_passthrough, &generic_write_port_passthrough)) {
- PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", i);
- }
+ if (v3_dev_hook_io(dev, i, &generic_read_port_passthrough, &generic_write_port_passthrough)) {
+ PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", i);
+ }
- } else if (tmp->type == GENERIC_PRINT_AND_IGNORE) {
+ } else if (tmp->type == GENERIC_PRINT_AND_IGNORE) {
- if (v3_dev_hook_io(dev, i, &generic_read_port_ignore, &generic_write_port_ignore)) {
- PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", i);
- }
- }
- }
+ if (v3_dev_hook_io(dev, i, &generic_read_port_ignore, &generic_write_port_ignore)) {
+ PrintDebug("generic: can't hook port 0x%x (already hooked?)\n", i);
+ }
+ }
+ }
+ }
+ } else {
+ PrintDebug("generic: hooking ports not supported\n");
}
- } else {
- PrintDebug("generic: hooking ports not supported\n");
- }
- if (MEM_HOOKS) { // This is a runtime conditional on a #define
- struct mem_range * tmp;
+ if (MEM_HOOKS) { // This is a runtime conditional on a #define
+ struct mem_range * tmp;
- list_for_each_entry(tmp, &(state->mem_list), range_link) {
+ list_for_each_entry(tmp, &(state->mem_list), range_link) {
- PrintDebug("generic: hooking addresses 0x%x to 0x%x\n",
- tmp->start, tmp->end);
+ PrintDebug("generic: hooking addresses 0x%x to 0x%x\n",
+ tmp->start, tmp->end);
- if (v3_dev_hook_mem(dev, tmp->start, tmp->end)) {
- PrintDebug("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
- tmp->start, tmp->end);
- }
+ if (v3_dev_hook_mem(dev, tmp->start, tmp->end)) {
+ PrintDebug("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
+ tmp->start, tmp->end);
+ }
+ }
+ } else {
+ PrintDebug("generic: hooking addresses not supported\n");
}
- } else {
- PrintDebug("generic: hooking addresses not supported\n");
- }
- if (IRQ_HOOKS) { // This is a runtime conditional on a #define
- struct irq_range * tmp;
+ if (IRQ_HOOKS) { // This is a runtime conditional on a #define
+ struct irq_range * tmp;
- list_for_each_entry(tmp, &(state->irq_list), range_link) {
- uint_t i;
+ list_for_each_entry(tmp, &(state->irq_list), range_link) {
+ uint_t i;
- PrintDebug("generic: hooking irqs 0x%x to 0x%x\n",
- tmp->start, tmp->end);
+ PrintDebug("generic: hooking irqs 0x%x to 0x%x\n",
+ tmp->start, tmp->end);
- for (i = tmp->start; i <= tmp->end; i++) {
- if (v3_dev_hook_irq(dev, i, &generic_interrupt)) {
- PrintDebug("generic: can't hook irq 0x%x (already hooked?)\n", i);
- }
- }
+ for (i = tmp->start; i <= tmp->end; i++) {
+ if (v3_dev_hook_irq(dev, i, &generic_interrupt)) {
+ PrintDebug("generic: can't hook irq 0x%x (already hooked?)\n", i);
+ }
+ }
+ }
+ } else {
+ PrintDebug("generic: hooking irqs not supported\n");
}
- } else {
- PrintDebug("generic: hooking irqs not supported\n");
- }
- return 0;
+ return 0;
}
static int generic_deinit_device(struct vm_device * dev) {
- struct generic_internal * state = (struct generic_internal *)(dev->private_data);
+ struct generic_internal * state = (struct generic_internal *)(dev->private_data);
- PrintDebug("generic: deinit_device\n");
+ PrintDebug("generic: deinit_device\n");
- if (IRQ_HOOKS) { // This is a runtime conditional on a #define
- struct irq_range * tmp;
- struct irq_range * cur;
+ if (IRQ_HOOKS) { // This is a runtime conditional on a #define
+ struct irq_range * tmp;
+ struct irq_range * cur;
- list_for_each_entry_safe(cur, tmp, &(state->irq_list), range_link) {
- uint_t i;
+ list_for_each_entry_safe(cur, tmp, &(state->irq_list), range_link) {
+ uint_t i;
- PrintDebug("generic: unhooking irqs 0x%x to 0x%x\n",
- cur->start, cur->end);
+ PrintDebug("generic: unhooking irqs 0x%x to 0x%x\n",
+ cur->start, cur->end);
- for (i = cur->start; i <= cur->end; i++) {
- if (v3_dev_unhook_irq(dev, i)) {
- PrintDebug("generic: can't unhook irq 0x%x (already unhooked?)\n", i);
- }
- }
+ for (i = cur->start; i <= cur->end; i++) {
+ if (v3_dev_unhook_irq(dev, i)) {
+ PrintDebug("generic: can't unhook irq 0x%x (already unhooked?)\n", i);
+ }
+ }
- list_del(&(cur->range_link));
- state->num_irq_ranges--;
- V3_Free(cur);
+ list_del(&(cur->range_link));
+ state->num_irq_ranges--;
+ V3_Free(cur);
+ }
+ } else {
+ PrintDebug("generic: unhooking irqs not supported\n");
}
- } else {
- PrintDebug("generic: unhooking irqs not supported\n");
- }
- if (MEM_HOOKS) {
- struct mem_range * tmp;
- struct mem_range * cur;
+ if (MEM_HOOKS) {
+ struct mem_range * tmp;
+ struct mem_range * cur;
- list_for_each_entry_safe(cur, tmp, &(state->mem_list), range_link) {
+ list_for_each_entry_safe(cur, tmp, &(state->mem_list), range_link) {
- PrintDebug("generic: unhooking addresses 0x%x to 0x%x\n",
- cur->start, cur->end);
+ PrintDebug("generic: unhooking addresses 0x%x to 0x%x\n",
+ cur->start, cur->end);
- if (v3_dev_unhook_mem(dev, cur->start, cur->end)) {
- PrintDebug("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
- cur->start, cur->end);
- }
+ if (v3_dev_unhook_mem(dev, cur->start, cur->end)) {
+ PrintDebug("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
+ cur->start, cur->end);
+ }
- list_del(&(cur->range_link));
- state->num_mem_ranges--;
- V3_Free(cur);
+ list_del(&(cur->range_link));
+ state->num_mem_ranges--;
+ V3_Free(cur);
+ }
+ } else {
+ PrintDebug("generic: unhooking addresses not supported\n");
}
- } else {
- PrintDebug("generic: unhooking addresses not supported\n");
- }
- if (PORT_HOOKS) {
- struct port_range * tmp;
- struct port_range * cur;
+ if (PORT_HOOKS) {
+ struct port_range * tmp;
+ struct port_range * cur;
- list_for_each_entry_safe(cur, tmp, &(state->port_list), range_link) {
- uint_t i;
+ list_for_each_entry_safe(cur, tmp, &(state->port_list), range_link) {
+ uint_t i;
- PrintDebug("generic: unhooking ports 0x%x to 0x%x\n",
- cur->start, cur->end);
+ PrintDebug("generic: unhooking ports 0x%x to 0x%x\n",
+ cur->start, cur->end);
- for (i = cur->start; i <= cur->end; i++) {
- if (v3_dev_unhook_io(dev, i)) {
- PrintDebug("generic: can't unhook port 0x%x (already unhooked?)\n", i);
+ for (i = cur->start; i <= cur->end; i++) {
+ if (v3_dev_unhook_io(dev, i)) {
+ PrintDebug("generic: can't unhook port 0x%x (already unhooked?)\n", i);
+ }
+ }
+
+ list_del(&(cur->range_link));
+ state->num_port_ranges--;
+ V3_Free(cur);
}
- }
-
- list_del(&(cur->range_link));
- state->num_port_ranges--;
- V3_Free(cur);
+ } else {
+ PrintDebug("generic: unhooking ports not supported\n");
}
- } else {
- PrintDebug("generic: unhooking ports not supported\n");
- }
- generic_reset_device(dev);
- return 0;
+ generic_reset_device(dev);
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = generic_init_device,
- .deinit = generic_deinit_device,
- .reset = generic_reset_device,
- .start = generic_start_device,
- .stop = generic_stop_device,
+ .init = generic_init_device,
+ .deinit = generic_deinit_device,
+ .reset = generic_reset_device,
+ .start = generic_start_device,
+ .stop = generic_stop_device,
};
int v3_generic_add_port_range(struct vm_device * dev, uint_t start, uint_t end, uint_t type) {
- if (PORT_HOOKS) {
- struct generic_internal * state = (struct generic_internal *)(dev->private_data);
+ if (PORT_HOOKS) {
+ struct generic_internal * state = (struct generic_internal *)(dev->private_data);
- struct port_range * range = (struct port_range *)V3_Malloc(sizeof(struct port_range));
- range->start = start;
- range->end = end;
- range->type = type;
+ struct port_range * range = (struct port_range *)V3_Malloc(sizeof(struct port_range));
+ range->start = start;
+ range->end = end;
+ range->type = type;
- PrintDebug("generic: Adding Port Range: 0x%x to 0x%x as %x\n",
- range->start, range->end,
- (range->type == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
+ PrintDebug("generic: Adding Port Range: 0x%x to 0x%x as %x\n",
+ range->start, range->end,
+ (range->type == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
- list_add(&(range->range_link), &(state->port_list));
- state->num_port_ranges++;
- } else {
- PrintDebug("generic: hooking IO ports not supported\n");
- return -1;
- }
-
- return 0;
+ list_add(&(range->range_link), &(state->port_list));
+ state->num_port_ranges++;
+ } else {
+ PrintDebug("generic: hooking IO ports not supported\n");
+ return -1;
+ }
+
+ return 0;
}
int v3_generic_add_mem_range(struct vm_device * dev, void * start, void * end, uint_t type) {
- if (MEM_HOOKS) {
- struct generic_internal * state = (struct generic_internal *)(dev->private_data);
+ if (MEM_HOOKS) {
+ struct generic_internal * state = (struct generic_internal *)(dev->private_data);
- struct mem_range * range = (struct mem_range *)V3_Malloc(sizeof(struct mem_range));
- range->start = start;
- range->end = end;
- range->type = type;
+ struct mem_range * range = (struct mem_range *)V3_Malloc(sizeof(struct mem_range));
+ range->start = start;
+ range->end = end;
+ range->type = type;
- list_add(&(range->range_link), &(state->port_list));
- state->num_mem_ranges++;
- } else {
- PrintDebug("generic: hooking memory not supported\n");
- return -1;
- }
-
- return 0;
+ list_add(&(range->range_link), &(state->port_list));
+ state->num_mem_ranges++;
+ } else {
+ PrintDebug("generic: hooking memory not supported\n");
+ return -1;
+ }
+
+ return 0;
}
int v3_generic_add_irq_range(struct vm_device * dev, uint_t start, uint_t end, uint_t type) {
- if (IRQ_HOOKS) {
- struct generic_internal * state = (struct generic_internal *)(dev->private_data);
+ if (IRQ_HOOKS) {
+ struct generic_internal * state = (struct generic_internal *)(dev->private_data);
- struct irq_range * range = (struct irq_range *)V3_Malloc(sizeof(struct irq_range));
- range->start = start;
- range->end = end;
- range->type = type;
+ struct irq_range * range = (struct irq_range *)V3_Malloc(sizeof(struct irq_range));
+ range->start = start;
+ range->end = end;
+ range->type = type;
- list_add(&(range->range_link), &(state->port_list));
- state->num_irq_ranges++;
- } else {
- PrintDebug("generic: hooking IRQs not supported\n");
- return -1;
- }
-
- return 0;
+ list_add(&(range->range_link), &(state->port_list));
+ state->num_irq_ranges++;
+ } else {
+ PrintDebug("generic: hooking IRQs not supported\n");
+ return -1;
+ }
+
+ return 0;
}
struct vm_device * v3_create_generic() {
- struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
+ struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
- generic_state->num_port_ranges = 0;
- generic_state->num_mem_ranges = 0;
- generic_state->num_irq_ranges = 0;
+ generic_state->num_port_ranges = 0;
+ generic_state->num_mem_ranges = 0;
+ generic_state->num_irq_ranges = 0;
- INIT_LIST_HEAD(&(generic_state->port_list));
- INIT_LIST_HEAD(&(generic_state->mem_list));
- INIT_LIST_HEAD(&(generic_state->irq_list));
+ INIT_LIST_HEAD(&(generic_state->port_list));
+ INIT_LIST_HEAD(&(generic_state->mem_list));
+ INIT_LIST_HEAD(&(generic_state->irq_list));
- struct vm_device * device = v3_create_device("GENERIC", &dev_ops, generic_state);
+ struct vm_device * device = v3_create_device("GENERIC", &dev_ops, generic_state);
- return device;
+ return device;
}
#include <devices/apic.h>
/*
-#ifndef DEBUG_IO_APIC
-#undef PrintDebug
-#define PrintDebug(fmt, args...)
-#endif
+ #ifndef DEBUG_IO_APIC
+ #undef PrintDebug
+ #define PrintDebug(fmt, args...)
+ #endif
*/
#define REDIR_LO_MASK ~0x00005000
struct ioapic_reg_sel {
- union {
- uint32_t val;
- struct {
- uint_t reg_addr : 8;
- uint_t rsvd : 24;
+ union {
+ uint32_t val;
+ struct {
+ uint_t reg_addr : 8;
+ uint_t rsvd : 24;
+ } __attribute__((packed));
} __attribute__((packed));
- } __attribute__((packed));
} __attribute__((packed));
struct ioapic_id_reg {
- union {
- uint32_t val;
- struct {
- uint_t rsvd1 : 24;
- uint_t id : 4;
- uint_t rsvd2 : 4;
+ union {
+ uint32_t val;
+ struct {
+ uint_t rsvd1 : 24;
+ uint_t id : 4;
+ uint_t rsvd2 : 4;
+ } __attribute__((packed));
} __attribute__((packed));
- } __attribute__((packed));
} __attribute__((packed));
struct ioapic_ver_reg {
- union {
- uint32_t val;
- struct {
- uint_t version : 8;
- uint_t rsvd1 : 8;
- uint_t max_redir : 8;
- uint_t rsvd2 : 8;
+ union {
+ uint32_t val;
+ struct {
+ uint_t version : 8;
+ uint_t rsvd1 : 8;
+ uint_t max_redir : 8;
+ uint_t rsvd2 : 8;
+ } __attribute__((packed));
} __attribute__((packed));
- } __attribute__((packed));
} __attribute__((packed));
struct ioapic_arb_reg {
- union {
- uint32_t val;
- struct {
- uint_t rsvd1 : 24;
- uint_t max_redir : 4;
- uint_t rsvd2 : 4;
+ union {
+ uint32_t val;
+ struct {
+ uint_t rsvd1 : 24;
+ uint_t max_redir : 4;
+ uint_t rsvd2 : 4;
+ } __attribute__((packed));
} __attribute__((packed));
- } __attribute__((packed));
} __attribute__((packed));
struct redir_tbl_entry {
- union {
- uint64_t val;
- struct {
- uint32_t lo;
- uint32_t hi;
- } __attribute__((packed));
- struct {
- uint_t vec : 8;
+ union {
+ uint64_t val;
+ struct {
+ uint32_t lo;
+ uint32_t hi;
+ } __attribute__((packed));
+ struct {
+ uint_t vec : 8;
#define FIXED 0x0
#define LOWEST_PRIOR 0x1
#define NMI 0x4
#define INIT 0x5
#define EXTINT 0x7
- uint_t del_mode : 3;
+ uint_t del_mode : 3;
#define PHSYICAL_DST_MODE 0
#define LOGICAL_DST_MODE 1
- uint_t dst_mode : 1;
- uint_t del_status : 1;
+ uint_t dst_mode : 1;
+ uint_t del_status : 1;
#define HIGH_ACTIVE 0
#define LOW_ACTIVE 1
- uint_t intr_pol : 1;
- uint_t rem_irr : 1;
- uint_t trig_mode : 1;
- uint_t mask : 1;
- uint64_t rsvd : 39;
- uint_t dst_field : 8;
+ uint_t intr_pol : 1;
+ uint_t rem_irr : 1;
+ uint_t trig_mode : 1;
+ uint_t mask : 1;
+ uint64_t rsvd : 39;
+ uint_t dst_field : 8;
+ } __attribute__((packed));
} __attribute__((packed));
- } __attribute__((packed));
} __attribute__((packed));
struct io_apic_state {
- addr_t base_addr;
+ addr_t base_addr;
- uint32_t index_reg;
+ uint32_t index_reg;
- struct ioapic_id_reg ioapic_id;
- struct ioapic_ver_reg ioapic_ver;
- struct ioapic_arb_reg ioapic_arb_id;
+ struct ioapic_id_reg ioapic_id;
+ struct ioapic_ver_reg ioapic_ver;
+ struct ioapic_arb_reg ioapic_arb_id;
- struct redir_tbl_entry redir_tbl[24];
+ struct redir_tbl_entry redir_tbl[24];
- // This is a temporary method of communication between the IOAPIC and the LAPIC
- struct vm_device * apic;
+ // This is a temporary method of communication between the IOAPIC and the LAPIC
+ struct vm_device * apic;
};
static void init_ioapic_state(struct io_apic_state * ioapic) {
- int i = 0;
- ioapic->base_addr = IO_APIC_BASE_ADDR;
- ioapic->index_reg = 0;
-
- ioapic->ioapic_id.val = 0x00000000;
- ioapic->ioapic_ver.val = 0x00170011;
- ioapic->ioapic_arb_id.val = 0x00000000;
-
- for (i = 0; i < 24; i++) {
- ioapic->redir_tbl[i].val = 0x0001000000000000LL;
- // Mask all interrupts until they are enabled....
- ioapic->redir_tbl[i].mask = 1;
- }
+ int i = 0;
+ ioapic->base_addr = IO_APIC_BASE_ADDR;
+ ioapic->index_reg = 0;
+
+ ioapic->ioapic_id.val = 0x00000000;
+ ioapic->ioapic_ver.val = 0x00170011;
+ ioapic->ioapic_arb_id.val = 0x00000000;
+
+ for (i = 0; i < 24; i++) {
+ ioapic->redir_tbl[i].val = 0x0001000000000000LL;
+ // Mask all interrupts until they are enabled....
+ ioapic->redir_tbl[i].mask = 1;
+ }
}
static int ioapic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
- struct vm_device * dev = (struct vm_device *)priv_data;
- struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
- uint32_t reg_tgt = guest_addr - ioapic->base_addr;
- uint32_t * op_val = (uint32_t *)dst;
-
- PrintDebug("IOAPIC Read at %p\n", (void *)guest_addr);
-
- if (reg_tgt == 0x00) {
- *op_val = ioapic->index_reg;
- } else if (reg_tgt == 0x10) {
- // IOWIN register
- switch (ioapic->index_reg) {
- case IOAPIC_ID_REG:
- *op_val = ioapic->ioapic_id.val;
- break;
- case IOAPIC_VER_REG:
- *op_val = ioapic->ioapic_ver.val;
- break;
- case IOAPIC_ARB_REG:
- *op_val = ioapic->ioapic_arb_id.val;
- break;
- default:
- {
- uint_t redir_index = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) & 0xfffffffe;
- uint_t hi_val = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) % 1;
-
- if (redir_index > 0x3f) {
- PrintError("Invalid redirection table entry %x\n", (uint32_t)redir_index);
- return -1;
- }
- if (hi_val) {
- *op_val = ioapic->redir_tbl[redir_index].hi;
- } else {
- *op_val = ioapic->redir_tbl[redir_index].lo;
+ struct vm_device * dev = (struct vm_device *)priv_data;
+ struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
+ uint32_t reg_tgt = guest_addr - ioapic->base_addr;
+ uint32_t * op_val = (uint32_t *)dst;
+
+ PrintDebug("IOAPIC Read at %p\n", (void *)guest_addr);
+
+ if (reg_tgt == 0x00) {
+ *op_val = ioapic->index_reg;
+ } else if (reg_tgt == 0x10) {
+ // IOWIN register
+ switch (ioapic->index_reg) {
+ case IOAPIC_ID_REG:
+ *op_val = ioapic->ioapic_id.val;
+ break;
+ case IOAPIC_VER_REG:
+ *op_val = ioapic->ioapic_ver.val;
+ break;
+ case IOAPIC_ARB_REG:
+ *op_val = ioapic->ioapic_arb_id.val;
+ break;
+ default:
+ {
+ uint_t redir_index = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) & 0xfffffffe;
+ uint_t hi_val = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) % 1;
+
+ if (redir_index > 0x3f) {
+ PrintError("Invalid redirection table entry %x\n", (uint32_t)redir_index);
+ return -1;
+ }
+ if (hi_val) {
+ *op_val = ioapic->redir_tbl[redir_index].hi;
+ } else {
+ *op_val = ioapic->redir_tbl[redir_index].lo;
+ }
+ }
}
- }
}
- }
- return length;
+ return length;
}
static int ioapic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
- struct vm_device * dev = (struct vm_device *)priv_data;
- struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
- uint32_t reg_tgt = guest_addr - ioapic->base_addr;
- uint32_t op_val = *(uint32_t *)src;
-
- PrintDebug("IOAPIC Write at %p (val = %d)\n", (void *)guest_addr, *(uint32_t *)src);
-
- if (reg_tgt == 0x00) {
- ioapic->index_reg = op_val;
- } else if (reg_tgt == 0x10) {
- // IOWIN register
- switch (ioapic->index_reg) {
- case IOAPIC_ID_REG:
- ioapic->ioapic_id.val = op_val;
- break;
- case IOAPIC_VER_REG:
- // GPF/PageFault/Ignore?
- PrintError("Writing to read only IOAPIC register\n");
- return -1;
- case IOAPIC_ARB_REG:
- ioapic->ioapic_arb_id.val = op_val;
- break;
- default:
- {
- uint_t redir_index = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) & 0xfffffffe;
- uint_t hi_val = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) % 1;
-
-
-
-
- if (redir_index > 0x3f) {
- PrintError("Invalid redirection table entry %x\n", (uint32_t)redir_index);
- return -1;
+ struct vm_device * dev = (struct vm_device *)priv_data;
+ struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
+ uint32_t reg_tgt = guest_addr - ioapic->base_addr;
+ uint32_t op_val = *(uint32_t *)src;
+
+ PrintDebug("IOAPIC Write at %p (val = %d)\n", (void *)guest_addr, *(uint32_t *)src);
+
+ if (reg_tgt == 0x00) {
+ ioapic->index_reg = op_val;
+ } else if (reg_tgt == 0x10) {
+ // IOWIN register
+ switch (ioapic->index_reg) {
+ case IOAPIC_ID_REG:
+ ioapic->ioapic_id.val = op_val;
+ break;
+ case IOAPIC_VER_REG:
+ // GPF/PageFault/Ignore?
+ PrintError("Writing to read only IOAPIC register\n");
+ return -1;
+ case IOAPIC_ARB_REG:
+ ioapic->ioapic_arb_id.val = op_val;
+ break;
+ default:
+ {
+ uint_t redir_index = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) & 0xfffffffe;
+ uint_t hi_val = (ioapic->index_reg - IOAPIC_REDIR_BASE_REG) % 1;
+
+
+
+
+ if (redir_index > 0x3f) {
+ PrintError("Invalid redirection table entry %x\n", (uint32_t)redir_index);
+ return -1;
+ }
+ if (hi_val) {
+ PrintDebug("Writing to hi of pin %d\n", redir_index);
+ ioapic->redir_tbl[redir_index].hi = op_val;
+ } else {
+ PrintDebug("Writing to lo of pin %d\n", redir_index);
+ op_val &= REDIR_LO_MASK;
+ ioapic->redir_tbl[redir_index].lo &= ~REDIR_LO_MASK;
+ ioapic->redir_tbl[redir_index].lo |= op_val;
+ }
+ }
}
- if (hi_val) {
- PrintDebug("Writing to hi of pin %d\n", redir_index);
- ioapic->redir_tbl[redir_index].hi = op_val;
- } else {
- PrintDebug("Writing to lo of pin %d\n", redir_index);
- op_val &= REDIR_LO_MASK;
- ioapic->redir_tbl[redir_index].lo &= ~REDIR_LO_MASK;
- ioapic->redir_tbl[redir_index].lo |= op_val;
- }
- }
}
- }
- return length;
+ return length;
}
/* Interrupt controller functions */
static int ioapic_intr_pending(void * private_data) {
- return 0;
+ return 0;
}
static int ioapic_get_intr_number(void * private_data) {
- return 0;
+ return 0;
}
static int ioapic_begin_irq(void * private_data, int irq) {
- return 0;
+ return 0;
}
static int ioapic_raise_irq(void * private_data, int irq) {
- struct vm_device * dev = (struct vm_device *)private_data;
- struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
- struct redir_tbl_entry * irq_entry = NULL;
+ struct vm_device * dev = (struct vm_device *)private_data;
+ struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
+ struct redir_tbl_entry * irq_entry = NULL;
- if (irq > 24) {
- PrintError("IRQ out of range of IO APIC\n");
- return -1;
- }
+ if (irq > 24) {
+ PrintError("IRQ out of range of IO APIC\n");
+ return -1;
+ }
- irq_entry = &(ioapic->redir_tbl[irq]);
+ irq_entry = &(ioapic->redir_tbl[irq]);
- if (irq_entry->mask == 0) {
- PrintDebug("IOAPIC Signalling APIC to raise INTR %d\n", irq_entry->vec);
- v3_apic_raise_intr(ioapic->apic, irq_entry->vec);
- }
+ if (irq_entry->mask == 0) {
+ PrintDebug("IOAPIC Signalling APIC to raise INTR %d\n", irq_entry->vec);
+ v3_apic_raise_intr(ioapic->apic, irq_entry->vec);
+ }
- return 0;
+ return 0;
}
/* I don't know if we can do anything here.... */
static int ioapic_lower_irq(void * private_data, int irq) {
- return 0;
+ return 0;
}
static struct intr_ctrl_ops intr_ops = {
- .intr_pending = ioapic_intr_pending,
- .get_intr_number = ioapic_get_intr_number,
- .raise_intr = ioapic_raise_irq,
- .begin_irq = ioapic_begin_irq,
- .lower_intr = ioapic_lower_irq,
+ .intr_pending = ioapic_intr_pending,
+ .get_intr_number = ioapic_get_intr_number,
+ .raise_intr = ioapic_raise_irq,
+ .begin_irq = ioapic_begin_irq,
+ .lower_intr = ioapic_lower_irq,
};
static int io_apic_init(struct vm_device * dev) {
- struct guest_info * info = dev->vm;
- struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
+ struct guest_info * info = dev->vm;
+ struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
- v3_register_intr_controller(dev->vm, &intr_ops, dev);
- init_ioapic_state(ioapic);
+ v3_register_intr_controller(dev->vm, &intr_ops, dev);
+ init_ioapic_state(ioapic);
- v3_hook_full_mem(info, ioapic->base_addr, ioapic->base_addr + PAGE_SIZE_4KB,
- ioapic_read, ioapic_write, dev);
+ v3_hook_full_mem(info, ioapic->base_addr, ioapic->base_addr + PAGE_SIZE_4KB,
+ ioapic_read, ioapic_write, dev);
- return 0;
+ return 0;
}
static int io_apic_deinit(struct vm_device * dev) {
- // struct guest_info * info = dev->vm;
+ // struct guest_info * info = dev->vm;
- return 0;
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = io_apic_init,
- .deinit = io_apic_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = io_apic_init,
+ .deinit = io_apic_deinit,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_io_apic(struct vm_device * apic) {
- PrintDebug("Creating IO APIC\n");
+ PrintDebug("Creating IO APIC\n");
- struct io_apic_state * ioapic = (struct io_apic_state *)V3_Malloc(sizeof(struct io_apic_state));
- ioapic->apic = apic;
+ struct io_apic_state * ioapic = (struct io_apic_state *)V3_Malloc(sizeof(struct io_apic_state));
+ ioapic->apic = apic;
- struct vm_device * device = v3_create_device("IOAPIC", &dev_ops, ioapic);
+ struct vm_device * device = v3_create_device("IOAPIC", &dev_ops, ioapic);
- return device;
+ return device;
}
struct keyboard_internal {
- //
- // 0x60 is the port for the keyboard microcontroller
- // writes are commands
- // reads from it usually return scancodes
- // however, it can also return other data
- // depending on the state of the onboard microcontroller
- //
- // 0x64 is the port for the onboard microcontroller
- // writes are commands
- // reads are status
- //
-
- // state of the onboard microcontroller
- // this is needed because sometimes 0x60 reads come
- // from the onboard microcontroller
- enum {// Normal mode measn we deliver keys
+ //
+ // 0x60 is the port for the keyboard microcontroller
+ // writes are commands
+ // reads from it usually return scancodes
+ // however, it can also return other data
+ // depending on the state of the onboard microcontroller
+ //
+ // 0x64 is the port for the onboard microcontroller
+ // writes are commands
+ // reads are status
+ //
+
+ // state of the onboard microcontroller
+ // this is needed because sometimes 0x60 reads come
+ // from the onboard microcontroller
+ enum {// Normal mode measn we deliver keys
// to the vm and accept commands from it
NORMAL,
// after receiving cmd 0x60
// we wait for a new output byte on 60
// then send it to the mouse
IN_MOUSE,
- } state;
-
-
- enum {
- // after receiving a mouse command 0f 0xff
- // we return the ack and then the next thing will be the
- // bat code (aa - success)
- RESET1,
- // followed by the device id (00 - mouse)
- RESET2,
- // Then it goes into stream mode
- STREAM1, //
- STREAM2, //
- STREAM3, // for each of the following bytes in mouse_packet
- // this is used for setting sample rate
- SAMPLE1,
- // this is used for getting device id
- DEVICE1,
- // just like the stream moes
- REMOTE1,
- REMOTE2,
- REMOTE3,
- // For getting status info
- STATUS1,
- STATUS2,
- STATUS3,
- // set resolution
- SETRES1,
- } mouse_state;
-
-
- uchar_t wrap;
- uchar_t mouse_packet[3]; // byte 1: y over, xover, y sign, x sign, 1, middle, right, left
- // byte 2: x movement
- // byte 3: y movement
-
- uchar_t mouse_needs_ack; //
- uchar_t mouse_done_after_ack;
-
- uchar_t cmd_byte; // for keyboard uC - read/written
- // via read/write cmd byte command
- uchar_t status_byte; // for on-board uC - read via 64h
-
- uchar_t output_byte; // output port of onboard uC (e.g. A20)
-
- uchar_t input_byte; // input port of onboard uC
-
- // Data for 8042
- uchar_t input_queue; //
- uint_t input_queue_len; //
- //uint_t input_queue_read;
- //uint_t input_queue_write;
- // Data for system
- uchar_t output_queue; //
- uint_t output_queue_len; //
- //uint_t output_queue_read;
- //uint_t output_queue_write;
+ } state;
+
+
+ enum {
+ // after receiving a mouse command 0f 0xff
+ // we return the ack and then the next thing will be the
+ // bat code (aa - success)
+ RESET1,
+ // followed by the device id (00 - mouse)
+ RESET2,
+ // Then it goes into stream mode
+ STREAM1, //
+ STREAM2, //
+ STREAM3, // for each of the following bytes in mouse_packet
+ // this is used for setting sample rate
+ SAMPLE1,
+ // this is used for getting device id
+ DEVICE1,
+ // just like the stream moes
+ REMOTE1,
+ REMOTE2,
+ REMOTE3,
+ // For getting status info
+ STATUS1,
+ STATUS2,
+ STATUS3,
+ // set resolution
+ SETRES1,
+ } mouse_state;
+
+
+ uchar_t wrap;
+ uchar_t mouse_packet[3]; // byte 1: y over, xover, y sign, x sign, 1, middle, right, left
+ // byte 2: x movement
+ // byte 3: y movement
+
+ uchar_t mouse_needs_ack; //
+ uchar_t mouse_done_after_ack;
+
+ uchar_t cmd_byte; // for keyboard uC - read/written
+ // via read/write cmd byte command
+ uchar_t status_byte; // for on-board uC - read via 64h
+
+ uchar_t output_byte; // output port of onboard uC (e.g. A20)
+
+ uchar_t input_byte; // input port of onboard uC
+
+ // Data for 8042
+ uchar_t input_queue; //
+ uint_t input_queue_len; //
+ //uint_t input_queue_read;
+ //uint_t input_queue_write;
+ // Data for system
+ uchar_t output_queue; //
+ uint_t output_queue_len; //
+ //uint_t output_queue_read;
+ //uint_t output_queue_write;
};
//
static int PushToOutputQueue(struct vm_device * dev, uchar_t value, uchar_t overwrite, uchar_t cmd, uchar_t mouse)
{
- struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+ struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
- if ((state->output_queue_len == 0) || overwrite) {
+ if ((state->output_queue_len == 0) || overwrite) {
- state->output_queue = value;
- state->output_queue_len = 1;
+ state->output_queue = value;
+ state->output_queue_len = 1;
- if (cmd) {
- state->status_byte |= STATUS_COMMAND_DATA_AVAIL;
- } else {
- state->status_byte &= ~STATUS_COMMAND_DATA_AVAIL;
- }
+ if (cmd) {
+ state->status_byte |= STATUS_COMMAND_DATA_AVAIL;
+ } else {
+ state->status_byte &= ~STATUS_COMMAND_DATA_AVAIL;
+ }
- if (mouse) {
- state->status_byte |= STATUS_MOUSE_BUFFER_FULL;
- }
+ if (mouse) {
+ state->status_byte |= STATUS_MOUSE_BUFFER_FULL;
+ }
- {
- state->status_byte |= STATUS_OUTPUT_BUFFER_FULL;
- }
+ {
+ state->status_byte |= STATUS_OUTPUT_BUFFER_FULL;
+ }
- return 0;
+ return 0;
- } else {
- PrintError("keyboard: PushToOutputQueue Failed - Queue Full\n");
- return -1;
- }
+ } else {
+ PrintError("keyboard: PushToOutputQueue Failed - Queue Full\n");
+ return -1;
+ }
}
#if 1
//
static int PullFromOutputQueue(struct vm_device * dev, uchar_t * value)
{
- struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+ struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
- if (1 || (state->output_queue_len == 1)) {
+ if (1 || (state->output_queue_len == 1)) {
- *value = state->output_queue;
- state->output_queue_len = 0;
+ *value = state->output_queue;
+ state->output_queue_len = 0;
- if (state->status_byte & STATUS_OUTPUT_BUFFER_FULL) {
- state->status_byte &= ~STATUS_OUTPUT_BUFFER_FULL;
- }
+ if (state->status_byte & STATUS_OUTPUT_BUFFER_FULL) {
+ state->status_byte &= ~STATUS_OUTPUT_BUFFER_FULL;
+ }
- if (state->status_byte & STATUS_MOUSE_BUFFER_FULL) {
- state->status_byte &= ~STATUS_MOUSE_BUFFER_FULL;
- }
+ if (state->status_byte & STATUS_MOUSE_BUFFER_FULL) {
+ state->status_byte &= ~STATUS_MOUSE_BUFFER_FULL;
+ }
- if (state->status_byte & STATUS_COMMAND_DATA_AVAIL) {
- state->status_byte &= ~STATUS_COMMAND_DATA_AVAIL;
- } // reset to data
+ if (state->status_byte & STATUS_COMMAND_DATA_AVAIL) {
+ state->status_byte &= ~STATUS_COMMAND_DATA_AVAIL;
+ } // reset to data
- return 0;
- } else {
- PrintError("keyboard: PullFromOutputQueue Failed - Queue Empty\n");
- return -1;
- }
+ return 0;
+ } else {
+ PrintError("keyboard: PullFromOutputQueue Failed - Queue Empty\n");
+ return -1;
+ }
}
#endif
//
static int PushToInputQueue(struct vm_device * dev, uchar_t value, uchar_t overwrite)
{
- struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+ struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
- if ((state->input_queue_len == 0) || overwrite) {
+ if ((state->input_queue_len == 0) || overwrite) {
- state->input_queue = value;
- state->input_queue_len = 1;
- state->status_byte |= STATUS_INPUT_BUFFER_FULL;
+ state->input_queue = value;
+ state->input_queue_len = 1;
+ state->status_byte |= STATUS_INPUT_BUFFER_FULL;
- return 0;
- } else {
- PrintError("keyboard: PushToOutputQueue Failed - Queue Full\n");
- return -1;
- }
+ return 0;
+ } else {
+ PrintError("keyboard: PushToOutputQueue Failed - Queue Full\n");
+ return -1;
+ }
}
//
//
static int PullFromInputQueue(struct vm_device *dev, uchar_t *value)
{
- struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
+ struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
- if (state->input_queue_len == 1) {
+ if (state->input_queue_len == 1) {
- *value = state->input_queue;
- state->input_queue_len = 0;
- state->status_byte &= ~STATUS_INPUT_BUFFER_FULL;
+ *value = state->input_queue;
+ state->input_queue_len = 0;
+ state->status_byte &= ~STATUS_INPUT_BUFFER_FULL;
- return 0;
- } else {
- PrintError("keyboard: PullFromInputQueue Failed - Queue Empty\n");
- return -1;
- }
+ return 0;
+ } else {
+ PrintError("keyboard: PullFromInputQueue Failed - Queue Empty\n");
+ return -1;
+ }
}
#endif
static int keyboard_interrupt(struct vm_device * dev, uint_t irq) {
- PrintDebug("keyboard: interrupt 0x%x\n", irq);
+ PrintDebug("keyboard: interrupt 0x%x\n", irq);
- v3_raise_irq(dev->vm, irq);
+ v3_raise_irq(dev->vm, irq);
- return 0;
+ return 0;
}
static int key_event_handler(struct guest_info * info,
struct v3_keyboard_event * evt,
void * private_data) {
- struct vm_device * dev = (struct vm_device *)private_data;
- struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+ struct vm_device * dev = (struct vm_device *)private_data;
+ struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
- PrintDebug("keyboard: injected status 0x%x, and scancode 0x%x\n", evt->status, evt->scan_code);
+ PrintDebug("keyboard: injected status 0x%x, and scancode 0x%x\n", evt->status, evt->scan_code);
- if ( (state->status_byte & STATUS_ENABLED) // onboard is enabled
- && (!(state->cmd_byte & CMD_DISABLE)) ) { // keyboard is enabled
+ if ( (state->status_byte & STATUS_ENABLED) // onboard is enabled
+ && (!(state->cmd_byte & CMD_DISABLE)) ) { // keyboard is enabled
- PushToOutputQueue(dev, evt->scan_code, OVERWRITE, DATA, KEYBOARD);
+ PushToOutputQueue(dev, evt->scan_code, OVERWRITE, DATA, KEYBOARD);
- if (state->cmd_byte & CMD_INTR) {
- keyboard_interrupt(dev, KEYBOARD_IRQ);
+ if (state->cmd_byte & CMD_INTR) {
+ keyboard_interrupt(dev, KEYBOARD_IRQ);
+ }
}
- }
- return 0;
+ return 0;
}
static int mouse_event_handler(struct guest_info * info,
struct v3_mouse_event * evt,
void * private_data) {
- struct vm_device * dev = (struct vm_device *)private_data;
- struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
+ struct vm_device * dev = (struct vm_device *)private_data;
+ struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
- PrintDebug("keyboard: injected mouse packet 0x %x %x %x\n",
- evt->data[0], evt->data[1], evt->data[2]);
+ PrintDebug("keyboard: injected mouse packet 0x %x %x %x\n",
+ evt->data[0], evt->data[1], evt->data[2]);
- memcpy(state->mouse_packet, evt->data, 3);
+ memcpy(state->mouse_packet, evt->data, 3);
- state->status_byte |= STATUS_MOUSE_BUFFER_FULL;
+ state->status_byte |= STATUS_MOUSE_BUFFER_FULL;
- switch (state->mouse_state) {
- case STREAM1:
- case STREAM2:
- case STREAM3:
- if (!(state->cmd_byte & CMD_MOUSE_DISABLE)) {
- keyboard_interrupt(dev, MOUSE_IRQ);
+ switch (state->mouse_state) {
+ case STREAM1:
+ case STREAM2:
+ case STREAM3:
+ if (!(state->cmd_byte & CMD_MOUSE_DISABLE)) {
+ keyboard_interrupt(dev, MOUSE_IRQ);
+ }
+ break;
+ default:
+ return -1;
+ break;
}
- break;
- default:
- return -1;
- break;
- }
- return 0;
+ return 0;
}
static int keyboard_reset_device(struct vm_device * dev)
{
- struct keyboard_internal *data = (struct keyboard_internal *)(dev->private_data);
+ struct keyboard_internal *data = (struct keyboard_internal *)(dev->private_data);
- memset(data, 0, sizeof(struct keyboard_internal));
+ memset(data, 0, sizeof(struct keyboard_internal));
- data->state = NORMAL;
- data->mouse_state = STREAM1;
+ data->state = NORMAL;
+ data->mouse_state = STREAM1;
- data->cmd_byte =
- CMD_INTR // interrupts on
- | CMD_MOUSE_INTR // mouse interupts on
- | CMD_SYSTEM ; // self test passed
- // PS2, keyboard+mouse enabled, generic translation
+ data->cmd_byte =
+ CMD_INTR // interrupts on
+ | CMD_MOUSE_INTR // mouse interupts on
+ | CMD_SYSTEM ; // self test passed
+ // PS2, keyboard+mouse enabled, generic translation
- data->status_byte =
- STATUS_SYSTEM // self-tests passed
- | STATUS_ENABLED ; // keyboard ready
- // buffers empty, no errors
+ data->status_byte =
+ STATUS_SYSTEM // self-tests passed
+ | STATUS_ENABLED ; // keyboard ready
+ // buffers empty, no errors
- data->output_byte = 0; // ?
+ data->output_byte = 0; // ?
- data->input_byte = INPUT_RAM; // we have some
- // also display=color, jumper 0, keyboard enabled
+ data->input_byte = INPUT_RAM; // we have some
+ // also display=color, jumper 0, keyboard enabled
- PrintDebug("keyboard: reset device\n");
+ PrintDebug("keyboard: reset device\n");
- return 0;
+ return 0;
}
static int keyboard_start_device(struct vm_device *dev)
{
- PrintDebug("keyboard: start device\n");
- return 0;
+ PrintDebug("keyboard: start device\n");
+ return 0;
}
static int keyboard_stop_device(struct vm_device *dev)
{
- PrintDebug("keyboard: stop device\n");
- return 0;
+ PrintDebug("keyboard: stop device\n");
+ return 0;
}
static int mouse_read_input(struct vm_device *dev)
{
- struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+ struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
- if (state->mouse_needs_ack) {
- state->mouse_needs_ack = 0;
+ if (state->mouse_needs_ack) {
+ state->mouse_needs_ack = 0;
- // the ack has been stuffed previously
- if (state->mouse_done_after_ack) {
- return 1;
- } else {
- return 0;
+ // the ack has been stuffed previously
+ if (state->mouse_done_after_ack) {
+ return 1;
+ } else {
+ return 0;
+ }
}
- }
- switch (state->mouse_state) {
+ switch (state->mouse_state) {
- case RESET1: // requesting the BAT code
- PushToOutputQueue(dev, 0xaa, OVERWRITE, DATA, MOUSE) ; // BAT successful
- PrintDebug(" mouse sent BAT code (sucesssful) ");
- state->mouse_state = RESET2;
+ case RESET1: // requesting the BAT code
+ PushToOutputQueue(dev, 0xaa, OVERWRITE, DATA, MOUSE) ; // BAT successful
+ PrintDebug(" mouse sent BAT code (sucesssful) ");
+ state->mouse_state = RESET2;
- return 0; // not done with mouse processing yet
- break;
+ return 0; // not done with mouse processing yet
+ break;
- case RESET2: // requesting the device id
- PushToOutputQueue(dev, 0x00, OVERWRITE, DATA, MOUSE) ; // normal mouse type
- PrintDebug(" mouse sent device id ");
- state->mouse_state = STREAM1;
+ case RESET2: // requesting the device id
+ PushToOutputQueue(dev, 0x00, OVERWRITE, DATA, MOUSE) ; // normal mouse type
+ PrintDebug(" mouse sent device id ");
+ state->mouse_state = STREAM1;
- return 1; // done with mouse processing
- break;
+ return 1; // done with mouse processing
+ break;
- case STREAM1: // send data
- PushToOutputQueue(dev, state->mouse_packet[0], OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent stream data1 ");
- state->mouse_state = STREAM2;
+ case STREAM1: // send data
+ PushToOutputQueue(dev, state->mouse_packet[0], OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent stream data1 ");
+ state->mouse_state = STREAM2;
- return 0;
- break;
+ return 0;
+ break;
- case STREAM2: // send data
- PushToOutputQueue(dev, state->mouse_packet[1], OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent stream data2 ");
- state->mouse_state = STREAM3;
+ case STREAM2: // send data
+ PushToOutputQueue(dev, state->mouse_packet[1], OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent stream data2 ");
+ state->mouse_state = STREAM3;
- return 0;
- break;
+ return 0;
+ break;
- case STREAM3: // send data
- PushToOutputQueue(dev, state->mouse_packet[2], OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent stream data3 ");
- state->mouse_state = STREAM1;
+ case STREAM3: // send data
+ PushToOutputQueue(dev, state->mouse_packet[2], OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent stream data3 ");
+ state->mouse_state = STREAM1;
- return 1; // now done
- break;
+ return 1; // now done
+ break;
- case REMOTE1: // send data
- PushToOutputQueue(dev, state->mouse_packet[0], OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent remote data1 ");
- state->mouse_state = REMOTE2;
+ case REMOTE1: // send data
+ PushToOutputQueue(dev, state->mouse_packet[0], OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent remote data1 ");
+ state->mouse_state = REMOTE2;
- return 0;
- break;
+ return 0;
+ break;
- case REMOTE2: // send data
- PushToOutputQueue(dev, state->mouse_packet[1], OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent remote data2 ");
- state->mouse_state = REMOTE3;
+ case REMOTE2: // send data
+ PushToOutputQueue(dev, state->mouse_packet[1], OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent remote data2 ");
+ state->mouse_state = REMOTE3;
- return 0;
- break;
+ return 0;
+ break;
- case REMOTE3: // send data
- PushToOutputQueue(dev, state->mouse_packet[2], OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent remote data3 ");
- state->mouse_state = REMOTE1;
+ case REMOTE3: // send data
+ PushToOutputQueue(dev, state->mouse_packet[2], OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent remote data3 ");
+ state->mouse_state = REMOTE1;
- return 1; // now done
- break;
+ return 1; // now done
+ break;
- case STATUS1: // send data
- PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent status data1 ");
- state->mouse_state = STATUS2;
+ case STATUS1: // send data
+ PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent status data1 ");
+ state->mouse_state = STATUS2;
- return 0;
- break;
+ return 0;
+ break;
- case STATUS2: // send data
- PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent status data2 ");
- state->mouse_state = STATUS3;
+ case STATUS2: // send data
+ PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent status data2 ");
+ state->mouse_state = STATUS3;
- return 0;
- break;
+ return 0;
+ break;
- case STATUS3: // send data
- PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent status data3 ");
- state->mouse_state = STREAM1;
+ case STATUS3: // send data
+ PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent status data3 ");
+ state->mouse_state = STREAM1;
- return 1; // now done
- break;
+ return 1; // now done
+ break;
- case DEVICE1: // send device id
- PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE);
- PrintDebug(" mouse sent device id ");
- state->mouse_state = STREAM1;
+ case DEVICE1: // send device id
+ PushToOutputQueue(dev, 0x0, OVERWRITE, DATA, MOUSE);
+ PrintDebug(" mouse sent device id ");
+ state->mouse_state = STREAM1;
- return 1; // now done
- break;
+ return 1; // now done
+ break;
- default:
- PrintDebug(" mouse has no data ");
- return 1; // done
- break;
- }
+ default:
+ PrintDebug(" mouse has no data ");
+ return 1; // done
+ break;
+ }
}
static int mouse_write_output(struct vm_device * dev, uchar_t data)
{
- struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
-
- switch (state->mouse_state) {
- case STREAM1:
- case STREAM2:
- case STREAM3:
- case REMOTE1:
- case REMOTE2:
- case REMOTE3:
- switch (data) {
-
- case 0xff: //reset
- PushToOutputQueue(dev, 0xfe, OVERWRITE, DATA, MOUSE) ; // no mouse!
- PrintDebug(" mouse reset begins (no mouse) ");
-
- return 1; // not done;
- break;
-
- /*
- case 0xff: //reset
- PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ;
- PrintDebug(" mouse reset begins ");
- state->mouse_done_after_ack=0;
- state->mouse_needs_ack=1;
- state->mouse_state=RESET1;
- return 0; // not done;
- break;
- */
- case 0xfe: //resend
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- PrintDebug(" mouse resend begins ");
- state->mouse_done_after_ack = 0;
- state->mouse_needs_ack = 0;
- state->mouse_state = STREAM1;
- return 0; // not done
- break;
+ struct keyboard_internal * state = (struct keyboard_internal *)(dev->private_data);
+
+ switch (state->mouse_state) {
+ case STREAM1:
+ case STREAM2:
+ case STREAM3:
+ case REMOTE1:
+ case REMOTE2:
+ case REMOTE3:
+ switch (data) {
+
+ case 0xff: //reset
+ PushToOutputQueue(dev, 0xfe, OVERWRITE, DATA, MOUSE) ; // no mouse!
+ PrintDebug(" mouse reset begins (no mouse) ");
+
+ return 1; // not done;
+ break;
+
+ /*
+ case 0xff: //reset
+ PushToOutputQueue(dev,0xfa,OVERWRITE,DATA,MOUSE) ;
+ PrintDebug(" mouse reset begins ");
+ state->mouse_done_after_ack=0;
+ state->mouse_needs_ack=1;
+ state->mouse_state=RESET1;
+ return 0; // not done;
+ break;
+ */
+ case 0xfe: //resend
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ PrintDebug(" mouse resend begins ");
+ state->mouse_done_after_ack = 0;
+ state->mouse_needs_ack = 0;
+ state->mouse_state = STREAM1;
+ return 0; // not done
+ break;
- case 0xf6: // set defaults
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- PrintDebug(" mouse set defaults ");
- state->mouse_done_after_ack = 1;
- state->mouse_needs_ack = 1;
- state->mouse_state = STREAM1;
- return 0; // not done
- break;
+ case 0xf6: // set defaults
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ PrintDebug(" mouse set defaults ");
+ state->mouse_done_after_ack = 1;
+ state->mouse_needs_ack = 1;
+ state->mouse_state = STREAM1;
+ return 0; // not done
+ break;
- case 0xf5: // disable data reporting
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 1;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse disable data reporting ");
- state->mouse_state = STREAM1;
- return 0; // not done
- break;
+ case 0xf5: // disable data reporting
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 1;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse disable data reporting ");
+ state->mouse_state = STREAM1;
+ return 0; // not done
+ break;
- case 0xf4: // enable data reporting
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 1;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse enable data reporting ");
- state->mouse_state = STREAM1;
- return 0; // not done
- break;
+ case 0xf4: // enable data reporting
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 1;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse enable data reporting ");
+ state->mouse_state = STREAM1;
+ return 0; // not done
+ break;
- case 0xf3: // set sample rate
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 0;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse set sample rate begins ");
- state->mouse_state = SAMPLE1;
- return 0; // not done
- break;
+ case 0xf3: // set sample rate
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 0;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse set sample rate begins ");
+ state->mouse_state = SAMPLE1;
+ return 0; // not done
+ break;
- case 0xf2: // get device id
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 0;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse get device id begins ");
- state->mouse_state = DEVICE1;
- return 0; // not done
- break;
+ case 0xf2: // get device id
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 0;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse get device id begins ");
+ state->mouse_state = DEVICE1;
+ return 0; // not done
+ break;
- case 0xf0: // set remote mode
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 1;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse set remote mode ");
- state->mouse_state = REMOTE1;
- return 0; // not done
- break;
-
- case 0xee: // set wrap mode
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 1;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse set wrap mode (ignored) ");
- state->mouse_state = STREAM1;
- return 0; // not done
- break;
-
- case 0xec: // reset wrap mode
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 1;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse reset wrap mode (ignored) ");
- state->mouse_state = STREAM1;
- return 0; // done
- break;
-
- case 0xeb: // read data
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 0;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse switch to wrap mode (ignored) ");
- state->mouse_state = REMOTE1;
- return 0; // not done
- break;
+ case 0xf0: // set remote mode
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 1;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse set remote mode ");
+ state->mouse_state = REMOTE1;
+ return 0; // not done
+ break;
+
+ case 0xee: // set wrap mode
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 1;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse set wrap mode (ignored) ");
+ state->mouse_state = STREAM1;
+ return 0; // not done
+ break;
+
+ case 0xec: // reset wrap mode
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 1;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse reset wrap mode (ignored) ");
+ state->mouse_state = STREAM1;
+ return 0; // done
+ break;
+
+ case 0xeb: // read data
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 0;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse switch to wrap mode (ignored) ");
+ state->mouse_state = REMOTE1;
+ return 0; // not done
+ break;
- case 0xea: // set stream mode
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 1;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse set stream mode ");
- state->mouse_state = STREAM1;
- return 0; // not done
- break;
-
- case 0xe9: // status request
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 0;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse status request begins ");
- state->mouse_state = STATUS1;
- return 0; // notdone
- break;
-
- case 0xe8: // set resolution
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 0;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse set resolution begins ");
- state->mouse_state = SETRES1;
- return 0; // notdone
- break;
-
- case 0xe7: // set scaling 2:1
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 1;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse set scaling 2:1 ");
- state->mouse_state = STREAM1;
- return 0; // not done
- break;
-
- case 0xe6: // set scaling 1:1
- PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
- state->mouse_done_after_ack = 1;
- state->mouse_needs_ack = 1;
- PrintDebug(" mouse set scaling 1:1 ");
- state->mouse_state = STREAM1;
- return 0; // done
- break;
+ case 0xea: // set stream mode
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 1;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse set stream mode ");
+ state->mouse_state = STREAM1;
+ return 0; // not done
+ break;
+
+ case 0xe9: // status request
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 0;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse status request begins ");
+ state->mouse_state = STATUS1;
+ return 0; // notdone
+ break;
+
+ case 0xe8: // set resolution
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 0;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse set resolution begins ");
+ state->mouse_state = SETRES1;
+ return 0; // notdone
+ break;
+
+ case 0xe7: // set scaling 2:1
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 1;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse set scaling 2:1 ");
+ state->mouse_state = STREAM1;
+ return 0; // not done
+ break;
+
+ case 0xe6: // set scaling 1:1
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, DATA, MOUSE) ;
+ state->mouse_done_after_ack = 1;
+ state->mouse_needs_ack = 1;
+ PrintDebug(" mouse set scaling 1:1 ");
+ state->mouse_state = STREAM1;
+ return 0; // done
+ break;
- default:
- PrintDebug(" receiving unknown mouse command (0x%x) in acceptable state ", data);
- return 1; // done
- break;
+ default:
+ PrintDebug(" receiving unknown mouse command (0x%x) in acceptable state ", data);
+ return 1; // done
+ break;
- }
+ }
- default:
- PrintDebug(" receiving mouse output in unhandled state (0x%x) ", state->mouse_state);
- break;
- return 1; // done?
- break;
- }
-
- PrintDebug(" HUH? ");
- return 1; // done
+ default:
+ PrintDebug(" receiving mouse output in unhandled state (0x%x) ", state->mouse_state);
+ break;
+ return 1; // done?
+ break;
+ }
+
+ PrintDebug(" HUH? ");
+ return 1; // done
}
#if KEYBOARD_DEBUG_80H
static int keyboard_write_delay(ushort_t port,
- void * src,
- uint_t length,
- struct vm_device * dev)
+ void * src,
+ uint_t length,
+ struct vm_device * dev)
{
- if (length == 1) {
- PrintDebug("keyboard: write of 0x%x to 80h\n", *((uchar_t*)src));
+ if (length == 1) {
+ PrintDebug("keyboard: write of 0x%x to 80h\n", *((uchar_t*)src));
- return 1;
- } else {
- PrintDebug("keyboard: write of >1 byte to 80h\n", *((uchar_t*)src));
+ return 1;
+ } else {
+ PrintDebug("keyboard: write of >1 byte to 80h\n", *((uchar_t*)src));
- return length;
- }
+ return length;
+ }
}
static int keyboard_read_delay(ushort_t port,
- void * dest,
- uint_t length,
- struct vm_device * dev)
+ void * dest,
+ uint_t length,
+ struct vm_device * dev)
{
- if (length == 1) {
- *((uchar_t*)dest) = v3_inb(port);
+ if (length == 1) {
+ *((uchar_t*)dest) = v3_inb(port);
- PrintDebug("keyboard: read of 0x%x from 80h\n", *((uchar_t*)dest));
+ PrintDebug("keyboard: read of 0x%x from 80h\n", *((uchar_t*)dest));
- return 1;
- } else {
- PrintDebug("keyboard: read of >1 byte from 80h\n");
+ return 1;
+ } else {
+ PrintDebug("keyboard: read of >1 byte from 80h\n");
- return length;
- }
+ return length;
+ }
}
#endif
uint_t length,
struct vm_device * dev)
{
- struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
- uchar_t cmd;
+ struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+ uchar_t cmd;
- // Should always be single byte write
+ // Should always be single byte write
- if (length != 1) {
- PrintError("keyboard: write of >1 bytes (%d) to 64h\n", length);
- return -1;
- }
+ if (length != 1) {
+ PrintError("keyboard: write of >1 bytes (%d) to 64h\n", length);
+ return -1;
+ }
- cmd = *((uchar_t*)src);
+ cmd = *((uchar_t*)src);
- if (state->state != NORMAL) {
- PrintDebug("keyboard: warning - receiving command on 64h but state != NORMAL\n");
- }
+ if (state->state != NORMAL) {
+ PrintDebug("keyboard: warning - receiving command on 64h but state != NORMAL\n");
+ }
- PrintDebug("keyboard: command 0x%x on 64h\n", cmd);
-
- switch (cmd) {
-
- case 0x20: // READ COMMAND BYTE (returned in 60h)
- PushToOutputQueue(dev, state->cmd_byte, OVERWRITE, COMMAND,KEYBOARD);
- state->state = NORMAL; // the next read on 0x60 will get the right data
- PrintDebug("keyboard: command byte 0x%x returned\n", state->cmd_byte);
- break;
-
- case 0x60: // WRITE COMMAND BYTE (read from 60h)
- state->state = WRITING_CMD_BYTE; // we need to make sure we send the next 0x60 byte appropriately
- PrintDebug("keyboard: prepare to write command byte\n");
- break;
-
- // case 0x90-9f - write to output port (?)
-
- case 0xa1: // Get version number
- PushToOutputQueue(dev, 0, OVERWRITE, COMMAND, KEYBOARD);
- state->state = NORMAL;
- PrintDebug("keyboard: version number 0x0 returned\n");
- break;
-
- case 0xa4: // is password installed? send result to 0x60
- // we don't support passwords
- PushToOutputQueue(dev, 0xf1, OVERWRITE, COMMAND, KEYBOARD);
- PrintDebug("keyboard: password not installed\n");
- state->state = NORMAL;
- break;
-
- case 0xa5: // new password will arrive on 0x60
- state->state = TRANSMIT_PASSWD;
- PrintDebug("keyboard: pepare to transmit password\n");
- break;
-
- case 0xa6: // check passwd;
- // since we do not support passwords, we will simply ignore this
- // the implication is that any password check immediately succeeds
- // with a blank password
- state->state = NORMAL;
- PrintDebug("keyboard: password check succeeded\n");
- break;
-
- case 0xa7: // disable mouse
- state->cmd_byte |= CMD_MOUSE_DISABLE;
- state->state = NORMAL;
- PrintDebug("keyboard: mouse disabled\n");
- break;
-
- case 0xa8: // enable mouse
- state->cmd_byte &= ~CMD_MOUSE_DISABLE;
- state->state = NORMAL;
- PrintDebug("keyboard: mouse enabled\n");
- break;
-
- case 0xa9: // mouse interface test (always succeeds)
- PushToOutputQueue(dev, 0, OVERWRITE, COMMAND, KEYBOARD);
- PrintDebug("keyboard: mouse interface test succeeded\n");
- state->state = NORMAL;
- break;
-
- case 0xaa: // controller self test (always succeeds)
- PushToOutputQueue(dev, 0x55, OVERWRITE, COMMAND, KEYBOARD);
- PrintDebug("keyboard: controller self test succeeded\n");
- state->state = NORMAL;
- break;
-
- case 0xab: // keyboard interface test (always succeeds)
- PushToOutputQueue(dev, 0, OVERWRITE, COMMAND, KEYBOARD);
- state->state = NORMAL;
- PrintDebug("keyboard: keyboard interface test succeeded\n");
- break;
-
- case 0xad: // disable keyboard
- state->cmd_byte |= CMD_DISABLE;
- state->state = NORMAL;
- PrintDebug("keyboard: keyboard disabled\n");
- break;
-
- case 0xae: // enable keyboard
- state->cmd_byte &= ~CMD_DISABLE;
- state->state = NORMAL;
- PrintDebug("keyboard: keyboard enabled\n");
- break;
-
- case 0xaf: // get version
- PushToOutputQueue(dev, 0x00, OVERWRITE, COMMAND, KEYBOARD);
- state->state = NORMAL;
- PrintDebug("keyboard: version 0 returned \n");
- break;
-
- case 0xd0: // return microcontroller output on 60h
- PushToOutputQueue(dev, state->output_byte, OVERWRITE, COMMAND, KEYBOARD);
- state->state = NORMAL;
- PrintDebug("keyboard: output byte 0x%x returned\n", state->output_byte);
- break;
-
- case 0xd1: // request to write next byte on 60h to the microcontroller output port
- state->state = WRITING_OUTPUT_PORT;
- PrintDebug("keyboard: prepare to write output byte\n");
- break;
-
- case 0xd2: // write keyboard buffer (inject key)
- state->state = INJECTING_KEY;
- PrintDebug("keyboard: prepare to inject key\n");
- break;
-
- case 0xd3: // write mouse buffer (inject mouse)
- state->state = INJECTING_MOUSE;
- PrintDebug("keyboard: prepare to inject mouse\n");
- break;
-
- case 0xd4: // write mouse device (command to mouse?)
- state->state = IN_MOUSE;
- PrintDebug("keyboard: prepare to inject mouse command\n");
- break;
-
- case 0xc0: // read input port
- PushToOutputQueue(dev, state->input_byte, OVERWRITE, COMMAND, KEYBOARD);
- state->state = NORMAL;
- PrintDebug("keyboard: input byte 0x%x returned\n", state->input_byte);
- break;
-
- case 0xc1: //copy input port lsn to status msn
- state->status_byte &= 0x0f;
- state->status_byte |= (state->input_byte & 0xf) << 4;
- state->state = NORMAL;
- PrintDebug("keyboard: copied input byte lsn to status msn\n");
- break;
-
- case 0xc2: // copy input port msn to status msn
- state->status_byte &= 0x0f;
- state->status_byte |= (state->input_byte & 0xf0);
- state->state = NORMAL;
- PrintDebug("keyboard: copied input byte msn to status msn\n");
- break;
+ PrintDebug("keyboard: command 0x%x on 64h\n", cmd);
+
+ switch (cmd) {
+
+ case 0x20: // READ COMMAND BYTE (returned in 60h)
+ PushToOutputQueue(dev, state->cmd_byte, OVERWRITE, COMMAND,KEYBOARD);
+ state->state = NORMAL; // the next read on 0x60 will get the right data
+ PrintDebug("keyboard: command byte 0x%x returned\n", state->cmd_byte);
+ break;
+
+ case 0x60: // WRITE COMMAND BYTE (read from 60h)
+ state->state = WRITING_CMD_BYTE; // we need to make sure we send the next 0x60 byte appropriately
+ PrintDebug("keyboard: prepare to write command byte\n");
+ break;
+
+ // case 0x90-9f - write to output port (?)
+
+ case 0xa1: // Get version number
+ PushToOutputQueue(dev, 0, OVERWRITE, COMMAND, KEYBOARD);
+ state->state = NORMAL;
+ PrintDebug("keyboard: version number 0x0 returned\n");
+ break;
+
+ case 0xa4: // is password installed? send result to 0x60
+ // we don't support passwords
+ PushToOutputQueue(dev, 0xf1, OVERWRITE, COMMAND, KEYBOARD);
+ PrintDebug("keyboard: password not installed\n");
+ state->state = NORMAL;
+ break;
+
+ case 0xa5: // new password will arrive on 0x60
+ state->state = TRANSMIT_PASSWD;
+ PrintDebug("keyboard: pepare to transmit password\n");
+ break;
+
+ case 0xa6: // check passwd;
+ // since we do not support passwords, we will simply ignore this
+ // the implication is that any password check immediately succeeds
+ // with a blank password
+ state->state = NORMAL;
+ PrintDebug("keyboard: password check succeeded\n");
+ break;
+
+ case 0xa7: // disable mouse
+ state->cmd_byte |= CMD_MOUSE_DISABLE;
+ state->state = NORMAL;
+ PrintDebug("keyboard: mouse disabled\n");
+ break;
+
+ case 0xa8: // enable mouse
+ state->cmd_byte &= ~CMD_MOUSE_DISABLE;
+ state->state = NORMAL;
+ PrintDebug("keyboard: mouse enabled\n");
+ break;
+
+ case 0xa9: // mouse interface test (always succeeds)
+ PushToOutputQueue(dev, 0, OVERWRITE, COMMAND, KEYBOARD);
+ PrintDebug("keyboard: mouse interface test succeeded\n");
+ state->state = NORMAL;
+ break;
+
+ case 0xaa: // controller self test (always succeeds)
+ PushToOutputQueue(dev, 0x55, OVERWRITE, COMMAND, KEYBOARD);
+ PrintDebug("keyboard: controller self test succeeded\n");
+ state->state = NORMAL;
+ break;
+
+ case 0xab: // keyboard interface test (always succeeds)
+ PushToOutputQueue(dev, 0, OVERWRITE, COMMAND, KEYBOARD);
+ state->state = NORMAL;
+ PrintDebug("keyboard: keyboard interface test succeeded\n");
+ break;
+
+ case 0xad: // disable keyboard
+ state->cmd_byte |= CMD_DISABLE;
+ state->state = NORMAL;
+ PrintDebug("keyboard: keyboard disabled\n");
+ break;
+
+ case 0xae: // enable keyboard
+ state->cmd_byte &= ~CMD_DISABLE;
+ state->state = NORMAL;
+ PrintDebug("keyboard: keyboard enabled\n");
+ break;
+
+ case 0xaf: // get version
+ PushToOutputQueue(dev, 0x00, OVERWRITE, COMMAND, KEYBOARD);
+ state->state = NORMAL;
+ PrintDebug("keyboard: version 0 returned \n");
+ break;
+
+ case 0xd0: // return microcontroller output on 60h
+ PushToOutputQueue(dev, state->output_byte, OVERWRITE, COMMAND, KEYBOARD);
+ state->state = NORMAL;
+ PrintDebug("keyboard: output byte 0x%x returned\n", state->output_byte);
+ break;
+
+ case 0xd1: // request to write next byte on 60h to the microcontroller output port
+ state->state = WRITING_OUTPUT_PORT;
+ PrintDebug("keyboard: prepare to write output byte\n");
+ break;
+
+ case 0xd2: // write keyboard buffer (inject key)
+ state->state = INJECTING_KEY;
+ PrintDebug("keyboard: prepare to inject key\n");
+ break;
+
+ case 0xd3: // write mouse buffer (inject mouse)
+ state->state = INJECTING_MOUSE;
+ PrintDebug("keyboard: prepare to inject mouse\n");
+ break;
+
+ case 0xd4: // write mouse device (command to mouse?)
+ state->state = IN_MOUSE;
+ PrintDebug("keyboard: prepare to inject mouse command\n");
+ break;
+
+ case 0xc0: // read input port
+ PushToOutputQueue(dev, state->input_byte, OVERWRITE, COMMAND, KEYBOARD);
+ state->state = NORMAL;
+ PrintDebug("keyboard: input byte 0x%x returned\n", state->input_byte);
+ break;
+
+ case 0xc1: //copy input port lsn to status msn
+ state->status_byte &= 0x0f;
+ state->status_byte |= (state->input_byte & 0xf) << 4;
+ state->state = NORMAL;
+ PrintDebug("keyboard: copied input byte lsn to status msn\n");
+ break;
+
+ case 0xc2: // copy input port msn to status msn
+ state->status_byte &= 0x0f;
+ state->status_byte |= (state->input_byte & 0xf0);
+ state->state = NORMAL;
+ PrintDebug("keyboard: copied input byte msn to status msn\n");
+ break;
- case 0xe0: // read test port
- PushToOutputQueue(dev, state->output_byte >> 6, OVERWRITE, COMMAND, KEYBOARD);
- state->state = NORMAL;
- PrintDebug("keyboard: read 0x%x from test port\n", state->output_byte >> 6);
- break;
+ case 0xe0: // read test port
+ PushToOutputQueue(dev, state->output_byte >> 6, OVERWRITE, COMMAND, KEYBOARD);
+ state->state = NORMAL;
+ PrintDebug("keyboard: read 0x%x from test port\n", state->output_byte >> 6);
+ break;
- case 0xf0: // pulse output port
- case 0xf1: // this should pulse 0..3 of cmd_byte on output port
- case 0xf2: // instead of what is currently in output_byte (I think)
- case 0xf3: // main effect is taht if bit zero is zero
- case 0xf4: // should cause reset
- case 0xf5: // I doubt anything more recent than a 286 running
- case 0xf6: // OS2 with the penalty box will care
- case 0xf7:
- case 0xf8:
- case 0xf9:
- case 0xfa:
- case 0xfb:
- case 0xfc:
- case 0xfd:
- case 0xfe:
- case 0xff:
+ case 0xf0: // pulse output port
+ case 0xf1: // this should pulse 0..3 of cmd_byte on output port
+ case 0xf2: // instead of what is currently in output_byte (I think)
+ case 0xf3: // main effect is taht if bit zero is zero
+ case 0xf4: // should cause reset
+ case 0xf5: // I doubt anything more recent than a 286 running
+ case 0xf6: // OS2 with the penalty box will care
+ case 0xf7:
+ case 0xf8:
+ case 0xf9:
+ case 0xfa:
+ case 0xfb:
+ case 0xfc:
+ case 0xfd:
+ case 0xfe:
+ case 0xff:
- PrintDebug("keyboard: ignoring pulse of 0x%x (low=pulsed) on output port\n", (cmd & 0xf));
- state->state = NORMAL;
- break;
+ PrintDebug("keyboard: ignoring pulse of 0x%x (low=pulsed) on output port\n", (cmd & 0xf));
+ state->state = NORMAL;
+ break;
- // case ac diagonstic - returns 16 bytes from keyboard microcontroler on 60h
- default:
- PrintDebug("keyboard: ignoring command (unimplemented)\n");
- state->state = NORMAL;
- break;
- }
+ // case ac diagonstic - returns 16 bytes from keyboard microcontroler on 60h
+ default:
+ PrintDebug("keyboard: ignoring command (unimplemented)\n");
+ state->state = NORMAL;
+ break;
+ }
- return 1;
+ return 1;
}
uint_t length,
struct vm_device * dev)
{
- struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+ struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
- if (length == 1) {
+ if (length == 1) {
- PrintDebug("keyboard: read status (64h): ");
+ PrintDebug("keyboard: read status (64h): ");
- *((uchar_t*)dest) = state->status_byte;
+ *((uchar_t*)dest) = state->status_byte;
- PrintDebug("0x%x\n", *((uchar_t*)dest));
+ PrintDebug("0x%x\n", *((uchar_t*)dest));
- return 1;
- } else {
- PrintError("keyboard: >1 byte read for status (64h)\n");
- return -1;
- }
+ return 1;
+ } else {
+ PrintError("keyboard: >1 byte read for status (64h)\n");
+ return -1;
+ }
}
static int keyboard_write_output(ushort_t port,
uint_t length,
struct vm_device * dev)
{
- struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+ struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
- if (length != 1) {
- PrintError("keyboard: write of 60h with >1 byte\n");
- return -1;
- }
+ if (length != 1) {
+ PrintError("keyboard: write of 60h with >1 byte\n");
+ return -1;
+ }
- uchar_t data = *((uchar_t*)src);
+ uchar_t data = *((uchar_t*)src);
- PrintDebug("keyboard: output 0x%x on 60h\n", data);
-
- switch (state->state) {
- case WRITING_CMD_BYTE:
- state->cmd_byte = data;
- state->state = NORMAL;
- PrintDebug("keyboard: wrote new command byte 0x%x\n", state->cmd_byte);
- break;
- case WRITING_OUTPUT_PORT:
- state->output_byte = data;
- state->state = NORMAL;
- PrintDebug("keyboard: wrote new output byte 0x%x\n", state->output_byte);
- break;
- case INJECTING_KEY:
- PushToOutputQueue(dev, data, OVERWRITE, COMMAND, KEYBOARD); // probably should be a call to deliver_key_to_vmm()
- state->state = NORMAL;
- PrintDebug("keyboard: injected key 0x%x\n", data);
- break;
- case INJECTING_MOUSE:
- PrintDebug("keyboard: ignoring injected mouse event 0x%x\n", data);
- state->state = NORMAL;
- break;
- case IN_MOUSE:
- PrintDebug("keyboard: mouse action: ");
- if (mouse_write_output(dev, data)) {
- state->state = NORMAL;
- }
- PrintDebug("\n");
- break;
- case TRANSMIT_PASSWD:
- if (data) {
- //ignore passwd
- PrintDebug("keyboard: ignoring password character 0x%x\n",data);
- } else {
- // end of password
- state->state = NORMAL;
- PrintDebug("keyboard: done with password\n");
+ PrintDebug("keyboard: output 0x%x on 60h\n", data);
+
+ switch (state->state) {
+ case WRITING_CMD_BYTE:
+ state->cmd_byte = data;
+ state->state = NORMAL;
+ PrintDebug("keyboard: wrote new command byte 0x%x\n", state->cmd_byte);
+ break;
+ case WRITING_OUTPUT_PORT:
+ state->output_byte = data;
+ state->state = NORMAL;
+ PrintDebug("keyboard: wrote new output byte 0x%x\n", state->output_byte);
+ break;
+ case INJECTING_KEY:
+ PushToOutputQueue(dev, data, OVERWRITE, COMMAND, KEYBOARD); // probably should be a call to deliver_key_to_vmm()
+ state->state = NORMAL;
+ PrintDebug("keyboard: injected key 0x%x\n", data);
+ break;
+ case INJECTING_MOUSE:
+ PrintDebug("keyboard: ignoring injected mouse event 0x%x\n", data);
+ state->state = NORMAL;
+ break;
+ case IN_MOUSE:
+ PrintDebug("keyboard: mouse action: ");
+ if (mouse_write_output(dev, data)) {
+ state->state = NORMAL;
+ }
+ PrintDebug("\n");
+ break;
+ case TRANSMIT_PASSWD:
+ if (data) {
+ //ignore passwd
+ PrintDebug("keyboard: ignoring password character 0x%x\n",data);
+ } else {
+ // end of password
+ state->state = NORMAL;
+ PrintDebug("keyboard: done with password\n");
+ }
+ break;
+ case NORMAL:
+ {
+ // command is being sent to keyboard controller
+ switch (data) {
+ case 0xff: // reset
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD); // ack
+ state->state = RESET;
+ PrintDebug("keyboard: reset complete and acked\n");
+ break;
+ case 0xf5: // disable scanning
+ case 0xf4: // enable scanning
+ // ack
+ PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD);
+ // should do something here... PAD
+ state->state = NORMAL;
+ PrintDebug("keyboard: %s scanning done and acked\n",data==0xf5 ? "disable" : "enable");
+ break;
+ case 0xfe: // resend
+ case 0xfd: // set key type make
+ case 0xfc: // set key typ make/break
+ case 0xfb: // set key type typematic
+ case 0xfa: // set all typematic make/break/typematic
+ case 0xf9: // set all make
+ case 0xf8: // set all make/break
+ case 0xf7: // set all typemaktic
+ case 0xf6: // set defaults
+ case 0xf3: // set typematic delay/rate
+ PrintDebug("keyboard: unhandled known command 0x%x on output buffer (60h)\n", data);
+ break;
+ default:
+ PrintDebug("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data);
+ state->status_byte |= 0x1;
+ break;
+ }
+ break;
+ }
+ default:
+ PrintDebug("keyboard: unknown state %x on command 0x%x on output buffer (60h)\n", state->state, data);
}
- break;
- case NORMAL:
- {
- // command is being sent to keyboard controller
- switch (data) {
- case 0xff: // reset
- PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD); // ack
- state->state = RESET;
- PrintDebug("keyboard: reset complete and acked\n");
- break;
- case 0xf5: // disable scanning
- case 0xf4: // enable scanning
- // ack
- PushToOutputQueue(dev, 0xfa, OVERWRITE, COMMAND, KEYBOARD);
- // should do something here... PAD
- state->state = NORMAL;
- PrintDebug("keyboard: %s scanning done and acked\n",data==0xf5 ? "disable" : "enable");
- break;
- case 0xfe: // resend
- case 0xfd: // set key type make
- case 0xfc: // set key typ make/break
- case 0xfb: // set key type typematic
- case 0xfa: // set all typematic make/break/typematic
- case 0xf9: // set all make
- case 0xf8: // set all make/break
- case 0xf7: // set all typemaktic
- case 0xf6: // set defaults
- case 0xf3: // set typematic delay/rate
- PrintDebug("keyboard: unhandled known command 0x%x on output buffer (60h)\n", data);
- break;
- default:
- PrintDebug("keyboard: unhandled unknown command 0x%x on output buffer (60h)\n", data);
- state->status_byte |= 0x1;
- break;
- }
- break;
- }
- default:
- PrintDebug("keyboard: unknown state %x on command 0x%x on output buffer (60h)\n", state->state, data);
- }
- return 1;
+ return 1;
}
static int keyboard_read_input(ushort_t port,
uint_t length,
struct vm_device * dev)
{
- struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
+ struct keyboard_internal *state = (struct keyboard_internal *)(dev->private_data);
- if (length == 1) {
- uchar_t data;
- int done_mouse;
+ if (length == 1) {
+ uchar_t data;
+ int done_mouse;
- PrintDebug("keyboard: read from input (60h): ");
+ PrintDebug("keyboard: read from input (60h): ");
- if (state->state == IN_MOUSE) {
- done_mouse = mouse_read_input(dev);
- if (done_mouse) {
- state->state = NORMAL;
- }
- }
+ if (state->state == IN_MOUSE) {
+ done_mouse = mouse_read_input(dev);
+ if (done_mouse) {
+ state->state = NORMAL;
+ }
+ }
- PullFromOutputQueue(dev, &data);
+ PullFromOutputQueue(dev, &data);
- if (state->state == RESET) {
- // We just delivered the ack for the reset
- // now we will ready ourselves to deliver the BAT code (success)
- PushToOutputQueue(dev, 0xaa, OVERWRITE, COMMAND, KEYBOARD);
- state->state = NORMAL;
- PrintDebug(" (in reset, pushing BAT test code 0xaa) ");
- }
+ if (state->state == RESET) {
+ // We just delivered the ack for the reset
+ // now we will ready ourselves to deliver the BAT code (success)
+ PushToOutputQueue(dev, 0xaa, OVERWRITE, COMMAND, KEYBOARD);
+ state->state = NORMAL;
+ PrintDebug(" (in reset, pushing BAT test code 0xaa) ");
+ }
- PrintDebug("0x%x\n", data);
+ PrintDebug("0x%x\n", data);
- *((uchar_t*)dest) = data;
+ *((uchar_t*)dest) = data;
- return 1;
- } else {
- PrintError("keyboard: unknown size read from input (60h)\n");
- return -1;
- }
+ return 1;
+ } else {
+ PrintError("keyboard: unknown size read from input (60h)\n");
+ return -1;
+ }
}
static int keyboard_init_device(struct vm_device * dev)
{
- // struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
+ // struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
- PrintDebug("keyboard: init_device\n");
+ PrintDebug("keyboard: init_device\n");
- // Would read state here
+ // Would read state here
- keyboard_reset_device(dev);
+ keyboard_reset_device(dev);
- // hook ports
- v3_dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command);
- v3_dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output);
+ // hook ports
+ v3_dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command);
+ v3_dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output);
- v3_hook_host_event(dev->vm, HOST_KEYBOARD_EVT, V3_HOST_EVENT_HANDLER(key_event_handler), dev);
- v3_hook_host_event(dev->vm, HOST_MOUSE_EVT, V3_HOST_EVENT_HANDLER(mouse_event_handler), dev);
+ v3_hook_host_event(dev->vm, HOST_KEYBOARD_EVT, V3_HOST_EVENT_HANDLER(key_event_handler), dev);
+ v3_hook_host_event(dev->vm, HOST_MOUSE_EVT, V3_HOST_EVENT_HANDLER(mouse_event_handler), dev);
#if KEYBOARD_DEBUG_80H
- v3_dev_hook_io(dev, KEYBOARD_DELAY_80H, &keyboard_read_delay, &keyboard_write_delay);
+ v3_dev_hook_io(dev, KEYBOARD_DELAY_80H, &keyboard_read_delay, &keyboard_write_delay);
#endif
- //
- // We do not hook the IRQ here. Instead, the underlying device driver
- // is responsible to call us back
- //
+ //
+ // We do not hook the IRQ here. Instead, the underlying device driver
+ // is responsible to call us back
+ //
- return 0;
+ return 0;
}
static int keyboard_deinit_device(struct vm_device *dev)
{
- v3_dev_unhook_io(dev, KEYBOARD_60H);
- v3_dev_unhook_io(dev, KEYBOARD_64H);
+ v3_dev_unhook_io(dev, KEYBOARD_60H);
+ v3_dev_unhook_io(dev, KEYBOARD_64H);
#if KEYBOARD_DEBUG_80H
- v3_dev_unhook_io(dev, KEYBOARD_DELAY_80H);
+ v3_dev_unhook_io(dev, KEYBOARD_DELAY_80H);
#endif
- keyboard_reset_device(dev);
- return 0;
+ keyboard_reset_device(dev);
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = keyboard_init_device,
- .deinit = keyboard_deinit_device,
- .reset = keyboard_reset_device,
- .start = keyboard_start_device,
- .stop = keyboard_stop_device,
+ .init = keyboard_init_device,
+ .deinit = keyboard_deinit_device,
+ .reset = keyboard_reset_device,
+ .start = keyboard_start_device,
+ .stop = keyboard_stop_device,
};
struct vm_device * v3_create_keyboard() {
- struct keyboard_internal * keyboard_state = NULL;
+ struct keyboard_internal * keyboard_state = NULL;
- keyboard_state = (struct keyboard_internal *)V3_Malloc(sizeof(struct keyboard_internal));
+ keyboard_state = (struct keyboard_internal *)V3_Malloc(sizeof(struct keyboard_internal));
- struct vm_device *device = v3_create_device("KEYBOARD", &dev_ops, keyboard_state);
+ struct vm_device *device = v3_create_device("KEYBOARD", &dev_ops, keyboard_state);
- return device;
+ return device;
}
struct nvram_internal {
- nvram_state_t dev_state;
- uchar_t thereg;
- uchar_t mem_state[NVRAM_REG_MAX];
+ nvram_state_t dev_state;
+ uchar_t thereg;
+ uchar_t mem_state[NVRAM_REG_MAX];
- uint_t us; //microseconds - for clock update - zeroed every second
- uint_t pus; //microseconds - for periodic interrupt - cleared every period
+ uint_t us; //microseconds - for clock update - zeroed every second
+ uint_t pus; //microseconds - for periodic interrupt - cleared every period
};
struct rtc_stata {
- uint_t rate: 4; // clock rate = 65536Hz / 2 rate (0110=1024 Hz)
- uint_t basis: 3; // time base, 010 = 32,768 Hz
- uint_t uip: 1; // 1=update in progress
+ uint_t rate: 4; // clock rate = 65536Hz / 2 rate (0110=1024 Hz)
+ uint_t basis: 3; // time base, 010 = 32,768 Hz
+ uint_t uip: 1; // 1=update in progress
} __attribute__((__packed__)) __attribute__((__aligned__ (1))) ;
struct rtc_statb {
- uint_t sum: 1; // 1=summer (daylight savings)
- uint_t h24: 1; // 1=24h clock
- uint_t dm: 1; // 1=date/time is in bcd, 0=binary
- uint_t rec: 1; // 1=rectangular signal
- uint_t ui: 1; // 1=update interrupt
- uint_t ai: 1; // 1=alarm interrupt
- uint_t pi: 1; // 1=periodic interrupt
- uint_t set: 1; // 1=blocked update
+ uint_t sum: 1; // 1=summer (daylight savings)
+ uint_t h24: 1; // 1=24h clock
+ uint_t dm: 1; // 1=date/time is in bcd, 0=binary
+ uint_t rec: 1; // 1=rectangular signal
+ uint_t ui: 1; // 1=update interrupt
+ uint_t ai: 1; // 1=alarm interrupt
+ uint_t pi: 1; // 1=periodic interrupt
+ uint_t set: 1; // 1=blocked update
} __attribute__((__packed__)) __attribute__((__aligned__ (1))) ;
struct rtc_statc {
- uint_t res: 4; // reserved
- uint_t uf: 1; // 1=source of interrupt is update
- uint_t af: 1; // 1=source of interrupt is alarm interrupt
- uint_t pf: 1; // 1=source of interrupt is periodic interrupt
- uint_t irq: 1; // 1=interrupt requested
+ uint_t res: 4; // reserved
+ uint_t uf: 1; // 1=source of interrupt is update
+ uint_t af: 1; // 1=source of interrupt is alarm interrupt
+ uint_t pf: 1; // 1=source of interrupt is periodic interrupt
+ uint_t irq: 1; // 1=interrupt requested
} __attribute__((__packed__)) __attribute__((__aligned__ (1))) ;
struct rtc_statd {
- uint_t res: 7; // reserved
- uint_t val: 1; // 1=cmos ram data is OK
+ uint_t res: 7; // reserved
+ uint_t val: 1; // 1=cmos ram data is OK
} __attribute__((__packed__)) __attribute__((__aligned__ (1))) ;
struct bcd_num {
- uchar_t bot : 4;
- uchar_t top : 4;
+ uchar_t bot : 4;
+ uchar_t top : 4;
};
static uchar_t add_to(uchar_t * left, uchar_t * right, uchar_t bcd) {
- uchar_t temp;
+ uchar_t temp;
- if (bcd) {
- struct bcd_num * bl = (struct bcd_num *)left;
- struct bcd_num * br = (struct bcd_num *)right;
- uchar_t carry = 0;
-
- bl->bot += br->bot;
- carry = bl->bot / 0xa;
- bl->bot %= 0xa;
+ if (bcd) {
+ struct bcd_num * bl = (struct bcd_num *)left;
+ struct bcd_num * br = (struct bcd_num *)right;
+ uchar_t carry = 0;
- bl->top += carry + br->top;
- carry = bl->top / 0xa;
- bl->top %= 0xa;
+ bl->bot += br->bot;
+ carry = bl->bot / 0xa;
+ bl->bot %= 0xa;
- return carry;
- } else {
- temp = *left;
- *left += *right;
+ bl->top += carry + br->top;
+ carry = bl->top / 0xa;
+ bl->top %= 0xa;
- if (*left < temp) {
- return 1;
+ return carry;
} else {
- return 0;
+ temp = *left;
+ *left += *right;
+
+ if (*left < temp) {
+ return 1;
+ } else {
+ return 0;
+ }
}
- }
}
static uchar_t days_in_month(struct vm_device * dev, uchar_t month, uchar_t bcd) {
- // This completely ignores Julian / Gregorian stuff right now
-
- if (bcd) {
-
- switch (month)
- {
- case 0x1: //jan
- case 0x3: //march
- case 0x5: //may
- case 0x7: //july
- case 0x8: //aug
- case 0x10: //oct
- case 0x12: //dec
- return 0x31;
- break;
- case 0x4: //april
- case 0x6: //june
- case 0x9: //sept
- case 0x11: //nov
- return 0x30;
- break;
- case 0x2: //feb
- return 0x28;
- break;
- default:
- return 0x30;
- }
+ // This completely ignores Julian / Gregorian stuff right now
+
+ if (bcd) {
+
+ switch (month)
+ {
+ case 0x1: //jan
+ case 0x3: //march
+ case 0x5: //may
+ case 0x7: //july
+ case 0x8: //aug
+ case 0x10: //oct
+ case 0x12: //dec
+ return 0x31;
+ break;
+ case 0x4: //april
+ case 0x6: //june
+ case 0x9: //sept
+ case 0x11: //nov
+ return 0x30;
+ break;
+ case 0x2: //feb
+ return 0x28;
+ break;
+ default:
+ return 0x30;
+ }
- } else {
-
- switch (month)
- {
- case 1: //jan
- case 3: //march
- case 5: //may
- case 7: //july
- case 8: //aug
- case 10: //oct
- case 12: //dec
- return 31;
- break;
- case 4: //april
- case 6: //june
- case 9: //sept
- case 11: //nov
- return 30;
- break;
- case 2: //feb
- return 28;
- break;
- default:
- return 30;
- }
- }
-}
-
+ } else {
-static void update_time(struct vm_device * dev, uint_t period_us) {
- struct nvram_internal * data = (struct nvram_internal *) (dev->private_data);
- struct rtc_stata * stata = (struct rtc_stata *) &((data->mem_state[NVRAM_REG_STAT_A]));
- struct rtc_statb * statb = (struct rtc_statb *) &((data->mem_state[NVRAM_REG_STAT_B]));
- struct rtc_statc * statc = (struct rtc_statc *) &((data->mem_state[NVRAM_REG_STAT_C]));
- //struct rtc_statd *statd = (struct rtc_statd *) &((data->mem_state[NVRAM_REG_STAT_D]));
- uchar_t * sec = (uchar_t *) &(data->mem_state[NVRAM_REG_SEC]);
- uchar_t * min = (uchar_t *) &(data->mem_state[NVRAM_REG_MIN]);
- uchar_t * hour = (uchar_t *) &(data->mem_state[NVRAM_REG_HOUR]);
- uchar_t * weekday = (uchar_t *) &(data->mem_state[NVRAM_REG_WEEK_DAY]);
- uchar_t * monthday = (uchar_t *) &(data->mem_state[NVRAM_REG_MONTH_DAY]);
- uchar_t * month = (uchar_t *) &(data->mem_state[NVRAM_REG_MONTH]);
- uchar_t * year = (uchar_t *) &(data->mem_state[NVRAM_REG_YEAR]);
- uchar_t * cent = (uchar_t *) &(data->mem_state[NVRAM_REG_IBM_CENTURY_BYTE]);
- uchar_t * seca = (uchar_t *) &(data->mem_state[NVRAM_REG_SEC_ALARM]);
- uchar_t * mina = (uchar_t *) &(data->mem_state[NVRAM_REG_MIN_ALARM]);
- uchar_t * houra = (uchar_t *) &(data->mem_state[NVRAM_REG_HOUR_ALARM]);
- uchar_t hour24;
-
- uchar_t bcd = (statb->dm == 1);
- uchar_t carry = 0;
- uchar_t nextday = 0;
- uint_t periodic_period;
-
- //PrintDebug("nvram: sizeof(struct rtc_stata)=%d\n", sizeof(struct rtc_stata));
-
-
- //PrintDebug("nvram: update_time\n",statb->pi);
-
- // We will set these flags on exit
- statc->irq = 0;
- statc->pf = 0;
- statc->af = 0;
- statc->uf = 0;
-
- // We will reset us after one second
- data->us += period_us;
- // We will reset pus after one periodic_period
- data->pus += period_us;
-
- if (data->us > 1000000) {
- carry = 1;
- carry = add_to(sec, &carry, bcd);
-
- if (carry) {
- PrintDebug("nvram: somehow managed to get a carry in second update\n");
+ switch (month)
+ {
+ case 1: //jan
+ case 3: //march
+ case 5: //may
+ case 7: //july
+ case 8: //aug
+ case 10: //oct
+ case 12: //dec
+ return 31;
+ break;
+ case 4: //april
+ case 6: //june
+ case 9: //sept
+ case 11: //nov
+ return 30;
+ break;
+ case 2: //feb
+ return 28;
+ break;
+ default:
+ return 30;
+ }
}
+}
- if ( (bcd && (*sec == 0x60)) ||
- ((!bcd) && (*sec == 60))) {
-
- *sec = 0;
-
- carry = 1;
- carry = add_to(min, &carry, bcd);
- if (carry) {
- PrintDebug("nvram: somehow managed to get a carry in minute update\n");
- }
-
- if ( (bcd && (*min == 0x60)) ||
- ((!bcd) && (*min == 60))) {
- *min = 0;
- hour24 = *hour;
+static void update_time(struct vm_device * dev, uint_t period_us) {
+ struct nvram_internal * data = (struct nvram_internal *) (dev->private_data);
+ struct rtc_stata * stata = (struct rtc_stata *) &((data->mem_state[NVRAM_REG_STAT_A]));
+ struct rtc_statb * statb = (struct rtc_statb *) &((data->mem_state[NVRAM_REG_STAT_B]));
+ struct rtc_statc * statc = (struct rtc_statc *) &((data->mem_state[NVRAM_REG_STAT_C]));
+ //struct rtc_statd *statd = (struct rtc_statd *) &((data->mem_state[NVRAM_REG_STAT_D]));
+ uchar_t * sec = (uchar_t *) &(data->mem_state[NVRAM_REG_SEC]);
+ uchar_t * min = (uchar_t *) &(data->mem_state[NVRAM_REG_MIN]);
+ uchar_t * hour = (uchar_t *) &(data->mem_state[NVRAM_REG_HOUR]);
+ uchar_t * weekday = (uchar_t *) &(data->mem_state[NVRAM_REG_WEEK_DAY]);
+ uchar_t * monthday = (uchar_t *) &(data->mem_state[NVRAM_REG_MONTH_DAY]);
+ uchar_t * month = (uchar_t *) &(data->mem_state[NVRAM_REG_MONTH]);
+ uchar_t * year = (uchar_t *) &(data->mem_state[NVRAM_REG_YEAR]);
+ uchar_t * cent = (uchar_t *) &(data->mem_state[NVRAM_REG_IBM_CENTURY_BYTE]);
+ uchar_t * seca = (uchar_t *) &(data->mem_state[NVRAM_REG_SEC_ALARM]);
+ uchar_t * mina = (uchar_t *) &(data->mem_state[NVRAM_REG_MIN_ALARM]);
+ uchar_t * houra = (uchar_t *) &(data->mem_state[NVRAM_REG_HOUR_ALARM]);
+ uchar_t hour24;
+
+ uchar_t bcd = (statb->dm == 1);
+ uchar_t carry = 0;
+ uchar_t nextday = 0;
+ uint_t periodic_period;
- if (!(statb->h24)) {
+ //PrintDebug("nvram: sizeof(struct rtc_stata)=%d\n", sizeof(struct rtc_stata));
- if (hour24 & 0x80) {
- hour24 &= 0x8f;
- uchar_t temp = ((bcd) ? 0x12 : 12);
- add_to(&hour24, &temp, bcd);
- }
- }
+ //PrintDebug("nvram: update_time\n",statb->pi);
+
+ // We will set these flags on exit
+ statc->irq = 0;
+ statc->pf = 0;
+ statc->af = 0;
+ statc->uf = 0;
+
+ // We will reset us after one second
+ data->us += period_us;
+ // We will reset pus after one periodic_period
+ data->pus += period_us;
+
+ if (data->us > 1000000) {
carry = 1;
- carry = add_to(&hour24, &carry, bcd);
+ carry = add_to(sec, &carry, bcd);
+
if (carry) {
- PrintDebug("nvram: somehow managed to get a carry in hour update\n");
+ PrintDebug("nvram: somehow managed to get a carry in second update\n");
}
- if ( (bcd && (hour24 == 0x24)) ||
- ((!bcd) && (hour24 == 24))) {
- carry = 1;
- nextday = 1;
- hour24 = 0;
- } else {
- carry = 0;
- }
+ if ( (bcd && (*sec == 0x60)) ||
+ ((!bcd) && (*sec == 60))) {
+
+ *sec = 0;
+ carry = 1;
+ carry = add_to(min, &carry, bcd);
+ if (carry) {
+ PrintDebug("nvram: somehow managed to get a carry in minute update\n");
+ }
- if (statb->h24) {
- *hour = hour24;
- } else {
- if ( (bcd && (hour24 < 0x12)) ||
- ((!bcd) && (hour24 < 12))) {
- *hour = hour24;
+ if ( (bcd && (*min == 0x60)) ||
+ ((!bcd) && (*min == 60))) {
- } else {
+ *min = 0;
+ hour24 = *hour;
- if (!bcd) {
- *hour = (hour24 - 12) | 0x80;
- } else {
- *hour = hour24;
- struct bcd_num * n = (struct bcd_num *)hour;
+ if (!(statb->h24)) {
- if (n->bot < 0x2) {
- n->top--;
- n->bot += 0xa;
- }
+ if (hour24 & 0x80) {
+ hour24 &= 0x8f;
+ uchar_t temp = ((bcd) ? 0x12 : 12);
+ add_to(&hour24, &temp, bcd);
+ }
+ }
- n->bot -= 0x2;
- n->top -= 0x1;
+ carry = 1;
+ carry = add_to(&hour24, &carry, bcd);
+ if (carry) {
+ PrintDebug("nvram: somehow managed to get a carry in hour update\n");
+ }
+
+ if ( (bcd && (hour24 == 0x24)) ||
+ ((!bcd) && (hour24 == 24))) {
+ carry = 1;
+ nextday = 1;
+ hour24 = 0;
+ } else {
+ carry = 0;
+ }
+
+
+ if (statb->h24) {
+ *hour = hour24;
+ } else {
+ if ( (bcd && (hour24 < 0x12)) ||
+ ((!bcd) && (hour24 < 12))) {
+ *hour = hour24;
+
+ } else {
+
+ if (!bcd) {
+ *hour = (hour24 - 12) | 0x80;
+ } else {
+ *hour = hour24;
+ struct bcd_num * n = (struct bcd_num *)hour;
+
+ if (n->bot < 0x2) {
+ n->top--;
+ n->bot += 0xa;
+ }
+
+ n->bot -= 0x2;
+ n->top -= 0x1;
+ }
+ }
+ }
+
+ // now see if we need to carry into the days and further
+ if (nextday) {
+ carry = 1;
+ add_to(weekday, &carry, bcd);
+
+ *weekday %= 0x7; // same regardless of bcd
+
+ if ((*monthday) != days_in_month(dev, *month, bcd)) {
+ add_to(monthday, &carry, bcd);
+ } else {
+ *monthday = 0x1;
+
+ carry = 1;
+ add_to(month, &carry, bcd);
+
+ if ( (bcd && (*month == 0x13)) ||
+ ((!bcd) && (*month == 13))) {
+ *month = 1; // same for both
+
+ carry = 1;
+ carry = add_to(year, &carry, bcd);
+
+ if ( (bcd && carry) ||
+ ((!bcd) && (*year == 100))) {
+ *year = 0;
+ carry = 1;
+ add_to(cent, &carry, bcd);
+ }
+ }
+ }
+ }
}
- }
}
- // now see if we need to carry into the days and further
- if (nextday) {
- carry = 1;
- add_to(weekday, &carry, bcd);
-
- *weekday %= 0x7; // same regardless of bcd
-
- if ((*monthday) != days_in_month(dev, *month, bcd)) {
- add_to(monthday, &carry, bcd);
- } else {
- *monthday = 0x1;
-
- carry = 1;
- add_to(month, &carry, bcd);
-
- if ( (bcd && (*month == 0x13)) ||
- ((!bcd) && (*month == 13))) {
- *month = 1; // same for both
- carry = 1;
- carry = add_to(year, &carry, bcd);
-
- if ( (bcd && carry) ||
- ((!bcd) && (*year == 100))) {
- *year = 0;
- carry = 1;
- add_to(cent, &carry, bcd);
- }
+ data->us -= 1000000;
+ // OK, now check for the alarm, if it is set to interrupt
+ if (statb->ai) {
+ if ((*sec == *seca) && (*min == *mina) && (*hour == *houra)) {
+ statc->af = 1;
+ PrintDebug("nvram: interrupt on alarm\n");
}
- }
}
- }
}
-
- data->us -= 1000000;
- // OK, now check for the alarm, if it is set to interrupt
- if (statb->ai) {
- if ((*sec == *seca) && (*min == *mina) && (*hour == *houra)) {
- statc->af = 1;
- PrintDebug("nvram: interrupt on alarm\n");
- }
- }
- }
-
- if (statb->pi) {
- periodic_period = 1000000 / (65536 / (0x1 << stata->rate));
- if (data->pus >= periodic_period) {
- statc->pf = 1;
- data->pus -= periodic_period;
- PrintDebug("nvram: interrupt on periodic\n");
+ if (statb->pi) {
+ periodic_period = 1000000 / (65536 / (0x1 << stata->rate));
+ if (data->pus >= periodic_period) {
+ statc->pf = 1;
+ data->pus -= periodic_period;
+ PrintDebug("nvram: interrupt on periodic\n");
+ }
}
- }
- if (statb->ui) {
- statc->uf = 1;
- PrintDebug("nvram: interrupt on update\n");
- }
+ if (statb->ui) {
+ statc->uf = 1;
+ PrintDebug("nvram: interrupt on update\n");
+ }
- statc->irq = (statc->pf || statc->af || statc->uf);
+ statc->irq = (statc->pf || statc->af || statc->uf);
- //PrintDebug("nvram: time is now: YMDHMS: 0x%x:0x%x:0x%x:0x%x:0x%x,0x%x bcd=%d\n", *year, *month, *monthday, *hour, *min, *sec,bcd);
+ //PrintDebug("nvram: time is now: YMDHMS: 0x%x:0x%x:0x%x:0x%x:0x%x,0x%x bcd=%d\n", *year, *month, *monthday, *hour, *min, *sec,bcd);
- // Interrupt associated VM, if needed
- if (statc->irq) {
- PrintDebug("nvram: injecting interrupt\n");
- v3_raise_irq(dev->vm, NVRAM_RTC_IRQ);
- }
+ // Interrupt associated VM, if needed
+ if (statc->irq) {
+ PrintDebug("nvram: injecting interrupt\n");
+ v3_raise_irq(dev->vm, NVRAM_RTC_IRQ);
+ }
}
static int handle_timer_event(struct guest_info * info,
- struct v3_timer_event * evt,
- void * priv_data) {
+ struct v3_timer_event * evt,
+ void * priv_data) {
- struct vm_device * dev = (struct vm_device *)priv_data;
+ struct vm_device * dev = (struct vm_device *)priv_data;
- if (dev) {
- update_time(dev, evt->period_us);
- }
+ if (dev) {
+ update_time(dev, evt->period_us);
+ }
- return 0;
+ return 0;
}
static void set_memory_size(struct nvram_internal * nvram, addr_t bytes) {
- // 1. Conventional Mem: 0-640k in K
- // 2. Extended Mem: 0-16MB in K
- // 3. Big Mem: 0-4G in 64K
-
- if (bytes > 640 * 1024) {
- nvram->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = 0x02;
- nvram->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = 0x80;
- } else {
- uint16_t memk = bytes * 1024;
- nvram->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = (memk >> 8) & 0x00ff;
- nvram->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = memk & 0x00ff;
+ // 1. Conventional Mem: 0-640k in K
+ // 2. Extended Mem: 0-16MB in K
+ // 3. Big Mem: 0-4G in 64K
- return;
- }
-
- if (bytes > (16 * 1024 * 1024)) {
- // Set extended memory to 15 MB
- nvram->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = 0x3C;
- nvram->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = 0x00;
- nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= 0x3C;
- nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= 0x00;
- } else {
- uint16_t memk = bytes * 1024;
- nvram->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = (memk >> 8) & 0x00ff;
- nvram->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = memk & 0x00ff;
- nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= (memk >> 8) & 0x00ff;
- nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= memk & 0x00ff;
+ if (bytes > 640 * 1024) {
+ nvram->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = 0x02;
+ nvram->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = 0x80;
+ } else {
+ uint16_t memk = bytes * 1024;
+ nvram->mem_state[NVRAM_REG_BASE_MEMORY_HIGH] = (memk >> 8) & 0x00ff;
+ nvram->mem_state[NVRAM_REG_BASE_MEMORY_LOW] = memk & 0x00ff;
- return;
- }
+ return;
+ }
- {
- // Set the extended memory beyond 16 MB in 64k chunks
- uint16_t mem_chunks = (bytes - (1024 * 1024 * 16)) / (1024 * 64);
- nvram->mem_state[NVRAM_REG_AMI_BIG_MEMORY_HIGH] = (mem_chunks >> 8) & 0x00ff;
- nvram->mem_state[NVRAM_REG_AMI_BIG_MEMORY_LOW] = mem_chunks & 0x00ff;
- }
+ if (bytes > (16 * 1024 * 1024)) {
+ // Set extended memory to 15 MB
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = 0x3C;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = 0x00;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= 0x3C;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= 0x00;
+ } else {
+ uint16_t memk = bytes * 1024;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_HIGH] = (memk >> 8) & 0x00ff;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_LOW] = memk & 0x00ff;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_HIGH]= (memk >> 8) & 0x00ff;
+ nvram->mem_state[NVRAM_REG_EXT_MEMORY_2ND_LOW]= memk & 0x00ff;
- return;
+ return;
+ }
+
+ {
+ // Set the extended memory beyond 16 MB in 64k chunks
+ uint16_t mem_chunks = (bytes - (1024 * 1024 * 16)) / (1024 * 64);
+ nvram->mem_state[NVRAM_REG_AMI_BIG_MEMORY_HIGH] = (mem_chunks >> 8) & 0x00ff;
+ nvram->mem_state[NVRAM_REG_AMI_BIG_MEMORY_LOW] = mem_chunks & 0x00ff;
+ }
+
+ return;
}
static int init_nvram_state(struct vm_device * dev) {
- struct guest_info * info = dev->vm;
- struct nvram_internal * nvram_state = (struct nvram_internal *)dev->private_data;
+ struct guest_info * info = dev->vm;
+ struct nvram_internal * nvram_state = (struct nvram_internal *)dev->private_data;
- memset(nvram_state->mem_state, 0, NVRAM_REG_MAX);
+ memset(nvram_state->mem_state, 0, NVRAM_REG_MAX);
- //
- // 2 1.44 MB floppy drives
- //
+ //
+ // 2 1.44 MB floppy drives
+ //
#if 1
- nvram_state->mem_state[NVRAM_REG_FLOPPY_TYPE] = 0x44;
+ nvram_state->mem_state[NVRAM_REG_FLOPPY_TYPE] = 0x44;
#else
- nvram_state->mem_state[NVRAM_REG_FLOPPY_TYPE] = 0x00;
+ nvram_state->mem_state[NVRAM_REG_FLOPPY_TYPE] = 0x00;
#endif
- //
- // For old boot sequence style, do floppy first
- //
- nvram_state->mem_state[NVRAM_REG_BOOTSEQ_OLD] = 0x10;
+ //
+ // For old boot sequence style, do floppy first
+ //
+ nvram_state->mem_state[NVRAM_REG_BOOTSEQ_OLD] = 0x10;
#if 0
- // For new boot sequence style, do floppy, cd, then hd
- nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_FIRST] = 0x31;
- nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_SECOND] = 0x20;
+ // For new boot sequence style, do floppy, cd, then hd
+ nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_FIRST] = 0x31;
+ nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_SECOND] = 0x20;
#endif
- // For new boot sequence style, do cd, hd, floppy
- nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_FIRST] = 0x23;
- nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_SECOND] = 0x10;
+ // For new boot sequence style, do cd, hd, floppy
+ nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_FIRST] = 0x23;
+ nvram_state->mem_state[NVRAM_REG_BOOTSEQ_NEW_SECOND] = 0x10;
- // Set equipment byte to note 2 floppies, vga display, keyboard,math,floppy
- nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0x4f;
- // nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0xf;
+ // Set equipment byte to note 2 floppies, vga display, keyboard,math,floppy
+ nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0x4f;
+ // nvram_state->mem_state[NVRAM_REG_EQUIPMENT_BYTE] = 0xf;
- // This is the harddisk type.... Set accordingly...
- nvram_state->mem_state[NVRAM_IBM_HD_DATA] = 0x20;
+ // This is the harddisk type.... Set accordingly...
+ nvram_state->mem_state[NVRAM_IBM_HD_DATA] = 0x20;
- // Set the shutdown status gently
- // soft reset
- nvram_state->mem_state[NVRAM_REG_SHUTDOWN_STATUS] = 0x0;
+ // Set the shutdown status gently
+ // soft reset
+ nvram_state->mem_state[NVRAM_REG_SHUTDOWN_STATUS] = 0x0;
- // RTC status A
- // 00100110 = no update in progress, base=32768 Hz, rate = 1024 Hz
- nvram_state->mem_state[NVRAM_REG_STAT_A] = 0x26;
+ // RTC status A
+ // 00100110 = no update in progress, base=32768 Hz, rate = 1024 Hz
+ nvram_state->mem_state[NVRAM_REG_STAT_A] = 0x26;
- // RTC status B
- // 00000100 = not setting, no interrupts, blocked rect signal, bcd mode, 24 hour, normal time
- nvram_state->mem_state[NVRAM_REG_STAT_B] = 0x06;
+ // RTC status B
+ // 00000100 = not setting, no interrupts, blocked rect signal, bcd mode, 24 hour, normal time
+ nvram_state->mem_state[NVRAM_REG_STAT_B] = 0x06;
- // RTC status C
- // No IRQ requested, result not do to any source
- nvram_state->mem_state[NVRAM_REG_STAT_C] = 0x00;
+ // RTC status C
+ // No IRQ requested, result not do to any source
+ nvram_state->mem_state[NVRAM_REG_STAT_C] = 0x00;
- // RTC status D
- // Battery is OK
- nvram_state->mem_state[NVRAM_REG_STAT_D] = 0x80;
+ // RTC status D
+ // Battery is OK
+ nvram_state->mem_state[NVRAM_REG_STAT_D] = 0x80;
- // january 1, 2008, 00:00:00
- nvram_state->mem_state[NVRAM_REG_MONTH] = 0x1;
- nvram_state->mem_state[NVRAM_REG_MONTH_DAY] = 0x1;
- nvram_state->mem_state[NVRAM_REG_WEEK_DAY] = 0x1;
- nvram_state->mem_state[NVRAM_REG_YEAR] = 0x08;
+ // january 1, 2008, 00:00:00
+ nvram_state->mem_state[NVRAM_REG_MONTH] = 0x1;
+ nvram_state->mem_state[NVRAM_REG_MONTH_DAY] = 0x1;
+ nvram_state->mem_state[NVRAM_REG_WEEK_DAY] = 0x1;
+ nvram_state->mem_state[NVRAM_REG_YEAR] = 0x08;
- nvram_state->us = 0;
- nvram_state->pus = 0;
+ nvram_state->us = 0;
+ nvram_state->pus = 0;
- set_memory_size(nvram_state, info->mem_size);
+ set_memory_size(nvram_state, info->mem_size);
- nvram_state->dev_state = NVRAM_READY;
- nvram_state->thereg = 0;
+ nvram_state->dev_state = NVRAM_READY;
+ nvram_state->thereg = 0;
- return 0;
+ return 0;
}
static int nvram_reset_device(struct vm_device * dev) {
- return 0;
+ return 0;
}
static int nvram_start_device(struct vm_device * dev) {
- PrintDebug("nvram: start device\n");
- return 0;
+ PrintDebug("nvram: start device\n");
+ return 0;
}
static int nvram_stop_device(struct vm_device * dev) {
- PrintDebug("nvram: stop device\n");
- return 0;
+ PrintDebug("nvram: stop device\n");
+ return 0;
}
void * src,
uint_t length,
struct vm_device * dev) {
- struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
+ struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
- memcpy(&(data->thereg), src, 1);
- PrintDebug("Writing To NVRAM reg: 0x%x\n", data->thereg);
+ memcpy(&(data->thereg), src, 1);
+ PrintDebug("Writing To NVRAM reg: 0x%x\n", data->thereg);
- return 1;
+ return 1;
}
static int nvram_read_data_port(ushort_t port,
void * dst,
uint_t length,
struct vm_device * dev) {
- struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
+ struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
- memcpy(dst, &(data->mem_state[data->thereg]), 1);
+ memcpy(dst, &(data->mem_state[data->thereg]), 1);
- PrintDebug("nvram_read_data_port(0x%x)=0x%x\n", data->thereg, data->mem_state[data->thereg]);
+ PrintDebug("nvram_read_data_port(0x%x)=0x%x\n", data->thereg, data->mem_state[data->thereg]);
- // hack
- if (data->thereg == NVRAM_REG_STAT_A) {
- data->mem_state[data->thereg] ^= 0x80; // toggle Update in progess
- }
+ // hack
+ if (data->thereg == NVRAM_REG_STAT_A) {
+ data->mem_state[data->thereg] ^= 0x80; // toggle Update in progess
+ }
- return 1;
+ return 1;
}
static int nvram_write_data_port(ushort_t port,
void * src,
uint_t length,
struct vm_device * dev) {
- struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
+ struct nvram_internal * data = (struct nvram_internal *)dev->private_data;
- memcpy(&(data->mem_state[data->thereg]), src, 1);
+ memcpy(&(data->mem_state[data->thereg]), src, 1);
- PrintDebug("nvram_write_data_port(0x%x)=0x%x\n", data->thereg, data->mem_state[data->thereg]);
+ PrintDebug("nvram_write_data_port(0x%x)=0x%x\n", data->thereg, data->mem_state[data->thereg]);
- return 1;
+ return 1;
}
static int nvram_init_device(struct vm_device * dev) {
- PrintDebug("nvram: init_device\n");
+ PrintDebug("nvram: init_device\n");
- init_nvram_state(dev);
+ init_nvram_state(dev);
- // hook ports
- v3_dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port);
- v3_dev_hook_io(dev, NVRAM_DATA_PORT, &nvram_read_data_port, &nvram_write_data_port);
+ // hook ports
+ v3_dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port);
+ v3_dev_hook_io(dev, NVRAM_DATA_PORT, &nvram_read_data_port, &nvram_write_data_port);
- v3_hook_host_event(dev->vm, HOST_TIMER_EVT, V3_HOST_EVENT_HANDLER(handle_timer_event), dev);
+ v3_hook_host_event(dev->vm, HOST_TIMER_EVT, V3_HOST_EVENT_HANDLER(handle_timer_event), dev);
- return 0;
+ return 0;
}
static int nvram_deinit_device(struct vm_device * dev) {
- v3_dev_unhook_io(dev, NVRAM_REG_PORT);
- v3_dev_unhook_io(dev, NVRAM_DATA_PORT);
+ v3_dev_unhook_io(dev, NVRAM_REG_PORT);
+ v3_dev_unhook_io(dev, NVRAM_DATA_PORT);
- nvram_reset_device(dev);
- return 0;
+ nvram_reset_device(dev);
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = nvram_init_device,
- .deinit = nvram_deinit_device,
- .reset = nvram_reset_device,
- .start = nvram_start_device,
- .stop = nvram_stop_device,
+ .init = nvram_init_device,
+ .deinit = nvram_deinit_device,
+ .reset = nvram_reset_device,
+ .start = nvram_start_device,
+ .stop = nvram_stop_device,
};
struct vm_device * v3_create_nvram() {
- struct nvram_internal * nvram_state = NULL;
+ struct nvram_internal * nvram_state = NULL;
- nvram_state = (struct nvram_internal *)V3_Malloc(sizeof(struct nvram_internal) + 1000);
+ nvram_state = (struct nvram_internal *)V3_Malloc(sizeof(struct nvram_internal) + 1000);
- PrintDebug("nvram: internal at %p\n", (void *)nvram_state);
+ PrintDebug("nvram: internal at %p\n", (void *)nvram_state);
- struct vm_device * device = v3_create_device("NVRAM", &dev_ops, nvram_state);
+ struct vm_device * device = v3_create_device("NVRAM", &dev_ops, nvram_state);
- return device;
+ return device;
}
struct debug_state {
- char debug_buf[BUF_SIZE];
- uint_t debug_offset;
+ char debug_buf[BUF_SIZE];
+ uint_t debug_offset;
};
static int handle_gen_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct debug_state * state = (struct debug_state *)dev->private_data;
+ struct debug_state * state = (struct debug_state *)dev->private_data;
- state->debug_buf[state->debug_offset++] = *(char*)src;
+ state->debug_buf[state->debug_offset++] = *(char*)src;
- if ((*(char*)src == 0xa) || (state->debug_offset == (BUF_SIZE - 1))) {
- PrintDebug("VM_CONSOLE>%s", state->debug_buf);
- memset(state->debug_buf, 0, BUF_SIZE);
- state->debug_offset = 0;
- }
+ if ((*(char*)src == 0xa) || (state->debug_offset == (BUF_SIZE - 1))) {
+ PrintDebug("VM_CONSOLE>%s", state->debug_buf);
+ memset(state->debug_buf, 0, BUF_SIZE);
+ state->debug_offset = 0;
+ }
- return length;
+ return length;
}
static int debug_init(struct vm_device * dev) {
- struct debug_state * state = (struct debug_state *)dev->private_data;
+ struct debug_state * state = (struct debug_state *)dev->private_data;
- v3_dev_hook_io(dev, DEBUG_PORT1, NULL, &handle_gen_write);
+ v3_dev_hook_io(dev, DEBUG_PORT1, NULL, &handle_gen_write);
- state->debug_offset = 0;
- memset(state->debug_buf, 0, BUF_SIZE);
+ state->debug_offset = 0;
+ memset(state->debug_buf, 0, BUF_SIZE);
- return 0;
+ return 0;
}
static int debug_deinit(struct vm_device * dev) {
- v3_dev_unhook_io(dev, DEBUG_PORT1);
+ v3_dev_unhook_io(dev, DEBUG_PORT1);
- return 0;
+ return 0;
};
static struct vm_device_ops dev_ops = {
- .init = debug_init,
- .deinit = debug_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = debug_init,
+ .deinit = debug_deinit,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_os_debug() {
- struct debug_state * state = NULL;
+ struct debug_state * state = NULL;
- state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
+ state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
- PrintDebug("Creating OS Debug Device\n");
- struct vm_device * device = v3_create_device("OS Debug", &dev_ops, state);
+ PrintDebug("Creating OS Debug Device\n");
+ struct vm_device * device = v3_create_device("OS Debug", &dev_ops, state);
- return device;
+ return device;
}
static inline const char * device_type_to_str(device_type_t type) {
- switch (type) {
- case IDE_DISK:
- return harddisk_str;
- case IDE_CDROM:
- return cdrom_str;
- case IDE_NONE:
- return none_str;
- default:
- return NULL;
- }
+ switch (type) {
+ case IDE_DISK:
+ return harddisk_str;
+ case IDE_CDROM:
+ return cdrom_str;
+ case IDE_NONE:
+ return none_str;
+ default:
+ return NULL;
+ }
}
static inline void write_features(struct channel_t * channel, uchar_t value) {
- channel->drives[0].controller.features = value;
- channel->drives[1].controller.features = value;
+ channel->drives[0].controller.features = value;
+ channel->drives[1].controller.features = value;
}
static inline void write_sector_count(struct channel_t * channel, uchar_t value) {
- channel->drives[0].controller.sector_count = value;
- channel->drives[1].controller.sector_count = value;
+ channel->drives[0].controller.sector_count = value;
+ channel->drives[1].controller.sector_count = value;
}
static inline void write_sector_number(struct channel_t * channel, uchar_t value) {
- channel->drives[0].controller.sector_no = value;
- channel->drives[1].controller.sector_no = value;
+ channel->drives[0].controller.sector_no = value;
+ channel->drives[1].controller.sector_no = value;
}
static inline void write_cylinder_low(struct channel_t * channel, uchar_t value) {
- channel->drives[0].controller.cylinder_no &= 0xff00;
- channel->drives[0].controller.cylinder_no |= value;
- channel->drives[1].controller.cylinder_no &= 0xff00;
- channel->drives[1].controller.cylinder_no |= value;
+ channel->drives[0].controller.cylinder_no &= 0xff00;
+ channel->drives[0].controller.cylinder_no |= value;
+ channel->drives[1].controller.cylinder_no &= 0xff00;
+ channel->drives[1].controller.cylinder_no |= value;
}
static inline void write_cylinder_high(struct channel_t * channel, uchar_t value) {
- ushort_t val2 = value;
- val2 = val2 << 8;
- channel->drives[0].controller.cylinder_no &= 0x00ff;
- channel->drives[0].controller.cylinder_no |= (val2 & 0xff00);
+ ushort_t val2 = value;
+ val2 = val2 << 8;
+ channel->drives[0].controller.cylinder_no &= 0x00ff;
+ channel->drives[0].controller.cylinder_no |= (val2 & 0xff00);
- channel->drives[1].controller.cylinder_no &= 0x00ff;
- channel->drives[1].controller.cylinder_no |= (val2 & 0xff00);
+ channel->drives[1].controller.cylinder_no &= 0x00ff;
+ channel->drives[1].controller.cylinder_no |= (val2 & 0xff00);
}
static inline void write_head_no(struct channel_t * channel, uchar_t value) {
- channel->drives[0].controller.head_no = value;
- channel->drives[1].controller.head_no = value;
+ channel->drives[0].controller.head_no = value;
+ channel->drives[1].controller.head_no = value;
}
static inline void write_lba_mode(struct channel_t * channel, uchar_t value) {
- channel->drives[0].controller.lba_mode = value;
- channel->drives[1].controller.lba_mode = value;
+ channel->drives[0].controller.lba_mode = value;
+ channel->drives[1].controller.lba_mode = value;
}
static inline uint_t get_channel_no(struct ramdisk_t * ramdisk, struct channel_t * channel) {
- return (((uchar_t *)channel - (uchar_t *)(ramdisk->channels)) / sizeof(struct channel_t));
+ return (((uchar_t *)channel - (uchar_t *)(ramdisk->channels)) / sizeof(struct channel_t));
}
static inline uint_t get_drive_no(struct channel_t * channel, struct drive_t * drive) {
- return (((uchar_t *)drive - (uchar_t*)(channel->drives)) / sizeof(struct drive_t));
+ return (((uchar_t *)drive - (uchar_t*)(channel->drives)) / sizeof(struct drive_t));
}
static inline struct drive_t * get_selected_drive(struct channel_t * channel) {
- return &(channel->drives[channel->drive_select]);
+ return &(channel->drives[channel->drive_select]);
}
static inline int is_primary_port(struct ramdisk_t * ramdisk, ushort_t port) {
- switch(port)
- {
- case PRI_DATA_PORT:
- case PRI_FEATURES_PORT:
- case PRI_SECT_CNT_PORT:
- case PRI_SECT_ADDR1_PORT:
- case PRI_SECT_ADDR2_PORT:
- case PRI_SECT_ADDR3_PORT:
- case PRI_DRV_SEL_PORT:
- case PRI_CMD_PORT:
- case PRI_CTRL_PORT:
- return 1;
- default:
- return 0;
- }
+ switch(port)
+ {
+ case PRI_DATA_PORT:
+ case PRI_FEATURES_PORT:
+ case PRI_SECT_CNT_PORT:
+ case PRI_SECT_ADDR1_PORT:
+ case PRI_SECT_ADDR2_PORT:
+ case PRI_SECT_ADDR3_PORT:
+ case PRI_DRV_SEL_PORT:
+ case PRI_CMD_PORT:
+ case PRI_CTRL_PORT:
+ return 1;
+ default:
+ return 0;
+ }
}
static inline int is_secondary_port(struct ramdisk_t * ramdisk, ushort_t port) {
- switch(port)
- {
- case SEC_DATA_PORT:
- case SEC_FEATURES_PORT:
- case SEC_SECT_CNT_PORT:
- case SEC_SECT_ADDR1_PORT:
- case SEC_SECT_ADDR2_PORT:
- case SEC_SECT_ADDR3_PORT:
- case SEC_DRV_SEL_PORT:
- case SEC_CMD_PORT:
- case SEC_CTRL_PORT:
- return 1;
- default:
- return 0;
- }
+ switch(port)
+ {
+ case SEC_DATA_PORT:
+ case SEC_FEATURES_PORT:
+ case SEC_SECT_CNT_PORT:
+ case SEC_SECT_ADDR1_PORT:
+ case SEC_SECT_ADDR2_PORT:
+ case SEC_SECT_ADDR3_PORT:
+ case SEC_DRV_SEL_PORT:
+ case SEC_CMD_PORT:
+ case SEC_CTRL_PORT:
+ return 1;
+ default:
+ return 0;
+ }
}
static inline int num_drives_on_channel(struct channel_t * channel) {
- if ((channel->drives[0].device_type == IDE_NONE) &&
- (channel->drives[1].device_type == IDE_NONE)) {
- return 0;
- } else if ((channel->drives[0].device_type != IDE_NONE) &&
- (channel->drives[1].device_type != IDE_NONE)) {
- return 2;
- } else {
- return 1;
- }
+ if ((channel->drives[0].device_type == IDE_NONE) &&
+ (channel->drives[1].device_type == IDE_NONE)) {
+ return 0;
+ } else if ((channel->drives[0].device_type != IDE_NONE) &&
+ (channel->drives[1].device_type != IDE_NONE)) {
+ return 2;
+ } else {
+ return 1;
+ }
}
static inline uchar_t extract_bits(uchar_t * buf, uint_t buf_offset, uint_t bit_offset, uint_t num_bits) {
- uchar_t val = buf[buf_offset];
- val = val >> bit_offset;
- val &= ((1 << num_bits) -1);
- return val;
+ uchar_t val = buf[buf_offset];
+ val = val >> bit_offset;
+ val &= ((1 << num_bits) -1);
+ return val;
}
static inline uchar_t get_packet_field(struct channel_t * channel, uint_t packet_offset, uint_t bit_offset, uint_t num_bits) {
- struct drive_t * drive = get_selected_drive(channel);
- return extract_bits(drive->controller.buffer, packet_offset, bit_offset, num_bits);
+ struct drive_t * drive = get_selected_drive(channel);
+ return extract_bits(drive->controller.buffer, packet_offset, bit_offset, num_bits);
}
static inline uchar_t get_packet_byte(struct channel_t * channel, uint_t offset) {
- struct drive_t * drive = get_selected_drive(channel);
- return drive->controller.buffer[offset];
+ struct drive_t * drive = get_selected_drive(channel);
+ return drive->controller.buffer[offset];
}
static inline uint16_t get_packet_word(struct channel_t * channel, uint_t offset) {
- struct drive_t * drive = get_selected_drive(channel);
- uint16_t val = drive->controller.buffer[offset];
- val = val << 8;
- val |= drive->controller.buffer[offset + 1];
- return val;
+ struct drive_t * drive = get_selected_drive(channel);
+ uint16_t val = drive->controller.buffer[offset];
+ val = val << 8;
+ val |= drive->controller.buffer[offset + 1];
+ return val;
}
static inline uint16_t rd_read_16bit(const uint8_t* buf) {
- return (buf[0] << 8) | buf[1];
+ return (buf[0] << 8) | buf[1];
}
static inline uint32_t rd_read_32bit(const uint8_t* buf) {
- return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
}
////////////////////////////////////////////////////////////////////////////
int v3_ramdisk_register_cdrom(struct vm_device * dev, uint_t busID, uint_t driveID, struct cdrom_ops* cd, void * private_data) {
- struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct channel_t * channel = &(ramdisk->channels[busID]);
- struct drive_t * drive = &(channel->drives[driveID]);
- struct controller_t * controller = &(drive->controller);
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct channel_t * channel = &(ramdisk->channels[busID]);
+ struct drive_t * drive = &(channel->drives[driveID]);
+ struct controller_t * controller = &(drive->controller);
- if (drive->device_type != IDE_NONE) {
- PrintError("Device already registered at this location\n");
- return -1;
- }
+ if (drive->device_type != IDE_NONE) {
+ PrintError("Device already registered at this location\n");
+ return -1;
+ }
- channel->irq = 15;
+ channel->irq = 15;
- // Make model string
- strncpy((char*)(drive->model_no), "V3VEE Ramdisk", 40);
+ // Make model string
+ strncpy((char*)(drive->model_no), "V3VEE Ramdisk", 40);
- while (strlen((char *)(drive->model_no)) < 40) {
- strcat ((char*)(drive->model_no), " ");
- }
+ while (strlen((char *)(drive->model_no)) < 40) {
+ strcat ((char*)(drive->model_no), " ");
+ }
- PrintDebug("CDROM on target %d/%d\n", busID, driveID);
+ PrintDebug("CDROM on target %d/%d\n", busID, driveID);
- drive->device_type = IDE_CDROM;
- drive->cdrom.locked = 0;
- drive->sense.sense_key = SENSE_NONE;
- drive->sense.asc = 0;
- drive->sense.ascq = 0;
+ drive->device_type = IDE_CDROM;
+ drive->cdrom.locked = 0;
+ drive->sense.sense_key = SENSE_NONE;
+ drive->sense.asc = 0;
+ drive->sense.ascq = 0;
- drive->private_data = private_data;
+ drive->private_data = private_data;
#ifdef DEBUG_RAMDISK
- if (check_bit_fields(controller) == INTR_REASON_BIT_ERR) {
- PrintError("interrupt reason: bit field error\n");
- return INTR_REASON_BIT_ERR;
- }
+ if (check_bit_fields(controller) == INTR_REASON_BIT_ERR) {
+ PrintError("interrupt reason: bit field error\n");
+ return INTR_REASON_BIT_ERR;
+ }
#endif
- controller->sector_count = 0;
+ controller->sector_count = 0;
- drive->cdrom.cd = cd;
+ drive->cdrom.cd = cd;
- PrintDebug("\t\tCD on ata%d-%d: '%s'\n",
- busID,
- driveID, "");
+ PrintDebug("\t\tCD on ata%d-%d: '%s'\n",
+ busID,
+ driveID, "");
- if(drive->cdrom.cd->insert_cdrom(drive->private_data)) {
- PrintDebug("\t\tMedia present in CD-ROM drive\n");
- drive->cdrom.ready = 1;
- drive->cdrom.capacity = drive->cdrom.cd->capacity(drive->private_data);
- PrintDebug("\t\tCDROM capacity is %d\n", drive->cdrom.capacity);
- } else {
- PrintDebug("\t\tCould not locate CD-ROM, continuing with media not present\n");
- drive->cdrom.ready = 0;
- }
+ if(drive->cdrom.cd->insert_cdrom(drive->private_data)) {
+ PrintDebug("\t\tMedia present in CD-ROM drive\n");
+ drive->cdrom.ready = 1;
+ drive->cdrom.capacity = drive->cdrom.cd->capacity(drive->private_data);
+ PrintDebug("\t\tCDROM capacity is %d\n", drive->cdrom.capacity);
+ } else {
+ PrintDebug("\t\tCould not locate CD-ROM, continuing with media not present\n");
+ drive->cdrom.ready = 0;
+ }
- return 0;
+ return 0;
}
static Bit32u rd_init_hardware(struct ramdisk_t *ramdisk) {
- uint_t channel_num;
- uint_t device;
- struct channel_t *channels = (struct channel_t *)(&(ramdisk->channels));
+ uint_t channel_num;
+ uint_t device;
+ struct channel_t *channels = (struct channel_t *)(&(ramdisk->channels));
- PrintDebug("[rd_init_harddrive]\n");
+ PrintDebug("[rd_init_harddrive]\n");
- for (channel_num = 0; channel_num < MAX_ATA_CHANNEL; channel_num++) {
- memset((char *)(channels + channel_num), 0, sizeof(struct channel_t));
- }
+ for (channel_num = 0; channel_num < MAX_ATA_CHANNEL; channel_num++) {
+ memset((char *)(channels + channel_num), 0, sizeof(struct channel_t));
+ }
- for (channel_num = 0; channel_num < MAX_ATA_CHANNEL; channel_num++){
- struct channel_t * channel = &(channels[channel_num]);
-
- channel->ioaddr1 = 0x0;
- channel->ioaddr2 = 0x0;
- channel->irq = 0;
-
- for (device = 0; device < 2; device++){
- struct drive_t * drive = &(channel->drives[device]);
- struct controller_t * controller = &(drive->controller);
-
- controller->status.busy = 0;
- controller->status.drive_ready = 1;
- controller->status.write_fault = 0;
- controller->status.seek_complete = 1;
- controller->status.drq = 0;
- controller->status.corrected_data = 0;
- controller->status.index_pulse = 0;
- controller->status.index_pulse_count = 0;
- controller->status.err = 0;
-
- controller->error_register = 0x01; // diagnostic code: no error
- controller->head_no = 0;
- controller->sector_count = 1;
- controller->sector_no = 1;
- controller->cylinder_no = 0;
- controller->current_command = 0x00;
- controller->buffer_index = 0;
-
- controller->control.reset = 0;
- controller->control.disable_irq = 0;
- controller->reset_in_progress = 0;
-
- controller->sectors_per_block = 0x80;
- controller->lba_mode = 0;
+ for (channel_num = 0; channel_num < MAX_ATA_CHANNEL; channel_num++){
+ struct channel_t * channel = &(channels[channel_num]);
+
+ channel->ioaddr1 = 0x0;
+ channel->ioaddr2 = 0x0;
+ channel->irq = 0;
+
+ for (device = 0; device < 2; device++){
+ struct drive_t * drive = &(channel->drives[device]);
+ struct controller_t * controller = &(drive->controller);
+
+ controller->status.busy = 0;
+ controller->status.drive_ready = 1;
+ controller->status.write_fault = 0;
+ controller->status.seek_complete = 1;
+ controller->status.drq = 0;
+ controller->status.corrected_data = 0;
+ controller->status.index_pulse = 0;
+ controller->status.index_pulse_count = 0;
+ controller->status.err = 0;
+
+ controller->error_register = 0x01; // diagnostic code: no error
+ controller->head_no = 0;
+ controller->sector_count = 1;
+ controller->sector_no = 1;
+ controller->cylinder_no = 0;
+ controller->current_command = 0x00;
+ controller->buffer_index = 0;
+
+ controller->control.reset = 0;
+ controller->control.disable_irq = 0;
+ controller->reset_in_progress = 0;
+
+ controller->sectors_per_block = 0x80;
+ controller->lba_mode = 0;
- controller->features = 0;
+ controller->features = 0;
- // If not present
- drive->device_type = IDE_NONE;
+ // If not present
+ drive->device_type = IDE_NONE;
- // Make model string
- strncpy((char*)(drive->model_no), "", 40);
- while(strlen((char *)(drive->model_no)) < 40) {
- strcat ((char*)(drive->model_no), " ");
- }
+ // Make model string
+ strncpy((char*)(drive->model_no), "", 40);
+ while(strlen((char *)(drive->model_no)) < 40) {
+ strcat ((char*)(drive->model_no), " ");
+ }
- }//for device
- }//for channel
+ }//for device
+ }//for channel
#ifdef DEBUG_RAMDISK
- rd_print_state(ramdisk);
+ rd_print_state(ramdisk);
#endif
- return 0;
+ return 0;
}
*/
static void rd_close_harddrive(struct ramdisk_t *ramdisk) {
- return;
+ return;
}
static int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct channel_t * channel = NULL;
- struct drive_t * drive = NULL;
- struct controller_t * controller = NULL;
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct channel_t * channel = NULL;
+ struct drive_t * drive = NULL;
+ struct controller_t * controller = NULL;
- if (is_primary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[0]);
- } else if (is_secondary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[1]);
- } else {
- PrintError("Invalid Port: %d\n", port);
- return -1;
- }
+ if (is_primary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[0]);
+ } else if (is_secondary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[1]);
+ } else {
+ PrintError("Invalid Port: %d\n", port);
+ return -1;
+ }
- drive = get_selected_drive(channel);
- controller = &(drive->controller);
+ drive = get_selected_drive(channel);
+ controller = &(drive->controller);
- PrintTrace("[read_data_handler] IO Read at 0x%x, on drive %d/%d current cmd=0x%x\n",
- port,
- get_channel_no(ramdisk, channel),
- get_drive_no(channel, drive),
- controller->current_command);
+ PrintTrace("[read_data_handler] IO Read at 0x%x, on drive %d/%d current cmd=0x%x\n",
+ port,
+ get_channel_no(ramdisk, channel),
+ get_drive_no(channel, drive),
+ controller->current_command);
- switch (controller->current_command) {
- case 0xec: // IDENTIFY DEVICE
- case 0xa1:
- {
+ switch (controller->current_command) {
+ case 0xec: // IDENTIFY DEVICE
+ case 0xa1:
+ {
- controller->status.busy = 0;
- controller->status.drive_ready = 1;
- controller->status.write_fault = 0;
- controller->status.seek_complete = 1;
- controller->status.corrected_data = 0;
- controller->status.err = 0;
+ controller->status.busy = 0;
+ controller->status.drive_ready = 1;
+ controller->status.write_fault = 0;
+ controller->status.seek_complete = 1;
+ controller->status.corrected_data = 0;
+ controller->status.err = 0;
- /*
- value32 = controller->buffer[index];
- index++;
+ /*
+ value32 = controller->buffer[index];
+ index++;
- if (io_len >= 2) {
- value32 |= (controller->buffer[index] << 8);
- index++;
- }
+ if (io_len >= 2) {
+ value32 |= (controller->buffer[index] << 8);
+ index++;
+ }
- if (io_len == 4) {
- value32 |= (controller->buffer[index] << 16);
- value32 |= (controller->buffer[index+1] << 24);
- index += 2;
- }
+ if (io_len == 4) {
+ value32 |= (controller->buffer[index] << 16);
+ value32 |= (controller->buffer[index+1] << 24);
+ index += 2;
+ }
- controller->buffer_index = index;
- */
- /* JRL */
- memcpy(dst, controller->buffer + controller->buffer_index, length);
- controller->buffer_index += length;
+ controller->buffer_index = index;
+ */
+ /* JRL */
+ memcpy(dst, controller->buffer + controller->buffer_index, length);
+ controller->buffer_index += length;
- if (controller->buffer_index >= 512) {
- controller->status.drq = 0;
- }
+ if (controller->buffer_index >= 512) {
+ controller->status.drq = 0;
+ }
- return length;
- }
- case 0xa0: //send packet cmd
- {
- uint_t index = controller->buffer_index;
+ return length;
+ }
+ case 0xa0: //send packet cmd
+ {
+ uint_t index = controller->buffer_index;
- PrintTrace("\t\tatapi.command(%02x), index(%d), cdrom.remaining_blocks(%d)\n",
- drive->atapi.command,
- index,
- drive->cdrom.remaining_blocks);
+ PrintTrace("\t\tatapi.command(%02x), index(%d), cdrom.remaining_blocks(%d)\n",
+ drive->atapi.command,
+ index,
+ drive->cdrom.remaining_blocks);
- // Load block if necessary
- if (index >= 2048) {
+ // Load block if necessary
+ if (index >= 2048) {
- if (index > 2048) {
- PrintError("\t\tindex > 2048 : 0x%x\n", index);
- return -1;
- }
+ if (index > 2048) {
+ PrintError("\t\tindex > 2048 : 0x%x\n", index);
+ return -1;
+ }
- switch (drive->atapi.command) {
- case 0x28: // read (10)
- case 0xa8: // read (12)
- {
+ switch (drive->atapi.command) {
+ case 0x28: // read (10)
+ case 0xa8: // read (12)
+ {
- if (!(drive->cdrom.ready)) {
- PrintError("\t\tRead with CDROM not ready\n");
- return -1;
- }
+ if (!(drive->cdrom.ready)) {
+ PrintError("\t\tRead with CDROM not ready\n");
+ return -1;
+ }
- drive->cdrom.cd->read_block(drive->private_data, controller->buffer,
- drive->cdrom.next_lba);
- drive->cdrom.next_lba++;
- drive->cdrom.remaining_blocks--;
+ drive->cdrom.cd->read_block(drive->private_data, controller->buffer,
+ drive->cdrom.next_lba);
+ drive->cdrom.next_lba++;
+ drive->cdrom.remaining_blocks--;
- if (!(drive->cdrom.remaining_blocks)) {
- PrintDebug("\t\tLast READ block loaded {CDROM}\n");
- } else {
- PrintDebug("\t\tREAD block loaded (%d remaining) {CDROM}\n",
- drive->cdrom.remaining_blocks);
- }
+ if (!(drive->cdrom.remaining_blocks)) {
+ PrintDebug("\t\tLast READ block loaded {CDROM}\n");
+ } else {
+ PrintDebug("\t\tREAD block loaded (%d remaining) {CDROM}\n",
+ drive->cdrom.remaining_blocks);
+ }
- // one block transfered, start at beginning
- index = 0;
- break;
- }
- default: // no need to load a new block
- break;
- }
- }
+ // one block transfered, start at beginning
+ index = 0;
+ break;
+ }
+ default: // no need to load a new block
+ break;
+ }
+ }
- /*
- increment = 0;
- value32 = controller->buffer[index + increment];
- increment++;
+ /*
+ increment = 0;
+ value32 = controller->buffer[index + increment];
+ increment++;
- if (io_len >= 2) {
- value32 |= (controller->buffer[index + increment] << 8);
- increment++;
- }
+ if (io_len >= 2) {
+ value32 |= (controller->buffer[index + increment] << 8);
+ increment++;
+ }
- if (io_len == 4) {
- value32 |= (controller->buffer[index + increment] << 16);
- value32 |= (controller->buffer[index + increment + 1] << 24);
- increment += 2;
- }
-
- controller->buffer_index = index + increment;
- controller->drq_index += increment;
-
- */
- /* JRL: CHECK THAT there is enough data in the buffer to copy.... */
- {
- memcpy(dst, controller->buffer + index, length);
+ if (io_len == 4) {
+ value32 |= (controller->buffer[index + increment] << 16);
+ value32 |= (controller->buffer[index + increment + 1] << 24);
+ increment += 2;
+ }
+
+ controller->buffer_index = index + increment;
+ controller->drq_index += increment;
+
+ */
+ /* JRL: CHECK THAT there is enough data in the buffer to copy.... */
+ {
+ memcpy(dst, controller->buffer + index, length);
- controller->buffer_index = index + length;
- controller->drq_index += length;
- }
+ controller->buffer_index = index + length;
+ controller->drq_index += length;
+ }
- /* *** */
+ /* *** */
- if (controller->drq_index >= (unsigned)drive->atapi.drq_bytes) {
- controller->status.drq = 0;
- controller->drq_index = 0;
+ if (controller->drq_index >= (unsigned)drive->atapi.drq_bytes) {
+ controller->status.drq = 0;
+ controller->drq_index = 0;
- drive->atapi.total_bytes_remaining -= drive->atapi.drq_bytes;
+ drive->atapi.total_bytes_remaining -= drive->atapi.drq_bytes;
- if (drive->atapi.total_bytes_remaining > 0) {
- // one or more blocks remaining (works only for single block commands)
+ if (drive->atapi.total_bytes_remaining > 0) {
+ // one or more blocks remaining (works only for single block commands)
- PrintDebug("\t\tPACKET drq bytes read\n");
- controller->interrupt_reason.i_o = 1;
- controller->status.busy = 0;
- controller->status.drq = 1;
- controller->interrupt_reason.c_d = 0;
+ PrintDebug("\t\tPACKET drq bytes read\n");
+ controller->interrupt_reason.i_o = 1;
+ controller->status.busy = 0;
+ controller->status.drq = 1;
+ controller->interrupt_reason.c_d = 0;
- // set new byte count if last block
- if (drive->atapi.total_bytes_remaining < controller->byte_count) {
- controller->byte_count = drive->atapi.total_bytes_remaining;
- }
- drive->atapi.drq_bytes = controller->byte_count;
+ // set new byte count if last block
+ if (drive->atapi.total_bytes_remaining < controller->byte_count) {
+ controller->byte_count = drive->atapi.total_bytes_remaining;
+ }
+ drive->atapi.drq_bytes = controller->byte_count;
- rd_raise_interrupt(dev, channel);
- } else {
- // all bytes read
- PrintDebug("\t\tPACKET all bytes read\n");
+ rd_raise_interrupt(dev, channel);
+ } else {
+ // all bytes read
+ PrintDebug("\t\tPACKET all bytes read\n");
- controller->interrupt_reason.i_o = 1;
- controller->interrupt_reason.c_d = 1;
- controller->status.drive_ready = 1;
- controller->interrupt_reason.rel = 0;
- controller->status.busy = 0;
- controller->status.drq = 0;
- controller->status.err = 0;
+ controller->interrupt_reason.i_o = 1;
+ controller->interrupt_reason.c_d = 1;
+ controller->status.drive_ready = 1;
+ controller->interrupt_reason.rel = 0;
+ controller->status.busy = 0;
+ controller->status.drq = 0;
+ controller->status.err = 0;
- rd_raise_interrupt(dev, channel);
- }
- }
- return length;
- break;
- }
+ rd_raise_interrupt(dev, channel);
+ }
+ }
+ return length;
+ break;
+ }
- default:
- PrintError("\t\tunsupported command: %02x\n", controller->current_command);
- break;
- }
+ default:
+ PrintError("\t\tunsupported command: %02x\n", controller->current_command);
+ break;
+ }
- return -1;
+ return -1;
}
static int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct channel_t * channel = NULL;
- struct drive_t * drive = NULL;
- struct controller_t * controller = NULL;
-
- if (is_primary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[0]);
- } else if (is_secondary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[1]);
- } else {
- PrintError("Invalid Port: %d\n", port);
- return -1;
- }
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct channel_t * channel = NULL;
+ struct drive_t * drive = NULL;
+ struct controller_t * controller = NULL;
+
+ if (is_primary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[0]);
+ } else if (is_secondary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[1]);
+ } else {
+ PrintError("Invalid Port: %d\n", port);
+ return -1;
+ }
- drive = get_selected_drive(channel);
- controller = &(drive->controller);
+ drive = get_selected_drive(channel);
+ controller = &(drive->controller);
- PrintDebug("[write_data_handler] IO write at 0x%x, current_cmd = 0x%02x\n",
- port, controller->current_command);
+ PrintDebug("[write_data_handler] IO write at 0x%x, current_cmd = 0x%02x\n",
+ port, controller->current_command);
- //PrintDebug("[write_data_handler]\n");
- switch (controller->current_command) {
- case 0x30: // WRITE SECTORS
- PrintError("\t\tneed to implement 0x30(write sector) to port 0x%x\n", port);
- return -1;
+ //PrintDebug("[write_data_handler]\n");
+ switch (controller->current_command) {
+ case 0x30: // WRITE SECTORS
+ PrintError("\t\tneed to implement 0x30(write sector) to port 0x%x\n", port);
+ return -1;
- case 0xa0: // PACKET
+ case 0xa0: // PACKET
- if (handle_atapi_packet_command(dev, channel, *(ushort_t *)src) == -1) {
- PrintError("Error sending atapi packet command in PACKET write to data port\n");
- return -1;
- }
+ if (handle_atapi_packet_command(dev, channel, *(ushort_t *)src) == -1) {
+ PrintError("Error sending atapi packet command in PACKET write to data port\n");
+ return -1;
+ }
- return length;
+ return length;
- default:
- PrintError("\t\tIO write(0x%x): current command is %02xh\n",
- port, controller->current_command);
+ default:
+ PrintError("\t\tIO write(0x%x): current command is %02xh\n",
+ port, controller->current_command);
- return -1;
- }
+ return -1;
+ }
- return -1;
+ return -1;
}
static int read_status_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct channel_t * channel = NULL;
- struct drive_t * drive = NULL;
- struct controller_t * controller = NULL;
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct channel_t * channel = NULL;
+ struct drive_t * drive = NULL;
+ struct controller_t * controller = NULL;
- if (is_primary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[0]);
- } else if (is_secondary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[1]);
- } else {
- PrintError("Invalid Port: %d\n", port);
- return -1;
- }
+ if (is_primary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[0]);
+ } else if (is_secondary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[1]);
+ } else {
+ PrintError("Invalid Port: %d\n", port);
+ return -1;
+ }
- drive = get_selected_drive(channel);
- controller = &(drive->controller);
+ drive = get_selected_drive(channel);
+ controller = &(drive->controller);
- PrintDebug("[read_status_handler] IO read at 0x%x, on drive %d/%d\n",
- port, get_channel_no(ramdisk, channel),
- channel->drive_select);
+ PrintDebug("[read_status_handler] IO read at 0x%x, on drive %d/%d\n",
+ port, get_channel_no(ramdisk, channel),
+ channel->drive_select);
- if (num_drives_on_channel(channel) == 0) {
- PrintDebug("Setting value to zero because 0 devices on channel\n");
- // (mch) Just return zero for these registers
- memset(dst, 0, length);
+ if (num_drives_on_channel(channel) == 0) {
+ PrintDebug("Setting value to zero because 0 devices on channel\n");
+ // (mch) Just return zero for these registers
+ memset(dst, 0, length);
- } else {
- uchar_t val = (
- (controller->status.busy << 7) |
- (controller->status.drive_ready << 6) |
- (controller->status.write_fault << 5) |
- (controller->status.seek_complete << 4) |
- (controller->status.drq << 3) |
- (controller->status.corrected_data << 2) |
- (controller->status.index_pulse << 1) |
- (controller->status.err) );
+ } else {
+ uchar_t val = (
+ (controller->status.busy << 7) |
+ (controller->status.drive_ready << 6) |
+ (controller->status.write_fault << 5) |
+ (controller->status.seek_complete << 4) |
+ (controller->status.drq << 3) |
+ (controller->status.corrected_data << 2) |
+ (controller->status.index_pulse << 1) |
+ (controller->status.err) );
- memcpy(dst, &val, length);
+ memcpy(dst, &val, length);
- controller->status.index_pulse_count++;
- controller->status.index_pulse = 0;
+ controller->status.index_pulse_count++;
+ controller->status.index_pulse = 0;
- if (controller->status.index_pulse_count >= INDEX_PULSE_CYCLE) {
- controller->status.index_pulse = 1;
- controller->status.index_pulse_count = 0;
+ if (controller->status.index_pulse_count >= INDEX_PULSE_CYCLE) {
+ controller->status.index_pulse = 1;
+ controller->status.index_pulse_count = 0;
+ }
}
- }
- if ((port == SEC_CMD_PORT) || (port == PRI_CMD_PORT)) {
- rd_lower_irq(dev, channel);
- }
+ if ((port == SEC_CMD_PORT) || (port == PRI_CMD_PORT)) {
+ rd_lower_irq(dev, channel);
+ }
- PrintDebug("\t\tRead STATUS = 0x%x\n", *(uchar_t *)dst);
+ PrintDebug("\t\tRead STATUS = 0x%x\n", *(uchar_t *)dst);
- return length;
+ return length;
}
static int write_cmd_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct channel_t * channel = NULL;
- struct drive_t * drive = NULL;
- struct controller_t * controller = NULL;
- uchar_t value = *(uchar_t *)src;
-
- if (length != 1) {
- PrintError("Invalid Command port write length: %d (port=%d)\n", length, port);
- return -1;
- }
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct channel_t * channel = NULL;
+ struct drive_t * drive = NULL;
+ struct controller_t * controller = NULL;
+ uchar_t value = *(uchar_t *)src;
+
+ if (length != 1) {
+ PrintError("Invalid Command port write length: %d (port=%d)\n", length, port);
+ return -1;
+ }
- if (is_primary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[0]);
- } else if (is_secondary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[1]);
- } else {
- PrintError("Invalid Port: %d\n", port);
- return -1;
- }
+ if (is_primary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[0]);
+ } else if (is_secondary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[1]);
+ } else {
+ PrintError("Invalid Port: %d\n", port);
+ return -1;
+ }
- drive = get_selected_drive(channel);
- controller = &(drive->controller);
+ drive = get_selected_drive(channel);
+ controller = &(drive->controller);
- PrintDebug("[write_command_handler] IO write at 0x%x, on drive %d/%d (val = 0x%x)\n",
- port, get_channel_no(ramdisk, channel),
- get_drive_no(channel, drive),
- value);
+ PrintDebug("[write_command_handler] IO write at 0x%x, on drive %d/%d (val = 0x%x)\n",
+ port, get_channel_no(ramdisk, channel),
+ get_drive_no(channel, drive),
+ value);
- switch (value) {
+ switch (value) {
#if 0
- case 0xec: // IDENTIFY DEVICE
- {
-
- if (drive->device_type == IDE_NONE) {
- PrintError("\t\tError: disk ata%d-%d not present, aborting\n",
- get_channel_no(ramdisk, channel),
- get_drive_no(channel, drive));
- rd_command_aborted(dev, channel, value);
- break;
- } else if (drive->device_type == IDE_CDROM) {
- PrintDebug("Identifying CDROM...Going to abort????\n");
- controller->head_no = 0;
- controller->sector_count = 1;
- controller->sector_no = 1;
- controller->cylinder_no = 0xeb14;
- rd_command_aborted(dev, channel, 0xec);
- } else {
- PrintError("\t\tError: Want to identify HDD!!\n");
- /*
- SELECTED_CONTROLLER(channel).current_command = value;
- SELECTED_CONTROLLER(channel).error_register = 0;
+ case 0xec: // IDENTIFY DEVICE
+ {
+
+ if (drive->device_type == IDE_NONE) {
+ PrintError("\t\tError: disk ata%d-%d not present, aborting\n",
+ get_channel_no(ramdisk, channel),
+ get_drive_no(channel, drive));
+ rd_command_aborted(dev, channel, value);
+ break;
+ } else if (drive->device_type == IDE_CDROM) {
+ PrintDebug("Identifying CDROM...Going to abort????\n");
+ controller->head_no = 0;
+ controller->sector_count = 1;
+ controller->sector_no = 1;
+ controller->cylinder_no = 0xeb14;
+ rd_command_aborted(dev, channel, 0xec);
+ } else {
+ PrintError("\t\tError: Want to identify HDD!!\n");
+ /*
+ SELECTED_CONTROLLER(channel).current_command = value;
+ SELECTED_CONTROLLER(channel).error_register = 0;
- // See ATA/ATAPI-4, 8.12
- SELECTED_CONTROLLER(channel).status.busy = 0;
- SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- SELECTED_CONTROLLER(channel).status.write_fault = 0;
- SELECTED_CONTROLLER(channel).status.drq = 1;
- SELECTED_CONTROLLER(channel).status.err = 0;
+ // See ATA/ATAPI-4, 8.12
+ SELECTED_CONTROLLER(channel).status.busy = 0;
+ SELECTED_CONTROLLER(channel).status.drive_ready = 1;
+ SELECTED_CONTROLLER(channel).status.write_fault = 0;
+ SELECTED_CONTROLLER(channel).status.drq = 1;
+ SELECTED_CONTROLLER(channel).status.err = 0;
- SELECTED_CONTROLLER(channel).status.seek_complete = 1;
- SELECTED_CONTROLLER(channel).status.corrected_data = 0;
+ SELECTED_CONTROLLER(channel).status.seek_complete = 1;
+ SELECTED_CONTROLLER(channel).status.corrected_data = 0;
- SELECTED_CONTROLLER(channel).buffer_index = 0;
- raise_interrupt(channel);
- identify_drive(channel);
- */
- }
+ SELECTED_CONTROLLER(channel).buffer_index = 0;
+ raise_interrupt(channel);
+ identify_drive(channel);
+ */
+ }
- break;
- }
+ break;
+ }
#endif
- // ATAPI commands
- case 0xa1: // IDENTIFY PACKET DEVICE
- {
- if (drive->device_type == IDE_CDROM) {
- controller->current_command = value;
- controller->error_register = 0;
+ // ATAPI commands
+ case 0xa1: // IDENTIFY PACKET DEVICE
+ {
+ if (drive->device_type == IDE_CDROM) {
+ controller->current_command = value;
+ controller->error_register = 0;
- controller->status.busy = 0;
- controller->status.drive_ready = 1;
- controller->status.write_fault = 0;
- controller->status.drq = 1;
- controller->status.err = 0;
+ controller->status.busy = 0;
+ controller->status.drive_ready = 1;
+ controller->status.write_fault = 0;
+ controller->status.drq = 1;
+ controller->status.err = 0;
- controller->status.seek_complete = 1;
- controller->status.corrected_data = 0;
+ controller->status.seek_complete = 1;
+ controller->status.corrected_data = 0;
- controller->buffer_index = 0;
- rd_raise_interrupt(dev, channel);
- rd_identify_ATAPI_drive(dev, channel);
- } else {
- PrintError("Identifying non cdrom device not supported - ata %d/%d\n",
- get_channel_no(ramdisk, channel),
- get_drive_no(channel, drive));
- rd_command_aborted(dev, channel, 0xa1);
- }
- break;
- }
- case 0xa0: // SEND PACKET (atapi)
- {
- if (drive->device_type == IDE_CDROM) {
- // PACKET
+ controller->buffer_index = 0;
+ rd_raise_interrupt(dev, channel);
+ rd_identify_ATAPI_drive(dev, channel);
+ } else {
+ PrintError("Identifying non cdrom device not supported - ata %d/%d\n",
+ get_channel_no(ramdisk, channel),
+ get_drive_no(channel, drive));
+ rd_command_aborted(dev, channel, 0xa1);
+ }
+ break;
+ }
+ case 0xa0: // SEND PACKET (atapi)
+ {
+ if (drive->device_type == IDE_CDROM) {
+ // PACKET
- if (controller->features & (1 << 0)) {
- PrintError("\t\tPACKET-DMA not supported");
- return -1;
- }
+ if (controller->features & (1 << 0)) {
+ PrintError("\t\tPACKET-DMA not supported");
+ return -1;
+ }
- if (controller->features & (1 << 1)) {
- PrintError("\t\tPACKET-overlapped not supported");
- return -1;
- }
+ if (controller->features & (1 << 1)) {
+ PrintError("\t\tPACKET-overlapped not supported");
+ return -1;
+ }
- // We're already ready!
- controller->sector_count = 1;
- controller->status.busy = 0;
- controller->status.write_fault = 0;
-
- // serv bit??
- controller->status.drq = 1;
- controller->status.err = 0;
+ // We're already ready!
+ controller->sector_count = 1;
+ controller->status.busy = 0;
+ controller->status.write_fault = 0;
+
+ // serv bit??
+ controller->status.drq = 1;
+ controller->status.err = 0;
- // NOTE: no interrupt here
- controller->current_command = value;
- controller->buffer_index = 0;
- } else {
- PrintError("Sending packet to non cdrom device not supported\n");
- rd_command_aborted (dev, channel, 0xa0);
- }
- break;
+ // NOTE: no interrupt here
+ controller->current_command = value;
+ controller->buffer_index = 0;
+ } else {
+ PrintError("Sending packet to non cdrom device not supported\n");
+ rd_command_aborted (dev, channel, 0xa0);
+ }
+ break;
+ }
+ default:
+ PrintError("\t\tneed translate command %2x - ata %d\%d\n", value,
+ get_channel_no(ramdisk, channel),
+ get_drive_no(channel, drive));
+ //return -1;
+ /* JRL THIS NEEDS TO CHANGE */
+ return length;
+
}
- default:
- PrintError("\t\tneed translate command %2x - ata %d\%d\n", value,
- get_channel_no(ramdisk, channel),
- get_drive_no(channel, drive));
- //return -1;
- /* JRL THIS NEEDS TO CHANGE */
return length;
-
- }
- return length;
}
static int write_ctrl_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct channel_t * channel = NULL;
- struct drive_t * master_drive = NULL;
- struct drive_t * slave_drive = NULL;
- struct controller_t * controller = NULL;
- uchar_t value = *(uchar_t *)src;
- rd_bool prev_control_reset;
-
- if (length != 1) {
- PrintError("Invalid Status port read length: %d (port=%d)\n", length, port);
- return -1;
- }
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct channel_t * channel = NULL;
+ struct drive_t * master_drive = NULL;
+ struct drive_t * slave_drive = NULL;
+ struct controller_t * controller = NULL;
+ uchar_t value = *(uchar_t *)src;
+ rd_bool prev_control_reset;
+
+ if (length != 1) {
+ PrintError("Invalid Status port read length: %d (port=%d)\n", length, port);
+ return -1;
+ }
- if (is_primary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[0]);
- } else if (is_secondary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[1]);
- } else {
- PrintError("Invalid Port: %d\n", port);
- return -1;
- }
+ if (is_primary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[0]);
+ } else if (is_secondary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[1]);
+ } else {
+ PrintError("Invalid Port: %d\n", port);
+ return -1;
+ }
- master_drive = &(channel->drives[0]);
- slave_drive = &(channel->drives[1]);
+ master_drive = &(channel->drives[0]);
+ slave_drive = &(channel->drives[1]);
- controller = &(get_selected_drive(channel)->controller);
+ controller = &(get_selected_drive(channel)->controller);
- PrintDebug("[write_control_handler] IO write at 0x%x, on drive %d/%d (val = 0x%x)\n",
- port, get_channel_no(ramdisk, channel),
- channel->drive_select,
- value);
+ PrintDebug("[write_control_handler] IO write at 0x%x, on drive %d/%d (val = 0x%x)\n",
+ port, get_channel_no(ramdisk, channel),
+ channel->drive_select,
+ value);
- // (mch) Even if device 1 was selected, a write to this register
- // goes to device 0 (if device 1 is absent)
+ // (mch) Even if device 1 was selected, a write to this register
+ // goes to device 0 (if device 1 is absent)
- prev_control_reset = controller->control.reset;
+ prev_control_reset = controller->control.reset;
- if (value & 0x04) {
- PrintDebug("RESET Signaled\n");
- }
+ if (value & 0x04) {
+ PrintDebug("RESET Signaled\n");
+ }
- master_drive->controller.control.reset = value & 0x04;
- slave_drive->controller.control.reset = value & 0x04;
+ master_drive->controller.control.reset = value & 0x04;
+ slave_drive->controller.control.reset = value & 0x04;
- // CGS: was: SELECTED_CONTROLLER(channel).control.disable_irq = value & 0x02;
- master_drive->controller.control.disable_irq = value & 0x02;
- slave_drive->controller.control.disable_irq = value & 0x02;
+ // CGS: was: SELECTED_CONTROLLER(channel).control.disable_irq = value & 0x02;
+ master_drive->controller.control.disable_irq = value & 0x02;
+ slave_drive->controller.control.disable_irq = value & 0x02;
- PrintDebug("\t\tadpater control reg: reset controller = %d\n",
- (unsigned) (controller->control.reset) ? 1 : 0);
- PrintDebug("\t\tadpater control reg: disable_irq(X) = %d\n",
- (unsigned) (controller->control.disable_irq) ? 1 : 0);
+ PrintDebug("\t\tadpater control reg: reset controller = %d\n",
+ (unsigned) (controller->control.reset) ? 1 : 0);
+ PrintDebug("\t\tadpater control reg: disable_irq(X) = %d\n",
+ (unsigned) (controller->control.disable_irq) ? 1 : 0);
- if ((!prev_control_reset) && (controller->control.reset)) {
- uint_t id = 0;
+ if ((!prev_control_reset) && (controller->control.reset)) {
+ uint_t id = 0;
- // transition from 0 to 1 causes all drives to reset
- PrintDebug("\t\thard drive: RESET\n");
+ // transition from 0 to 1 causes all drives to reset
+ PrintDebug("\t\thard drive: RESET\n");
- // (mch) Set BSY, drive not ready
- for (id = 0; id < 2; id++) {
- struct controller_t * ctrl = NULL;
-
- if (id == 0) {
- ctrl = &(master_drive->controller);
- } else if (id == 1) {
- ctrl = &(slave_drive->controller);
- }
+ // (mch) Set BSY, drive not ready
+ for (id = 0; id < 2; id++) {
+ struct controller_t * ctrl = NULL;
+
+ if (id == 0) {
+ ctrl = &(master_drive->controller);
+ } else if (id == 1) {
+ ctrl = &(slave_drive->controller);
+ }
- ctrl->status.busy = 1;
- ctrl->status.drive_ready = 0;
- ctrl->reset_in_progress = 1;
+ ctrl->status.busy = 1;
+ ctrl->status.drive_ready = 0;
+ ctrl->reset_in_progress = 1;
- ctrl->status.write_fault = 0;
- ctrl->status.seek_complete = 1;
- ctrl->status.drq = 0;
- ctrl->status.corrected_data = 0;
- ctrl->status.err = 0;
+ ctrl->status.write_fault = 0;
+ ctrl->status.seek_complete = 1;
+ ctrl->status.drq = 0;
+ ctrl->status.corrected_data = 0;
+ ctrl->status.err = 0;
- ctrl->error_register = 0x01; // diagnostic code: no error
+ ctrl->error_register = 0x01; // diagnostic code: no error
- ctrl->current_command = 0x00;
- ctrl->buffer_index = 0;
+ ctrl->current_command = 0x00;
+ ctrl->buffer_index = 0;
- ctrl->sectors_per_block = 0x80;
- ctrl->lba_mode = 0;
+ ctrl->sectors_per_block = 0x80;
+ ctrl->lba_mode = 0;
- ctrl->control.disable_irq = 0;
- }
+ ctrl->control.disable_irq = 0;
+ }
- rd_lower_irq(dev, channel);
+ rd_lower_irq(dev, channel);
- } else if ((controller->reset_in_progress) &&
- (!controller->control.reset)) {
- uint_t id;
- // Clear BSY and DRDY
- PrintDebug("\t\tReset complete {%s}\n", device_type_to_str(get_selected_drive(channel)->device_type));
+ } else if ((controller->reset_in_progress) &&
+ (!controller->control.reset)) {
+ uint_t id;
+ // Clear BSY and DRDY
+ PrintDebug("\t\tReset complete {%s}\n", device_type_to_str(get_selected_drive(channel)->device_type));
- for (id = 0; id < 2; id++) {
- struct controller_t * ctrl = NULL;
- struct drive_t * drv = NULL;
+ for (id = 0; id < 2; id++) {
+ struct controller_t * ctrl = NULL;
+ struct drive_t * drv = NULL;
- if (id == 0) {
- ctrl = &(master_drive->controller);
- drv = master_drive;
- } else if (id == 1) {
- ctrl = &(slave_drive->controller);
- drv = slave_drive;
- }
+ if (id == 0) {
+ ctrl = &(master_drive->controller);
+ drv = master_drive;
+ } else if (id == 1) {
+ ctrl = &(slave_drive->controller);
+ drv = slave_drive;
+ }
- ctrl->status.busy = 0;
- ctrl->status.drive_ready = 1;
- ctrl->reset_in_progress = 0;
+ ctrl->status.busy = 0;
+ ctrl->status.drive_ready = 1;
+ ctrl->reset_in_progress = 0;
- // Device signature
- if (drv->device_type == IDE_DISK) {
- PrintDebug("\t\tdrive %d/%d is harddrive\n", get_channel_no(ramdisk, channel), id);
- ctrl->head_no = 0;
- ctrl->sector_count = 1;
- ctrl->sector_no = 1;
- ctrl->cylinder_no = 0;
- } else {
- ctrl->head_no = 0;
- ctrl->sector_count = 1;
- ctrl->sector_no = 1;
- ctrl->cylinder_no = 0xeb14;
- }
+ // Device signature
+ if (drv->device_type == IDE_DISK) {
+ PrintDebug("\t\tdrive %d/%d is harddrive\n", get_channel_no(ramdisk, channel), id);
+ ctrl->head_no = 0;
+ ctrl->sector_count = 1;
+ ctrl->sector_no = 1;
+ ctrl->cylinder_no = 0;
+ } else {
+ ctrl->head_no = 0;
+ ctrl->sector_count = 1;
+ ctrl->sector_no = 1;
+ ctrl->cylinder_no = 0xeb14;
+ }
+ }
}
- }
- PrintDebug("\t\ts[0].controller.control.disable_irq = %02x\n",
- master_drive->controller.control.disable_irq);
- PrintDebug("\t\ts[1].controller.control.disable_irq = %02x\n",
- slave_drive->controller.control.disable_irq);
- return length;
+ PrintDebug("\t\ts[0].controller.control.disable_irq = %02x\n",
+ master_drive->controller.control.disable_irq);
+ PrintDebug("\t\ts[1].controller.control.disable_irq = %02x\n",
+ slave_drive->controller.control.disable_irq);
+ return length;
}
static int read_general_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct channel_t * channel = NULL;
- struct drive_t * drive = NULL;
- struct controller_t * controller = NULL;
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct channel_t * channel = NULL;
+ struct drive_t * drive = NULL;
+ struct controller_t * controller = NULL;
- if (length != 1) {
- PrintError("Invalid Status port read length: %d (port=%d)\n", length, port);
- return -1;
- }
+ if (length != 1) {
+ PrintError("Invalid Status port read length: %d (port=%d)\n", length, port);
+ return -1;
+ }
- if (is_primary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[0]);
- } else if (is_secondary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[1]);
- } else {
- PrintError("Invalid Port: %d\n", port);
- return -1;
- }
+ if (is_primary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[0]);
+ } else if (is_secondary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[1]);
+ } else {
+ PrintError("Invalid Port: %d\n", port);
+ return -1;
+ }
- drive = get_selected_drive(channel);
- controller = &(drive->controller);
+ drive = get_selected_drive(channel);
+ controller = &(drive->controller);
- PrintDebug("[read_general_handler] IO read addr at %x, on drive %d/%d, curcmd = %02x\n",
- port, get_channel_no(ramdisk, channel),
- channel->drive_select,
- controller->current_command);
+ PrintDebug("[read_general_handler] IO read addr at %x, on drive %d/%d, curcmd = %02x\n",
+ port, get_channel_no(ramdisk, channel),
+ channel->drive_select,
+ controller->current_command);
- switch (port) {
- case PRI_FEATURES_PORT:
- case SEC_FEATURES_PORT: // hard disk error register 0x1f1
- {
- uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->error_register;
+ switch (port) {
+ case PRI_FEATURES_PORT:
+ case SEC_FEATURES_PORT: // hard disk error register 0x1f1
+ {
+ uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->error_register;
- controller->status.err = 0;
+ controller->status.err = 0;
- PrintDebug("\t\tRead FEATURES = 0x%x\n", val);
+ PrintDebug("\t\tRead FEATURES = 0x%x\n", val);
- *(uchar_t *)dst = val;
- return length;
+ *(uchar_t *)dst = val;
+ return length;
- break;
- }
+ break;
+ }
- case PRI_SECT_CNT_PORT:
- case SEC_SECT_CNT_PORT: // hard disk sector count / interrupt reason 0x1f2
- {
- uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->sector_count;
- PrintDebug("\t\tRead SECTOR COUNT = 0x%x\n", val);
- *(uchar_t *)dst = val;
- return length;
+ case PRI_SECT_CNT_PORT:
+ case SEC_SECT_CNT_PORT: // hard disk sector count / interrupt reason 0x1f2
+ {
+ uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->sector_count;
+ PrintDebug("\t\tRead SECTOR COUNT = 0x%x\n", val);
+ *(uchar_t *)dst = val;
+ return length;
- break;
- }
- case PRI_SECT_ADDR1_PORT:
- case SEC_SECT_ADDR1_PORT: // sector number 0x1f3
- {
- uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->sector_no;
+ break;
+ }
+ case PRI_SECT_ADDR1_PORT:
+ case SEC_SECT_ADDR1_PORT: // sector number 0x1f3
+ {
+ uchar_t val = (drive->device_type == IDE_NONE) ? 0 : controller->sector_no;
- PrintDebug("\t\tRead SECTOR ADDR1 = 0x%x\n", val);
+ PrintDebug("\t\tRead SECTOR ADDR1 = 0x%x\n", val);
- *(uchar_t *)dst = val;
- return length;
+ *(uchar_t *)dst = val;
+ return length;
- break;
- }
+ break;
+ }
- case PRI_SECT_ADDR2_PORT:
- case SEC_SECT_ADDR2_PORT: // cylinder low 0x1f4
- {
- // -- WARNING : On real hardware the controller registers are shared between drives.
- // So we must respond even if the select device is not present. Some OS uses this fact
- // to detect the disks.... minix2 for example
- uchar_t val = (num_drives_on_channel(channel) == 0) ? 0 : (controller->cylinder_no & 0x00ff);
+ case PRI_SECT_ADDR2_PORT:
+ case SEC_SECT_ADDR2_PORT: // cylinder low 0x1f4
+ {
+ // -- WARNING : On real hardware the controller registers are shared between drives.
+ // So we must respond even if the select device is not present. Some OS uses this fact
+ // to detect the disks.... minix2 for example
+ uchar_t val = (num_drives_on_channel(channel) == 0) ? 0 : (controller->cylinder_no & 0x00ff);
- PrintDebug("\t\tRead SECTOR ADDR2 = 0x%x\n", val);
+ PrintDebug("\t\tRead SECTOR ADDR2 = 0x%x\n", val);
- *(uchar_t *)dst = val;
- return length;
+ *(uchar_t *)dst = val;
+ return length;
- break;
- }
+ break;
+ }
- case PRI_SECT_ADDR3_PORT:
- case SEC_SECT_ADDR3_PORT: // cylinder high 0x1f5
- {
- // -- WARNING : On real hardware the controller registers are shared between drives.
- // So we must respond even if the select device is not present. Some OS uses this fact
- // to detect the disks.... minix2 for example
- uchar_t val = (num_drives_on_channel(channel) == 0) ? 0 : (controller->cylinder_no >> 8);
+ case PRI_SECT_ADDR3_PORT:
+ case SEC_SECT_ADDR3_PORT: // cylinder high 0x1f5
+ {
+ // -- WARNING : On real hardware the controller registers are shared between drives.
+ // So we must respond even if the select device is not present. Some OS uses this fact
+ // to detect the disks.... minix2 for example
+ uchar_t val = (num_drives_on_channel(channel) == 0) ? 0 : (controller->cylinder_no >> 8);
- PrintDebug("\t\tRead SECTOR ADDR3 = 0x%x\n", val);
+ PrintDebug("\t\tRead SECTOR ADDR3 = 0x%x\n", val);
- *(uchar_t *)dst = val;
- return length;
+ *(uchar_t *)dst = val;
+ return length;
- break;
- }
- case PRI_DRV_SEL_PORT:
- case SEC_DRV_SEL_PORT: // hard disk drive and head register 0x1f6
- {
- // b7 Extended data field for ECC
- // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128
- // Since 512 was always used, bit 6 was taken to mean LBA mode:
- // b6 1=LBA mode, 0=CHS mode
- // b5 1
- // b4: DRV
- // b3..0 HD3..HD0
- uchar_t val = ((1 << 7) |
- ((controller->lba_mode > 0) << 6) |
- (1 << 5) | // 01b = 512 sector size
- (channel->drive_select << 4) |
- (controller->head_no << 0));
+ break;
+ }
+ case PRI_DRV_SEL_PORT:
+ case SEC_DRV_SEL_PORT: // hard disk drive and head register 0x1f6
+ {
+ // b7 Extended data field for ECC
+ // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128
+ // Since 512 was always used, bit 6 was taken to mean LBA mode:
+ // b6 1=LBA mode, 0=CHS mode
+ // b5 1
+ // b4: DRV
+ // b3..0 HD3..HD0
+ uchar_t val = ((1 << 7) |
+ ((controller->lba_mode > 0) << 6) |
+ (1 << 5) | // 01b = 512 sector size
+ (channel->drive_select << 4) |
+ (controller->head_no << 0));
- PrintDebug("\t\tRead DRIVE SELECT = 0x%x\n", val);
- *(uchar_t *)dst = val;
- return length;
+ PrintDebug("\t\tRead DRIVE SELECT = 0x%x\n", val);
+ *(uchar_t *)dst = val;
+ return length;
- break;
- }
- case PRI_ADDR_REG_PORT:
- case SEC_ADDR_REG_PORT: // Hard Disk Address Register 0x3f7
- {
- // Obsolete and unsupported register. Not driven by hard
- // disk controller. Report all 1's. If floppy controller
- // is handling this address, it will call this function
- // set/clear D7 (the only bit it handles), then return
- // the combined value
- *(uchar_t *)dst = 0xff;
- return length;
- }
+ break;
+ }
+ case PRI_ADDR_REG_PORT:
+ case SEC_ADDR_REG_PORT: // Hard Disk Address Register 0x3f7
+ {
+ // Obsolete and unsupported register. Not driven by hard
+ // disk controller. Report all 1's. If floppy controller
+ // is handling this address, it will call this function
+ // set/clear D7 (the only bit it handles), then return
+ // the combined value
+ *(uchar_t *)dst = 0xff;
+ return length;
+ }
- default:
- PrintError("Invalid Port: %d\n", port);
- return -1;
- }
+ default:
+ PrintError("Invalid Port: %d\n", port);
+ return -1;
+ }
}
static int write_general_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct channel_t * channel = NULL;
- struct drive_t * drive = NULL;
- struct controller_t * controller = NULL;
- uchar_t value = *(uchar_t *)src;
-
- if (length != 1) {
- PrintError("Invalid Status port read length: %d (port=%d)\n", length, port);
- return -1;
- }
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct channel_t * channel = NULL;
+ struct drive_t * drive = NULL;
+ struct controller_t * controller = NULL;
+ uchar_t value = *(uchar_t *)src;
+
+ if (length != 1) {
+ PrintError("Invalid Status port read length: %d (port=%d)\n", length, port);
+ return -1;
+ }
- if (is_primary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[0]);
- } else if (is_secondary_port(ramdisk, port)) {
- channel = &(ramdisk->channels[1]);
- } else {
- PrintError("Invalid Port: %d\n", port);
- return -1;
- }
+ if (is_primary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[0]);
+ } else if (is_secondary_port(ramdisk, port)) {
+ channel = &(ramdisk->channels[1]);
+ } else {
+ PrintError("Invalid Port: %d\n", port);
+ return -1;
+ }
- drive = get_selected_drive(channel);
- controller = &(drive->controller);
+ drive = get_selected_drive(channel);
+ controller = &(drive->controller);
- PrintDebug("[write_general_handler] IO write to port %x (val=0x%02x), channel = %d\n",
- port, value, get_channel_no(ramdisk, channel));
+ PrintDebug("[write_general_handler] IO write to port %x (val=0x%02x), channel = %d\n",
+ port, value, get_channel_no(ramdisk, channel));
- switch (port) {
+ switch (port) {
- case PRI_FEATURES_PORT:
- case SEC_FEATURES_PORT: // hard disk write precompensation 0x1f1
- {
- write_features(channel, value);
- break;
- }
- case PRI_SECT_CNT_PORT:
- case SEC_SECT_CNT_PORT: // hard disk sector count 0x1f2
- {
- write_sector_count(channel, value);
- break;
- }
- case PRI_SECT_ADDR1_PORT:
- case SEC_SECT_ADDR1_PORT: // hard disk sector number 0x1f3
- {
- write_sector_number(channel, value);
- break;
- }
- case PRI_SECT_ADDR2_PORT:
- case SEC_SECT_ADDR2_PORT: // hard disk cylinder low 0x1f4
- {
- write_cylinder_low(channel, value);
- break;
- }
- case PRI_SECT_ADDR3_PORT:
- case SEC_SECT_ADDR3_PORT: // hard disk cylinder high 0x1f5
- {
- write_cylinder_high(channel, value);
- break;
- }
- case PRI_DRV_SEL_PORT:
- case SEC_DRV_SEL_PORT: // hard disk drive and head register 0x1f6
- {
- // b7 Extended data field for ECC
- // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128
- // Since 512 was always used, bit 6 was taken to mean LBA mode:
- // b6 1=LBA mode, 0=CHS mode
- // b5 1
- // b4: DRV
- // b3..0 HD3..HD0
-
- // 1x1xxxxx
-
- PrintDebug("\tDrive Select value=%x\n", value);
-
- if ((value & 0xa0) != 0xa0) {
- PrintDebug("\t\tIO write 0x%x (%02x): not 1x1xxxxxb\n", port, (unsigned) value);
- }
+ case PRI_FEATURES_PORT:
+ case SEC_FEATURES_PORT: // hard disk write precompensation 0x1f1
+ {
+ write_features(channel, value);
+ break;
+ }
+ case PRI_SECT_CNT_PORT:
+ case SEC_SECT_CNT_PORT: // hard disk sector count 0x1f2
+ {
+ write_sector_count(channel, value);
+ break;
+ }
+ case PRI_SECT_ADDR1_PORT:
+ case SEC_SECT_ADDR1_PORT: // hard disk sector number 0x1f3
+ {
+ write_sector_number(channel, value);
+ break;
+ }
+ case PRI_SECT_ADDR2_PORT:
+ case SEC_SECT_ADDR2_PORT: // hard disk cylinder low 0x1f4
+ {
+ write_cylinder_low(channel, value);
+ break;
+ }
+ case PRI_SECT_ADDR3_PORT:
+ case SEC_SECT_ADDR3_PORT: // hard disk cylinder high 0x1f5
+ {
+ write_cylinder_high(channel, value);
+ break;
+ }
+ case PRI_DRV_SEL_PORT:
+ case SEC_DRV_SEL_PORT: // hard disk drive and head register 0x1f6
+ {
+ // b7 Extended data field for ECC
+ // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128
+ // Since 512 was always used, bit 6 was taken to mean LBA mode:
+ // b6 1=LBA mode, 0=CHS mode
+ // b5 1
+ // b4: DRV
+ // b3..0 HD3..HD0
+
+ // 1x1xxxxx
+
+ PrintDebug("\tDrive Select value=%x\n", value);
+
+ if ((value & 0xa0) != 0xa0) {
+ PrintDebug("\t\tIO write 0x%x (%02x): not 1x1xxxxxb\n", port, (unsigned) value);
+ }
- write_head_no(channel, value & 0xf);
- if ((controller->lba_mode == 0) && (((value >> 6) & 1) == 1)) {
- PrintDebug("\t\tenabling LBA mode\n");
- }
+ write_head_no(channel, value & 0xf);
+ if ((controller->lba_mode == 0) && (((value >> 6) & 1) == 1)) {
+ PrintDebug("\t\tenabling LBA mode\n");
+ }
- write_lba_mode(channel, (value >> 6) & 1);
+ write_lba_mode(channel, (value >> 6) & 1);
- if (drive->cdrom.cd) {
- PrintDebug("\t\tSetting LBA on CDROM: %d\n", (value >> 6) & 1);
- drive->cdrom.cd->set_LBA(drive->private_data, (value >> 6) & 1);
- }
+ if (drive->cdrom.cd) {
+ PrintDebug("\t\tSetting LBA on CDROM: %d\n", (value >> 6) & 1);
+ drive->cdrom.cd->set_LBA(drive->private_data, (value >> 6) & 1);
+ }
- channel->drive_select = (value >> 4) & 0x01;
- drive = get_selected_drive(channel);
+ channel->drive_select = (value >> 4) & 0x01;
+ drive = get_selected_drive(channel);
- if (drive->device_type == IDE_NONE) {
- PrintError("\t\tError: device set to %d which does not exist! channel = 0x%x\n",
- channel->drive_select, get_channel_no(ramdisk, channel));
+ if (drive->device_type == IDE_NONE) {
+ PrintError("\t\tError: device set to %d which does not exist! channel = 0x%x\n",
+ channel->drive_select, get_channel_no(ramdisk, channel));
- controller->error_register = 0x04; // aborted
- controller->status.err = 1;
- }
+ controller->error_register = 0x04; // aborted
+ controller->status.err = 1;
+ }
- break;
+ break;
+ }
+ default:
+ PrintError("\t\thard drive: io write to unhandled port 0x%x (value = %c)\n", port, value);
+ //return -1;
}
- default:
- PrintError("\t\thard drive: io write to unhandled port 0x%x (value = %c)\n", port, value);
- //return -1;
- }
- return length;
+ return length;
}
static void rd_raise_interrupt(struct vm_device * dev, struct channel_t * channel) {
- // struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct drive_t * drive = get_selected_drive(channel);
- struct controller_t * controller = &(drive->controller);
+ // struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct drive_t * drive = get_selected_drive(channel);
+ struct controller_t * controller = &(drive->controller);
- PrintDebug("[raise_interrupt] disable_irq = 0x%02x\n", controller->control.disable_irq);
+ PrintDebug("[raise_interrupt] disable_irq = 0x%02x\n", controller->control.disable_irq);
- if (!(controller->control.disable_irq)) {
+ if (!(controller->control.disable_irq)) {
- PrintDebug("\t\tRaising interrupt %d {%s}\n\n", channel->irq, device_type_to_str(drive->device_type));
+ PrintDebug("\t\tRaising interrupt %d {%s}\n\n", channel->irq, device_type_to_str(drive->device_type));
- v3_raise_irq(dev->vm, channel->irq);
- } else {
- PrintDebug("\t\tRaising irq but irq is disabled\n");
- }
+ v3_raise_irq(dev->vm, channel->irq);
+ } else {
+ PrintDebug("\t\tRaising irq but irq is disabled\n");
+ }
- return;
+ return;
}
static void rd_lower_irq(struct vm_device *dev, struct channel_t * channel) {
- PrintDebug("[lower_irq] irq = %d\n", channel->irq);
- v3_lower_irq(dev->vm, channel->irq);
+ PrintDebug("[lower_irq] irq = %d\n", channel->irq);
+ v3_lower_irq(dev->vm, channel->irq);
}
int handle_atapi_packet_command(struct vm_device * dev, struct channel_t * channel, ushort_t value) {
- struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
- struct drive_t * drive = get_selected_drive(channel);
- struct controller_t * controller = &(drive->controller);
-
- if (controller->buffer_index >= PACKET_SIZE) {
- PrintError("ATAPI packet exceeded maximum length: buffer_index (%d) >= PACKET_SIZE\n",
- controller->buffer_index);
- return -1;
- }
+ struct ramdisk_t * ramdisk = (struct ramdisk_t *)(dev->private_data);
+ struct drive_t * drive = get_selected_drive(channel);
+ struct controller_t * controller = &(drive->controller);
+
+ if (controller->buffer_index >= PACKET_SIZE) {
+ PrintError("ATAPI packet exceeded maximum length: buffer_index (%d) >= PACKET_SIZE\n",
+ controller->buffer_index);
+ return -1;
+ }
- controller->buffer[controller->buffer_index] = value;
- controller->buffer[controller->buffer_index + 1] = (value >> 8);
- controller->buffer_index += 2;
+ controller->buffer[controller->buffer_index] = value;
+ controller->buffer[controller->buffer_index + 1] = (value >> 8);
+ controller->buffer_index += 2;
- /* if packet completely writtten */
- if (controller->buffer_index >= PACKET_SIZE) {
- // complete command received
- Bit8u atapi_command = controller->buffer[0];
+ /* if packet completely writtten */
+ if (controller->buffer_index >= PACKET_SIZE) {
+ // complete command received
+ Bit8u atapi_command = controller->buffer[0];
- PrintDebug("\t\tcdrom: ATAPI command 0x%x started\n", atapi_command);
+ PrintDebug("\t\tcdrom: ATAPI command 0x%x started\n", atapi_command);
- switch (atapi_command) {
- case 0x00: // test unit ready
- {
- PrintDebug("Testing unit ready\n");
- if (drive->cdrom.ready) {
- rd_atapi_cmd_nop(dev, channel);
- } else {
- PrintError("CDROM not ready in test unit ready\n");
- rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- }
+ switch (atapi_command) {
+ case 0x00: // test unit ready
+ {
+ PrintDebug("Testing unit ready\n");
+ if (drive->cdrom.ready) {
+ rd_atapi_cmd_nop(dev, channel);
+ } else {
+ PrintError("CDROM not ready in test unit ready\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ }
- rd_raise_interrupt(dev, channel);
+ rd_raise_interrupt(dev, channel);
- break;
- }
- case 0x03: // request sense
- {
- int alloc_length = controller->buffer[4];
-
- if (rd_init_send_atapi_command(dev, channel, atapi_command, 18, alloc_length, false) == -1) {
- PrintError("Error sending atapi command in Request Sense\n");
- return -1;
- }
+ break;
+ }
+ case 0x03: // request sense
+ {
+ int alloc_length = controller->buffer[4];
+
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, 18, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in Request Sense\n");
+ return -1;
+ }
- // sense data
- controller->buffer[0] = 0x70 | (1 << 7);
- controller->buffer[1] = 0;
- controller->buffer[2] = drive->sense.sense_key;
- controller->buffer[3] = drive->sense.information.arr[0];
- controller->buffer[4] = drive->sense.information.arr[1];
- controller->buffer[5] = drive->sense.information.arr[2];
- controller->buffer[6] = drive->sense.information.arr[3];
- controller->buffer[7] = 17 - 7;
- controller->buffer[8] = drive->sense.specific_inf.arr[0];
- controller->buffer[9] = drive->sense.specific_inf.arr[1];
- controller->buffer[10] = drive->sense.specific_inf.arr[2];
- controller->buffer[11] = drive->sense.specific_inf.arr[3];
- controller->buffer[12] = drive->sense.asc;
- controller->buffer[13] = drive->sense.ascq;
- controller->buffer[14] = drive->sense.fruc;
- controller->buffer[15] = drive->sense.key_spec.arr[0];
- controller->buffer[16] = drive->sense.key_spec.arr[1];
- controller->buffer[17] = drive->sense.key_spec.arr[2];
+ // sense data
+ controller->buffer[0] = 0x70 | (1 << 7);
+ controller->buffer[1] = 0;
+ controller->buffer[2] = drive->sense.sense_key;
+ controller->buffer[3] = drive->sense.information.arr[0];
+ controller->buffer[4] = drive->sense.information.arr[1];
+ controller->buffer[5] = drive->sense.information.arr[2];
+ controller->buffer[6] = drive->sense.information.arr[3];
+ controller->buffer[7] = 17 - 7;
+ controller->buffer[8] = drive->sense.specific_inf.arr[0];
+ controller->buffer[9] = drive->sense.specific_inf.arr[1];
+ controller->buffer[10] = drive->sense.specific_inf.arr[2];
+ controller->buffer[11] = drive->sense.specific_inf.arr[3];
+ controller->buffer[12] = drive->sense.asc;
+ controller->buffer[13] = drive->sense.ascq;
+ controller->buffer[14] = drive->sense.fruc;
+ controller->buffer[15] = drive->sense.key_spec.arr[0];
+ controller->buffer[16] = drive->sense.key_spec.arr[1];
+ controller->buffer[17] = drive->sense.key_spec.arr[2];
- rd_ready_to_send_atapi(dev, channel);
- break;
- }
- case 0x1b: // start stop unit
- {
- //bx_bool Immed = (controller->buffer[1] >> 0) & 1;
- rd_bool LoEj = (controller->buffer[4] >> 1) & 1;
- rd_bool Start = (controller->buffer[4] >> 0) & 1;
+ rd_ready_to_send_atapi(dev, channel);
+ break;
+ }
+ case 0x1b: // start stop unit
+ {
+ //bx_bool Immed = (controller->buffer[1] >> 0) & 1;
+ rd_bool LoEj = (controller->buffer[4] >> 1) & 1;
+ rd_bool Start = (controller->buffer[4] >> 0) & 1;
- // stop the disc
- if ((!LoEj) && (!Start)) {
- PrintError("FIXME: Stop disc not implemented\n");
+ // stop the disc
+ if ((!LoEj) && (!Start)) {
+ PrintError("FIXME: Stop disc not implemented\n");
- rd_atapi_cmd_nop(dev, channel);
- rd_raise_interrupt(dev, channel);
+ rd_atapi_cmd_nop(dev, channel);
+ rd_raise_interrupt(dev, channel);
- } else if (!LoEj && Start) { // start (spin up) the disc
+ } else if (!LoEj && Start) { // start (spin up) the disc
- drive->cdrom.cd->start_cdrom(drive->private_data);
+ drive->cdrom.cd->start_cdrom(drive->private_data);
- PrintError("FIXME: ATAPI start disc not reading TOC\n");
- rd_atapi_cmd_nop(dev, channel);
- rd_raise_interrupt(dev, channel);
-
- } else if (LoEj && !Start) { // Eject the disc
- rd_atapi_cmd_nop(dev, channel);
- PrintDebug("Ejecting Disk\n");
- if (drive->cdrom.ready) {
+ PrintError("FIXME: ATAPI start disc not reading TOC\n");
+ rd_atapi_cmd_nop(dev, channel);
+ rd_raise_interrupt(dev, channel);
+
+ } else if (LoEj && !Start) { // Eject the disc
+ rd_atapi_cmd_nop(dev, channel);
+ PrintDebug("Ejecting Disk\n");
+ if (drive->cdrom.ready) {
- drive->cdrom.cd->eject_cdrom(drive->private_data);
+ drive->cdrom.cd->eject_cdrom(drive->private_data);
- drive->cdrom.ready = 0;
- //bx_options.atadevice[channel][SLAVE_SELECTED(channel)].Ostatus->set(EJECTED);
- //bx_gui->update_drive_status_buttons();
- }
- rd_raise_interrupt(dev, channel);
-
- } else { // Load the disc
- // My guess is that this command only closes the tray, that's a no-op for us
- rd_atapi_cmd_nop(dev, channel);
- rd_raise_interrupt(dev, channel);
- }
- break;
- }
- case 0xbd: // mechanism status
- {
- uint16_t alloc_length = rd_read_16bit(controller->buffer + 8);
+ drive->cdrom.ready = 0;
+ //bx_options.atadevice[channel][SLAVE_SELECTED(channel)].Ostatus->set(EJECTED);
+ //bx_gui->update_drive_status_buttons();
+ }
+ rd_raise_interrupt(dev, channel);
+
+ } else { // Load the disc
+ // My guess is that this command only closes the tray, that's a no-op for us
+ rd_atapi_cmd_nop(dev, channel);
+ rd_raise_interrupt(dev, channel);
+ }
+ break;
+ }
+ case 0xbd: // mechanism status
+ {
+ uint16_t alloc_length = rd_read_16bit(controller->buffer + 8);
- if (alloc_length == 0) {
- PrintError("Zero allocation length to MECHANISM STATUS not impl.\n");
- return -1;
- }
+ if (alloc_length == 0) {
+ PrintError("Zero allocation length to MECHANISM STATUS not impl.\n");
+ return -1;
+ }
- if (rd_init_send_atapi_command(dev, channel, atapi_command, 8, alloc_length, false) == -1) {
- PrintError("Error sending atapi command in mechanism status\n");
- return -1;
- }
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, 8, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in mechanism status\n");
+ return -1;
+ }
- controller->buffer[0] = 0; // reserved for non changers
- controller->buffer[1] = 0; // reserved for non changers
+ controller->buffer[0] = 0; // reserved for non changers
+ controller->buffer[1] = 0; // reserved for non changers
- controller->buffer[2] = 0; // Current LBA (TODO!)
- controller->buffer[3] = 0; // Current LBA (TODO!)
- controller->buffer[4] = 0; // Current LBA (TODO!)
+ controller->buffer[2] = 0; // Current LBA (TODO!)
+ controller->buffer[3] = 0; // Current LBA (TODO!)
+ controller->buffer[4] = 0; // Current LBA (TODO!)
- controller->buffer[5] = 1; // one slot
+ controller->buffer[5] = 1; // one slot
- controller->buffer[6] = 0; // slot table length
- controller->buffer[7] = 0; // slot table length
+ controller->buffer[6] = 0; // slot table length
+ controller->buffer[7] = 0; // slot table length
- rd_ready_to_send_atapi(dev, channel);
- break;
- }
- case 0x5a: // mode sense
- {
- uint16_t alloc_length = rd_read_16bit(controller->buffer + 7);
+ rd_ready_to_send_atapi(dev, channel);
+ break;
+ }
+ case 0x5a: // mode sense
+ {
+ uint16_t alloc_length = rd_read_16bit(controller->buffer + 7);
- Bit8u PC = controller->buffer[2] >> 6;
- Bit8u PageCode = controller->buffer[2] & 0x3f;
+ Bit8u PC = controller->buffer[2] >> 6;
+ Bit8u PageCode = controller->buffer[2] & 0x3f;
- switch (PC) {
- case 0x0: // current values
- {
- switch (PageCode) {
- case 0x01: // error recovery
- {
+ switch (PC) {
+ case 0x0: // current values
+ {
+ switch (PageCode) {
+ case 0x01: // error recovery
+ {
- if (rd_init_send_atapi_command(dev, channel, atapi_command, sizeof(struct error_recovery_t) + 8, alloc_length, false) == -1) {
- PrintError("Error sending atapi command in mode sense error recovery\n");
- return -1;
- }
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, sizeof(struct error_recovery_t) + 8, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in mode sense error recovery\n");
+ return -1;
+ }
- rd_init_mode_sense_single(dev, channel, &(drive->cdrom.current.error_recovery),
- sizeof(struct error_recovery_t));
- rd_ready_to_send_atapi(dev, channel);
- break;
- }
- case 0x2a: // CD-ROM capabilities & mech. status
- {
-
- if (rd_init_send_atapi_command(dev, channel, atapi_command, 28, alloc_length, false) == -1) {
- PrintError("Error sending atapi command in CDROM caps/mech mode-sense\n");
- return -1;
- }
-
- rd_init_mode_sense_single(dev, channel, &(controller->buffer[8]), 28);
+ rd_init_mode_sense_single(dev, channel, &(drive->cdrom.current.error_recovery),
+ sizeof(struct error_recovery_t));
+ rd_ready_to_send_atapi(dev, channel);
+ break;
+ }
+ case 0x2a: // CD-ROM capabilities & mech. status
+ {
+
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, 28, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in CDROM caps/mech mode-sense\n");
+ return -1;
+ }
+
+ rd_init_mode_sense_single(dev, channel, &(controller->buffer[8]), 28);
- controller->buffer[8] = 0x2a;
- controller->buffer[9] = 0x12;
- controller->buffer[10] = 0x00;
- controller->buffer[11] = 0x00;
- // Multisession, Mode 2 Form 2, Mode 2 Form 1
- controller->buffer[12] = 0x70;
- controller->buffer[13] = (3 << 5);
- controller->buffer[14] = (unsigned char) (1 |
- (drive->cdrom.locked ? (1 << 1) : 0) |
- (1 << 3) |
- (1 << 5));
- controller->buffer[15] = 0x00;
- controller->buffer[16] = (706 >> 8) & 0xff;
- controller->buffer[17] = 706 & 0xff;
- controller->buffer[18] = 0;
- controller->buffer[19] = 2;
- controller->buffer[20] = (512 >> 8) & 0xff;
- controller->buffer[21] = 512 & 0xff;
- controller->buffer[22] = (706 >> 8) & 0xff;
- controller->buffer[23] = 706 & 0xff;
- controller->buffer[24] = 0;
- controller->buffer[25] = 0;
- controller->buffer[26] = 0;
- controller->buffer[27] = 0;
- rd_ready_to_send_atapi(dev, channel);
- break;
- }
- case 0x0d: // CD-ROM
- case 0x0e: // CD-ROM audio control
- case 0x3f: // all
- {
- PrintError("Ramdisk: cdrom: MODE SENSE (curr), code=%x not implemented yet\n",
- PageCode);
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- break;
- }
- default:
- {
- // not implemeted by this device
- PrintError("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n",
- PC, PageCode);
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- break;
- }
- }
- break;
- }
- case 0x1: // changeable values
- {
- switch (PageCode) {
- case 0x01: // error recovery
- case 0x0d: // CD-ROM
- case 0x0e: // CD-ROM audio control
- case 0x2a: // CD-ROM capabilities & mech. status
- case 0x3f: // all
- {
- PrintError("cdrom: MODE SENSE (chg), code=%x not implemented yet\n",
- PageCode);
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- break;
- }
- default:
- {
- // not implemeted by this device
- PrintError("Changeable values of mode sense not supported by cdrom\n");
- PrintDebug("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n",
- PC, PageCode);
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- break;
- }
- }
- break;
- }
- case 0x2: // default values
- {
- switch (PageCode) {
- case 0x01: // error recovery
- case 0x0d: // CD-ROM
- case 0x0e: // CD-ROM audio control
- case 0x2a: // CD-ROM capabilities & mech. status
- case 0x3f: // all
- PrintError("Default values of mode sense not supported by cdrom\n");
- PrintDebug("cdrom: MODE SENSE (dflt), code=%x\n",
- PageCode);
- return -1;
+ controller->buffer[8] = 0x2a;
+ controller->buffer[9] = 0x12;
+ controller->buffer[10] = 0x00;
+ controller->buffer[11] = 0x00;
+ // Multisession, Mode 2 Form 2, Mode 2 Form 1
+ controller->buffer[12] = 0x70;
+ controller->buffer[13] = (3 << 5);
+ controller->buffer[14] = (unsigned char) (1 |
+ (drive->cdrom.locked ? (1 << 1) : 0) |
+ (1 << 3) |
+ (1 << 5));
+ controller->buffer[15] = 0x00;
+ controller->buffer[16] = (706 >> 8) & 0xff;
+ controller->buffer[17] = 706 & 0xff;
+ controller->buffer[18] = 0;
+ controller->buffer[19] = 2;
+ controller->buffer[20] = (512 >> 8) & 0xff;
+ controller->buffer[21] = 512 & 0xff;
+ controller->buffer[22] = (706 >> 8) & 0xff;
+ controller->buffer[23] = 706 & 0xff;
+ controller->buffer[24] = 0;
+ controller->buffer[25] = 0;
+ controller->buffer[26] = 0;
+ controller->buffer[27] = 0;
+ rd_ready_to_send_atapi(dev, channel);
+ break;
+ }
+ case 0x0d: // CD-ROM
+ case 0x0e: // CD-ROM audio control
+ case 0x3f: // all
+ {
+ PrintError("Ramdisk: cdrom: MODE SENSE (curr), code=%x not implemented yet\n",
+ PageCode);
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
+ default:
+ {
+ // not implemeted by this device
+ PrintError("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n",
+ PC, PageCode);
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
+ }
+ break;
+ }
+ case 0x1: // changeable values
+ {
+ switch (PageCode) {
+ case 0x01: // error recovery
+ case 0x0d: // CD-ROM
+ case 0x0e: // CD-ROM audio control
+ case 0x2a: // CD-ROM capabilities & mech. status
+ case 0x3f: // all
+ {
+ PrintError("cdrom: MODE SENSE (chg), code=%x not implemented yet\n",
+ PageCode);
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
+ default:
+ {
+ // not implemeted by this device
+ PrintError("Changeable values of mode sense not supported by cdrom\n");
+ PrintDebug("\t\tcdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n",
+ PC, PageCode);
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
+ }
+ break;
+ }
+ case 0x2: // default values
+ {
+ switch (PageCode) {
+ case 0x01: // error recovery
+ case 0x0d: // CD-ROM
+ case 0x0e: // CD-ROM audio control
+ case 0x2a: // CD-ROM capabilities & mech. status
+ case 0x3f: // all
+ PrintError("Default values of mode sense not supported by cdrom\n");
+ PrintDebug("cdrom: MODE SENSE (dflt), code=%x\n",
+ PageCode);
+ return -1;
- default:
- {
- PrintError("Default values of mode sense not implemented in cdrom\n");
- // not implemeted by this device
- PrintDebug("cdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n",
- PC, PageCode);
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- break;
- }
- }
- break;
- }
- case 0x3: // saved values not implemented
- {
- PrintError("\t\tSaved values not implemented in mode sense\n");
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
- rd_raise_interrupt(dev, channel);
- break;
- }
- default:
- {
- PrintError("Unsupported Mode sense value\n");
- return -1;
- break;
- }
- }
- break;
- }
- case 0x12: // inquiry
- {
- uint8_t alloc_length = controller->buffer[4];
+ default:
+ {
+ PrintError("Default values of mode sense not implemented in cdrom\n");
+ // not implemeted by this device
+ PrintDebug("cdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device\n",
+ PC, PageCode);
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
+ }
+ break;
+ }
+ case 0x3: // saved values not implemented
+ {
+ PrintError("\t\tSaved values not implemented in mode sense\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
+ default:
+ {
+ PrintError("Unsupported Mode sense value\n");
+ return -1;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x12: // inquiry
+ {
+ uint8_t alloc_length = controller->buffer[4];
- if (rd_init_send_atapi_command(dev, channel, atapi_command, 36, alloc_length, false) == -1) {
- PrintError("Error sending atapi command in inquiry\n");
- return -1;
- }
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, 36, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in inquiry\n");
+ return -1;
+ }
- controller->buffer[0] = 0x05; // CD-ROM
- controller->buffer[1] = 0x80; // Removable
- controller->buffer[2] = 0x00; // ISO, ECMA, ANSI version
- controller->buffer[3] = 0x21; // ATAPI-2, as specified
- controller->buffer[4] = 31; // additional length (total 36)
- controller->buffer[5] = 0x00; // reserved
- controller->buffer[6] = 0x00; // reserved
- controller->buffer[7] = 0x00; // reserved
+ controller->buffer[0] = 0x05; // CD-ROM
+ controller->buffer[1] = 0x80; // Removable
+ controller->buffer[2] = 0x00; // ISO, ECMA, ANSI version
+ controller->buffer[3] = 0x21; // ATAPI-2, as specified
+ controller->buffer[4] = 31; // additional length (total 36)
+ controller->buffer[5] = 0x00; // reserved
+ controller->buffer[6] = 0x00; // reserved
+ controller->buffer[7] = 0x00; // reserved
- // Vendor ID
- const char* vendor_id = "VTAB ";
- int i;
- for (i = 0; i < 8; i++) {
- controller->buffer[8+i] = vendor_id[i];
- }
-
- // Product ID
- const char* product_id = "Turbo CD-ROM ";
- for (i = 0; i < 16; i++) {
- controller->buffer[16+i] = product_id[i];
- }
-
- // Product Revision level
- const char* rev_level = "1.0 ";
- for (i = 0; i < 4; i++) {
- controller->buffer[32 + i] = rev_level[i];
- }
-
- rd_ready_to_send_atapi(dev, channel);
- break;
- }
- case 0x25: // read cd-rom capacity
- {
- // no allocation length???
- if (rd_init_send_atapi_command(dev, channel, atapi_command, 8, 8, false) == -1) {
- PrintError("Error sending atapi command in read cdrom capacity\n");
- return -1;
- }
+ // Vendor ID
+ const char* vendor_id = "VTAB ";
+ int i;
+ for (i = 0; i < 8; i++) {
+ controller->buffer[8+i] = vendor_id[i];
+ }
+
+ // Product ID
+ const char* product_id = "Turbo CD-ROM ";
+ for (i = 0; i < 16; i++) {
+ controller->buffer[16+i] = product_id[i];
+ }
+
+ // Product Revision level
+ const char* rev_level = "1.0 ";
+ for (i = 0; i < 4; i++) {
+ controller->buffer[32 + i] = rev_level[i];
+ }
+
+ rd_ready_to_send_atapi(dev, channel);
+ break;
+ }
+ case 0x25: // read cd-rom capacity
+ {
+ // no allocation length???
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, 8, 8, false) == -1) {
+ PrintError("Error sending atapi command in read cdrom capacity\n");
+ return -1;
+ }
- if (drive->cdrom.ready) {
- uint32_t capacity = drive->cdrom.capacity;
-
- PrintDebug("\t\tCapacity is %d sectors (%d bytes)\n", capacity, capacity * 2048);
-
- controller->buffer[0] = (capacity >> 24) & 0xff;
- controller->buffer[1] = (capacity >> 16) & 0xff;
- controller->buffer[2] = (capacity >> 8) & 0xff;
- controller->buffer[3] = (capacity >> 0) & 0xff;
- controller->buffer[4] = (2048 >> 24) & 0xff;
- controller->buffer[5] = (2048 >> 16) & 0xff;
- controller->buffer[6] = (2048 >> 8) & 0xff;
- controller->buffer[7] = (2048 >> 0) & 0xff;
-
- rd_ready_to_send_atapi(dev, channel);
- } else {
- PrintError("CDROM not ready in read cdrom capacity\n");
- rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- rd_raise_interrupt(dev, channel);
- }
- break;
- }
+ if (drive->cdrom.ready) {
+ uint32_t capacity = drive->cdrom.capacity;
+
+ PrintDebug("\t\tCapacity is %d sectors (%d bytes)\n", capacity, capacity * 2048);
+
+ controller->buffer[0] = (capacity >> 24) & 0xff;
+ controller->buffer[1] = (capacity >> 16) & 0xff;
+ controller->buffer[2] = (capacity >> 8) & 0xff;
+ controller->buffer[3] = (capacity >> 0) & 0xff;
+ controller->buffer[4] = (2048 >> 24) & 0xff;
+ controller->buffer[5] = (2048 >> 16) & 0xff;
+ controller->buffer[6] = (2048 >> 8) & 0xff;
+ controller->buffer[7] = (2048 >> 0) & 0xff;
+
+ rd_ready_to_send_atapi(dev, channel);
+ } else {
+ PrintError("CDROM not ready in read cdrom capacity\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ rd_raise_interrupt(dev, channel);
+ }
+ break;
+ }
- case 0xbe: // read cd
- {
- if (drive->cdrom.ready) {
- PrintError("Read CD with CD present not implemented\n");
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- } else {
- PrintError("Drive not ready in read cd with CD present\n");
- rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- rd_raise_interrupt(dev, channel);
- }
- break;
- }
- case 0x43: // read toc
- {
- if (drive->cdrom.ready) {
- int toc_length = 0;
- bool msf = (controller->buffer[1] >> 1) & 1;
- uint8_t starting_track = controller->buffer[6];
+ case 0xbe: // read cd
+ {
+ if (drive->cdrom.ready) {
+ PrintError("Read CD with CD present not implemented\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ } else {
+ PrintError("Drive not ready in read cd with CD present\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ rd_raise_interrupt(dev, channel);
+ }
+ break;
+ }
+ case 0x43: // read toc
+ {
+ if (drive->cdrom.ready) {
+ int toc_length = 0;
+ bool msf = (controller->buffer[1] >> 1) & 1;
+ uint8_t starting_track = controller->buffer[6];
- uint16_t alloc_length = rd_read_16bit(controller->buffer + 7);
+ uint16_t alloc_length = rd_read_16bit(controller->buffer + 7);
- uint8_t format = (controller->buffer[9] >> 6);
- int i;
-
- PrintDebug("Reading CDROM TOC: Format=%d (byte count=%d) (toc length:%d)\n",
- format, controller->byte_count, toc_length);
-
- switch (format) {
- case 0:
- {
- if (!(drive->cdrom.cd->read_toc(drive->private_data, controller->buffer,
- &toc_length, msf, starting_track))) {
- PrintError("CDROM: Reading Table of Contents Failed\n");
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- break;
- }
+ uint8_t format = (controller->buffer[9] >> 6);
+ int i;
+
+ PrintDebug("Reading CDROM TOC: Format=%d (byte count=%d) (toc length:%d)\n",
+ format, controller->byte_count, toc_length);
+
+ switch (format) {
+ case 0:
+ if (!(drive->cdrom.cd->read_toc(drive->private_data, controller->buffer,
+ &toc_length, msf, starting_track))) {
+ PrintError("CDROM: Reading Table of Contents Failed\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
- if (rd_init_send_atapi_command(dev, channel, atapi_command, toc_length, alloc_length, false) == -1) {
- PrintError("Failed to init send atapi command in read toc (fmt=%d)\n", format);
- return -1;
- }
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, toc_length, alloc_length, false) == -1) {
+ PrintError("Failed to init send atapi command in read toc (fmt=%d)\n", format);
+ return -1;
+ }
- rd_ready_to_send_atapi(dev, channel);
+ rd_ready_to_send_atapi(dev, channel);
- break;
- }
- case 1:
- // multi session stuff. we ignore this and emulate a single session only
+ break;
- if (rd_init_send_atapi_command(dev, channel, atapi_command, 12, alloc_length, false) == -1) {
- PrintError("Failed to init send atapi command in read toc (fmt=%d)\n", format);
- return -1;
- }
+ case 1:
+ // multi session stuff. we ignore this and emulate a single session only
+
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, 12, alloc_length, false) == -1) {
+ PrintError("Failed to init send atapi command in read toc (fmt=%d)\n", format);
+ return -1;
+ }
- controller->buffer[0] = 0;
- controller->buffer[1] = 0x0a;
- controller->buffer[2] = 1;
- controller->buffer[3] = 1;
+ controller->buffer[0] = 0;
+ controller->buffer[1] = 0x0a;
+ controller->buffer[2] = 1;
+ controller->buffer[3] = 1;
- for (i = 0; i < 8; i++) {
- controller->buffer[4 + i] = 0;
- }
+ for (i = 0; i < 8; i++) {
+ controller->buffer[4 + i] = 0;
+ }
- rd_ready_to_send_atapi(dev, channel);
- break;
+ rd_ready_to_send_atapi(dev, channel);
+ break;
- case 2:
- default:
- PrintError("(READ TOC) Format %d not supported\n", format);
- return -1;
- }
- } else {
- PrintError("CDROM not ready in read toc\n");
- rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- rd_raise_interrupt(dev, channel);
- }
- break;
- }
- case 0x28: // read (10)
- case 0xa8: // read (12)
- {
+ case 2:
+ default:
+ PrintError("(READ TOC) Format %d not supported\n", format);
+ return -1;
+ }
+ } else {
+ PrintError("CDROM not ready in read toc\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ rd_raise_interrupt(dev, channel);
+ }
+ break;
+ }
+ case 0x28: // read (10)
+ case 0xa8: // read (12)
+ {
- uint32_t transfer_length;
- if (atapi_command == 0x28) {
- transfer_length = rd_read_16bit(controller->buffer + 7);
- } else {
- transfer_length = rd_read_32bit(controller->buffer + 6);
- }
-
- uint32_t lba = rd_read_32bit(controller->buffer + 2);
+ uint32_t transfer_length;
+ if (atapi_command == 0x28) {
+ transfer_length = rd_read_16bit(controller->buffer + 7);
+ } else {
+ transfer_length = rd_read_32bit(controller->buffer + 6);
+ }
+
+ uint32_t lba = rd_read_32bit(controller->buffer + 2);
- if (!(drive->cdrom.ready)) {
- PrintError("CDROM Error: Not Ready (ATA%d/%d)\n",
- get_channel_no(ramdisk, channel), get_drive_no(channel, drive));
- rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- rd_raise_interrupt(dev, channel);
- break;
- }
+ if (!(drive->cdrom.ready)) {
+ PrintError("CDROM Error: Not Ready (ATA%d/%d)\n",
+ get_channel_no(ramdisk, channel), get_drive_no(channel, drive));
+ rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
- if (transfer_length == 0) {
- PrintError("READ(%d) with transfer length 0, ok\n",
- (atapi_command == 0x28) ? 10 : 12);
- rd_atapi_cmd_nop(dev, channel);
- rd_raise_interrupt(dev, channel);
- break;
- }
+ if (transfer_length == 0) {
+ PrintError("READ(%d) with transfer length 0, ok\n",
+ (atapi_command == 0x28) ? 10 : 12);
+ rd_atapi_cmd_nop(dev, channel);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
- if (lba + transfer_length > drive->cdrom.capacity) {
- PrintError("CDROM Error: Capacity exceeded [capacity=%d] (ATA%d/%d)\n",
- drive->cdrom.capacity,
- get_channel_no(ramdisk, channel), get_drive_no(channel, drive));
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
- rd_raise_interrupt(dev, channel);
- break;
- }
+ if (lba + transfer_length > drive->cdrom.capacity) {
+ PrintError("CDROM Error: Capacity exceeded [capacity=%d] (ATA%d/%d)\n",
+ drive->cdrom.capacity,
+ get_channel_no(ramdisk, channel), get_drive_no(channel, drive));
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
- PrintDebug("\t\tcdrom: READ (%d) LBA=%d LEN=%d\n",
- (atapi_command == 0x28) ? 10 : 12,
- lba, transfer_length);
+ PrintDebug("\t\tcdrom: READ (%d) LBA=%d LEN=%d\n",
+ (atapi_command == 0x28) ? 10 : 12,
+ lba, transfer_length);
- // handle command
- if (rd_init_send_atapi_command(dev, channel, atapi_command, transfer_length * 2048,
- transfer_length * 2048, true) == -1) {
- PrintError("CDROM Error: Atapi command send error\n");
- return -1;
- }
-
- drive->cdrom.remaining_blocks = transfer_length;
- drive->cdrom.next_lba = lba;
- rd_ready_to_send_atapi(dev, channel);
- break;
- }
- case 0x2b: // seek
- {
- uint32_t lba = rd_read_32bit(controller->buffer + 2);
-
- if (!(drive->cdrom.ready)) {
- PrintError("CDROM not ready in seek\n");
- rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- rd_raise_interrupt(dev, channel);
- break;
- }
+ // handle command
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, transfer_length * 2048,
+ transfer_length * 2048, true) == -1) {
+ PrintError("CDROM Error: Atapi command send error\n");
+ return -1;
+ }
+
+ drive->cdrom.remaining_blocks = transfer_length;
+ drive->cdrom.next_lba = lba;
+ rd_ready_to_send_atapi(dev, channel);
+ break;
+ }
+ case 0x2b: // seek
+ {
+ uint32_t lba = rd_read_32bit(controller->buffer + 2);
+
+ if (!(drive->cdrom.ready)) {
+ PrintError("CDROM not ready in seek\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
- if (lba > drive->cdrom.capacity) {
- PrintError("LBA is greater than CDROM capacity in seek\n");
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
- rd_raise_interrupt(dev, channel);
- break;
- }
+ if (lba > drive->cdrom.capacity) {
+ PrintError("LBA is greater than CDROM capacity in seek\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
- PrintError("\t\tcdrom: SEEK (ignored)\n");
+ PrintError("\t\tcdrom: SEEK (ignored)\n");
- rd_atapi_cmd_nop(dev, channel);
- rd_raise_interrupt(dev, channel);
+ rd_atapi_cmd_nop(dev, channel);
+ rd_raise_interrupt(dev, channel);
- break;
- }
- case 0x1e: // prevent/allow medium removal
- {
-
- if (drive->cdrom.ready) {
- drive->cdrom.locked = controller->buffer[4] & 1;
- rd_atapi_cmd_nop(dev, channel);
- } else {
- PrintError("CD not ready in prevent/allow medium removal\n");
- rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- }
+ break;
+ }
+ case 0x1e: // prevent/allow medium removal
+ {
- rd_raise_interrupt(dev, channel);
+ if (drive->cdrom.ready) {
+ drive->cdrom.locked = controller->buffer[4] & 1;
+ rd_atapi_cmd_nop(dev, channel);
+ } else {
+ PrintError("CD not ready in prevent/allow medium removal\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ }
- break;
- }
- case 0x42: // read sub-channel
- {
- //bool msf = get_packet_field(channel,1, 1, 1);
- bool sub_q = get_packet_field(channel,2, 6, 1);
- //uint8_t data_format = get_packet_byte(channel,3);
- //uint8_t track_number = get_packet_byte(channel,6);
- uint16_t alloc_length = get_packet_word(channel,7);
+ rd_raise_interrupt(dev, channel);
+
+ break;
+ }
+ case 0x42: // read sub-channel
+ {
+ //bool msf = get_packet_field(channel,1, 1, 1);
+ bool sub_q = get_packet_field(channel,2, 6, 1);
+ //uint8_t data_format = get_packet_byte(channel,3);
+ //uint8_t track_number = get_packet_byte(channel,6);
+ uint16_t alloc_length = get_packet_word(channel,7);
- /*
- UNUSED(msf);
- UNUSED(data_format);
- UNUSED(track_number);
- */
- if (!(drive->cdrom.ready)) {
- PrintError("CDROM not ready in read sub-channel\n");
- rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- rd_raise_interrupt(dev, channel);
- } else {
- controller->buffer[0] = 0;
- controller->buffer[1] = 0; // audio not supported
- controller->buffer[2] = 0;
- controller->buffer[3] = 0;
+ /*
+ UNUSED(msf);
+ UNUSED(data_format);
+ UNUSED(track_number);
+ */
+ if (!(drive->cdrom.ready)) {
+ PrintError("CDROM not ready in read sub-channel\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
+ rd_raise_interrupt(dev, channel);
+ } else {
+ controller->buffer[0] = 0;
+ controller->buffer[1] = 0; // audio not supported
+ controller->buffer[2] = 0;
+ controller->buffer[3] = 0;
- int ret_len = 4; // header size
+ int ret_len = 4; // header size
- if (sub_q) { // !sub_q == header only
- PrintError("Read sub-channel with SubQ not implemented\n");
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- }
+ if (sub_q) { // !sub_q == header only
+ PrintError("Read sub-channel with SubQ not implemented\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ }
- if (rd_init_send_atapi_command(dev, channel, atapi_command, ret_len, alloc_length, false) == -1) {
- PrintError("Error sending atapi command in read sub-channel\n");
- return -1;
- }
- rd_ready_to_send_atapi(dev, channel);
+ if (rd_init_send_atapi_command(dev, channel, atapi_command, ret_len, alloc_length, false) == -1) {
+ PrintError("Error sending atapi command in read sub-channel\n");
+ return -1;
+ }
+ rd_ready_to_send_atapi(dev, channel);
+ }
+ break;
+ }
+ case 0x51: // read disc info
+ {
+ // no-op to keep the Linux CD-ROM driver happy
+ PrintError("Error: Read disk info no-op to keep the Linux CD-ROM driver happy\n");
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
+ }
+ case 0x55: // mode select
+ case 0xa6: // load/unload cd
+ case 0x4b: // pause/resume
+ case 0x45: // play audio
+ case 0x47: // play audio msf
+ case 0xbc: // play cd
+ case 0xb9: // read cd msf
+ case 0x44: // read header
+ case 0xba: // scan
+ case 0xbb: // set cd speed
+ case 0x4e: // stop play/scan
+ case 0x46: // ???
+ case 0x4a: // ???
+ PrintError("ATAPI command 0x%x not implemented yet\n",
+ atapi_command);
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
+ default:
+ PrintError("Unknown ATAPI command 0x%x (%d)\n",
+ atapi_command, atapi_command);
+ // We'd better signal the error if the user chose to continue
+ rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
+ rd_raise_interrupt(dev, channel);
+ break;
}
- break;
- }
- case 0x51: // read disc info
- {
- // no-op to keep the Linux CD-ROM driver happy
- PrintError("Error: Read disk info no-op to keep the Linux CD-ROM driver happy\n");
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- break;
- }
- case 0x55: // mode select
- case 0xa6: // load/unload cd
- case 0x4b: // pause/resume
- case 0x45: // play audio
- case 0x47: // play audio msf
- case 0xbc: // play cd
- case 0xb9: // read cd msf
- case 0x44: // read header
- case 0xba: // scan
- case 0xbb: // set cd speed
- case 0x4e: // stop play/scan
- case 0x46: // ???
- case 0x4a: // ???
- PrintError("ATAPI command 0x%x not implemented yet\n",
- atapi_command);
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- break;
- default:
- PrintError("Unknown ATAPI command 0x%x (%d)\n",
- atapi_command, atapi_command);
- // We'd better signal the error if the user chose to continue
- rd_atapi_cmd_error(dev, channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
- rd_raise_interrupt(dev, channel);
- break;
}
- }
- return 0;
+ return 0;
}
int rd_init_send_atapi_command(struct vm_device * dev, struct channel_t * channel, Bit8u command, int req_length, int alloc_length, bool lazy)
{
- struct drive_t * drive = &(channel->drives[channel->drive_select]);
- struct controller_t * controller = &(drive->controller);
+ struct drive_t * drive = &(channel->drives[channel->drive_select]);
+ struct controller_t * controller = &(drive->controller);
- // controller->byte_count is a union of controller->cylinder_no;
- // lazy is used to force a data read in the buffer at the next read.
+ // controller->byte_count is a union of controller->cylinder_no;
+ // lazy is used to force a data read in the buffer at the next read.
- PrintDebug("[rd_init_send_atapi_cmd]\n");
+ PrintDebug("[rd_init_send_atapi_cmd]\n");
- if (controller->byte_count == 0xffff) {
- controller->byte_count = 0xfffe;
- }
+ if (controller->byte_count == 0xffff) {
+ controller->byte_count = 0xfffe;
+ }
- if ((controller->byte_count & 1) &&
- !(alloc_length <= controller->byte_count)) {
+ if ((controller->byte_count & 1) &&
+ !(alloc_length <= controller->byte_count)) {
- PrintDebug("\t\tOdd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%x\n",
- controller->byte_count,
- command,
- controller->byte_count - 1);
+ PrintDebug("\t\tOdd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%x\n",
+ controller->byte_count,
+ command,
+ controller->byte_count - 1);
- controller->byte_count -= 1;
- }
+ controller->byte_count -= 1;
+ }
- if (controller->byte_count == 0) {
- PrintError("\t\tATAPI command with zero byte count\n");
- return -1;
- }
+ if (controller->byte_count == 0) {
+ PrintError("\t\tATAPI command with zero byte count\n");
+ return -1;
+ }
- if (alloc_length < 0) {
- PrintError("\t\tAllocation length < 0\n");
- return -1;
- }
+ if (alloc_length < 0) {
+ PrintError("\t\tAllocation length < 0\n");
+ return -1;
+ }
- if (alloc_length == 0) {
- alloc_length = controller->byte_count;
- }
+ if (alloc_length == 0) {
+ alloc_length = controller->byte_count;
+ }
- controller->interrupt_reason.i_o = 1;
- controller->interrupt_reason.c_d = 0;
- controller->status.busy = 0;
- controller->status.drq = 1;
- controller->status.err = 0;
+ controller->interrupt_reason.i_o = 1;
+ controller->interrupt_reason.c_d = 0;
+ controller->status.busy = 0;
+ controller->status.drq = 1;
+ controller->status.err = 0;
- // no bytes transfered yet
- if (lazy) {
- controller->buffer_index = 2048;
- } else {
- controller->buffer_index = 0;
- }
+ // no bytes transfered yet
+ if (lazy) {
+ controller->buffer_index = 2048;
+ } else {
+ controller->buffer_index = 0;
+ }
- controller->drq_index = 0;
+ controller->drq_index = 0;
- if (controller->byte_count > req_length) {
- controller->byte_count = req_length;
- }
+ if (controller->byte_count > req_length) {
+ controller->byte_count = req_length;
+ }
- if (controller->byte_count > alloc_length) {
- controller->byte_count = alloc_length;
- }
+ if (controller->byte_count > alloc_length) {
+ controller->byte_count = alloc_length;
+ }
- drive->atapi.command = command;
- drive->atapi.drq_bytes = controller->byte_count;
- drive->atapi.total_bytes_remaining = (req_length < alloc_length) ? req_length : alloc_length;
+ drive->atapi.command = command;
+ drive->atapi.drq_bytes = controller->byte_count;
+ drive->atapi.total_bytes_remaining = (req_length < alloc_length) ? req_length : alloc_length;
- // if (lazy) {
- // // bias drq_bytes and total_bytes_remaining
- // SELECTED_DRIVE(channel).atapi.drq_bytes += 2048;
- // SELECTED_DRIVE(channel).atapi.total_bytes_remaining += 2048;
- // }
+ // if (lazy) {
+ // // bias drq_bytes and total_bytes_remaining
+ // SELECTED_DRIVE(channel).atapi.drq_bytes += 2048;
+ // SELECTED_DRIVE(channel).atapi.total_bytes_remaining += 2048;
+ // }
- return 0;
+ return 0;
}
void rd_ready_to_send_atapi(struct vm_device * dev, struct channel_t * channel) {
- PrintDebug("[rd_ready_to_send_atapi]\n");
+ PrintDebug("[rd_ready_to_send_atapi]\n");
- rd_raise_interrupt(dev, channel);
+ rd_raise_interrupt(dev, channel);
}
void rd_atapi_cmd_error(struct vm_device * dev, struct channel_t * channel, sense_t sense_key, asc_t asc)
{
- struct drive_t * drive = &(channel->drives[channel->drive_select]);
- struct controller_t * controller = &(drive->controller);
+ struct drive_t * drive = &(channel->drives[channel->drive_select]);
+ struct controller_t * controller = &(drive->controller);
- struct ramdisk_t *ramdisk = (struct ramdisk_t *)(dev->private_data);
- PrintError("[rd_atapi_cmd_error]\n");
- PrintError("Error: atapi_cmd_error channel=%02x key=%02x asc=%02x\n",
- get_channel_no(ramdisk, channel), sense_key, asc);
+ struct ramdisk_t *ramdisk = (struct ramdisk_t *)(dev->private_data);
+ PrintError("[rd_atapi_cmd_error]\n");
+ PrintError("Error: atapi_cmd_error channel=%02x key=%02x asc=%02x\n",
+ get_channel_no(ramdisk, channel), sense_key, asc);
- controller->error_register = sense_key << 4;
- controller->interrupt_reason.i_o = 1;
- controller->interrupt_reason.c_d = 1;
- controller->interrupt_reason.rel = 0;
- controller->status.busy = 0;
- controller->status.drive_ready = 1;
- controller->status.write_fault = 0;
- controller->status.drq = 0;
- controller->status.err = 1;
+ controller->error_register = sense_key << 4;
+ controller->interrupt_reason.i_o = 1;
+ controller->interrupt_reason.c_d = 1;
+ controller->interrupt_reason.rel = 0;
+ controller->status.busy = 0;
+ controller->status.drive_ready = 1;
+ controller->status.write_fault = 0;
+ controller->status.drq = 0;
+ controller->status.err = 1;
- drive->sense.sense_key = sense_key;
- drive->sense.asc = asc;
- drive->sense.ascq = 0;
+ drive->sense.sense_key = sense_key;
+ drive->sense.asc = asc;
+ drive->sense.ascq = 0;
}
void rd_atapi_cmd_nop(struct vm_device * dev, struct channel_t * channel)
{
- struct drive_t * drive = &(channel->drives[channel->drive_select]);
- struct controller_t * controller = &(drive->controller);
-
- PrintDebug("[rd_atapi_cmd_nop]\n");
- controller->interrupt_reason.i_o = 1;
- controller->interrupt_reason.c_d = 1;
- controller->interrupt_reason.rel = 0;
- controller->status.busy = 0;
- controller->status.drive_ready = 1;
- controller->status.drq = 0;
- controller->status.err = 0;
+ struct drive_t * drive = &(channel->drives[channel->drive_select]);
+ struct controller_t * controller = &(drive->controller);
+
+ PrintDebug("[rd_atapi_cmd_nop]\n");
+ controller->interrupt_reason.i_o = 1;
+ controller->interrupt_reason.c_d = 1;
+ controller->interrupt_reason.rel = 0;
+ controller->status.busy = 0;
+ controller->status.drive_ready = 1;
+ controller->status.drq = 0;
+ controller->status.err = 0;
}
void rd_identify_ATAPI_drive(struct vm_device * dev, struct channel_t * channel)
{
- struct drive_t * drive = &(channel->drives[channel->drive_select]);
- struct controller_t * controller = &(drive->controller);
+ struct drive_t * drive = &(channel->drives[channel->drive_select]);
+ struct controller_t * controller = &(drive->controller);
- uint_t i;
- const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
- const char* firmware = "ALPHA1 ";
+ uint_t i;
+ const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
+ const char* firmware = "ALPHA1 ";
- drive->id_drive[0] = (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0); // Removable CDROM, 50us response, 12 byte packets
+ drive->id_drive[0] = (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0); // Removable CDROM, 50us response, 12 byte packets
- for (i = 1; i <= 9; i++) {
- drive->id_drive[i] = 0;
- }
+ for (i = 1; i <= 9; i++) {
+ drive->id_drive[i] = 0;
+ }
- for (i = 0; i < 10; i++) {
- drive->id_drive[10 + i] = ((serial_number[i * 2] << 8) |
- (serial_number[(i * 2) + 1]));
- }
+ for (i = 0; i < 10; i++) {
+ drive->id_drive[10 + i] = ((serial_number[i * 2] << 8) |
+ (serial_number[(i * 2) + 1]));
+ }
- for (i = 20; i <= 22; i++) {
- drive->id_drive[i] = 0;
- }
+ for (i = 20; i <= 22; i++) {
+ drive->id_drive[i] = 0;
+ }
- for (i = 0; i < strlen(firmware)/2; i++) {
- drive->id_drive[23 + i] = ((firmware[i * 2] << 8) |
- (firmware[(i * 2) + 1]));
- }
- V3_ASSERT((23 + i) == 27);
+ for (i = 0; i < strlen(firmware)/2; i++) {
+ drive->id_drive[23 + i] = ((firmware[i * 2] << 8) |
+ (firmware[(i * 2) + 1]));
+ }
+ V3_ASSERT((23 + i) == 27);
- for (i = 0; i < strlen((char *)(drive->model_no)) / 2; i++) {
- drive->id_drive[27 + i] = ((drive->model_no[i * 2] << 8) |
- (drive->model_no[(i * 2) + 1]));
- }
- V3_ASSERT((27 + i) == 47);
+ for (i = 0; i < strlen((char *)(drive->model_no)) / 2; i++) {
+ drive->id_drive[27 + i] = ((drive->model_no[i * 2] << 8) |
+ (drive->model_no[(i * 2) + 1]));
+ }
+ V3_ASSERT((27 + i) == 47);
- drive->id_drive[47] = 0;
- drive->id_drive[48] = 1; // 32 bits access
+ drive->id_drive[47] = 0;
+ drive->id_drive[48] = 1; // 32 bits access
- drive->id_drive[49] = (1 << 9); // LBA supported
+ drive->id_drive[49] = (1 << 9); // LBA supported
- drive->id_drive[50] = 0;
- drive->id_drive[51] = 0;
- drive->id_drive[52] = 0;
+ drive->id_drive[50] = 0;
+ drive->id_drive[51] = 0;
+ drive->id_drive[52] = 0;
- drive->id_drive[53] = 3; // words 64-70, 54-58 valid
+ drive->id_drive[53] = 3; // words 64-70, 54-58 valid
- for (i = 54; i <= 62; i++) {
- drive->id_drive[i] = 0;
- }
+ for (i = 54; i <= 62; i++) {
+ drive->id_drive[i] = 0;
+ }
- // copied from CFA540A
- drive->id_drive[63] = 0x0103; // variable (DMA stuff)
- drive->id_drive[64] = 0x0001; // PIO
- drive->id_drive[65] = 0x00b4;
- drive->id_drive[66] = 0x00b4;
- drive->id_drive[67] = 0x012c;
- drive->id_drive[68] = 0x00b4;
-
- drive->id_drive[69] = 0;
- drive->id_drive[70] = 0;
- drive->id_drive[71] = 30; // faked
- drive->id_drive[72] = 30; // faked
- drive->id_drive[73] = 0;
- drive->id_drive[74] = 0;
-
- drive->id_drive[75] = 0;
-
- for (i = 76; i <= 79; i++) {
- drive->id_drive[i] = 0;
- }
+ // copied from CFA540A
+ drive->id_drive[63] = 0x0103; // variable (DMA stuff)
+ drive->id_drive[64] = 0x0001; // PIO
+ drive->id_drive[65] = 0x00b4;
+ drive->id_drive[66] = 0x00b4;
+ drive->id_drive[67] = 0x012c;
+ drive->id_drive[68] = 0x00b4;
+
+ drive->id_drive[69] = 0;
+ drive->id_drive[70] = 0;
+ drive->id_drive[71] = 30; // faked
+ drive->id_drive[72] = 30; // faked
+ drive->id_drive[73] = 0;
+ drive->id_drive[74] = 0;
+
+ drive->id_drive[75] = 0;
+
+ for (i = 76; i <= 79; i++) {
+ drive->id_drive[i] = 0;
+ }
- drive->id_drive[80] = 0x1e; // supports up to ATA/ATAPI-4
- drive->id_drive[81] = 0;
- drive->id_drive[82] = 0;
- drive->id_drive[83] = 0;
- drive->id_drive[84] = 0;
- drive->id_drive[85] = 0;
- drive->id_drive[86] = 0;
- drive->id_drive[87] = 0;
- drive->id_drive[88] = 0;
-
- for (i = 89; i <= 126; i++) {
- drive->id_drive[i] = 0;
- }
+ drive->id_drive[80] = 0x1e; // supports up to ATA/ATAPI-4
+ drive->id_drive[81] = 0;
+ drive->id_drive[82] = 0;
+ drive->id_drive[83] = 0;
+ drive->id_drive[84] = 0;
+ drive->id_drive[85] = 0;
+ drive->id_drive[86] = 0;
+ drive->id_drive[87] = 0;
+ drive->id_drive[88] = 0;
+
+ for (i = 89; i <= 126; i++) {
+ drive->id_drive[i] = 0;
+ }
- drive->id_drive[127] = 0;
- drive->id_drive[128] = 0;
+ drive->id_drive[127] = 0;
+ drive->id_drive[128] = 0;
- for (i = 129; i <= 159; i++) {
- drive->id_drive[i] = 0;
- }
+ for (i = 129; i <= 159; i++) {
+ drive->id_drive[i] = 0;
+ }
- for (i = 160; i <= 255; i++) {
- drive->id_drive[i] = 0;
- }
+ for (i = 160; i <= 255; i++) {
+ drive->id_drive[i] = 0;
+ }
- // now convert the id_drive array (native 256 word format) to
- // the controller buffer (512 bytes)
- Bit16u temp16;
- for (i = 0; i <= 255; i++) {
- temp16 = drive->id_drive[i];
- controller->buffer[i * 2] = temp16 & 0x00ff;
- controller->buffer[i * 2 + 1] = temp16 >> 8;
- }
+ // now convert the id_drive array (native 256 word format) to
+ // the controller buffer (512 bytes)
+ Bit16u temp16;
+ for (i = 0; i <= 255; i++) {
+ temp16 = drive->id_drive[i];
+ controller->buffer[i * 2] = temp16 & 0x00ff;
+ controller->buffer[i * 2 + 1] = temp16 >> 8;
+ }
- return;
+ return;
}
void rd_init_mode_sense_single(struct vm_device * dev,
struct channel_t * channel, const void* src, int size)
{
- struct drive_t * drive = &(channel->drives[channel->drive_select]);
- struct controller_t * controller = &(drive->controller);
-
- PrintDebug("[rd_init_mode_sense_single]\n");
-
- // Header
- controller->buffer[0] = (size + 6) >> 8;
- controller->buffer[1] = (size + 6) & 0xff;
- controller->buffer[2] = 0x70; // no media present
- controller->buffer[3] = 0; // reserved
- controller->buffer[4] = 0; // reserved
- controller->buffer[5] = 0; // reserved
- controller->buffer[6] = 0; // reserved
- controller->buffer[7] = 0; // reserved
+ struct drive_t * drive = &(channel->drives[channel->drive_select]);
+ struct controller_t * controller = &(drive->controller);
+
+ PrintDebug("[rd_init_mode_sense_single]\n");
+
+ // Header
+ controller->buffer[0] = (size + 6) >> 8;
+ controller->buffer[1] = (size + 6) & 0xff;
+ controller->buffer[2] = 0x70; // no media present
+ controller->buffer[3] = 0; // reserved
+ controller->buffer[4] = 0; // reserved
+ controller->buffer[5] = 0; // reserved
+ controller->buffer[6] = 0; // reserved
+ controller->buffer[7] = 0; // reserved
- // Data
- memcpy(controller->buffer + 8, src, size);
+ // Data
+ memcpy(controller->buffer + 8, src, size);
}
static void rd_command_aborted(struct vm_device * dev,
struct channel_t * channel, unsigned value) {
- struct drive_t * drive = &(channel->drives[channel->drive_select]);
- struct controller_t * controller = &(drive->controller);
-
- PrintError("[rd_command_aborted]\n");
- PrintError("\t\taborting on command 0x%02x {%s}\n", value, device_type_to_str(drive->device_type));
-
- controller->current_command = 0;
- controller->status.busy = 0;
- controller->status.drive_ready = 1;
- controller->status.err = 1;
- controller->error_register = 0x04; // command ABORTED
- controller->status.drq = 0;
- controller->status.seek_complete = 0;
- controller->status.corrected_data = 0;
- controller->buffer_index = 0;
-
- rd_raise_interrupt(dev, channel);
+ struct drive_t * drive = &(channel->drives[channel->drive_select]);
+ struct controller_t * controller = &(drive->controller);
+
+ PrintError("[rd_command_aborted]\n");
+ PrintError("\t\taborting on command 0x%02x {%s}\n", value, device_type_to_str(drive->device_type));
+
+ controller->current_command = 0;
+ controller->status.busy = 0;
+ controller->status.drive_ready = 1;
+ controller->status.err = 1;
+ controller->error_register = 0x04; // command ABORTED
+ controller->status.drq = 0;
+ controller->status.seek_complete = 0;
+ controller->status.corrected_data = 0;
+ controller->buffer_index = 0;
+
+ rd_raise_interrupt(dev, channel);
}
static int ramdisk_init_device(struct vm_device *dev) {
- struct ramdisk_t *ramdisk= (struct ramdisk_t *)dev->private_data;
-
- PrintDebug("Initializing Ramdisk\n");
-
-
- rd_init_hardware(ramdisk);
-
-
- v3_dev_hook_io(dev, PRI_CTRL_PORT,
- &read_status_port, &write_ctrl_port);
-
- v3_dev_hook_io(dev, PRI_DATA_PORT,
- &read_data_port, &write_data_port);
- v3_dev_hook_io(dev, PRI_FEATURES_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, PRI_SECT_CNT_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, PRI_SECT_ADDR1_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, PRI_SECT_ADDR2_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, PRI_SECT_ADDR3_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, PRI_DRV_SEL_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, PRI_CMD_PORT,
- &read_status_port, &write_cmd_port);
-
-
- v3_dev_hook_io(dev, SEC_CTRL_PORT,
- &read_status_port, &write_ctrl_port);
-
- v3_dev_hook_io(dev, SEC_DATA_PORT,
- &read_data_port, &write_data_port);
- v3_dev_hook_io(dev, SEC_FEATURES_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, SEC_SECT_CNT_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, SEC_SECT_ADDR1_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, SEC_SECT_ADDR2_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, SEC_SECT_ADDR3_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, SEC_DRV_SEL_PORT,
- &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, SEC_CMD_PORT,
- &read_status_port, &write_cmd_port);
+ struct ramdisk_t *ramdisk= (struct ramdisk_t *)dev->private_data;
+
+ PrintDebug("Initializing Ramdisk\n");
+
+
+ rd_init_hardware(ramdisk);
+
+
+ v3_dev_hook_io(dev, PRI_CTRL_PORT,
+ &read_status_port, &write_ctrl_port);
+
+ v3_dev_hook_io(dev, PRI_DATA_PORT,
+ &read_data_port, &write_data_port);
+ v3_dev_hook_io(dev, PRI_FEATURES_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_SECT_CNT_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_SECT_ADDR1_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_SECT_ADDR2_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_SECT_ADDR3_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_DRV_SEL_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_CMD_PORT,
+ &read_status_port, &write_cmd_port);
+
+
+ v3_dev_hook_io(dev, SEC_CTRL_PORT,
+ &read_status_port, &write_ctrl_port);
+
+ v3_dev_hook_io(dev, SEC_DATA_PORT,
+ &read_data_port, &write_data_port);
+ v3_dev_hook_io(dev, SEC_FEATURES_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_SECT_CNT_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_SECT_ADDR1_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_SECT_ADDR2_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_SECT_ADDR3_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_DRV_SEL_PORT,
+ &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_CMD_PORT,
+ &read_status_port, &write_cmd_port);
- v3_dev_hook_io(dev, SEC_ADDR_REG_PORT,
- &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, SEC_ADDR_REG_PORT,
+ &read_general_port, &write_general_port);
- v3_dev_hook_io(dev, PRI_ADDR_REG_PORT,
- &read_general_port, &write_general_port);
+ v3_dev_hook_io(dev, PRI_ADDR_REG_PORT,
+ &read_general_port, &write_general_port);
- return 0;
+ return 0;
}
static int ramdisk_deinit_device(struct vm_device *dev) {
- struct ramdisk_t *ramdisk = (struct ramdisk_t *)(dev->private_data);
- rd_close_harddrive(ramdisk);
- return 0;
+ struct ramdisk_t *ramdisk = (struct ramdisk_t *)(dev->private_data);
+ rd_close_harddrive(ramdisk);
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = ramdisk_init_device,
- .deinit = ramdisk_deinit_device,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = ramdisk_init_device,
+ .deinit = ramdisk_deinit_device,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_ramdisk()
{
- struct ramdisk_t *ramdisk;
- ramdisk = (struct ramdisk_t *)V3_Malloc(sizeof(struct ramdisk_t));
- V3_ASSERT(ramdisk != NULL);
+ struct ramdisk_t *ramdisk;
+ ramdisk = (struct ramdisk_t *)V3_Malloc(sizeof(struct ramdisk_t));
+ V3_ASSERT(ramdisk != NULL);
- PrintDebug("[create_ramdisk]\n");
+ PrintDebug("[create_ramdisk]\n");
- struct vm_device * device = v3_create_device("RAMDISK", &dev_ops, ramdisk);
+ struct vm_device * device = v3_create_device("RAMDISK", &dev_ops, ramdisk);
- return device;
+ return device;
}
#ifdef DEBUG_RAMDISK
static void rd_print_state(struct ramdisk_t * ramdisk) {
- uchar_t channel;
- uchar_t device;
- struct channel_t * channels = (struct channel_t *)(&(ramdisk->channels));
+ uchar_t channel;
+ uchar_t device;
+ struct channel_t * channels = (struct channel_t *)(&(ramdisk->channels));
- /*
- for (channel = 0; channel < MAX_ATA_CHANNEL; channel++) {
- memset((char *)(channels + channel), 0, sizeof(struct channel_t));
- }
- */
- PrintDebug("sizeof(*channels) = %d\n", sizeof(*channels));
- PrintDebug("sizeof(channles->drives[0].controller) = %d\n", sizeof((channels->drives[0].controller)));
- PrintDebug("sizeof(channles->drives[0].cdrom) = %d\n", sizeof((channels->drives[0].cdrom)));
- PrintDebug("sizeof(channles->drives[0].sense) = %d\n", sizeof((channels->drives[0].sense)));
- PrintDebug("sizeof(channles->drives[0].atapi) = %d\n", sizeof((channels->drives[0].atapi)));
+ /*
+ for (channel = 0; channel < MAX_ATA_CHANNEL; channel++) {
+ memset((char *)(channels + channel), 0, sizeof(struct channel_t));
+ }
+ */
+ PrintDebug("sizeof(*channels) = %d\n", sizeof(*channels));
+ PrintDebug("sizeof(channles->drives[0].controller) = %d\n", sizeof((channels->drives[0].controller)));
+ PrintDebug("sizeof(channles->drives[0].cdrom) = %d\n", sizeof((channels->drives[0].cdrom)));
+ PrintDebug("sizeof(channles->drives[0].sense) = %d\n", sizeof((channels->drives[0].sense)));
+ PrintDebug("sizeof(channles->drives[0].atapi) = %d\n", sizeof((channels->drives[0].atapi)));
- PrintDebug("sizeof(channles->drives[0].controller.status) = %d\n",
- sizeof((channels->drives[0].controller.status)));
- PrintDebug("sizeof(channles->drives[0].controller.sector_count) = %d\n",
- sizeof((channels->drives[0].controller.sector_count)));
- PrintDebug("sizeof(channles->drives[0].controller.interrupt_reason) = %d\n",
- sizeof((channels->drives[0].controller.interrupt_reason)));
+ PrintDebug("sizeof(channles->drives[0].controller.status) = %d\n",
+ sizeof((channels->drives[0].controller.status)));
+ PrintDebug("sizeof(channles->drives[0].controller.sector_count) = %d\n",
+ sizeof((channels->drives[0].controller.sector_count)));
+ PrintDebug("sizeof(channles->drives[0].controller.interrupt_reason) = %d\n",
+ sizeof((channels->drives[0].controller.interrupt_reason)));
- PrintDebug("sizeof(channles->drives[0].controller.cylinder_no) = %d\n",
- sizeof((channels->drives[0].controller.cylinder_no)));
- PrintDebug("sizeof(channles->drives[0].controller.byte_count) = %d\n",
- sizeof((channels->drives[0].controller.byte_count)));
+ PrintDebug("sizeof(channles->drives[0].controller.cylinder_no) = %d\n",
+ sizeof((channels->drives[0].controller.cylinder_no)));
+ PrintDebug("sizeof(channles->drives[0].controller.byte_count) = %d\n",
+ sizeof((channels->drives[0].controller.byte_count)));
- PrintDebug("sizeof(channles->drives[0].controller.control) = %d\n",
- sizeof((channels->drives[0].controller.control)));
+ PrintDebug("sizeof(channles->drives[0].controller.control) = %d\n",
+ sizeof((channels->drives[0].controller.control)));
- for (channel = 0; channel < MAX_ATA_CHANNEL; channel++){
+ for (channel = 0; channel < MAX_ATA_CHANNEL; channel++){
- for (device = 0; device < 2; device++){
+ for (device = 0; device < 2; device++){
- // Initialize controller state, even if device is not present
- PrintDebug("channels[%d].drives[%d].controller.status.busy = %d\n",
- channel, device,
- channels[channel].drives[device].controller.status.busy);
- PrintDebug("channels[%d].drives[%d].controller.status.drive_ready = %d\n",
- channel, device,
- channels[channel].drives[device].controller.status.drive_ready);
- PrintDebug("channels[%d].drives[%d].controller.status.write_fault = %d\n",
- channel, device,
- channels[channel].drives[device].controller.status.write_fault);
- PrintDebug("channels[%d].drives[%d].controller.status.seek_complete = %d\n",
- channel, device,
- channels[channel].drives[device].controller.status.seek_complete);
- PrintDebug("channels[%d].drives[%d].controller.status.drq = %d\n",
- channel, device,
- channels[channel].drives[device].controller.status.drq);
- PrintDebug("channels[%d].drives[%d].controller.status.corrected_data = %d\n",
- channel, device,
- channels[channel].drives[device].controller.status.corrected_data);
- PrintDebug("channels[%d].drives[%d].controller.status.index_pulse = %d\n",
- channel, device,
- channels[channel].drives[device].controller.status.index_pulse);
- PrintDebug("channels[%d].drives[%d].controller.status.index_pulse_count = %d\n",
- channel, device,
- channels[channel].drives[device].controller.status.index_pulse_count);
- PrintDebug("channels[%d].drives[%d].controller.status.err = %d\n",
- channel, device,
- channels[channel].drives[device].controller.status.err);
-
-
- PrintDebug("channels[%d].drives[%d].controller.error_register = %d\n",
- channel, device,
- channels[channel].drives[device].controller.error_register);
- PrintDebug("channels[%d].drives[%d].controller.head_no = %d\n",
- channel, device,
- channels[channel].drives[device].controller.head_no);
- PrintDebug("channels[%d].drives[%d].controller.sector_count = %d\n",
- channel, device,
- channels[channel].drives[device].controller.sector_count);
- PrintDebug("channels[%d].drives[%d].controller.sector_no = %d\n",
- channel, device,
- channels[channel].drives[device].controller.sector_no);
- PrintDebug("channels[%d].drives[%d].controller.cylinder_no = %d\n",
- channel, device,
- channels[channel].drives[device].controller.cylinder_no);
- PrintDebug("channels[%d].drives[%d].controller.current_command = %02x\n",
- channel, device,
- channels[channel].drives[device].controller.current_command);
- PrintDebug("channels[%d].drives[%d].controller.buffer_index = %d\n",
- channel, device,
- channels[channel].drives[device].controller.buffer_index);
-
-
- PrintDebug("channels[%d].drives[%d].controller.control.reset = %d\n",
- channel, device,
- channels[channel].drives[device].controller.control.reset);
- PrintDebug("channels[%d].drives[%d].controller.control.disable_irq = %d\n",
- channel, device,
- channels[channel].drives[device].controller.control.disable_irq);
-
-
- PrintDebug("channels[%d].drives[%d].controller.reset_in_progress = %d\n",
- channel, device,
- channels[channel].drives[device].controller.reset_in_progress);
- PrintDebug("channels[%d].drives[%d].controller.sectors_per_block = %02x\n",
- channel, device,
- channels[channel].drives[device].controller.sectors_per_block);
- PrintDebug("channels[%d].drives[%d].controller.lba_mode = %d\n",
- channel, device,
- channels[channel].drives[device].controller.lba_mode);
- PrintDebug("channels[%d].drives[%d].controller.features = %d\n",
- channel, device,
- channels[channel].drives[device].controller.features);
-
-
- PrintDebug("channels[%d].drives[%d].model_no = %s\n",
- channel, device,
- channels[channel].drives[device].model_no);
- PrintDebug("channels[%d].drives[%d].device_type = %d\n",
- channel, device,
- channels[channel].drives[device].device_type);
- PrintDebug("channels[%d].drives[%d].cdrom.locked = %d\n",
- channel, device,
- channels[channel].drives[device].cdrom.locked);
- PrintDebug("channels[%d].drives[%d].sense.sense_key = %d\n",
- channel, device,
- channels[channel].drives[device].sense.sense_key);
- PrintDebug("channels[%d].drives[%d].sense.asc = %d\n",
- channel, device,
- channels[channel].drives[device].sense.asc);
- PrintDebug("channels[%d].drives[%d].sense.ascq = %d\n",
- channel, device,
- channels[channel].drives[device].sense.ascq);
-
-
-
- PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.c_d = %02x\n",
- channel, device,
- channels[channel].drives[device].controller.interrupt_reason.c_d);
-
- PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.i_o = %02x\n",
- channel, device,
- channels[channel].drives[device].controller.interrupt_reason.i_o);
-
- PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.rel = %02x\n",
- channel, device,
- channels[channel].drives[device].controller.interrupt_reason.rel);
-
- PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.tag = %02x\n",
- channel, device,
- channels[channel].drives[device].controller.interrupt_reason.tag);
-
- PrintDebug("channels[%d].drives[%d].cdrom.ready = %d\n",
- channel, device,
- channels[channel].drives[device].cdrom.ready);
+ // Initialize controller state, even if device is not present
+ PrintDebug("channels[%d].drives[%d].controller.status.busy = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.status.busy);
+ PrintDebug("channels[%d].drives[%d].controller.status.drive_ready = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.status.drive_ready);
+ PrintDebug("channels[%d].drives[%d].controller.status.write_fault = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.status.write_fault);
+ PrintDebug("channels[%d].drives[%d].controller.status.seek_complete = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.status.seek_complete);
+ PrintDebug("channels[%d].drives[%d].controller.status.drq = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.status.drq);
+ PrintDebug("channels[%d].drives[%d].controller.status.corrected_data = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.status.corrected_data);
+ PrintDebug("channels[%d].drives[%d].controller.status.index_pulse = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.status.index_pulse);
+ PrintDebug("channels[%d].drives[%d].controller.status.index_pulse_count = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.status.index_pulse_count);
+ PrintDebug("channels[%d].drives[%d].controller.status.err = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.status.err);
+
+
+ PrintDebug("channels[%d].drives[%d].controller.error_register = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.error_register);
+ PrintDebug("channels[%d].drives[%d].controller.head_no = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.head_no);
+ PrintDebug("channels[%d].drives[%d].controller.sector_count = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.sector_count);
+ PrintDebug("channels[%d].drives[%d].controller.sector_no = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.sector_no);
+ PrintDebug("channels[%d].drives[%d].controller.cylinder_no = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.cylinder_no);
+ PrintDebug("channels[%d].drives[%d].controller.current_command = %02x\n",
+ channel, device,
+ channels[channel].drives[device].controller.current_command);
+ PrintDebug("channels[%d].drives[%d].controller.buffer_index = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.buffer_index);
+
+
+ PrintDebug("channels[%d].drives[%d].controller.control.reset = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.control.reset);
+ PrintDebug("channels[%d].drives[%d].controller.control.disable_irq = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.control.disable_irq);
+
+
+ PrintDebug("channels[%d].drives[%d].controller.reset_in_progress = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.reset_in_progress);
+ PrintDebug("channels[%d].drives[%d].controller.sectors_per_block = %02x\n",
+ channel, device,
+ channels[channel].drives[device].controller.sectors_per_block);
+ PrintDebug("channels[%d].drives[%d].controller.lba_mode = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.lba_mode);
+ PrintDebug("channels[%d].drives[%d].controller.features = %d\n",
+ channel, device,
+ channels[channel].drives[device].controller.features);
+
+
+ PrintDebug("channels[%d].drives[%d].model_no = %s\n",
+ channel, device,
+ channels[channel].drives[device].model_no);
+ PrintDebug("channels[%d].drives[%d].device_type = %d\n",
+ channel, device,
+ channels[channel].drives[device].device_type);
+ PrintDebug("channels[%d].drives[%d].cdrom.locked = %d\n",
+ channel, device,
+ channels[channel].drives[device].cdrom.locked);
+ PrintDebug("channels[%d].drives[%d].sense.sense_key = %d\n",
+ channel, device,
+ channels[channel].drives[device].sense.sense_key);
+ PrintDebug("channels[%d].drives[%d].sense.asc = %d\n",
+ channel, device,
+ channels[channel].drives[device].sense.asc);
+ PrintDebug("channels[%d].drives[%d].sense.ascq = %d\n",
+ channel, device,
+ channels[channel].drives[device].sense.ascq);
+
+
+
+ PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.c_d = %02x\n",
+ channel, device,
+ channels[channel].drives[device].controller.interrupt_reason.c_d);
+
+ PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.i_o = %02x\n",
+ channel, device,
+ channels[channel].drives[device].controller.interrupt_reason.i_o);
+
+ PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.rel = %02x\n",
+ channel, device,
+ channels[channel].drives[device].controller.interrupt_reason.rel);
+
+ PrintDebug("channels[%d].drives[%d].controller.interrupt_reason.tag = %02x\n",
+ channel, device,
+ channels[channel].drives[device].controller.interrupt_reason.tag);
+
+ PrintDebug("channels[%d].drives[%d].cdrom.ready = %d\n",
+ channel, device,
+ channels[channel].drives[device].cdrom.ready);
- } //for device
- } //for channel
+ } //for device
+ } //for channel
- return;
+ return;
}
static int check_bit_fields(struct controller_t * controller) {
- //Check bit fields
- controller->sector_count = 0;
- controller->interrupt_reason.c_d = 1;
- if (controller->sector_count != 0x01) {
- return INTR_REASON_BIT_ERR;
- }
+ //Check bit fields
+ controller->sector_count = 0;
+ controller->interrupt_reason.c_d = 1;
+ if (controller->sector_count != 0x01) {
+ return INTR_REASON_BIT_ERR;
+ }
- controller->sector_count = 0;
- controller->interrupt_reason.i_o = 1;
- if (controller->sector_count != 0x02) {
- return INTR_REASON_BIT_ERR;
- }
+ controller->sector_count = 0;
+ controller->interrupt_reason.i_o = 1;
+ if (controller->sector_count != 0x02) {
+ return INTR_REASON_BIT_ERR;
+ }
- controller->sector_count = 0;
- controller->interrupt_reason.rel = 1;
- if (controller->sector_count != 0x04) {
- return INTR_REASON_BIT_ERR;
- }
+ controller->sector_count = 0;
+ controller->interrupt_reason.rel = 1;
+ if (controller->sector_count != 0x04) {
+ return INTR_REASON_BIT_ERR;
+ }
- controller->sector_count = 0;
- controller->interrupt_reason.tag = 3;
- if (controller->sector_count != 0x18) {
- return INTR_REASON_BIT_ERR;
- }
+ controller->sector_count = 0;
+ controller->interrupt_reason.tag = 3;
+ if (controller->sector_count != 0x18) {
+ return INTR_REASON_BIT_ERR;
+ }
- return 0;
+ return 0;
}
#endif
struct irq_enable_reg {
- uint_t erbfi : 1; // Enable Receiver Buffer full interrupt
- uint_t etbei : 1; // Enable Transmit buffer empty interrupt
- uint_t elsi : 1; // Enable Line Status Interrupt
- uint_t edssi : 1; // Enable Delta Status signals interrupt
- uint_t rsvd : 4; // MBZ
+ uint_t erbfi : 1; // Enable Receiver Buffer full interrupt
+ uint_t etbei : 1; // Enable Transmit buffer empty interrupt
+ uint_t elsi : 1; // Enable Line Status Interrupt
+ uint_t edssi : 1; // Enable Delta Status signals interrupt
+ uint_t rsvd : 4; // MBZ
};
#define MODEL_IRQ_DELTA_SET 0x0
struct irq_id_reg {
- uint_t pending : 1; // Interrupt pending (0=interrupt pending)
- uint_t iid : 3; // Interrupt Identification
- uint_t rsvd : 2; // MBZ
- uint_t fifo_en : 2; // FIFO enable
+ uint_t pending : 1; // Interrupt pending (0=interrupt pending)
+ uint_t iid : 3; // Interrupt Identification
+ uint_t rsvd : 2; // MBZ
+ uint_t fifo_en : 2; // FIFO enable
};
struct fifo_ctrl_reg {
- uint_t enable : 1; // enable fifo
- uint_t rfres : 1; // RX FIFO reset
- uint_t xfres : 1; // TX FIFO reset
- uint_t dma_sel : 1; // DMA mode select
- uint_t rsvd : 2; // MBZ
- uint_t rx_trigger: 2; // RX FIFO trigger level select
+ uint_t enable : 1; // enable fifo
+ uint_t rfres : 1; // RX FIFO reset
+ uint_t xfres : 1; // TX FIFO reset
+ uint_t dma_sel : 1; // DMA mode select
+ uint_t rsvd : 2; // MBZ
+ uint_t rx_trigger: 2; // RX FIFO trigger level select
};
struct line_ctrl_reg {
- uint_t word_len : 2; // word length select
- uint_t stop_bits : 1; // Stop Bit select
- uint_t parity_enable : 1; // Enable parity
- uint_t even_sel : 1; // Even Parity Select
- uint_t stick_parity : 1; // Stick Parity Select
- uint_t sbr : 1; // Set Break
- uint_t dlab : 1; // Divisor latch access bit
+ uint_t word_len : 2; // word length select
+ uint_t stop_bits : 1; // Stop Bit select
+ uint_t parity_enable : 1; // Enable parity
+ uint_t even_sel : 1; // Even Parity Select
+ uint_t stick_parity : 1; // Stick Parity Select
+ uint_t sbr : 1; // Set Break
+ uint_t dlab : 1; // Divisor latch access bit
};
struct modem_ctrl_reg {
- uint_t dtr : 1;
- uint_t rts : 1;
- uint_t out1 : 1;
- uint_t out2 : 1;
- uint_t loop : 1; // loopback mode
- uint_t rsvd : 3; // MBZ
+ uint_t dtr : 1;
+ uint_t rts : 1;
+ uint_t out1 : 1;
+ uint_t out2 : 1;
+ uint_t loop : 1; // loopback mode
+ uint_t rsvd : 3; // MBZ
};
struct line_status_reg {
- uint_t rbf : 1; // Receiver Buffer Full
- uint_t oe : 1; // Overrun error
- uint_t pe : 1; // Parity Error
- uint_t fe : 1; // Framing Error
- uint_t brk : 1; // broken line detected
- uint_t thre : 1; // Transmitter holding register empty
- uint_t temt : 1; // Transmitter Empty
- uint_t fifo_err : 1; // at least one error is pending in the RX FIFO chain
+ uint_t rbf : 1; // Receiver Buffer Full
+ uint_t oe : 1; // Overrun error
+ uint_t pe : 1; // Parity Error
+ uint_t fe : 1; // Framing Error
+ uint_t brk : 1; // broken line detected
+ uint_t thre : 1; // Transmitter holding register empty
+ uint_t temt : 1; // Transmitter Empty
+ uint_t fifo_err : 1; // at least one error is pending in the RX FIFO chain
};
struct modem_status_reg {
- uint_t dcts : 1; // Delta Clear To Send
- uint_t ddsr : 1; // Delta Data Set Ready
- uint_t teri : 1; // Trailing Edge Ring Indicator
- uint_t ddcd : 1; // Delta Data Carrier Detect
- uint_t cts : 1; // Clear to Send
- uint_t dsr : 1; // Data Set Ready
- uint_t ri : 1; // Ring Indicator
- uint_t dcd : 1; // Data Carrier Detect
+ uint_t dcts : 1; // Delta Clear To Send
+ uint_t ddsr : 1; // Delta Data Set Ready
+ uint_t teri : 1; // Trailing Edge Ring Indicator
+ uint_t ddcd : 1; // Delta Data Carrier Detect
+ uint_t cts : 1; // Clear to Send
+ uint_t dsr : 1; // Data Set Ready
+ uint_t ri : 1; // Ring Indicator
+ uint_t dcd : 1; // Data Carrier Detect
};
#define SERIAL_BUF_LEN 256
struct serial_buffer {
- uint_t head; // most recent data
- uint_t tail; // oldest char
- char buffer[SERIAL_BUF_LEN];
+ uint_t head; // most recent data
+ uint_t tail; // oldest char
+ char buffer[SERIAL_BUF_LEN];
};
static int queue_data(struct serial_buffer * buf, char data) {
- uint_t next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
+ uint_t next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
- if (next_loc == buf->tail) {
- return -1;
- }
+ if (next_loc == buf->tail) {
+ return -1;
+ }
- buf->buffer[next_loc] = data;
- buf->head = next_loc;
+ buf->buffer[next_loc] = data;
+ buf->head = next_loc;
- return 0;
+ return 0;
}
static int dequeue_data(struct serial_buffer * buf, char * data) {
- uint_t next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
+ uint_t next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
- if (buf->head == buf->tail) {
- return -1;
- }
+ if (buf->head == buf->tail) {
+ return -1;
+ }
- *data = buf->buffer[buf->tail];
- buf->tail = next_tail;
+ *data = buf->buffer[buf->tail];
+ buf->tail = next_tail;
- return 0;
+ return 0;
}
struct serial_port {
- char ier;
- char iir;
- char fcr;
- char lcr;
- char mcr;
- char lsr;
- char msr;
-
- struct serial_buffer tx_buffer;
- struct serial_buffer rx_buffer;
+ char ier;
+ char iir;
+ char fcr;
+ char lcr;
+ char mcr;
+ char lsr;
+ char msr;
+
+ struct serial_buffer tx_buffer;
+ struct serial_buffer rx_buffer;
};
struct serial_state {
- struct serial_port com1;
- struct serial_port com2;
- struct serial_port com3;
- struct serial_port com4;
+ struct serial_port com1;
+ struct serial_port com2;
+ struct serial_port com3;
+ struct serial_port com4;
};
static int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct serial_state * state = (struct serial_state *)dev->private_data;
- char * val = (char *)src;
- PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *(char*)src);
+ struct serial_state * state = (struct serial_state *)dev->private_data;
+ char * val = (char *)src;
+ PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *(char*)src);
- if (length != 1) {
- PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
- return -1;
- }
-
- switch (port) {
- case COM1_DATA_PORT:
- queue_data(&(state->com1.tx_buffer), *val);
- break;
- case COM2_DATA_PORT:
- queue_data(&(state->com2.tx_buffer), *val);
- break;
- case COM3_DATA_PORT:
- queue_data(&(state->com3.tx_buffer), *val);
- break;
- case COM4_DATA_PORT:
- queue_data(&(state->com4.tx_buffer), *val);
- break;
- default:
- return -1;
- }
+ if (length != 1) {
+ PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
+ return -1;
+ }
+
+ switch (port) {
+ case COM1_DATA_PORT:
+ queue_data(&(state->com1.tx_buffer), *val);
+ break;
+ case COM2_DATA_PORT:
+ queue_data(&(state->com2.tx_buffer), *val);
+ break;
+ case COM3_DATA_PORT:
+ queue_data(&(state->com3.tx_buffer), *val);
+ break;
+ case COM4_DATA_PORT:
+ queue_data(&(state->com4.tx_buffer), *val);
+ break;
+ default:
+ return -1;
+ }
- return length;
+ return length;
}
static int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct serial_state * state = (struct serial_state *)dev->private_data;
- char * val = (char *)dst;
- PrintDebug("Read from Data Port 0x%x\n", port);
+ struct serial_state * state = (struct serial_state *)dev->private_data;
+ char * val = (char *)dst;
+ PrintDebug("Read from Data Port 0x%x\n", port);
- if (length != 1) {
- PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
- return -1;
- }
-
- switch (port) {
- case COM1_DATA_PORT:
- dequeue_data(&(state->com1.tx_buffer), val);
- break;
- case COM2_DATA_PORT:
- dequeue_data(&(state->com2.tx_buffer), val);
- break;
- case COM3_DATA_PORT:
- dequeue_data(&(state->com3.tx_buffer), val);
- break;
- case COM4_DATA_PORT:
- dequeue_data(&(state->com4.tx_buffer), val);
- break;
- default:
- return -1;
- }
+ if (length != 1) {
+ PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
+ return -1;
+ }
+
+ switch (port) {
+ case COM1_DATA_PORT:
+ dequeue_data(&(state->com1.tx_buffer), val);
+ break;
+ case COM2_DATA_PORT:
+ dequeue_data(&(state->com2.tx_buffer), val);
+ break;
+ case COM3_DATA_PORT:
+ dequeue_data(&(state->com3.tx_buffer), val);
+ break;
+ case COM4_DATA_PORT:
+ dequeue_data(&(state->com4.tx_buffer), val);
+ break;
+ default:
+ return -1;
+ }
- return length;
+ return length;
}
static int handle_ier_write(struct serial_port * com, struct irq_enable_reg * ier) {
- return -1;
+ return -1;
}
static int write_ctrl_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- struct serial_state * state = (struct serial_state *)dev->private_data;
- char * val = (char *)src;
- PrintDebug("Write to Control Port (val=%x)\n", *(char *)src);
-
- if (length != 1) {
- PrintDebug("Invalid Write length to control port %d\n", port);
- return -1;
- }
+ struct serial_state * state = (struct serial_state *)dev->private_data;
+ char * val = (char *)src;
+ PrintDebug("Write to Control Port (val=%x)\n", *(char *)src);
- switch (port) {
- case COM1_IRQ_ENABLE_PORT:
- if (handle_ier_write(&(state->com1), (struct irq_enable_reg *)val) == -1) {
- return -1;
+ if (length != 1) {
+ PrintDebug("Invalid Write length to control port %d\n", port);
+ return -1;
}
- break;
- case COM2_IRQ_ENABLE_PORT:
- if (handle_ier_write(&(state->com2), (struct irq_enable_reg *)val) == -1) {
- return -1;
- }
- break;
- case COM3_IRQ_ENABLE_PORT:
- if (handle_ier_write(&(state->com3), (struct irq_enable_reg *)val) == -1) {
- return -1;
- }
- break;
- case COM4_IRQ_ENABLE_PORT:
- if (handle_ier_write(&(state->com4), (struct irq_enable_reg *)val) == -1) {
- return -1;
- }
- break;
-
- case COM1_FIFO_CTRL_PORT:
- case COM2_FIFO_CTRL_PORT:
- case COM3_FIFO_CTRL_PORT:
- case COM4_FIFO_CTRL_PORT:
-
- case COM1_LINE_CTRL_PORT:
- case COM2_LINE_CTRL_PORT:
- case COM3_LINE_CTRL_PORT:
- case COM4_LINE_CTRL_PORT:
-
- case COM1_MODEM_CTRL_PORT:
- case COM2_MODEM_CTRL_PORT:
- case COM3_MODEM_CTRL_PORT:
- case COM4_MODEM_CTRL_PORT:
+
+ switch (port) {
+ case COM1_IRQ_ENABLE_PORT:
+ if (handle_ier_write(&(state->com1), (struct irq_enable_reg *)val) == -1) {
+ return -1;
+ }
+ break;
+ case COM2_IRQ_ENABLE_PORT:
+ if (handle_ier_write(&(state->com2), (struct irq_enable_reg *)val) == -1) {
+ return -1;
+ }
+ break;
+ case COM3_IRQ_ENABLE_PORT:
+ if (handle_ier_write(&(state->com3), (struct irq_enable_reg *)val) == -1) {
+ return -1;
+ }
+ break;
+ case COM4_IRQ_ENABLE_PORT:
+ if (handle_ier_write(&(state->com4), (struct irq_enable_reg *)val) == -1) {
+ return -1;
+ }
+ break;
+
+ case COM1_FIFO_CTRL_PORT:
+ case COM2_FIFO_CTRL_PORT:
+ case COM3_FIFO_CTRL_PORT:
+ case COM4_FIFO_CTRL_PORT:
+
+ case COM1_LINE_CTRL_PORT:
+ case COM2_LINE_CTRL_PORT:
+ case COM3_LINE_CTRL_PORT:
+ case COM4_LINE_CTRL_PORT:
+
+ case COM1_MODEM_CTRL_PORT:
+ case COM2_MODEM_CTRL_PORT:
+ case COM3_MODEM_CTRL_PORT:
+ case COM4_MODEM_CTRL_PORT:
- default:
- return -1;
- }
+ default:
+ return -1;
+ }
- return -1;
+ return -1;
}
static int read_ctrl_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct serial_state * state = (struct serial_state *)dev->private_data;
- char * val = (char *)dst;
- PrintDebug("Read from Control Port\n");
+ struct serial_state * state = (struct serial_state *)dev->private_data;
+ char * val = (char *)dst;
+ PrintDebug("Read from Control Port\n");
- if (length != 1) {
- PrintDebug("Invalid Read length to control port\n");
- return -1;
- }
-
- switch (port) {
- case COM1_IRQ_ENABLE_PORT:
- *val = state->com1.ier;
- break;
- case COM2_IRQ_ENABLE_PORT:
- *val = state->com2.ier;
- break;
- case COM3_IRQ_ENABLE_PORT:
- *val = state->com3.ier;
- break;
- case COM4_IRQ_ENABLE_PORT:
- *val = state->com4.ier;
- break;
-
- case COM1_FIFO_CTRL_PORT:
- *val = state->com1.fcr;
- break;
- case COM2_FIFO_CTRL_PORT:
- *val = state->com2.fcr;
- break;
- case COM3_FIFO_CTRL_PORT:
- *val = state->com3.fcr;
- break;
- case COM4_FIFO_CTRL_PORT:
- *val = state->com4.fcr;
- break;
-
- case COM1_LINE_CTRL_PORT:
- *val = state->com1.lcr;
- break;
- case COM2_LINE_CTRL_PORT:
- *val = state->com2.lcr;
- break;
- case COM3_LINE_CTRL_PORT:
- *val = state->com3.lcr;
- break;
- case COM4_LINE_CTRL_PORT:
- *val = state->com4.lcr;
- break;
-
- case COM1_MODEM_CTRL_PORT:
- *val = state->com1.mcr;
- break;
- case COM2_MODEM_CTRL_PORT:
- *val = state->com2.mcr;
- break;
- case COM3_MODEM_CTRL_PORT:
- *val = state->com3.mcr;
- break;
- case COM4_MODEM_CTRL_PORT:
- *val = state->com4.mcr;
- break;
-
- default:
- return -1;
- }
+ if (length != 1) {
+ PrintDebug("Invalid Read length to control port\n");
+ return -1;
+ }
+
+ switch (port) {
+ case COM1_IRQ_ENABLE_PORT:
+ *val = state->com1.ier;
+ break;
+ case COM2_IRQ_ENABLE_PORT:
+ *val = state->com2.ier;
+ break;
+ case COM3_IRQ_ENABLE_PORT:
+ *val = state->com3.ier;
+ break;
+ case COM4_IRQ_ENABLE_PORT:
+ *val = state->com4.ier;
+ break;
+
+ case COM1_FIFO_CTRL_PORT:
+ *val = state->com1.fcr;
+ break;
+ case COM2_FIFO_CTRL_PORT:
+ *val = state->com2.fcr;
+ break;
+ case COM3_FIFO_CTRL_PORT:
+ *val = state->com3.fcr;
+ break;
+ case COM4_FIFO_CTRL_PORT:
+ *val = state->com4.fcr;
+ break;
+
+ case COM1_LINE_CTRL_PORT:
+ *val = state->com1.lcr;
+ break;
+ case COM2_LINE_CTRL_PORT:
+ *val = state->com2.lcr;
+ break;
+ case COM3_LINE_CTRL_PORT:
+ *val = state->com3.lcr;
+ break;
+ case COM4_LINE_CTRL_PORT:
+ *val = state->com4.lcr;
+ break;
+
+ case COM1_MODEM_CTRL_PORT:
+ *val = state->com1.mcr;
+ break;
+ case COM2_MODEM_CTRL_PORT:
+ *val = state->com2.mcr;
+ break;
+ case COM3_MODEM_CTRL_PORT:
+ *val = state->com3.mcr;
+ break;
+ case COM4_MODEM_CTRL_PORT:
+ *val = state->com4.mcr;
+ break;
+
+ default:
+ return -1;
+ }
- return length;
+ return length;
}
static int write_status_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- PrintDebug("Write to Status Port 0x%x (val=%x)\n", port, *(char *)src);
+ PrintDebug("Write to Status Port 0x%x (val=%x)\n", port, *(char *)src);
- return -1;
+ return -1;
}
static int read_status_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- struct serial_state * state = (struct serial_state *)dev->private_data;
- char * val = (char *)dst;
- PrintDebug("Read from Status Port 0x%x\n", port);
+ struct serial_state * state = (struct serial_state *)dev->private_data;
+ char * val = (char *)dst;
+ PrintDebug("Read from Status Port 0x%x\n", port);
- if (length != 1) {
- PrintDebug("Invalid Read length to control port\n");
- return -1;
- }
+ if (length != 1) {
+ PrintDebug("Invalid Read length to control port\n");
+ return -1;
+ }
- switch (port) {
- case COM1_LINE_STATUS_PORT:
- *val = state->com1.lsr;
- break;
- case COM2_LINE_STATUS_PORT:
- *val = state->com2.lsr;
- break;
- case COM3_LINE_STATUS_PORT:
- *val = state->com3.lsr;
- break;
- case COM4_LINE_STATUS_PORT:
- *val = state->com4.lsr;
- break;
+ switch (port) {
+ case COM1_LINE_STATUS_PORT:
+ *val = state->com1.lsr;
+ break;
+ case COM2_LINE_STATUS_PORT:
+ *val = state->com2.lsr;
+ break;
+ case COM3_LINE_STATUS_PORT:
+ *val = state->com3.lsr;
+ break;
+ case COM4_LINE_STATUS_PORT:
+ *val = state->com4.lsr;
+ break;
- case COM1_MODEM_STATUS_PORT:
- *val = state->com1.msr;
- break;
- case COM2_MODEM_STATUS_PORT:
- *val = state->com2.msr;
- break;
- case COM3_MODEM_STATUS_PORT:
- *val = state->com3.msr;
- break;
- case COM4_MODEM_STATUS_PORT:
- *val = state->com4.msr;
- break;
-
- default:
- return -1;
- }
+ case COM1_MODEM_STATUS_PORT:
+ *val = state->com1.msr;
+ break;
+ case COM2_MODEM_STATUS_PORT:
+ *val = state->com2.msr;
+ break;
+ case COM3_MODEM_STATUS_PORT:
+ *val = state->com3.msr;
+ break;
+ case COM4_MODEM_STATUS_PORT:
+ *val = state->com4.msr;
+ break;
+
+ default:
+ return -1;
+ }
- return length;
+ return length;
}
static int init_serial_port(struct serial_port * com) {
- //struct irq_enable_reg * ier = (struct irq_enable_reg *)&(com->ier);
- //struct irq_id_reg * iir = (struct irq_id_reg *)&(com->iir);
- //struct fifo_ctrl_reg * fcr = (struct fifo_ctrl_reg *)&(com->fcr);
- //struct line_ctrl_reg * lcr = (struct line_ctrl_reg *)&(com->lcr);
- //struct modem_ctrl_reg * mcr = (struct modem_ctrl_reg *)&(com->mcr);
- //struct line_status_reg * lsr = (struct line_status_reg *)&(com->lsr);
- //struct modem_status_reg * msr = (struct modem_status_reg *)&(com->msr);
-
- com->ier = 0x00;
- com->iir = 0x01;
- com->fcr = 0x00;
- com->lcr = 0x00;
- com->mcr = 0x00;
- com->lsr = 0x60;
- com->msr = 0x00;
-
- return 0;
+ //struct irq_enable_reg * ier = (struct irq_enable_reg *)&(com->ier);
+ //struct irq_id_reg * iir = (struct irq_id_reg *)&(com->iir);
+ //struct fifo_ctrl_reg * fcr = (struct fifo_ctrl_reg *)&(com->fcr);
+ //struct line_ctrl_reg * lcr = (struct line_ctrl_reg *)&(com->lcr);
+ //struct modem_ctrl_reg * mcr = (struct modem_ctrl_reg *)&(com->mcr);
+ //struct line_status_reg * lsr = (struct line_status_reg *)&(com->lsr);
+ //struct modem_status_reg * msr = (struct modem_status_reg *)&(com->msr);
+
+ com->ier = 0x00;
+ com->iir = 0x01;
+ com->fcr = 0x00;
+ com->lcr = 0x00;
+ com->mcr = 0x00;
+ com->lsr = 0x60;
+ com->msr = 0x00;
+
+ return 0;
}
static int serial_init(struct vm_device * dev) {
- struct serial_state * state = (struct serial_state *)dev->private_data;
-
-
- init_serial_port(&(state->com1));
- init_serial_port(&(state->com2));
- init_serial_port(&(state->com3));
- init_serial_port(&(state->com4));
-
- v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
- v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
- v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
- v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
- v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
- v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
- v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
- v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
- v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
- v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
- return 0;
+ struct serial_state * state = (struct serial_state *)dev->private_data;
+
+
+ init_serial_port(&(state->com1));
+ init_serial_port(&(state->com2));
+ init_serial_port(&(state->com3));
+ init_serial_port(&(state->com4));
+
+ v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
+ v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+ v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+ v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+ v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
+ v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+ v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+ v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+ v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
+ v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+ v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+ v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+ v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
+ v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+ v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+ v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+ v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+ return 0;
}
static int serial_deinit(struct vm_device * dev) {
- v3_dev_unhook_io(dev, COM1_DATA_PORT);
- v3_dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
- v3_dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
- v3_dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
- v3_dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
- v3_dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
- v3_dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
- v3_dev_unhook_io(dev, COM1_SCRATCH_PORT);
-
- v3_dev_unhook_io(dev, COM2_DATA_PORT);
- v3_dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
- v3_dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
- v3_dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
- v3_dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
- v3_dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
- v3_dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
- v3_dev_unhook_io(dev, COM2_SCRATCH_PORT);
-
- v3_dev_unhook_io(dev, COM3_DATA_PORT);
- v3_dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
- v3_dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
- v3_dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
- v3_dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
- v3_dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
- v3_dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
- v3_dev_unhook_io(dev, COM3_SCRATCH_PORT);
-
- v3_dev_unhook_io(dev, COM4_DATA_PORT);
- v3_dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
- v3_dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
- v3_dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
- v3_dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
- v3_dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
- v3_dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
- v3_dev_unhook_io(dev, COM4_SCRATCH_PORT);
-
- return 0;
+ v3_dev_unhook_io(dev, COM1_DATA_PORT);
+ v3_dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
+ v3_dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
+ v3_dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
+ v3_dev_unhook_io(dev, COM1_SCRATCH_PORT);
+
+ v3_dev_unhook_io(dev, COM2_DATA_PORT);
+ v3_dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
+ v3_dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
+ v3_dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
+ v3_dev_unhook_io(dev, COM2_SCRATCH_PORT);
+
+ v3_dev_unhook_io(dev, COM3_DATA_PORT);
+ v3_dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
+ v3_dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
+ v3_dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
+ v3_dev_unhook_io(dev, COM3_SCRATCH_PORT);
+
+ v3_dev_unhook_io(dev, COM4_DATA_PORT);
+ v3_dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
+ v3_dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
+ v3_dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
+ v3_dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
+ v3_dev_unhook_io(dev, COM4_SCRATCH_PORT);
+
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = serial_init,
- .deinit = serial_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = serial_init,
+ .deinit = serial_deinit,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_serial(int num_ports) {
- struct serial_state * state = NULL;
- state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
- V3_ASSERT(state != NULL);
+ struct serial_state * state = NULL;
+ state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
+ V3_ASSERT(state != NULL);
- struct vm_device * device = v3_create_device("Serial UART", &dev_ops, state);
+ struct vm_device * device = v3_create_device("Serial UART", &dev_ops, state);
- return device;
+ return device;
}
#include <palacios/vmm.h>
struct pic_internal {
- int pending_irq;
+ int pending_irq;
};
static int pic_intr_pending(void * private_data) {
- struct pic_internal * data = (struct pic_internal *)private_data;
+ struct pic_internal * data = (struct pic_internal *)private_data;
- return (data->pending_irq > 0);
+ return (data->pending_irq > 0);
}
static int pic_raise_intr(void * private_data, int irq) {
- struct pic_internal * data = (struct pic_internal *)private_data;
+ struct pic_internal * data = (struct pic_internal *)private_data;
- data->pending_irq = irq;
+ data->pending_irq = irq;
- return 0;
+ return 0;
}
static int pic_get_intr_number(void * private_data) {
- struct pic_internal * data = (struct pic_internal *)private_data;
+ struct pic_internal * data = (struct pic_internal *)private_data;
- return data->pending_irq;
+ return data->pending_irq;
}
static struct intr_ctrl_ops intr_ops = {
- .intr_pending = pic_intr_pending,
- .get_intr_number = pic_get_intr_number,
- .raise_intr = pic_raise_intr
+ .intr_pending = pic_intr_pending,
+ .get_intr_number = pic_get_intr_number,
+ .raise_intr = pic_raise_intr
};
static int pic_init_device(struct vm_device * dev) {
- struct pic_internal * data = (struct pic_internal *)dev->private_data;
- v3_register_intr_controller(dev->vm, &intr_ops, data);
- data->pending_irq = 0;
+ struct pic_internal * data = (struct pic_internal *)dev->private_data;
+ v3_register_intr_controller(dev->vm, &intr_ops, data);
+ data->pending_irq = 0;
- return 0;
+ return 0;
}
static int pic_deinit_device(struct vm_device * dev) {
- return 0;
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = pic_init_device,
- .deinit = pic_deinit_device,
- .reset = NULL,
- .start = NULL,
- .stop = NULL
+ .init = pic_init_device,
+ .deinit = pic_deinit_device,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL
};
struct vm_device * v3_create_simple_pic() {
- struct pic_internal * state = NULL;
- state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
- V3_ASSERT(state != NULL);
+ struct pic_internal * state = NULL;
+ state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
+ V3_ASSERT(state != NULL);
- struct vm_device * pic_dev = v3_create_device("Simple Pic", &dev_ops, state);
+ struct vm_device * pic_dev = v3_create_device("Simple Pic", &dev_ops, state);
- return pic_dev;
+ return pic_dev;
}
#define TIMER_IRQ 32
struct timer_state {
- int foo;
+ int foo;
};
/*
-static int irq_handler(uint_t irq, struct vm_device * dev) {
+ static int irq_handler(uint_t irq, struct vm_device * dev) {
PrintDebug("Timer interrupt\n");
return 0;
-}
+ }
*/
static int timer_init(struct vm_device * dev) {
- //dev_hook_irq(dev, TIMER_IRQ, &irq_handler);
+ //dev_hook_irq(dev, TIMER_IRQ, &irq_handler);
- return 0;
+ return 0;
}
static int timer_deinit(struct vm_device * dev) {
- return 0;
+ return 0;
}
static struct vm_device_ops dev_ops = {
- .init = timer_init,
- .deinit = timer_deinit,
- .reset = NULL,
- .start = NULL,
- .stop = NULL,
+ .init = timer_init,
+ .deinit = timer_deinit,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
};
struct vm_device * v3_create_timer() {
- struct timer_state * timer = NULL;
- timer = (struct timer_state *)V3_Malloc( sizeof(struct timer_state));
- V3_ASSERT(timer != NULL);
+ struct timer_state * timer = NULL;
+ timer = (struct timer_state *)V3_Malloc( sizeof(struct timer_state));
+ V3_ASSERT(timer != NULL);
- struct vm_device * dev = v3_create_device("Timer", &dev_ops, timer);
+ struct vm_device * dev = v3_create_device("Timer", &dev_ops, timer);
- return dev;
+ return dev;
}