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#include <simple/simple.h>
15#include <vspace/vspace.h>
16#include <vka/vka.h>
17#include <sel4platsupport/pmem.h>
18#include <sel4utils/vspace.h>
19#include <sel4platsupport/timer.h>
20#include <rumprun/init_data.h>
21
22enum serial_variant {
23    SERIAL_SERVER,
24    SERIAL_INTERFACE,
25};
26
27enum timer_variant {
28    TIMER_LTIMER,
29    TIMER_INTERFACE,
30};
31
32enum pci_config_variant {
33    PCI_CONFIG_HW,
34    PCI_CONFIG_INTERFACE
35};
36
37
38typedef struct serial_config {
39    enum serial_variant serial;
40    void (*putchar)(int c);
41    seL4_CPtr ep;
42} serial_config_t;
43
44typedef struct timer_config {
45    enum timer_variant timer;
46    seL4_CPtr timer_ntfn;
47    uint64_t tsc_freq;
48    union {
49        struct {
50            int (*oneshot_relative)(int tid, uint64_t ns);
51            uint64_t (*time)(void);
52        } interface;
53        struct {
54            ltimer_t ltimer;
55        } ltimer;
56    };
57} timer_config_t;
58
59typedef struct pci_config_config {
60    enum pci_config_variant pci_config;
61    int32_t (*pci_config_read32)(uint8_t bus,  uint8_t dev,  uint8_t fun,  unsigned int offset);
62    void (*pci_config_write32)(uint8_t bus,  uint8_t dev,  uint8_t fun,  unsigned int offset,  uint32_t val);
63} pci_config_config_t;
64
65typedef struct ethernet_intr_config {
66    int (*eth_irq_acknowledge)(void);
67} ethernet_intr_config_t;
68
69typedef struct custom_simple {
70    const char *cmdline;
71    int priority;
72    bool camkes;
73    simple_t *simple;
74    size_t rumprun_memory_size;
75    serial_config_t serial_config;
76    timer_config_t timer_config;
77    pci_config_config_t pci_config_config;
78    ethernet_intr_config_t ethernet_intr_config;
79    seL4_CPtr rpc_ep;
80    void *stdio_buf[3];
81    seL4_CPtr stdio_ep[3];
82    void (*get_char_handler)(void);
83} custom_simple_t;
84
85
86static inline bool is_ltimer(custom_simple_t *custom_simple)
87{
88    return custom_simple->timer_config.timer == TIMER_LTIMER;
89}
90
91static inline bool is_hw_serial(custom_simple_t *custom_simple)
92{
93    return custom_simple->serial_config.serial == SERIAL_SERVER;
94}
95
96static inline bool is_hw_pci_config(custom_simple_t *custom_simple)
97{
98    return custom_simple->pci_config_config.pci_config == PCI_CONFIG_HW;
99}
100
101static inline int custom_irq_from_pci_device(custom_simple_t *custom_simple,
102                                             uint32_t bus, uint32_t dev, uint32_t function, ps_irq_t *irq)
103{
104    if (custom_simple->camkes || irq == NULL) {
105        return -1;
106    }
107
108    init_data_t *init_data = custom_simple->simple->data;
109    for (int i = 0; i < MAX_NUM_PCI_DEVICES; i++) {
110        if (bus == init_data->interrupt_list[i].bus &&
111            dev == init_data->interrupt_list[i].dev &&
112            function == init_data->interrupt_list[i].function) {
113            *irq = init_data->interrupt_list[i].irq;
114            return 0;
115        }
116    }
117    return -1;
118
119}
120
121int custom_simple_vspace_bootstrap_frames(custom_simple_t *custom_simple, vspace_t *vspace,
122                                          sel4utils_alloc_data_t *alloc_data,
123                                          vka_t *vka);
124int custom_get_num_regions(custom_simple_t *custom_simple);
125int custom_get_region_list(custom_simple_t *custom_simple, int num_regions, pmem_region_t *regions);
126void rump_irq_handle(int intr, int soft_intr);
127void preinit_rumprun(custom_simple_t *custom_simple);
128int init_rumprun(custom_simple_t *custom_simple);
129
130int custom_get_priority(custom_simple_t *custom_simple);
131const char *custom_get_cmdline(custom_simple_t *custom_simple);
132