1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef __ISR_H
18 #define __ISR_H
19 
20 #include <stdbool.h>
21 #include <stdint.h>
22 
23 #include <cpu.h>
24 #include <list.h>
25 #include <util.h>
26 #include <seos.h>
27 
28 struct ChainedInterrupt {
29     link_t isrs;
30 
31     void (*const enable)(struct ChainedInterrupt *);
32     void (*const disable)(struct ChainedInterrupt *);
33 };
34 
35 struct ChainedIsr {
36     link_t node;
37     bool (*func)(struct ChainedIsr *);
38     uint16_t tid;
39 };
40 
chainIsr(struct ChainedInterrupt * interrupt,struct ChainedIsr * isr)41 static inline void chainIsr(struct ChainedInterrupt *interrupt, struct ChainedIsr *isr)
42 {
43     interrupt->disable(interrupt);
44     list_add_tail(&interrupt->isrs, &isr->node);
45     interrupt->enable(interrupt);
46 }
47 
unchainIsr(struct ChainedInterrupt * interrupt,struct ChainedIsr * isr)48 static inline void unchainIsr(struct ChainedInterrupt *interrupt, struct ChainedIsr *isr)
49 {
50     interrupt->disable(interrupt);
51     isr->tid = 0;
52     list_delete(&isr->node);
53     if (!list_is_empty(&interrupt->isrs))
54         interrupt->enable(interrupt);
55 }
56 
dispatchIsr(struct ChainedInterrupt * interrupt)57 static inline bool dispatchIsr(struct ChainedInterrupt *interrupt)
58 {
59     struct link_t *cur, *tmp;
60     bool handled = false;
61     uint16_t oldTid = osGetCurrentTid();
62 
63     list_iterate(&interrupt->isrs, cur, tmp) {
64         struct ChainedIsr *curIsr = container_of(cur, struct ChainedIsr, node);
65         osSetCurrentTid(curIsr->tid);
66         handled = curIsr->func(curIsr);
67         if (handled)
68             break;
69     }
70     osSetCurrentTid(oldTid);
71 
72     return handled;
73 }
74 
unchainIsrAll(struct ChainedInterrupt * interrupt,uint32_t tid)75 static inline int unchainIsrAll(struct ChainedInterrupt *interrupt, uint32_t tid)
76 {
77     int count = 0;
78     struct link_t *cur, *tmp;
79 
80     list_iterate(&interrupt->isrs, cur, tmp) {
81         struct ChainedIsr *curIsr = container_of(cur, struct ChainedIsr, node);
82         if (curIsr->tid == tid) {
83             unchainIsr(interrupt, curIsr);
84             count++;
85         }
86     }
87 
88     return count;
89 }
90 
91 #endif /* __ISR_H */
92