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.


Release 1.0
[palacios.git] / geekos / src / geekos / serial.c
diff --git a/geekos/src/geekos/serial.c b/geekos/src/geekos/serial.c
new file mode 100644 (file)
index 0000000..c698dbb
--- /dev/null
@@ -0,0 +1,223 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Peter Dinda <pdinda@northwestern.edu> 
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Peter Dinda <pdinda@northwestern.edu>
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <geekos/serial.h>
+#include <geekos/reboot.h>
+#include <geekos/gdt.h>
+#include <geekos/idt.h>
+#include <geekos/fmtout.h>
+
+
+
+
+unsigned short serial_io_addr = 0;
+uint_t serial_print_level;
+
+static void Serial_Interrupt_Handler(struct Interrupt_State * state) {
+  char rcv_byte;
+  char irq_id;
+
+  Begin_IRQ(state);
+
+  irq_id = In_Byte(serial_io_addr + 2);
+
+
+  if ((irq_id & 0x04) != 0) {
+    rcv_byte = In_Byte(serial_io_addr + 0);
+
+    if (rcv_byte == 'k') {
+      SerialPrint("Restarting Machine\r\n");
+      machine_real_restart();
+    } else if (rcv_byte=='d') { 
+      SerialPrint("Dumping Machine State\n");
+      Dump_Interrupt_State(state);
+      DumpIDT();
+      DumpGDT();
+    }
+      
+#if 0
+      SerialPrint("Unreserved serial byte: %d (%c)\r\n", rcv_byte, rcv_byte);
+#endif
+  }
+  End_IRQ(state);
+}
+
+
+
+void InitSerialAddr(unsigned short io_addr) {
+  serial_io_addr = io_addr;
+
+  Print("Initializing Polled Serial Output on COM1 - 115200 N81 noflow\n");
+  //  io_adr = 0x3F8;  /* 3F8=COM1, 2F8=COM2, 3E8=COM3, 2E8=COM4 */
+  Out_Byte(io_addr + 3, 0x80);
+  // 115200 /* 115200 / 12 = 9600 baud */
+  Out_Byte(io_addr + 0, 1);
+  Out_Byte(io_addr + 1, 0);
+  /* 8N1 */
+  Out_Byte(io_addr + 3, 0x03);
+  /* all interrupts disabled */
+  //  Out_Byte(io_addr + 1, 0);
+  Out_Byte(io_addr + 1, 0x01);
+  /* turn off FIFO, if any */
+  Out_Byte(io_addr + 2, 0);
+  /* loopback off, interrupts (Out2) off, Out1/RTS/DTR off */
+  //  Out_Byte(io_addr + 4, 0);
+  // enable interrupts (bit 3)
+  Out_Byte(io_addr + 4, 0x08);
+}
+
+
+
+
+void SerialPutChar(unsigned char c) {
+ //  static unsigned short io_adr;
+  if (serial_io_addr==0) { 
+    return;
+  }
+
+
+  if (c=='\n') { 
+    /* wait for transmitter ready */
+    while((In_Byte(serial_io_addr + 5) & 0x40) == 0) {
+    }
+    /* send char */
+    Out_Byte(serial_io_addr + 0, '\r');
+    /* wait for transmitter ready */
+  }
+  while((In_Byte(serial_io_addr + 5) & 0x40) == 0) {
+  }
+  /* send char */
+  Out_Byte(serial_io_addr + 0, c);
+}
+
+
+
+void SerialPutLineN(char * line, int len) {
+  int i;
+  for (i = 0; i < len && line[i] != 0; i++) { 
+    SerialPutChar(line[i]); 
+  }
+}
+
+
+void SerialPutLine(char * line) {
+  int i;
+  for (i = 0; line[i]!= 0; i++) { 
+    SerialPutChar(line[i]); 
+  }
+}
+
+
+void SerialPrintHex(unsigned char x)
+{
+  unsigned char z;
+  
+  z = (x>>4) & 0xf ;
+  SerialPrint("%x", z);
+  z = x & 0xf;
+  SerialPrint("%x", z);
+}
+
+void SerialMemDump(unsigned char *start, int n)
+{
+  int i, j;
+
+  for (i=0;i<n;i+=16) {
+    SerialPrint("%8x", (unsigned)(start+i));
+    for (j=i; j<i+16 && j<n; j+=2) {
+      SerialPrint(" ");
+      SerialPrintHex(*((unsigned char *)(start+j)));
+      if ((j+1)<n) { 
+       SerialPrintHex(*((unsigned char *)(start+j+1)));
+      }
+    }
+    SerialPrint(" ");
+    for (j=i; j<i+16 && j<n;j++) {
+      SerialPrint("%c", ((start[j]>=32) && (start[j]<=126)) ? start[j] : '.');
+    }
+    SerialPrint("\n");
+  }
+}
+
+
+static struct Output_Sink serial_output_sink;
+static void Serial_Emit(struct Output_Sink * o, int ch) { 
+  SerialPutChar((unsigned char)ch); 
+}
+static void Serial_Finish(struct Output_Sink * o) { return; }
+
+
+static void __inline__ SerialPrintInternal(const char * format, va_list ap) {
+  Format_Output(&serial_output_sink, format, ap);
+}
+
+
+void SerialPrint(const char * format, ...) {
+  va_list args;
+  bool iflag = Begin_Int_Atomic();
+
+  va_start(args, format);
+  SerialPrintInternal(format, args);
+  va_end(args);
+
+  End_Int_Atomic(iflag);
+}
+
+void SerialPrintList(const char * format, va_list ap) {
+  bool iflag = Begin_Int_Atomic();
+  SerialPrintInternal(format, ap);
+  End_Int_Atomic(iflag);
+
+}
+
+
+
+
+void SerialPrintLevel(int level, const char * format, ...) {
+  if (level > serial_print_level) {
+    va_list args;
+    bool iflag = Begin_Int_Atomic();
+    
+    va_start(args, format);
+    SerialPrintInternal(format, args);
+    va_end(args);
+    
+    End_Int_Atomic(iflag);   
+  }
+}
+
+
+
+
+void Init_Serial() {
+
+  serial_print_level = SERIAL_PRINT_DEBUG_LEVEL;
+
+  Print("Initialzing Serial\n");
+
+  serial_output_sink.Emit = &Serial_Emit;
+  serial_output_sink.Finish = &Serial_Finish;
+
+  Install_IRQ(COM1_IRQ, Serial_Interrupt_Handler);
+  Enable_IRQ(COM1_IRQ);
+  InitSerialAddr(DEFAULT_SERIAL_ADDR);
+}