From 74afa70d3051553df46d1ea0d76149a7a86c0a47 Mon Sep 17 00:00:00 2001
From: rsc <rsc>
Date: Sun, 31 May 2009 00:24:11 +0000
Subject: [PATCH] Add serial port input/output. Delete parallel port output.
 Works well with qemu -nographic mode.

---
 console.c | 28 ++++----------------
 trap.c    |  5 ++++
 traps.h   |  1 +
 uart.c    | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 87 insertions(+), 23 deletions(-)
 create mode 100644 uart.c

diff --git a/console.c b/console.c
index c1c66b2..8f89b49 100644
--- a/console.c
+++ b/console.c
@@ -1,6 +1,6 @@
 // Console input and output.
-// Input is from the keyboard only.
-// Output is written to the screen and the printer port.
+// Input is from the keyboard or serial port.
+// Output is written to the screen and serial port.
 
 #include "types.h"
 #include "defs.h"
@@ -13,31 +13,13 @@
 #include "x86.h"
 
 #define CRTPORT 0x3d4
-#define LPTPORT 0x378
 #define BACKSPACE 0x100
 
 static ushort *crt = (ushort*)0xb8000;  // CGA memory
 
 static struct spinlock console_lock;
 int panicked = 0;
-int use_console_lock = 0;
-
-// Copy console output to parallel port, which you can tell
-// .bochsrc to copy to the stdout:
-//   parport1: enabled=1, file="/dev/stdout"
-static void
-lptputc(int c)
-{
-  int i;
-
-  for(i = 0; !(inb(LPTPORT+1) & 0x80) && i < 12800; i++)
-    ;
-  if(c == BACKSPACE)
-    c = '\b';
-  outb(LPTPORT+0, c);
-  outb(LPTPORT+2, 0x08|0x04|0x01);
-  outb(LPTPORT+2, 0x08);
-}
+volatile int use_console_lock = 0;
 
 static void
 cgaputc(int c)
@@ -80,14 +62,14 @@ consputc(int c)
       ;
   }
 
-  lptputc(c);
+  uartputc(c);
   cgaputc(c);
 }
 
 void
 printint(int xx, int base, int sgn)
 {
-  static char digits[] = "0123456789ABCDEF";
+  static char digits[] = "0123456789abcdef";
   char buf[16];
   int i = 0, neg = 0;
   uint x;
diff --git a/trap.c b/trap.c
index f35f8de..f95e563 100644
--- a/trap.c
+++ b/trap.c
@@ -62,6 +62,11 @@ trap(struct trapframe *tf)
     kbdintr();
     lapiceoi();
     break;
+  case IRQ_OFFSET + IRQ_COM1:
+    uartintr();
+    lapiceoi();
+    break;
+  case IRQ_OFFSET + 7:
   case IRQ_OFFSET + IRQ_SPURIOUS:
     cprintf("cpu%d: spurious interrupt at %x:%x\n",
             cpu(), tf->cs, tf->eip);
diff --git a/traps.h b/traps.h
index b69edd2..6476bbe 100644
--- a/traps.h
+++ b/traps.h
@@ -31,6 +31,7 @@
 
 #define IRQ_TIMER        0
 #define IRQ_KBD          1
+#define IRQ_COM1         4
 #define IRQ_IDE         14
 #define IRQ_ERROR       19
 #define IRQ_SPURIOUS    31
diff --git a/uart.c b/uart.c
new file mode 100644
index 0000000..298066f
--- /dev/null
+++ b/uart.c
@@ -0,0 +1,76 @@
+// Intel 8250 serial port (UART).
+
+#include "types.h"
+#include "defs.h"
+#include "param.h"
+#include "traps.h"
+#include "spinlock.h"
+#include "dev.h"
+#include "mmu.h"
+#include "proc.h"
+#include "x86.h"
+
+#define COM1	0x3f8
+
+static int uart;	// is there a uart?
+
+void
+uartinit(void)
+{
+	char *p;
+
+	// Turn off the FIFO
+	outb(COM1+2, 0);
+	
+	// 9600 baud, 8 data bits, 1 stop bit, parity off.
+	outb(COM1+3, 0x80);	// Unlock divisor
+	outb(COM1+0, 115200/9600);
+	outb(COM1+1, 0);
+	outb(COM1+3, 0x03);	// Lock divisor, 8 data bits.
+	outb(COM1+4, 0);
+	outb(COM1+1, 0x01);	// Enable receive interrupts.
+
+	// If status is 0xFF, no serial port.
+	if(inb(COM1+5) == 0xFF)
+		return;
+	uart = 1;
+
+	// Acknowledge pre-existing interrupt conditions;
+	// enable interrupts.
+	inb(COM1+2);
+	inb(COM1+0);
+	picenable(IRQ_COM1);
+	ioapicenable(IRQ_COM1, 0);
+	
+	// Announce that we're here.
+	for(p="xv6...\n"; *p; p++)
+		uartputc(*p);
+}
+
+void
+uartputc(int c)
+{
+	int i;
+
+	if(!uart)
+		return;
+	for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++)
+		microdelay(10);
+	outb(COM1+0, c);
+}
+
+static int
+uartgetc(void)
+{
+	if(!uart)
+		return -1;
+	if(!(inb(COM1+5) & 0x01))
+		return -1;
+	return inb(COM1+0);
+}
+
+void
+uartintr(void)
+{
+	consoleintr(uartgetc);
+}
-- 
GitLab