1/* 2 * Copyright 2020, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <assert.h> 14#include <camkes.h> 15#include <sel4/sel4.h> 16#include <stdbool.h> 17#include <stddef.h> 18#include <utils/util.h> 19#include <platsupport/irq.h> 20#include <camkes/irq.h> 21 22/*? macros.show_includes(me.instance.type.includes) ?*/ 23 24 25/*- from 'global-endpoint.template.c' import allocate_cap with context -*/ 26 27/*- do allocate_cap(me, is_reader=False) -*/ 28/*- set notification_origin = pop('notification') -*/ 29/*- set badge = pop('badge') -*/ 30/*- include 'get-notification.template.c' -*/ 31/*- set ntfn = pop('callback_notification') -*/ 32/*- set type_attr = '%s_irq_type' % me.parent.from_interface.name -*/ 33/*- set type = configuration[me.parent.from_instance.name].get(type_attr, 'simple') -*/ 34 35/*- if type == 'simple' -*/ 36 /*- set attr = '%s_irq_number' % me.parent.from_interface.name -*/ 37 /*- set _irq = configuration[me.parent.from_instance.name].get(attr) -*/ 38 /*- if _irq is none -*/ 39 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not defined' % (me.parent.from_instance.name, attr))) ?*/ 40 /*- endif -*/ 41 /*- if not isinstance(_irq, numbers.Integral) -*/ 42 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 43 /*- endif -*/ 44 /*- set spi_attr = '%s_spi_number' % me.parent.from_interface.name -*/ 45 /*- set _irq_spi = configuration[me.parent.from_instance.name].get(spi_attr) -*/ 46 /*- if (isinstance(_irq_spi, numbers.Integral)) and (_irq_spi == 0) -*/ 47 /*- set _irq = _irq + 32 -*/ 48 /*- endif -*/ 49 /*- set irq = alloc('irq', seL4_IRQHandler, number=_irq, notification=my_cnode[ntfn]) -*/ 50/*- elif type in ['arm'] -*/ 51 /*- set attr = '%s_irq_trigger' % me.parent.from_interface.name -*/ 52 /*- set trigger = configuration[me.parent.from_instance.name].get(attr, "level") -*/ 53 /*- if trigger == "level" -*/ 54 /*- set trigger = seL4_ARM_IRQ_LEVEL -*/ 55 /*- set sel4_trigger_param = 0 -*/ 56 /*- elif trigger == "edge" -*/ 57 /*- set trigger = seL4_ARM_IRQ_EDGE -*/ 58 /*- set sel4_trigger_param = 1 -*/ 59 /*- else -*/ 60 /*? 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))) ?*/ 61 /*- endif -*/ 62 /*- set attr = '%s_irq_number' % me.parent.from_interface.name -*/ 63 /*- set _irq = configuration[me.parent.from_instance.name].get(attr) -*/ 64 /*- if _irq is none -*/ 65 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not defined' % (me.parent.from_instance.name, attr))) ?*/ 66 /*- endif -*/ 67 /*- if not isinstance(_irq, numbers.Integral) -*/ 68 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 69 /*- endif -*/ 70 /*- set attr = '%s_irq_target' % me.parent.from_interface.name -*/ 71 /*- set target = configuration[me.parent.from_instance.name].get(attr, 0) -*/ 72 /*- if not isinstance(target, numbers.Integral) -*/ 73 /*? raise(TemplateError('Setting %s.%s that should specify a target core is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 74 /*- endif -*/ 75 /*- set irq = alloc('irq', seL4_IRQHandler, number=_irq, trigger=trigger, target=target, notification=my_cnode[ntfn]) -*/ 76/*- elif type in ['ioapic','isa','pci'] -*/ 77 /*- if type == 'isa' -*/ 78 /*- set level = 0 -*/ 79 /*- set polarity = 0 -*/ 80 /*- elif type == 'pci' -*/ 81 /*- set level = 1 -*/ 82 /*- set polarity = 1 -*/ 83 /*- else -*/ 84 /*- set attr = '%s_irq_level' % me.parent.from_interface.name -*/ 85 /*- set level = configuration[me.parent.from_instance.name].get(attr) -*/ 86 /*- if level is none -*/ 87 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt level is not defined' % (me.parent.from_instance.name, attr))) ?*/ 88 /*- endif -*/ 89 /*- if not isinstance(level, numbers.Integral) -*/ 90 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt level is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 91 /*- endif -*/ 92 /*- set attr = '%s_irq_polarity' % me.parent.from_interface.name -*/ 93 /*- set polarity = configuration[me.parent.from_instance.name].get(attr) -*/ 94 /*- if polarity is none -*/ 95 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt polarity is not defined' % (me.parent.from_instance.name, attr))) ?*/ 96 /*- endif -*/ 97 /*- if not isinstance(polarity, numbers.Integral) -*/ 98 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt polarity is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 99 /*- endif -*/ 100 /*- endif -*/ 101 /*- set attr = '%s_irq_ioapic' % me.parent.from_interface.name -*/ 102 /*- set ioapic = configuration[me.parent.from_instance.name].get(attr) -*/ 103 /*- if ioapic is none -*/ 104 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC controller number is not defined' % (me.parent.from_instance.name, attr))) ?*/ 105 /*- endif -*/ 106 /*- if not isinstance(ioapic, numbers.Integral) -*/ 107 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC controller number is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 108 /*- endif -*/ 109 /*- set attr = '%s_irq_ioapic_pin' % me.parent.from_interface.name -*/ 110 /*- set ioapic_pin = configuration[me.parent.from_instance.name].get(attr) -*/ 111 /*- if ioapic_pin is none -*/ 112 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC pin number is not defined' % (me.parent.from_instance.name, attr))) ?*/ 113 /*- endif -*/ 114 /*- if not isinstance(ioapic_pin, numbers.Integral) -*/ 115 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC pin number is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 116 /*- endif -*/ 117 /*- set attr = '%s_irq_vector' % me.parent.from_interface.name -*/ 118 /*- set vector = configuration[me.parent.from_instance.name].get(attr) -*/ 119 /*- if vector is none -*/ 120 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not defined' % (me.parent.from_instance.name, attr))) ?*/ 121 /*- endif -*/ 122 /*- if not isinstance(vector, numbers.Integral) -*/ 123 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 124 /*- endif -*/ 125 /*- set irq = alloc('irq', seL4_IRQHandler, vector=vector, ioapic=ioapic, ioapic_pin=ioapic_pin, level=level, polarity=polarity, notification=my_cnode[ntfn]) -*/ 126/*- elif type == 'msi' -*/ 127 /*- set attr = '%s_irq_handle' % me.parent.from_interface.name -*/ 128 /*- set handle = configuration[me.parent.from_instance.name].get(attr) -*/ 129 /*- if handle is none -*/ 130 /*? raise(TemplateError('Setting %s.%s that should specify an MSI handle is not defined' % (me.parent.from_instance.name, attr))) ?*/ 131 /*- endif -*/ 132 /*- if not isinstance(handle, numbers.Integral) -*/ 133 /*? raise(TemplateError('Setting %s.%s that should specify an MSI handle is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 134 /*- endif -*/ 135 /*- set attr = '%s_irq_pci_bus' % me.parent.from_interface.name -*/ 136 /*- set pci_bus = configuration[me.parent.from_instance.name].get(attr) -*/ 137 /*- if pci_bus is none -*/ 138 /*? raise(TemplateError('Setting %s.%s that should specify a PCI bus is not defined' % (me.parent.from_instance.name, attr))) ?*/ 139 /*- endif -*/ 140 /*- if not isinstance(pci_bus, numbers.Integral) -*/ 141 /*? raise(TemplateError('Setting %s.%s that should specify a PCI bus is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 142 /*- endif -*/ 143 /*- set attr = '%s_irq_pci_dev' % me.parent.from_interface.name -*/ 144 /*- set pci_dev = configuration[me.parent.from_instance.name].get(attr) -*/ 145 /*- if pci_dev is none -*/ 146 /*? raise(TemplateError('Setting %s.%s that should specify a PCI device is not defined' % (me.parent.from_instance.name, attr))) ?*/ 147 /*- endif -*/ 148 /*- if not isinstance(pci_dev, numbers.Integral) -*/ 149 /*? raise(TemplateError('Setting %s.%s that should specify a PCI device is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 150 /*- endif -*/ 151 /*- set attr = '%s_irq_pci_fun' % me.parent.from_interface.name -*/ 152 /*- set pci_fun = configuration[me.parent.from_instance.name].get(attr) -*/ 153 /*- if pci_fun is none -*/ 154 /*? raise(TemplateError('Setting %s.%s that should specify a PCI function is not defined' % (me.parent.from_instance.name, attr))) ?*/ 155 /*- endif -*/ 156 /*- if not isinstance(pci_fun, numbers.Integral) -*/ 157 /*? raise(TemplateError('Setting %s.%s that should specify a PCI function is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 158 /*- endif -*/ 159 /*- set attr = '%s_irq_vector' % me.parent.from_interface.name -*/ 160 /*- set vector = configuration[me.parent.from_instance.name].get(attr) -*/ 161 /*- if vector is none -*/ 162 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not defined' % (me.parent.from_instance.name, attr))) ?*/ 163 /*- endif -*/ 164 /*- if not isinstance(vector, numbers.Integral) -*/ 165 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 166 /*- endif -*/ 167 /*- 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]) -*/ 168/*- else -*/ 169 /*? raise(TemplateError('Unknown irq type specified by %s.%s' % (me.parent.from_instance.name, type_attr))) ?*/ 170/*- endif -*/ 171 172/*# Add an entry to the allocated_irqs ELF section #*/ 173/*- set irq_struct_name = '%s_irq' % me.interface.name -*/ 174static allocated_irq_t /*? irq_struct_name ?*/ = { 175 .irq_handler = /*? irq ?*/, 176/*- if type == 'simple' -*/ 177 .irq = { .type = PS_INTERRUPT, .irq = { .number = /*? _irq ?*/ }}, 178/*- elif type in ['ioapic','isa','pci'] -*/ 179 .irq = { .type = PS_IOAPIC, .ioapic = { .ioapic = /*? ioapic ?*/, .pin = /*? ioapic_pin ?*/, 180 .level = /*? level ?*/, .polarity = /*? polarity ?*/, 181 .vector = /*? vector ?*/ }}, 182/*- elif type == 'msi' -*/ 183 .irq = { .type = PS_MSI, .msi = { .pci_bus = /*? pci_bus ?*/, .pci_dev = /*? pci_dev ?*/, 184 .pci_func = /*? pci_fun ?*/, .handle = /*? handle ?*/, 185 .vector = /*? vector ?*/ }}, 186/*- elif type == 'arm' -*/ 187 .irq = { .type = PS_TRIGGER, .cpu = { .trigger = /*? trigger.value ?*/, .cpu_idx= /*? target ?*/, .number = /*? _irq ?*/ }}, 188/*- endif -*/ 189 .is_allocated = false, 190 .callback_fn = NULL, 191 .callback_data = NULL 192}; 193USED SECTION("_allocated_irqs") 194allocated_irq_t * /*? irq_struct_name ?*/_ptr = &/*? irq_struct_name ?*/; 195 196int /*? me.interface.name ?*/_poll(void) { 197 assert(!"not implemented for this connector"); 198 return 0; 199} 200 201void /*? me.interface.name ?*/_wait(void) { 202 assert(!"not implemented for this connector"); 203 while (true); 204} 205 206int /*? me.interface.name ?*/_reg_callback(void (*callback)(void*) UNUSED, 207 void *arg UNUSED) { 208 assert(!"not implemented for this connector"); 209 return -1; 210} 211 212 213static int /*? me.interface.name ?*/_acknowledge_cb(UNUSED void* cookie) { 214 return seL4_IRQHandler_Ack(/*? irq ?*/); 215} 216 217/*# Add an entry to the global_notification_irqs ELF section #*/ 218/*- set irq_handler_struct_name = '%s_irq_handler' % me.interface.name -*/ 219static global_notification_irq_handler_t /*? irq_handler_struct_name ?*/ = { 220 .badge = /*? badge ?*/, 221 .ack_fun = /*? me.interface.name ?*/_acknowledge_cb, 222 .allocated_ref = &/*? irq_struct_name ?*/, 223}; 224 225USED SECTION("_global_notification_irqs") 226global_notification_irq_handler_t * /*? irq_handler_struct_name ?*/_ptr = &/*? irq_handler_struct_name ?*/; 227 228// Set the badge of the IRQHandler. 229static void __attribute__((constructor)) register_connector(void) { 230 int error = seL4_IRQHandler_SetNotification(/*? irq ?*/, /*? notification_origin ?*/); 231 if (error) { 232 assert(!"Failed to pair IRQ handler with notification"); 233 } 234} 235 236