0e0baa32bbbb04866fc9985b3f00095a98402b5e
[my-code/arm.git] / betty / interrupts.c
1 /*
2  * interrupts.c - arm exception handling
3  *
4  * author: hackbard@hackdaworld.org
5  *
6  */
7
8 #include "interrupts.h"
9 #include "functions.h"
10
11 // 'module global' interrupt variable
12 static t_interrupt interrupt;
13
14 /*
15  * functions
16  */
17
18 // generaal interrupt handling
19
20 void interrupt_init(void) {
21
22         interrupt.default_soft_callback=0;
23         VICSoftIntClr=0xffffffff;
24         VICIntEnClr=0xffffffff;
25         VICDefVectAddr=0;
26 }
27
28 void interrupt_set_default_callback(u32 callback_addr) {
29
30         VICDefVectAddr=callback_addr;
31 }
32
33 void interrupt_set_soft_callback(void (*callback)(void)) {
34
35         interrupt.default_soft_callback=callback;
36 }
37
38 void interrupt_set_fiq_callback(void (*callback)(void)) {
39
40         interrupt.fiq_callback=callback;
41 }
42
43 void interrupt_soft_clear(u8 src_number) {
44
45         VICSoftIntClr=(1<<src_number);
46 }
47 void interrupt_clear(u8 src_number) {
48
49         int cnt;
50         u32 *addr;
51         u32 *cntl;
52
53         VICIntEnClr=(1<<src_number);
54         VICIntSelect&=~(1<<src_number);
55
56         addr=(u32 *)&VICVectAddr0;
57         cntl=(u32 *)&VICVectCntl0;
58
59         for(cnt=0;cnt<INTERRUPT_MAX_VIC;cnt++) {
60                 if((cntl[cnt]&0x1f)==src_number) {
61                         *((volatile u32 *)(addr+cnt))=0;
62                         *((volatile u32 *)(cntl+cnt))=0;
63                 }
64         }
65 }
66
67 void interrupt_soft_enable(u8 src_number) {
68         
69         VICSoftInt=(1<<src_number);
70 }
71
72 int interrupt_enable(u8 src_number,u8 mode,u8 prio,u32 callback_addr) {
73
74         u32 *addr;
75         u32 *cntl;
76
77         addr=(u32 *)&VICVectAddr0;
78         cntl=(u32 *)&VICVectCntl0;
79
80         /* check whether this ir source is allready assigned */
81         if(VICIntEnable&(1<<src_number))
82                 return INTERRUPT_USED;
83
84         /* prepare depending on mode */
85         switch(mode) {
86                 case INTERRUPT_MODE_FIQ:
87                         VICIntSelect|=(1<<src_number);
88                         break;
89                 case INTERRUPT_MODE_VIRQ:
90                         if(addr[prio]&0x3f)
91                                 return INTERRUPT_PRIORITY_USED;
92                         *((volatile u32 *)(addr+prio))=callback_addr;
93                         *((volatile u32 *)(cntl+prio))=(src_number&0x1f)+0x20;
94                 case INTERRUPT_MODE_IRQ:
95                 default:
96                         break;
97         }
98
99         /* force interrupt */
100         VICIntEnable=(1<<src_number);
101
102         return INTERRUPT_SET;
103 }
104
105 int interrupt_change_callback(u8 src_number,u32 callback) {
106
107         int i;
108         u32 *addr,*cntl;
109
110         cntl=(u32 *)&VICVectCntl0;
111         addr=(u32 *)&VICVectAddr0;
112
113         i=0;
114         while(i<INTERRUPT_MAX_VIC) {
115                 if((*cntl&0x1f)==src_number) {
116                         *(addr+i)=callback;
117                         return INTERRUPT_CALLBACK_CHANGED;
118                 }
119                 i++;
120         }
121
122         return INTERRUPT_SRC_NOT_USED;
123 }
124
125 void interrupt_ack(void) {
126
127         VICVectAddr=0;
128 }
129
130 // specific interrupt handling
131
132 // external interrupts
133 void interrupt_ext_ir_config(u8 eint,u8 wakeup,u8 mode,u8 polarity) {
134
135         if(eint>3)
136                 return;
137
138         if(wakeup)
139                 EXTWAKE=(EXTWAKE&0xf)|(1<<eint);
140
141         EXTMODE=(EXTMODE&0xf)|(mode<<eint);
142         EXTPOLAR=(EXTPOLAR&0xf)|(polarity<<eint);
143 }
144
145 void interrupt_ext_ir_set(u8 eint) {
146
147         if(eint>3)
148                 return;
149
150         EXTINT=(1<<eint);
151 }
152
153 // timer counter interrupts
154 void interrupt_tc_config(u8 tcnum,u8 mode,u8 cap,u32 psc) {
155
156         if(tcnum>1)
157                 return;
158
159         if(tcnum==0) {
160                 T0TCR=0x03;
161                 T0CTCR=mode|(cap<<2);
162                 T0PR=psc;
163         }
164         else {
165                 T1TCR=0x03;
166                 T1CTCR=mode|(cap<<2);
167                 T1PR=psc;
168         }
169 }
170
171 void interrupt_tc_match_config(u8 tcnum,u8 mnum,u32 val,u8 mode) {
172
173         u32 *mraddr;
174
175         if(tcnum>1)
176                 return;
177
178         if(mnum>3)
179                 return;
180
181         if(tcnum==0) {
182                 T0MCR=mode<<(3*mnum);
183                 mrddr=&T0MR0
184         }
185         else {
186                 T1MCR=mode<<(3*mnum);
187                 mrddr=&T1MR0
188         }
189
190         mraddr[mnum]=val;
191 }
192
193 void interrupt_tc_capt_config(u8 tcnum,u8 cnum,u8 mode) {
194
195         if(tcnum>1)
196                 return;
197
198         if(cnum>3)
199                 return;
200
201         if(tcnum==0)
202                 T0CCR=mode<<(3*cnum);
203         else
204                 T1CCR=mode<<(3*cnum);
205 }
206
207 void interrupt_tc_ir_set(u8 tcnum,u8 tcmc) {
208
209         if(tcnum>1)
210                 return;
211
212         if(tcnum==0)
213                 T0IR=tcmc;
214         else
215                 T1IR=tcmc;
216 }
217
218 /*
219  * the actual exception handlers (as defined in startup.s)
220  */
221
222 // reset
223 void interrupt_handler_reset(void) {
224 }
225
226 // undefined instruction
227 void interrupt_handler_undef_instruction(void) {
228 }
229
230 // software interrupt
231 void interrupt_handler_soft_ir(void) {
232         
233         if(interrupt.default_soft_callback)
234                 interrupt.default_soft_callback();
235 }
236
237 // prefetch abort
238 void interrupt_handler_prefetch_abort(void) {
239 }
240
241 // data abort
242 void interrupt_handler_data_abort(void) {
243 }
244
245 // fiq
246 void interrupt_handler_fiq(void) {
247
248         if(interrupt.fiq_callback)
249                 interrupt.fiq_callback();
250 }
251