f1facf91a5a46fe1e3118411c32340c80343d662
[lunaix-os.git] / lunaix-os / arch / i386 / exceptions / i386_isrm.c
1 #include <lunaix/isrm.h>
2 #include <lunaix/spike.h>
3
4 #include <hal/intc.h>
5
6 /*
7     total: 256 ivs
8     0~31: reserved for sys use (x32)
9     32~47: reserved for os use (x16)
10     48~  : free to allocate for external hardware use. (x208)
11 */
12
13 static char iv_bmp[(IV_EX_END - IV_BASE_END) / 8];
14 static isr_cb handlers[TOTAL_IV];
15 static ptr_t ivhand_payload[TOTAL_IV];
16
17 extern void
18 intr_routine_fallback(const isr_param* param);
19
20 void
21 isrm_init()
22 {
23     for (size_t i = 0; i < TOTAL_IV; i++) {
24         handlers[i] = intr_routine_fallback;
25     }
26 }
27
28 static inline int
29 __ivalloc_within(size_t a, size_t b, isr_cb handler)
30 {
31     a = (a - IV_BASE_END);
32     b = (b - IV_BASE_END);
33     u8_t j = a % 8;
34     u8_t k = 0;
35
36     for (size_t i = a / 8; i < b / 8; i++, k += 8) {
37         u8_t chunk = iv_bmp[i];
38
39         if (chunk == 0xff)
40             continue;
41
42         chunk >>= j;
43         while ((chunk & 0x1) && k <= b) {
44             chunk >>= 1;
45             j++;
46             k++;
47         }
48
49         if (k > b) {
50             break;
51         }
52
53         iv_bmp[i] |= 1 << j;
54
55         int iv = IV_BASE_END + i * 8 + j;
56         handlers[iv] = handler ? handler : intr_routine_fallback;
57
58         return iv;
59     }
60
61     return 0;
62 }
63
64 int
65 isrm_ivosalloc(isr_cb handler)
66 {
67     return __ivalloc_within(IV_BASE_END, IV_EX_BEGIN, handler);
68 }
69
70 int
71 isrm_ivexalloc(isr_cb handler)
72 {
73     return __ivalloc_within(IV_EX_BEGIN, IV_EX_END, handler);
74 }
75
76 void
77 isrm_ivfree(int iv)
78 {
79     assert(iv < 256);
80
81     if (iv >= IV_BASE_END) {
82         iv_bmp[(iv - IV_BASE_END) / 8] &= ~(1 << ((iv - IV_BASE_END) % 8));
83     }
84
85     handlers[iv] = intr_routine_fallback;
86 }
87
88 int
89 isrm_bindirq(int irq, isr_cb irq_handler)
90 {
91     int iv;
92     if (!(iv = isrm_ivexalloc(irq_handler))) {
93         fail("out of IV resource.");
94         return 0; // never reach
95     }
96
97     // fixed, edge trigged, polarity=high
98     intc_irq_attach(irq, iv, 0, IRQ_DEFAULT);
99
100     return iv;
101 }
102
103 void
104 isrm_bindiv(int iv, isr_cb handler)
105 {
106     assert(iv < 256);
107
108     if (iv >= IV_BASE_END) {
109         iv_bmp[(iv - IV_BASE_END) / 8] |= 1 << ((iv - IV_BASE_END) % 8);
110     }
111
112     handlers[iv] = handler;
113 }
114
115 isr_cb
116 isrm_get(int iv)
117 {
118     assert(iv < 256);
119
120     return handlers[iv];
121 }
122
123 ptr_t
124 isrm_get_payload(const isr_param* param)
125 {
126     int iv = param->execp->vector;
127     assert(iv < 256);
128
129     return ivhand_payload[iv];
130 }
131
132 void
133 isrm_set_payload(int iv, ptr_t payload)
134 {
135     assert(iv < 256);
136
137     ivhand_payload[iv] = payload;
138 }