xref: /original-bsd/sys/i386/isa/icu.s (revision 36940495)
1/*-
2 * Copyright (C) 1989, 1990 W. Jolitz
3 * Copyright (c) 1992, 1993
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * William Jolitz.
8 *
9 * %sccs.include.redist.c%
10 *
11 *	@(#)icu.s	8.1 (Berkeley) 06/11/93
12 */
13
14	.data
15	.globl	_imen
16	.globl	_cpl
17_cpl:	.long	0xffff			# current priority level (all off)
18_imen:	.long	0xffff			# interrupt mask enable (all off)
19	.globl	_highmask
20_highmask:	.long	0xffff
21	.globl	_ttymask
22_ttymask:	.long	0
23	.globl	_biomask
24_biomask:	.long	0
25	.globl	_netmask
26_netmask:	.long	0
27	.globl	_isa_intr
28_isa_intr:	.space	16*4
29
30	.text
31#include <net/netisr.h>
32
33#define DONET(s, c)	; \
34	.globl	c ;  \
35	btrl	$ s ,_netisr ;  \
36	jnb	1f ; \
37	call	c ; \
381:
39
40/*
41 * Handle return from interrupt after device handler finishes
42 *
43 * register usage:
44 *
45 * %ebx is cpl we are going back to
46 * %esi is 0 if returning to kernel mode
47 *
48 * Note that these registers will be preserved though C calls,
49 * such as the network interrupt routines.
50 */
51doreti:
52	cli
53	popl	%ebx			# flush unit number
54	popl	%ebx			# get previous priority
55	# now interrupt frame is a trap frame!
56
57	/* compensate for drivers that return with non-zero cpl */
58	movl	0x34(%esp), %esi /* cs */
59	andl	$3, %esi
60	jz	1f
61
62return_to_user_mode: /* entry point from trap and syscall return */
63
64	/* return cs is for user mode: force 0 cpl */
65	xorl	%ebx,%ebx
661:
67
68	/* like splx(%ebx), except without special 0 handling */
69	cli
70	movl	%ebx, %eax
71	movw	%ax,_cpl
72	orw	_imen,%ax
73	outb	%al, $ IO_ICU1+1
74	movb	%ah, %al
75	outb	%al, $ IO_ICU2+1
76
77	/* return immediately if previous cpl was non-zero */
78	cmpw	$0, %bx
79	jnz	just_return
80
81	/* do network stuff, if requested, even if returning to kernel mode */
82	cmpl	$0,_netisr
83	jne	donet
84
85	/* if (returning to user mode && astpending), go back to trap
86	 * (check astpending first since it is more likely to be false)
87	 */
88	cmpl	$0,_astpending
89	je	just_return
90
91	testl	%esi, %esi
92	jz	just_return
93
94	/* we need to go back to trap */
95	popl	%es
96	popl	%ds
97	popal
98	addl	$8,%esp
99
100	pushl	$0
101	TRAP (T_ASTFLT)
102	/* this doesn't return here ... instead it goes though
103	 * calltrap in locore.s
104	 */
105
106donet:
107	/* like splnet(), except we know the current pri is 0 */
108	cli
109	movw _netmask, %ax
110	movw %ax,_cpl
111	orw _imen,%ax
112	outb %al, $ IO_ICU1+1
113	movb %ah, %al
114	outb %al, $ IO_ICU2+1
115	sti
116
117	DONET(NETISR_RAW,_rawintr)
118#ifdef INET
119	DONET(NETISR_IP,_ipintr)
120	DONET(NETISR_ARP,_arpintr)
121#endif
122#ifdef IMP
123	DONET(NETISR_IMP,_impintr)
124#endif
125#ifdef NS
126	DONET(NETISR_NS,_nsintr)
127#endif
128#ifdef ISO
129	DONET(NETISR_ISO,_clnlintr)
130#endif
131#ifdef CCITT
132	DONET(NETISR_CCITT,_hdintr)
133#endif
134
135	btrl	$ NETISR_SCLK,_netisr
136	jnb	return_to_user_mode
137
138	/* like splsoftclock */
139	cli
140	movw $0x8000, %ax
141	movw %ax,_cpl
142	orw _imen,%ax
143	outb %al, $ IO_ICU1+1
144	movb %ah, %al
145	outb %al, $ IO_ICU2+1
146	sti
147
148	# back to an interrupt frame for a moment
149	pushl	%eax
150	pushl	$0xff	# dummy intr
151	call	_softclock
152	leal	8(%esp), %esp
153	jmp	return_to_user_mode
154
155just_return:
156	pop	%es
157	pop	%ds
158	popa
159	leal	8(%esp),%esp
160	iret
161
162/*
163 * Interrupt priority mechanism
164 *
165 * Two flavors	-- imlXX masks relative to ISA noemenclature (for PC compat sw)
166 *		-- splXX masks with group mechanism for BSD purposes
167 */
168
169	.globl	_splhigh
170	.globl	_splclock
171_splhigh:
172_splclock:
173	cli				# disable interrupts
174	movw	$0xffff,%ax		# set new priority level
175	movw	%ax,%dx
176	# orw	_imen,%ax		# mask off those not enabled yet
177	movw	%ax,%cx
178	outb	%al,$ IO_ICU1+1		/* update icu's */
179	movb	%ah,%al
180	outb	%al,$ IO_ICU2+1
181	movzwl	_cpl,%eax		# return old priority
182	movw	%dx,_cpl		# set new priority level
183	sti				# enable interrupts
184	ret
185
186	.globl	_spltty			# block clists
187_spltty:
188	cli				# disable interrupts
189	movw	_cpl,%ax
190	orw	_ttymask,%ax
191	movw	%ax,%dx
192	orw	_imen,%ax		# mask off those not enabled yet
193	movw	%ax,%cx
194	outb	%al,$ IO_ICU1+1		/* update icu's */
195	movb	%ah,%al
196	outb	%al,$ IO_ICU2+1
197	movzwl	_cpl,%eax		# return old priority
198	movw	%dx,_cpl		# set new priority level
199	sti				# enable interrupts
200	ret
201
202	.globl	_splimp
203	.globl	_splnet
204_splimp:
205_splnet:
206	cli				# disable interrupts
207	movw	_cpl,%ax
208	orw	_netmask,%ax
209	movw	%ax,%dx
210	orw	_imen,%ax		# mask off those not enabled yet
211	movw	%ax,%cx
212	outb	%al,$ IO_ICU1+1		/* update icu's */
213	movb	%ah,%al
214	outb	%al,$ IO_ICU2+1
215	movzwl	_cpl,%eax		# return old priority
216	movw	%dx,_cpl		# set new priority level
217	sti				# enable interrupts
218	ret
219
220	.globl	_splbio
221_splbio:
222	cli				# disable interrupts
223	movw	_cpl,%ax
224	orw	_biomask,%ax
225	movw	%ax,%dx
226	orw	_imen,%ax		# mask off those not enabled yet
227	movw	%ax,%cx
228	outb	%al,$ IO_ICU1+1		/* update icu's */
229	movb	%ah,%al
230	outb	%al,$ IO_ICU2+1
231	movzwl	_cpl,%eax		# return old priority
232	movw	%dx,_cpl		# set new priority level
233	sti				# enable interrupts
234	ret
235
236	.globl	_splsoftclock
237_splsoftclock:
238	cli				# disable interrupts
239	movw	_cpl,%ax
240	orw	$0x8000,%ax		# set new priority level
241	movw	%ax,%dx
242	orw	_imen,%ax		# mask off those not enabled yet
243	movw	%ax,%cx
244	outb	%al,$ IO_ICU1+1		/* update icu's */
245	movb	%ah,%al
246	outb	%al,$ IO_ICU2+1
247	movzwl	_cpl,%eax		# return old priority
248	movw	%dx,_cpl		# set new priority level
249	sti				# enable interrupts
250	ret
251
252	.globl _splnone
253	.globl _spl0
254_splnone:
255_spl0:
256	cli				# disable interrupts
257	pushl	_cpl			# save old priority
258	movw	_cpl,%ax
259	orw	_netmask,%ax		# mask off those network devices
260	movw	%ax,_cpl		# set new priority level
261	orw	_imen,%ax		# mask off those not enabled yet
262	outb	%al,$ IO_ICU1+1		/* update icu's */
263	movb	%ah,%al
264	outb	%al,$ IO_ICU2+1
265	sti				# enable interrupts
266
267	DONET(NETISR_RAW,_rawintr)
268#ifdef INET
269	DONET(NETISR_IP,_ipintr)
270	DONET(NETISR_ARP,_arpintr)
271#endif
272#ifdef IMP
273	DONET(NETISR_IMP,_impintr)
274#endif
275#ifdef NS
276	DONET(NETISR_NS,_nsintr)
277#endif
278#ifdef ISO
279	DONET(NETISR_ISO,_clnlintr)
280#endif
281#ifdef CCITT
282	DONET(NETISR_CCITT,_hdintr)
283#endif
284
285	cli				# disable interrupts
286	popl	_cpl			# save old priority
287	nop
288
289	movw	$0,%ax			# set new priority level
290	movw	%ax,%dx
291	orw	_imen,%ax		# mask off those not enabled yet
292	movw	%ax,%cx
293	outb	%al,$ IO_ICU1+1		/* update icu's */
294	movb	%ah,%al
295	outb	%al,$ IO_ICU2+1
296	movzwl	_cpl,%eax		# return old priority
297	movw	%dx,_cpl		# set new priority level
298	sti				# enable interrupts
299	ret
300
301	.globl _splx
302_splx:
303	cli				# disable interrupts
304	movw	4(%esp),%ax		# new priority level
305	movw	%ax,%dx
306	cmpw	$0,%dx
307	je	_spl0			# going to "zero level" is special
308
309	orw	_imen,%ax		# mask off those not enabled yet
310	movw	%ax,%cx
311	outb	%al,$ IO_ICU1+1		/* update icu's */
312	movb	%ah,%al
313	outb	%al,$ IO_ICU2+1
314	movzwl	_cpl,%eax		# return old priority
315	movw	%dx,_cpl		# set new priority level
316	sti				# enable interrupts
317	ret
318
319	/* hardware interrupt catcher (IDT 32 - 47) */
320	.globl	_isa_strayintr
321
322IDTVEC(intr0)
323	INTR1(0, _highmask, 0) ; call	_isa_strayintr ; INTREXIT1
324
325IDTVEC(intr1)
326	INTR1(1, _highmask, 1) ; call	_isa_strayintr ; INTREXIT1
327
328IDTVEC(intr2)
329	INTR1(2, _highmask, 2) ; call	_isa_strayintr ; INTREXIT1
330
331IDTVEC(intr3)
332	INTR1(3, _highmask, 3) ; call	_isa_strayintr ; INTREXIT1
333
334IDTVEC(intr4)
335	INTR1(4, _highmask, 4) ; call	_isa_strayintr ; INTREXIT1
336
337IDTVEC(intr5)
338	INTR1(5, _highmask, 5) ; call	_isa_strayintr ; INTREXIT1
339
340IDTVEC(intr6)
341	INTR1(6, _highmask, 6) ; call	_isa_strayintr ; INTREXIT1
342
343IDTVEC(intr7)
344	INTR1(7, _highmask, 7) ; call	_isa_strayintr ; INTREXIT1
345
346
347IDTVEC(intr8)
348	INTR2(8, _highmask, 8) ; call	_isa_strayintr ; INTREXIT2
349
350IDTVEC(intr9)
351	INTR2(9, _highmask, 9) ; call	_isa_strayintr ; INTREXIT2
352
353IDTVEC(intr10)
354	INTR2(10, _highmask, 10) ; call	_isa_strayintr ; INTREXIT2
355
356IDTVEC(intr11)
357	INTR2(11, _highmask, 11) ; call	_isa_strayintr ; INTREXIT2
358
359IDTVEC(intr12)
360	INTR2(12, _highmask, 12) ; call	_isa_strayintr ; INTREXIT2
361
362IDTVEC(intr13)
363	INTR2(13, _highmask, 13) ; call	_isa_strayintr ; INTREXIT2
364
365IDTVEC(intr14)
366	INTR2(14, _highmask, 14) ; call	_isa_strayintr ; INTREXIT2
367
368IDTVEC(intr15)
369	INTR2(15, _highmask, 15) ; call	_isa_strayintr ; INTREXIT2
370