FreeBSD/Linux Kernel Cross Reference
sys/i386/interrupt.s
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
4 * Copyright (c) 1991 IBM Corporation
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation,
12 * and that the name IBM not be used in advertising or publicity
13 * pertaining to distribution of the software without specific, written
14 * prior permission.
15 *
16 * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie Mellon
28 * the rights to redistribute these changes.
29 */
30
31
32 /*
33 * HISTORY
34 * $Log: interrupt.s,v $
35 * Revision 2.17 93/11/17 16:36:09 dbg
36 * PIC addresses are constants (and known to be <= 0xff), so they
37 * can be used as immediate addresses in IN and OUT instructions.
38 * [93/10/29 dbg]
39 *
40 * The reason that the spurious interrupt check has never worked is
41 * that the non-specific EOI has already CLEARED the ISR bit that we
42 * are checking!
43 * [93/10/25 dbg]
44 *
45 * Changes from ralf@chpc.org: handle spuroius interrupts
46 * generated by Adaptec 174x.
47 * [93/10/20 13:03:31 af]
48 *
49 * Revision 2.16 93/02/04 07:56:24 danner
50 * Convert asm comment "/" over to "/ *" "* /"
51 * [93/01/28 rvb]
52 *
53 * Integrate PS2 code from IBM.
54 * [93/01/18 prithvi]
55 *
56 * Revision 2.15 92/04/06 01:15:53 rpd
57 * Converted from #-style to /-style comments, for ANSI preprocessors.
58 * [92/04/05 rpd]
59 *
60 * Revision 2.14 91/10/07 17:24:48 af
61 * From mg32: testing for spurious interrupts is bogus.
62 * [91/09/23 rvb]
63 *
64 * Revision 2.13 91/08/28 21:31:06 jsb
65 * Check for out-of-range interrupts.
66 * [91/08/20 dbg]
67 *
68 * Revision 2.12 91/07/31 17:37:31 dbg
69 * Support separate interrupt stack. Interrupt handler may now be
70 * called from different places.
71 * [91/07/30 16:52:19 dbg]
72 *
73 * Revision 2.11 91/06/19 11:55:12 rvb
74 * cputypes.h->platforms.h
75 * [91/06/12 13:44:55 rvb]
76 *
77 * Revision 2.10 91/05/14 16:09:08 mrt
78 * Correcting copyright
79 *
80 * Revision 2.9 91/05/08 12:38:18 dbg
81 * Put parentheses around substituted immediate expressions, so
82 * that they will pass through the GNU preprocessor.
83 *
84 * Use platforms.h. Call version of set_spl that leaves interrupts
85 * disabled (IF clear) until iret.
86 * [91/04/26 14:35:53 dbg]
87 *
88 * Revision 2.8 91/02/05 17:12:22 mrt
89 * Changed to new Mach copyright
90 * [91/02/01 17:34:58 mrt]
91 *
92 * Revision 2.7 91/01/08 17:32:06 rpd
93 * Need special interrupt_return
94 * [90/12/21 14:36:12 rvb]
95 *
96 * Revision 2.6 90/12/20 16:35:58 jeffreyh
97 * Changes for __STDC__
98 * [90/12/07 15:43:38 jeffreyh]
99 *
100 * Revision 2.5 90/12/04 14:46:08 jsb
101 * iPSC2 -> iPSC386.
102 * [90/12/04 11:16:47 jsb]
103 *
104 * Revision 2.4 90/11/26 14:48:33 rvb
105 * Change Prime copyright as per Peter J. Weyman authorization.
106 * [90/11/19 rvb]
107 *
108 * Revision 2.3 90/09/23 17:45:14 jsb
109 * Added support for iPSC2.
110 * [90/09/21 16:40:09 jsb]
111 *
112 * Revision 2.2 90/05/03 15:27:54 dbg
113 * Stole from Prime.
114 * Pass new parameters to clock_interrupt (no longer called
115 * hardclock). Set curr_ipl correctly around call to clock_interrupt.
116 * Moved softclock logic to splx.
117 * Added kdb_kintr to find registers for kdb.
118 * [90/02/14 dbg]
119 *
120 */
121
122 /*
123 Copyright (c) 1988,1989 Prime Computer, Inc. Natick, MA 01760
124 All Rights Reserved.
125
126 Permission to use, copy, modify, and distribute this
127 software and its documentation for any purpose and
128 without fee is hereby granted, provided that the above
129 copyright notice appears in all copies and that both the
130 copyright notice and this permission notice appear in
131 supporting documentation, and that the name of Prime
132 Computer, Inc. not be used in advertising or publicity
133 pertaining to distribution of the software without
134 specific, written prior permission.
135
136 THIS SOFTWARE IS PROVIDED "AS IS", AND PRIME COMPUTER,
137 INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
138 SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
139 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
140 NO EVENT SHALL PRIME COMPUTER, INC. BE LIABLE FOR ANY
141 SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
142 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
143 PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR
144 OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
145 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
146 */
147
148 #include <platforms.h>
149
150 #include <i386/asm.h>
151 #include <i386/ipl.h>
152 #include <i386/pic.h>
153 #include <assym.s>
154
155 /*
156 * Called from locore.s. The register save area is on top
157 * of the stack. %eax contains the interrupt number.
158 * Only %ecx and %edx have been saved.
159 */
160 ENTRY(interrupt)
161
162 movl %eax,%ecx /* stash interrupt vector number */
163 subl $0x40,%ecx /* interrupt vectors we use */
164 /* start at 0x40, not 0 */
165 jl int_range_err /* and are between 0x40 */
166 cmpl $15,%ecx /* and 0x4f */
167 jg int_range_err
168
169 /*
170 * Check for spurious interrupt. A level 7 (for master) or
171 * level 15 (slave) interrupt can occur if the INT line is
172 * dropped too soon. We check for this by reading the
173 * Interrupt Service Register (BEFORE clearing it with EOI!!)
174 * and testing for bit 7. If it is zero, the interrupt
175 * was spurious.
176 */
177
178 movw $(MASTER_ICW), %dx /* point to master PIC */
179
180 #if defined(AT386) || defined(PS2)
181 cmpl $2,%ecx /* IRQ 2 is the slave cascade */
182 je spurious_interrupt /* interrupt - ignore it. */
183 #endif
184
185 cmpl $7,%ecx /* master - level 7? */
186 je int_check
187 cmpl $15,%ecx /* slave - level 15? */
188 jne int_ok
189 addw $(SIZE_PIC),%dx /* if so, point to slave PIC */
190 int_check:
191 movw $(OCW_TEMPLATE | READ_NEXT_RD | READ_IS_ONRD), %ax
192 outb %al,%dx /* ask to read ISR */
193 jmp 0f /* delay XXX */
194 0:
195 inb %dx,%al /* read ISR */
196 testb $0x80, %al /* if ISR.7 is off, */
197 jz spurious_interrupt /* this is a spurious interrupt */
198 int_ok:
199
200 #ifndef PS2
201 /*
202 * Now we must acknowledge the interrupt and issue an EOI command to
203 * the pics. We send a NON-SPECIFIC EOI, as we assume that the pic
204 * automatically interrupts us with only the highest priority interrupt.
205 */
206
207 movb $(NON_SPEC_EOI),%al
208 outb %al,$(MASTER_ICW) /* EOI for master */
209 nop; nop; /* give the bus some breathing room */
210 outb %al,$(SLAVE_ICW) /* EOI for slave */
211 #endif /* not PS2 */
212
213 /*
214 * Now we must change the interrupt priority level, with interrupts
215 * turned off. First we get the interrupt number and get
216 * the interrupt level associated with it, then we call set_spl().
217 */
218
219 movzbl _intpri(%ecx),%eax /* intpri[int#] */
220 call _set_spl /* set SPL */
221
222 /*
223 * Interrupts are now enabled. Call the relevant interrupt
224 * handler as per the ivect[] array set up in pic_init.
225 */
226
227 pushl %eax /* 2 save old IPL */
228 #ifdef PS2
229 pushl %ecx /* 2 save intr # */
230 #endif
231 pushl _iunit(,%ecx,4) /* 2 push unit# as int handler arg */
232 call *_ivect(,%ecx,4) /* 4 *ivect[int#]() */
233 addl $4,%esp /* remove interrupt number from stack */
234 #ifdef PS2
235 popl %ecx /* 2 save intr # */
236 #endif
237 cli /* 3 disable interrupts */
238
239 #ifdef PS2
240 /*
241 * Now we must acknowledge the interrupt and issue an EOI command to
242 * the pics. We send a SPECIFIC EOI.
243 */
244 mov %ecx,%eax
245 cmp $7,%ecx
246 jle do_master
247 andb $7,%al
248 orb $(SPECIFIC_EOI),%al
249 outb %al,$(SLAVE_ICW)
250 movb $2,%al
251 do_master:
252 orb $(SPECIFIC_EOI),%al
253 outb %al,$(MASTER_ICW)
254 #endif /* PS2 */
255
256 /*
257 * 5. Having dealt with the interrupt now we must return to the previous
258 * interrupt priority level. This is done with interrupts turned off.
259 */
260
261 popl %eax /* get old IPL from stack */
262 jmp _set_spl_noi /* set old SPL, and return to */
263 /* our caller. */
264 /*
265 * Spurious interrupt. Send the EOI anyway (XXX),
266 * and return.
267 */
268 spurious_interrupt:
269 movb $(NON_SPEC_EOI),%al
270 outb %al,$(MASTER_ICW) /* EOI for master */
271 nop; nop; /* give the bus some breathing room */
272 outb %al,$(SLAVE_ICW) /* EOI for slave */
273 ret
274
275 /*
276 * Interrupt number out of range.
277 */
278 int_range_err:
279 addl $0x40,%ecx /* restore original interrupt number */
280 pushl %ecx /* push number */
281 pushl $int_range_message /* push message */
282 call _panic /* panic */
283 addl $8,%esp /* pop stack */
284 ret /* return to caller */
285
286 int_range_message:
287 .ascii "Bad interrupt number %#x"
288 .byte 0
289
Cache object: e0fab2af5b547c36950058f8020fa528
|