blob: 582a06fffa3ada9e3d6ec29adab834970c6b45c3 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
/* SPDX-License-Identifier: copyleft-next-0.3.1 */
/* Copyright 2023, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
/**
* @file irq.c
* Common IRQ handling stuff implementations.
*/
#include <kmi/irq.h>
#include <kmi/bkl.h>
#include <kmi/pmem.h>
#include <kmi/debug.h>
#include <kmi/assert.h>
#include <kmi/notify.h>
#include <kmi/string.h>
#include <arch/irq.h>
/** Hold maximum IRQ id supported by system. */
static size_t max_irq;
/** Hold map of IRD ID -> thread id. @todo process id? */
static id_t *irq_map;
void init_irq(void *fdt)
{
/** @todo check arch max irq and adjust accordingly */
irq_map = (id_t *)alloc_page(MM_O0);
memset(irq_map, 0, order_size(MM_O0));
max_irq = order_size(MM_O0) / sizeof(irq_map[0]);
setup_irq(fdt);
}
stat_t register_irq(struct tcb *t, irq_t id)
{
if (id >= max_irq)
return ERR_INVAL;
if (irq_map[id])
return ERR_EXT;
irq_map[id] = t->tid;
return activate_irq(id);
}
stat_t unregister_irq(struct tcb *t, irq_t id)
{
id_t tid = irq_map[id];
if (tid != t->tid)
return ERR_PERM;
irq_map[id] = 0;
return deactivate_irq(id);
}
void handle_irq()
{
bkl_lock();
irq_t id = get_irq();
assert(id < max_irq);
id_t tid = irq_map[id];
if (!tid) {
bug("unregistered irq %llu\n", (unsigned long long)id);
return;
}
struct tcb *t = get_tcb(tid);
if (!t || orphan(t)) {
info("tcb %llu dead at irq %llu\n",
(unsigned long long)tid,
(unsigned long long)id);
/* unregister irq handler */
irq_map[id] = 0;
bkl_unlock();
return;
}
disable_irqs();
notify(t, NOTIFY_IRQ);
bkl_unlock();
}
|