i386 - Get completely rid of APIC_IO
[dragonfly.git] / sys / platform / pc32 / icu / icu_vector.s
CommitLineData
984263bc
MD
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 $
21ce0dfa 4 * $DragonFly: src/sys/platform/pc32/icu/icu_vector.s,v 1.33 2008/08/02 01:14:43 dillon Exp $
97359a5b
MD
5 */
6/*
7 * WARNING! SMP builds can use the ICU now so this code must be MP safe.
984263bc
MD
8 */
9
06f5be02
MD
10#include "use_npx.h"
11#include "opt_auto_eoi.h"
12
13#include <machine/asmacros.h>
06f5be02
MD
14#include <machine/lock.h>
15#include <machine/psl.h>
16#include <machine/trap.h>
06f5be02 17
a9295349 18#include <machine_base/icu/icu.h>
21ce0dfa 19#include <bus/isa/isa.h>
06f5be02
MD
20
21#include "assym.s"
a7231bde 22#include "icu_ipl.h"
06f5be02 23
984263bc 24#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */
984263bc
MD
25
26#define ICU_EOI 0x20 /* XXX - define elsewhere */
27
ef0fdad1 28#define IRQ_LBIT(irq_num) (1 << (irq_num))
984263bc
MD
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
ef0fdad1
MD
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
984263bc
MD
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
ef0fdad1
MD
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
984263bc
MD
56#endif
57
58/*
ef0fdad1 59 * Macro helpers
984263bc 60 */
ef0fdad1
MD
61#define PUSH_FRAME \
62 pushl $0 ; /* dummy error code */ \
63 pushl $0 ; /* dummy trap type */ \
4e7c41c5 64 pushl $0 ; /* dummy xflags */ \
ef0fdad1
MD
65 pushal ; /* 8 registers */ \
66 pushl %ds ; \
67 pushl %es ; \
68 pushl %fs ; \
4e7c41c5 69 pushl %gs ; \
c885c20e 70 cld ; \
ef0fdad1
MD
71 mov $KDSEL,%ax ; \
72 mov %ax,%ds ; \
73 mov %ax,%es ; \
4e7c41c5 74 mov %ax,%gs ; \
ef0fdad1
MD
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 */ \
4e7c41c5
MD
84 pushl $0 ; /* dummy xflags */ \
85 subl $13*4,%esp ; /* pushal + 4 seg regs (dummy) + CPL */ \
984263bc 86
ef0fdad1
MD
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 \
4e7c41c5 93 popl %gs ; \
ef0fdad1
MD
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 \
4e7c41c5 101 addl $19*4,%esp ; \
ef0fdad1
MD
102
103#define MASK_IRQ(icu, irq_num) \
97359a5b 104 ICU_IMASK_LOCK ; \
06f5be02 105 movb icu_imen + IRQ_BYTE(irq_num),%al ; \
ef0fdad1 106 orb $IRQ_BIT(irq_num),%al ; \
06f5be02 107 movb %al,icu_imen + IRQ_BYTE(irq_num) ; \
ef0fdad1 108 outb %al,$icu+ICU_IMR_OFFSET ; \
97359a5b 109 ICU_IMASK_UNLOCK ; \
ef0fdad1
MD
110
111#define UNMASK_IRQ(icu, irq_num) \
477d3c1c
MD
112 cmpl $0,%eax ; \
113 jnz 8f ; \
97359a5b 114 ICU_IMASK_LOCK ; \
06f5be02 115 movb icu_imen + IRQ_BYTE(irq_num),%al ; \
ef0fdad1 116 andb $~IRQ_BIT(irq_num),%al ; \
06f5be02 117 movb %al,icu_imen + IRQ_BYTE(irq_num) ; \
ef0fdad1 118 outb %al,$icu+ICU_IMR_OFFSET ; \
97359a5b 119 ICU_IMASK_UNLOCK ; \
477d3c1c 1208: ; \
ef0fdad1
MD
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
1e9de339 136#define FAST_INTR(irq_num, vec_name, icu, enable_icus) \
ee776109
MD
137 .text ; \
138 SUPERALIGN_TEXT ; \
139IDTVEC(vec_name) ; \
ef0fdad1 140 PUSH_FRAME ; \
4e7c41c5 141 FAKE_MCOUNT(15*4(%esp)) ; \
ef0fdad1
MD
142 MASK_IRQ(icu, irq_num) ; \
143 enable_icus ; \
2954c92f 144 movl PCPU(curthread),%ebx ; \
38787eef 145 pushl $0 ; /* DUMMY CPL FOR DORETI */ \
1be5027b
MD
146 testl $-1,TD_NEST_COUNT(%ebx) ; \
147 jne 1f ; \
f9235b6d
MD
148 testl $-1,TD_CRITCOUNT(%ebx) ; \
149 je 2f ; \
ef0fdad1
MD
1501: ; \
151 /* set pending bit and return, leave interrupt masked */ \
2954c92f 152 orl $IRQ_LBIT(irq_num),PCPU(fpending) ; \
235957ed 153 orl $RQF_INTPEND, PCPU(reqflags) ; \
ef0fdad1
MD
154 jmp 5f ; \
1552: ; \
156 /* clear pending bit, run handler */ \
2954c92f 157 andl $~IRQ_LBIT(irq_num),PCPU(fpending) ; \
477d3c1c 158 pushl $irq_num ; \
c7eb0589 159 pushl %esp ; /* pass frame by reference */ \
f9235b6d 160 incl TD_CRITCOUNT(%ebx) ; \
477d3c1c 161 call ithread_fast_handler ; /* returns 0 to unmask int */ \
f9235b6d 162 decl TD_CRITCOUNT(%ebx) ; \
c7eb0589 163 addl $8,%esp ; \
ef0fdad1
MD
164 UNMASK_IRQ(icu, irq_num) ; \
1655: ; \
166 MEXITCOUNT ; \
167 jmp doreti ; \
168
169/*
ef0fdad1
MD
170 * Unmask a slow interrupt. This function is used by interrupt threads
171 * after they have descheduled themselves to reenable interrupts and
96728c05 172 * possibly cause a reschedule to occur.
ef0fdad1
MD
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 ; \
477d3c1c 181 subl %eax, %eax ; \
ef0fdad1
MD
182 UNMASK_IRQ(icu, irq_num) ; \
183 popl %ebp ; \
184 ret ; \
984263bc
MD
185
186MCOUNT_LABEL(bintr)
1e9de339
MD
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)
984263bc
MD
203MCOUNT_LABEL(eintr)
204
205 .data
984263bc
MD
206
207 .text