Test initialisation of MUIA_List_AdjustWidth and MUIA_List_AdjustHeight, and
[AROS.git] / arch / .unmaintained / arm-all / exec / core.c
blobe86f776dd1f65d2cc2e7a0bc030c8a1468963d90
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Core of AROS.
6 Lang: english
7 */
8 #include <exec/types.h>
9 #include <exec/memory.h>
10 #include <exec/execbase.h>
11 #include <exec/ptrace.h>
12 #include <proto/exec.h>
13 #include <hidd/irq.h>
15 #include <aros/core.h>
16 #include <asm/irq.h>
17 #include <asm/registers.h>
18 #include <asm/cpu.h>
20 # define DEBUG 1
21 # include <aros/debug.h>
23 #include "arm_exec_internal.h"
26 * Build all interrupt assmbly code needed. Derived from i386-native code.
28 BUILD_IRQ(_Reset)
29 BUILD_IRQ(_Undef)
30 BUILD_IRQ(_Prefetch_Abort)
31 BUILD_IRQ(_Data_Abort)
32 BUILD_IRQ(_std)
33 BUILD_IRQ(_FIQ)
35 static void irqSetup(struct irqDescriptor *, struct ExecBase *);
36 static void handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqServer * is);
39 void do_IRQ(struct pt_regs * regs, LONG adjust);
41 BOOL init_core(struct ExecBase * SysBase)
43 int rc = FALSE;
44 SysBase->PlatformData = AllocMem(sizeof(struct PlatformData),
45 MEMF_CLEAR|MEMF_PUBLIC);
46 if (NULL != SysBase->PlatformData) {
47 rc = TRUE;
49 * Now initialise the PlatformData structure.
51 irqSetup(&PLATFORMDATA(SysBase)->irq_desc[0], SysBase);
53 * Activate the low-level (assembly) interrupt handlers
55 INSTALL_IRQ_HANDLER(VECTOR_SWI, _sys_swi_handler);
56 // WREG_L(VECTOR_PREFETCH_ABORT) = 0xe25ef004;
57 WREG_L(VECTOR_DATA_ABORT) = 0xe25ef004; // NECESSARY!!!
58 INSTALL_IRQ_HANDLER(VECTOR_IRQ, IRQ_std_interrupt);
59 WREG_L(VECTOR_FIQ) = 0xe25ef004;
60 D(bug("Installed SWI Handler!\r\n"));
61 D(bug("*0x08 = %x\n",RREG_L(0x08)));
62 D(bug("*0x0c = %x\n",RREG_L(0x0c)));
63 D(bug("*0x18 = %x\n",RREG_L(0x18)));
64 D(bug("_sys_swi_handler = %x\n",_sys_swi_handler));
65 D(bug("IRQ_std_interrupt = %x\n",IRQ_std_interrupt));
67 /* Start the timer */
68 WREG_L(OSCR) = 0;
69 WREG_L(OIER) = 0x1;
70 /* allow this interrupt! */
71 WREG_L(ICMR) = (1 << 26);
73 return rc;
76 static void do_db_IRQ(unsigned int irq,
77 unsigned int virq,
78 struct pt_regs * regs);
79 static void disable_db_irq(unsigned int irq);
80 static void enable_db_irq(unsigned int irq);
82 #define startup_db_irq enable_db_irq
83 #define shutdown_db_irq disable_db_irq
85 static struct irqController db_controller =
87 "Dragonball", // ic_Name
88 startup_db_irq, // ic_startup
89 shutdown_db_irq, // ic_shutdown
90 do_db_IRQ, // ic_handle
91 enable_db_irq, // ic_enable
92 disable_db_irq // ic_disable
97 static void disable_db_irq(unsigned int irq)
101 static void enable_db_irq(unsigned int virq)
103 ULONG icmr = RREG_L(ICMR);
105 * On this processor I must clear the flags of those interrupts
106 * that I want to enable.
108 switch (virq) {
109 case vHidd_IRQ_Timer2:
110 // imr &= ~(TMR2_F);
111 break;
112 case vHidd_IRQ_CustomD:
113 // imr &= ~(INT0_F | INT1_F | INT2_F | INT3_F | INT4_F | INT5_F | INT6_F | INT7_F);
114 break;
115 case vHidd_IRQ_Serial1:
116 // imr &= ~(UART1_F);
117 break;
118 case vHidd_IRQ_Touchscreen:
119 // imr &= ~(PEN_F);
120 break;
122 WREG_L(ICMR) = icmr;
126 static inline void mask_and_ack_dbirq(unsigned int irq)
130 static void do_db_IRQ(unsigned int irq,
131 unsigned int virq,
132 struct pt_regs * regs)
134 struct irqServer * iServer;
135 struct irqDescriptor * desc = &PLATFORMDATA(SysBase)->irq_desc[irq];
137 // D(bug("In do_db_IRQ(irq=%d,virq=%d)\n",irq,virq));
139 unsigned int status;
140 mask_and_ack_dbirq(irq);
141 status = desc->id_status & ~(IRQ_REPLAY | IRQ_WAITING);
142 iServer = NULL;
143 if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
144 iServer = desc->id_server;
145 status |= IRQ_INPROGRESS;
146 // D(bug("Marked IRQ as INPROGRESS!\n"));
147 } else {
148 D(bug("IRQ server used!? %p status=0x%x (irq=%d,virq=%d)\n",
149 desc->id_server,
150 status,
151 irq,
152 virq));
153 if (status & IRQ_INPROGRESS) {
154 D(bug("IRQ in progress!?!?!\n"));
155 } else {
156 D(bug("IRQ disabled!?!?!\n"));
159 desc->id_status = status;
162 /* Exit early if we had no action or it was disabled */
163 if (!iServer) {
164 D(bug("No IRQ handler found!\n"));
165 return;
166 } else {
167 // D(bug("IRQ server at %x\n",iServer));
169 // D(bug("Handling virq %d in server now!\n",virq));
170 handle_IRQ_event(virq, regs, iServer);
173 unsigned int status = desc->id_status & ~IRQ_INPROGRESS;
174 desc->id_status = status;
175 // D(bug("UNMarked IRQ as INPROGRESS!\n"));
176 if (!(status & IRQ_DISABLED))
177 enable_db_irq(irq);
181 /*******************************************************************************
182 Lowlevel IRQ functions used by each controller
183 *******************************************************************************/
185 static void handle_IRQ_event(unsigned int virq, struct pt_regs * regs, struct irqServer * is)
187 ULONG icmr = RREG_L(ICMR);
188 WREG_L(ICMR) = 0;
189 is->is_handler(virq, is->is_UserData, regs);
190 WREG_L(ICMR) = icmr;
196 * Generic enable/disable code: this just calls
197 * down into the PIC-specific version for the actual
198 * hardware disable after having gotten the irq
199 * controller lock.
201 void disable_irq_nosync(unsigned int irq)
203 if (!PLATFORMDATA(SysBase)->irq_desc[irq].id_depth++) {
204 PLATFORMDATA(SysBase)->irq_desc[irq].id_status |= IRQ_DISABLED;
205 PLATFORMDATA(SysBase)->irq_desc[irq].id_handler->ic_disable(irq);
210 * Synchronous version of the above, making sure the IRQ is
211 * no longer running on any other IRQ..
213 void disable_irq(unsigned int virq)
215 disable_db_irq(virq);
216 #if 0
217 disable_irq_nosync(irq);
218 #endif
221 void enable_irq(unsigned int virq)
223 enable_db_irq(virq);
224 #if 0
225 struct irqDescriptor * irq_desc = PLATFORMDATA(SysBase)->irq_desc;
226 switch (irq_desc[irq].id_depth) {
227 case 0: break;
228 case 1:
229 irq_desc[irq].id_status &= ~IRQ_DISABLED;
230 irq_desc[irq].id_handler->ic_enable(virq);
231 /* fall throught */
232 default:
233 irq_desc[irq].id_depth--;
235 #endif
240 * Called from low level assembly code. Handles irq number 'irq'.
241 * 'irq' on the ARM implementation is ignored.
243 void do_IRQ(struct pt_regs * regs, LONG adjust)
245 BOOL treated = FALSE;
246 struct irqDescriptor * irq_desc = &PLATFORMDATA(SysBase)->irq_desc[1];
247 ULONG icip = RREG_L(ICIP);
248 #if 0
249 D(bug("In do_IRQ !!!!\n"));
250 D(bug("Entering! @regs=%x, icip=%x, lr_svc=%x, spsr=%x, r0=%x\n",
251 &regs,
252 RREG_L(ICIP),
253 regs->lr_svc,
254 regs->cpsr,
255 regs->r0));
256 #endif
258 * Now the problem with this processor is that it multiplexes multiple
259 * interrupt sources over one IRQ. So I demultiplex them here by
260 * looking at the interrupt pending register depending on what irq
261 * level I have.
264 /* OS Timer 0 */
265 if (icip & (1 << 26)) {
266 // D(bug("------------ Task SWITCH!\n"));
267 treated = TRUE;
269 * Explicitly call the dispatcher here to get Multitasking
270 * going. Hm, might maybe want to put this into the chain
271 * of handlers...
273 sys_Dispatch(regs, adjust);
275 irq_desc->id_count++;
276 irq_desc->id_handler->ic_handle(1,
277 0, /* -> index of vHidd_IRQ_Timer2 in servers.c */
278 regs);
279 WREG_L(OSSR) = 1;
280 WREG_L(OSCR) = 0;
283 /* UART */
284 if (icip & (1 << 17)) {
285 // D(bug("-------------- UART IRQ!\n"));
286 /* UART 1 */
287 treated = TRUE;
289 irq_desc->id_count++;
290 irq_desc->id_handler->ic_handle(1,
291 4, /* -> index of vHidd_IRQ_Serial1 in servers.c */
292 regs);
295 if (FALSE == treated) {
296 D(bug("Untreated: icip=0x%x\n",icip));
299 * Reset all flags
301 WREG_L(ICIP) = icip;
302 #if 0
303 D(bug("Leaving! @regs=%x, icip=%x, lr_svc=%x, spsr=%x, r0=%x\n",
304 &regs,
305 RREG_L(ICIP),
306 regs->lr_svc,
307 regs->cpsr,
308 regs->r0));
309 #endif
313 static void VBL_handler(int i, void *user, struct pt_regs *regs)
315 if (SysBase->Elapsed == 0) {
316 SysBase->SysFlags |= 0x2000;
317 SysBase->AttnResched |= 0x80;
318 } else {
319 SysBase->Elapsed--;
321 // D(bug("In VBL handler!\n"));
324 static struct irqServer VBlank = { VBL_handler, "VBlank", NULL };
327 static void irqSetup(struct irqDescriptor irq_desc[], struct ExecBase * SysBase)
329 ULONG i;
331 for (i = 0; i<NR_IRQS; i++) {
332 irq_desc[i].id_handler = &db_controller;
333 irq_desc[i].id_status = IRQ_DISABLED;
334 irq_desc[i].id_depth = 0;
335 irq_desc[i].id_server = 0;
338 irqSet(0, &VBlank, NULL, SysBase);
339 irq_desc[0].id_server = &VBlank;
340 irq_desc[0].id_depth = 0;
341 irq_desc[0].id_status &= ~IRQ_DISABLED;
342 irq_desc[0].id_handler->ic_startup(0);
346 BOOL irqSet(int irq, struct irqServer *is, void * isd, struct ExecBase * SysBase)
348 BOOL rc = FALSE;
349 if (is) {
350 struct irqServer * _is = AllocMem(sizeof(struct irqServer),
351 MEMF_PUBLIC|MEMF_CLEAR);
352 if (NULL != _is) {
353 rc = TRUE;
354 _is->is_handler = is->is_handler;
355 _is->is_name = is->is_name;
356 _is->is_UserData = isd;
357 PLATFORMDATA(SysBase)->irq_desc[irq].id_server = _is;
358 PLATFORMDATA(SysBase)->irq_desc[irq].id_depth = 0;
359 PLATFORMDATA(SysBase)->irq_desc[irq].id_status &= ~IRQ_DISABLED;
360 PLATFORMDATA(SysBase)->irq_desc[irq].id_handler->ic_startup(irq);
363 return rc;
368 * Interrupts
371 LONG sys_Cause(struct pt_regs);
372 LONG sys_Supervisor(struct pt_regs regs) {return 0;}
373 LONG sys_None(struct pt_regs regs) { return 0; }
375 LONG sys_ColdReboot(struct pt_regs regs)
377 // __asm__("jmp kernel_startup");
378 return 0;
382 LONG (*sys_call_table[])(struct pt_regs) =
384 sys_Cause,
385 sys_ColdReboot,
386 sys_Supervisor,
387 sys_None