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