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 $
7 * WARNING! SMP builds can use the ICU now so this code must be MP safe.
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>
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)
35 #define ENABLE_ICU1 /* use auto-EOI to reduce i/o */
39 movb $ICU_EOI
,%al ;
/* as soon as possible send EOI ... */ \
40 OUTB_ICU1 ;
/* ... to clear in service bit */ \
49 * The data sheet says no auto-EOI on slave, but it sometimes works.
51 #define ENABLE_ICU1_AND_2 ENABLE_ICU1
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) */ \
64 pushl $
0 ;
/* dummy error code */ \
65 pushl $
0 ;
/* dummy trap type */ \
66 pushl $
0 ;
/* dummy xflags */ \
67 pushal ;
/* 8 registers */ \
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
100 addl $
2*4,%esp ;
/* dummy trap & error codes */ \
105 #define MASK_IRQ(icu, irq_num) \
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 ; \
113 #define UNMASK_IRQ(icu, irq_num) \
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 ; \
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
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
138 #define FAST_INTR(irq_num, vec_name, icu, enable_icus) \
143 FAKE_MCOUNT
(15*4(%esp
)) ; \
144 MASK_IRQ
(icu
, irq_num
) ; \
146 movl PCPU
(curthread
),%ebx ; \
147 pushl $
0 ;
/* DUMMY CPL FOR DORETI */ \
148 testl $
-1,TD_NEST_COUNT
(%ebx
) ; \
150 cmpl $TDPRI_CRIT
,TD_PRI
(%ebx
) ; \
153 /* set pending bit and return, leave interrupt masked */ \
154 orl $IRQ_LBIT
(irq_num
),PCPU
(fpending
) ; \
155 orl $RQF_INTPEND
, PCPU
(reqflags
) ; \
158 /* clear pending bit, run handler */ \
159 andl $~IRQ_LBIT
(irq_num
),PCPU
(fpending
) ; \
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
) ; \
166 UNMASK_IRQ
(icu
, irq_num
) ; \
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) \
181 pushl
%ebp ;
/* frame for ddb backtrace */ \
184 UNMASK_IRQ
(icu
, irq_num
) ; \
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
)