blob: b33720565d6975e396a660bb1a0e8c3b68ed4b02 [file]
/*
* Copyright 2020, Data61, ABN 41 687 119 230.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <assert.h>
#include <camkes.h>
#include <sel4/sel4.h>
#include <stdbool.h>
#include <stddef.h>
#include <utils/util.h>
#include <platsupport/irq.h>
#include <camkes/irq.h>
/*? macros.show_includes(me.instance.type.includes) ?*/
/*- from 'global-endpoint.template.c' import allocate_cap with context -*/
/*- do allocate_cap(me, is_reader=False) -*/
/*- set notification_origin = pop('notification') -*/
/*- set badge = pop('badge') -*/
/*- include 'get-notification.template.c' -*/
/*- set ntfn = pop('callback_notification') -*/
/*- set type_attr = '%s_irq_type' % me.parent.from_interface.name -*/
/*- set type = configuration[me.parent.from_instance.name].get(type_attr, 'simple') -*/
/*- if type == 'simple' -*/
/*- set attr = '%s_irq_number' % me.parent.from_interface.name -*/
/*- set _irq = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if _irq is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(_irq, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set spi_attr = '%s_spi_number' % me.parent.from_interface.name -*/
/*- set _irq_spi = configuration[me.parent.from_instance.name].get(spi_attr) -*/
/*- if (isinstance(_irq_spi, numbers.Integral)) and (_irq_spi == 0) -*/
/*- set _irq = _irq + 32 -*/
/*- endif -*/
/*- set irq = alloc('irq', seL4_IRQHandler, number=_irq, notification=my_cnode[ntfn]) -*/
/*- elif type in ['arm'] -*/
/*- set attr = '%s_irq_trigger' % me.parent.from_interface.name -*/
/*- set trigger = configuration[me.parent.from_instance.name].get(attr, "level") -*/
/*- if trigger == "level" -*/
/*- set trigger = seL4_ARM_IRQ_LEVEL -*/
/*- set sel4_trigger_param = 0 -*/
/*- elif trigger == "edge" -*/
/*- set trigger = seL4_ARM_IRQ_EDGE -*/
/*- set sel4_trigger_param = 1 -*/
/*- else -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IRQ trigger mode can only be "edge" or "level" but is set to: %s' % (me.parent.from_instance.name, attr, trigger))) ?*/
/*- endif -*/
/*- set attr = '%s_irq_number' % me.parent.from_interface.name -*/
/*- set _irq = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if _irq is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(_irq, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set attr = '%s_irq_target' % me.parent.from_interface.name -*/
/*- set target = configuration[me.parent.from_instance.name].get(attr, 0) -*/
/*- if not isinstance(target, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify a target core is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set irq = alloc('irq', seL4_IRQHandler, number=_irq, trigger=trigger, target=target, notification=my_cnode[ntfn]) -*/
/*- elif type in ['ioapic','isa','pci'] -*/
/*- if type == 'isa' -*/
/*- set level = 0 -*/
/*- set polarity = 0 -*/
/*- elif type == 'pci' -*/
/*- set level = 1 -*/
/*- set polarity = 1 -*/
/*- else -*/
/*- set attr = '%s_irq_level' % me.parent.from_interface.name -*/
/*- set level = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if level is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt level is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(level, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt level is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set attr = '%s_irq_polarity' % me.parent.from_interface.name -*/
/*- set polarity = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if polarity is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt polarity is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(polarity, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt polarity is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- endif -*/
/*- set attr = '%s_irq_ioapic' % me.parent.from_interface.name -*/
/*- set ioapic = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if ioapic is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC controller number is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(ioapic, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC controller number is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set attr = '%s_irq_ioapic_pin' % me.parent.from_interface.name -*/
/*- set ioapic_pin = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if ioapic_pin is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC pin number is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(ioapic_pin, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC pin number is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set attr = '%s_irq_vector' % me.parent.from_interface.name -*/
/*- set vector = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if vector is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(vector, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set irq = alloc('irq', seL4_IRQHandler, vector=vector, ioapic=ioapic, ioapic_pin=ioapic_pin, level=level, polarity=polarity, notification=my_cnode[ntfn]) -*/
/*- elif type == 'msi' -*/
/*- set attr = '%s_irq_handle' % me.parent.from_interface.name -*/
/*- set handle = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if handle is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify an MSI handle is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(handle, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify an MSI handle is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set attr = '%s_irq_pci_bus' % me.parent.from_interface.name -*/
/*- set pci_bus = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if pci_bus is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify a PCI bus is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(pci_bus, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify a PCI bus is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set attr = '%s_irq_pci_dev' % me.parent.from_interface.name -*/
/*- set pci_dev = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if pci_dev is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify a PCI device is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(pci_dev, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify a PCI device is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set attr = '%s_irq_pci_fun' % me.parent.from_interface.name -*/
/*- set pci_fun = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if pci_fun is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify a PCI function is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(pci_fun, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify a PCI function is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set attr = '%s_irq_vector' % me.parent.from_interface.name -*/
/*- set vector = configuration[me.parent.from_instance.name].get(attr) -*/
/*- if vector is none -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not defined' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- if not isinstance(vector, numbers.Integral) -*/
/*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not an integer' % (me.parent.from_instance.name, attr))) ?*/
/*- endif -*/
/*- set irq = alloc('irq', seL4_IRQHandler, vector=vector, handle=handle, pci_bus=pci_bus, pci_dev=pci_dev, pci_fun=pci_fun, notification=my_cnode[ntfn]) -*/
/*- else -*/
/*? raise(TemplateError('Unknown irq type specified by %s.%s' % (me.parent.from_instance.name, type_attr))) ?*/
/*- endif -*/
/*# Add an entry to the allocated_irqs ELF section #*/
/*- set irq_struct_name = '%s_irq' % me.interface.name -*/
static allocated_irq_t /*? irq_struct_name ?*/ = {
.irq_handler = /*? irq ?*/,
/*- if type == 'simple' -*/
.irq = { .type = PS_INTERRUPT, .irq = { .number = /*? _irq ?*/ }},
/*- elif type in ['ioapic','isa','pci'] -*/
.irq = { .type = PS_IOAPIC, .ioapic = { .ioapic = /*? ioapic ?*/, .pin = /*? ioapic_pin ?*/,
.level = /*? level ?*/, .polarity = /*? polarity ?*/,
.vector = /*? vector ?*/ }},
/*- elif type == 'msi' -*/
.irq = { .type = PS_MSI, .msi = { .pci_bus = /*? pci_bus ?*/, .pci_dev = /*? pci_dev ?*/,
.pci_func = /*? pci_fun ?*/, .handle = /*? handle ?*/,
.vector = /*? vector ?*/ }},
/*- elif type == 'arm' -*/
.irq = { .type = PS_TRIGGER, .cpu = { .trigger = /*? trigger.value ?*/, .cpu_idx= /*? target ?*/, .number = /*? _irq ?*/ }},
/*- endif -*/
.is_allocated = false,
.callback_fn = NULL,
.callback_data = NULL
};
USED SECTION("_allocated_irqs")
allocated_irq_t * /*? irq_struct_name ?*/_ptr = &/*? irq_struct_name ?*/;
int /*? me.interface.name ?*/_poll(void) {
assert(!"not implemented for this connector");
return 0;
}
void /*? me.interface.name ?*/_wait(void) {
assert(!"not implemented for this connector");
while (true);
}
int /*? me.interface.name ?*/_reg_callback(void (*callback)(void*) UNUSED,
void *arg UNUSED) {
assert(!"not implemented for this connector");
return -1;
}
static int /*? me.interface.name ?*/_acknowledge_cb(UNUSED void* cookie) {
return seL4_IRQHandler_Ack(/*? irq ?*/);
}
/*# Add an entry to the global_notification_irqs ELF section #*/
/*- set irq_handler_struct_name = '%s_irq_handler' % me.interface.name -*/
static global_notification_irq_handler_t /*? irq_handler_struct_name ?*/ = {
.badge = /*? badge ?*/,
.ack_fun = /*? me.interface.name ?*/_acknowledge_cb,
.allocated_ref = &/*? irq_struct_name ?*/,
};
USED SECTION("_global_notification_irqs")
global_notification_irq_handler_t * /*? irq_handler_struct_name ?*/_ptr = &/*? irq_handler_struct_name ?*/;
// Set the badge of the IRQHandler.
static void __attribute__((constructor)) register_connector(void) {
int error = seL4_IRQHandler_SetNotification(/*? irq ?*/, /*? notification_origin ?*/);
if (error) {
assert(!"Failed to pair IRQ handler with notification");
}
}