--- /dev/null
+\documentclass[a4paper,twoside]{report} % for a report (default)
+
+\usepackage{amsmath}
+\usepackage{bftn} % You need this
+\usepackage{cite}
+\usepackage{color}
+\usepackage{listings}
+\usepackage{xspace}
+
+\title{Serial ports in Barrelfish} % title of report
+\author{Timothy Roscoe} % author
+\tnnumber{016} % give the number of the tech report
+\tnkey{Serial ports} % Short title, will appear in footer
+
+% \date{Month Year} % Not needed - will be taken from version history
+
+\begin{document}
+\maketitle
+
+%
+% Include version history first
+%
+\begin{versionhistory}
+\vhEntry{0.0}{08.07.2012}{TR}{Initial version}
+\end{versionhistory}
+
+% \intro{Abstract} % Insert abstract here
+% \intro{Acknowledgements} % Uncomment (if needed) for acknowledgements
+% \tableofcontents % Uncomment (if needed) for final draft
+% \listoffigures % Uncomment (if needed) for final draft
+% \listoftables % Uncomment (if needed) for final draft
+
+\lstset{
+ language=C,
+ basicstyle=\ttfamily \small,
+ flexiblecolumns=false,
+ basewidth={0.5em,0.45em},
+ boxpos=t,
+}
+
+\newcommand{\note}[1]{[\textcolor{red}{\emph{#1}}]}
+\newcommand{\Intf}{\texttt{/kernel/include/serial.h}\xspace}
+
+\tableofcontents
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\chapter{Introduction}
+
+This technical note describes the use of serial ports (UARTS) in
+Barrelfish.
+
+At present, it only describes the kernel-space interface
+to serial ports, used internally by CPU drivers for debugging and
+console output.
+
+In the future, it will also describe the interface to user-space UART
+drivers and other console subsystems.
+
+\chapter{CPU driver interface}\label{cha:cpudriver}
+
+CPU drivers use serial port access for printing debug information,
+status messages during startup, and connecting a debugger such as GDB
+to a processor.
+
+Each CPU driver implements a serial port subsystem which provides a
+small number serial ports to the rest of the CPU driver.
+
+The interface to this subsystem is specified in the file
+\Intf, and is described in this chapter.
+Check the header file for a (possibly) more-up-to-date description.
+
+The interface is intentionally very basic. It assumes each UART runs
+at a fixed, default speed with basic settings (typically 115000 baud,
+8-bit words, no parity, no flow control). Serious applications
+should use a full user-space UART driver instead.
+
+\section{Physical ports}
+
+Serial ports available inside a CPU driver are numbered starting at
+zero.
+
+The number of available serial ports is given by:
+\begin{alltt}
+ extern const unsigned serial\_num\_physical\_ports;
+\end{alltt}
+
+\subsection{Initialization}
+
+Each port must be initialized before it can be used:
+\begin{alltt}
+ extern errval\_t serial\_init(unsigned port);
+\end{alltt}
+This call should fail with \texttt{SYS\_ERR\_SERIAL\_PORT\_INVALID} if
+the port cannot be initialized, or the port number is out of range.
+
+Initializing a serial port more than once, however, is permissible:
+subsequent attempts to initialize an initialized port are silently
+ignored. The motivation for this is to handle the case where the
+console and debug logical ports share the same physical port.
+
+In some cases it is necessary to do an ``early'' initializaton, for
+example while running in physical address space before the MMU is
+enabled. In such cases the CPU driver should call, and the code
+implement, the following:
+\begin{alltt}
+ extern errval\_t serial\_early\_init(unsigned port);
+\end{alltt}
+
+This returns the same errors as \texttt{serial\_init()}, but it is a
+bug to call this function more than once with the same port number,
+and doing so will cause an assertion failure.
+
+\subsection{Input/output}
+
+Each serial port provides polled, blocking, single-character
+programmed I/O:
+\begin{alltt}
+ extern void serial\_putchar(unsigned port, char c);
+ extern char serial\_getchar(unsigned port);
+\end{alltt}
+It is a bug to call these with a port number that is out of range
+(i.e. one that is greater than or equal to
+\texttt{serial\_num\_physical\_ports}), and doing so will cause an
+assertion failure. It may also cause an assertion failure to call
+these functions on a serial port which has not yet been initialized
+with a call to \texttt{serial\_init()} or
+\texttt{serial\_early\_init()}.
+
+Note that implementations of these functions should not attempt to use
+DMA or interrupts. They should also not buffer any data in software
+(though they may use a hardware FIFO in the UART if appropriate).
+
+\section{Logical ports}
+
+Barrelfish CPU drivers have access to two logical serial ports:
+\begin{itemize}
+\item The \emph{console} port is used for general logging and debug
+ information. It is principally called by \texttt{kputchar()}, which
+ implements line-buffering and is in turn called by the kernel
+ \texttt{printf()} function.
+\item The \emph{debug} port can be used to attach an external debugger
+ like \texttt{gdb}.
+\end{itemize}
+
+Both logical ports are assigned to sensible default physical ports by
+the serial port implementation, but they can be changed by writing
+these variables:
+\begin{alltt}
+ extern unsigned serial\_console\_port;
+ extern unsigned serial\_debug\_port;
+\end{alltt}
+
+Note that it is not unusual for both logical ports to be assigned to
+the same physical port.
+
+The file \Intf also includes inline functions to initialize whichever
+physical port is currently assigned to a logical port:
+\begin{alltt}
+ static inline errval\_t serial\_console\_init(void);
+ static inline errval\_t serial\_debug\_init(void);
+\end{alltt}
+
+There are also input functions, which simply call
+\texttt{serial\_getchar()} with the appropriate port number:
+\begin{alltt}
+ static inline char serial\_console\_getchar(void);
+ static inline char serial\_debug\_getchar(void);
+\end{alltt}
+
+Output functions are similar, but in addition replace any LF character
+with the sequence CR/LF:
+\begin{alltt}
+ static inline void serial\_console\_putchar(char c);
+ static inline void serial\_debug\_putchar(char c);
+\end{alltt}
+
+\section{Implementing a serial port subsystem}
+
+Typically, a rudimentary console driver is the first thing to be
+implemented when writing a CPU driver for a new architecture.
+
+The serial port subsystem for a CPU driver must implement all the
+functionality in \Intf that deals with physical serial ports, in other
+words:
+\begin{verbatim}
+ const unsigned serial_num_physical_ports;
+ errval_t serial_init(unsigned port);
+ errval_t serial_early_init(unsigned port);
+ void serial_putchar(unsigned port, char c);
+ char serial_getchar(unsigned port);
+ unsigned serial_console_port;
+ unsigned serial_debug_port;
+\end{verbatim}
+
+Functions for logical ports are provided by inline functions in the
+header file.
+
+Initializing a serial port typically consists of configuring the UART
+hardware, and then mapping the registers appropriately into the
+kernel's virtual address space.
+
+Examples of serial port implementations at time of writing include:
+\begin{itemize}
+\item \texttt{/kernel/arch/omap44xx/omap\_uart.c}
+\item \texttt{/kernel/arch/x86/serial.c}
+\end{itemize}
+
+\subsection{Multiprocessor considerations}
+
+This document does not address accessing a single UART from more than
+CPU driver. If this happens at all, it is typically hidden by the
+implementation (for example, some x86 CPU drivers use a global
+spinlock, since performance is not an issue anyway). Care should be
+taken not to initialize the UARTs multiple times in such
+circumstances.
+
+
+
+\end{document}
--- /dev/null
+/**
+ * \file
+ * \brief ARM GEM5 kernel-level serial driver. Implements the
+ * interface in /kernel/include/serial.h
+ */
+/*
+ * Copyright (c) 2007-2012 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaestr. 6, CH-8092 Zurich.
+ * Attn: Systems Group.
+ */
+
+#include <kernel.h>
+#include <paging_kernel_arch.h>
+#include <serial.h>
+#include <dev/pl011_uart_dev.h>
+#include <pl011_uart.h>
+
+#define NUM_PORTS 2
+unsigned serial_console_port = 0;
+unsigned serial_debug_port = 1;
+const unsigned serial_num_physical_ports = NUM_PORTS;
+
+
+#define UART0_VBASE 0xE0009000
+#define UART0_SECTION_OFFSET 0x9000
+#define UART_DEVICE_BYTES 0x4c
+#define UART_MAPPING_DIFF 0x1000
+
+static pl011_uart_t ports[NUM_PORTS];
+
+/*
+ * Initialize a serial port
+ */
+errval_t serial_init(unsigned port)
+{
+ if (port < NUM_PORTS) {
+ lvaddr_t base = paging_map_device(UART0_VBASE + port*UART_MAPPING_DIFF,
+ UART_DEVICE_BYTES);
+ pl011_uart_init(&ports[port],
+ base + UART0_SECTION_OFFSET + port*UART_MAPPING_DIFF);
+ return SYS_ERR_OK;
+ } else {
+ return SYS_ERR_SERIAL_PORT_INVALID;
+ }
+}
+
+errval_t serial_early_init(unsigned port)
+{
+ if (port < NUM_PORTS) {
+ assert(ports[port].base == 0);
+ pl011_uart_init(&ports[port], UART0_VBASE + port*UART_MAPPING_DIFF);
+ return SYS_ERR_OK;
+ } else {
+ return SYS_ERR_SERIAL_PORT_INVALID;
+ }
+}
+
+void serial_putchar(unsigned port, char c)
+{
+ assert(port < NUM_PORTS);
+ assert(ports[port].base != 0);
+ pl011_putchar(&ports[port], c);
+};
+
+char serial_getchar(unsigned port)
+{
+ assert(port < NUM_PORTS);
+ assert(ports[port].base != 0);
+ return pl011_getchar(&ports[port]);
+};