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>
24 * Build all interrupt assmbly code needed. Derived from i386-native code.
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
)
41 SysBase
->PlatformData
= AllocMem(sizeof(struct PlatformData
),
42 MEMF_CLEAR
|MEMF_PUBLIC
);
43 if (NULL
!= SysBase
->PlatformData
) {
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
;
68 WREG_W(TCMP2
) = 0x411a;
73 static void do_db_IRQ(unsigned int irq
,
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.
106 case vHidd_IRQ_Timer
:
110 imr
&= ~(INT0_F
| INT1_F
| INT2_F
| INT3_F
| INT4_F
| INT5_F
| INT6_F
| INT7_F
);
112 case vHidd_IRQ_Serial1
:
115 case vHidd_IRQ_Mouse
:
123 static inline void mask_and_ack_dbirq(unsigned int irq
)
127 static void do_db_IRQ(unsigned int irq
,
129 struct pt_regs
* regs
)
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));
138 mask_and_ack_dbirq(irq
);
139 status
= desc
->id_status
& ~(IRQ_REPLAY
| IRQ_WAITING
);
141 if (!(status
& (IRQ_DISABLED
| IRQ_INPROGRESS
))) {
142 iServer
= desc
->id_server
;
143 status
|= IRQ_INPROGRESS
;
145 D(bug("IRQ server used!? %p (irq=%d,virq=%d)\n",
150 desc
->id_status
= status
;
153 /* Exit early if we had no action or it was disabled */
155 D(bug("No IRQ handler found!\n"));
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
))
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
);
177 is
->is_handler(virq
, is
->is_UserData
, regs
);
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
189 void disable_irq_nosync(unsigned int irq
)
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
);
206 disable_irq_nosync(irq
);
210 void enable_irq(unsigned int virq
)
215 struct irqDescriptor
* irq_desc
= PLATFORMDATA(SysBase
)->irq_desc
;
216 switch (irq_desc
[irq
].id_depth
) {
219 irq_desc
[irq
].id_status
&= ~IRQ_DISABLED
;
220 irq_desc
[irq
].id_handler
->ic_enable(virq
);
223 irq_desc
[irq
].id_depth
--;
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
)
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
248 // D(bug("isr=0x%x,irq=%d\n",isr,irq));
268 volatile UWORD tstat2
;
271 * Leave the following two lines as they are.
273 tstat2
= RREG_W(TSTAT2
);
276 * Explicitly call the dispatcher here to get Multitasking
277 * going. Hm, might maybe want to put this into the chain
280 // D(bug("------------ Task SWITCH!\n"));
282 irq_desc
->id_count
++;
284 irq_desc
->id_handler
->ic_handle(irq
,
285 0, /* -> index of vHidd_IRQ_Timer2 in servers.c */
290 // D(bug("-------------- UART IRQ!\n"));
294 irq_desc
->id_count
++;
295 irq_desc
->id_handler
->ic_handle(irq
,
296 4, /* -> index of vHidd_IRQ_Serial1 in servers.c */
305 /* real time clock */
316 if (isr
& (INT0_F
|INT1_F
|INT2_F
|INT3_F
|INT4_F
|INT5_F
|INT6_F
|INT7_F
)) {
318 D(bug("--------------- Keyboard IRQ!\n"));
321 irq_desc
->id_count
++;
322 irq_desc
->id_handler
->ic_handle(irq
,
323 1, /* -> index of vHidd_IRQ_CustomD */
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 */
355 * Check for the configurable IRQs here
358 if ((isr
& PWM2_F
) && (irq
== ((ilcr
>> 4) & 0x07))) {
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
)
371 if (SysBase
->Elapsed
== 0) {
372 SysBase
->SysFlags
|= 0x2000;
373 SysBase
->AttnResched
|= 0x80;
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
)
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
)
406 struct irqServer
* _is
= AllocMem(sizeof(struct irqServer
),
407 MEMF_PUBLIC
|MEMF_CLEAR
);
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
);
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");
438 LONG (*sys_call_table
[])(struct pt_regs
) =