1235633Sdim/*
2221345Sdim * Copyright 2017, Data61
3193323Sed * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4193323Sed * ABN 41 687 119 230.
5193323Sed *
6193323Sed * This software may be distributed and modified according to the terms of
7221345Sdim * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8193323Sed * See "LICENSE_BSD2.txt" for details.
9193323Sed *
10193323Sed * @TAG(DATA61_BSD)
11193323Sed */
12193323Sed
13221345Sdim#pragma once
14193323Sed
15193323Sed#include <autoconf.h>
16193323Sed
17193323Sed#include <assert.h>
18193323Sed#include <sel4/sel4.h>
19193323Sed#include <stdlib.h>
20221345Sdim#include <utils/util.h>
21193323Sed#include <vka/cspacepath_t.h>
22193323Sed
23224145Sdim/* Simple does not address initial null caps, including seL4_CapNull */
24224145Sdim#ifdef CONFIG_IOMMU
25193323Sed#define SIMPLE_SKIPPED_INIT_CAPS 1
26202878Srdivacky#else
27202878Srdivacky/* seL4_CapIOSpace is null if IOMMU isn't supported */
28193323Sed#define SIMPLE_SKIPPED_INIT_CAPS 2
29263509Sdim#endif
30263509Sdim
31263509Sdim/**
32263509Sdim * Request a cap to the IOPorts
33193323Sed *
34193323Sed * @param data cookie for the underlying implementation
35193323Sed * @param start port number that a cap is needed to
36226890Sdim * @param end port number that a cap is needed to
37226890Sdim * @param root The CNode in which to put this cap
38226890Sdim * @param dest The index within the CNode to put the cap
39226890Sdim * @param depth of index
40235633Sdim */
41235633Sdimtypedef 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);
42226890Sdim
43226890Sdim/**
44235633Sdim * Request a cap to a specific MSI IRQ number on the system
45235633Sdim *
46235633Sdim * @param irq the msi irq number to get the cap for
47235633Sdim * @param data cookie for the underlying implementation
48235633Sdim * @param the CNode in which to put this cap
49226890Sdim * @param the index within the CNode to put cap
50226890Sdim * @param Depth of index
51226890Sdim */
52226890Sdimtypedef seL4_Error (*arch_simple_get_msi_fn)(void *data, seL4_CNode root, seL4_Word index,
53226890Sdim                                             uint8_t depth, seL4_Word pci_bus, seL4_Word pci_dev,
54226890Sdim                                             seL4_Word pci_func, seL4_Word handle,
55226890Sdim                                             seL4_Word vector);
56226890Sdim
57226890Sdimtypedef seL4_Error (*arch_simple_get_ioapic_fn)(void *data, seL4_CNode root, seL4_Word index,
58226890Sdim                                               uint8_t depth, seL4_Word ioapic, seL4_Word pin,
59226890Sdim                                               seL4_Word level, seL4_Word polarity,
60226890Sdim                                               seL4_Word vector);
61226890Sdim
62226890Sdim/**
63226890Sdim * Request a cap to a specific IRQ number on the system
64226890Sdim *
65226890Sdim * @param irq the irq number to get the cap for
66226890Sdim * @param data cookie for the underlying implementation
67235633Sdim * @param the CNode in which to put this cap
68235633Sdim * @param the index within the CNode to put cap
69226890Sdim * @param Depth of index
70226890Sdim */
71235633Sdimtypedef seL4_Error (*arch_simple_get_IRQ_handler_fn)(void *data, int irq, seL4_CNode cnode, seL4_Word index,
72235633Sdim                                                     uint8_t depth);
73235633Sdim
74235633Sdim#ifdef CONFIG_IOMMU
75235633Sdim/**
76235633Sdim * Get the IO space capability for the specified PCI device and domain ID
77235633Sdim *
78235633Sdim * @param data cookie for the underlying implementation
79235633Sdim * @param domainID domain ID to request
80235633Sdim * @param deviceID PCI device ID
81235633Sdim * @param path Path to where to put this cap
82235633Sdim *
83235633Sdim*/
84235633Sdimtypedef seL4_Error (*arch_simple_get_iospace_fn)(void *data, uint16_t domainID, uint16_t deviceID,
85235633Sdim                                                 cspacepath_t *path);
86235633Sdim
87226890Sdim#endif
88226890Sdim
89226890Sdimtypedef struct arch_simple {
90226890Sdim    void *data;
91226890Sdim    arch_simple_get_IOPort_cap_fn IOPort_cap;
92226890Sdim#ifdef CONFIG_IOMMU
93226890Sdim    arch_simple_get_iospace_fn iospace;
94226890Sdim#endif
95226890Sdim    arch_simple_get_msi_fn msi;
96226890Sdim    arch_simple_get_IRQ_handler_fn irq;
97226890Sdim    arch_simple_get_ioapic_fn ioapic;
98226890Sdim} arch_simple_t;
99226890Sdim
100226890Sdimstatic inline seL4_Error
101252723Sdimarch_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)
102252723Sdim{
103252723Sdim    if (!arch_simple) {
104252723Sdim        ZF_LOGE("Arch-simple is NULL");
105252723Sdim        return seL4_InvalidArgument;
106252723Sdim    }
107226890Sdim
108193323Sed    if (!arch_simple->IOPort_cap) {
109193323Sed        ZF_LOGE("%s not implemented", __FUNCTION__);
110193323Sed        return seL4_InvalidArgument;
111193323Sed    }
112193323Sed
113193323Sed    return arch_simple->IOPort_cap(arch_simple->data, start_port, end_port, root, dest, depth);
114193323Sed}
115193323Sed
116193323Sedstatic inline seL4_Error
117193323Sedarch_simple_get_msi(arch_simple_t *arch_simple, cspacepath_t path, seL4_Word pci_bus,
118221345Sdim                    seL4_Word pci_dev, seL4_Word pci_func, seL4_Word handle,
119221345Sdim                    seL4_Word vector)
120193323Sed{
121193323Sed    if (!arch_simple) {
122221345Sdim        ZF_LOGE("Arch-simple is NULL");
123193323Sed        return seL4_InvalidArgument;
124193323Sed    }
125221345Sdim
126221345Sdim    if (!arch_simple->msi) {
127193323Sed        ZF_LOGE("%s not implemented", __FUNCTION__);
128193323Sed    }
129193323Sed
130193323Sed    return arch_simple->msi(arch_simple->data, path.root, path.capPtr, path.capDepth, pci_bus,
131193323Sed                            pci_dev, pci_func, handle, vector);
132193323Sed}
133193323Sed
134193323Sedstatic inline seL4_Error
135193323Sedarch_simple_get_ioapic(arch_simple_t *arch_simple, cspacepath_t path, seL4_Word ioapic,
136193323Sed                       seL4_Word pin, seL4_Word level, seL4_Word polarity,
137193323Sed                       seL4_Word vector)
138193323Sed{
139193323Sed    if (!arch_simple) {
140193323Sed        ZF_LOGE("Arch-simple is NULL");
141193323Sed        return seL4_InvalidArgument;
142193323Sed    }
143193323Sed
144193323Sed    if (!arch_simple->ioapic) {
145193323Sed        ZF_LOGE("%s not implemented", __FUNCTION__);
146193323Sed    }
147193323Sed
148193323Sed    return arch_simple->ioapic(arch_simple->data, path.root, path.capPtr, path.capDepth, ioapic,
149193323Sed                               pin, level, polarity, vector);
150245431Sdim}
151245431Sdim
152245431Sdim#ifdef CONFIG_IOMMU
153245431Sdimstatic inline seL4_CPtr
154263509Sdimarch_simple_get_iospace(arch_simple_t *arch_simple, uint16_t domainID, uint16_t deviceID, cspacepath_t *path)
155263509Sdim{
156263509Sdim    if (!arch_simple) {
157263509Sdim        ZF_LOGE("Arch-simple is NULL");
158263509Sdim        return seL4_CapNull;
159263509Sdim    }
160263509Sdim    if (!arch_simple->iospace) {
161263509Sdim        ZF_LOGE("%s not implemented", __FUNCTION__);
162263509Sdim        return seL4_CapNull;
163263509Sdim    }
164245431Sdim
165245431Sdim    return arch_simple->iospace(arch_simple->data, domainID, deviceID, path);
166245431Sdim}
167245431Sdim#endif
168245431Sdim
169245431Sdim