ARMv7: Rewrote serial drivers on ARM.
authorDavid Cock <david.cock@inf.ethz.ch>
Wed, 27 Jul 2016 18:16:24 +0000 (20:16 +0200)
committerDavid Cock <david.cock@inf.ethz.ch>
Thu, 28 Jul 2016 09:56:17 +0000 (11:56 +0200)
They're now fairly well compartmentalised on both ARM and x86, and can start
automatically from Kaluga.  There's also a 'kernel' serial driver, which uses
the syscall interface to read and write on the kernel console.  This avoids
having user level and kernel code racing on access to the UART.  Fish works
(minus line editing) on all Versatile Express platforms.

Signed-off-by: David Cock <david.cock@inf.ethz.ch>

38 files changed:
devices/pl011_uart.dev
hake/menu.lst.armv7_a15ve
hake/menu.lst.armv7_a15ve_gem5 [new file with mode: 0644]
hake/menu.lst.armv7_a9ve
hake/menu.lst.armv7_pandaboard
hake/menu.lst.armv7_zynq7
hake/menu.lst.x86_32
hake/menu.lst.x86_64
include/barrelfish/barrelfish.h
include/barrelfish/syscalls.h
include/barrelfish_kpi/syscalls.h
include/bitmacros.h
include/multiboot.h
kernel/arch/arm/pl011.c
kernel/arch/arm/zynq_uart.c
kernel/arch/armv7/init.c
kernel/arch/armv7/plat_a15mpcore.c
kernel/arch/armv7/startup_arch.c
kernel/arch/armv7/syscall.c
lib/barrelfish/syscalls.c
platforms/Hakefile
tools/arm_boot/arm_bootimage.c
usr/drivers/serial/Hakefile
usr/drivers/serial/main.c
usr/drivers/serial/serial.h
usr/drivers/serial/serial_debug.h
usr/drivers/serial/serial_gem5.c [deleted file]
usr/drivers/serial/serial_kernel.c [new file with mode: 0644]
usr/drivers/serial/serial_omap44xx.c [moved from usr/drivers/serial/omap44xx_serial.c with 77% similarity]
usr/drivers/serial/serial_pc16550d.c [moved from usr/drivers/serial/serial.c with 86% similarity]
usr/drivers/serial/serial_pl011.c [new file with mode: 0644]
usr/drivers/serial/serial_tmas.c [deleted file]
usr/fish/fish_common.c
usr/kaluga/Hakefile
usr/kaluga/armv7.c
usr/kaluga/armv7_startup.c [moved from usr/kaluga/omap_startup.c with 74% similarity]
usr/kaluga/debug.h
usr/kaluga/device_caps.c

index ec52bfa..9080bc1 100644 (file)
@@ -169,7 +169,7 @@ device pl011_uart msbfirst ( addr base ) "PL011 UART" {
   };
 
   register ICR addr (base, 0x44) "Interrupt clear register" {
-    _        21;
+    _        21 mbz;
     oeic      1 rw1c    "Overrun error interrupt clear";
     beic      1 rw1c    "Break error interrupt clear";
     peic      1 rw1c    "Parity error interrupt clear";
index 523702e..e728233 100644 (file)
@@ -22,15 +22,21 @@ module /armv7/sbin/ramfsd boot
 module /armv7/sbin/skb boot
 modulenounzip /eclipseclp_ramfs.cpio.gz nospawn
 modulenounzip /skb_ramfs.cpio.gz nospawn
+module /armv7/sbin/kaluga boot
 module /armv7/sbin/spawnd boot
 module /armv7/sbin/startd boot
 
+# Device drivers
+# module /armv7/sbin/serial_pl011 auto
+module /armv7/sbin/serial_kernel irq=37
+
 # General user domains
-#module        /armv7/sbin/serial
-#module        /armv7/sbin/fish
+module /armv7/sbin/angler serial0.terminal dumb
+module /armv7/sbin/fish nospawn
 
 module /armv7/sbin/memtest
 
 # gem5 simulates 512MB of RAM starting at 0x80000000
 #        start       size       id
+mmap map 0x00000000  0x80000000 13 # Device region
 mmap map 0x80000000  0x20000000 1
diff --git a/hake/menu.lst.armv7_a15ve_gem5 b/hake/menu.lst.armv7_a15ve_gem5
new file mode 100644 (file)
index 0000000..96d4dc6
--- /dev/null
@@ -0,0 +1,42 @@
+timeout 0
+
+#
+# This script is used to describe the commands to start at
+# boot-time and the arguments they should receive.
+#
+# Kernel arguments are not read from this script. On QEMU they can be
+# set using 'qemu-system-arm -append ...'.
+
+title  Barrelfish
+#root  (nd)
+kernel /armv7/sbin/cpu_a15ve loglevel=4 periphbase=0x2c000000 consolePort=0 timerirq=29
+module /armv7/sbin/cpu_a15ve
+module /armv7/sbin/init
+
+# Domains spawned by init
+module /armv7/sbin/mem_serv
+module /armv7/sbin/monitor
+
+# Special boot time domains spawned by monitor
+module /armv7/sbin/ramfsd boot
+module /armv7/sbin/skb boot
+modulenounzip /eclipseclp_ramfs.cpio.gz nospawn
+modulenounzip /skb_ramfs.cpio.gz nospawn
+module /armv7/sbin/kaluga boot
+module /armv7/sbin/spawnd boot
+module /armv7/sbin/startd boot
+
+# Device drivers
+# module /armv7/sbin/serial_pl011 auto
+module /armv7/sbin/serial_kernel irq=37
+
+# General user domains
+module /armv7/sbin/angler serial0.terminal dumb
+module /armv7/sbin/fish nospawn
+
+module /armv7/sbin/memtest
+
+# gem5 simulates 512MB of RAM starting at 0x80000000
+#        start       size       id
+mmap map 0x00000000  0x80000000 13 # Device region
+mmap map 0x80000000  0x20000000 1
index 74c7a7e..1a3825c 100644 (file)
@@ -9,7 +9,7 @@ timeout 0
 
 title  Barrelfish
 # We have 100MHz timer on the FVP, but that's not discoverable at run time.
-kernel /armv7/sbin/cpu_a9ve loglevel=4 periphclk=100000000 consolePort=0
+kernel /armv7/sbin/cpu_a9ve loglevel=5 logmask=1 periphclk=100000000 consolePort=0
 module /armv7/sbin/cpu_a9ve
 module /armv7/sbin/init
 
@@ -22,17 +22,24 @@ module /armv7/sbin/ramfsd boot
 module /armv7/sbin/skb boot
 modulenounzip /eclipseclp_ramfs.cpio.gz nospawn
 modulenounzip /skb_ramfs.cpio.gz nospawn
+module /armv7/sbin/kaluga boot
 module /armv7/sbin/spawnd boot
 module /armv7/sbin/startd boot
 
+# Device drivers
+# module /armv7/sbin/serial_pl011 auto
+module /armv7/sbin/serial_kernel irq=37
+
 # General user domains
-#module        /armv7/sbin/serial
-#module        /armv7/sbin/fish
+module /armv7/sbin/angler serial0.terminal dumb
+module /armv7/sbin/fish nospawn
 
 module /armv7/sbin/memtest
 
 # The FVP simulates 4GB of RAM, 2GB of which is in the 32-bit address space.
 #        start       size       id
-mmap map  0x80000000  0x40000000 1
-mmap map  0xC0000000  0x40000000 1
-mmap map 0x880000000  0x80000000 1
+mmap map  0x00000000  0x80000000 13 # Device region
+mmap map  0x80000000  0x40000000  1
+mmap map  0xC0000000  0x40000000  1
+# Caps above 4GB break things right now, but should be ignored.
+#mmap map 0x880000000  0x80000000  1
index 0f4adcf..bf78332 100644 (file)
@@ -24,14 +24,18 @@ module /armv7/sbin/kaluga boot
 module /armv7/sbin/spawnd boot bootarm=0
 module /armv7/sbin/startd boot
 
+# Device drivers
+# module /armv7/sbin/serial_omap44xx
+module /armv7/sbin/serial_kernel irq=74
+
 # General user domains
-module /armv7/sbin/serial auto portbase=2
+module /armv7/sbin/angler serial0.terminal dumb
 module /armv7/sbin/fish nospawn
-module /armv7/sbin/angler serial0.terminal xterm
 
 module /armv7/sbin/memtest
 
 #module /armv7/sbin/corectrl auto
 
 # For pandaboard, use following values.
-mmap map 0x80000000 0x40000000 1
+mmap map 0x40000000 0x40000000 13 # Devices
+mmap map 0x80000000 0x40000000  1
index 12835ff..dc1c0a1 100644 (file)
@@ -21,14 +21,19 @@ module /armv7/sbin/ramfsd boot
 module /armv7/sbin/skb boot
 modulenounzip /eclipseclp_ramfs.cpio.gz nospawn
 modulenounzip /skb_ramfs.cpio.gz nospawn
+module /armv7/sbin/kaluga boot
 module /armv7/sbin/spawnd boot
 module /armv7/sbin/startd boot
 
+# Device drivers
+module /armv7/sbin/serial_kernel irq=82
+
 # General user domains
-#module        /armv7/sbin/serial
-#module        /armv7/sbin/fish
+module /armv7/sbin/angler serial0.terminal dumb
+module /armv7/sbin/fish nospawn
 
 module /armv7/sbin/memtest
 
 #        start       size       id
-mmap map 0x00000000  0x40000000 1
+mmap map 0x00000000  0x40000000  1
+mmap map 0x80000000  0x80000000 13 # Devices
index 26e978e..8760131 100644 (file)
@@ -36,6 +36,6 @@ module /x86_32/sbin/corectrl auto
 module /x86_32/sbin/pci auto
 
 # General user domains
-module /x86_32/sbin/serial
+module /x86_32/sbin/serial_pc16550d
 module  /x86_32/sbin/fish nospawn
 module /x86_32/sbin/angler serial0.terminal xterm
index 9f2a8a7..95c8439 100644 (file)
@@ -46,7 +46,7 @@ module /x86_64/sbin/NGD_mng auto
 module /x86_64/sbin/netd auto
 
 # General user domains
-module /x86_64/sbin/serial
+module /x86_64/sbin/serial_pc16550d
 module  /x86_64/sbin/fish nospawn
 module /x86_64/sbin/angler serial0.terminal xterm
 
index 1fad374..00b8833 100644 (file)
@@ -23,6 +23,9 @@
 #include <stdlib.h>
 #include <assert.h>
 
+/* utility macros */
+#include <bitmacros.h>
+
 /* barrelfish kernel interface definitions */
 #include <errors/errno.h>
 #include <barrelfish_kpi/types.h>
 
 /* XXX: utility macros. not sure where to put these */
 
-/// Round up n to the next multiple of size
-#define ROUND_UP(n, size)           ((((n) + (size) - 1)) & (~((size) - 1)))
-
-/// Divide n by size, rounding up
-#define DIVIDE_ROUND_UP(n, size)    (((n) + (size) - 1) / (size))
-
-/// Round n down to the nearest multiple of size
-#define ROUND_DOWN(n, size)         ((n) & (~((size) - 1)))
-
-/** Macro to return the number of entries in a statically-allocated array. */
-#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
-
-/// Computes the floor of log_2 of the given number
-static inline uint8_t log2floor(uintptr_t num)
-{
-    uint8_t l = 0;
-    uintptr_t n;
-    for (n = num; n > 1; n >>= 1, l++);
-    return l;
-}
-
-/// Computes the ceiling of log_2 of the given number
-static inline uint8_t log2ceil(uintptr_t num)
-{
-    uint8_t l = log2floor(num);
-    if (num == ((uintptr_t)1) << l) { /* fencepost case */
-        return l;
-    } else {
-        return l + 1;
-    }
-}
-
-/// Duplicate memory
+/* Duplicate memory */
 static inline void * memdup(const void *ptr, size_t size) {
     void *res = malloc(size);
     assert(res);
index f3fb74f..8ad1a79 100644 (file)
@@ -55,6 +55,8 @@ errval_t sys_reboot(void);
  */
 errval_t sys_print(const char *string, size_t length);
 
+errval_t sys_getchar(char *c);
+
 /**
  * \brief get time elapsed (in milliseconds) since system boot.
  */
index a5ea4ee..8a34829 100644 (file)
@@ -47,15 +47,16 @@ struct sysret {
 #define SYSCALL_REBOOT              4     ///< Reboot the machine
 #define SYSCALL_NOP                 5     ///< No operation
 #define SYSCALL_PRINT               6     ///< Write to console
+#define SYSCALL_GETCHAR             7     ///< Read from console
 
 /* Architecture-specific syscalls
  * FIXME: shouldn't these be in an arch-specific header? -AB */
-#define SYSCALL_X86_FPU_TRAP_ON     7     ///< Turn FPU trap on (x86)
-#define SYSCALL_X86_RELOAD_LDT      8     ///< Reload the LDT register (x86_64)
-#define SYSCALL_SUSPEND             9     ///< Suspend the CPU
-#define SYSCALL_GET_ABS_TIME        10    ///< Get time elapsed since boot
+#define SYSCALL_X86_FPU_TRAP_ON     8     ///< Turn FPU trap on (x86)
+#define SYSCALL_X86_RELOAD_LDT      9     ///< Reload the LDT register (x86_64)
+#define SYSCALL_SUSPEND             10    ///< Suspend the CPU
+#define SYSCALL_GET_ABS_TIME        11    ///< Get time elapsed since boot
 
-#define SYSCALL_COUNT               11     ///< Number of syscalls [0..SYSCALL_COUNT - 1]
+#define SYSCALL_COUNT               12     ///< Number of syscalls [0..SYSCALL_COUNT - 1]
 
 /*
  * To understand system calls it might be helpful to know that there
index 8dc0541..7f4a5ab 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef __BITMACROS_H
 #define __BITMACROS_H
 
+#include <stdint.h>
+
 /* A one-bit mask at bit n */
 #define BIT(n) (1ULL << (n))
 
 /* Round n up to the next multiple of size */
 #define ROUND_UP(n, size) ((((n) + (size) - 1)) & (~((size) - 1)))
 
+/* Divide n by size, rounding up */
+#define DIVIDE_ROUND_UP(n, size) (((n) + (size) - 1) / (size))
+
+/* Round n down to the nearest multiple of size */
+#define ROUND_DOWN(n, size) ((n) & (~((size) - 1)))
+
+/* Return the number of entries in a statically-allocated array */
+#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
+
+/* Compute the floor of log_2 of the given number */
+static inline uint8_t
+log2floor(uintptr_t num) {
+    uint8_t l = 0;
+    uintptr_t n;
+    for (n = num; n > 1; n >>= 1, l++);
+    return l;
+}
+
+/* Compute the ceiling of log_2 of the given number */
+static inline uint8_t
+log2ceil(uintptr_t num) {
+    uint8_t l = log2floor(num);
+    if (num == ((uintptr_t)1) << l) { /* fencepost case */
+        return l;
+    } else {
+        return l + 1;
+    }
+}
+
 #endif /* __BITMACROS_H */
index 6546f46..bfd81f1 100644 (file)
@@ -119,6 +119,8 @@ struct multiboot_modinfo {
 #define MULTIBOOT_MEM_TYPE_RAM          1
 // special type for the host memory mapping of the xeon phi
 #define MULTIBOOT_MEM_TYPE_HOST_MEMORY  2
+// Memory-mapped devices
+#define MULTIBOOT_MEM_TYPE_DEVICE      13
 
 struct multiboot_mmap {
     uint32_t    size;
index d201ed8..0a90709 100644 (file)
@@ -53,7 +53,6 @@ errval_t serial_early_init(unsigned n)
     return SYS_ERR_OK;
 }
 
-
 /**
  * \brief Configure the serial interface, from a caller that knows
  * that this is a bunch of PL011s, and furthermore where they are in
@@ -87,23 +86,49 @@ void pl011_init(unsigned port, lvaddr_t base, bool hwinit)
     pl011_uart_initialize(u, (mackerel_addr_t) base);
 
     if (hwinit) {
-       // Mask all interrupts: set all bits to zero
-       pl011_uart_IMSC_rawwr(u, INTERRUPTS_MASK);
-       
-       // Configure port to 38400 baud, 8 data, no parity, 1 stop (8-N-1)
-       //
-       // (This is a mild scam as system is running in QEMU)
-       //
-       // Note baud rate changes not committed in h/w until lcr_h
-       // written.
-       pl011_uart_IBRD_divint_wrf(u, 0xc); // Assuming UARTCLK is 7.3728MHz
-       pl011_uart_FBRD_divfrac_wrf(u, 0);
-       
-       // Set 8 bits, no parity
-       pl011_uart_LCR_H_t lcr = (pl011_uart_LCR_H_t)0;
-       pl011_uart_LCR_H_fen_insert(lcr, 1);
-       pl011_uart_LCR_H_wlen_insert(lcr, pl011_uart_bits8);
-       pl011_uart_LCR_H_wr(u, lcr);
+        // Mask all interrupts: set all bits to zero
+        pl011_uart_IMSC_rawwr(u, INTERRUPTS_MASK);
+
+        // Disable the UART before reconfiguring it.
+        pl011_uart_CR_uarten_wrf(u, 0);
+
+        // Clear and enable the receive interrupt.
+        pl011_uart_ICR_rxic_wrf(u, 1);
+        pl011_uart_IMSC_rxim_wrf(u, 1);
+        
+        // Configure port to 38400 baud, 8 data, no parity, 1 stop (8-N-1)
+        //
+        // (This is a mild scam as system is running in QEMU)
+        //
+        // Note baud rate changes not committed in h/w until lcr_h
+        // written.
+        pl011_uart_IBRD_divint_wrf(u, 0xc); // Assuming UARTCLK is 7.3728MHz
+        pl011_uart_FBRD_divfrac_wrf(u, 0);
+        
+        /* Configure the line control register. */
+        pl011_uart_LCR_H_t lcr= (pl011_uart_LCR_H_t)0;
+        /* Disable FIFOs.  There's no way to get an interrupt when a single
+         * character arrives with FIFOs, so it's useless as a console. */
+        lcr= pl011_uart_LCR_H_fen_insert(lcr, 0);
+        /* Eight data bits. */
+        lcr= pl011_uart_LCR_H_wlen_insert(lcr, pl011_uart_bits8);
+        /* No parity. */
+        lcr= pl011_uart_LCR_H_pen_insert(lcr, 0);
+        /* One stop bit. */
+        lcr= pl011_uart_LCR_H_stp2_insert(lcr, 0);
+        pl011_uart_LCR_H_wr(u, lcr);
+
+        /* Configure the main control register. */
+        pl011_uart_CR_t cr = (pl011_uart_CR_t)0;
+        /* No flow control. */
+        cr= pl011_uart_CR_ctsen_insert(cr, 0);
+        cr= pl011_uart_CR_rtsen_insert(cr, 0);
+        /* Enable transmit and receive. */
+        cr= pl011_uart_CR_txe_insert(cr, 1);
+        cr= pl011_uart_CR_rxe_insert(cr, 1);
+        /* Enable UART. */
+        cr= pl011_uart_CR_uarten_insert(cr, 1);
+        pl011_uart_CR_wr(u, cr);
     }
 }
 
@@ -112,29 +137,28 @@ void pl011_init(unsigned port, lvaddr_t base, bool hwinit)
  */
 void serial_putchar(unsigned port, char c) 
 {
-    assert(port < MAX_PORTS );
+    assert(port < MAX_PORTS);
     pl011_uart_t *u = &uarts[port];
     assert(u->base != 0);
 
-    while (pl011_uart_FR_txff_rdf(u) == 1)
-        ;
+    while(pl011_uart_FR_txff_rdf(u) == 1) ;
     pl011_uart_DR_rawwr(u, c);
-    // pl011_uart_DR_t dr;
-    // dr = (pl011_uart_DR_t)0;
-    // pl011_uart_DR_data_insert(dr, (uint8_t)c);
-};
-
+}
 
 /*
  * \brief Read a character from a port
  */
 char serial_getchar(unsigned port)
 {
-    assert(port < MAX_PORTS );
+    assert(port < MAX_PORTS);
     pl011_uart_t *u = &uarts[port];
     assert(u->base != 0);
 
-    while (pl011_uart_FR_rxfe_rdf(u) == 1)
-        ;
-    return (char) pl011_uart_DR_data_rdf(u);
-};
+    /* Wait for data. */
+    while(pl011_uart_FR_rxfe_rdf(u) == 1);
+
+    /* Acknowledge any interrupt. */
+    pl011_uart_ICR_rxic_wrf(u, 1);
+
+    return (char)pl011_uart_DR_data_rdf(u);
+}
index d8a0956..25f800f 100644 (file)
@@ -57,7 +57,21 @@ zynq_uart_init(unsigned port, lvaddr_t base, bool initialize_hw) {
  */
 static void
 zynq_uart_hw_init(zynq_uart_t *uart) {
-    /* Do we need this at all, if we're assuming it already works? */
+    /* Disable all interrupts. */
+    zynq_uart_IDR_rawwr(uart, 0);
+
+    /* Clear all interrupts. */
+    zynq_uart_ISR_rawwr(uart, 0xffffffff);
+
+    /* Trigger an interrupt on a single byte. */
+    zynq_uart_RXWM_RTRIG_wrf(uart, 1);
+
+    /* Enable RX trigger interrupt. */
+    zynq_uart_IER_rtrig_wrf(uart, 1);
+
+    /* Enable receiver. */
+    zynq_uart_CR_rx_dis_wrf(uart, 0);
+    zynq_uart_CR_rx_en_wrf(uart, 1);
 }
 
 /**
@@ -87,6 +101,9 @@ serial_getchar(unsigned port) {
     /* Wait until there is at least one character in the FIFO. */
     while(zynq_uart_SR_RXEMPTY_rdf(uart));
 
+    /* Clear the RX interrupt - XXX should be level-triggered. */
+    zynq_uart_ISR_rtrig_wrf(uart, 1);
+
     /* Return the character. */
     return zynq_uart_FIFO_FIFO_rdf(uart);
 }
index ba7588d..24c619d 100644 (file)
@@ -51,6 +51,7 @@ static bool is_bsp = false;
 
 uint32_t periphclk = 0;
 uint32_t periphbase = 0;
+uint32_t timerirq = 0;
 
 static struct cmdarg cmdargs[] = {
     { "consolePort", ArgType_UInt, { .uinteger = (void *)0 } },
@@ -60,6 +61,7 @@ static struct cmdarg cmdargs[] = {
     { "timeslice",   ArgType_Int,  { .integer  = (void *)0 } },
     { "periphclk",   ArgType_UInt, { .uinteger = (void *)0 } },
     { "periphbase",  ArgType_UInt, { .uinteger = (void *)0 } },
+    { "timerirq"  ,  ArgType_UInt, { .uinteger = (void *)0 } },
     { NULL, 0, { NULL } }
 };
 
@@ -72,6 +74,7 @@ init_cmdargs(void) {
     cmdargs[4].var.integer=  &kernel_timeslice;
     cmdargs[5].var.uinteger= &periphclk;
     cmdargs[6].var.uinteger= &periphbase;
+    cmdargs[7].var.uinteger= &timerirq;
 }
 
 /**
index 8d49fa5..dc8a37c 100644 (file)
@@ -55,12 +55,12 @@ platform_get_core_count(void) {
 /* Timeslice counter uses the Non-secure Physical Timer. */
 
 /* See TRM 8.2.3 */
-// XXX - this *should* be IRQ 30, for the non-secure timer, but GEM5 only
-// provides the secure timer, even in NS mode.  This will need to be a quirk
-// parameter.
-//#define LOCAL_TIMER_IRQ 30
-#define LOCAL_TIMER_IRQ 29
+/* This *should* be IRQ 30, for the non-secure timer, but GEM5 only
+ * provides the secure timer, even in NS mode.
+ * The timerirq parameter allows this to be overridden. */
+#define DEFAULT_TIMER_IRQ 30
 
+extern uint32_t timerirq;
 static uint32_t timeslice_ticks;
 
 void
@@ -74,8 +74,11 @@ timers_init(int timeslice) {
 
     a15_gt_init();
 
+    if(timerirq == 0) timerirq= DEFAULT_TIMER_IRQ;
+    MSG("Timer interrupt is %u\n", timerirq);
+
     /* Enable the interrupt. */
-    gic_enable_interrupt(LOCAL_TIMER_IRQ, 0, 0, 0, 0);
+    gic_enable_interrupt(timerirq, 0, 0, 0, 0);
 
     /* Set the first timeout. */
     a15_gt_timeout(timeslice_ticks);
@@ -96,7 +99,7 @@ timestamp_freq(void) {
 
 bool
 timer_interrupt(uint32_t irq) {
-    if(irq == LOCAL_TIMER_IRQ) {
+    if(irq == timerirq) {
         gic_ack_irq(irq);
 
         /* Reset the timeout. */
index ad498f2..e30e62c 100644 (file)
@@ -326,92 +326,81 @@ void create_module_caps(struct spawn_state *st)
     }
 }
 
-/// Create physical address range or RAM caps to unused physical memory
+/* Create physical address range or RAM caps to unused physical memory.
+   init_alloc_addr is the last address allocated for the init process, plus
+   one. */
 static void create_phys_caps(lpaddr_t init_alloc_addr)
 {
     struct multiboot_info *mb=
         (struct multiboot_info *)core_data->multiboot_header;
     errval_t err;
 
-    /* Walk multiboot MMAP structure, and create appropriate caps for memory */
-    char *mmap_addr = MBADDR_ASSTRING(mb->mmap_addr);
-    genpaddr_t last_end_addr = 0;
-
-    for(char *m = mmap_addr; m < mmap_addr + mb->mmap_length;) {
-        struct multiboot_mmap *mmap = (struct multiboot_mmap * SAFE)TC(m);
-
-        debug(SUBSYS_STARTUP, "MMAP %llx--%llx Type %"PRIu32"\n",
-                mmap->base_addr, mmap->base_addr + mmap->length,
-                mmap->type);
-
-        if (last_end_addr >= init_alloc_addr
-                && mmap->base_addr > last_end_addr) {
-            /* we have a gap between regions. add this as a physaddr range */
-            debug(SUBSYS_STARTUP, "physical address range %llx--%llx\n",
-                    last_end_addr, mmap->base_addr);
-
-            err = create_caps_to_cnode(last_end_addr,
-                    mmap->base_addr - last_end_addr,
-                    RegionType_PhyAddr, &spawn_state, bootinfo);
-            assert(err_is_ok(err));
-        }
-
-        if (mmap->type == MULTIBOOT_MEM_TYPE_RAM) {
-            genpaddr_t base_addr = mmap->base_addr;
-            genpaddr_t end_addr  = base_addr + mmap->length;
-
-            // only map RAM which is greater than init_alloc_addr
-            if (end_addr > local_phys_to_gen_phys(init_alloc_addr))
-            {
-                if (base_addr < local_phys_to_gen_phys(init_alloc_addr)) {
-                    base_addr = local_phys_to_gen_phys(init_alloc_addr);
+    /* Walk multiboot MMAP structure, and create appropriate caps for memory.
+       This function assumes that the memory map is sorted by base address,
+       and contains no overlaps.  We also assume that the kernel, and init,
+       have been allocated at the beginning of the first RAM region, and thus
+       that init_alloc_addr represents the lowest unallocated RAM address. */
+    genpaddr_t last_end_addr= 0;
+    genpaddr_t first_free_byte= local_phys_to_gen_phys(init_alloc_addr);
+    debug(SUBSYS_STARTUP, "First free byte is PA:0x%"PRIxGENPADDR".\n",
+                          first_free_byte);
+
+    lvaddr_t mmap_vaddr= local_phys_to_mem((lpaddr_t)mb->mmap_addr);
+    for(uint32_t i= 0; i < mb->mmap_length; i++) {
+        struct multiboot_mmap *mmap = (struct multiboot_mmap *)mmap_vaddr;
+
+        genpaddr_t base_addr = mmap->base_addr;
+        genpaddr_t end_addr  = base_addr + (mmap->length - 1);
+
+        debug(SUBSYS_STARTUP, "MMAP PA:0x%"PRIxGENPADDR"-0x%"
+                              PRIxGENPADDR" type %"PRIu32"\n",
+                              base_addr, end_addr, mmap->type);
+
+        switch(mmap->type) {
+            case MULTIBOOT_MEM_TYPE_RAM:
+                /* Only map RAM which is greater than init_alloc_addr. */
+                if (end_addr >= first_free_byte) {
+                    if(base_addr < first_free_byte)
+                        base_addr= first_free_byte;
+                    debug(SUBSYS_STARTUP, "RAM PA:0x%"PRIxGENPADDR"-0x%"
+                                          PRIxGENPADDR"\n",
+                                          base_addr, end_addr);
+
+                    assert(end_addr >= base_addr);
+                    err= create_caps_to_cnode(base_addr,
+                            (end_addr - base_addr) + 1,
+                            RegionType_Empty, &spawn_state, bootinfo);
+                    assert(err_is_ok(err));
+                }
+                break;
+
+            case MULTIBOOT_MEM_TYPE_DEVICE:
+                /* Device memory will be handled explicitly later. */
+                break;
+
+            default:
+                if (mmap->base_addr >= first_free_byte) {
+                    /* XXX: The multiboot spec just says that mapping types
+                     * other than RAM are "reserved", but GRUB always maps the
+                     * ACPI tables as type 3, and things like the IOAPIC tend
+                     * to show up as type 2 or 4, so we map all these regions
+                     * as platform data.  */
+                    debug(SUBSYS_STARTUP, "Platform data PA:0x%"PRIxGENPADDR
+                                          "-0x%"PRIxGENPADDR"\n", base_addr,
+                                          end_addr);
+                    assert(base_addr >= first_free_byte);
+                    err = create_caps_to_cnode(base_addr, mmap->length,
+                            RegionType_PlatformData, &spawn_state, bootinfo);
+                    assert(err_is_ok(err));
                 }
-                debug(SUBSYS_STARTUP, "RAM %llx--%llx\n", base_addr, end_addr);
-
-                assert(end_addr >= base_addr);
-                err = create_caps_to_cnode(base_addr, end_addr - base_addr,
-                        RegionType_Empty, &spawn_state, bootinfo);
-                assert(err_is_ok(err));
-            }
-        } else if (mmap->base_addr > local_phys_to_gen_phys(init_alloc_addr)) {
-            /* XXX: The multiboot spec just says that mapping types other than
-             * RAM are "reserved", but GRUB always maps the ACPI tables as type
-             * 3, and things like the IOAPIC tend to show up as type 2 or 4,
-             * so we map all these regions as platform data
-             */
-            debug(SUBSYS_STARTUP, "platform %llx--%llx\n", mmap->base_addr,
-                    mmap->base_addr + mmap->length);
-            assert(mmap->base_addr > local_phys_to_gen_phys(init_alloc_addr));
-            err = create_caps_to_cnode(mmap->base_addr, mmap->length,
-                    RegionType_PlatformData, &spawn_state, bootinfo);
-            assert(err_is_ok(err));
         }
-        last_end_addr = mmap->base_addr + mmap->length;
-        m += mmap->size + 4;
+
+        last_end_addr= end_addr;
+        mmap_vaddr+= mmap->size;
     }
 
     // Assert that we have some physical address space
     assert(last_end_addr != 0);
-
-    if (last_end_addr < PADDR_SPACE_SIZE) {
-       /*
-        * FIXME: adding the full range results in too many caps to add
-        * to the cnode (and we can't handle such big caps in user-space
-        * yet anyway) so instead we limit it to something much smaller
-        */
-       genpaddr_t size = PADDR_SPACE_SIZE - last_end_addr;
-       const genpaddr_t phys_region_limit = 1ULL << 32; // PCI implementation limit
-       if (last_end_addr > phys_region_limit) {
-               size = 0; // end of RAM is already too high!
-       } else if (last_end_addr + size > phys_region_limit) {
-               size = phys_region_limit - last_end_addr;
-       }
-       debug(SUBSYS_STARTUP, "end physical address range %llx--%llx\n",
-                       last_end_addr, last_end_addr + size);
-       err = create_caps_to_cnode(last_end_addr, size,
-                       RegionType_PhyAddr, &spawn_state, bootinfo);
-       assert(err_is_ok(err));
-    }
 }
 
 /*
@@ -494,6 +483,41 @@ static void init_page_tables(void)
     paging_context_switch(mem_to_local_phys((lvaddr_t)init_l1));
 }
 
+/* Locate the first device region below 4GB listed in the multiboot memory
+ * map, and truncate it to fit. */
+static void
+first_device_region(lpaddr_t *base, lpaddr_t *length) {
+    struct multiboot_info *mb=
+        (struct multiboot_info *)core_data->multiboot_header;
+
+    lvaddr_t mmap_vaddr= local_phys_to_mem((lpaddr_t)mb->mmap_addr);
+    for(uint32_t i= 0; i < mb->mmap_length; i++) {
+        struct multiboot_mmap *mmap= (struct multiboot_mmap *)mmap_vaddr;
+
+        if(mmap->type == MULTIBOOT_MEM_TYPE_DEVICE) {
+            uint64_t base64=   mmap->base_addr;
+            uint64_t length64= mmap->length;
+
+            if(base64 > (uint64_t)UINT32_MAX) {
+                MSG("device region %"PRIu32" lies above 4GB.\n", i);
+            }
+            else if(base64 + length64 > (uint64_t)UINT32_MAX) {
+                MSG("device region %"PRIu32" extends beyond 4GB, "
+                    "truncating it.\n", i);
+                length64= ((uint64_t)UINT32_MAX - base64) + 1;
+            }
+
+            *base=   (lpaddr_t)base64;
+            *length= (lpaddr_t)length64;
+            return;
+        }
+
+        mmap_vaddr+= mmap->size;
+    }
+
+    panic("No device regions specified in multiboot memory map.\n");
+}
+
 static struct dcb *
 spawn_init_common(const char *name, int argc, const char *argv[],
                   lpaddr_t bootinfo_phys, alloc_phys_func alloc_phys,
@@ -524,17 +548,29 @@ spawn_init_common(const char *name, int argc, const char *argv[],
                    mem_to_local_phys(init_dcb->disp), DISPATCHER_SIZE,
                    INIT_PERM_RW);
 
+    /* Locate the memory-mapped device region. */
+    lpaddr_t device_base, device_length;
+    first_device_region(&device_base, &device_length);
+    MSG("Using device region at PA:0x%"PRIx32"-0x%"PRIx32"\n",
+            device_base, device_base + (device_length - 1));
+    if((1UL << log2ceil(device_length)) != device_length) {
+        panic("Device region isn't a power of two in size.\n");
+    }
 
     /*
-     * we create the capability to the devices at this stage and store it
+     * We create the capability to the devices at this stage and store it
      * in the TASKCN_SLOT_IO, where on x86 the IO capability is stored for
-     * device access on PCI. PCI is not available on the pandaboard so this
-     * should not be a problem.
+     * device access on PCI.
+     *
+     * PCI is not available on our existing ARMv7 platforms, but this may be a
+     * problem in future.
      */
-    struct cte *iocap = caps_locate_slot(CNODE(spawn_state.taskcn), TASKCN_SLOT_IO);
-    errval_t  err = caps_create_new(ObjType_DevFrame, 0x40000000, 1UL << 30,
-                                    1UL << 30, my_core_id, iocap);
-        assert(err_is_ok(err));
+    struct cte *iocap=
+        caps_locate_slot(CNODE(spawn_state.taskcn), TASKCN_SLOT_IO);
+    errval_t err=
+        caps_create_new(ObjType_DevFrame, device_base, device_length,
+                        device_length, my_core_id, iocap);
+    assert(err_is_ok(err));
 
     struct dispatcher_shared_generic *disp
         = get_dispatcher_shared_generic(init_dcb->disp);
index 5724234..b0891bb 100644 (file)
@@ -19,6 +19,7 @@
 #include <paging_kernel_arch.h>
 #include <dispatch.h>
 #include <exec.h>
+#include <serial.h>
 #include <stdio.h>
 #include <sys_debug.h>
 #include <syscall.h>
@@ -1169,6 +1170,11 @@ void sys_syscall(arch_registers_state_t* context,
             }
             break;
 
+        case SYSCALL_GETCHAR:
+            r.value = serial_console_getchar();
+            r.error = SYS_ERR_OK;
+            break;
+
         case SYSCALL_DEBUG:
             if (argc == 2) {
                 r = handle_debug_syscall(sa->arg1);
index bd297b5..64ff7b6 100644 (file)
@@ -36,3 +36,10 @@ errval_t sys_print(const char *string, size_t length)
 {
     return syscall3(SYSCALL_PRINT, (uintptr_t)string, length).error;
 }
+
+errval_t sys_getchar(char *c)
+{
+    struct sysret ret= syscall1(SYSCALL_GETCHAR);
+    *c= ret.value;
+    return ret.error;
+}
index e22b48a..6540754 100644 (file)
@@ -209,7 +209,7 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                            "pci",
                            "routing_setup",
                            "rtl8029",
-                           "serial",
+                           "serial_pc16550d",
                            "sfxge",
                            "slideshow",
                            "sshd",
@@ -235,7 +235,7 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
     modules_x86_32  = [ "/sbin/" ++ f | f <- [
                            "cpu",
                            "lpc_kbd",
-                           "serial",
+                           "serial_pc16550d",
                            "rcce_pingpong",
                            "bench",
                            "fbdemo",
@@ -283,7 +283,8 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                         "bulk_sdma",
                         "usb_manager",
                         "usb_keyboard",
-                        "serial",
+                        "serial_omap44xx",
+                        "serial_kernel",
                         "angler"
                         -- "corectrl"
                         ] ]
@@ -292,13 +293,18 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
     vExpressEMMModules_A15 = [ "/sbin/" ++ f | f <- [
                                "cpu_a15ve",
                                "init",
+                               "kaluga",
                                "mem_serv",
                                "monitor",
                                "ramfsd",
+                               "serial_pl011",
+                               "serial_kernel",
                                "spawnd",
                                "startd",
                                -- "corectrl",
                                "skb",
+                               "angler",
+                               "fish",
                                "memtest"
                                ] ]
 
@@ -306,13 +312,18 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
     vExpressEMMModules_A9 = [ "/sbin/" ++ f | f <- [
                               "cpu_a9ve",
                               "init",
+                              "kaluga",
                               "mem_serv",
                               "monitor",
                               "ramfsd",
+                              "serial_pl011",
+                              "serial_kernel",
                               "spawnd",
                               "startd",
                               -- "corectrl",
                               "skb",
+                              "angler",
+                              "fish",
                               "memtest"
                               ] ]
 
@@ -320,13 +331,17 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
     zynq7Modules = [ "/sbin/" ++ f | f <- [
                      "cpu_zynq7",
                      "init",
+                     "kaluga",
                      "mem_serv",
                      "monitor",
                      "ramfsd",
+                     "serial_kernel",
                      "spawnd",
                      "startd",
                      -- "corectrl",
                      "skb",
+                     "angler",
+                     "fish",
                      "memtest"
                      ] ]
 
@@ -342,7 +357,7 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                        -- "corectrl",
                        "skb",
                        "memtest",
-                       "serial",
+                       "serial_pl011",
                        "fish",
                        "angler"
                        ] ]
@@ -360,7 +375,7 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                        "skb",
                        "pci",
                        "memtest",
-                       "serial_tmas",
+                       "serial_kernel",
                        "fish",
                        "angler",
                        "kaluga",
@@ -472,7 +487,9 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
     platform "VExpressEMM-A15" [ "armv7" ]
     ([ ("armv7", f) | f <- vExpressEMMModules_A15 ] ++
      [ ("root", "/armv7_a15ve_image"),
-       ("root", "/armv7_a15ve_image-gdb.gdb") ])
+       ("root", "/armv7_a15ve_image-gdb.gdb"),
+       ("root", "/armv7_a15ve_gem5_image"),
+       ("root", "/armv7_a15ve_gem5_image-gdb.gdb") ])
     "VersatileExpress EMM board with ARM Cortex-A15s under GEM5",
 
     platform "VExpressEMM-A9" [ "armv7" ]
@@ -501,6 +518,10 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
     -- Build the A15 simulation image (VersatileExpress EMM board)
     armv7Image "armv7_a15ve" "ve" "a15ve" "0x80000000" vExpressEMMModules_A15,
 
+    -- Build the A15 simulation image (VersatileExpress EMM board, with GEM5
+    -- quirks)
+    armv7Image "armv7_a15ve_gem5" "ve" "a15ve" "0x80000000" vExpressEMMModules_A15,
+
     -- Build the A9 simulation image (VersatileExpress EMM board)
     armv7Image "armv7_a9ve" "ve" "a15ve" "0x80000000" vExpressEMMModules_A9,
 
@@ -531,6 +552,7 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                      "armv8_qemu",
                      "armv7_a9ve",
                      "armv7_a15ve",
+                     "armv7_a15ve_gem5",
                      "armv7_pandaboard",
                      "armv7_zynq7" ]],
     Rules [ copyFile SrcTree "root" ("/hake/menu.lst." ++ p)
@@ -560,7 +582,7 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
     boot "gem5_armv7_vexpressemm" [ "armv7" ] [
       In SrcTree "tools" "/tools/arm_gem5/boot_gem5.sh",
       Str "VExpress_EMM",
-      In BuildTree "root" "/armv7_a15ve_image" ]
+      In BuildTree "root" "/armv7_a15ve_gem5_image" ]
     "Boot an ARMv7a multicore image on a VersatileExpress EMM board in GEM5",
 
     boot "FVP_VE_A9x1" [ "armv7" ] [
index 03925a8..46dcdf2 100644 (file)
@@ -999,6 +999,24 @@ usage(const char *name) {
          name);
 }
 
+/* Find the first (lowest base address) RAM region. */
+static struct menu_mmap_entry *
+first_ram_region(struct menu_lst *menu) {
+    struct menu_mmap_entry *first= NULL;
+    uint64_t lowest_base= UINT64_MAX;
+
+    for(uint32_t i= 0; i < menu->mmap_len; i++) {
+        struct menu_mmap_entry *e= &menu->mmap[i];
+
+        if(e->type == MULTIBOOT_MEM_TYPE_RAM && e->base < lowest_base) {
+            lowest_base= e->base;
+            first= e;
+        }
+    }
+
+    return first;
+}
+
 int
 main(int argc, char **argv) {
     char pathbuf[PATH_MAX+1];
@@ -1021,15 +1039,16 @@ main(int argc, char **argv) {
     struct menu_lst *menu= read_menu_lst(menu_lst);
 
     /* Check that the requested base address is inside the first RAM region. */
-    if(menu->mmap_len == 0) fail("No MMAP.\n");
-    if(menu->mmap[0].base > (uint64_t)UINT32_MAX)
+    struct menu_mmap_entry *ram_region= first_ram_region(menu);
+    if(!ram_region) fail("No RAM regions defined.\n");
+    if(ram_region->base > (uint64_t)UINT32_MAX)
         fail("This seems to be a 64-bit memory map.\n");
-    if(phys_base < menu->mmap[0].base |
-       phys_base >= menu->mmap[0].base + menu->mmap[0].length) {
+    if(phys_base < ram_region->base |
+       phys_base >= ram_region->base + ram_region->length) {
         fail("Requested base address %08x is outside the first RAM region.\n",
              phys_base);
     }
-    paddr_t ram_start= (paddr_t)menu->mmap[0].base;
+    paddr_t ram_start= (paddr_t)ram_region->base;
     uint32_t kernel_offset= KERNEL_WINDOW - ram_start;
 
     /* Begin allocation at the requested start address. */
@@ -1182,7 +1201,7 @@ main(int argc, char **argv) {
     out_ehdr->e_shoff= get_elf_offset();
 
     size_t total_size= end_of_segment - loadable_segment_offset;
-    if(total_size > menu->mmap[0].length)
+    if(total_size > ram_region->length)
         fail("Overflowed the first RAM region.\n");
 
     out_phdr->p_type=   PT_LOAD;
index d2051f4..f4ebfd8 100644 (file)
@@ -1,5 +1,5 @@
 --------------------------------------------------------------------------
--- Copyright (c) 2007-2009, 2012, ETH Zurich.
+-- Copyright (c) 2007-2009,2012,2016 ETH Zurich.
 -- All rights reserved.
 --
 -- This file is distributed under the terms in the attached LICENSE file.
@@ -11,9 +11,9 @@
 -- 
 --------------------------------------------------------------------------
 
-[ build application { target = "serial",
-                      cFiles = [ "serial.c", "main.c", "basic_service.c",
-                                 "terminal_service.c" ],
+[ build application { target = "serial_pc16550d",
+                      cFiles = [ "serial_pc16550d.c", "main.c",
+                                 "basic_service.c", "terminal_service.c" ],
                       flounderBindings = [ "serial" ],
                       flounderDefs = [ "terminal" , "terminal_config",
                                        "terminal_session" ],
                       addLibraries = [ "pci", "term_server" ],
                       architectures = [ "x86_64", "x86_32" ]
                     },
-  build application { target = "serial",
-                      cFiles = [ "main.c", "basic_service.c",
-                                 "terminal_service.c", "omap44xx_serial.c" ],
+  build application { target = "serial_omap44xx",
+                      cFiles = [ "serial_omap44xx.c", "main.c",
+                                 "basic_service.c", "terminal_service.c" ],
                       flounderBindings = [ "serial" ],
                       flounderDefs = [ "terminal" , "terminal_config",
                                        "terminal_session" ],
                       mackerelDevices = [ "omap/omap44xx_uart3" ],
-                      addLibraries = [ "term_server", "driverkit" ],
+                      addLibraries = [ "driverkit", "term_server" ],
                       architectures = [ "armv7" ]
                     },
-  build application { target = "serial_gem5",
-                      cFiles = [ "main.c", "basic_service.c",
-                                 "terminal_service.c", "serial_gem5.c" ],
+  build application { target = "serial_pl011",
+                      cFiles = [ "serial_pl011.c", "main.c",
+                                 "basic_service.c", "terminal_service.c" ],
                       flounderBindings = [ "serial" ],
                       flounderDefs = [ "terminal" , "terminal_config",
                                        "terminal_session" ],
                       mackerelDevices = [ "pl011_uart" ],
-                      addLibraries = [ "term_server", "driverkit" ],
-                      architectures = [ "armv8" ]
+                      addLibraries = [ "driverkit", "term_server" ],
+                      architectures = [ "armv7", "armv8" ]
                     },
-  build application { target = "serial_tmas",
-                      cFiles = [ "main.c", "basic_service.c",
-                                 "terminal_service.c", "serial_tmas.c" ],
+  build application { target = "serial_kernel",
+                      cFiles = [ "serial_kernel.c", "main.c",
+                                 "basic_service.c", "terminal_service.c" ],
                       flounderBindings = [ "serial" ],
                       flounderDefs = [ "terminal" , "terminal_config",
                                        "terminal_session" ],
-                      mackerelDevices = [ "pl011_uart" ],
                       addLibraries = [ "term_server", "driverkit" ],
-                      architectures = [ "armv8" ]
+                      architectures = [ "x86_32", "x86_64",
+                                        "armv7", "armv8" ]
                     }
-
 ]
index c4a4c90..ad8210c 100644 (file)
@@ -21,9 +21,6 @@
 #include "serial.h"
 #include "serial_debug.h"
 
-#define DEFAULT_PORTBASE            0x3f8   //< COM1 port
-#define DEFAULT_IRQ                 4       //< COM1 IRQ
-
 static char *driver_name = "serial0";       // default driver name
 
 static struct serial_buffer buffer;
@@ -81,26 +78,34 @@ int main(int argc, char *argv[])
 {
     errval_t err;
 
-    uint16_t portbase = DEFAULT_PORTBASE;
-    uint8_t irq = DEFAULT_IRQ;
+    struct serial_params params = {
+        .portbase       = SERIAL_PORTBASE_INVALID,
+        .irq            = SERIAL_IRQ_INVALID,
+        .membase        = SERIAL_MEMBASE_INVALID,
+    };
 
     // Parse args
     for (int i = 1; i < argc; i++) {
         if (strncmp(argv[i], "portbase=", sizeof("portbase=") - 1) == 0) {
-            unsigned long x = strtoul(argv[i] + sizeof("portbase=") - 1, NULL,
-                                      0);
+            uint32_t x=
+                strtoul(argv[i] + sizeof("portbase=") - 1, NULL, 0);
             if (x == 0 || x > 65535) {
-                fprintf(stderr, "Error: invalid portbase 0x%lx\n", x);
+                fprintf(stderr, "Error: invalid portbase 0x%"PRIx32"\n", x);
                 goto usage;
             }
-            portbase = (uint16_t) x;
+            params.portbase = x;
         } else if (strncmp(argv[i], "irq=", sizeof("irq=") - 1) == 0) {
-             unsigned long x = strtoul(argv[i] + sizeof("irq=") - 1, NULL, 0);
-             if (irq == 0) {
-                fprintf(stderr, "Error: invalid IRQ %lu\n", x);
+             uint32_t x=
+                 strtoul(argv[i] + sizeof("irq=") - 1, NULL, 0);
+             if (x == 0) {
+                fprintf(stderr, "Error: invalid IRQ %"PRIu32"\n", x);
                 goto usage;
             }
-            irq = (uint8_t) x;
+            params.irq = x;
+        } else if (strncmp(argv[i], "membase=", sizeof("membase=") - 1) == 0) {
+            uint64_t x=
+                strtoull(argv[i] + sizeof("membase=") - 1, NULL, 0);
+            params.membase = x;
         } else if (strncmp(argv[i], "name=", sizeof("name=") - 1) == 0) {
              driver_name = argv[i] + sizeof("name=") - 1;
         } else if (strncmp(argv[i], "auto", 4) == 0) {
@@ -111,19 +116,14 @@ int main(int argc, char *argv[])
         }
     }
 
-    if (argc > 1) {
-        printf("%s: using port base 0x%x and IRQ %d. Using name '%s'.\n",
-               argv[0], portbase, irq, driver_name);
-    }
-
     // Initialize serial driver
-    err = serial_init(portbase, irq);
+    err = serial_init(&params);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "Error initializing serial driver.");
     }
 
-    SERIAL_DEBUG("Serial driver initialized at port base 0x%x, IRQ %d. "
-                 "Using driver name %s.\n", portbase, irq, driver_name);
+    SERIAL_DEBUG("Serial driver initialized.\n"
+                 "Using driver name %s.\n", driver_name);
 
     // Stick around waiting for input
     struct waitset *ws = get_default_waitset();
@@ -137,6 +137,7 @@ int main(int argc, char *argv[])
     return EXIT_SUCCESS;
 
 usage:
-    fprintf(stderr, "Usage: %s [portbase=PORT] [irq=IRQ] [name=NAME]\n", argv[0]);
+    fprintf(stderr, "Usage: %s [portbase=PORT] [irq=IRQ] [name=NAME]\n"
+                    "    [membase=ADDR] [kernel]\n", argv[0]);
     return 1;
 }
index 63b87da..f6476bc 100644 (file)
@@ -23,10 +23,20 @@ struct serial_buffer {
     size_t len;
 };
 
+#define SERIAL_PORTBASE_INVALID 0xffffffff
+#define SERIAL_IRQ_INVALID      0xffffffff
+#define SERIAL_MEMBASE_INVALID  0xffffffffffffffffULL
+
+struct serial_params {
+    uint32_t portbase;
+    uint32_t irq;
+    uint64_t membase;
+};
+
 typedef void serial_input_fn_t(char *data, size_t length);
 
 void serial_write(char *c, size_t len);
-errval_t serial_init(uint16_t portbase, uint8_t irq);
+errval_t serial_init(struct serial_params *params);
 void start_service(void);
 void start_basic_service(char *driver_name);
 void start_terminal_service(char *driver_name);
index 158f1c3..e758854 100644 (file)
@@ -16,6 +16,8 @@
  * Debug printer:
  *****************************************************************/
 
+#define SERIAL_DRIVER_DEBUG
+
 #if defined(SERIAL_DRIVER_DEBUG) || defined(GLOBAL_DEBUG)
 #define SERIAL_DEBUG(arg...) debug_printf(arg)
 #else
diff --git a/usr/drivers/serial/serial_gem5.c b/usr/drivers/serial/serial_gem5.c
deleted file mode 100644 (file)
index 4319b5b..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/**
- * \file
- * \brief Serial port driver.
- */
-
-/*
- * Copyright (c) 2007, 2008, 2010, 2011, 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, Universitaetstr. 6, CH-8092 Zurich,
- * Attn: Systems Group.
- */
-
-#include <barrelfish/barrelfish.h>
-#include <pci/pci.h>
-#include <barrelfish/inthandler.h>
-#include <driverkit/driverkit.h>
-#include "serial.h"
-#include <dev/pl011_uart_dev.h>
-
-static struct pl011_uart_t uart;
-//static uint16_t portbase;
-
-#define INTERRUPTS_MASK                0x0070
-
-#define NUM_PORTS 2
-unsigned serial_console_port = 0;
-unsigned serial_debug_port = 0;
-const unsigned serial_num_physical_ports = NUM_PORTS;
-
-
-#define UART0_VBASE            0x1c090000
-#define UART0_SECTION_OFFSET   0x90000
-
-#define UART_DEVICE_BYTES      0x4c
-#define UART_MAPPING_DIFF      0x1000
-
-static void serial_poll(void)
-{
-    // Read as many characters as possible from FIFO
-    while (pl011_uart_FR_rd(&uart).rxfe == 1)
-        ;
-
-    char c = (char) pl011_uart_DR_rd(&uart).data;
-
-    serial_input(&c, 1);
-}
-
-static void serial_interrupt(void *arg)
-{
-    //pc16550d_iir_t iir = pc16550d_iir_rd(&uart);
-
-    // Assert no error happened
-    //assert(pc16550d_iir_iid_extract(iir) != pc16550d_rls
-    //       && pc16550d_iir_iid_extract(iir) != pc16550d_ms);
-
-    // Read serial port just like with polling
-    serial_poll();
-}
-
-static void real_init(lvaddr_t base)
-{
-    pl011_uart_LCR_H_t lcr = {
-        .brk = 0, .pen = 0, .eps  = 0, .stp2 = 0, .fen  = 1,
-        .wlen = pl011_uart_bits8, .sps  = 0
-    };
-
-    pl011_uart_initialize(&uart, (mackerel_addr_t) base);
-
-    // Mask all interrupts
-    // gem5 implementation of pl011 only supports
-    // RXIM, TXIM, RTIM interrupts, so we only mask them
-    pl011_uart_IMSC_wr_raw(&uart, INTERRUPTS_MASK);
-
-    // Configure port to 38400 baud, 8 data, no parity, 1 stop (8-N-1)
-    //
-    // (This is a mild scam as system is running in QEMU)
-    //
-    // Note baud rate changes not committed in h/w until lcr_h written.
-
-    pl011_uart_IBRD_wr_raw(&uart, 0xc);     // Assuming UARTCLK is 7.3728MHz
-    pl011_uart_FBRD_wr_raw(&uart, 0);
-
-    pl011_uart_LCR_H_wr(&uart, lcr);
-
-    // offer service now we're up
-    //start_service();
-}
-
-errval_t serial_init(uint16_t lportbase, uint8_t irq)
-{
-
-       lportbase = 0;
-
-    if (lportbase < NUM_PORTS) {
-
-           // XXX: TODO: figure this out --> kaluga magic?
-       errval_t err;
-           lvaddr_t base;
-       err = map_device_register(UART0_VBASE + lportbase*UART_MAPPING_DIFF, UART_DEVICE_BYTES, &base);
-           if (err_is_fail(err)) {
-           USER_PANIC_ERR(err, "map_device_register failed\n");
-               return err;
-           }
-
-       assert(base);
-
-        //real_init(base + UART0_SECTION_OFFSET + lportbase*UART_MAPPING_DIFF);
-               real_init(base + lportbase*UART_MAPPING_DIFF);
-
-       // register interrupt
-           uint16_t *pb = malloc(sizeof(uint16_t));
-       *pb = lportbase;
-           err = inthandler_setup_arm(serial_interrupt, pb, 44);
-       if (err_is_fail(err)) {
-               USER_PANIC_ERR(err, "interrupt setup failed.");
-           }
-
-       // offer service now we're up
-           start_service();
-       return SYS_ERR_OK;
-               
-    } else {
-        return SYS_ERR_SERIAL_PORT_INVALID;
-    }
-
-}
-
-static void serial_putc(char c)
-{
-    pl011_uart_DR_un dr_un;
-
-    while (pl011_uart_FR_rd(&uart).txff == 1)
-        ;
-
-    dr_un.raw  = 0;
-    dr_un.val.data = (uint8_t)c;
-    pl011_uart_DR_wr(&uart, dr_un.val);
-}
-
-void serial_write(char *c, size_t len)
-{
-    for (int i = 0; i < len; i++) {
-        serial_putc(c[i]);
-    }
-}
diff --git a/usr/drivers/serial/serial_kernel.c b/usr/drivers/serial/serial_kernel.c
new file mode 100644 (file)
index 0000000..ab59c0a
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * \file
+ * \brief Serial port driver.
+ */
+
+/*
+ * Copyright (c) 2007, 2008, 2010, 2011, 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, Universitaetstr. 6, CH-8092 Zurich,
+ * Attn: Systems Group.
+ */
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/inthandler.h>
+#include <driverkit/driverkit.h>
+#include "serial.h"
+
+static void
+serial_interrupt(void *arg) {
+    char c;
+    errval_t err= sys_getchar(&c);
+    assert(err_is_ok(err));
+
+    //printf("'%c'\n", c);
+
+    serial_input(&c, 1);
+}
+
+errval_t serial_init(struct serial_params *params)
+{
+    errval_t err;
+
+    if(params->irq == SERIAL_IRQ_INVALID)
+        USER_PANIC("serial_kernel requires an irq= parameter");
+
+    /* Register interrupt handler. */
+    err = inthandler_setup_arm(serial_interrupt, NULL, params->irq);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "interrupt setup failed.");
+    }
+
+    // offer service now we're up
+    start_service();
+    return SYS_ERR_OK;
+}
+
+
+void serial_write(char *c, size_t len)
+{
+    sys_print(c, len);
+}
similarity index 77%
rename from usr/drivers/serial/omap44xx_serial.c
rename to usr/drivers/serial/serial_omap44xx.c
index 7269b99..75ad184 100644 (file)
@@ -7,36 +7,12 @@
 #include <arch/arm/omap44xx/device_registers.h>
 #include <omap44xx_map.h>
 
-//
-// Serial console and debugger interfaces
-//
-#define NUM_PORTS 4
-
+/* XXX */
 #define UART_IRQ (32+74)
 
+#define DEFAULT_MEMBASE OMAP44XX_MAP_L4_PER_UART3
 
-unsigned int serial_console_port = 2;
-unsigned int serial_debug_port = 2;
-unsigned const int serial_num_physical_ports = NUM_PORTS;
-
-
-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
-};
-
-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 omap44xx_uart3_t ports[NUM_PORTS];
-static bool uart_initialized[NUM_PORTS];
+static omap44xx_uart3_t port;
 
 static void serial_poll(omap44xx_uart3_t *uart)
 {
@@ -49,25 +25,19 @@ static void serial_poll(omap44xx_uart3_t *uart)
 
 static void serial_interrupt(void *arg)
 {
-    // We better be initialized!
-    assert(uart_initialized[serial_console_port]);
-    // XXX: this is probably not correct for all ports!
-    uint16_t port = *(uint16_t*)arg;
-    omap44xx_uart3_t *uart = &ports[port];
-
     // get type
-    omap44xx_uart3_iir_t iir =
-        omap44xx_uart3_iir_rd(uart);
+    omap44xx_uart3_iir_t iir= omap44xx_uart3_iir_rd(&port);
 
     if (omap44xx_uart3_iir_it_pending_extract(iir) == 0) {
-        omap44xx_uart3_it_type_status_t it_type = omap44xx_uart3_iir_it_type_extract(iir);
+        omap44xx_uart3_it_type_status_t it_type=
+            omap44xx_uart3_iir_it_type_extract(iir);
         switch(it_type) {
             case omap44xx_uart3_it_modem:
-                (void) omap44xx_uart3_msr_rd(uart);
+                omap44xx_uart3_msr_rd(&port);
                 break;
             case omap44xx_uart3_it_rxtimeout:
             case omap44xx_uart3_it_rhr:
-                serial_poll(uart);
+                serial_poll(&port);
                 break;
             default:
                 debug_printf("serial_interrupt: unhandled irq: %d\n", it_type);
@@ -76,7 +46,6 @@ static void serial_interrupt(void *arg)
     }
 }
 
-
 static bool convert_rx_simple(uint8_t *trig)
 {
     switch(*trig) {
@@ -96,6 +65,7 @@ static bool convert_rx_simple(uint8_t *trig)
             return false;
     }
 }
+
 static bool convert_tx_simple(uint8_t *trig)
 {
     switch(*trig) {
@@ -226,20 +196,12 @@ static void omap44xx_uart3_init(omap44xx_uart3_t *uart, lvaddr_t base)
 }
 
 
-static errval_t real_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;
-    }
-
+static
+errval_t real_init(uint32_t membase) {
     // XXX: TODO: figure this out --> kaluga magic?
     errval_t err;
     lvaddr_t vbase;
-    err = map_device_register(uart_base[port], uart_size[port], &vbase);
+    err = map_device_register(membase, BASE_PAGE_SIZE, &vbase);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "map_device_register failed\n");
         return err;
@@ -249,31 +211,30 @@ static errval_t real_init(unsigned port)
     // paging_map_device returns an address pointing to the beginning of
     // a section, need to add the offset for within the section again
     debug_printf("omap serial_init base = 0x%"PRIxLVADDR"\n", vbase);
-    omap44xx_uart3_init(&ports[port], vbase);
-    uart_initialized[port] = true;
+    omap44xx_uart3_init(&port, vbase);
     debug_printf("omap serial_init[%d]: done.\n", port);
     return SYS_ERR_OK;
 }
 
-errval_t serial_init(uint16_t portbase, uint8_t irq)
+errval_t serial_init(struct serial_params *params)
 {
-    // ARM: we ignore the irq argument and use the portbase as UART port
-    // number.
-    if (portbase > NUM_PORTS) {
-        debug_printf("don't have serial port #%d... exiting\n", portbase);
-        return SYS_ERR_SERIAL_PORT_INVALID;
-    }
+    uint32_t membase= DEFAULT_MEMBASE;
+    if(params->membase != SERIAL_MEMBASE_INVALID)
+        membase= (uint32_t)params->membase;
+
+    uint8_t irq= UART_IRQ;
+    if(params->irq != SERIAL_IRQ_INVALID)
+        irq= params->irq;
+
     // initialize hardware
-    errval_t err = real_init(portbase);
+    errval_t err = real_init(membase);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "serial_init failed\n");
         return -1;
     }
 
     // register interrupt
-    uint16_t *pb = malloc(sizeof(uint16_t));
-    *pb = portbase;
-    err = inthandler_setup_arm(serial_interrupt, pb, UART_IRQ);
+    err = inthandler_setup_arm(serial_interrupt, NULL, irq);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "interrupt setup failed.");
     }
@@ -284,22 +245,18 @@ errval_t serial_init(uint16_t portbase, uint8_t irq)
 }
 
 /** output a single character */
-static void serial_putchar(unsigned port, char c)
+static void serial_putchar(char c)
 {
-    assert(port <= NUM_PORTS);
-    omap44xx_uart3_t *uart = &ports[port];
-
     // Wait until FIFO can hold more characters
-    while (!omap44xx_uart3_lsr_tx_fifo_e_rdf(uart));
+    while (!omap44xx_uart3_lsr_tx_fifo_e_rdf(&port));
     // Write character
-    omap44xx_uart3_thr_thr_wrf(uart, c);
+    omap44xx_uart3_thr_thr_wrf(&port, c);
 }
 
 /** write string to serial port */
 void serial_write(char *c, size_t len)
 {
     for (int i = 0; i < len; i++) {
-        serial_putchar(serial_console_port, c[i]);
+        serial_putchar(c[i]);
     }
 }
-
similarity index 86%
rename from usr/drivers/serial/serial.c
rename to usr/drivers/serial/serial_pc16550d.c
index 6c870c0..c3bd7a2 100644 (file)
@@ -18,6 +18,9 @@
 #include "serial.h"
 #include <dev/pc16550d_dev.h>
 
+#define DEFAULT_PORTBASE            0x3f8   //< COM1 port
+#define DEFAULT_IRQ                 4       //< COM1 IRQ
+
 static struct pc16550d_t uart;
 static uint16_t portbase;
 
@@ -80,7 +83,7 @@ static void real_init(void)
     start_service();
 }
 
-errval_t serial_init(uint16_t portbase_arg, uint8_t irq)
+errval_t serial_init(struct serial_params *params)
 {
     errval_t err;
 
@@ -89,7 +92,15 @@ errval_t serial_init(uint16_t portbase_arg, uint8_t irq)
         return err;
     }
 
-    portbase = portbase_arg;
+    portbase= DEFAULT_PORTBASE;
+    if(params->portbase != SERIAL_PORTBASE_INVALID)
+        portbase= params->portbase;
+
+    uint8_t irq= DEFAULT_IRQ;
+    if(params->irq != SERIAL_IRQ_INVALID)
+        irq= params->irq;
+
+    printf("Using port base 0x%x and IRQ %d.\n", portbase, irq);
 
     return pci_register_legacy_driver_irq(real_init, portbase, portbase+8,
                                           irq, serial_interrupt, NULL);
diff --git a/usr/drivers/serial/serial_pl011.c b/usr/drivers/serial/serial_pl011.c
new file mode 100644 (file)
index 0000000..19a149e
--- /dev/null
@@ -0,0 +1,128 @@
+/**
+ * \file
+ * \brief Serial port driver.
+ */
+
+/*
+ * Copyright (c) 2007-2016 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, Universitaetstr. 6, CH-8092 Zurich,
+ * Attn: Systems Group.
+ */
+
+#include <barrelfish/barrelfish.h>
+#include <pci/pci.h>
+#include <barrelfish/inthandler.h>
+#include <driverkit/driverkit.h>
+#include <dev/pl011_uart_dev.h>
+
+#include "serial.h"
+
+static struct pl011_uart_t uart;
+
+/* Versatile express UART1. */
+#define DEFAULT_IRQ 38
+#define DEFAULT_MEMBASE 0x1c0a0000
+
+static void
+serial_interrupt(void *arg) {
+    /* Read as many characters as possible. */
+    while(pl011_uart_FR_rxfe_rdf(&uart) == 0) {
+        char c= (char)pl011_uart_DR_rd(&uart);
+
+        serial_input(&c, 1);
+    }
+}
+
+errval_t
+serial_init(struct serial_params *params) {
+    uint32_t membase= DEFAULT_MEMBASE;
+    if(params->membase != SERIAL_MEMBASE_INVALID)
+        membase= (uint32_t)params->membase;
+
+    uint8_t irq= DEFAULT_IRQ;
+    if(params->irq != SERIAL_IRQ_INVALID)
+        irq= params->irq;
+
+    // XXX: TODO: figure this out --> kaluga magic?
+    errval_t err;
+    lvaddr_t base;
+    printf("serial: mapping device at PA %"PRIx32"\n", (uint32_t)membase);
+    err= map_device_register(membase, BASE_PAGE_SIZE, &base);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "map_device_register failed\n");
+        return err;
+    }
+
+    pl011_uart_initialize(&uart, (mackerel_addr_t) base);
+
+       /* Mask all interrupts: set all bits to zero. */
+       pl011_uart_IMSC_rawwr(&uart, 0);
+
+    /* Register interrupt handler. */
+    err = inthandler_setup_arm(serial_interrupt, NULL, irq);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "interrupt setup failed.");
+    }
+
+    /* Disable the UART before reconfiguring it. */
+       pl011_uart_CR_uarten_wrf(&uart, 0);
+
+    /* Clear and enable the receive interrupt. */
+    pl011_uart_ICR_rxic_wrf(&uart, 1);
+    pl011_uart_IMSC_rxim_wrf(&uart, 1);
+       
+       // Configure port to 38400 baud, 8 data, no parity, 1 stop (8-N-1)
+       //
+       // (This is a mild scam as system is running in QEMU)
+       //
+       // Note baud rate changes not committed in h/w until lcr_h
+       // written.
+       pl011_uart_IBRD_divint_wrf(&uart, 0xc); // Assuming UARTCLK is 7.3728MHz
+       pl011_uart_FBRD_divfrac_wrf(&uart, 0);
+       
+       /* Configure the line control register. */
+       pl011_uart_LCR_H_t lcr= (pl011_uart_LCR_H_t)0;
+    /* Disable FIFOs.  There's no way to get an interrupt when a single
+     * character arrives with FIFOs, so it's useless as a console. */
+       lcr= pl011_uart_LCR_H_fen_insert(lcr, 0);
+    /* Eight data bits. */
+       lcr= pl011_uart_LCR_H_wlen_insert(lcr, pl011_uart_bits8);
+    /* No parity. */
+       lcr= pl011_uart_LCR_H_pen_insert(lcr, 0);
+    /* One stop bit. */
+       lcr= pl011_uart_LCR_H_stp2_insert(lcr, 0);
+       pl011_uart_LCR_H_wr(&uart, lcr);
+
+    /* Configure the main control register. */
+       pl011_uart_CR_t cr = (pl011_uart_CR_t)0;
+    /* No flow control. */
+       cr= pl011_uart_CR_ctsen_insert(cr, 0);
+       cr= pl011_uart_CR_rtsen_insert(cr, 0);
+    /* Enable transmit and receive. */
+       cr= pl011_uart_CR_txe_insert(cr, 1);
+       cr= pl011_uart_CR_rxe_insert(cr, 1);
+    /* Enable UART. */
+       cr= pl011_uart_CR_uarten_insert(cr, 1);
+       pl011_uart_CR_wr(&uart, cr);
+
+    /* Offer service now we're up. */
+    start_service();
+    return SYS_ERR_OK;
+}
+
+static void
+serial_putc(char c) {
+    while(pl011_uart_FR_txff_rdf(&uart) == 1);
+    pl011_uart_DR_rawwr(&uart, c);
+}
+
+void
+serial_write(char *c, size_t len) {
+    for (int i = 0; i < len; i++) {
+        serial_putc(c[i]);
+    }
+}
diff --git a/usr/drivers/serial/serial_tmas.c b/usr/drivers/serial/serial_tmas.c
deleted file mode 100644 (file)
index 753dc26..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * \file
- * \brief Serial port driver.
- */
-
-/*
- * Copyright (c) 2007, 2008, 2010, 2011, 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, Universitaetstr. 6, CH-8092 Zurich,
- * Attn: Systems Group.
- */
-
-#include <barrelfish/barrelfish.h>
-#include <pci/pci.h>
-#include <barrelfish/inthandler.h>
-#include <driverkit/driverkit.h>
-#include "serial.h"
-#include <dev/pl011_uart_dev.h>
-
-errval_t serial_init(uint16_t lportbase, uint8_t irq)
-{
-    // offer service now we're up
-    start_service();
-    return SYS_ERR_OK;
-}
-
-
-void serial_write(char *c, size_t len)
-{
-    debug_printf("%.*s", len, c);
-}
index b7fa35c..89d6173 100644 (file)
@@ -1369,7 +1369,6 @@ int main(int argc, const char *argv[])
     term_client_blocking_config(&ts->client, TerminalConfig_CTRLC, false);
     linenoiseHistorySetMaxLen(1024);
     for (;;) {
-
         char* input = NULL;
         int cmd_argc;
         char *cmd_argv[64]; // Support a max of 64 cmd args
index 2d8e6e1..109a6c1 100644 (file)
@@ -38,7 +38,7 @@ let commonCFiles = [ "boot_modules.c",
                                                "trace" ],
                       architectures = [ "k1om" ] },
   build application { target = "kaluga",
-                      cFiles = commonCFiles ++ [ "armv7.c", "omap_startup.c" ],
+                      cFiles = commonCFiles ++ [ "armv7.c", "armv7_startup.c" ],
                       flounderDefs = [ "monitor" ],
                       flounderBindings = [ "octopus" ],
                       flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
index 23331de..39add62 100644 (file)
@@ -92,9 +92,9 @@ static errval_t vexpress_startup(void)
     err = oct_set("all_spawnds_up { iref: 0 }");
     assert(err_is_ok(err));
 
-    struct module_info* mi = find_module("serial");
+    struct module_info* mi = find_module("serial_pl011");
     if (mi != NULL) {
-        err = mi->start_function(0, mi, "hw.arm.gem5.uart {}");
+        err = mi->start_function(0, mi, "hw.arm.vexpress.uart {}");
         assert(err_is_ok(err));
     }
     return SYS_ERR_OK;
similarity index 74%
rename from usr/kaluga/omap_startup.c
rename to usr/kaluga/armv7_startup.c
index 50d8632..6fe51f9 100644 (file)
 
 #include <barrelfish/barrelfish.h>
 #include <barrelfish/spawn_client.h>
+#include <barrelfish_kpi/platform.h>
+#include <if/monitor_blocking_rpcclient_defs.h>
 
 #include <arch/arm/omap44xx/device_registers.h>
 #include <omap44xx_map.h>
+#include <vexpress_map.h>
 
 #include "kaluga.h"
 
@@ -93,7 +96,7 @@ static struct allowed_registers prcm = {
     }
 };
 
-static struct allowed_registers uart = {
+static struct allowed_registers omap_uart = {
     .binary = "hw.arm.omap44xx.uart",
     .registers =
     {
@@ -114,29 +117,68 @@ static struct allowed_registers sdma = {
     }
 };
 
-static struct allowed_registers* omap44xx[10] = {
+static struct allowed_registers* omap44xx[] = {
     &usb,
     &fdif,
     &mmchs,
     &prcm,
-    &uart,
+    &omap_uart,
     &sdma,
     NULL,
 };
 
+static struct allowed_registers vexpress_uart = {
+    .binary = "hw.arm.vexpress.uart",
+    .registers =
+    {
+        {VEXPRESS_MAP_UART0, VEXPRESS_MAP_UART0_SIZE},
+        {VEXPRESS_MAP_UART1, VEXPRESS_MAP_UART1_SIZE},
+        {VEXPRESS_MAP_UART2, VEXPRESS_MAP_UART2_SIZE},
+        {VEXPRESS_MAP_UART3, VEXPRESS_MAP_UART3_SIZE},
+        {0x0, 0x0}
+    }
+};
+
+static struct allowed_registers* vexpress[] = {
+    &vexpress_uart,
+    NULL,
+};
+
 /**
- * \brief Startup function for OMAP drivers.
+ * \brief Startup function for ARMv7 drivers.
  *
  * Makes sure we get the device register capabilities.
  */
-errval_t default_start_function(coreid_t where, struct module_info* driver,
-        char* record)
-{
+errval_t
+default_start_function(coreid_t where, struct module_info* driver,
+                       char* record) {
     assert(driver != NULL);
     assert(record != NULL);
 
     errval_t err;
 
+    struct monitor_blocking_rpc_client *m=
+        get_monitor_blocking_rpc_client();
+    assert(m != NULL);
+
+    uint32_t arch, platform;
+    err = m->vtbl.get_platform(m, &arch, &platform);
+    assert(err_is_ok(err));
+    assert(arch == PI_ARCH_ARMV7A);
+
+    struct allowed_registers **regs= NULL;
+    switch(platform) {
+        case PI_PLATFORM_OMAP44XX:
+            regs= omap44xx;
+            break;
+        case PI_PLATFORM_VEXPRESS:
+            regs= vexpress;
+            break;
+        default:
+            printf("Unrecognised ARMv7 platform\n");
+            abort();
+    }
+
     // TODO Request the right set of caps and put in device_range_cap
     struct cnoderef dev_cnode;
     struct capref dev_cnode_cap;
@@ -152,25 +194,27 @@ errval_t default_start_function(coreid_t where, struct module_info* driver,
     err = oct_read(record, "%s", &name);
     assert(err_is_ok(err));
     KALUGA_DEBUG("%s:%d: Starting driver for %s\n", __FUNCTION__, __LINE__, name);
-    for (size_t i=0; omap44xx[i] != NULL; i++) {
+    for (size_t i=0; regs[i] != NULL; i++) {
 
-        if(strcmp(name, omap44xx[i]->binary) != 0) {
+        if(strcmp(name, regs[i]->binary) != 0) {
             continue;
         }
 
         // Get the device cap from the managed capability tree
         // put them all in a single cnode
-        for (size_t j=0; omap44xx[i]->registers[j][0] != 0x0; j++) {
+        for (size_t j=0; regs[i]->registers[j][0] != 0x0; j++) {
             struct capref device_frame;
             KALUGA_DEBUG("%s:%d: mapping 0x%"PRIxLPADDR" %"PRIuLPADDR"\n", __FUNCTION__, __LINE__,
-                   omap44xx[i]->registers[j][0], omap44xx[i]->registers[j][1]);
+                   regs[i]->registers[j][0], regs[i]->registers[j][1]);
 
-            lpaddr_t base = omap44xx[i]->registers[j][0] & ~(BASE_PAGE_SIZE-1);
+            lpaddr_t base = regs[i]->registers[j][0] & ~(BASE_PAGE_SIZE-1);
             err = get_device_cap(base,
-                                 omap44xx[i]->registers[j][1],
+                                 regs[i]->registers[j][1],
                                  &device_frame);
             assert(err_is_ok(err));
 
+            KALUGA_DEBUG("get_device_cap worked\n");
+
             err = cap_copy(device_cap, device_frame);
             assert(err_is_ok(err));
             device_cap.slot++;
index 46fe912..4e6255e 100644 (file)
@@ -15,7 +15,7 @@
 #ifndef KALUGA_DEBUG_H_
 #define KALUGA_DEBUG_H_
 
-//#define KALUGA_SERVICE_DEBUG 1
+#define KALUGA_SERVICE_DEBUG 1
 
 #if defined(KALUGA_SERVICE_DEBUG) || defined(GLOBAL_DEBUG)
 #define KALUGA_DEBUG(x...) debug_printf(x)
index 4d2e34a..2874a1c 100644 (file)
@@ -97,26 +97,24 @@ errval_t init_cap_manager(void)
 
     struct frame_identity ret;
     err = invoke_frame_identify(requested_cap, &ret);
+    size_t capbits= log2ceil(ret.bytes);
     assert (err_is_ok(err));
-    assert((1ULL << log2ceil(ret.bytes)) == ret.bytes);
+    assert((1ULL << capbits) == ret.bytes);
+    
+    printf("IO Cap: %"PRIx64"-%"PRIx64"\n", ret.base, ret.base + (ret.bytes - 1));
+    printf("IO Cap: %"PRIx64" %"PRIx64"\n", ret.base, ret.bytes);
 
-    err = mm_init(&register_manager, ObjType_DevFrame, ret.base, log2ceil(ret.bytes),
-                  1, slab_default_refill, slot_alloc_dynamic, 
+    err = mm_init(&register_manager, ObjType_DevFrame, ret.base, capbits, 1,
+                  slab_default_refill, slot_alloc_dynamic,
                   &devframes_allocator, false);
     if (err_is_fail(err)) {
         return err_push(err, MM_ERR_MM_INIT);
     }
 
-       #ifdef __gem5__
-    // TODO(gz): fix hardcoded values
-    err = mm_add(&register_manager, requested_cap,
-                 28, 0x10000000);
-       #else
-    // TODO(gz): fix hardcoded values
-    err = mm_add(&register_manager, requested_cap,
-                 30, 0x40000000);
-       #endif
-    assert(err_is_ok(err));
+    err= mm_add(&register_manager, requested_cap, capbits, ret.base);
+    if (err_is_fail(err)) {
+        return err_push(err, MM_ERR_MM_INIT);
+    }
  
     KALUGA_DEBUG("init_cap_manager DONE\n");
     return SYS_ERR_OK;