/* * Copyright 2020, Data61 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) * ABN 41 687 119 230. * * This software may be distributed and modified according to the terms of * the BSD 2-Clause license. Note that NO WARRANTY is provided. * See "LICENSE_BSD2.txt" for details. * * @TAG(DATA61_BSD) */ #include #include #include #include #include #include #include #include /*? 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"); } }