The unified diff between revisions [cbddc8b3..] and [a2621a92..] is displayed below. It can also be downloaded as a raw diff.

#
# old_revision [cbddc8b347cfe68cf634efaf314c99652ed27527]
# new_revision [a2621a92a8c03a907239e78df69f38370d023a70]
#
# patch "uart.c"
#  from [cd75769ab8ffb66cd0ff19a158def1fadbbbe56f]
#    to [07a014210246046a28c0b690de8dd6dd8af95e2d]
#
============================================================
--- uart.c	cd75769ab8ffb66cd0ff19a158def1fadbbbe56f
+++ uart.c	07a014210246046a28c0b690de8dd6dd8af95e2d
@@ -26,11 +26,15 @@
 #define U0THRE ((UREG(LSR) & (1<<5))) /* UART0 transmitter holding register is empty */
 #define U0DR ((UREG(LSR) & (1<<0))) /* UART0 data ready */
 
-#define UART_BUFSIZE 128
+#define UART_TXBUFSIZE 128
+#define UART_RXBUFSIZE 128
 
-char uart_txbuf[UART_BUFSIZE];
+char uart_txbuf[UART_TXBUFSIZE];
+char uart_rxbuf[UART_RXBUFSIZE];
 volatile int uart_txread;
 volatile int uart_txwrite;
+volatile int uart_rxread;
+volatile int uart_rxwrite;
 volatile bool tx_running;
 
 void __attribute__((interrupt("IRQ"))) uart_interrupt_handler(void);
@@ -47,15 +51,17 @@ void init_uart(void)
 
 	uart_txread = 0;
 	uart_txwrite = 0;
+	uart_rxread = 0;
+	uart_rxwrite = 0;
 	tx_running = FALSE;
 	interrupt_register(UART0, uart_interrupt_handler);
 
-	UREG(IER) = 0x02; /* THRE interrupt enable */
+	UREG(IER) = 0x03; /* RBR and THRE interrupt enable */
 }
 
 void putch(char c) {
 	/* Wait for space in the buffer */
-	while (uart_txread == ((uart_txwrite+1) % UART_BUFSIZE));
+	while (uart_txread == ((uart_txwrite+1) % UART_TXBUFSIZE));
 
 	if (uart_txread == uart_txwrite) {
 		if (U0THRE) {
@@ -66,12 +72,12 @@ void putch(char c) {
 	}
 
 	uart_txbuf[uart_txwrite] = c;
-	uart_txwrite = (uart_txwrite + 1) % UART_BUFSIZE;
+	uart_txwrite = (uart_txwrite + 1) % UART_TXBUFSIZE;
 
 	if (!tx_running) {
 		if (uart_txread != uart_txwrite) {
 			tx_running = TRUE;
-			uart_txread = (uart_txread + 1) % UART_BUFSIZE;
+			uart_txread = (uart_txread + 1) % UART_TXBUFSIZE;
 			UREG(THR) = c;
 		}
 	}
@@ -86,29 +92,48 @@ void __attribute__((interrupt("IRQ"))) u
 	 * to treat them as such in this handler, so let the compiler
 	 * have an easier time.
 	 */
-	int local_txwrite = uart_txwrite;
-	int local_txread = uart_txread;
+	int local_txwrite;
+	int local_txread;
+	int local_rxwrite;
+	int local_rxread;
 
 	source = UREG(IIR);
 
-	/* For now we assume that all interrupts are actually THR empty
-	 * interrupts. Actually check this when we do more things with
-	 * the UART
-	 */
+	switch (source & 0x0e) {
+	case 0x4: /* Receive Data Available */
+	case 0xc: /* Character Time-out Indicator */
+		local_rxwrite = uart_rxwrite;
+		local_rxread = uart_rxread;
+		while (U0DR) {
+			unsigned char c = UREG(RBR);
+			if (local_rxread !=
+			    ((local_rxwrite+1) % UART_RXBUFSIZE)) {
+				uart_rxbuf[local_rxwrite] = c;
+				local_rxwrite = (local_rxwrite + 1) %
+				    UART_RXBUFSIZE;
+			}
+		}
+		uart_rxwrite = local_rxwrite;
+		break;
 
-	if (U0THRE) {
+	case 0x2: /* THRE interrupt */
+		local_txwrite = uart_txwrite;
+		local_txread = uart_txread;
 		for (i = 0; (i < 16) && (local_txwrite != local_txread); i++) {
 			UREG(THR) = uart_txbuf[local_txread];
-			local_txread = (local_txread + 1) % UART_BUFSIZE;
+			local_txread = (local_txread + 1) % UART_TXBUFSIZE;
 			active = TRUE;
 		}
-	}
+		uart_txread = local_txread;
+		if (!active)
+			tx_running = FALSE;
+		break;
 
-	uart_txread = local_txread;
+	case 0x6: /* Receive Line Status */
+	default: /* Anything else */
+		break;
+	}
 
-	if (!active)
-		tx_running = FALSE;
-
 	interrupt_clear();
 }
 
@@ -148,8 +173,13 @@ char getch(void) {
 }
 
 char getch(void) {
-	while (!U0DR) {
+	char c;
+
+	while (uart_rxread == uart_rxwrite) {
 		FP0XVAL ^= 0x04000000;
 	}
-	return UREG(RBR);
+
+	c = uart_rxbuf[uart_rxread];
+	uart_rxread = (uart_rxread + 1) % UART_RXBUFSIZE;
+	return c;
 }