Add {WA_Shape, 0} to avoid Intuition and App
[tangerine.git] / arch / m68k-mac / exec / core.c
blob7fbf3a0a3049f36781080ed67f883a7667516af3
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>
24 * Build all interrupt assmbly code needed. Derived from i386-native code.
26 BUILD_IRQ(0)
27 BUILD_IRQ(1)
28 BUILD_IRQ(2)
29 BUILD_IRQ(3)
30 BUILD_IRQ(4)
31 BUILD_IRQ(5)
32 BUILD_IRQ(6)
33 BUILD_IRQ(7)
35 static void irqSetup(struct irqDescriptor *, struct ExecBase *);
36 static void handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqServer * is);
38 BOOL init_core(struct ExecBase * SysBase)
40 int rc = FALSE;
41 SysBase->PlatformData = AllocMem(sizeof(struct PlatformData),
42 MEMF_CLEAR|MEMF_PUBLIC);
43 if (NULL != SysBase->PlatformData) {
44 rc = TRUE;
46 * Now initialise the PlatformData structure.
48 irqSetup(&PLATFORMDATA(SysBase)->irq_desc[0], SysBase);
50 * Activate the low-level (assembly) interrupt handlers
52 INSTALL_IRQ_HANDLER(IRQ_LEVEL6, IRQ6_interrupt);
53 INSTALL_IRQ_HANDLER(IRQ_LEVEL5, IRQ5_interrupt);
54 INSTALL_IRQ_HANDLER(IRQ_LEVEL4, IRQ4_interrupt);
55 INSTALL_IRQ_HANDLER(IRQ_LEVEL3, IRQ3_interrupt);
56 INSTALL_IRQ_HANDLER(IRQ_LEVEL2, IRQ2_interrupt);
57 INSTALL_IRQ_HANDLER(IRQ_LEVEL1, IRQ1_interrupt);
59 // WREG_L(0x100) = (ULONG)IRQ0_interrupt;
60 WREG_L(0x104) = (ULONG)IRQ1_interrupt;
61 WREG_L(0x108) = (ULONG)IRQ2_interrupt;
62 WREG_L(0x10c) = (ULONG)IRQ3_interrupt;
63 WREG_L(0x110) = (ULONG)IRQ4_interrupt;
64 WREG_L(0x114) = (ULONG)IRQ5_interrupt;
65 WREG_L(0x118) = (ULONG)IRQ6_interrupt;
67 WREG_W(TCTL2) = 0x11;
68 WREG_W(TCMP2) = 0x411a;
70 return rc;
73 static void do_db_IRQ(unsigned int irq,
74 unsigned int virq,
75 struct pt_regs * regs);
76 static void disable_db_irq(unsigned int irq);
77 static void enable_db_irq(unsigned int irq);
79 #define startup_db_irq enable_db_irq
80 #define shutdown_db_irq disable_db_irq
82 static struct irqController db_controller =
84 "Dragonball", // ic_Name
85 startup_db_irq, // ic_startup
86 shutdown_db_irq, // ic_shutdown
87 do_db_IRQ, // ic_handle
88 enable_db_irq, // ic_enable
89 disable_db_irq // ic_disable
94 static void disable_db_irq(unsigned int irq)
98 static void enable_db_irq(unsigned int virq)
100 ULONG imr = RREG_L(IMR);
102 * On this processor I must clear the flags of those interrupts
103 * that I want to enable.
105 switch (virq) {
106 case vHidd_IRQ_Timer:
107 imr &= ~(TMR2_F);
108 break;
109 case vHidd_IRQ_HDD1:
110 imr &= ~(INT0_F | INT1_F | INT2_F | INT3_F | INT4_F | INT5_F | INT6_F | INT7_F);
111 break;
112 case vHidd_IRQ_Serial1:
113 imr &= ~(UART1_F);
114 break;
115 case vHidd_IRQ_Mouse:
116 imr &= ~(PEN_F);
117 break;
119 WREG_L(IMR) = imr;
123 static inline void mask_and_ack_dbirq(unsigned int irq)
127 static void do_db_IRQ(unsigned int irq,
128 unsigned int virq,
129 struct pt_regs * regs)
131 AROS_GET_SYSBASE
132 struct irqServer * iServer;
133 struct irqDescriptor * desc = &PLATFORMDATA(SysBase)->irq_desc[irq];
135 // D(bug("In do_db_IRQ(irq=%d,virq=%d)\n",irq,virq));
137 unsigned int status;
138 mask_and_ack_dbirq(irq);
139 status = desc->id_status & ~(IRQ_REPLAY | IRQ_WAITING);
140 iServer = NULL;
141 if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
142 iServer = desc->id_server;
143 status |= IRQ_INPROGRESS;
144 } else {
145 D(bug("IRQ server used!? %p (irq=%d,virq=%d)\n",
146 desc->id_server,
147 irq,
148 virq));
150 desc->id_status = status;
153 /* Exit early if we had no action or it was disabled */
154 if (!iServer) {
155 D(bug("No IRQ handler found!\n"));
156 return;
158 // D(bug("Handling virq %d in server now!\n",virq));
159 handle_IRQ_event(virq, regs, iServer);
162 unsigned int status = desc->id_status & ~IRQ_INPROGRESS;
163 desc->id_status = status;
164 if (!(status & IRQ_DISABLED))
165 enable_db_irq(irq);
169 /*******************************************************************************
170 Lowlevel IRQ functions used by each controller
171 *******************************************************************************/
173 static void handle_IRQ_event(unsigned int virq, struct pt_regs * regs, struct irqServer * is)
175 ULONG imr = RREG_L(IMR);
176 WREG_L(IMR) = ~0;
177 is->is_handler(virq, is->is_UserData, regs);
178 WREG_L(IMR) = imr;
184 * Generic enable/disable code: this just calls
185 * down into the PIC-specific version for the actual
186 * hardware disable after having gotten the irq
187 * controller lock.
189 void disable_irq_nosync(unsigned int irq)
191 AROS_GET_SYSBASE
192 if (!PLATFORMDATA(SysBase)->irq_desc[irq].id_depth++) {
193 PLATFORMDATA(SysBase)->irq_desc[irq].id_status |= IRQ_DISABLED;
194 PLATFORMDATA(SysBase)->irq_desc[irq].id_handler->ic_disable(irq);
199 * Synchronous version of the above, making sure the IRQ is
200 * no longer running on any other IRQ..
202 void disable_irq(unsigned int virq)
204 disable_db_irq(virq);
205 #if 0
206 disable_irq_nosync(irq);
207 #endif
210 void enable_irq(unsigned int virq)
212 enable_db_irq(virq);
213 #if 0
214 AROS_GET_SYSBASE
215 struct irqDescriptor * irq_desc = PLATFORMDATA(SysBase)->irq_desc;
216 switch (irq_desc[irq].id_depth) {
217 case 0: break;
218 case 1:
219 irq_desc[irq].id_status &= ~IRQ_DISABLED;
220 irq_desc[irq].id_handler->ic_enable(virq);
221 /* fall throught */
222 default:
223 irq_desc[irq].id_depth--;
225 #endif
229 // !!! Move this into include file !!!
230 extern void sys_Dispatch(struct pt_regs * regs);
232 * Called from low level assembly code. Handles irq number 'irq'.
234 /*asmlinkage*/ void do_IRQ(struct pt_regs * regs, ULONG irq)
236 AROS_GET_SYSBASE
237 BOOL treated = FALSE;
238 struct irqDescriptor * irq_desc = &PLATFORMDATA(SysBase)->irq_desc[irq];
239 ULONG isr = RREG_L(ISR);
242 * Now the problem with this processor is that it multiplexes multiple
243 * interrupt sources over one IRQ. So I demultiplex them here by
244 * looking at the interrupt pending register depending on what irq
245 * level I have.
248 // D(bug("isr=0x%x,irq=%d\n",isr,irq));
249 switch (irq) {
250 case 0:
252 break;
254 case 1:
256 break;
258 case 2:
260 break;
262 case 3:
264 break;
266 case 4:
267 if (isr & TMR2_F) {
268 volatile UWORD tstat2;
269 treated = TRUE;
271 * Leave the following two lines as they are.
273 tstat2 = RREG_W(TSTAT2);
274 WREG_W(TSTAT2) = 0;
276 * Explicitly call the dispatcher here to get Multitasking
277 * going. Hm, might maybe want to put this into the chain
278 * of handlers...
280 // D(bug("------------ Task SWITCH!\n"));
281 sys_Dispatch(regs);
282 irq_desc->id_count++;
284 irq_desc->id_handler->ic_handle(irq,
285 0, /* -> index of vHidd_IRQ_Timer2 in servers.c */
286 regs);
289 if (isr & UART1_F) {
290 // D(bug("-------------- UART IRQ!\n"));
291 /* UART 1 */
292 treated = TRUE;
294 irq_desc->id_count++;
295 irq_desc->id_handler->ic_handle(irq,
296 4, /* -> index of vHidd_IRQ_Serial1 in servers.c */
297 regs);
300 if (isr & WDT_F) {
301 /* Watchdog timer */
304 if (isr & RTC_F) {
305 /* real time clock */
308 if (isr & LCDC_F) {
309 /* LCDC ??? */
312 if (isr & KB_F) {
313 /* Keyboard */
316 if (isr & (INT0_F|INT1_F|INT2_F|INT3_F|INT4_F|INT5_F|INT6_F|INT7_F)) {
317 /* Port D */
318 D(bug("--------------- Keyboard IRQ!\n"));
319 treated = TRUE;
321 irq_desc->id_count++;
322 irq_desc->id_handler->ic_handle(irq,
323 1, /* -> index of vHidd_IRQ_CustomD */
324 regs);
327 break;
329 case 5:
330 if (isr & PEN_F) {
331 // D(bug("Pen IRQ!\n"));
332 irq_desc->id_count++;
333 irq_desc->id_handler->ic_handle(irq,
334 12, /* index of vHidd_IRQ_Mouse in servers.c */
335 regs);
336 treated = TRUE;
338 break;
340 case 6:
341 if (isr & PWM1_F) {
342 /* PWM */
345 if (isr & TMR1_F) {
346 /* TMR1 */
348 break;
350 case 7:
351 break;
355 * Check for the configurable IRQs here
357 #if 0
358 if ((isr & PWM2_F) && (irq == ((ilcr >> 4) & 0x07))) {
361 #endif
363 if (FALSE == treated) {
364 D(bug("Untreated: irq=%d,isr=0x%x\n",irq,isr));
368 static void VBL_handler(int i, void *user, struct pt_regs *regs)
370 AROS_GET_SYSBASE;
371 if (SysBase->Elapsed == 0) {
372 SysBase->SysFlags |= 0x2000;
373 SysBase->AttnResched |= 0x80;
374 } else {
375 SysBase->Elapsed--;
377 // D(bug("In VBL handler!\n"));
380 static struct irqServer VBlank = { VBL_handler, "VBlank", NULL };
383 static void irqSetup(struct irqDescriptor irq_desc[], struct ExecBase * SysBase)
385 ULONG i;
387 for (i = 0; i<NR_IRQS; i++) {
388 irq_desc[i].id_handler = &db_controller;
389 irq_desc[i].id_status = IRQ_DISABLED;
390 irq_desc[i].id_depth = 0;
391 irq_desc[i].id_server = 0;
394 irqSet(0, &VBlank, NULL, SysBase);
395 irq_desc[0].id_server = &VBlank;
396 irq_desc[0].id_depth = 0;
397 irq_desc[0].id_status &= ~IRQ_DISABLED;
398 irq_desc[0].id_handler->ic_startup(0);
402 BOOL irqSet(int irq, struct irqServer *is, void * isd, struct ExecBase * SysBase)
404 BOOL rc = FALSE;
405 if (is) {
406 struct irqServer * _is = AllocMem(sizeof(struct irqServer),
407 MEMF_PUBLIC|MEMF_CLEAR);
408 if (NULL != _is) {
409 rc = TRUE;
410 _is->is_handler = is->is_handler;
411 _is->is_name = is->is_name;
412 _is->is_UserData = isd;
413 PLATFORMDATA(SysBase)->irq_desc[irq].id_server = _is;
414 PLATFORMDATA(SysBase)->irq_desc[irq].id_depth = 0;
415 PLATFORMDATA(SysBase)->irq_desc[irq].id_status &= ~IRQ_DISABLED;
416 PLATFORMDATA(SysBase)->irq_desc[irq].id_handler->ic_startup(irq);
419 return rc;
424 * Interrupts
427 LONG sys_Cause(struct pt_regs);
428 LONG sys_Supervisor(struct pt_regs regs) {return 0;}
429 LONG sys_None(struct pt_regs regs) { return 0; }
431 LONG sys_ColdReboot(struct pt_regs regs)
433 // __asm__("jmp kernel_startup");
434 return 0;
438 LONG (*sys_call_table[])(struct pt_regs) =
440 sys_Cause,
441 sys_ColdReboot,
442 sys_Supervisor,
443 sys_None