Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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