# 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
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
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
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
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);
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;
}
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);
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) {
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 };
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
[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,
},
}
}
-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++) {
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]));
}
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);
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
-- 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"]
}
]
return err;
}
+__attribute__((used))
static errval_t alloc_dest_irq_cap(struct capref *retcap)
{
errval_t err, msgerr;
}
}
+/**
+ * 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;
/* 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;
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,
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);
"usb_manager",
"usb_keyboard",
"serial_omap44xx",
- "serial_kernel",
"angler",
"corectrl",
"driverdomain",
+ "driverdomain_pl390",
"int_route"
] ]
"monitor",
"proc_mgmt",
"ramfsd",
- "serial_pl011",
- "serial_kernel",
"spawnd",
"startd",
"corectrl",
"fish",
"memtest",
"driverdomain",
+ "driverdomain_pl390",
"int_route"
] ]
"monitor",
"proc_mgmt",
"ramfsd",
- "serial_pl011",
"serial_kernel",
"spawnd",
"startd",
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"]
}
]
*/
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);
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);
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));
}
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);
}
return err;
}
- HERE;
err = int_route_controller_bind(
int_route_service, bind_cb, bfi,
get_default_waitset(), IDC_BIND_FLAGS_DEFAULT);
DEBUG_ERR(err, "Could not bind int_route_service\n");
return err;
}
- HERE;
return SYS_ERR_OK;
}
--
--------------------------------------------------------------------------
-[ 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" ]
}
#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);
}
}
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;
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);
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.");
#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(¶ms);
- 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(¶ms);
+// 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) {
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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);
#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
#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);
-}
#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,
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 */
#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>
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);
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;
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;
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;
}
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));
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
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!");
}
}
+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)
{
.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,