Removed __startup attribute. It is already present in AROS_SHxx definition, and doubl...
[AROS.git] / arch / m68k-mac / exec / core.c
blob917f7e82ea3b452d1c0925e42c850798001881f5
1 /*
2 Copyright © 1995-2007, 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>
14 #include <aros/core.h>
15 #include <asm/irq.h>
16 #include <asm/registers.h>
17 #include <asm/cpu.h>
19 # define DEBUG 1
20 # include <aros/debug.h>
23 * Build all interrupt assmbly code needed. Derived from i386-native code.
25 BUILD_IRQ(0)
26 BUILD_IRQ(1)
27 BUILD_IRQ(2)
28 BUILD_IRQ(3)
29 BUILD_IRQ(4)
30 BUILD_IRQ(5)
31 BUILD_IRQ(6)
32 BUILD_IRQ(7)
34 static void irqSetup(struct irqDescriptor *, struct ExecBase *);
35 static void handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqServer * is);
37 BOOL init_core(struct ExecBase * SysBase)
39 int rc = FALSE;
40 SysBase->PlatformData = AllocMem(sizeof(struct PlatformData),
41 MEMF_CLEAR|MEMF_PUBLIC);
42 if (NULL != SysBase->PlatformData) {
43 rc = TRUE;
45 * Now initialise the PlatformData structure.
47 irqSetup(&PLATFORMDATA(SysBase)->irq_desc[0], SysBase);
49 * Activate the low-level (assembly) interrupt handlers
51 INSTALL_IRQ_HANDLER(IRQ_LEVEL6, IRQ6_interrupt);
52 INSTALL_IRQ_HANDLER(IRQ_LEVEL5, IRQ5_interrupt);
53 INSTALL_IRQ_HANDLER(IRQ_LEVEL4, IRQ4_interrupt);
54 INSTALL_IRQ_HANDLER(IRQ_LEVEL3, IRQ3_interrupt);
55 INSTALL_IRQ_HANDLER(IRQ_LEVEL2, IRQ2_interrupt);
56 INSTALL_IRQ_HANDLER(IRQ_LEVEL1, IRQ1_interrupt);
58 // WREG_L(0x100) = (ULONG)IRQ0_interrupt;
59 WREG_L(0x104) = (ULONG)IRQ1_interrupt;
60 WREG_L(0x108) = (ULONG)IRQ2_interrupt;
61 WREG_L(0x10c) = (ULONG)IRQ3_interrupt;
62 WREG_L(0x110) = (ULONG)IRQ4_interrupt;
63 WREG_L(0x114) = (ULONG)IRQ5_interrupt;
64 WREG_L(0x118) = (ULONG)IRQ6_interrupt;
66 WREG_W(TCTL2) = 0x11;
67 WREG_W(TCMP2) = 0x411a;
69 return rc;
72 static void do_db_IRQ(unsigned int irq,
73 unsigned int virq,
74 struct pt_regs * regs);
75 static void disable_db_irq(unsigned int irq);
76 static void enable_db_irq(unsigned int irq);
78 #define startup_db_irq enable_db_irq
79 #define shutdown_db_irq disable_db_irq
81 static struct irqController db_controller =
83 "Dragonball", // ic_Name
84 startup_db_irq, // ic_startup
85 shutdown_db_irq, // ic_shutdown
86 do_db_IRQ, // ic_handle
87 enable_db_irq, // ic_enable
88 disable_db_irq // ic_disable
93 static void disable_db_irq(unsigned int irq)
97 static void enable_db_irq(unsigned int virq)
99 ULONG imr = RREG_L(IMR);
101 * On this processor I must clear the flags of those interrupts
102 * that I want to enable.
104 switch (virq) {
105 case vHidd_IRQ_Timer:
106 imr &= ~(TMR2_F);
107 break;
108 case vHidd_IRQ_HDD1:
109 imr &= ~(INT0_F | INT1_F | INT2_F | INT3_F | INT4_F | INT5_F | INT6_F | INT7_F);
110 break;
111 case vHidd_IRQ_Serial1:
112 imr &= ~(UART1_F);
113 break;
114 case vHidd_IRQ_Mouse:
115 imr &= ~(PEN_F);
116 break;
118 WREG_L(IMR) = imr;
122 static inline void mask_and_ack_dbirq(unsigned int irq)
126 static void do_db_IRQ(unsigned int irq,
127 unsigned int virq,
128 struct pt_regs * regs)
130 struct irqServer * iServer;
131 struct irqDescriptor * desc = &PLATFORMDATA(SysBase)->irq_desc[irq];
133 // D(bug("In do_db_IRQ(irq=%d,virq=%d)\n",irq,virq));
135 unsigned int status;
136 mask_and_ack_dbirq(irq);
137 status = desc->id_status & ~(IRQ_REPLAY | IRQ_WAITING);
138 iServer = NULL;
139 if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
140 iServer = desc->id_server;
141 status |= IRQ_INPROGRESS;
142 } else {
143 D(bug("IRQ server used!? %p (irq=%d,virq=%d)\n",
144 desc->id_server,
145 irq,
146 virq));
148 desc->id_status = status;
151 /* Exit early if we had no action or it was disabled */
152 if (!iServer) {
153 D(bug("No IRQ handler found!\n"));
154 return;
156 // D(bug("Handling virq %d in server now!\n",virq));
157 handle_IRQ_event(virq, regs, iServer);
160 unsigned int status = desc->id_status & ~IRQ_INPROGRESS;
161 desc->id_status = status;
162 if (!(status & IRQ_DISABLED))
163 enable_db_irq(irq);
167 /*******************************************************************************
168 Lowlevel IRQ functions used by each controller
169 *******************************************************************************/
171 static void handle_IRQ_event(unsigned int virq, struct pt_regs * regs, struct irqServer * is)
173 ULONG imr = RREG_L(IMR);
174 WREG_L(IMR) = ~0;
175 is->is_handler(virq, is->is_UserData, regs);
176 WREG_L(IMR) = imr;
182 * Generic enable/disable code: this just calls
183 * down into the PIC-specific version for the actual
184 * hardware disable after having gotten the irq
185 * controller lock.
187 void disable_irq_nosync(unsigned int irq)
189 if (!PLATFORMDATA(SysBase)->irq_desc[irq].id_depth++) {
190 PLATFORMDATA(SysBase)->irq_desc[irq].id_status |= IRQ_DISABLED;
191 PLATFORMDATA(SysBase)->irq_desc[irq].id_handler->ic_disable(irq);
196 * Synchronous version of the above, making sure the IRQ is
197 * no longer running on any other IRQ..
199 void disable_irq(unsigned int virq)
201 disable_db_irq(virq);
202 #if 0
203 disable_irq_nosync(irq);
204 #endif
207 void enable_irq(unsigned int virq)
209 enable_db_irq(virq);
210 #if 0
211 struct irqDescriptor * irq_desc = PLATFORMDATA(SysBase)->irq_desc;
212 switch (irq_desc[irq].id_depth) {
213 case 0: break;
214 case 1:
215 irq_desc[irq].id_status &= ~IRQ_DISABLED;
216 irq_desc[irq].id_handler->ic_enable(virq);
217 /* fall throught */
218 default:
219 irq_desc[irq].id_depth--;
221 #endif
225 // !!! Move this into include file !!!
226 extern void sys_Dispatch(struct pt_regs * regs);
228 * Called from low level assembly code. Handles irq number 'irq'.
230 /*asmlinkage*/ void do_IRQ(struct pt_regs * regs, ULONG irq)
232 BOOL treated = FALSE;
233 struct irqDescriptor * irq_desc = &PLATFORMDATA(SysBase)->irq_desc[irq];
234 ULONG isr = RREG_L(ISR);
237 * Now the problem with this processor is that it multiplexes multiple
238 * interrupt sources over one IRQ. So I demultiplex them here by
239 * looking at the interrupt pending register depending on what irq
240 * level I have.
243 // D(bug("isr=0x%x,irq=%d\n",isr,irq));
244 switch (irq) {
245 case 0:
247 break;
249 case 1:
251 break;
253 case 2:
255 break;
257 case 3:
259 break;
261 case 4:
262 if (isr & TMR2_F) {
263 volatile UWORD tstat2;
264 treated = TRUE;
266 * Leave the following two lines as they are.
268 tstat2 = RREG_W(TSTAT2);
269 WREG_W(TSTAT2) = 0;
271 * Explicitly call the dispatcher here to get Multitasking
272 * going. Hm, might maybe want to put this into the chain
273 * of handlers...
275 // D(bug("------------ Task SWITCH!\n"));
276 sys_Dispatch(regs);
277 irq_desc->id_count++;
279 irq_desc->id_handler->ic_handle(irq,
280 0, /* -> index of vHidd_IRQ_Timer2 in servers.c */
281 regs);
284 if (isr & UART1_F) {
285 // D(bug("-------------- UART IRQ!\n"));
286 /* UART 1 */
287 treated = TRUE;
289 irq_desc->id_count++;
290 irq_desc->id_handler->ic_handle(irq,
291 4, /* -> index of vHidd_IRQ_Serial1 in servers.c */
292 regs);
295 if (isr & WDT_F) {
296 /* Watchdog timer */
299 if (isr & RTC_F) {
300 /* real time clock */
303 if (isr & LCDC_F) {
304 /* LCDC ??? */
307 if (isr & KB_F) {
308 /* Keyboard */
311 if (isr & (INT0_F|INT1_F|INT2_F|INT3_F|INT4_F|INT5_F|INT6_F|INT7_F)) {
312 /* Port D */
313 D(bug("--------------- Keyboard IRQ!\n"));
314 treated = TRUE;
316 irq_desc->id_count++;
317 irq_desc->id_handler->ic_handle(irq,
318 1, /* -> index of vHidd_IRQ_CustomD */
319 regs);
322 break;
324 case 5:
325 if (isr & PEN_F) {
326 // D(bug("Pen IRQ!\n"));
327 irq_desc->id_count++;
328 irq_desc->id_handler->ic_handle(irq,
329 12, /* index of vHidd_IRQ_Mouse in servers.c */
330 regs);
331 treated = TRUE;
333 break;
335 case 6:
336 if (isr & PWM1_F) {
337 /* PWM */
340 if (isr & TMR1_F) {
341 /* TMR1 */
343 break;
345 case 7:
346 break;
350 * Check for the configurable IRQs here
352 #if 0
353 if ((isr & PWM2_F) && (irq == ((ilcr >> 4) & 0x07))) {
356 #endif
358 if (FALSE == treated) {
359 D(bug("Untreated: irq=%d,isr=0x%x\n",irq,isr));
363 static void VBL_handler(int i, void *user, struct pt_regs *regs)
365 if (SysBase->Elapsed == 0) {
366 SysBase->SysFlags |= 0x2000;
367 SysBase->AttnResched |= 0x80;
368 } else {
369 SysBase->Elapsed--;
371 // D(bug("In VBL handler!\n"));
374 static struct irqServer VBlank = { VBL_handler, "VBlank", NULL };
377 static void irqSetup(struct irqDescriptor irq_desc[], struct ExecBase * SysBase)
379 ULONG i;
381 for (i = 0; i<NR_IRQS; i++) {
382 irq_desc[i].id_handler = &db_controller;
383 irq_desc[i].id_status = IRQ_DISABLED;
384 irq_desc[i].id_depth = 0;
385 irq_desc[i].id_server = 0;
388 irqSet(0, &VBlank, NULL, SysBase);
389 irq_desc[0].id_server = &VBlank;
390 irq_desc[0].id_depth = 0;
391 irq_desc[0].id_status &= ~IRQ_DISABLED;
392 irq_desc[0].id_handler->ic_startup(0);
396 BOOL irqSet(int irq, struct irqServer *is, void * isd, struct ExecBase * SysBase)
398 BOOL rc = FALSE;
399 if (is) {
400 struct irqServer * _is = AllocMem(sizeof(struct irqServer),
401 MEMF_PUBLIC|MEMF_CLEAR);
402 if (NULL != _is) {
403 rc = TRUE;
404 _is->is_handler = is->is_handler;
405 _is->is_name = is->is_name;
406 _is->is_UserData = isd;
407 PLATFORMDATA(SysBase)->irq_desc[irq].id_server = _is;
408 PLATFORMDATA(SysBase)->irq_desc[irq].id_depth = 0;
409 PLATFORMDATA(SysBase)->irq_desc[irq].id_status &= ~IRQ_DISABLED;
410 PLATFORMDATA(SysBase)->irq_desc[irq].id_handler->ic_startup(irq);
413 return rc;
418 * Interrupts
421 LONG sys_Cause(struct pt_regs);
422 LONG sys_Supervisor(struct pt_regs regs) {return 0;}
423 LONG sys_None(struct pt_regs regs) { return 0; }
425 LONG sys_ColdReboot(struct pt_regs regs)
427 // __asm__("jmp kernel_startup");
428 return 0;
432 LONG (*sys_call_table[])(struct pt_regs) =
434 sys_Cause,
435 sys_ColdReboot,
436 sys_Supervisor,
437 sys_None