2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
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>
15 #include <aros/core.h>
17 #include <asm/registers.h>
21 # include <aros/debug.h>
23 #include "arm_exec_internal.h"
26 * Build all interrupt assmbly code needed. Derived from i386-native code.
30 BUILD_IRQ(_Prefetch_Abort
)
31 BUILD_IRQ(_Data_Abort
)
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
)
44 SysBase
->PlatformData
= AllocMem(sizeof(struct PlatformData
),
45 MEMF_CLEAR
|MEMF_PUBLIC
);
46 if (NULL
!= SysBase
->PlatformData
) {
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
));
70 /* allow this interrupt! */
71 WREG_L(ICMR
) = (1 << 26);
76 static void do_db_IRQ(unsigned int irq
,
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.
109 case vHidd_IRQ_Timer2
:
112 case vHidd_IRQ_CustomD
:
113 // imr &= ~(INT0_F | INT1_F | INT2_F | INT3_F | INT4_F | INT5_F | INT6_F | INT7_F);
115 case vHidd_IRQ_Serial1
:
116 // imr &= ~(UART1_F);
118 case vHidd_IRQ_Touchscreen
:
126 static inline void mask_and_ack_dbirq(unsigned int irq
)
130 static void do_db_IRQ(unsigned int irq
,
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));
140 mask_and_ack_dbirq(irq
);
141 status
= desc
->id_status
& ~(IRQ_REPLAY
| IRQ_WAITING
);
143 if (!(status
& (IRQ_DISABLED
| IRQ_INPROGRESS
))) {
144 iServer
= desc
->id_server
;
145 status
|= IRQ_INPROGRESS
;
146 // D(bug("Marked IRQ as INPROGRESS!\n"));
148 D(bug("IRQ server used!? %p status=0x%x (irq=%d,virq=%d)\n",
153 if (status
& IRQ_INPROGRESS
) {
154 D(bug("IRQ in progress!?!?!\n"));
156 D(bug("IRQ disabled!?!?!\n"));
159 desc
->id_status
= status
;
162 /* Exit early if we had no action or it was disabled */
164 D(bug("No IRQ handler found!\n"));
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
))
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
);
189 is
->is_handler(virq
, is
->is_UserData
, regs
);
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
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
);
217 disable_irq_nosync(irq
);
221 void enable_irq(unsigned int virq
)
225 struct irqDescriptor
* irq_desc
= PLATFORMDATA(SysBase
)->irq_desc
;
226 switch (irq_desc
[irq
].id_depth
) {
229 irq_desc
[irq
].id_status
&= ~IRQ_DISABLED
;
230 irq_desc
[irq
].id_handler
->ic_enable(virq
);
233 irq_desc
[irq
].id_depth
--;
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
);
249 D(bug("In do_IRQ !!!!\n"));
250 D(bug("Entering! @regs=%x, icip=%x, lr_svc=%x, spsr=%x, r0=%x\n",
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
265 if (icip
& (1 << 26)) {
266 // D(bug("------------ Task SWITCH!\n"));
269 * Explicitly call the dispatcher here to get Multitasking
270 * going. Hm, might maybe want to put this into the chain
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 */
284 if (icip
& (1 << 17)) {
285 // D(bug("-------------- UART IRQ!\n"));
289 irq_desc
->id_count
++;
290 irq_desc
->id_handler
->ic_handle(1,
291 4, /* -> index of vHidd_IRQ_Serial1 in servers.c */
295 if (FALSE
== treated
) {
296 D(bug("Untreated: icip=0x%x\n",icip
));
303 D(bug("Leaving! @regs=%x, icip=%x, lr_svc=%x, spsr=%x, r0=%x\n",
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;
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
)
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
)
350 struct irqServer
* _is
= AllocMem(sizeof(struct irqServer
),
351 MEMF_PUBLIC
|MEMF_CLEAR
);
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
);
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");
382 LONG (*sys_call_table
[])(struct pt_regs
) =