# Makefile for GeekOS kernel, userspace, and tools
 # Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
-# $Revision: 1.69 $
+# $Revision: 1.70 $
 
 # This is free software.  You are permitted to use,
 # redistribute, and modify it as specified in the file "COPYING".
 endif
 
 
-DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DTEST_NE2K
+#DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DTEST_NE2K
 
 ifeq ($(DEBUG),1)
   JRLDEBUG= -DSERIAL_PRINT_DEBUG=1 -DSERIAL_PRINT_DEBUG_LEVEL=10 -DSERIAL_PRINT=1 -DVMM_DEBUG=1 -DVMM_INFO=1 -DVMM_TRACE=1 $(DEBUG_SECTIONS)
        serial.c  reboot.c \
         paging.c \
        debug.c vmm_stubs.c  vm.c  pci.c\
-       queue.c socket.c ring_buffer.c \
+       queue.c  ring_buffer.c \
        main.c
+       #socket.c
 
 # Kernel object files built from C source files
 KERNEL_C_OBJS := $(KERNEL_C_SRCS:%.c=geekos/%.o)
 
 /*
  * GeekOS timer interrupt support
  * Copyright (c) 2001, David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
 
 extern volatile ulong_t g_numTicks;
 
+typedef void (*timerCallback)(int);
+
 void Init_Timer(void);
 
 void Micro_Delay(int us);
 
 
+typedef struct {
+    int ticks;                           /* timer code decrements this */
+    int id;                              /* unqiue id for this timer even */
+    timerCallback callBack;              /* Queue to wakeup on timer expire */
+    int origTicks;
+} timerEvent;
+
+int Start_Timer(int ticks, timerCallback);
+int Get_Remaing_Timer_Ticks(int id);
+int Cancel_Timer(int id);
+
+
 void Micro_Delay(int us);
 
 #endif  /* GEEKOS_TIMER_H */
 
 
   vm_operating_mode_t run_state;
   void * vmm_data;
+
+  /* TEMP */
+  //ullong_t exit_tsc;
+
 };
 
 
 
 #ifndef DEBUG_PIC
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
-#define PrintPicTrace(_f, _a...) PrintTrace("\n8259a.c(%d) "_f, __LINE__, ## _a)
+//#define PrintPicTrace(_f, _a...) PrintTrace("\n8259a.c(%d) "_f, __LINE__, ## _a)
 #endif
 
 
 
   struct pic_internal *state = (struct pic_internal*)private_data;
 
-  PrintPicTrace("[pic_lower_intr] IRQ line %d now low\n", (unsigned) irq_no);
+  PrintDebug("[pic_lower_intr] IRQ line %d now low\n", (unsigned) irq_no);
   if (irq_no <= 7) {
 
     state->master_irr &= ~(1 << irq_no);
     if ((state->master_irr & ~(state->master_imr)) == 0) {
-      PrintPicTrace("\t\tFIXME: Master maybe should do sth\n");
+      PrintDebug("\t\tFIXME: Master maybe should do sth\n");
     }
   } else if ((irq_no > 7) && (irq_no <= 15)) {
 
     state->slave_irr &= ~(1 << (irq_no - 8));
     if ((state->slave_irr & (~(state->slave_imr))) == 0) {
-      PrintPicTrace("\t\tFIXME: Slave maybe should do sth\n");
+      PrintDebug("\t\tFIXME: Slave maybe should do sth\n");
     }
   }
   return 0;
 
  * Copyright (c) 2001,2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
  * Copyright (c) 2004, Iulian Neamtiu <neamtiu@cs.umd.edu>
- * $Revision: 1.45 $
+ * $Revision: 1.46 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
 
   Init_Stubs();
 
-
-#ifdef TEST_NE2K
+#if 0
   {
     init_network();
     uchar_t local_addr[4];
     local_addr[0] = 10;
     local_addr[1] = 0;
     local_addr[2] = 2;
-    local_addr[3] = 20;
+    local_addr[3] = 21;
 
     set_ip_addr(local_addr);
 
     remote_addr[0] = 10;
     remote_addr[1] = 0;
     remote_addr[2] = 2;
-    remote_addr[3] = 21;
+    remote_addr[3] = 20;
 
 
     connect(remote_addr, 4301);
   }
 #endif
 
-#if !TEST_NE2K
+
   {
     RunVMM(bootInfo);
   }
-#endif
 
 
   SerialPrint("RunVMM returned, spinning\n");
 
 
 static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
 {
+
   Begin_IRQ(state);
   PrintBoth("NIC Interrupt Occured!\n");
   uchar_t isr_content = In_Byte(NE2K_ISR);
 
 #include <uip/uip_arp.h>
 #include <geekos/vmm_stubs.h>
 #include <geekos/debug.h>
-
+#include <geekos/timer.h>
 
 
 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
 
 struct socket sockets[MAX_SOCKS];
 
+void socket_appcall(void);
+#ifndef UIP_APPCALL
+#define UIP_APPCALL socket_appcall
+#endif /* UIP_APPCALL */
+
+
 
 
-int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt);
+static int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt);
+static void periodic_caller(int timer_id);
 
 void init_network() {
    int i = 0;
+   bool iflag;
+
    
    for (i = 0; i < MAX_SOCKS; i++) {
       sockets[i].in_use = 0;
    }
 
 
+
     //initiate uIP
     uip_init();
     uip_arp_init();
     //setup device driver
     Init_Ne2k(&Packet_Received);
 
-
+    iflag = Begin_Int_Atomic();
+    Start_Timer(2, periodic_caller);
+    End_Int_Atomic(iflag);
 
 }
 
 }
 
 
+
+static void periodic_caller(int timer_id) {
+  int i;
+  //handle the periodic calls of uIP
+  
+  //PrintBoth("Timer CALLBACK handler\n");
+
+  for(i = 0; i < UIP_CONNS; ++i) {
+    uip_periodic(i);
+    if(uip_len > 0) {
+      //devicedriver_send();
+      PrintBoth("Sending Packet\n");
+      NE2K_Transmit(uip_len);
+    }
+  }
+  for(i = 0; i < UIP_UDP_CONNS; i++) {
+    uip_udp_periodic(i);
+    if(uip_len > 0) {
+    //devicedriver_send();
+      NE2K_Transmit(uip_len);
+    }
+  }
+}
+
+
 int connect(const uchar_t ip_addr[4], ushort_t port) {
   int sockfd = -1;
   sockfd = allocate_socket_fd();
-  uip_ipaddr_t ipaddr;
+  static uip_ipaddr_t ipaddr;
   
   if (sockfd == -1) {
     return -1;
   }
 
   uip_ipaddr(&ipaddr, ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);  
-
-  sockets[sockfd].state = WAITING;
   
-  sockets[sockfd].con = uip_connect((uip_ipaddr_t *)&ip_addr, htons(port));
+  sockets[sockfd].con = uip_connect(&ipaddr, htons(port));
 
 
   if (sockets[sockfd].con == NULL){
 
 
   PrintBoth("Connection start\n");
-
-  while(sockets[sockfd].state == WAITING) {
-    timer_int_handler(NULL);
-  }
-
+  Wait(&(sock->recv_wait_queue));
+  
     
   PrintBoth("Connected\n");
 
-  if (sockets[sockfd].state != ESTABLISHED) {
-    release_socket_fd(sockfd);
-    return -1;
-  }
+
 
 
   return sockfd;
   return recvlen;
 }
 
-void timer_int_Handler(struct Interrupt_State * state){
-       int i;
-       //handle the periodic calls of uIP
-       for(i = 0; i < UIP_CONNS; ++i) {
-              uip_periodic(i);
-               if(uip_len > 0) {
-                    //devicedriver_send();
-                    NE2K_Transmit(uip_len);
-               }
-       }
-       for(i = 0; i < UIP_UDP_CONNS; i++) {
-                uip_udp_periodic(i);
-                if(uip_len > 0) {
-                    //devicedriver_send();
-                    NE2K_Transmit(uip_len);
-               }
-       }
-}
+
 
 // a series of utilities to handle conncetion states
 static void connected(int sockfd) {
 
 
 
-int Packet_Received(struct NE2K_Packet_Info * info, uchar_t * pkt) {
+static int Packet_Received(struct NE2K_Packet_Info * info, uchar_t * pkt) {
   //int i;
-  
   uip_len = info->size; 
 
   //  for (i = 0; i < info->size; i++) {
   //  uip_buf[i] = *(pkt + i);
   //}
 
+  PrintBoth("Packet REceived\n");
+
   memcpy(uip_buf, pkt, uip_len);
 
 
   Free(pkt);
 
   if (BUF->type == htons(UIP_ETHTYPE_ARP)) {
+    PrintBoth("ARP PACKET\n");
+
     uip_arp_arpin();
 
+
     if (uip_len > 0) {
+      PrintBoth("Transmitting\n");
       NE2K_Transmit(uip_len);
-    }                                  
+    }  
+                       
 
   } else {
-
+    PrintBoth("Data PACKET\n");
     uip_arp_ipin();
     uip_input();
 
+
     if (uip_len > 0) {
+      PrintBoth("Transmitting\n");
       uip_arp_out();
       NE2K_Transmit(uip_len);
     }
+    
   }
-                         
-  return 0;
 
+  return 0;
 }
 
  * GeekOS timer interrupt support
  * Copyright (c) 2001,2003 David H. Hovemeyer <daveho@cs.umd.edu>
  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
- * $Revision: 1.10 $
+ * $Revision: 1.11 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
 #include <geekos/serial.h>
 #include <geekos/debug.h>
 
+#include <geekos/io_crap.h>
 
 /* PAD this currently is in nvram.c */
 extern void deliver_timer_interrupt_to_vmm(uint_t period_us);
 uint_t cpu_khz_freq;
 
 
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
 
-#ifdef REALLY_SLOW_IO
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
-#else
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
-#endif
-
-
-
-#define __OUT1(s,x) \
-static inline void out##s(unsigned x value, unsigned short port) {
-
-#define __OUT2(s,s1,s2) \
-__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
-
-#define __OUT(s,s1,x) \
-__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
-__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
-
-
-#define __IN1(s) \
-static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
-
-#define __IN2(s,s1,s2) \
-__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
-
-#define __IN(s,s1,i...) \
-__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
-__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
-
-
-#define RETURN_TYPE unsigned char
-__IN(b,"")
-#undef RETURN_TYPE
-#define RETURN_TYPE unsigned short
-__IN(w,"")
-#undef RETURN_TYPE
-#define RETURN_TYPE unsigned int
-__IN(l,"")
-#undef RETURN_TYPE
 
 
 
-__OUT(b,"b",char)
-__OUT(w,"w",short)
-
 
 
 
 
 
 
+#define MAX_TIMER_EVENTS       100
+
+static int timerDebug = 0;
+static int timeEventCount;
+static int nextEventID;
+timerEvent pendingTimerEvents[MAX_TIMER_EVENTS];
+
 
 
 /*
 
 static void Timer_Interrupt_Handler(struct Interrupt_State* state)
 {
-   struct Kernel_Thread* current = g_currentThread;
-
-    Begin_IRQ(state);
-
-
+  int i;
+  struct Kernel_Thread* current = g_currentThread;
 
-#if 0
-#define STACK_LEN 256
+  Begin_IRQ(state);
 
-    SerialPrint("Host Timer Interrupt Handler running\n");
-    SerialPrint("Timer====\n");
-    Dump_Interrupt_State(state);
-    //    SerialMemDump((unsigned char*)(¤t),STACK_LEN);
-    SerialPrint("Timer done===\n");
-
-#endif
-    /* Update global and per-thread number of ticks */
-    ++g_numTicks;
-    ++current->numTicks;
+  /* Update global and per-thread number of ticks */
+  ++g_numTicks;
+  ++current->numTicks;
+  
 
+  /* update timer events */
+  for (i=0; i < timeEventCount; i++) {
+    if (pendingTimerEvents[i].ticks == 0) {
+      if (timerDebug) Print("timer: event %d expired (%d ticks)\n", 
+                           pendingTimerEvents[i].id, pendingTimerEvents[i].origTicks);
+      (pendingTimerEvents[i].callBack)(pendingTimerEvents[i].id);
+      pendingTimerEvents[i].ticks = pendingTimerEvents[i].origTicks;
+    } else {
+      pendingTimerEvents[i].ticks--;
+    }
+  }
+
+  /*
+   * If thread has been running for an entire quantum,
+   * inform the interrupt return code that we want
+   * to choose a new thread.
+   */
+  if (current->numTicks >= g_Quantum) {
+    g_needReschedule = true;
     /*
-     * If thread has been running for an entire quantum,
-     * inform the interrupt return code that we want
-     * to choose a new thread.
+     * The current process is moved to a lower priority queue,
+     * since it consumed a full quantum.
      */
-    if (current->numTicks >= g_Quantum) {
-       g_needReschedule = true;
-    }
-
-
-    deliver_timer_interrupt_to_vmm(1000000/HZ);
-
-    End_IRQ(state);
+    //if (current->currentReadyQueue < (MAX_QUEUE_LEVEL - 1)) {
+      /*Print("process %d moved to ready queue %d\n", current->pid, current->currentReadyQueue); */
+      //current->currentReadyQueue++;
+    //}
+    
+  }
+  
+  
+  deliver_timer_interrupt_to_vmm(1000000/HZ);
+  
+  End_IRQ(state);
 }
 
 /*
 }
 
 
+int Start_Timer(int ticks, timerCallback cb)
+{
+    int ret;
+
+    KASSERT(!Interrupts_Enabled());
+
+    if (timeEventCount == MAX_TIMER_EVENTS) {
+       return -1;
+    } else {
+       ret = nextEventID++;
+       pendingTimerEvents[timeEventCount].id = ret;
+       pendingTimerEvents[timeEventCount].callBack = cb;
+       pendingTimerEvents[timeEventCount].ticks = ticks;
+       pendingTimerEvents[timeEventCount].origTicks = ticks;
+       timeEventCount++;
+
+       return ret;
+    }
+}
+
+int Get_Remaing_Timer_Ticks(int id)
+{
+    int i;
+
+    KASSERT(!Interrupts_Enabled());
+    for (i=0; i < timeEventCount; i++) {
+       if (pendingTimerEvents[i].id == id) {
+           return pendingTimerEvents[i].ticks;
+       }
+    }
+
+    return -1;
+}
+
+int Cancel_Timer(int id)
+{
+    int i;
+    KASSERT(!Interrupts_Enabled());
+    for (i=0; i < timeEventCount; i++) {
+       if (pendingTimerEvents[i].id == id) {
+           pendingTimerEvents[i] = pendingTimerEvents[timeEventCount-1];
+           timeEventCount--;
+           return 0;
+       }
+    }
+
+    Print("timer: unable to find timer id %d to cancel it\n", id);
+    return -1;
+}
+
+
 #define US_PER_TICK (HZ * 1000000)
 
 /*
 
 }
 
 
+
 // can we start a kernel thread here...
-static int start_svm_guest(struct guest_info *info) {
+ int start_svm_guest(struct guest_info *info) {
   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
   vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
   uint_t num_exits = 0;
 
 
 
+
 /* Checks machine SVM capability */
 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
 int is_svm_capable() {
 
          return -1;
        }
       } else {
+       /*
+       ulong_t tsc_spread = 0;
+       ullong_t exit_tsc = 0;
+
+       ulong_t rax = (ulong_t)info->vm_regs.rbx;
+       ulong_t rdx = (ulong_t)info->vm_regs.rcx;
+
+       *(ulong_t *)(&exit_tsc) = rax;
+       *(((ulong_t *)(&exit_tsc)) + 1) = rdx; 
+
+       tsc_spread = info->exit_tsc - exit_tsc;
+
+       PrintError("VMMCALL tsc diff = %lu\n",tsc_spread); 
+       info->rip += 3;
+       */
        PrintError("VMMCALL with not emulator...\n");
        return -1;
       }
 
 }
 
 
+/*static int IO_Read(ushort_t port, void * dst, uint_t length, void * priv_data) {
+
+  struct guest_info * info = priv_data;
+  ulong_t tsc_spread = 0;
+  ullong_t exit_tsc = 0;
+
+  
+  *(ulong_t *)(&exit_tsc) = info->vm_regs.rbx;
+  *(ulong_t *)((&exit_tsc) + 4) = info->vm_regs.rcx; 
+  tsc_spread = info->exit_tsc - exit_tsc;
+  
+  PrintError("IOREAD tsc diff = %lu\n",tsc_spread); 
+  info->rip += 3;
+
+
+  return 1;
+}
+*/
 
 int config_guest(struct guest_info * info, void * config_ptr) {
 
 #endif
   
 
+  //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
+
   info->rip = 0xfff0;
   info->vm_regs.rsp = 0x0;
   
       v3_hook_io_port(&vm_info, 0x61, &IO_Read, &IO_Write, NULL);
       v3_hook_io_port(&vm_info, 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
       
+
+
       /*
        vm_info.cr0 = 0;
        vm_info.cs.base=0xf000;
 
 #ifndef DEBUG_INTERRUPTS
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
-#else 
-#undef PrintDebug
-#define PrintDebug(fmt, args...) PrintTrace("\nvmm_intr.c(%d) "_f, __LINE__, ## _a)
 #endif