xref: /dragonfly/sys/platform/pc64/icu/icu_vector.s (revision bbf928c6)
1c8fe38aeSMatthew Dillon/*
2c8fe38aeSMatthew Dillon * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
3c8fe38aeSMatthew Dillon *
4c8fe38aeSMatthew Dillon * Redistribution and use in source and binary forms, with or without
5c8fe38aeSMatthew Dillon * modification, are permitted provided that the following conditions
6c8fe38aeSMatthew Dillon * are met:
7c8fe38aeSMatthew Dillon *
8c8fe38aeSMatthew Dillon * 1. Redistributions of source code must retain the above copyright
9c8fe38aeSMatthew Dillon *    notice, this list of conditions and the following disclaimer.
10c8fe38aeSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
11c8fe38aeSMatthew Dillon *    notice, this list of conditions and the following disclaimer in
12c8fe38aeSMatthew Dillon *    the documentation and/or other materials provided with the
13c8fe38aeSMatthew Dillon *    distribution.
14c8fe38aeSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
15c8fe38aeSMatthew Dillon *    contributors may be used to endorse or promote products derived
16c8fe38aeSMatthew Dillon *    from this software without specific, prior written permission.
17c8fe38aeSMatthew Dillon *
18c8fe38aeSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19c8fe38aeSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20c8fe38aeSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21c8fe38aeSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
22c8fe38aeSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23c8fe38aeSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24c8fe38aeSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25c8fe38aeSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26c8fe38aeSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27c8fe38aeSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28c8fe38aeSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29c8fe38aeSMatthew Dillon * SUCH DAMAGE.
30c8fe38aeSMatthew Dillon *
31c8fe38aeSMatthew Dillon * from: vector.s, 386BSD 0.1 unknown origin
32c8fe38aeSMatthew Dillon * $FreeBSD: src/sys/i386/isa/icu_vector.s,v 1.14.2.2 2000/07/18 21:12:42 dfr Exp $
33c8fe38aeSMatthew Dillon */
34c8fe38aeSMatthew Dillon/*
35c8fe38aeSMatthew Dillon * WARNING!  SMP builds can use the ICU now so this code must be MP safe.
36c8fe38aeSMatthew Dillon */
37c8fe38aeSMatthew Dillon
38c8fe38aeSMatthew Dillon#include "opt_auto_eoi.h"
39c8fe38aeSMatthew Dillon
40c8fe38aeSMatthew Dillon#include <machine/asmacros.h>
41c8fe38aeSMatthew Dillon#include <machine/lock.h>
42c8fe38aeSMatthew Dillon#include <machine/psl.h>
43c8fe38aeSMatthew Dillon#include <machine/trap.h>
44bfc09ba0SMatthew Dillon#include <machine/segments.h>
45c8fe38aeSMatthew Dillon#include <machine_base/icu/icu.h>
461c2bce94SSepherosa Ziehau#include <machine_base/icu/icu_ipl.h>
471c2bce94SSepherosa Ziehau
487fdff911SSascha Wildner#include <bus/isa/isa.h>
49c8fe38aeSMatthew Dillon
50c8fe38aeSMatthew Dillon#include "assym.s"
51c8fe38aeSMatthew Dillon
52c8fe38aeSMatthew Dillon#define	ICU_EOI			0x20	/* XXX - define elsewhere */
53c8fe38aeSMatthew Dillon
54c8fe38aeSMatthew Dillon#define	IRQ_LBIT(irq_num)	(1 << (irq_num))
55c8fe38aeSMatthew Dillon#define	IRQ_BIT(irq_num)	(1 << ((irq_num) % 8))
56c8fe38aeSMatthew Dillon#define	IRQ_BYTE(irq_num)	((irq_num) >> 3)
57c8fe38aeSMatthew Dillon
58c8fe38aeSMatthew Dillon#ifdef AUTO_EOI_1
59c8fe38aeSMatthew Dillon#define	ENABLE_ICU1		/* use auto-EOI to reduce i/o */
60c8fe38aeSMatthew Dillon#define	OUTB_ICU1
61c8fe38aeSMatthew Dillon#else
62c8fe38aeSMatthew Dillon#define	ENABLE_ICU1 							\
63c8fe38aeSMatthew Dillon	movb	$ICU_EOI,%al ;	/* as soon as possible send EOI ... */ 	\
64c8fe38aeSMatthew Dillon	OUTB_ICU1 ;		/* ... to clear in service bit */	\
65c8fe38aeSMatthew Dillon
66c8fe38aeSMatthew Dillon#define	OUTB_ICU1 							\
67c8fe38aeSMatthew Dillon	outb	%al,$IO_ICU1 ;						\
68c8fe38aeSMatthew Dillon
69c8fe38aeSMatthew Dillon#endif
70c8fe38aeSMatthew Dillon
71c8fe38aeSMatthew Dillon#ifdef AUTO_EOI_2
72c8fe38aeSMatthew Dillon/*
73c8fe38aeSMatthew Dillon * The data sheet says no auto-EOI on slave, but it sometimes works.
74c8fe38aeSMatthew Dillon */
75c8fe38aeSMatthew Dillon#define	ENABLE_ICU1_AND_2	ENABLE_ICU1
76c8fe38aeSMatthew Dillon#else
77c8fe38aeSMatthew Dillon#define	ENABLE_ICU1_AND_2 						\
78c8fe38aeSMatthew Dillon	movb	$ICU_EOI,%al ;	/* as above */ 				\
79c8fe38aeSMatthew Dillon	outb	%al,$IO_ICU2 ;	/* but do second icu first ... */ 	\
80c8fe38aeSMatthew Dillon	OUTB_ICU1 ;	/* ... then first icu (if !AUTO_EOI_1) */	\
81c8fe38aeSMatthew Dillon
82c8fe38aeSMatthew Dillon#endif
83c8fe38aeSMatthew Dillon
84c8fe38aeSMatthew Dillon/*
85c8fe38aeSMatthew Dillon * Macro helpers
86c8fe38aeSMatthew Dillon */
87c8fe38aeSMatthew Dillon#define ICU_PUSH_FRAME							\
884611d87fSMatthew Dillon	PUSH_FRAME_TFRIP ;	/* 15 regs + space for 5 extras */	\
895b9f6cc4SMatthew Dillon	movl $0,TF_XFLAGS(%rsp) ;					\
90c8fe38aeSMatthew Dillon	movl $0,TF_TRAPNO(%rsp) ;					\
91c8fe38aeSMatthew Dillon	movl $0,TF_ADDR(%rsp) ;						\
92c8fe38aeSMatthew Dillon	movl $0,TF_FLAGS(%rsp) ;					\
93c8fe38aeSMatthew Dillon	movl $0,TF_ERR(%rsp) ;						\
94c8fe38aeSMatthew Dillon	cld ;								\
95c8fe38aeSMatthew Dillon
96*bbf928c6SMatthew Dillon/*
97*bbf928c6SMatthew Dillon * Caller must re-enable the ICU atomically with the masking and
98*bbf928c6SMatthew Dillon * is responsible for ICU_IMASK_LOCK/UNLOCK
99*bbf928c6SMatthew Dillon */
100c8fe38aeSMatthew Dillon#define MASK_IRQ(icu, irq_num)						\
101c8fe38aeSMatthew Dillon	movb	icu_imen + IRQ_BYTE(irq_num),%al ;			\
102c8fe38aeSMatthew Dillon	orb	$IRQ_BIT(irq_num),%al ;					\
103c8fe38aeSMatthew Dillon	movb	%al,icu_imen + IRQ_BYTE(irq_num) ;			\
104c8fe38aeSMatthew Dillon	outb	%al,$icu+ICU_IMR_OFFSET ;				\
105c8fe38aeSMatthew Dillon
106c8fe38aeSMatthew Dillon#define UNMASK_IRQ(icu, irq_num)					\
107c8fe38aeSMatthew Dillon	cmpl	$0,%eax ;						\
108c8fe38aeSMatthew Dillon	jnz	8f ;							\
109c8fe38aeSMatthew Dillon	ICU_IMASK_LOCK ;						\
110c8fe38aeSMatthew Dillon	movb	icu_imen + IRQ_BYTE(irq_num),%al ;			\
111c8fe38aeSMatthew Dillon	andb	$~IRQ_BIT(irq_num),%al ;				\
112c8fe38aeSMatthew Dillon	movb	%al,icu_imen + IRQ_BYTE(irq_num) ;			\
113c8fe38aeSMatthew Dillon	outb	%al,$icu+ICU_IMR_OFFSET ;				\
114c8fe38aeSMatthew Dillon	ICU_IMASK_UNLOCK ;						\
115c8fe38aeSMatthew Dillon8: ;									\
116c8fe38aeSMatthew Dillon
117c8fe38aeSMatthew Dillon/*
11835e45e47SSepherosa Ziehau * Interrupt call handlers run in the following sequence:
119c8fe38aeSMatthew Dillon *
120c8fe38aeSMatthew Dillon *	- Push the trap frame required by doreti.
121c8fe38aeSMatthew Dillon *	- Mask the interrupt and reenable its source.
1229611ff20SSepherosa Ziehau *	- If we cannot take the interrupt set its ipending bit and
123c8fe38aeSMatthew Dillon *	  doreti.
1249611ff20SSepherosa Ziehau *	- If we can take the interrupt clear its ipending bit,
125c8fe38aeSMatthew Dillon *	  call the handler, then unmask the interrupt and doreti.
126c8fe38aeSMatthew Dillon *
127c8fe38aeSMatthew Dillon *	YYY can cache gd base pointer instead of using hidden %fs
128c8fe38aeSMatthew Dillon *	prefixes.
129c8fe38aeSMatthew Dillon */
130c8fe38aeSMatthew Dillon
13158e8d3d8SSepherosa Ziehau#define	INTR_HANDLER(irq_num, icu, enable_icus)				\
132c8fe38aeSMatthew Dillon	.text ; 							\
133c8fe38aeSMatthew Dillon	SUPERALIGN_TEXT ; 						\
13458e8d3d8SSepherosa ZiehauIDTVEC(icu_intr##irq_num) ; 						\
135c8fe38aeSMatthew Dillon	ICU_PUSH_FRAME ;						\
1362883d2d8SMatthew Dillon	FAKE_MCOUNT(TF_RIP(%rsp)) ; 					\
137*bbf928c6SMatthew Dillon	ICU_IMASK_LOCK ;						\
138c8fe38aeSMatthew Dillon	MASK_IRQ(icu, irq_num) ;					\
139c8fe38aeSMatthew Dillon	enable_icus ;							\
140*bbf928c6SMatthew Dillon	ICU_IMASK_UNLOCK ;						\
141c8fe38aeSMatthew Dillon	movq	PCPU(curthread),%rbx ;					\
142c8fe38aeSMatthew Dillon	testl	$-1,TD_NEST_COUNT(%rbx) ;				\
143c8fe38aeSMatthew Dillon	jne	1f ;							\
144f9235b6dSMatthew Dillon	testl	$-1,TD_CRITCOUNT(%rbx) ;				\
145f9235b6dSMatthew Dillon	je	2f ;							\
146c8fe38aeSMatthew Dillon1: ;									\
147c8fe38aeSMatthew Dillon	/* set pending bit and return, leave interrupt masked */	\
1484fb281afSSepherosa Ziehau	movq	$0,%rdx ;						\
1494fb281afSSepherosa Ziehau	orq	$IRQ_LBIT(irq_num),PCPU_E8(ipending,%rdx) ;		\
150c8fe38aeSMatthew Dillon	orl	$RQF_INTPEND, PCPU(reqflags) ;				\
151c8fe38aeSMatthew Dillon	jmp	5f ;							\
152c8fe38aeSMatthew Dillon2: ;									\
153c8fe38aeSMatthew Dillon	/* clear pending bit, run handler */				\
1544fb281afSSepherosa Ziehau	movq	$0,%rdx ;						\
1554fb281afSSepherosa Ziehau	andq	$~IRQ_LBIT(irq_num),PCPU_E8(ipending,%rdx) ;		\
156c8fe38aeSMatthew Dillon	pushq	$irq_num ;						\
157c8fe38aeSMatthew Dillon	movq	%rsp,%rdi ;		/* rdi = call argument */	\
158f9235b6dSMatthew Dillon	incl	TD_CRITCOUNT(%rbx) ;					\
1592d910aafSMatthew Dillon	sti ;								\
160c8fe38aeSMatthew Dillon	call	ithread_fast_handler ;	/* returns 0 to unmask int */	\
161f9235b6dSMatthew Dillon	decl	TD_CRITCOUNT(%rbx) ;					\
162c8fe38aeSMatthew Dillon	addq	$8,%rsp ;		/* intr frame -> trap frame */	\
163c8fe38aeSMatthew Dillon	UNMASK_IRQ(icu, irq_num) ;					\
164c8fe38aeSMatthew Dillon5: ;									\
165c8fe38aeSMatthew Dillon	MEXITCOUNT ;							\
166c8fe38aeSMatthew Dillon	jmp	doreti ;						\
167c8fe38aeSMatthew Dillon
168c8fe38aeSMatthew DillonMCOUNT_LABEL(bintr)
16958e8d3d8SSepherosa Ziehau	INTR_HANDLER(0, IO_ICU1, ENABLE_ICU1)
17058e8d3d8SSepherosa Ziehau	INTR_HANDLER(1, IO_ICU1, ENABLE_ICU1)
17158e8d3d8SSepherosa Ziehau	INTR_HANDLER(2, IO_ICU1, ENABLE_ICU1)
17258e8d3d8SSepherosa Ziehau	INTR_HANDLER(3, IO_ICU1, ENABLE_ICU1)
17358e8d3d8SSepherosa Ziehau	INTR_HANDLER(4, IO_ICU1, ENABLE_ICU1)
17458e8d3d8SSepherosa Ziehau	INTR_HANDLER(5, IO_ICU1, ENABLE_ICU1)
17558e8d3d8SSepherosa Ziehau	INTR_HANDLER(6, IO_ICU1, ENABLE_ICU1)
17658e8d3d8SSepherosa Ziehau	INTR_HANDLER(7, IO_ICU1, ENABLE_ICU1)
17758e8d3d8SSepherosa Ziehau	INTR_HANDLER(8, IO_ICU2, ENABLE_ICU1_AND_2)
17858e8d3d8SSepherosa Ziehau	INTR_HANDLER(9, IO_ICU2, ENABLE_ICU1_AND_2)
17958e8d3d8SSepherosa Ziehau	INTR_HANDLER(10, IO_ICU2, ENABLE_ICU1_AND_2)
18058e8d3d8SSepherosa Ziehau	INTR_HANDLER(11, IO_ICU2, ENABLE_ICU1_AND_2)
18158e8d3d8SSepherosa Ziehau	INTR_HANDLER(12, IO_ICU2, ENABLE_ICU1_AND_2)
18258e8d3d8SSepherosa Ziehau	INTR_HANDLER(13, IO_ICU2, ENABLE_ICU1_AND_2)
18358e8d3d8SSepherosa Ziehau	INTR_HANDLER(14, IO_ICU2, ENABLE_ICU1_AND_2)
18458e8d3d8SSepherosa Ziehau	INTR_HANDLER(15, IO_ICU2, ENABLE_ICU1_AND_2)
185c8fe38aeSMatthew DillonMCOUNT_LABEL(eintr)
186c8fe38aeSMatthew Dillon
187c8fe38aeSMatthew Dillon	.data
188c8fe38aeSMatthew Dillon
189c8fe38aeSMatthew Dillon	.text
190