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