Turn serial driver into module and fix userspace GIC
authorLukas Humbel <lukas.humbel@inf.ethz.ch>
Wed, 20 Feb 2019 13:40:41 +0000 (14:40 +0100)
committerLukas Humbel <lukas.humbel@inf.ethz.ch>
Wed, 20 Feb 2019 13:40:41 +0000 (14:40 +0100)
Signed-off-by: Lukas Humbel <lukas.humbel@inf.ethz.ch>

32 files changed:
hake/menu.lst.armv7_a15a7ve
hake/menu.lst.armv7_a15ve_1
hake/menu.lst.armv7_a15ve_2
hake/menu.lst.armv7_a15ve_4
if/monitor_blocking.if
include/barrelfish/invocations.h
kernel/arch/arm/irq.c
kernel/arch/armv7/syscall.c
kernel/arch/x86_64/irq.c
kernel/arch/x86_64/syscall.c
kernel/include/arch/armv7/irq.h
kernel/include/arch/x86_64/irq.h
lib/int_route/Hakefile
lib/int_route/client/client.c
lib/int_route/server/standalone.c
lib/term/server/server.c
platforms/Hakefile
usr/drivers/domain/Hakefile
usr/drivers/domain/main.c
usr/drivers/pl390_dist/main.c
usr/drivers/serial/Hakefile
usr/drivers/serial/basic_service.c
usr/drivers/serial/main.c
usr/drivers/serial/main_common.c [new file with mode: 0644]
usr/drivers/serial/main_module.c [new file with mode: 0644]
usr/drivers/serial/serial.h
usr/drivers/serial/serial_kernel.c
usr/drivers/serial/terminal_service.c
usr/kaluga/armv7.c
usr/kaluga/driver_startup.c
usr/kaluga/main.c
usr/monitor/monitor_rpc_server.c

index eb25747..4cafa29 100644 (file)
@@ -30,7 +30,7 @@ module /armv7/sbin/startd boot
 # Device drivers
 # module /armv7/sbin/serial_pl011 auto
 module /armv7/sbin/driverdomain auto
-module /armv7/sbin/serial_kernel irq=37
+module /armv7/sbin/driverdomain_pl390 auto
 module /armv7/sbin/corectrl nospawn
 
 # General user domains
index 386cebb..6d63a1a 100644 (file)
@@ -28,9 +28,8 @@ module /armv7/sbin/proc_mgmt boot
 module /armv7/sbin/startd boot
 
 # Device drivers
-# module /armv7/sbin/serial_pl011 auto
 module /armv7/sbin/driverdomain auto
-module /armv7/sbin/serial_kernel irq=37
+module /armv7/sbin/driverdomain_pl390 auto
 module /armv7/sbin/corectrl auto
 
 # General user domains
index 0c916c6..985af37 100644 (file)
@@ -28,9 +28,8 @@ module /armv7/sbin/proc_mgmt boot
 module /armv7/sbin/startd boot
 
 # Device drivers
-# module /armv7/sbin/serial_pl011 auto
 module /armv7/sbin/driverdomain auto
-module /armv7/sbin/serial_kernel irq=37
+module /armv7/sbin/driverdomain_pl390 auto
 module /armv7/sbin/corectrl auto
 
 # General user domains
index 03f9c85..ae356fa 100644 (file)
@@ -28,9 +28,8 @@ module /armv7/sbin/proc_mgmt boot
 module /armv7/sbin/startd boot
 
 # Device drivers
-# module /armv7/sbin/serial_pl011 auto
 module /armv7/sbin/driverdomain auto
-module /armv7/sbin/serial_kernel irq=37
+module /armv7/sbin/driverdomain_pl390 auto
 module /armv7/sbin/corectrl auto
 
 # General user domains
index 12d94b5..b2f72e9 100644 (file)
@@ -35,9 +35,14 @@ interface monitor_blocking "The monitor to client RPC interface" {
     rpc get_phyaddr_cap(out cap pyaddr, out errval err);
     rpc get_io_cap(out cap io, out errval err);
     
-    // Get a capability that is targeted at the local apic.
+    // Get a irq destination capability that is targeted at the local apic, 
+    // with an unused vector.
     rpc get_irq_dest_cap(out cap io, out errval err);
 
+    // Get a irq destination capability that is connectable with the irq src
+    // capability.
+    rpc get_irq_dest_cap_arm(in cap src, in int irq_idx, out cap io, out errval err);
+
     // Resource control
     rpc rsrc_manifest(in cap dispatcher, in String manifest[2048],
             out rsrcid id, out errval err);
index e0873a1..2d59de3 100644 (file)
@@ -418,12 +418,20 @@ static inline errval_t invoke_irqsrc_get_vec_end(struct capref irqcap, uint64_t
     return ret.error;
 }
 
-static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
+/**
+ * Allocate a free entry in the vector table and return it as dest_cap.
+ * Set vec_hint to a positive value, and the allocator will force 
+ * that vector to be allocated.
+ */
+static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap,
+                                                      struct capref dest_cap,
+                                                      int vec_hint
+                                                      )
 {
     uint8_t dcn_level = get_cnode_level(dest_cap);
     capaddr_t dcn_addr = get_cnode_addr(dest_cap);
-    struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap,
-                                    dcn_level, dcn_addr, dest_cap.slot);
+    struct sysret ret = cap_invoke5(irqcap, IRQTableCmd_AllocDestCap,
+                                    dcn_level, dcn_addr, dest_cap.slot, vec_hint);
     return ret.error;
 }
 
index 46ddf85..d5dc983 100644 (file)
@@ -60,7 +60,7 @@ errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint)
     if (nidt < NDISPATCH) {
         // check that we don't overwrite someone else's handler
         if (irq_dispatch[nidt].cap.type != ObjType_Null) {
-            printf("kernel: installing new handler for IRQ %d\n", nidt);
+            printf("kernel: replacing handler for IRQ %d\n", nidt);
         }
         err = caps_copy_to_cte(&irq_dispatch[nidt], recv, false, 0, 0);
 
@@ -73,6 +73,11 @@ errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint)
     return SYS_ERR_IRQ_INVALID;
 }
 
+errval_t irq_connect(struct capability *irq_dest, capaddr_t endpoint) {
+    assert(irq_dest->type == ObjType_IRQDest);
+    return irq_table_set(irq_dest->u.irqdest.vector, endpoint);
+}
+
 errval_t irq_table_delete(unsigned int nidt)
 {
     if (nidt < NDISPATCH) {
@@ -85,6 +90,36 @@ errval_t irq_table_delete(unsigned int nidt)
     return SYS_ERR_IRQ_INVALID;
 }
 
+errval_t irq_table_alloc_dest_cap(uint8_t dcn_level, capaddr_t dcn,
+                                  capaddr_t out_cap_addr, int vec_hint)
+{
+    errval_t err;
+    if(vec_hint < 0){
+        printk(LOG_WARN, "irq: vec_hint must be provided on ARM\n", vec_hint);
+        return SYS_ERR_IRQ_INVALID;
+    }
+    if(vec_hint >= NDISPATCH){
+        printk(LOG_WARN, "irq: vec_hint invalid\n", vec_hint);
+        return SYS_ERR_IRQ_INVALID;
+    }
+
+    // TODO: Keep track of allocations 
+    struct cte * cn;
+    err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_level,
+                           &cn, CAPRIGHTS_WRITE);
+    if(err_is_fail(err)){
+        return err;
+    }
+
+    struct cte out_cap;
+    memset(&out_cap, 0, sizeof(struct cte));
+    out_cap.cap.type = ObjType_IRQDest;
+    out_cap.cap.u.irqdest.cpu = my_core_id;
+    out_cap.cap.u.irqdest.vector = vec_hint;
+    caps_copy_to_cnode(cn, out_cap_addr, &out_cap, 0, 0, 0);
+    return  SYS_ERR_OK;
+}
+
 errval_t irq_table_notify_domains(struct kcb *kcb)
 {
     uintptr_t msg[] = { 1 };
index 9c2658a..d838f2f 100644 (file)
@@ -840,6 +840,64 @@ INVOCATION_HANDLER(monitor_identify_domains_cap)
     return sys_monitor_identify_cap(root, cptr, level, retbuf);
 }
 
+static struct sysret handle_irqsrc_get_vec_start(struct capability *to,
+        arch_registers_state_t* context,
+        int argc)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irqsrc.vec_start;
+    return ret;
+}
+
+static struct sysret handle_irqsrc_get_vec_end(struct capability *to,
+        arch_registers_state_t* context,
+        int argc)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irqsrc.vec_end;
+    return ret;
+}
+
+static struct sysret handle_irqdest_connect(struct capability* to,
+        arch_registers_state_t* context,
+        int argc)
+
+{
+    struct registers_arm_syscall_args* sa = &context->syscall_args;
+    return SYSRET(irq_connect(to, sa->arg2));
+}
+
+static struct sysret handle_irqdest_get_vector(struct capability *to,
+        arch_registers_state_t* context,
+        int argc)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irqdest.vector;
+    return ret;
+}
+
+static struct sysret handle_irqdest_get_cpu(struct capability *to,
+        arch_registers_state_t* context,
+        int argc)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irqdest.cpu;
+    return ret;
+}
+
+static struct sysret handle_irq_table_alloc_dest_cap(struct capability* to,
+        arch_registers_state_t* context,
+        int argc
+        )
+{
+    struct registers_arm_syscall_args* sa = &context->syscall_args;
+    return SYSRET(irq_table_alloc_dest_cap(sa->arg2, sa->arg3, sa->arg4, sa->arg5));
+}
+
 static struct sysret handle_irq_table_set( struct capability* to,
         arch_registers_state_t* context,
         int argc
@@ -1161,7 +1219,17 @@ static invocation_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [MappingCmd_Destroy] = handle_mapping_destroy,
         [MappingCmd_Modify] = handle_mapping_modify,
     },
+       [ObjType_IRQSrc] = {
+        [IRQSrcCmd_GetVecStart] = handle_irqsrc_get_vec_start,
+        [IRQSrcCmd_GetVecEnd] = handle_irqsrc_get_vec_end
+       },
+       [ObjType_IRQDest] = {
+        [IRQDestCmd_Connect] = handle_irqdest_connect,
+        [IRQDestCmd_GetVector] = handle_irqdest_get_vector,
+        [IRQDestCmd_GetCpu] = handle_irqdest_get_cpu
+       },
     [ObjType_IRQTable] = {
+            [IRQTableCmd_AllocDestCap] = handle_irq_table_alloc_dest_cap,
             [IRQTableCmd_Set] = handle_irq_table_set,
             [IRQTableCmd_Delete] = handle_irq_table_delete,
         },
index 8f5ceaf..bead261 100644 (file)
@@ -512,10 +512,16 @@ errval_t irq_table_alloc(int *outvec)
     }
 }
 
-errval_t irq_table_alloc_dest_cap(uint8_t dcn_level, capaddr_t dcn, capaddr_t out_cap_addr)
+errval_t irq_table_alloc_dest_cap(uint8_t dcn_level, capaddr_t dcn,
+                                  capaddr_t out_cap_addr, int vec_hint)
 {
     errval_t err;
 
+    if(vec_hint >= 0){
+        printk(LOG_WARN, "irq: vec_hint not supported on x86\n", i);
+        return SYS_ERR_IRQ_INVALID;
+    }
+
     int i;
     bool i_usable = false;
     for (i = NEXCEPTIONS+1; i < NDISPATCH; i++) {
index 80f2a2a..416b9a6 100644 (file)
@@ -919,7 +919,7 @@ static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
 static struct sysret handle_irq_table_alloc_dest_cap(struct capability *to, int cmd,
                                             uintptr_t *args)
 {
-    return SYSRET(irq_table_alloc_dest_cap(args[0],args[1],args[2]));
+    return SYSRET(irq_table_alloc_dest_cap(args[0],args[1],args[2], args[3]));
 }
 
 
index 7f56011..1843e57 100644 (file)
 
 struct capability;
 struct idc_recv_msg;
-//struct sysret irq_table_set(struct capability *to, struct idc_recv_msg *msg);
-//struct sysret irq_table_delete(struct capability *to, struct idc_recv_msg *msg);
 errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint);
+errval_t irq_connect(struct capability *irq_dest, capaddr_t endpoint);
 errval_t irq_table_delete(unsigned int nidt);
+errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn,
+        capaddr_t out_cap_addr, int vec_hint);
 struct kcb;
 errval_t irq_table_notify_domains(struct kcb *kcb);
 void send_user_interrupt(int irq);
index ab2c53a..a2da697 100644 (file)
@@ -165,6 +165,6 @@ errval_t irq_table_delete(unsigned int nidt);
 struct kcb;
 errval_t irq_table_notify_domains(struct kcb *kcb);
 errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn,
-        capaddr_t out_cap_addr);
+        capaddr_t out_cap_addr, int vec_hint);
 
 #endif
index 395ef97..00af569 100644 (file)
     -- We run a stand alone IRS on ARMv7
     build application { target = "int_route",
                     cFiles = [ "server/standalone.c" ],
-                    flounderDefs = [ "int_route_service" ],
+                    flounderDefs = [ "int_route_service", "monitor_blocking" ],
                     flounderBindings = [ "int_route_service", "int_route_controller" ],
-                    flounderExtraBindings = [ ("int_route_service", ["rpcclient"]) ],
+                    flounderExtraBindings = [ ("int_route_service", ["rpcclient"]),
+                                              ("monitor_blocking", ["rpcclient"]) ],
                     architectures = ["armv7"]
                    }
 ]
index a255492..fd5c89a 100644 (file)
@@ -57,6 +57,7 @@ errval_t int_route_client_route(struct capref intsrc, int irq_idx,
     return err;
 }
 
+__attribute__((used))
 static errval_t alloc_dest_irq_cap(struct capref *retcap)
 {
     errval_t err, msgerr;
@@ -74,6 +75,27 @@ static errval_t alloc_dest_irq_cap(struct capref *retcap)
     }
 }
 
+/**
+ * Get IRQ 
+ */
+__attribute__((used))
+static errval_t alloc_dest_irq_cap_arm(struct capref irq_src, int irq_idx, struct capref *retcap)
+{
+    errval_t err, msgerr;
+
+    struct monitor_blocking_binding *r = get_monitor_blocking_binding();
+    err = slot_alloc(retcap);
+    if (err_is_fail(err)) {
+        return err;
+    }
+    err = r->rpc_tx_vtbl.get_irq_dest_cap_arm(r, irq_src, irq_idx, retcap, &msgerr);
+    if (err_is_fail(err)){
+        return err;
+    } else {
+        return msgerr;
+    }
+}
+
 struct irq_handler_arg { 
     struct lmp_endpoint *ep;
     struct event_closure uc;
@@ -105,7 +127,11 @@ errval_t int_route_client_route_and_connect(struct capref intsrc, int irq_idx,
 
     /* allocate irq dest cap */
     struct capref irq_dest_cap;
+#ifdef __arm__
+    err = alloc_dest_irq_cap_arm(intsrc, irq_idx, &irq_dest_cap);
+#else
     err = alloc_dest_irq_cap(&irq_dest_cap);
+#endif
     if(err_is_fail(err)){
         DEBUG_ERR(err, "alloc_dest_irq_cap");
         return err;
index 5966f57..079235b 100644 (file)
@@ -149,10 +149,9 @@ static void driver_route_call_armv7(struct int_route_service_binding *b,
         err = int_route_controller_add_mapping__tx(gic_dist->binding,
                 BLOCKING_CONT, NULL, class, in_msg,
                 out_msg);
-        assert(err_is_ok(err));
     }
 
-    b->tx_vtbl.route_response(b, NOP_CONT, SYS_ERR_IRQ_INVALID);
+    b->tx_vtbl.route_response(b, NOP_CONT, err);
 }
 
 static void ctrl_register_controller(struct int_route_controller_binding *_binding,
index 8b143f7..cd6571d 100644 (file)
@@ -370,7 +370,8 @@ static void check_first_client_connected(struct term_server *server)
         return;
     }
 
-    TERM_DEBUG("First client successfully connected to terminal server.\n");
+    TERM_DEBUG("First client successfully connected to terminal server."
+            "server=%p, server->st=%p\n", server, server->st);
 
     /* new session callback */
     server->new_session_cb(server->st, server->session_id);
index 0f1a4ab..9d06212 100644 (file)
@@ -284,10 +284,10 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                         "usb_manager",
                         "usb_keyboard",
                         "serial_omap44xx",
-                        "serial_kernel",
                         "angler",
                         "corectrl",
                         "driverdomain",
+                        "driverdomain_pl390",
                         "int_route"
                         ] ]
 
@@ -300,8 +300,6 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                                "monitor",
                                "proc_mgmt",
                                "ramfsd",
-                               "serial_pl011",
-                               "serial_kernel",
                                "spawnd",
                                "startd",
                                "corectrl",
@@ -310,6 +308,7 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                                "fish",
                                "memtest",
                                "driverdomain",
+                               "driverdomain_pl390",
                                "int_route"
                                ] ]
 
@@ -322,7 +321,6 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                               "monitor",
                               "proc_mgmt",
                               "ramfsd",
-                              "serial_pl011",
                               "serial_kernel",
                               "spawnd",
                               "startd",
index cd5c171..82f0593 100644 (file)
     target = "driverdomain",
     cFiles = [ "main.c"],
     addLinkFlags = ["-T" ++ Config.source_dir ++ "/lib/driverkit/bfdrivers.ld" ],
-    addLibraries = libDeps [ "driverkit", "thc" ],
+    addLibraries = libDeps [ "driverkit", "thc", "term_server", "int_route_client" ],
     addModules = ["fdif_module", "sdma_module", "cm2_module", "twl6030_module",
-                  "mmchs_module", "pl390_dist_module"],
+                  "mmchs_module", "serial_kernel_module"],
+    architectures = ["armv7"]
+  },
+
+  build application {
+    target = "driverdomain_pl390",
+    cFiles = [ "main.c"],
+    addLinkFlags = ["-T" ++ Config.source_dir ++ "/lib/driverkit/bfdrivers.ld" ],
+    addLibraries = libDeps [ "driverkit", "thc", "term_server", "int_route_client" ],
+    addModules = ["pl390_dist_module"],
     architectures = ["armv7"]
   }
 ]
index 0ecc23e..cb0c6c2 100644 (file)
  */
 int main(int argc, char** argv)
 {
-    size_t drivers = 0;
-    struct bfdriver* cur = NULL;
-    driverkit_list(&cur, &drivers);
-    for (size_t i=0; i<drivers; i++) {
-        //printf("%s:%s:%d: Found device driver class = %s\n", __FILE__, __FUNCTION__, __LINE__, cur->name);
-        cur += 1;
+    if(argc<3){
+        USER_PANIC("Not enough arguments. argv[2] for ddomain communication!\n");
     }
-    /*for (size_t i=0; i<argc; i++) {
-        printf("%s:%s:%d: argv[i] = %s\n", __FILE__, __FUNCTION__, __LINE__, argv[i]);
-    }*/
 
     iref_t kaluga_iref = 0;
     errval_t err = nameservice_blocking_lookup("ddomain_controller", &kaluga_iref);
index c4729b1..fead4fa 100644 (file)
@@ -106,7 +106,9 @@ static errval_t pl390_dist_init(struct pl390_dist_driver_state * ds, mackerel_ad
 static errval_t enable_interrupt(struct pl390_dist_driver_state *ds, int int_id,
     uint8_t cpu_targets, bool edge_triggered, bool one_to_n, uint16_t prio)
 {
-
+    //LH: We can't really handle level triggered interrupts in the kernel
+    assert(edge_triggered);
+    PL390_DEBUG("enable int=%d forwarding to cpu_mask=%d\n", int_id, cpu_targets);
     uint32_t ind = int_id / 32;
     uint32_t bit_mask = (1U << (int_id % 32));
     enum IrqType irq_type = get_irq_type(int_id);
@@ -233,10 +235,17 @@ static void add_mapping(struct int_route_controller_binding *b,
         int_route_controller_int_message_t to)
 {
     errval_t err;
-    PL390_DEBUG("add_mapping: label:%s, class:%s (%"PRIu64", %"PRIu64") to "
-            "(%"PRIu64", %"PRIu64")\n", label, class, from.addr, from.msg, to.addr, to.msg);
-    // TODO: CPU mask
-    err = enable_interrupt(b->st, from.port, 0, 0, 0, 0);
+    PL390_DEBUG("add_mapping: label:%s, class:%s (%"PRIu64",%"PRIu64", %"PRIu64") to "
+            "(%"PRIu64",%"PRIu64", %"PRIu64")\n", label, class,
+            from.port, from.addr, from.msg,
+            to.port, to.addr, to.msg);
+
+    assert(to.port < 8);
+    uint8_t cpu_mask = 1<<to.port;
+    bool edge_triggered = 1;
+    bool one_to_n = 0;
+    uint16_t prio = 1;
+    err = enable_interrupt(b->st, from.port, cpu_mask, edge_triggered, one_to_n, prio);
     assert(err_is_ok(err));
 }
 
@@ -255,7 +264,6 @@ static void bind_cb(void *st, errval_t err, struct int_route_controller_binding
     char label[128];
     snprintf(label, sizeof(label), "dist_%d", ds->cpu_index);
     const char * ctrl_class = "gic_dist";
-    HERE;
     b->tx_vtbl.register_controller(b, NOP_CONT, label, ctrl_class);
 }
 
@@ -270,7 +278,6 @@ static errval_t connect_to_irs(struct bfdriver_instance *bfi) {
         return err;
     }
 
-    HERE;
     err = int_route_controller_bind(
         int_route_service, bind_cb, bfi,
         get_default_waitset(), IDC_BIND_FLAGS_DEFAULT);
@@ -279,7 +286,6 @@ static errval_t connect_to_irs(struct bfdriver_instance *bfi) {
         DEBUG_ERR(err, "Could not bind int_route_service\n");
         return err;
     }
-    HERE;
 
     return SYS_ERR_OK;
 }
index f4ebfd8..ffc76dd 100644 (file)
 -- 
 --------------------------------------------------------------------------
 
-[ 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" ],
-                      mackerelDevices = [ "pc16550d" ],
-                      addLibraries = [ "pci", "term_server" ],
-                      architectures = [ "x86_64", "x86_32" ]
-                    },
-  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 = [ "driverkit", "term_server" ],
-                      architectures = [ "armv7" ]
-                    },
-  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 = [ "driverkit", "term_server" ],
-                      architectures = [ "armv7", "armv8" ]
-                    },
-  build application { target = "serial_kernel",
-                      cFiles = [ "serial_kernel.c", "main.c",
+[ 
+ -- build application { target = "serial_pc16550d",
+ --                      cFiles = [ "serial_pc16550d.c", "main.c", "main_common.c"
+ --                                 "basic_service.c", "terminal_service.c" ],
+ --                      flounderBindings = [ "serial" ],
+ --                      flounderDefs = [ "terminal" , "terminal_config",
+ --                                       "terminal_session" ],
+ --                      mackerelDevices = [ "pc16550d" ],
+ --                      addLibraries = [ "pci", "term_server" ],
+ --                      architectures = [ "x86_64", "x86_32" ]
+ --                    },
+ --  build application { target = "serial_omap44xx",
+ --                      cFiles = [ "serial_omap44xx.c", "main.c", "main_common.c"
+ --                                 "basic_service.c", "terminal_service.c" ],
+ --                      flounderBindings = [ "serial" ],
+ --                      flounderDefs = [ "terminal" , "terminal_config",
+ --                                       "terminal_session" ],
+ --                      mackerelDevices = [ "omap/omap44xx_uart3" ],
+ --                      addLibraries = [ "driverkit", "term_server" ],
+ --                      architectures = [ "armv7" ]
+ --                    },
+ --  build application { target = "serial_pl011",
+ --                      cFiles = [ "serial_pl011.c", "main.c", "main_common.c"
+ --                                 "basic_service.c", "terminal_service.c" ],
+ --                      flounderBindings = [ "serial" ],
+ --                      flounderDefs = [ "terminal" , "terminal_config",
+ --                                       "terminal_session" ],
+ --                      mackerelDevices = [ "pl011_uart" ],
+ --                      addLibraries = [ "driverkit", "term_server" ],
+ --                      architectures = [ "armv7", "armv8" ]
+ --                    },
+
+  build library { target = "serial_kernel_module",
+                      cFiles = [ "serial_kernel.c", "main_module.c",
+                                 "main_common.c",
                                  "basic_service.c", "terminal_service.c" ],
                       flounderBindings = [ "serial" ],
                       flounderDefs = [ "terminal" , "terminal_config",
                                        "terminal_session" ],
-                      addLibraries = [ "term_server", "driverkit" ],
+                      -- addLibraries = [ "term_server", "driverkit" ],
                       architectures = [ "x86_32", "x86_64",
                                         "armv7", "armv8" ]
                     }
index ee7d3cc..5589637 100644 (file)
 
 #define SERVICE_SUFFIX "raw"
 
-/// input buffers, double-buffered for safety with async IDC sends
-static struct serial_buffer inbuf[2];
-static int ninbuf;
+struct bs_state {
+    struct serial_main *serial;
+    struct term_server *server;
+
+    /// input buffers, double-buffered for safety with async IDC sends
+    struct serial_buffer inbuf[2];
+    int ninbuf;
+
+    /// current consumer of input
+    struct serial_binding *terminal;
+};
 
-/// current consumer of input
-static struct serial_binding *terminal;
 
 static void tx_handler(void *arg)
 {
-    struct serial_binding *b = arg;
+    struct bs_state * bs = arg;
+    struct serial_binding *b = bs->terminal;
     errval_t err;
 
     // free previously-sent buffer, if there is one
-    if (inbuf[!ninbuf].buf != NULL) {
-        free(inbuf[!ninbuf].buf);
-        inbuf[!ninbuf].buf = NULL;
+    if (bs->inbuf[!bs->ninbuf].buf != NULL) {
+        free(bs->inbuf[!bs->ninbuf].buf);
+        bs->inbuf[!bs->ninbuf].buf = NULL;
     }
 
     // do we have something to send? if not, bail out
-    if (inbuf[ninbuf].buf == NULL) {
+    if (bs->inbuf[bs->ninbuf].buf == NULL) {
         return;
     }
 
     // try to send
-    err = b->tx_vtbl.input(b, MKCONT(tx_handler,b), inbuf[ninbuf].buf,
-                           inbuf[ninbuf].len);
+    err = b->tx_vtbl.input(b, MKCONT(tx_handler,b), bs->inbuf[bs->ninbuf].buf,
+                           bs->inbuf[bs->ninbuf].len);
     if (err_is_ok(err)) {
         // swing buffer pointer
-        ninbuf = !ninbuf;
-        assert(inbuf[ninbuf].buf == NULL);
+        bs->ninbuf = !bs->ninbuf;
+        assert(bs->inbuf[bs->ninbuf].buf == NULL);
     } else if (err_is_fail(err)) {
         DEBUG_ERR(err, "error sending serial input to terminal");
     }
 }
 
-static void basic_serial_input(char *data, size_t length)
+static void basic_serial_input(void *st, char *data, size_t length)
 {
-    if (inbuf[ninbuf].buf == NULL) { // allocate a buffer
-        inbuf[ninbuf].buf = malloc(length);
-        assert(inbuf[ninbuf].buf != NULL);
-        memcpy(inbuf[ninbuf].buf, data, length);
-        inbuf[ninbuf].len = length;
+    struct bs_state *bs = st;
+    struct serial_buffer *in = &bs->inbuf[bs->ninbuf]; 
+
+    if (in->buf == NULL) { // allocate a buffer
+        in->buf = malloc(length);
+        assert(in->buf != NULL);
+        memcpy(in->buf, data, length);
+        in->len = length;
     } else { // append new data to existing buffer
-        inbuf[ninbuf].buf = realloc(inbuf[ninbuf].buf, inbuf[ninbuf].len + length);
-        assert(inbuf[ninbuf].buf != NULL);
-        memcpy(inbuf[ninbuf].buf + inbuf[ninbuf].len, data, length);
-        inbuf[ninbuf].len += length;
+        in->buf = realloc(in->buf, in->len + length);
+        assert(in->buf != NULL);
+        memcpy(in->buf + in->len, data, length);
+        in->len += length;
     }
 
     // try to send something, if we're not already doing so
-    if (terminal != NULL && inbuf[!ninbuf].buf == NULL) {
-        tx_handler(terminal);
+    if (bs->terminal != NULL && bs->inbuf[!bs->ninbuf].buf == NULL) {
+        tx_handler(bs);
     }
 }
 
 static void output_handler(struct serial_binding *b, const char *c, size_t len)
 {
-    serial_write(c, len);
+    struct bs_state *bs = b->st;
+    bs->serial->output(bs->serial, c, len);
 }
 
 static void associate_stdin_handler(struct serial_binding *b)
 {
     SERIAL_DEBUG("associate_stdin called on basic interface\n");
+    struct bs_state *bs = b->st;
 
-    terminal = b;
-    set_new_input_consumer(basic_serial_input);
+    bs->terminal = b;
+    serial_set_new_input_consumer(bs->serial, basic_serial_input, bs);
     // try to send something, if we have it ready
-    if (inbuf[ninbuf].buf != NULL) {
-        tx_handler(b);
+    if (bs->inbuf[bs->ninbuf].buf != NULL) {
+        tx_handler(bs);
     }
 }
 
@@ -105,15 +117,16 @@ static struct serial_rx_vtbl serial_rx_vtbl = {
 
 static errval_t connect_cb(void *st, struct serial_binding *b)
 {
+    struct bs_state *bs = st;
     SERIAL_DEBUG("Client connected to basic interface.\n");
 
+    b->st = bs;
     b->rx_vtbl = serial_rx_vtbl;
-
-    terminal = b;
-    set_new_input_consumer(basic_serial_input);
+    bs->terminal = b;
+    serial_set_new_input_consumer(bs->serial, basic_serial_input, bs);
     // try to send something, if we have it ready
-    if (inbuf[ninbuf].buf != NULL) {
-        tx_handler(b);
+    if (bs->inbuf[bs->ninbuf].buf != NULL) {
+        tx_handler(bs);
     }
 
     return SYS_ERR_OK;
@@ -121,21 +134,21 @@ static errval_t connect_cb(void *st, struct serial_binding *b)
 
 static void export_cb(void *st, errval_t err, iref_t iref)
 {
+    struct bs_state *bs = st;
     size_t size = 0;
     char *service_name = NULL;
-    char *driver_name = (char *) st;
 
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "Exporting basic interface failed.\n");
     }
 
     // build service name as driver_name.SERVICE_SUFFIX
-    size = snprintf(NULL, 0, "%s.%s", driver_name, SERVICE_SUFFIX);
+    size = snprintf(NULL, 0, "%s.%s", bs->serial->driver_name, SERVICE_SUFFIX);
     service_name = (char *) malloc(size + 1);
     if (service_name == NULL) {
         USER_PANIC("Error allocating memory.");
     }
-    snprintf(service_name, size + 1, "%s.%s", driver_name, SERVICE_SUFFIX);
+    snprintf(service_name, size + 1, "%s.%s", bs->serial->driver_name, SERVICE_SUFFIX);
 
     SERIAL_DEBUG("About to register basic interface '%s' at nameservice.\n",
                  service_name);
@@ -150,10 +163,12 @@ static void export_cb(void *st, errval_t err, iref_t iref)
     free(service_name);
 }
 
-void start_basic_service(char *driver_name)
+void start_basic_service(struct serial_main *serial)
 {
     errval_t err;
-    err = serial_export(driver_name, export_cb, connect_cb,
+    struct bs_state *bs = malloc(sizeof(struct bs_state));
+    bs->serial = serial;
+    err = serial_export(bs, export_cb, connect_cb,
                         get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "Preparing basic interface for export failed.");
index 227b112..5f59228 100644 (file)
 #include "serial.h"
 #include "serial_debug.h"
 
-static char *driver_name = "serial0";       // default driver name
-
-static struct serial_buffer buffer;
-
-static serial_input_fn_t *consumer_serial_input = NULL;
-
-void serial_input(char *data, size_t length)
-{
-    if (consumer_serial_input != NULL) {
-        // There is a consumer (client) attached to either the basic service
-        // interface or the terminal service interface. Direct input directly
-        // to service.
-        consumer_serial_input(data, length);
-    } else {
-        // No consumer (client) attached. Buffer input.
-        if (buffer.buf == NULL) {
-            // Allocate a new buffer.
-            buffer.buf = (char *) malloc(length);
-            assert(buffer.buf != NULL);
-            memcpy(buffer.buf, data, length);
-            buffer.len = length;
-        } else {
-            // Append new data to existing buffer.
-            buffer.buf = realloc(buffer.buf, buffer.len + length);
-            assert(buffer.buf != NULL);
-            memcpy(buffer.buf + buffer.len, data, length);
-            buffer.len += length;
-        }
-    }
-}
-
-void set_new_input_consumer(serial_input_fn_t fn)
-{
-    SERIAL_DEBUG("New input consumer set.\n");
-    consumer_serial_input = fn;
-
-    // Send previously buffered input to newly attached consumer.
-    if (buffer.buf != NULL) {
-        SERIAL_DEBUG("Previously buffered input sent to newly attached "
-                     "consumer.\n");
-        consumer_serial_input(buffer.buf, buffer.len);
-        free(buffer.buf);
-        buffer.buf = NULL;
-    }
-}
-
-void start_service(void)
-{
-    SERIAL_DEBUG("Starting services.\n");
-    start_terminal_service(driver_name);
-    start_basic_service(driver_name);
-}
-
 int main(int argc, char *argv[])
 {
-    errval_t err;
 
-    struct serial_params params = {
-        .portbase       = SERIAL_PORTBASE_INVALID,
-        .irq            = SERIAL_IRQ_INVALID,
-        .membase        = SERIAL_MEMBASE_INVALID,
-    };
+    static struct serial_main main;
+    init_serial_main(&main, argc, argv);
 
-    // Parse args
-    for (int i = 1; i < argc; i++) {
-        if (strncmp(argv[i], "portbase=", sizeof("portbase=") - 1) == 0) {
-            uint32_t x=
-                strtoul(argv[i] + sizeof("portbase=") - 1, NULL, 0);
-            if (x == 0 || x > 65535) {
-                fprintf(stderr, "Error: invalid portbase 0x%"PRIx32"\n", x);
-                goto usage;
-            }
-            params.portbase = x;
-        } else if (strncmp(argv[i], "irq=", sizeof("irq=") - 1) == 0) {
-             uint32_t x=
-                 strtoul(argv[i] + sizeof("irq=") - 1, NULL, 0);
-             if (x == 0) {
-                fprintf(stderr, "Error: invalid IRQ %"PRIu32"\n", x);
-                goto usage;
-            }
-            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) {
-            // do nothing, means we are being started through kaluga
-        } else if (strncmp(argv[i], "int_model=", sizeof("int_model=") - 1) == 0) {
-            // ignore. x86 just assumes that legacy interrupts are used.
-        } else {
-            fprintf(stderr, "Error: unknown option %s\n", argv[i]);
-            goto usage;
-        }
-    }
 
     // Initialize serial driver
-    err = serial_init(&params);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "Error initializing serial driver.");
-    }
-
-    SERIAL_DEBUG("Serial driver initialized.\n"
-                 "Using driver name %s.\n", driver_name);
-
+    // TODO: Figure out how to init the right module.
+//    err = serial_init(&params);
+//    if (err_is_fail(err)) {
+//        USER_PANIC_ERR(err, "Error initializing serial driver.");
+//    }
+//
+//    SERIAL_DEBUG("Serial driver initialized.\n"
+//                 "Using driver name %s.\n", driver_name);
+//
     // Stick around waiting for input
     struct waitset *ws = get_default_waitset();
     while (1) {
diff --git a/usr/drivers/serial/main_common.c b/usr/drivers/serial/main_common.c
new file mode 100644 (file)
index 0000000..cc4965d
--- /dev/null
@@ -0,0 +1,126 @@
+/**
+ * \file
+ * \brief Serial port driver.
+ */
+
+/*
+ * Copyright (c) 2007, 2008, 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/waitset.h>
+#include "serial.h"
+#include "serial_debug.h"
+
+
+void serial_input(struct serial_main *main, char *data, size_t length)
+{
+    if (main->input_consumer != NULL) {
+        // There is a consumer (client) attached to either the basic service
+        // interface or the terminal service interface. Direct input directly
+        // to service.
+        main->input_consumer(main->input_consumer_arg, data, length);
+    } else {
+        // No consumer (client) attached. Buffer input.
+        if (main->buffer.buf == NULL) {
+            // Allocate a new buffer.
+            main->buffer.buf = (char *) malloc(length);
+            assert(main->buffer.buf != NULL);
+            memcpy(main->buffer.buf, data, length);
+            main->buffer.len = length;
+        } else {
+            // Append new data to existing buffer.
+            main->buffer.buf = realloc(main->buffer.buf, main->buffer.len + length);
+            assert(main->buffer.buf != NULL);
+            memcpy(main->buffer.buf + main->buffer.len, data, length);
+            main->buffer.len += length;
+        }
+    }
+}
+
+void serial_set_new_input_consumer(struct serial_main *main,
+                                   serial_input_fn_t fn, void *fn_arg)
+{
+    SERIAL_DEBUG("New input consumer set. main=%p\n", main);
+    main->input_consumer = fn;
+    main->input_consumer_arg = fn_arg;
+
+    // Send previously buffered input to newly attached consumer.
+    if (main->buffer.buf != NULL) {
+        SERIAL_DEBUG("Previously buffered input sent to newly attached "
+                     "consumer.\n");
+        main->input_consumer(main->input_consumer, main->buffer.buf, main->buffer.len);
+        free(main->buffer.buf);
+        main->buffer.buf = NULL;
+    }
+}
+
+void start_service(struct serial_main *m)
+{
+    SERIAL_DEBUG("Starting services.\n");
+    start_terminal_service(m);
+    start_basic_service(m);
+}
+
+errval_t init_serial_main(struct serial_main *m, int argc, char **argv)
+{
+    // defaults
+    m->driver_name = "serial0";       
+    m->input_consumer = NULL;
+    m->input_consumer_arg = NULL;
+    m->buffer.buf = NULL;
+    m->buffer.len = 0;
+    m->portbase       = SERIAL_PORTBASE_INVALID;
+    m->irq            = SERIAL_IRQ_INVALID;
+    m->membase        = SERIAL_MEMBASE_INVALID;
+
+    // Parse args
+    for (int i = 1; i < argc; i++) {
+        if (strncmp(argv[i], "portbase=", sizeof("portbase=") - 1) == 0) {
+            uint32_t x=
+                strtoul(argv[i] + sizeof("portbase=") - 1, NULL, 0);
+            if (x == 0 || x > 65535) {
+                fprintf(stderr, "Error: invalid portbase 0x%"PRIx32"\n", x);
+                goto usage;
+            }
+            m->portbase = x;
+        } else if (strncmp(argv[i], "irq=", sizeof("irq=") - 1) == 0) {
+             uint32_t x=
+                 strtoul(argv[i] + sizeof("irq=") - 1, NULL, 0);
+             if (x == 0) {
+                fprintf(stderr, "Error: invalid IRQ %"PRIu32"\n", x);
+                goto usage;
+            }
+            m->irq = x;
+        } else if (strncmp(argv[i], "membase=", sizeof("membase=") - 1) == 0) {
+            uint64_t x=
+                strtoull(argv[i] + sizeof("membase=") - 1, NULL, 0);
+            m->membase = x;
+        } else if (strncmp(argv[i], "name=", sizeof("name=") - 1) == 0) {
+             m->driver_name = argv[i] + sizeof("name=") - 1;
+        } else if (strncmp(argv[i], "auto", 4) == 0) {
+            // do nothing, means we are being started through kaluga
+        } else if (strncmp(argv[i], "int_model=", sizeof("int_model=") - 1) == 0) {
+            // ignore. x86 just assumes that legacy interrupts are used.
+        } else {
+            fprintf(stderr, "Error: unknown option %s\n", argv[i]);
+            goto usage;
+        }
+    }
+
+    return SYS_ERR_OK;
+
+usage:
+    fprintf(stderr, "Usage: %s [portbase=PORT] [irq=IRQ] [name=NAME]\n"
+                    "    [membase=ADDR] [kernel]\n", argv[0]);
+    return SYS_ERR_IRQ_INVALID;
+}
diff --git a/usr/drivers/serial/main_module.c b/usr/drivers/serial/main_module.c
new file mode 100644 (file)
index 0000000..0a6135d
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * \file
+ * \brief Serial port driver.
+ */
+
+/*
+ * Copyright (c) 2007, 2008, 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/waitset.h>
+#include "serial.h"
+#include "serial_debug.h"
+#include <driverkit/driverkit.h>
+
+static errval_t
+init_kernel(struct bfdriver_instance* bfi, uint64_t flags, iref_t *dev)
+{
+    errval_t err;
+    struct serial_main *m = malloc(sizeof(struct serial_main));
+    bfi->dstate = m;
+
+    m->irq_src.cnode = bfi->argcn;
+    m->irq_src.slot = 0;
+    char db[1024];
+    debug_print_cap_at_capref(db, 1024, m->irq_src);
+    debug_printf("cap = %s\n", db);
+
+    err = init_serial_main(m, bfi->argc, bfi->argv);
+    assert(err_is_ok(err));
+
+    // Initialize serial driver
+    err = serial_kernel_init(m);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "serial_init");
+        return err;
+    }
+
+    SERIAL_DEBUG("Kernel Serial driver initialized.\n");
+
+    return SYS_ERR_OK;
+}
+
+static errval_t attach(struct bfdriver_instance* bfi) {
+    return SYS_ERR_OK;
+}
+
+static errval_t detach(struct bfdriver_instance* bfi) {
+    return SYS_ERR_OK;
+}
+
+static errval_t set_sleep_level(struct bfdriver_instance* bfi, uint32_t level) {
+    return SYS_ERR_OK;
+}
+
+static errval_t destroy(struct bfdriver_instance* bfi) {
+    struct pl390_dist_driver_state* uds = bfi->dstate;
+    free(uds);
+    bfi->dstate = NULL;
+    // XXX: Tear-down the service
+    bfi->device = 0x0;
+    return SYS_ERR_OK;
+}
+
+static errval_t get_ep(struct bfdriver_instance* bfi, bool lmp, struct capref* ret_cap)
+{   
+    USER_PANIC("NIY \n");
+    return SYS_ERR_OK;
+}
+
+DEFINE_MODULE(serial_kernel, init_kernel, attach, detach, set_sleep_level, destroy, get_ep);
index 8e4e0a8..9cdcfbc 100644 (file)
@@ -27,20 +27,43 @@ struct serial_buffer {
 #define SERIAL_IRQ_INVALID      0xffffffff
 #define SERIAL_MEMBASE_INVALID  0xffffffffffffffffULL
 
-struct serial_params {
+struct serial_main;
+
+typedef void (*serial_input_fn_t)
+    (void *arg, char *data, size_t length);
+typedef void (*serial_output_fn_t)
+    (struct serial_main * main, const char *c, size_t length);
+
+struct serial_main {
     uint32_t portbase;
     uint32_t irq;
+    struct capref irq_src;
     uint64_t membase;
+    char *driver_name;
+    struct serial_buffer buffer;
+
+    // Handler for input from the serial line. Set in main.
+    // Module should call serial_input(..) to perform buffering.
+    serial_input_fn_t input_consumer;      
+    void *input_consumer_arg;      
+
+    // Output on the serial line. Set in module, called from main 
+    serial_output_fn_t output;     
 };
 
-typedef void serial_input_fn_t(char *data, size_t length);
 
-void serial_write(const char *c, size_t len);
-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);
-void serial_input(char *data, size_t length);
-void set_new_input_consumer(serial_input_fn_t fn);
+// Module specific init functions
+errval_t init_serial_main(struct serial_main *main, int argc, char **argv);
+errval_t serial_kernel_init(struct serial_main *main);
+
+// Generic interface
+void serial_input(struct serial_main *main, char *data, size_t length);
+void serial_set_new_input_consumer(struct serial_main *main,
+        serial_input_fn_t fn, void *fn_arg);
+
+// Service interface
+void start_service(struct serial_main *main);
+void start_basic_service(struct serial_main *main);
+void start_terminal_service(struct serial_main *main);
 
 #endif
index 04d2cf5..e4161f8 100644 (file)
 
 #include <barrelfish/barrelfish.h>
 #include <barrelfish/inthandler.h>
+#include <int_route/int_route_client.h>
 #include <driverkit/driverkit.h>
 #include "serial.h"
 
 static void
 serial_interrupt(void *arg) {
+    struct serial_main * m = arg;
     char c;
-    errval_t err= sys_getchar(&c);
+    errval_t err = sys_getchar(&c);
     assert(err_is_ok(err));
+    serial_input(m, &c, 1);
+}
 
-    //printf("'%c'\n", c);
-
-    serial_input(&c, 1);
+static void
+serial_write(struct serial_main *m, const char *c, size_t len)
+{
+    sys_print(c, len);
 }
 
-errval_t serial_init(struct serial_params *params)
+errval_t serial_kernel_init(struct serial_main *m)
 {
     errval_t err;
 
-    if(params->irq == SERIAL_IRQ_INVALID)
-        USER_PANIC("serial_kernel requires an irq= parameter");
+    if(capref_is_null(m->irq_src))
+        USER_PANIC("serial_kernel requires an irq cap");
 
-    /* Register interrupt handler. */
-    err = inthandler_setup_arm(serial_interrupt, NULL, params->irq);
+    m->output = serial_write;
+
+    // Register interrupt handler
+    err = int_route_client_route_and_connect(m->irq_src, 0,
+            get_default_waitset(), serial_interrupt, m);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "interrupt setup failed.");
     }
 
     // offer service now we're up
-    start_service();
+    start_service(m);
     return SYS_ERR_OK;
 }
 
 
-void serial_write(const char *c, size_t len)
-{
-    sys_print(c, len);
-}
index 1bbf0b9..5fa045e 100644 (file)
 #include "serial.h"
 #include "serial_debug.h"
 
-static struct term_server server;
+struct ts_state {
+    struct serial_main *serial;
+    struct term_server *server;
+};
 
-static void terminal_serial_input(char *data, size_t length)
+static void terminal_serial_input(void *st, char *data, size_t length)
 {
-    term_server_send(&server, data, length);
+    struct ts_state * ts = (struct ts_state *)st;
+    term_server_send(ts->server, data, length);
 }
 
 static void characters_handler(void *st, char *buffer, size_t length)
 {
-    serial_write(buffer, length);
+    struct ts_state * ts = (struct ts_state *)st;
+    ts->serial->output(ts->serial, buffer, length);
 }
 
 static void configuration_handler(void *st, terminal_config_option_t opt,
@@ -45,31 +50,41 @@ static void configuration_handler(void *st, terminal_config_option_t opt,
 
 static void new_session_handler(void *st, struct capref session_id)
 {
-    set_new_input_consumer(terminal_serial_input);
+    struct ts_state * ts = (struct ts_state *)st;
+    serial_set_new_input_consumer(ts->serial, terminal_serial_input, ts);
 }
 
-void start_terminal_service(char *driver_name)
+void start_terminal_service(struct serial_main *serial)
 {
     errval_t err;
     iref_t iref = NULL_IREF;
     char *service_name = NULL;
     size_t size = 0;
 
+    struct ts_state *ts = malloc(sizeof(struct ts_state));
+    assert(ts != NULL);
+    ts->server = malloc(sizeof(struct term_server));
+    assert(ts->server != NULL);
+    ts->serial = serial;
+
     struct waitset *ws = get_default_waitset();
 
-    err = term_server_init(&server, &iref, ws, ws, ws, ws, characters_handler,
+    err = term_server_init(ts->server, &iref, ws, ws, ws, ws, characters_handler,
                            configuration_handler, new_session_handler);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "Error exporting terminal interface.");
     }
 
+    /* Set state pointer (keep after initialization!) */
+    ts->server->st = ts;
+
     /* build service name as driver_nameTERM_SESSION_IF_SUFFIX */
-    size = snprintf(NULL, 0, "%s%s", driver_name, TERM_SESSION_IF_SUFFIX);
+    size = snprintf(NULL, 0, "%s%s", serial->driver_name, TERM_SESSION_IF_SUFFIX);
     service_name = (char *) malloc(size + 1);
     if (service_name == NULL) {
         USER_PANIC("Error allocating memory for service name.");
     }
-    snprintf(service_name, size + 1, "%s%s", driver_name,
+    snprintf(service_name, size + 1, "%s%s", serial->driver_name,
              TERM_SESSION_IF_SUFFIX);
 
     /* register terminal session interface at nameservice */
index c23246c..bb739b4 100644 (file)
@@ -18,6 +18,7 @@
 #include <barrelfish_kpi/platform.h>
 #include <if/monitor_blocking_defs.h>
 #include <maps/vexpress_map.h>
+#include <barrelfish/sys_debug.h>
 
 #include <skb/skb.h>
 #include <octopus/getset.h>
@@ -27,6 +28,7 @@
 static void start_driverdomain(char* module_name, char* record) {
     struct module_info* mi = find_module("driverdomain");
     struct driver_argument arg;
+    init_driver_argument(&arg);
     arg.module_name = module_name;
     if (mi != NULL) {
         errval_t err = mi->start_function(0, mi, record, &arg);
@@ -93,9 +95,9 @@ static errval_t start_gic_dist(coreid_t where){
     errval_t err;
 
     /* Prepare module and cap */
-    struct module_info *mi = find_module("driverdomain");
+    struct module_info *mi = find_module("driverdomain_pl390");
     if (mi == NULL) {
-        debug_printf("Binary driverdomain not found!\n");
+        debug_printf("Binary driverdomain_pl390 not found!\n");
         return KALUGA_ERR_MODULE_NOT_FOUND;
     }
     struct capref dist_reg;
@@ -128,6 +130,50 @@ static errval_t start_gic_dist(coreid_t where){
     return err;
 }
 
+static errval_t start_serial(char *name, coreid_t where){
+    errval_t err;
+
+    /* Prepare module and cap */
+    struct module_info *mi = find_module("driverdomain");
+    if (mi == NULL) {
+        debug_printf("Binary driverdomain not found!\n");
+        return KALUGA_ERR_MODULE_NOT_FOUND;
+    }
+
+    // TODO Add caps for all cases
+    if(strcmp(name, "serial_kernel") == 0) {
+        // No caps needed
+    } else {
+       assert(!"NYI"); 
+    }
+
+    struct driver_argument arg;
+    init_driver_argument(&arg);
+    arg.module_name = name;
+    struct capref irq_src;
+    err = slot_alloc(&irq_src);
+    assert(err_is_ok(err));
+
+    err = sys_debug_create_irq_src_cap(irq_src, 37, 37);
+    assert(err_is_ok(err));
+
+    struct capref irq_dst = {
+        .cnode = arg.argnode_ref,
+        .slot = 0
+    };
+    err = cap_copy(irq_dst, irq_src);
+    if(err_is_fail(err)){
+        DEBUG_ERR(err, "cap_copy\n");
+        return err;
+    }
+
+    err = mi->start_function(where, mi, "hw.arm.vexpress.uart", &arg);
+    if(err_is_fail(err)){
+        DEBUG_ERR(err, "couldnt start gic dist on core=%d\n", where);
+    }
+    return err;
+}
+
 static errval_t vexpress_startup(void)
 {
     errval_t err;
@@ -135,19 +181,10 @@ static errval_t vexpress_startup(void)
     assert(err_is_ok(err));
 
     err = start_gic_dist(0);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "Unable to start gic dist.");
-    }
-
-    HERE;
-    struct module_info* mi = find_module("serial_pl011");
-    if (mi != NULL) {
-        err = mi->start_function(0, mi, "hw.arm.vexpress.uart {}", NULL);
-        assert(err_is_ok(err));
-    } else {
-        debug_printf("Module serial_pl011 not found!\n");
-    }
+    assert(err_is_ok(err));
 
+    err = start_serial("serial_kernel", 0);
+    assert(err_is_ok(err));
 
     return SYS_ERR_OK;
 }
index 3931f3f..b10d0a3 100644 (file)
@@ -135,20 +135,23 @@ errval_t
 default_start_function_pure(coreid_t where, struct module_info* mi, char* record,
                            struct driver_argument* arg) {
 
-    // TODO this doesn't reuse existing driver domains
     struct domain_instance* inst;
     errval_t err;
 
-    KALUGA_DEBUG("Creating new driver domain for %s\n", mi->binary);
-    inst = instantiate_driver_domain(mi->binary, where);
-    if (inst == NULL) {
-        return DRIVERKIT_ERR_DRIVER_INIT;
+    if(mi->driverinstance == NULL){
+        KALUGA_DEBUG("Creating new driver domain for %s\n", mi->binary);
+        inst = instantiate_driver_domain(mi->binary, where);
+        if (inst == NULL) {
+            return DRIVERKIT_ERR_DRIVER_INIT;
+        }
+        
+        while (inst->b == NULL) {
+            event_dispatch(get_default_waitset());
+        }   
+        mi->driverinstance = inst;
     }
-    
-    while (inst->b == NULL) {
-        event_dispatch(get_default_waitset());
-    }   
 
+    inst = mi->driverinstance;
     char* oct_id;
     err = oct_read(record, "%s {}", &oct_id);
     assert(err_is_ok(err));
index cee3a64..aaa184b 100644 (file)
@@ -66,6 +66,7 @@ static void add_start_function_overrides(void)
     set_start_function("xeon_phi", default_start_function_new);
 #else
     set_start_function("driverdomain", default_start_function_pure);
+    set_start_function("driverdomain_pl390", default_start_function_pure);
 #endif
 
 
index 78260ac..00ebb39 100644 (file)
@@ -371,11 +371,10 @@ static void get_io_cap(struct monitor_blocking_binding *b)
 static void get_irq_dest_cap(struct monitor_blocking_binding *b)
 {
     errval_t err;
-    //TODO get real cap
 
     struct capref dest_cap;
     slot_alloc(&dest_cap);
-    err = invoke_irqtable_alloc_dest_cap(cap_irq, dest_cap);
+    err = invoke_irqtable_alloc_dest_cap(cap_irq, dest_cap, -1);
     if(err_is_fail(err)){
         DEBUG_ERR(err,"x");
         USER_PANIC_ERR(err, "could not allocate dest cap!");
@@ -397,6 +396,48 @@ static void get_irq_dest_cap(struct monitor_blocking_binding *b)
     }
 }
 
+static void get_irq_dest_cap_arm(
+        struct monitor_blocking_binding *b,
+        struct capref irqsrc, int irq_idx)
+{
+    errval_t err;
+    //TODO get real cap
+    struct capability irqsrc_cap;
+    debug_cap_identify(irqsrc, &irqsrc_cap);
+    if(irqsrc_cap.type != ObjType_IRQSrc) {
+        USER_PANIC("Must be invoked with IRQSrc cap!");
+    }
+
+    if(irqsrc_cap.u.irqsrc.vec_start + irq_idx > irqsrc_cap.u.irqsrc.vec_end ||
+            irq_idx < 0){
+        USER_PANIC("invalid irq_idx");
+    }
+
+    struct capref dest_cap;
+    slot_alloc(&dest_cap);
+    err = invoke_irqtable_alloc_dest_cap(cap_irq, dest_cap,
+            irqsrc_cap.u.irqsrc.vec_start + irq_idx);
+    if(err_is_fail(err)){
+        DEBUG_ERR(err,"x");
+        USER_PANIC_ERR(err, "could not allocate dest cap!");
+    }
+
+
+    err = b->tx_vtbl.get_irq_dest_cap_arm_response(b, NOP_CONT, dest_cap,
+            SYS_ERR_OK);
+    if (err_is_fail(err)) {
+        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+            err = b->register_send(b, get_default_waitset(),
+                                   MKCONT((void (*)(void *))get_io_cap, b));
+            if (err_is_fail(err)) {
+                USER_PANIC_ERR(err, "register_send failed");
+            }
+        }
+
+        USER_PANIC_ERR(err, "sending get_io_cap_response failed");
+    }
+}
+
 
 static void get_bootinfo(struct monitor_blocking_binding *b)
 {
@@ -728,6 +769,7 @@ static struct monitor_blocking_rx_vtbl rx_vtbl = {
     .get_phyaddr_cap_call = get_phyaddr_cap,
     .get_io_cap_call = get_io_cap,
     .get_irq_dest_cap_call = get_irq_dest_cap,
+    .get_irq_dest_cap_arm_call = get_irq_dest_cap_arm,
 
     .remote_cap_retype_call  = remote_cap_retype,
     .remote_cap_delete_call  = remote_cap_delete,