1 /*
2 * from: vector.s, 386BSD 0.1 unknown origin
3 * $FreeBSD$
4 */
5
6 /*
7 * modified for PC98 by Kakefuda
8 */
9
10 #ifdef PC98
11 #define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */
12 #else
13 #define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */
14 #endif
15
16 #define ICU_EOI 0x20 /* XXX - define elsewhere */
17
18 #define IRQ_BIT(irq_num) (1 << ((irq_num) % 8))
19 #define IRQ_BYTE(irq_num) ((irq_num) >> 3)
20
21 #ifdef AUTO_EOI_1
22 #define ENABLE_ICU1 /* use auto-EOI to reduce i/o */
23 #define OUTB_ICU1
24 #else
25 #define ENABLE_ICU1 \
26 movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \
27 OUTB_ICU1 /* ... to clear in service bit */
28 #define OUTB_ICU1 \
29 outb %al,$IO_ICU1
30 #endif
31
32 #ifdef AUTO_EOI_2
33 /*
34 * The data sheet says no auto-EOI on slave, but it sometimes works.
35 */
36 #define ENABLE_ICU1_AND_2 ENABLE_ICU1
37 #else
38 #define ENABLE_ICU1_AND_2 \
39 movb $ICU_EOI,%al ; /* as above */ \
40 outb %al,$IO_ICU2 ; /* but do second icu first ... */ \
41 OUTB_ICU1 /* ... then first icu (if !AUTO_EOI_1) */
42 #endif
43
44 /*
45 * Macros for interrupt interrupt entry, call to handler, and exit.
46 */
47
48 #define FAST_INTR(irq_num, vec_name, enable_icus) \
49 .text ; \
50 SUPERALIGN_TEXT ; \
51 IDTVEC(vec_name) ; \
52 pushl %eax ; /* save only call-used registers */ \
53 pushl %ecx ; \
54 pushl %edx ; \
55 pushl %ds ; \
56 MAYBE_PUSHL_ES ; \
57 movl $KDSEL,%eax ; \
58 movl %ax,%ds ; \
59 MAYBE_MOVW_AX_ES ; \
60 FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \
61 pushl _intr_unit + (irq_num) * 4 ; \
62 call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \
63 enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \
64 addl $4,%esp ; \
65 incl _cnt+V_INTR ; /* book-keeping can wait */ \
66 movl _intr_countp + (irq_num) * 4,%eax ; \
67 incl (%eax) ; \
68 movl _cpl,%eax ; /* are we unmasking pending HWIs or SWIs? */ \
69 notl %eax ; \
70 andl _ipending,%eax ; \
71 jne 2f ; /* yes, maybe handle them */ \
72 1: ; \
73 MEXITCOUNT ; \
74 MAYBE_POPL_ES ; \
75 popl %ds ; \
76 popl %edx ; \
77 popl %ecx ; \
78 popl %eax ; \
79 iret ; \
80 ; \
81 ALIGN_TEXT ; \
82 2: ; \
83 cmpb $3,_intr_nesting_level ; /* is there enough stack? */ \
84 jae 1b ; /* no, return */ \
85 movl _cpl,%eax ; \
86 /* XXX next line is probably unnecessary now. */ \
87 movl $HWI_MASK|SWI_MASK,_cpl ; /* limit nesting ... */ \
88 incb _intr_nesting_level ; /* ... really limit it ... */ \
89 sti ; /* ... to do this as early as possible */ \
90 MAYBE_POPL_ES ; /* discard most of thin frame ... */ \
91 popl %ecx ; /* ... original %ds ... */ \
92 popl %edx ; \
93 xchgl %eax,4(%esp) ; /* orig %eax; save cpl */ \
94 pushal ; /* build fat frame (grrr) ... */ \
95 pushl %ecx ; /* ... actually %ds ... */ \
96 pushl %es ; \
97 movl $KDSEL,%eax ; \
98 movl %ax,%es ; \
99 movl (2+8+0)*4(%esp),%ecx ; /* ... %ecx from thin frame ... */ \
100 movl %ecx,(2+6)*4(%esp) ; /* ... to fat frame ... */ \
101 movl (2+8+1)*4(%esp),%eax ; /* ... cpl from thin frame */ \
102 pushl %eax ; \
103 subl $4,%esp ; /* junk for unit number */ \
104 MEXITCOUNT ; \
105 jmp _doreti
106
107 #define INTR(irq_num, vec_name, icu, enable_icus, reg) \
108 .text ; \
109 SUPERALIGN_TEXT ; \
110 IDTVEC(vec_name) ; \
111 pushl $0 ; /* dummy error code */ \
112 pushl $0 ; /* dummy trap type */ \
113 pushal ; \
114 pushl %ds ; /* save our data and extra segments ... */ \
115 pushl %es ; \
116 movl $KDSEL,%eax ; /* ... and reload with kernel's own ... */ \
117 movl %ax,%ds ; /* ... early for obsolete reasons */ \
118 movl %ax,%es ; \
119 movb _imen + IRQ_BYTE(irq_num),%al ; \
120 orb $IRQ_BIT(irq_num),%al ; \
121 movb %al,_imen + IRQ_BYTE(irq_num) ; \
122 outb %al,$icu+ICU_IMR_OFFSET ; \
123 enable_icus ; \
124 movl _cpl,%eax ; \
125 testb $IRQ_BIT(irq_num),%reg ; \
126 jne 2f ; \
127 incb _intr_nesting_level ; \
128 __CONCAT(Xresume,irq_num): ; \
129 FAKE_MCOUNT(12*4(%esp)) ; /* XXX late to avoid double count */ \
130 incl _cnt+V_INTR ; /* tally interrupts */ \
131 movl _intr_countp + (irq_num) * 4,%eax ; \
132 incl (%eax) ; \
133 movl _cpl,%eax ; \
134 pushl %eax ; \
135 pushl _intr_unit + (irq_num) * 4 ; \
136 orl _intr_mask + (irq_num) * 4,%eax ; \
137 movl %eax,_cpl ; \
138 sti ; \
139 call *_intr_handler + (irq_num) * 4 ; \
140 cli ; /* must unmask _imen and icu atomically */ \
141 movb _imen + IRQ_BYTE(irq_num),%al ; \
142 andb $~IRQ_BIT(irq_num),%al ; \
143 movb %al,_imen + IRQ_BYTE(irq_num) ; \
144 outb %al,$icu+ICU_IMR_OFFSET ; \
145 sti ; /* XXX _doreti repeats the cli/sti */ \
146 MEXITCOUNT ; \
147 /* We could usually avoid the following jmp by inlining some of */ \
148 /* _doreti, but it's probably better to use less cache. */ \
149 jmp _doreti ; \
150 ; \
151 ALIGN_TEXT ; \
152 2: ; \
153 /* XXX skip mcounting here to avoid double count */ \
154 orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \
155 popl %es ; \
156 popl %ds ; \
157 popal ; \
158 addl $4+4,%esp ; \
159 iret
160
161 MCOUNT_LABEL(bintr)
162 FAST_INTR(0,fastintr0, ENABLE_ICU1)
163 FAST_INTR(1,fastintr1, ENABLE_ICU1)
164 FAST_INTR(2,fastintr2, ENABLE_ICU1)
165 FAST_INTR(3,fastintr3, ENABLE_ICU1)
166 FAST_INTR(4,fastintr4, ENABLE_ICU1)
167 FAST_INTR(5,fastintr5, ENABLE_ICU1)
168 FAST_INTR(6,fastintr6, ENABLE_ICU1)
169 FAST_INTR(7,fastintr7, ENABLE_ICU1)
170 FAST_INTR(8,fastintr8, ENABLE_ICU1_AND_2)
171 FAST_INTR(9,fastintr9, ENABLE_ICU1_AND_2)
172 FAST_INTR(10,fastintr10, ENABLE_ICU1_AND_2)
173 FAST_INTR(11,fastintr11, ENABLE_ICU1_AND_2)
174 FAST_INTR(12,fastintr12, ENABLE_ICU1_AND_2)
175 FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2)
176 FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2)
177 FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2)
178 INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al)
179 INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al)
180 INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al)
181 INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al)
182 INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al)
183 INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al)
184 INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al)
185 INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al)
186 INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah)
187 INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah)
188 INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah)
189 INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah)
190 INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah)
191 INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah)
192 INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah)
193 INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah)
194 MCOUNT_LABEL(eintr)
195
196 .data
197 .globl _ihandlers
198 _ihandlers: /* addresses of interrupt handlers */
199 /* actually resumption addresses for HWI's */
200 .long Xresume0, Xresume1, Xresume2, Xresume3
201 .long Xresume4, Xresume5, Xresume6, Xresume7
202 .long Xresume8, Xresume9, Xresume10, Xresume11
203 .long Xresume12, Xresume13, Xresume14, Xresume15
204 .long _swi_null, swi_net, _swi_null, _swi_null
205 .long _swi_vm, _swi_null, _swi_null, _swi_null
206 .long _swi_null, _swi_null, _swi_null, _swi_null
207 .long _swi_null, _swi_null, _softclock, swi_ast
208
209 imasks: /* masks for interrupt handlers */
210 .space NHWI*4 /* padding; HWI masks are elsewhere */
211
212 .long SWI_TTY_MASK, SWI_NET_MASK, SWI_CAMNET_MASK, SWI_CAMBIO_MASK
213 .long SWI_VM_MASK, 0, 0, 0
214 .long 0, 0, 0, 0
215 .long 0, 0, SWI_CLOCK_MASK, SWI_AST_MASK
216
217 /*
218 * Interrupt counters and names. The format of these and the label names
219 * must agree with what vmstat expects. The tables are indexed by device
220 * ids so that we don't have to move the names around as devices are
221 * attached.
222 */
223 #include "vector.h"
224 .globl _intrcnt, _eintrcnt
225 _intrcnt:
226 .space (NR_DEVICES + ICU_LEN) * 4
227 _eintrcnt:
228
229 .globl _intrnames, _eintrnames
230 _intrnames:
231 .ascii DEVICE_NAMES
232 .asciz "stray irq0"
233 .asciz "stray irq1"
234 .asciz "stray irq2"
235 .asciz "stray irq3"
236 .asciz "stray irq4"
237 .asciz "stray irq5"
238 .asciz "stray irq6"
239 .asciz "stray irq7"
240 .asciz "stray irq8"
241 .asciz "stray irq9"
242 .asciz "stray irq10"
243 .asciz "stray irq11"
244 .asciz "stray irq12"
245 .asciz "stray irq13"
246 .asciz "stray irq14"
247 .asciz "stray irq15"
248 _eintrnames:
249
250 .text
Cache object: 7e182d18a7a7a3908f12f9b96d10608c
|