pc32: Split out isa_intr.h and move isa/intr_machdep.h to include/
[dragonfly.git] / sys / platform / pc32 / icu / icu_abi.c
CommitLineData
06f5be02
MD
1/*
2 * Copyright (c) 2005 The DragonFly Project. All rights reserved.
10ff1029
MD
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
06f5be02
MD
5 *
6 * This code is derived from software contributed to The DragonFly Project
7 * by Matthew Dillon <dillon@backplane.com>
10ff1029
MD
8 *
9 * This code is derived from software contributed to Berkeley by
10 * William Jolitz.
06f5be02
MD
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in
20 * the documentation and/or other materials provided with the
21 * distribution.
22 * 3. Neither the name of The DragonFly Project nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific, prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
34 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
35 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
36 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
d916dbc1 39 * $DragonFly: src/sys/platform/pc32/icu/icu_abi.c,v 1.14 2007/07/07 12:13:47 sephe Exp $
06f5be02
MD
40 */
41
37e7efec
MD
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>
45#include <sys/machintr.h>
10ff1029
MD
46#include <sys/interrupt.h>
47#include <sys/bus.h>
48
49#include <machine/segments.h>
50#include <machine/md_var.h>
87cf6827 51#include <machine/intr_machdep.h>
0b692e79 52#include <machine/globaldata.h>
10db3cc6 53#include <machine/smp.h>
0b692e79
MD
54
55#include <sys/thread2.h>
5f456c40
MD
56
57#include "icu.h"
58#include "icu_ipl.h"
37e7efec 59
10db3cc6 60extern struct machintr_abi MachIntrABI_APIC;
37e7efec 61
10ff1029 62extern inthand_t
081be8a5
SZ
63 IDTVEC(icu_intr0), IDTVEC(icu_intr1),
64 IDTVEC(icu_intr2), IDTVEC(icu_intr3),
65 IDTVEC(icu_intr4), IDTVEC(icu_intr5),
66 IDTVEC(icu_intr6), IDTVEC(icu_intr7),
67 IDTVEC(icu_intr8), IDTVEC(icu_intr9),
68 IDTVEC(icu_intr10), IDTVEC(icu_intr11),
69 IDTVEC(icu_intr12), IDTVEC(icu_intr13),
70 IDTVEC(icu_intr14), IDTVEC(icu_intr15);
10ff1029 71
081be8a5
SZ
72static inthand_t *icu_intr[ICU_HWI_VECTORS] = {
73 &IDTVEC(icu_intr0), &IDTVEC(icu_intr1),
74 &IDTVEC(icu_intr2), &IDTVEC(icu_intr3),
75 &IDTVEC(icu_intr4), &IDTVEC(icu_intr5),
76 &IDTVEC(icu_intr6), &IDTVEC(icu_intr7),
77 &IDTVEC(icu_intr8), &IDTVEC(icu_intr9),
78 &IDTVEC(icu_intr10), &IDTVEC(icu_intr11),
79 &IDTVEC(icu_intr12), &IDTVEC(icu_intr13),
80 &IDTVEC(icu_intr14), &IDTVEC(icu_intr15)
10ff1029
MD
81};
82
10db3cc6
SZ
83extern void ICU_INTREN(int);
84extern void ICU_INTRDIS(int);
85
86static int icu_vectorctl(int, int, int);
87static int icu_setvar(int, const void *);
88static int icu_getvar(int, void *);
89static void icu_finalize(void);
90static void icu_cleanup(void);
91static void icu_setdefault(void);
92
30c5f287 93struct machintr_abi MachIntrABI_ICU = {
54e1df6b
SZ
94 MACHINTR_ICU,
95 .intrdis = ICU_INTRDIS,
96 .intren = ICU_INTREN,
97 .vectorctl = icu_vectorctl,
98 .setvar = icu_setvar,
99 .getvar = icu_getvar,
100 .finalize = icu_finalize,
10db3cc6
SZ
101 .cleanup = icu_cleanup,
102 .setdefault = icu_setdefault
37e7efec
MD
103};
104
54e1df6b 105static int icu_imcr_present;
e96ee753 106
97359a5b
MD
107/*
108 * WARNING! SMP builds can use the ICU now so this code must be MP safe.
109 */
54e1df6b 110static int
d916dbc1 111icu_setvar(int varid, const void *buf)
37e7efec 112{
54e1df6b 113 int error = 0;
e96ee753 114
54e1df6b
SZ
115 switch (varid) {
116 case MACHINTR_VAR_IMCR_PRESENT:
117 icu_imcr_present = *(const int *)buf;
118 break;
119
120 default:
121 error = ENOENT;
122 break;
123 }
124 return error;
37e7efec
MD
125}
126
54e1df6b 127static int
d916dbc1 128icu_getvar(int varid, void *buf)
37e7efec 129{
54e1df6b 130 int error = 0;
e96ee753 131
54e1df6b
SZ
132 switch (varid) {
133 case MACHINTR_VAR_IMCR_PRESENT:
134 *(int *)buf = icu_imcr_present;
135 break;
136
137 default:
138 error = ENOENT;
139 break;
140 }
141 return error;
37e7efec
MD
142}
143
0b692e79
MD
144/*
145 * Called before interrupts are physically enabled
146 */
37e7efec
MD
147static void
148icu_finalize(void)
149{
54e1df6b
SZ
150 int intr;
151
10db3cc6
SZ
152#ifdef SMP
153 if (apic_io_enable) {
154 KKASSERT(MachIntrABI.type == MACHINTR_ICU);
155 MachIntrABI_APIC.setvar(MACHINTR_VAR_IMCR_PRESENT,
156 &icu_imcr_present);
157 MachIntrABI_APIC.finalize();
158 return;
159 }
160#endif
161
54e1df6b
SZ
162 for (intr = 0; intr < ICU_HWI_VECTORS; ++intr)
163 machintr_intrdis(intr);
164 machintr_intren(ICU_IRQ_SLAVE);
165
166#ifdef SMP
167 /*
168 * If an IMCR is present, programming bit 0 disconnects the 8259
169 * from the BSP. The 8259 may still be connected to LINT0 on the
170 * BSP's LAPIC.
171 *
172 * If we are running SMP the LAPIC is active, try to use virtual
173 * wire mode so we can use other interrupt sources within the LAPIC
174 * in addition to the 8259.
175 */
176 if (icu_imcr_present) {
177 outb(0x22, 0x70);
178 outb(0x23, 0x01);
179 }
e96ee753 180#endif
37e7efec
MD
181}
182
0b692e79
MD
183/*
184 * Called after interrupts physically enabled but before the
185 * critical section is released.
186 */
54e1df6b 187static void
0b692e79
MD
188icu_cleanup(void)
189{
c263294b 190 bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending));
0b692e79
MD
191}
192
54e1df6b 193static int
10ff1029
MD
194icu_vectorctl(int op, int intr, int flags)
195{
54e1df6b
SZ
196 int error;
197 u_long ef;
198
199 if (intr < 0 || intr >= ICU_HWI_VECTORS || intr == ICU_IRQ_SLAVE)
200 return EINVAL;
201
202 ef = read_eflags();
203 cpu_disable_intr();
204 error = 0;
205
206 switch (op) {
207 case MACHINTR_VECTOR_SETUP:
081be8a5 208 setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYS386IGT,
54e1df6b
SZ
209 SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
210 machintr_intren(intr);
211 break;
212
213 case MACHINTR_VECTOR_TEARDOWN:
10db3cc6 214 machintr_intrdis(intr);
081be8a5 215 setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYS386IGT,
54e1df6b 216 SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
54e1df6b
SZ
217 break;
218
219 default:
220 error = EOPNOTSUPP;
221 break;
222 }
223 write_eflags(ef);
224 return error;
10ff1029 225}
10db3cc6
SZ
226
227static void
228icu_setdefault(void)
229{
230 int intr;
231
232 for (intr = 0; intr < ICU_HWI_VECTORS; ++intr) {
233 if (intr == ICU_IRQ_SLAVE)
234 continue;
235 setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYS386IGT,
236 SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
237 }
238}