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.


added pic device
Jack Lange [Wed, 23 Apr 2008 20:56:50 +0000 (20:56 +0000)]
palacios/build/Makefile
palacios/include/devices/8259a.h
palacios/include/devices/simple_pic.h
palacios/src/devices/8259a.c
palacios/src/devices/simple_pic.c
palacios/src/geekos/vm.c

index 416b0c7..4a28af3 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for GeekOS kernel, userspace, and tools
 # Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
-# $Revision: 1.27 $
+# $Revision: 1.28 $
 
 # This is free software.  You are permitted to use,
 # redistribute, and modify it as specified in the file "COPYING".
@@ -134,7 +134,7 @@ VMM_C_OBJS := $(VMM_C_SRCS:%.c=palacios/%.o)
 
 VMM_OBJS := $(VMM_C_OBJS) $(VMM_ASM_OBJS)
 
-DEVICE_C_SRCS :=  nvram.c timer.c simple_pic.c
+DEVICE_C_SRCS :=  nvram.c timer.c simple_pic.c 8259a.c
 
 DEVICE_C_OBJS := $(DEVICE_C_SRCS:%.c=devices/%.o)
 
index 64fa889..23567d3 100644 (file)
@@ -1,9 +1,10 @@
 #ifndef __8259A_H
 #define __8259A_H
 
+#include <palacios/vm_dev.h>
 
 
-
+struct vm_device * create_pic();
 
 
 #endif
index 58a9080..bc651da 100644 (file)
@@ -2,6 +2,6 @@
 #define __SIMPLE_PIC_H
 #include <palacios/vm_dev.h>
 
-struct vm_device * create_pic();
+struct vm_device * create_simple_pic();
 
 #endif
index 60d6180..2e305e9 100644 (file)
@@ -1,9 +1,464 @@
-#include <palacios/8259a.h>
+#include <devices/8259a.h>
+#include <palacios/vmm_intr.h>
+#include <palacios/vmm_types.h>
 #include <palacios/vmm.h>
 
 
+typedef enum {RESET, ICW1, ICW2, ICW3, ICW4,  READY} pic_state_t;
+
+static const uint_t MASTER_PORT1 = 0x20;
+static const uint_t MASTER_PORT2 = 0x21;
+static const uint_t SLAVE_PORT1 = 0xA0;
+static const uint_t SLAVE_PORT2 = 0xA1;
+
+#define IS_OCW2(x) (((x & 0x18) >> 3) == 0x0)
+#define IS_OCW3(x) (((x & 0x18) >> 3) == 0x1)
+
+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;
+};
+
+
+struct icw2 {
+  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;
+};
+
+// The ID is the Slave device ID
+struct icw3_slave {
+  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;
+};
+
+
+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;
+};
+
+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;
+};
+
+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;
+};
+
+
+struct pic_internal {
+
+
+  char master_irr;
+  char slave_irr;
+  
+  char master_isr;
+  char slave_isr;
+
+  char master_icw1;
+  char master_icw2;
+  char master_icw3;
+  char master_icw4;
+
+
+  char slave_icw1;
+  char slave_icw2;
+  char slave_icw3;
+  char slave_icw4;
+
+
+  char master_imr;
+  char slave_imr;
+  char master_ocw2;
+  char master_ocw3;
+  char slave_ocw2;
+  char slave_ocw3;
+
+  pic_state_t master_state;
+  pic_state_t slave_state;
+};
+
+
+
+static int pic_raise_intr(void * private_data, int irq, int error_code) {
+  struct pic_internal * state = (struct pic_internal*)private_data;
+
+  if (irq == 2) {
+    irq = 9;
+  }
+
+  if (irq <= 7) {
+    state->master_irr |= 0x1 << irq;
+  } else if ((irq > 7) && (irq < 16)) {
+    state->slave_irr |= 0x1 << (irq - 7);
+  } else {
+    return -1;
+  }
+
+  return 0;
+}
+
+static int pic_intr_pending(void * 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;
+  }
+
+  return 0;
+}
+
+static int pic_get_intr_number(void * private_data) {
+  struct pic_internal * state = (struct pic_internal*)private_data;
+  int i;
+
+  for (i = 0; i < 16; i++) {
+    if (i <= 7) {
+      if (((state->master_irr & ~(state->master_imr)) >> i) == 0x1) {
+       return i;
+      }
+    } else {
+      if (((state->slave_irr & ~(state->slave_imr)) >> i) == 0x1) {
+       return i;
+      }
+    }
+  }
+
+  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
+};
+
+
+
+
+
+
+
+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;
+  if (length != 1) {
+    //error
+  }
+  
+  if ((state->master_ocw3 & 0x3) == 0x2) {
+    *(char *)dst = state->master_irr;
+  } else if ((state->master_ocw3 & 0x3) == 0x3) {
+    *(char *)dst = state->master_isr;
+  } else {
+    *(char *)dst = 0;
+  }
+  
+  return 1;
+}
+
+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;
+  if (length != 1) {
+    // error
+  }
+
+  *(char *)dst = state->master_imr;
+
+  return 1;
+  
+}
+
+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;
+  if (length != 1) {
+    // error
+  }
+  
+  if ((state->slave_ocw3 & 0x3) == 0x2) {
+    *(char*)dst = state->slave_irr;
+  } else if ((state->slave_ocw3 & 0x3) == 0x3) {
+    *(char *)dst = state->slave_isr;
+  } else {
+    *(char *)dst = 0;
+  }
+
+  return 1;
+}
+
+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;
+  if (length != 1) {
+    // error
+  }
+
+  *(char *)dst = state->slave_imr;
+
+  return 1;
+}
+
+
+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;
+  char cw = *(char *)src;
+
+  if (length != 1) {
+    // error
+  }
+  
+  if (state->master_state == ICW1) {
+    state->master_icw1 = cw;
+    state->master_state = ICW2;
+  } else if (state->master_state == READY) {
+    if (IS_OCW2(cw)) {
+      state->master_ocw2 = cw;
+    } else if (IS_OCW3(cw)) {
+      state->master_ocw3 = cw;
+    } else {
+      // error
+    }
+  } else {
+    // error
+  }
+
+  return 1;
+}
+
+int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+    char cw = *(char *)src;    
+
+    if (length != 1) {
+      //error
+    }
+    
+    if (state->master_state == ICW2) {
+      struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
+
+      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;
+      }
+
+    } else if (state->master_state == ICW3) {
+      struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
+
+      state->master_icw3 = cw;
+
+      if (cw1->ic4 == 1) {
+       state->master_state = ICW4;
+      } else {
+       state->master_state = READY;
+      }
+
+    } else if (state->master_state == ICW4) {
+      state->master_icw4 = cw;
+      state->master_state = READY;
+    } else if (state->master_state == READY) {
+      state->master_imr = cw;
+    } else {
+      // error
+    }
+
+    return 1;
+}
+
+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;
+  char cw = *(char *)src;
+
+  if (length != 1) {
+    // error
+  }
+
+  if (state->slave_state == ICW1) {
+    state->slave_icw1 = cw;
+    state->slave_state = ICW2;
+  } else if (state->slave_state == READY) {
+    if (IS_OCW2(cw)) {
+      state->slave_ocw2 = cw;
+    } else if (IS_OCW3(cw)) {
+      state->slave_ocw3 = cw;
+    } else {
+      // error
+    }
+  } else {
+    // error
+  }
+
+  return 1;
+}
+
+int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct pic_internal * state = (struct pic_internal*)dev->private_data;
+    char cw = *(char *)src;    
+
+    if (length != 1) {
+      //error
+    }
+
+    if (state->slave_state == ICW2) {
+      struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
+
+      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;
+      }
+
+    } else if (state->slave_state == ICW3) {
+      struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
+
+      state->slave_icw3 = cw;
+
+      if (cw1->ic4 == 1) {
+       state->slave_state = ICW4;
+      } else {
+       state->slave_state = READY;
+      }
+
+    } else if (state->slave_state == ICW4) {
+      state->slave_icw4 = cw;
+      state->slave_state = READY;
+    } else if (state->slave_state == READY) {
+      state->slave_imr = cw;
+    } else {
+      // error
+    }
+
+    return 1;
+}
+
+
+
+
+
+
+
+
+int pic_init(struct vm_device * dev) {
+  struct pic_internal * state = (struct pic_internal*)dev->private_data;
+
+  set_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 = 0x2;
+  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 = 0x2;
+  state->slave_state = ICW1;
+
+
+  dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
+  dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
+  dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
+  dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
+
+  return 0;
+}
+
+
+int pic_deinit(struct vm_device * dev) {
+  dev_unhook_io(dev, MASTER_PORT1);
+  dev_unhook_io(dev, MASTER_PORT2);
+  dev_unhook_io(dev, SLAVE_PORT1);
+  dev_unhook_io(dev, SLAVE_PORT2);
+
+  return 0;
+}
+
+
+
+
+
+
+
+static struct vm_device_ops dev_ops = {
+  .init = pic_init,
+  .deinit = pic_deinit,
+  .reset = NULL,
+  .start = NULL,
+  .stop = NULL,
+};
+
+
+struct vm_device * create_pic() {
+  struct pic_internal * state = NULL;
+  VMMMalloc(struct pic_internal *, state, sizeof(struct pic_internal));
+
+  struct vm_device *device = create_device("8259A", &dev_ops, state);
+
+  return device;
+}
+
+
+
 
-static const uint_t PIC1_PORT_1 0x20;
-static const uint_t PIC1_PORT_2 0x21;
-static const uint_t PIC2_PORT_1 0xA0;
-static const uint_t PIC2_PORT_2 0xA1;
index a4e25f5..c3539b7 100644 (file)
@@ -9,13 +9,13 @@ struct pic_internal {
 };
 
 
-int pic_intr_pending(void * private_data) {
+static int pic_intr_pending(void * private_data) {
   struct pic_internal * data = (struct pic_internal *)private_data;
   
   return (data->pending_irq > 0);
 }
 
-int pic_raise_intr(void * private_data, int irq, int error_code) {
+static int pic_raise_intr(void * private_data, int irq, int error_code) {
   struct pic_internal * data = (struct pic_internal *)private_data;
 
   data->pending_irq = irq;
@@ -25,7 +25,7 @@ int pic_raise_intr(void * private_data, int irq, int error_code) {
 }
 
 
-int pic_get_intr_number(void * private_data) {
+static int pic_get_intr_number(void * private_data) {
   struct pic_internal * data = (struct pic_internal *)private_data;
 
   return data->pending_irq;
@@ -67,7 +67,7 @@ static struct vm_device_ops dev_ops = {
 };
 
 
-struct vm_device * create_pic() {
+struct vm_device * create_simple_pic() {
   struct pic_internal * state = NULL;
   VMMMalloc(struct pic_internal *, state, sizeof(struct pic_internal));
 
index 4375e43..2697333 100644 (file)
@@ -8,6 +8,7 @@
 #include <devices/nvram.h>
 #include <devices/timer.h>
 #include <devices/simple_pic.h>
+#include <devices/8259a.h>
 #include <palacios/vmm_intr.h>
 
 
@@ -281,11 +282,12 @@ int RunVMM(struct Boot_Info * bootInfo) {
       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
 
-      hook_io_port(&(vm_info.io_map), 0x20, &IO_Read, &IO_Write_to_Serial, NULL);
-      hook_io_port(&(vm_info.io_map), 0x21, &IO_Read, &IO_Write_to_Serial, NULL);
-      hook_io_port(&(vm_info.io_map), 0xa0, &IO_Read, &IO_Write_to_Serial, NULL);
-      hook_io_port(&(vm_info.io_map), 0xa1, &IO_Read, &IO_Write_to_Serial, NULL);
-
+      /*
+       hook_io_port(&(vm_info.io_map), 0x20, &IO_Read, &IO_Write_to_Serial, NULL);
+       hook_io_port(&(vm_info.io_map), 0x21, &IO_Read, &IO_Write_to_Serial, NULL);
+       hook_io_port(&(vm_info.io_map), 0xa0, &IO_Read, &IO_Write_to_Serial, NULL);
+       hook_io_port(&(vm_info.io_map), 0xa1, &IO_Read, &IO_Write_to_Serial, NULL);
+      */
       hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial, NULL);
       hook_io_port(&(vm_info.io_map), 0x401, &IO_Read, &IO_Write_to_Serial, NULL);
       hook_io_port(&(vm_info.io_map), 0x402, &IO_Read, &IO_BOCHS_debug, NULL);