1/* 2 * Copyright 2017, 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/*- set ntfn_obj = alloc_obj('ntfn', seL4_NotificationObject) -*/ 24/*- set ntfn = alloc_cap('ntfn', ntfn_obj, read=True) -*/ 25 26/*- set type_attr = '%s_irq_type' % me.parent.from_interface.name -*/ 27/*- set type = configuration[me.parent.from_instance.name].get(type_attr, 'simple') -*/ 28 29/*- if type == 'simple' -*/ 30 /*- set attr = '%s_irq_number' % me.parent.from_interface.name -*/ 31 /*- set _irq = configuration[me.parent.from_instance.name].get(attr) -*/ 32 /*- if _irq is none -*/ 33 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not defined' % (me.parent.from_instance.name, attr))) ?*/ 34 /*- endif -*/ 35 /*- if not isinstance(_irq, numbers.Integral) -*/ 36 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 37 /*- endif -*/ 38 /*- set spi_attr = '%s_spi_number' % me.parent.from_interface.name -*/ 39 /*- set _irq_spi = configuration[me.parent.from_instance.name].get(spi_attr) -*/ 40 /*- if (isinstance(_irq_spi, numbers.Integral)) and (_irq_spi == 0) -*/ 41 /*- set _irq = _irq + 32 -*/ 42 /*- endif -*/ 43 /*- set irq = alloc('irq', seL4_IRQHandler, number=_irq, notification=my_cnode[ntfn]) -*/ 44/*- elif type in ['arm'] -*/ 45 /*- set attr = '%s_irq_trigger' % me.parent.from_interface.name -*/ 46 /*- set trigger = configuration[me.parent.from_instance.name].get(attr, "level") -*/ 47 /*- if trigger == "level" -*/ 48 /*- set trigger = seL4_ARM_IRQ_LEVEL -*/ 49 /*- set sel4_trigger_param = 0 -*/ 50 /*- elif trigger == "edge" -*/ 51 /*- set trigger = seL4_ARM_IRQ_EDGE -*/ 52 /*- set sel4_trigger_param = 1 -*/ 53 /*- else -*/ 54 /*? 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))) ?*/ 55 /*- endif -*/ 56 /*- set attr = '%s_irq_number' % me.parent.from_interface.name -*/ 57 /*- set _irq = configuration[me.parent.from_instance.name].get(attr) -*/ 58 /*- if _irq is none -*/ 59 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not defined' % (me.parent.from_instance.name, attr))) ?*/ 60 /*- endif -*/ 61 /*- if not isinstance(_irq, numbers.Integral) -*/ 62 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ number is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 63 /*- endif -*/ 64 /*- set attr = '%s_irq_target' % me.parent.from_interface.name -*/ 65 /*- set target = configuration[me.parent.from_instance.name].get(attr, 0) -*/ 66 /*- if not isinstance(target, numbers.Integral) -*/ 67 /*? raise(TemplateError('Setting %s.%s that should specify a target core is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 68 /*- endif -*/ 69 /*- set irq = alloc('irq', seL4_IRQHandler, number=_irq, trigger=trigger, target=target, notification=my_cnode[ntfn]) -*/ 70/*- elif type in ['ioapic','isa','pci'] -*/ 71 /*- if type == 'isa' -*/ 72 /*- set level = 0 -*/ 73 /*- set polarity = 0 -*/ 74 /*- elif type == 'pci' -*/ 75 /*- set level = 1 -*/ 76 /*- set polarity = 1 -*/ 77 /*- else -*/ 78 /*- set attr = '%s_irq_level' % me.parent.from_interface.name -*/ 79 /*- set level = configuration[me.parent.from_instance.name].get(attr) -*/ 80 /*- if level is none -*/ 81 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt level is not defined' % (me.parent.from_instance.name, attr))) ?*/ 82 /*- endif -*/ 83 /*- if not isinstance(level, numbers.Integral) -*/ 84 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt level is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 85 /*- endif -*/ 86 /*- set attr = '%s_irq_polarity' % me.parent.from_interface.name -*/ 87 /*- set polarity = configuration[me.parent.from_instance.name].get(attr) -*/ 88 /*- if polarity is none -*/ 89 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt polarity is not defined' % (me.parent.from_instance.name, attr))) ?*/ 90 /*- endif -*/ 91 /*- if not isinstance(polarity, numbers.Integral) -*/ 92 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC interrupt polarity is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 93 /*- endif -*/ 94 /*- endif -*/ 95 /*- set attr = '%s_irq_ioapic' % me.parent.from_interface.name -*/ 96 /*- set ioapic = configuration[me.parent.from_instance.name].get(attr) -*/ 97 /*- if ioapic is none -*/ 98 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC controller number is not defined' % (me.parent.from_instance.name, attr))) ?*/ 99 /*- endif -*/ 100 /*- if not isinstance(ioapic, numbers.Integral) -*/ 101 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC controller number is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 102 /*- endif -*/ 103 /*- set attr = '%s_irq_ioapic_pin' % me.parent.from_interface.name -*/ 104 /*- set ioapic_pin = configuration[me.parent.from_instance.name].get(attr) -*/ 105 /*- if ioapic_pin is none -*/ 106 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC pin number is not defined' % (me.parent.from_instance.name, attr))) ?*/ 107 /*- endif -*/ 108 /*- if not isinstance(ioapic_pin, numbers.Integral) -*/ 109 /*? raise(TemplateError('Setting %s.%s that should specify an IOAPIC pin number is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 110 /*- endif -*/ 111 /*- set attr = '%s_irq_vector' % me.parent.from_interface.name -*/ 112 /*- set vector = configuration[me.parent.from_instance.name].get(attr) -*/ 113 /*- if vector is none -*/ 114 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not defined' % (me.parent.from_instance.name, attr))) ?*/ 115 /*- endif -*/ 116 /*- if not isinstance(vector, numbers.Integral) -*/ 117 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 118 /*- endif -*/ 119 /*- set irq = alloc('irq', seL4_IRQHandler, vector=vector, ioapic=ioapic, ioapic_pin=ioapic_pin, level=level, polarity=polarity, notification=my_cnode[ntfn]) -*/ 120/*- elif type == 'msi' -*/ 121 /*- set attr = '%s_irq_handle' % me.parent.from_interface.name -*/ 122 /*- set handle = configuration[me.parent.from_instance.name].get(attr) -*/ 123 /*- if handle is none -*/ 124 /*? raise(TemplateError('Setting %s.%s that should specify an MSI handle is not defined' % (me.parent.from_instance.name, attr))) ?*/ 125 /*- endif -*/ 126 /*- if not isinstance(handle, numbers.Integral) -*/ 127 /*? raise(TemplateError('Setting %s.%s that should specify an MSI handle is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 128 /*- endif -*/ 129 /*- set attr = '%s_irq_pci_bus' % me.parent.from_interface.name -*/ 130 /*- set pci_bus = configuration[me.parent.from_instance.name].get(attr) -*/ 131 /*- if pci_bus is none -*/ 132 /*? raise(TemplateError('Setting %s.%s that should specify a PCI bus is not defined' % (me.parent.from_instance.name, attr))) ?*/ 133 /*- endif -*/ 134 /*- if not isinstance(pci_bus, numbers.Integral) -*/ 135 /*? raise(TemplateError('Setting %s.%s that should specify a PCI bus is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 136 /*- endif -*/ 137 /*- set attr = '%s_irq_pci_dev' % me.parent.from_interface.name -*/ 138 /*- set pci_dev = configuration[me.parent.from_instance.name].get(attr) -*/ 139 /*- if pci_dev is none -*/ 140 /*? raise(TemplateError('Setting %s.%s that should specify a PCI device is not defined' % (me.parent.from_instance.name, attr))) ?*/ 141 /*- endif -*/ 142 /*- if not isinstance(pci_dev, numbers.Integral) -*/ 143 /*? raise(TemplateError('Setting %s.%s that should specify a PCI device is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 144 /*- endif -*/ 145 /*- set attr = '%s_irq_pci_fun' % me.parent.from_interface.name -*/ 146 /*- set pci_fun = configuration[me.parent.from_instance.name].get(attr) -*/ 147 /*- if pci_fun is none -*/ 148 /*? raise(TemplateError('Setting %s.%s that should specify a PCI function is not defined' % (me.parent.from_instance.name, attr))) ?*/ 149 /*- endif -*/ 150 /*- if not isinstance(pci_fun, numbers.Integral) -*/ 151 /*? raise(TemplateError('Setting %s.%s that should specify a PCI function is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 152 /*- endif -*/ 153 /*- set attr = '%s_irq_vector' % me.parent.from_interface.name -*/ 154 /*- set vector = configuration[me.parent.from_instance.name].get(attr) -*/ 155 /*- if vector is none -*/ 156 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not defined' % (me.parent.from_instance.name, attr))) ?*/ 157 /*- endif -*/ 158 /*- if not isinstance(vector, numbers.Integral) -*/ 159 /*? raise(TemplateError('Setting %s.%s that should specify an IRQ vector is not an integer' % (me.parent.from_instance.name, attr))) ?*/ 160 /*- endif -*/ 161 /*- 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]) -*/ 162/*- else -*/ 163 /*? raise(TemplateError('Unknown irq type specified by %s.%s' % (me.parent.from_instance.name, type_attr))) ?*/ 164/*- endif -*/ 165 166/*# Add an entry to the allocated_irqs ELF section #*/ 167/*- set irq_struct_name = '%s_irq' % me.interface.name -*/ 168static allocated_irq_t /*? irq_struct_name ?*/ = { 169 .irq_handler = /*? irq ?*/, 170/*- if type == 'simple' -*/ 171 .irq = { .type = PS_INTERRUPT, .irq = { .number = /*? _irq ?*/ }}, 172/*- elif type in ['ioapic','isa','pci'] -*/ 173 .irq = { .type = PS_IOAPIC, .ioapic = { .ioapic = /*? ioapic ?*/, .pin = /*? ioapic_pin ?*/, 174 .level = /*? level ?*/, .polarity = /*? polarity ?*/, 175 .vector = /*? vector ?*/ }}, 176/*- elif type == 'msi' -*/ 177 .irq = { .type = PS_MSI, .msi = { .pci_bus = /*? pci_bus ?*/, .pci_dev = /*? pci_dev ?*/, 178 .pci_func = /*? pci_fun ?*/, .handle = /*? handle ?*/, 179 .vector = /*? vector ?*/ }}, 180/*- elif type == 'arm' -*/ 181 .irq = { .type = PS_TRIGGER, .cpu = { .trigger = /*? trigger.value ?*/, .cpu_idx= /*? target ?*/, .number = /*? _irq ?*/ }}, 182/*- endif -*/ 183 .is_allocated = false, 184 .callback_fn = NULL, 185 .callback_data = NULL 186}; 187USED SECTION("_allocated_irqs") 188allocated_irq_t * /*? irq_struct_name ?*/_ptr = &/*? irq_struct_name ?*/; 189 190int /*? me.interface.name ?*/_poll(void) { 191 assert(!"not implemented for this connector"); 192 return 0; 193} 194 195void /*? me.interface.name ?*/_wait(void) { 196 assert(!"not implemented for this connector"); 197 while (true); 198} 199 200int /*? me.interface.name ?*/_reg_callback(void (*callback)(void*) UNUSED, 201 void *arg UNUSED) { 202 assert(!"not implemented for this connector"); 203 return -1; 204} 205 206int /*? me.interface.name ?*/_acknowledge(void) { 207 return seL4_IRQHandler_Ack(/*? irq ?*/); 208} 209 210static int /*? me.interface.name ?*/_acknowledge_cb(UNUSED void* cookie) { 211 return seL4_IRQHandler_Ack(/*? irq ?*/); 212} 213 214int /*? me.interface.name ?*/__run(void) { 215 while (true) { 216 seL4_Wait(/*? ntfn ?*/, NULL); 217 if (/*? me.interface.name ?*/_handle && /*? irq_struct_name ?*/.is_allocated) { 218 ZF_LOGF("Both IRQ interface and 'handle' function is in use! " 219 "These are mutually exclusive, use one or the other."); 220 } else if (/*? me.interface.name ?*/_handle) { 221 /*? me.interface.name ?*/_handle(); 222 } else if (/*? irq_struct_name ?*/.is_allocated) { 223 /*? irq_struct_name ?*/.callback_fn(/*? irq_struct_name ?*/.callback_data, 224 /*? me.interface.name ?*/_acknowledge_cb, 225 NULL); 226 } else { 227 ZF_LOGE("No mechanism exists to handle this interrupt, it will be ignored"); 228 } 229 } 230 231 UNREACHABLE(); 232} 233