New serial interface inside the CPU driver.
authorMothy <troscoe@inf.ethz.ch>
Mon, 6 Aug 2012 16:17:53 +0000 (18:17 +0200)
committerMothy <troscoe@inf.ethz.ch>
Mon, 6 Aug 2012 16:17:53 +0000 (18:17 +0200)
18 files changed:
include/getopt/getopt.h
kernel/Hakefile
kernel/arch/arm/init.c
kernel/arch/arm/integrator.c
kernel/arch/arm_gem5/init.c
kernel/arch/arm_gem5/integrator.c
kernel/arch/arm_gem5/pl011_uart.c
kernel/arch/omap44xx/init.c
kernel/arch/omap44xx/omap.c
kernel/arch/omap44xx/omap_uart.c
kernel/arch/x86/serial.c
kernel/arch/x86_32/init.c
kernel/arch/x86_64/init.c
kernel/arch/xscale/ixp2800_integrator.c
kernel/include/arch/arm/omap_uart.h [deleted file]
kernel/include/serial.h
kernel/stdlib.c
lib/getopt/getopt.c

index 82dc49b..4d15ed4 100644 (file)
@@ -17,6 +17,7 @@
 
 enum argtype {
     ArgType_Int,
+    ArgType_UInt,
     ArgType_Bool,
     ArgType_Custom
 };
@@ -29,11 +30,12 @@ struct cmdarg {
 
     union {
         int             *integer;
+        unsigned        *uinteger;
         bool            *boolean;
         cmdarg_handler  handler;
     } var;
 };
 
-void parse_commandline(const char *cmdline, struct cmdarg *cmdargs);
+extern void parse_commandline(const char *cmdline, struct cmdarg *cmdargs);
 
 #endif // GETOPT_H
index c20d713..d4caac8 100644 (file)
@@ -277,6 +277,7 @@ let
                "arch/arm_gem5/init.c", 
                "arch/arm_gem5/integrator.c", 
                "arch/arm_gem5/paging.c", 
+               "arch/arm_gem5/gem5_serial.c", 
                "arch/arm_gem5/pl011_uart.c", 
                "arch/arm_gem5/startup_arch.c", 
                "arch/arm_gem5/syscall.c", 
index 9bb5275..66b29fa 100644 (file)
@@ -194,7 +194,7 @@ void arch_init(uint32_t     board_id,
     {
         errval_t errval;
 
-        serial_console_init(serial_console_port);
+        serial_console_init();
 
         // do not remove/change this printf: needed by regression harness
         printf("Barrelfish CPU driver starting on ARMv5 Board id 0x%08"PRIx32"\n",
index fabf9c6..090ad13 100644 (file)
@@ -207,12 +207,20 @@ uint32_t tsc_get_hz(void)
 // Serial console and debugger interfaces
 //
 
-#define CONSOLE_PORT 0
-#define DEBUG_PORT   1
+#define NUM_PORTS 2
+static unsigned serial_console_port = 0;
+static unsigned serial_debug_port = 1
+static unsigned serial_num_physical_ports = NUM_PORTS
 
-static pl011_uart_t ports[2];
 
-static errval_t serial_init(uint8_t index, uint8_t port_no)
+#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];
+
+errval_t serial_init(uint8_t index, uint8_t port_no)
 {
     if (port_no < 2) {
         assert(ports[port_no].base == 0);
@@ -226,33 +234,21 @@ static errval_t serial_init(uint8_t index, uint8_t port_no)
         return SYS_ERR_SERIAL_PORT_INVALID;
     }
 }
-
-errval_t serial_console_init(uint8_t port_ordinal)
-{
-    return serial_init(CONSOLE_PORT, port_ordinal);
-}
-
-void serial_console_putchar(char c)
-{
-    pl011_putchar(&ports[CONSOLE_PORT], c);
-}
-
-char serial_console_getchar(void)
+errval_t serial_early_init(unsigned port)
 {
-    return pl011_getchar(&ports[CONSOLE_PORT]);
+    return SYS_ERR_OK; // Unused
 }
 
-errval_t serial_debug_init(uint8_t port_ordinal)
+void serial_putchar(unsigned port, char c) 
 {
-    return serial_init(DEBUG_PORT, port_ordinal);
-}
+    assert(port < NUM_PORTS);
+    assert(ports[port].base != 0);
+    pl011_putchar(&ports[port], c);
+};
 
-void serial_debug_putchar(char c)
+char serial_getchar(unsigned port)
 {
-    pl011_putchar(&ports[DEBUG_PORT], c);
-}
-
-char serial_debug_getchar(void)
-{
-    return pl011_getchar(&ports[DEBUG_PORT]);
-}
+    assert(port < NUM_PORTS);
+    assert(ports[port].base != 0);
+    return pl011_putchar(&ports[port], c);
+};
index 9682571..bb0e590 100644 (file)
@@ -31,9 +31,6 @@
 
 #define GEM5_RAM_SIZE  0x20000000
 
-extern errval_t early_serial_init(uint8_t port_no);
-
-
 /// Round up n to the next multiple of size
 #define ROUND_UP(n, size)           ((((n) + (size) - 1)) & (~((size) - 1)))
 
@@ -181,12 +178,10 @@ struct atag {
 //
 
 static int timeslice                            = 5;           //interval in ms in which the scheduler gets called
-static int serial_console_port       = 0;
-static int serial_debug_port         = 1;
 
 static struct cmdarg cmdargs[] = {
-    { "consolePort",    ArgType_Int, { .integer = &serial_console_port}},
-    { "debugPort",      ArgType_Int, { .integer = &serial_debug_port}},
+    { "consolePort",    ArgType_UInt, { .uinteger = &serial_console_port}},
+    { "debugPort",      ArgType_UInt, { .uinteger = &serial_debug_port}},
     { "loglevel",       ArgType_Int, { .integer = &kernel_loglevel }},
     { "logmask",        ArgType_Int, { .integer = &kernel_log_subsystem_mask }},
     { "timeslice",      ArgType_Int, { .integer = &timeslice }},
@@ -310,13 +305,13 @@ static void  __attribute__ ((noinline,noreturn)) text_init(void)
        kernel_startup_early();
 
        //initialize console
-        serial_console_init(serial_console_port);
+        serial_console_init();
 
         // do not remove/change this printf: needed by regression harness
         printf("Barrelfish CPU driver starting on ARMv7 Board id 0x%08"PRIx32"\n", hal_get_board_id());
         printf("The address of paging_map_kernel_section is %p\n", paging_map_kernel_section);
 
-        errval = serial_debug_init(serial_debug_port);
+        errval = serial_debug_init();
         if (err_is_fail(errval))
         {
                 printf("Failed to initialize debug port: %d", serial_debug_port);
@@ -364,7 +359,8 @@ void arch_init(void *pointer)
 
     struct Elf32_Shdr *rela, *symtab;
     struct arm_coredata_elf *elf = NULL;
-       early_serial_init(serial_console_port);
+
+    serial_early_init(serial_console_port);
 
     if(hal_cpu_is_bsp())
     {
index c64432c..ff3910a 100644 (file)
 #include <kernel.h>
 #include <paging_kernel_arch.h>
 
-#include <dev/pl011_uart_dev.h>
 #include <dev/pl130_gic_dev.h>
 #include <dev/sp804_pit_dev.h>
 #include <dev/cortex_a9_pit_dev.h>
 #include <dev/arm_icp_pit_dev.h>
 #include <dev/a9scu_dev.h>
 
-#include <pl011_uart.h>
-#include <serial.h>
 #include <arm_hal.h>
 #include <cp15.h>
 #include <io.h>
@@ -486,75 +483,3 @@ void write_sysflags_reg(uint32_t regval)
 {
        writel(regval, (char *)SYSFLAGSET_BASE);
 }
-
-//
-// Serial console and debugger interfaces
-//
-
-#define CONSOLE_PORT 0
-#define DEBUG_PORT   1
-
-#define UART0_VBASE                            0xE0009000
-#define UART0_SECTION_OFFSET   0x9000
-#define UART_DEVICE_BYTES              0x4c
-#define UART_MAPPING_DIFF              0x1000
-
-static pl011_uart_t ports[2];
-
-static errval_t serial_init(uint8_t index, uint8_t port_no)
-{
-    if (port_no < 2) {
-        //assert(ports[port_no].base == 0);
-
-        lvaddr_t base = paging_map_device(UART0_VBASE + port_no * UART_MAPPING_DIFF,
-                                          UART_DEVICE_BYTES);
-        pl011_uart_init(&ports[index], base + UART0_SECTION_OFFSET + port_no*UART_MAPPING_DIFF);
-        //pl011_uart_init(&ports[index], UART0_VBASE);
-        return SYS_ERR_OK;
-    }
-    else {
-        return SYS_ERR_SERIAL_PORT_INVALID;
-    }
-}
-errval_t early_serial_init(uint8_t port_no);
-errval_t early_serial_init(uint8_t port_no)
-{
-       if (port_no < 2) {
-               assert(ports[port_no].base == 0);
-               pl011_uart_init(&ports[CONSOLE_PORT], UART0_VBASE);
-               return SYS_ERR_OK;
-       }
-       else {
-               return SYS_ERR_SERIAL_PORT_INVALID;
-       }
-}
-
-errval_t serial_console_init(uint8_t port_ordinal)
-{
-    return serial_init(CONSOLE_PORT, port_ordinal);
-}
-
-void serial_console_putchar(char c)
-{
-    pl011_putchar(&ports[CONSOLE_PORT], c);
-}
-
-char serial_console_getchar(void)
-{
-    return pl011_getchar(&ports[CONSOLE_PORT]);
-}
-
-errval_t serial_debug_init(uint8_t port_ordinal)
-{
-    return serial_init(DEBUG_PORT, port_ordinal);
-}
-
-void serial_debug_putchar(char c)
-{
-    pl011_putchar(&ports[DEBUG_PORT], c);
-}
-
-char serial_debug_getchar(void)
-{
-    return pl011_getchar(&ports[DEBUG_PORT]);
-}
index cde391f..98fded3 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * \file
- * \brief The world's simplest serial driver.
+ * \brief ARM pl011 UART kernel-level driver. 
  */
 
 /*
index 58f2b7c..b945520 100644 (file)
 #define GEM5_RAM_SIZE  0x20000000
 //#define GEM5_RAM_SIZE        0x2000000
 
-extern errval_t early_serial_init(uint8_t port_no);
-
-void put_serial_test(char c);
-
 /// Round up n to the next multiple of size
 #define ROUND_UP(n, size)           ((((n) + (size) - 1)) & (~((size) - 1)))
 
@@ -185,13 +181,11 @@ struct atag {
 // Kernel command line variables and binding options
 //
 
-static int timeslice                = 5; //interval in ms in which the scheduler gets called
-static int serial_console_port       = 2;
-static int serial_debug_port         = 2;
+static int timeslice  = 5; //interval in ms in which the scheduler gets called
 
 static struct cmdarg cmdargs[] = {
-    { "consolePort",    ArgType_Int, { .integer = &serial_console_port}},
-    { "debugPort",      ArgType_Int, { .integer = &serial_debug_port}},
+    { "consolePort",    ArgType_UInt, { .uinteger = &serial_console_port}},
+    { "debugPort",      ArgType_UInt, { .uinteger = &serial_debug_port}},
     { "loglevel",       ArgType_Int, { .integer = &kernel_loglevel }},
     { "logmask",        ArgType_Int, { .integer = &kernel_log_subsystem_mask }},
     { "timeslice",      ArgType_Int, { .integer = &timeslice }},
@@ -347,7 +341,7 @@ static void  __attribute__ ((noinline,noreturn)) text_init(void)
     printf("kernel_startup_early done!\n");
 
     //initialize console
-    serial_console_init(serial_console_port);
+    serial_init(serial_console_port);
 
     // do not remove/change this printf: needed by regression harness
     printf("Barrelfish CPU driver starting on ARMv7"
@@ -355,7 +349,7 @@ static void  __attribute__ ((noinline,noreturn)) text_init(void)
     printf("The address of paging_map_kernel_section is %p\n",
            paging_map_kernel_section);
 
-    errval = serial_debug_init(serial_debug_port);
+    errval = serial_debug_init();
     if (err_is_fail(errval))
         {
             printf("Failed to initialize debug port: %d",
@@ -438,7 +432,7 @@ void arch_init(void *pointer)
 {
     struct arm_coredata_elf *elf = NULL;
 
-    early_serial_init(serial_console_port);
+    serial_early_init(serial_console_port);
 
     if(hal_cpu_is_bsp())
     {
index 7e79536..52dd0eb 100644 (file)
 #include <dev/cortex_a9_pit_dev.h>
 #include <dev/a9scu_dev.h>
 
-#include <omap_uart.h>
-#include <omap44xx_map.h>
-
-#include <serial.h>
 #include <arm_hal.h>
 #include <cp15.h>
 
@@ -533,84 +529,3 @@ int scu_get_core_count(void)
 {
        return a9scu_SCUConfig_cpu_number_rdf(&scu);
 }
-
-//
-// Serial console and debugger interfaces
-//
-
-#define CONSOLE_PORT 2
-#define DEBUG_PORT   2
-
-
-static omap_uart_t ports[4];
-
-static errval_t serial_init(uint8_t index, uint8_t port_no)
-{
-    if (port_no >= 4) {
-        return SYS_ERR_SERIAL_PORT_INVALID;
-    }
-
-    assert(port_no == 2);
-        lvaddr_t base = paging_map_device(OMAP44XX_MAP_L4_PER_UART3,
-                                         OMAP44XX_MAP_L4_PER_UART3_SIZE);
-    // paging_map_device returns an address pointing to the beginning of
-    // a section, need to add the offset for within the section again
-    uint32_t offset = (OMAP44XX_MAP_L4_PER_UART3 & ARM_L1_SECTION_MASK);
-    printf("omap serial_init: base = 0x%"PRIxLVADDR" 0x%"PRIxLVADDR"\n",
-            base, base + offset);
-    omap_uart_init(&ports[index], base + offset);
-
-    return SYS_ERR_OK;
-}
-
-errval_t early_serial_init(uint8_t port_no);
-errval_t early_serial_init(uint8_t port_no)
-{
-    if (port_no < 4) {
-        assert(ports[port_no].base == 0);
-        omap_uart_init(&ports[CONSOLE_PORT], OMAP44XX_MAP_L4_PER_UART3);
-        return SYS_ERR_OK;
-    }
-    else {
-        return SYS_ERR_SERIAL_PORT_INVALID;
-    }
-}
-
-errval_t serial_console_init(uint8_t port_ordinal)
-{
-    printf("Starting UART driver\n");
-    return serial_init(CONSOLE_PORT, port_ordinal);
-}
-
-void serial_console_putchar(char c)
-{
-    if (c == '\n') {
-        omap_putchar(&ports[CONSOLE_PORT], '\r');
-    }
-
-    omap_putchar(&ports[CONSOLE_PORT], c);
-}
-
-char serial_console_getchar(void)
-{
-    return omap_getchar(&ports[CONSOLE_PORT]);
-}
-
-errval_t serial_debug_init(uint8_t port_ordinal)
-{
-    printf("Starting Debug UART driver\n");
-    return serial_init(DEBUG_PORT, port_ordinal);
-}
-
-void serial_debug_putchar(char c)
-{
-    if (c == '\n') {
-        omap_putchar(&ports[DEBUG_PORT], '\r');
-    }
-    omap_putchar(&ports[DEBUG_PORT], c);
-}
-
-char serial_debug_getchar(void)
-{
-    return omap_getchar(&ports[DEBUG_PORT]);
-}
index b212771..6ae5894 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * \file
- * \brief The world's simplest serial driver.
+ * \brief Kernel serial driver for the OMAP44xx UARTs.  Implements the
+ * interface found in /kernel/include/serial.h
  */
 
 /*
 
 #include <kernel.h>
 #include <arm.h>
+#include <paging_kernel_arch.h>
 
+#include <serial.h>
 #include <omap_uart_dev.h>
-#include <omap_uart.h>
+#include <omap44xx_map.h>
 
-void omap_uart_init(omap_uart_t *uart, lvaddr_t base)
+//
+// Serial console and debugger interfaces
+//
+#define NUM_PORTS 4
+unsigned int serial_console_port = 2;
+unsigned int serial_debug_port = 2;
+unsigned const int serial_num_physical_ports = NUM_PORTS;
+
+static omap_uart_t ports[NUM_PORTS];
+
+static lpaddr_t uart_base[NUM_PORTS] = {
+    OMAP44XX_MAP_L4_PER_UART1,
+    OMAP44XX_MAP_L4_PER_UART2,
+    OMAP44XX_MAP_L4_PER_UART3,
+    OMAP44XX_MAP_L4_PER_UART4
+};
+
+static size_t uart_size[NUM_PORTS] = {
+    OMAP44XX_MAP_L4_PER_UART1_SIZE,
+    OMAP44XX_MAP_L4_PER_UART2_SIZE,
+    OMAP44XX_MAP_L4_PER_UART3_SIZE,
+    OMAP44XX_MAP_L4_PER_UART4_SIZE
+};
+
+static bool uart_initialized[NUM_PORTS];
+
+static void omap_uart_init(omap_uart_t *uart, lvaddr_t base)
 {
     omap_uart_initialize(uart, (mackerel_addr_t) base);
 
@@ -37,23 +66,72 @@ void omap_uart_init(omap_uart_t *uart, lvaddr_t base)
     omap_uart_LCR_t lcr = omap_uart_LCR_default;
     lcr = omap_uart_LCR_parity_en_insert(lcr, 0);       // No parity
     lcr = omap_uart_LCR_nb_stop_insert(lcr, 0);         // 1 stop bit
-    lcr = omap_uart_LCR_char_length_insert(lcr, omap_uart_wl_8bits);      // 8 data bits
+    lcr = omap_uart_LCR_char_length_insert(lcr, omap_uart_wl_8bits); // 8 data bits
     omap_uart_LCR_wr(uart, lcr);
 }
 
-/** \brief Prints a single character to the default serial port. */
-void omap_putchar(omap_uart_t *uart, char c)
+errval_t serial_init(unsigned port)
+{
+    if (port >= NUM_PORTS) { 
+        return SYS_ERR_SERIAL_PORT_INVALID;
+    }
+    if (uart_initialized[port]) {
+       printf("omap serial_init[%d]: already initialized; skipping.\n", port);
+       return SYS_ERR_OK;
+    }
+    
+    lvaddr_t base = paging_map_device(uart_base[port],uart_size[port]);
+    // paging_map_device returns an address pointing to the beginning of
+    // a section, need to add the offset for within the section again
+    uint32_t offset = (uart_base[port] & ARM_L1_SECTION_MASK);
+    printf("omap serial_init[%d]: base = 0x%"PRIxLVADDR" 0x%"PRIxLVADDR"\n",
+          port, base, base + offset);
+    omap_uart_init(&ports[port], base + offset);
+    uart_initialized[port] = true;
+    printf("omap serial_init[%d]: done.\n", port);
+    return SYS_ERR_OK;
+}
+
+errval_t serial_early_init(unsigned port)
+{
+    if (port < NUM_PORTS) {
+       // Bug to call twice on a port
+        assert(ports[port].base == 0);
+        omap_uart_init(&ports[port], uart_base[port]);
+        return SYS_ERR_OK;
+    } else {
+        return SYS_ERR_SERIAL_PORT_INVALID;
+    }
+}
+
+
+/**
+ * \brief Prints a single character to a serial port. 
+ */
+void serial_putchar(unsigned port, char c)
 {
+    assert(port <= NUM_PORTS);
+    omap_uart_t *uart = &ports[port];
+
     // Wait until FIFO can hold more characters
     while(!omap_uart_LSR_tx_fifo_e_rdf(uart));
+
     // Write character
     omap_uart_THR_thr_wrf(uart, c);
 }
 
-/** \brief Reads a single character from the default serial port.
+/** 
+ * \brief Reads a single character from the default serial port.
  * This function spins waiting for a character to arrive.
  */
-char omap_getchar(omap_uart_t *uart)
+char serial_getchar(unsigned port)
 {
+    assert(port <= NUM_PORTS);
+    omap_uart_t *uart = &ports[port];
+
+    // Wait until there is at least one character in the FIFO
+    while(!omap_uart_LSR_rx_fifo_e_rdf(uart));
+
+    // Return the character
     return omap_uart_RHR_rhr_rdf(uart);
 }
index f4d5c9b..4885d11 100644 (file)
@@ -1,13 +1,12 @@
 /**
  * \file
- * \brief The world's simplest serial driver.
+ * \brief PC16550 low-level kernel UART driver
  *
  * AB's quick-and-nasty serial driver.
- * FIXME: make platform independent
  */
 
 /*
- * Copyright (c) 2007, 2008, 2010, 2011, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2010, 2012, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -27,14 +26,37 @@ int serial_portbase = 0x3f8; // COM1 default, can be changed via command-line ar
 #define HEXLETTER 0x3a
 #define HEXCORRECTION 0x7
 
-static pc16550d_t uart;
+#define NUM_PORTS 2
+unsigned serial_console_port = 0;
+unsigned serial_debug_port = 0;
+unsigned serial_num_physical_ports = NUM_PORTS;
+
+// Note: hardwired for PC hardware
+static const uint32_t portbases[NUM_PORTS] = { 0x3f8, 0x2f8 };
+static pc16550d_t ports[NUM_PORTS];
 
 /** \brief Initialise the serial driver. */
-errval_t serial_console_init(uint8_t ordinal)
+errval_t serial_init(unsigned port)
 {
-    assert(ordinal == 0); // multiple ports NYI
+    if (port >= NUM_PORTS) {
+       return SYS_ERR_SERIAL_PORT_INVALID;
+    };
+
+    // XXX Backwards compatibility!
+    if (serial_portbase != 0x3f8 && port == 0) {
+       // We're trying to initialize the console port on a machine
+       // which uses the second UART, but the CPU driver doesn't
+       // understand the new serial interface yet.  Kluge this into
+       // using the second UART, and set the console and debug ports
+       // accordingly. 
+       serial_console_port = 1;
+       serial_debug_port = 1;
+       port = 1;
+    }
 
-    pc16550d_initialize(&uart, serial_portbase);
+    pc16550d_t *uart = &ports[port];
+    pc16550d_initialize(uart, portbases[port]);
+    
 
     // XXX: if non-BSP core, assume HW is already initialised
     if (!arch_core_is_bsp()) {
@@ -45,68 +67,62 @@ errval_t serial_console_init(uint8_t ordinal)
     // disable interrupt
     pc16550d_ier_t ier = pc16550d_ier_default;
     ier = pc16550d_ier_erbfi_insert(ier, 0);
-    pc16550d_ier_wr(&uart, ier);
+    pc16550d_ier_wr(uart, ier);
 
     // enable FIFOs
     pc16550d_fcr_t fcr = pc16550d_fcr_default;
     fcr = pc16550d_fcr_fifoe_insert(fcr, 1);
     // FIFOs hold 14 bytes
     fcr = pc16550d_fcr_rtrigger_insert(fcr, pc16550d_bytes14);
-    pc16550d_fcr_wr(&uart, fcr);
+    pc16550d_fcr_wr(uart, fcr);
 
     pc16550d_lcr_t lcr = pc16550d_lcr_default;
     lcr = pc16550d_lcr_wls_insert(lcr, pc16550d_bits8); // 8 data bits
     lcr = pc16550d_lcr_stb_insert(lcr, 1); // 1 stop bit
     lcr = pc16550d_lcr_pen_insert(lcr, 0); // no parity
-    pc16550d_lcr_wr(&uart, lcr);
+    pc16550d_lcr_wr(uart, lcr);
 
     // set data terminal ready
     pc16550d_mcr_t mcr = pc16550d_mcr_default;
     mcr = pc16550d_mcr_dtr_insert(mcr, 1);
     mcr = pc16550d_mcr_out_insert(mcr, 2);
-    pc16550d_mcr_wr(&uart, mcr);
+    pc16550d_mcr_wr(uart, mcr);
 
     // Set baudrate (XXX: hard-coded to 115200)
     if (!CPU_IS_M5_SIMULATOR) {
-        pc16550d_lcr_dlab_wrf(&uart, 1);
-        pc16550d_dl_wr(&uart, pc16550d_baud115200);
-        pc16550d_lcr_dlab_wrf(&uart, 0);
+        pc16550d_lcr_dlab_wrf(uart, 1);
+        pc16550d_dl_wr(uart, pc16550d_baud115200);
+        pc16550d_lcr_dlab_wrf(uart, 0);
     }
 
     return SYS_ERR_OK;
 }
 
+errval_t serial_early_init(unsigned port)
+{
+    return SYS_ERR_OK;
+}
+
 /** \brief Prints a single character to the default serial port. */
-void serial_console_putchar(char c)
+void serial_putchar(unsigned port, char c)
 {
+    assert(port < NUM_PORTS);
+    assert(ports[port].base != 0);
     // Wait until FIFO can hold more characters
-    while(!pc16550d_lsr_thre_rdf(&uart));
+    while(!pc16550d_lsr_thre_rdf(&uarts[port]));
     // Write character
-    pc16550d_thr_wr(&uart, c);
+    pc16550d_thr_wr(&uarts[port], c);
 }
 
 /** \brief Reads a single character from the default serial port.
  * This function spins waiting for a character to arrive.
  */
-char serial_console_getchar(void)
+char serial_getchar(unsigned port)
 {
-    // Read as many characters as possible from FIFO
-    while( !pc16550d_lsr_dr_rdf(&uart));
-    return pc16550d_rbr_rd(&uart);
-}
+    assert(port < NUM_PORTS);
+    assert(ports[port].base != 0);
 
-errval_t serial_debug_init(uint8_t ordinal)
-{
-    // NOP - for now uses serial console port
-    return SYS_ERR_OK;
-}
-
-void serial_debug_putchar(char c)
-{
-    serial_console_putchar(c);
-}
-
-char serial_debug_getchar(void)
-{
-    return serial_console_getchar();
+    // Read a character from FIFO
+    while( !pc16550d_lsr_dr_rdf(&uarts[port]));
+    return pc16550d_rbr_rd(&uarts[port]);
 }
index 5fec5a1..a4c0346 100644 (file)
@@ -551,7 +551,7 @@ static void  __attribute__ ((noreturn, noinline)) text_init(void)
     kernel_startup_early();
 
     // XXX: re-init the serial driver, in case the port changed after parsing args
-    serial_console_init(0);
+    serial_console_init();
 
     // Setup IDT
     setup_default_idt();
@@ -671,7 +671,7 @@ void arch_init(uint32_t magic, void *pointer)
 #ifndef __scc__
     conio_cls();
 #endif
-    serial_console_init(0);
+    serial_console_init();
 
     /* determine page-aligned physical address past end of multiboot */
     lvaddr_t dest = (lvaddr_t)&_start_kernel;
index 3a41041..30e6c5b 100644 (file)
@@ -465,7 +465,7 @@ static void  __attribute__ ((noreturn, noinline)) text_init(void)
     kernel_startup_early();
 
     // XXX: re-init the serial driver, in case the port changed after parsing args
-    serial_console_init(0);
+    serial_console_init();
 
     // Setup IDT
     setup_default_idt();
@@ -565,7 +565,7 @@ void arch_init(uint64_t magic, void *pointer)
 {
     // Sanitize the screen
     conio_cls();
-    serial_console_init(0);
+    serial_console_init();
 
     void __attribute__ ((noreturn)) (*reloc_text_init)(void) =
         (void *)local_phys_to_mem((lpaddr_t)text_init);
index 5772c82..a856faa 100644 (file)
@@ -224,53 +224,39 @@ uint32_t tsc_get_hz(void)
 // Serial console and debugger interfaces
 //
 
-#define CONSOLE_PORT 0
-#define DEBUG_PORT   1
+#define NUM_PORTS 2
+unsigned serial_console_port = 0;
+unsigned serial_debug_port = 1;
+unsigned serial_num_physical_ports = NUM_PORTS;
 
 static ixp2800_uart_t ports[2];
 
-static errval_t serial_init(uint8_t index, uint8_t port_no)
+errval_t serial_init(unsigned port)
 {
-    if (port_no < 2) {
-        assert(ports[port_no].base == 0);
-
-        lvaddr_t base = paging_map_device(0xc0030000ul + port_no * 0x01000000, 0x00100000);
+    if (port < NUM_PORTS) {
+        assert(ports[port].base == 0);
+        lvaddr_t base = paging_map_device(0xc0030000ul + port * 0x01000000, 0x00100000);
         ixp2800_uart_init(&ports[index], base + 0x30000);
         return SYS_ERR_OK;
-    }
-    else {
+    } else {
         return SYS_ERR_SERIAL_PORT_INVALID;
     }
 }
-
-errval_t serial_console_init(uint8_t port_ordinal)
-{
-    return serial_init(CONSOLE_PORT, port_ordinal);
-}
-
-void serial_console_putchar(char c)
-{
-     ixp2800_putchar(&ports[CONSOLE_PORT], c);
-}
-
-char serial_console_getchar(void)
-{
-    return ixp2800_getchar(&ports[CONSOLE_PORT]);
-}
-
-errval_t serial_debug_init(uint8_t port_ordinal)
+errval_t serial_early_init(unsigned port)
 {
-    //Unused
-    return SYS_ERR_OK;
+    return SYS_ERR_OK; // Unused currently
 }
 
-void serial_debug_putchar(char c)
+void serial_putchar(unsigned port, char c) 
 {
-    //Redirect debug to putchar
-    serial_console_putchar(c);
-}
+    assert(port < NUM_PORTS);
+    assert(ports[port].base != 0);
+    ixp2800_putchar(&ports[port], c);
+};
 
-char serial_debug_getchar(void)
+char serial_getchar(unsigned port)
 {
-    return ixp2800_getchar(&ports[DEBUG_PORT]);
-}
+    assert(port < NUM_PORTS);
+    assert(ports[port].base != 0);
+    return ixp2800_putchar(&ports[port], c);
+};
diff --git a/kernel/include/arch/arm/omap_uart.h b/kernel/include/arch/arm/omap_uart.h
deleted file mode 100644 (file)
index 8af4cae..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#ifndef OMAP_UART_H
-#define OMAP_UART_H
-
-void omap_uart_init(omap_uart_t *uart, lvaddr_t base);
-void omap_putchar(omap_uart_t *uart, char c);
-char omap_getchar(omap_uart_t *uart);
-
-#endif
index b0c860a..919c0b4 100644 (file)
@@ -1,10 +1,16 @@
+/**
+ * \file
+ * \brief Architecture-independent interface to the kernel serial port
+ * subsystem.  
+ */
 /*
- * Copyright (c) 2007, ETH Zurich.
+ * 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ * ETH Zurich D-INFK, CAB F.78, Universitaestr. 6, CH-8092 Zurich. 
+ * Attn: Systems Group.
  */
 
 #ifndef __SERIAL_H
 /* Need to include this for errval_t */
 #include <errors/errno.h>
 
-extern int serial_portbase;
+/*
+ * What kind of serial ports do we have?
+ */
+extern const unsigned serial_num_physical_ports;
+
+/*
+ * Initialize a physical serial port
+ */
+extern errval_t serial_init(unsigned port);
+extern errval_t serial_early_init(unsigned port);
 
-errval_t serial_console_init(uint8_t port_ordinal);
-void serial_console_putchar(char c);
-char serial_console_getchar(void);
+/*
+ * Polled, blocking input/output.  No buffering.
+ */
+extern void serial_putchar(unsigned port, char c);
+extern char serial_getchar(unsigned port);
+
+/*
+ * Console logical port.  Putchar will replace LF with CRLF, unlike
+ * the above calls.
+ */
+extern unsigned serial_console_port;
+
+static inline errval_t serial_console_init(void)
+{
+    return serial_init(serial_console_port);
+}
+static inline void serial_console_putchar(char c)
+{
+    if (c == '\n') {
+        serial_putchar(serial_console_port,'\r');
+    }
+    serial_putchar(serial_console_port, c);
+}
+static inline char serial_console_getchar(void)
+{
+    return serial_getchar(serial_console_port);
+}
+
+/*
+ * Debug logical port.  Putchar will replace LF with CRLF, unlike
+ * the above calls.
+ */
+extern unsigned serial_debug_port;
 
-errval_t serial_debug_init(uint8_t port_ordinal);
-void serial_debug_putchar(char c);
-char serial_debug_getchar(void);
+static inline errval_t serial_debug_init(void)
+{
+    return serial_init(serial_debug_port);
+}
+static inline void serial_debug_putchar(char c)
+{
+    if (c == '\n') {
+        serial_putchar(serial_debug_port,'\r');
+    }
+    serial_putchar(serial_debug_port, c);
+}
+static inline char serial_debug_getchar(void)
+{
+    return serial_getchar(serial_debug_port);
+}
 
 #endif //__SERIAL_H
index e31d929..a04c27f 100644 (file)
@@ -65,6 +65,9 @@ ascii_to_int(int c)
     }
 }
 
+/*
+ * XXX doesn't actually deal with a sign character!!!
+ */
 long int strtol(const char *nptr, char **endptr, int base)
 {
     assert(base == 10 || base == 16);
@@ -80,3 +83,18 @@ long int strtol(const char *nptr, char **endptr, int base)
 
     return retval;
 }
+unsigned long int strtoul(const char *nptr, char **endptr, int base)
+{
+    assert(base == 10 || base == 16);
+    
+    unsigned long int retval = 0;
+
+    for(int i = 0;
+        (base == 10 && isdigit((int)nptr[i])) || (base == 16 && isxdigit((int)nptr[i]));
+        i++) {
+        // Shift and add a digit
+        retval = retval * base + ascii_to_int(nptr[i]);
+    }
+
+    return retval;
+}
index b33d1f0..4fce2b9 100644 (file)
 #include <limits.h>
 #include <getopt/getopt.h>
 
+static int handle_uint(unsigned int *var, const char *val)
+{
+    assert(var != NULL);
+    int base;
+
+    // determine base (0x -> hex, anything else -> decimal)
+    if (val[0] == '0' && val[1] == 'x') {
+        base = 16;
+        val += 2;
+    } else {
+        base = 10;
+    }
+
+    unsigned long x = strtoul(val, NULL, base);
+    if (x > UINT_MAX) { 
+       x = UINT_MAX;
+    }
+    *var = (unsigned)x;
+    return 0;
+}
+
 static int handle_int(int *var, const char *val)
 {
     assert(var != NULL);
     int base;
 
     // determine base (0x -> hex, anything else -> decimal)
-    if (val && val[0] == '0' && val[1] == 'x') {
+    if (val[0] == '0' && val[1] == 'x') {
         base = 16;
         val += 2;
     } else {
@@ -65,6 +86,9 @@ static int handle_argument(const char *var, const char *val,
             case ArgType_Int:
                 return handle_int(a->var.integer, val);
 
+            case ArgType_UInt:
+                return handle_uint(a->var.uinteger, val);
+
             case ArgType_Bool:
                 return handle_bool(a->var.boolean, val);