2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Interrupt core, part of kernel.resource
11 //#include "include/machine.i"
13 #include <exec/types.h>
14 #include <exec/execbase.h>
17 #define __text __attribute__((section(".text")))
19 struct view
{ unsigned char sign
; unsigned char attr
; };
21 extern unsigned int cached_irq_mask
;
22 extern unsigned long io_apic_irqs
;
23 extern struct irqDescriptor irq_desc
[];
24 void handle_IRQ_event(unsigned int irq
, struct pt_regs
* regs
, struct irqServer
* is
);
27 * Build all interrupt assemble code needed. We use some very ugly macros
28 * which were taken from linux sources.
36 #define BUILD_16_IRQS(x) \
37 BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
38 BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
39 BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
40 BI(x,c) BI(x,d) BI(x,e) BI(x,f)
43 * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
44 * (these are usually mapped to vectors 0x20-0x30)
52 (const void (*)(void))IRQ##x##y##_interrupt
54 #define IRQLIST_16(x) \
55 IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
56 IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
57 IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
58 IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
60 const void (*interrupt
[NR_IRQS
])(void) __text
= {
68 * This is the 'legacy' 8259A Programmable Interrupt Controller,
69 * present in the majority of PC/AT boxes.
72 static void do_8259A_IRQ(unsigned int, struct pt_regs
*);
73 static void enable_8259A_irq(unsigned int);
74 void disable_8259A_irq(unsigned int);
76 #define startup_8259A_irq enable_8259A_irq
77 #define shutdown_8259A_irq disable_8259A_irq
79 static const struct irqController i8259_controller
=
89 #define __byte(x,y) (((unsigned char *)&(y))[x])
90 #define cached_21 (__byte(0,cached_irq_mask))
91 #define cached_A1 (__byte(1,cached_irq_mask))
93 void disable_8259A_irq(unsigned int irq
)
95 cached_irq_mask
|= (1 << irq
);
98 outb(cached_A1
, 0xa1);
101 outb(cached_21
, 0x21);
105 static void enable_8259A_irq(unsigned int irq
)
107 cached_irq_mask
&= ~(1 << irq
);
109 outb(cached_A1
,0xA1);
111 outb(cached_21
,0x21);
116 * Careful! The 8259A is a fragile beast, it pretty
117 * much _has_ to be done exactly like this (mask it
118 * first, _then_ send the EOI, and the order of EOI
119 * to the two 8259s is important!
121 static inline void mask_and_ack_8259A(unsigned int irq
)
123 cached_irq_mask
|= 1 << irq
;
125 // inb(0xA1); /* DUMMY */
126 outb(cached_A1
,0xA1);
127 outb(0x62,0x20); /* Specific EOI to cascade */
130 // inb(0x21); /* DUMMY */
131 outb(cached_21
,0x21);
136 static void do_8259A_IRQ(unsigned int irq
, struct pt_regs
* regs
)
138 struct irqServer
* iServer
;
139 struct irqDescriptor
*desc
= &irq_desc
[irq
];
143 mask_and_ack_8259A(irq
);
144 status
= desc
->id_status
& ~(IRQ_REPLAY
| IRQ_WAITING
);
146 if (!(status
& (IRQ_DISABLED
| IRQ_INPROGRESS
))) {
147 iServer
= desc
->id_server
;
148 status
|= IRQ_INPROGRESS
;
150 desc
->id_status
= status
;
153 /* Exit early if we had no action or it was disabled */
157 handle_IRQ_event(irq
, regs
, iServer
);
160 unsigned int status
= desc
->id_status
& ~IRQ_INPROGRESS
;
161 desc
->id_status
= status
;
162 if (!(status
& IRQ_DISABLED
))
163 enable_8259A_irq(irq
);
167 /*******************************************************************************
168 Lowlevel IRQ functions used by each controller
169 *******************************************************************************/
171 void handle_IRQ_event(unsigned int irq
, struct pt_regs
* regs
, struct irqServer
* is
)
174 is
->is_handler(irq
, is
->is_UserData
, regs
);
179 * Generic enable/disable code: this just calls
180 * down into the PIC-specific version for the actual
181 * hardware disable after having gotten the irq
184 void disable_irq_nosync(unsigned int irq
)
186 if (!irq_desc
[irq
].id_depth
++) {
187 irq_desc
[irq
].id_status
|= IRQ_DISABLED
;
188 irq_desc
[irq
].id_handler
->ic_disable(irq
);
193 * Synchronous version of the above, making sure the IRQ is
194 * no longer running on any other IRQ..
196 void disable_irq(unsigned int irq
)
198 disable_irq_nosync(irq
);
201 void enable_irq(unsigned int irq
)
203 switch (irq_desc
[irq
].id_depth
)
207 irq_desc
[irq
].id_status
&= ~IRQ_DISABLED
;
208 irq_desc
[irq
].id_handler
->ic_enable(irq
);
211 irq_desc
[irq
].id_depth
--;
216 * do_IRQ handles all normal device IRQ's (the special
217 * SMP cross-CPU interrupts have their own specific
220 asmlinkage
void do_IRQ(struct pt_regs regs
)
223 * We ack quickly, we don't want the irq controller
224 * thinking we're snobs just because some other CPU has
225 * disabled global interrupts (we have already done the
226 * INT_ACK cycles, it's too late to try to pretend to the
227 * controller that we aren't taking the interrupt).
229 * 0 return value means that this irq is already being
230 * handled by some other CPU. (or is disabled)
233 irq_desc
[regs
.orig_eax
].id_count
++;
234 irq_desc
[regs
.orig_eax
].id_handler
->ic_handle(regs
.orig_eax
, ®s
);
240 ((struct view
*)0xb8000)[64+i
].attr
= 0x1f;
241 ((struct view
*)0xb8000)[64+i
].sign
=
242 (irq_desc
[i
].id_count
& 7) ? '0' + (irq_desc
[i
].id_count
& 7):'.';
249 extern struct ExecBase
*SysBase
;
253 static void VBL_handler(int i
, void *user
, struct pt_regs
*regs
)
255 if (SysBase
->Elapsed
== 0)
257 SysBase
->SysFlags
|= 0x2000;
258 SysBase
->AttnResched
|= 0x80;
260 else SysBase
->Elapsed
--;
263 static struct irqServer VBlank
= { VBL_handler
, "VBlank", NULL
};
266 #define LATCH ((1193180 + 25)/50)
268 void irqSet(int irq
, struct irqServer
*is
)
272 irq_desc
[irq
].id_server
= is
;
273 irq_desc
[irq
].id_depth
= 0;
274 irq_desc
[irq
].id_status
&= ~IRQ_DISABLED
;
275 irq_desc
[irq
].id_handler
->ic_startup(irq
);
283 cached_irq_mask
= 0xffff;
289 :"eax"(0), /* FIll with 0 */
290 "D"(&irq_desc
), /* irq_desc table */
293 bzero(&irq_desc
, 512);
296 for (i
= 0; i
<NR_IRQS
; i
++)
298 irq_desc
[i
].id_handler
= &i8259_controller
;
299 irq_desc
[i
].id_status
= IRQ_DISABLED
;
300 irq_desc
[i
].id_depth
= 0;
301 irq_desc
[i
].id_server
= 0;
303 set_intr_gate(FIRST_EXT_VECTOR
+ i
, interrupt
[i
]);
306 outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
307 outb_p(LATCH
& 0xff , 0x40); /* LSB */
308 outb(LATCH
>> 8 , 0x40); /* MSB */
310 irq_desc
[0].id_server
= &VBlank
;
311 irq_desc
[0].id_depth
= 0;
312 irq_desc
[0].id_status
&= ~IRQ_DISABLED
;
313 irq_desc
[0].id_handler
->ic_startup(0);
320 int sys_Cause(struct pt_regs
);
321 int sys_Supervisor(struct pt_regs
);
322 int sys_None(struct pt_regs regs
) { return 0; }
324 asmlinkage
int sys_ColdReboot(struct pt_regs regs
)
326 __asm__("jmp kernel_startup");
330 int (*sys_call_table
[])(struct pt_regs
) __text
=