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#pragma once 14 15#include <autoconf.h> 16 17#include <assert.h> 18#include <sel4/sel4.h> 19#include <stdlib.h> 20#include <utils/util.h> 21#include <vka/cspacepath_t.h> 22 23/* Simple does not address initial null caps, including seL4_CapNull */ 24#ifdef CONFIG_IOMMU 25#define SIMPLE_SKIPPED_INIT_CAPS 1 26#else 27/* seL4_CapIOSpace is null if IOMMU isn't supported */ 28#define SIMPLE_SKIPPED_INIT_CAPS 2 29#endif 30 31/** 32 * Request a cap to the IOPorts 33 * 34 * @param data cookie for the underlying implementation 35 * @param start port number that a cap is needed to 36 * @param end port number that a cap is needed to 37 * @param root The CNode in which to put this cap 38 * @param dest The index within the CNode to put the cap 39 * @param depth of index 40 */ 41typedef seL4_Error (*arch_simple_get_IOPort_cap_fn)(void *data, uint16_t start_port, uint16_t end_port, seL4_Word root, seL4_Word dest, seL4_Word depth); 42 43/** 44 * Request a cap to a specific MSI IRQ number on the system 45 * 46 * @param irq the msi irq number to get the cap for 47 * @param data cookie for the underlying implementation 48 * @param the CNode in which to put this cap 49 * @param the index within the CNode to put cap 50 * @param Depth of index 51 */ 52typedef seL4_Error (*arch_simple_get_msi_fn)(void *data, seL4_CNode root, seL4_Word index, 53 uint8_t depth, seL4_Word pci_bus, seL4_Word pci_dev, 54 seL4_Word pci_func, seL4_Word handle, 55 seL4_Word vector); 56 57typedef seL4_Error (*arch_simple_get_ioapic_fn)(void *data, seL4_CNode root, seL4_Word index, 58 uint8_t depth, seL4_Word ioapic, seL4_Word pin, 59 seL4_Word level, seL4_Word polarity, 60 seL4_Word vector); 61 62/** 63 * Request a cap to a specific IRQ number on the system 64 * 65 * @param irq the irq number to get the cap for 66 * @param data cookie for the underlying implementation 67 * @param the CNode in which to put this cap 68 * @param the index within the CNode to put cap 69 * @param Depth of index 70 */ 71typedef seL4_Error (*arch_simple_get_IRQ_handler_fn)(void *data, int irq, seL4_CNode cnode, seL4_Word index, 72 uint8_t depth); 73 74#ifdef CONFIG_IOMMU 75/** 76 * Get the IO space capability for the specified PCI device and domain ID 77 * 78 * @param data cookie for the underlying implementation 79 * @param domainID domain ID to request 80 * @param deviceID PCI device ID 81 * @param path Path to where to put this cap 82 * 83*/ 84typedef seL4_Error (*arch_simple_get_iospace_fn)(void *data, uint16_t domainID, uint16_t deviceID, 85 cspacepath_t *path); 86 87#endif 88 89typedef struct arch_simple { 90 void *data; 91 arch_simple_get_IOPort_cap_fn IOPort_cap; 92#ifdef CONFIG_IOMMU 93 arch_simple_get_iospace_fn iospace; 94#endif 95 arch_simple_get_msi_fn msi; 96 arch_simple_get_IRQ_handler_fn irq; 97 arch_simple_get_ioapic_fn ioapic; 98} arch_simple_t; 99 100static inline seL4_Error 101arch_simple_get_IOPort_cap(arch_simple_t *arch_simple, uint16_t start_port, uint16_t end_port, seL4_Word root, seL4_Word dest, seL4_Word depth) 102{ 103 if (!arch_simple) { 104 ZF_LOGE("Arch-simple is NULL"); 105 return seL4_InvalidArgument; 106 } 107 108 if (!arch_simple->IOPort_cap) { 109 ZF_LOGE("%s not implemented", __FUNCTION__); 110 return seL4_InvalidArgument; 111 } 112 113 return arch_simple->IOPort_cap(arch_simple->data, start_port, end_port, root, dest, depth); 114} 115 116static inline seL4_Error 117arch_simple_get_msi(arch_simple_t *arch_simple, cspacepath_t path, seL4_Word pci_bus, 118 seL4_Word pci_dev, seL4_Word pci_func, seL4_Word handle, 119 seL4_Word vector) 120{ 121 if (!arch_simple) { 122 ZF_LOGE("Arch-simple is NULL"); 123 return seL4_InvalidArgument; 124 } 125 126 if (!arch_simple->msi) { 127 ZF_LOGE("%s not implemented", __FUNCTION__); 128 } 129 130 return arch_simple->msi(arch_simple->data, path.root, path.capPtr, path.capDepth, pci_bus, 131 pci_dev, pci_func, handle, vector); 132} 133 134static inline seL4_Error 135arch_simple_get_ioapic(arch_simple_t *arch_simple, cspacepath_t path, seL4_Word ioapic, 136 seL4_Word pin, seL4_Word level, seL4_Word polarity, 137 seL4_Word vector) 138{ 139 if (!arch_simple) { 140 ZF_LOGE("Arch-simple is NULL"); 141 return seL4_InvalidArgument; 142 } 143 144 if (!arch_simple->ioapic) { 145 ZF_LOGE("%s not implemented", __FUNCTION__); 146 } 147 148 return arch_simple->ioapic(arch_simple->data, path.root, path.capPtr, path.capDepth, ioapic, 149 pin, level, polarity, vector); 150} 151 152#ifdef CONFIG_IOMMU 153static inline seL4_CPtr 154arch_simple_get_iospace(arch_simple_t *arch_simple, uint16_t domainID, uint16_t deviceID, cspacepath_t *path) 155{ 156 if (!arch_simple) { 157 ZF_LOGE("Arch-simple is NULL"); 158 return seL4_CapNull; 159 } 160 if (!arch_simple->iospace) { 161 ZF_LOGE("%s not implemented", __FUNCTION__); 162 return seL4_CapNull; 163 } 164 165 return arch_simple->iospace(arch_simple->data, domainID, deviceID, path); 166} 167#endif 168 169