i386 - Get completely rid of APIC_IO
[dragonfly.git] / sys / platform / pc32 / icu / icu_vector.s
... / ...
CommitLineData
1/*
2 * from: vector.s, 386BSD 0.1 unknown origin
3 * $FreeBSD: src/sys/i386/isa/icu_vector.s,v 1.14.2.2 2000/07/18 21:12:42 dfr Exp $
4 * $DragonFly: src/sys/platform/pc32/icu/icu_vector.s,v 1.33 2008/08/02 01:14:43 dillon Exp $
5 */
6/*
7 * WARNING! SMP builds can use the ICU now so this code must be MP safe.
8 */
9
10#include "use_npx.h"
11#include "opt_auto_eoi.h"
12
13#include <machine/asmacros.h>
14#include <machine/lock.h>
15#include <machine/psl.h>
16#include <machine/trap.h>
17
18#include <machine_base/icu/icu.h>
19#include <bus/isa/isa.h>
20
21#include "assym.s"
22#include "icu_ipl.h"
23
24#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */
25
26#define ICU_EOI 0x20 /* XXX - define elsewhere */
27
28#define IRQ_LBIT(irq_num) (1 << (irq_num))
29#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8))
30#define IRQ_BYTE(irq_num) ((irq_num) >> 3)
31
32#ifdef AUTO_EOI_1
33#define ENABLE_ICU1 /* use auto-EOI to reduce i/o */
34#define OUTB_ICU1
35#else
36#define ENABLE_ICU1 \
37 movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \
38 OUTB_ICU1 ; /* ... to clear in service bit */ \
39
40#define OUTB_ICU1 \
41 outb %al,$IO_ICU1 ; \
42
43#endif
44
45#ifdef AUTO_EOI_2
46/*
47 * The data sheet says no auto-EOI on slave, but it sometimes works.
48 */
49#define ENABLE_ICU1_AND_2 ENABLE_ICU1
50#else
51#define ENABLE_ICU1_AND_2 \
52 movb $ICU_EOI,%al ; /* as above */ \
53 outb %al,$IO_ICU2 ; /* but do second icu first ... */ \
54 OUTB_ICU1 ; /* ... then first icu (if !AUTO_EOI_1) */ \
55
56#endif
57
58/*
59 * Macro helpers
60 */
61#define PUSH_FRAME \
62 pushl $0 ; /* dummy error code */ \
63 pushl $0 ; /* dummy trap type */ \
64 pushl $0 ; /* dummy xflags */ \
65 pushal ; /* 8 registers */ \
66 pushl %ds ; \
67 pushl %es ; \
68 pushl %fs ; \
69 pushl %gs ; \
70 cld ; \
71 mov $KDSEL,%ax ; \
72 mov %ax,%ds ; \
73 mov %ax,%es ; \
74 mov %ax,%gs ; \
75 mov $KPSEL,%ax ; \
76 mov %ax,%fs ; \
77
78#define PUSH_DUMMY \
79 pushfl ; /* phys int frame / flags */ \
80 pushl %cs ; /* phys int frame / cs */ \
81 pushl 12(%esp) ; /* original caller eip */ \
82 pushl $0 ; /* dummy error code */ \
83 pushl $0 ; /* dummy trap type */ \
84 pushl $0 ; /* dummy xflags */ \
85 subl $13*4,%esp ; /* pushal + 4 seg regs (dummy) + CPL */ \
86
87/*
88 * Warning: POP_FRAME can only be used if there is no chance of a
89 * segment register being changed (e.g. by procfs), which is why syscalls
90 * have to use doreti.
91 */
92#define POP_FRAME \
93 popl %gs ; \
94 popl %fs ; \
95 popl %es ; \
96 popl %ds ; \
97 popal ; \
98 addl $2*4,%esp ; /* dummy trap & error codes */ \
99
100#define POP_DUMMY \
101 addl $19*4,%esp ; \
102
103#define MASK_IRQ(icu, irq_num) \
104 ICU_IMASK_LOCK ; \
105 movb icu_imen + IRQ_BYTE(irq_num),%al ; \
106 orb $IRQ_BIT(irq_num),%al ; \
107 movb %al,icu_imen + IRQ_BYTE(irq_num) ; \
108 outb %al,$icu+ICU_IMR_OFFSET ; \
109 ICU_IMASK_UNLOCK ; \
110
111#define UNMASK_IRQ(icu, irq_num) \
112 cmpl $0,%eax ; \
113 jnz 8f ; \
114 ICU_IMASK_LOCK ; \
115 movb icu_imen + IRQ_BYTE(irq_num),%al ; \
116 andb $~IRQ_BIT(irq_num),%al ; \
117 movb %al,icu_imen + IRQ_BYTE(irq_num) ; \
118 outb %al,$icu+ICU_IMR_OFFSET ; \
119 ICU_IMASK_UNLOCK ; \
1208: ; \
121
122/*
123 * Fast interrupt call handlers run in the following sequence:
124 *
125 * - Push the trap frame required by doreti.
126 * - Mask the interrupt and reenable its source.
127 * - If we cannot take the interrupt set its fpending bit and
128 * doreti.
129 * - If we can take the interrupt clear its fpending bit,
130 * call the handler, then unmask the interrupt and doreti.
131 *
132 * YYY can cache gd base pointer instead of using hidden %fs
133 * prefixes.
134 */
135
136#define FAST_INTR(irq_num, vec_name, icu, enable_icus) \
137 .text ; \
138 SUPERALIGN_TEXT ; \
139IDTVEC(vec_name) ; \
140 PUSH_FRAME ; \
141 FAKE_MCOUNT(15*4(%esp)) ; \
142 MASK_IRQ(icu, irq_num) ; \
143 enable_icus ; \
144 movl PCPU(curthread),%ebx ; \
145 pushl $0 ; /* DUMMY CPL FOR DORETI */ \
146 testl $-1,TD_NEST_COUNT(%ebx) ; \
147 jne 1f ; \
148 testl $-1,TD_CRITCOUNT(%ebx) ; \
149 je 2f ; \
1501: ; \
151 /* set pending bit and return, leave interrupt masked */ \
152 orl $IRQ_LBIT(irq_num),PCPU(fpending) ; \
153 orl $RQF_INTPEND, PCPU(reqflags) ; \
154 jmp 5f ; \
1552: ; \
156 /* clear pending bit, run handler */ \
157 andl $~IRQ_LBIT(irq_num),PCPU(fpending) ; \
158 pushl $irq_num ; \
159 pushl %esp ; /* pass frame by reference */ \
160 incl TD_CRITCOUNT(%ebx) ; \
161 call ithread_fast_handler ; /* returns 0 to unmask int */ \
162 decl TD_CRITCOUNT(%ebx) ; \
163 addl $8,%esp ; \
164 UNMASK_IRQ(icu, irq_num) ; \
1655: ; \
166 MEXITCOUNT ; \
167 jmp doreti ; \
168
169/*
170 * Unmask a slow interrupt. This function is used by interrupt threads
171 * after they have descheduled themselves to reenable interrupts and
172 * possibly cause a reschedule to occur.
173 */
174
175#define INTR_UNMASK(irq_num, vec_name, icu) \
176 .text ; \
177 SUPERALIGN_TEXT ; \
178IDTVEC(vec_name) ; \
179 pushl %ebp ; /* frame for ddb backtrace */ \
180 movl %esp, %ebp ; \
181 subl %eax, %eax ; \
182 UNMASK_IRQ(icu, irq_num) ; \
183 popl %ebp ; \
184 ret ; \
185
186MCOUNT_LABEL(bintr)
187 FAST_INTR(0,icu_fastintr0, IO_ICU1, ENABLE_ICU1)
188 FAST_INTR(1,icu_fastintr1, IO_ICU1, ENABLE_ICU1)
189 FAST_INTR(2,icu_fastintr2, IO_ICU1, ENABLE_ICU1)
190 FAST_INTR(3,icu_fastintr3, IO_ICU1, ENABLE_ICU1)
191 FAST_INTR(4,icu_fastintr4, IO_ICU1, ENABLE_ICU1)
192 FAST_INTR(5,icu_fastintr5, IO_ICU1, ENABLE_ICU1)
193 FAST_INTR(6,icu_fastintr6, IO_ICU1, ENABLE_ICU1)
194 FAST_INTR(7,icu_fastintr7, IO_ICU1, ENABLE_ICU1)
195 FAST_INTR(8,icu_fastintr8, IO_ICU2, ENABLE_ICU1_AND_2)
196 FAST_INTR(9,icu_fastintr9, IO_ICU2, ENABLE_ICU1_AND_2)
197 FAST_INTR(10,icu_fastintr10, IO_ICU2, ENABLE_ICU1_AND_2)
198 FAST_INTR(11,icu_fastintr11, IO_ICU2, ENABLE_ICU1_AND_2)
199 FAST_INTR(12,icu_fastintr12, IO_ICU2, ENABLE_ICU1_AND_2)
200 FAST_INTR(13,icu_fastintr13, IO_ICU2, ENABLE_ICU1_AND_2)
201 FAST_INTR(14,icu_fastintr14, IO_ICU2, ENABLE_ICU1_AND_2)
202 FAST_INTR(15,icu_fastintr15, IO_ICU2, ENABLE_ICU1_AND_2)
203MCOUNT_LABEL(eintr)
204
205 .data
206
207 .text