Merge from vendor branch OPENSSL:
[dragonfly.git] / sys / platform / pc64 / isa / intr_machdep.c
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * Copyright (c) 2008 The DragonFly Project.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * William Jolitz.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by the University of
20  *      California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *      from: @(#)isa.c 7.2 (Berkeley) 5/13/91
38  * $FreeBSD: src/sys/i386/isa/intr_machdep.c,v 1.29.2.5 2001/10/14 06:54:27 luigi Exp $
39  * $DragonFly: src/sys/platform/pc64/isa/intr_machdep.c,v 1.1 2008/08/29 17:07:19 dillon Exp $
40  */
41 /*
42  * This file contains an aggregated module marked:
43  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
44  * All rights reserved.
45  * See the notice for details.
46  */
47
48 #include "use_isa.h"
49 //#include "opt_auto_eoi.h"
50
51 #include <sys/param.h>
52 #ifndef SMP
53 #include <machine/lock.h>
54 #endif
55 #include <sys/systm.h>
56 #include <sys/syslog.h>
57 #include <sys/malloc.h>
58 #include <sys/errno.h>
59 #include <sys/interrupt.h>
60 #include <machine/ipl.h>
61 #include <machine/md_var.h>
62 #include <machine/segments.h>
63 #include <sys/bus.h> 
64 #include <machine/globaldata.h>
65 #include <sys/proc.h>
66 #include <sys/thread2.h>
67 #include <sys/machintr.h>
68
69 #include <machine/smp.h>
70 #include <bus/isa/i386/isa.h>
71 #include <machine_base/icu/icu.h>
72
73 #if NISA > 0
74 #include <bus/isa/isavar.h>
75 #endif
76 #include <machine_base/isa/intr_machdep.h>
77 #include <sys/interrupt.h>
78 #include <machine/clock.h>
79 #include <machine/cpu.h>
80
81 /* XXX should be in suitable include files */
82 #define ICU_IMR_OFFSET          1               /* IO_ICU{1,2} + 1 */
83
84 #ifdef APIC_IO
85 /*
86  * This is to accommodate "mixed-mode" programming for 
87  * motherboards that don't connect the 8254 to the IO APIC.
88  */
89 #define AUTO_EOI_1      1
90 #endif
91
92 static void     init_i8259(void);
93
94 #define NMI_PARITY (1 << 7)
95 #define NMI_IOCHAN (1 << 6)
96 #define ENMI_WATCHDOG (1 << 7)
97 #define ENMI_BUSTIMER (1 << 6)
98 #define ENMI_IOSTATUS (1 << 5)
99
100 /*
101  * Handle a NMI, possibly a machine check.
102  * return true to panic system, false to ignore.
103  */
104 int
105 isa_nmi(int cd)
106 {
107         int retval = 0;
108         int isa_port = inb(0x61);
109         int eisa_port = inb(0x461);
110
111         log(LOG_CRIT, "NMI ISA %x, EISA %x\n", isa_port, eisa_port);
112         
113         if (isa_port & NMI_PARITY) {
114                 log(LOG_CRIT, "RAM parity error, likely hardware failure.");
115                 retval = 1;
116         }
117
118         if (isa_port & NMI_IOCHAN) {
119                 log(LOG_CRIT, "I/O channel check, likely hardware failure.");
120                 retval = 1;
121         }
122
123         /*
124          * On a real EISA machine, this will never happen.  However it can
125          * happen on ISA machines which implement XT style floating point
126          * error handling (very rare).  Save them from a meaningless panic.
127          */
128         if (eisa_port == 0xff)
129                 return(retval);
130
131         if (eisa_port & ENMI_WATCHDOG) {
132                 log(LOG_CRIT, "EISA watchdog timer expired, likely hardware failure.");
133                 retval = 1;
134         }
135
136         if (eisa_port & ENMI_BUSTIMER) {
137                 log(LOG_CRIT, "EISA bus timeout, likely hardware failure.");
138                 retval = 1;
139         }
140
141         if (eisa_port & ENMI_IOSTATUS) {
142                 log(LOG_CRIT, "EISA I/O port status error.");
143                 retval = 1;
144         }
145         return(retval);
146 }
147
148 /*
149  *  ICU reinitialize when ICU configuration has lost.
150  */
151 void
152 icu_reinit(void)
153 {
154         int i;
155
156         init_i8259();
157         for (i = 0; i < MAX_HARDINTS; ++i) {
158                 if (count_registered_ints(i))
159                         machintr_intren(i);
160         }
161 }
162
163 /*
164  * Fill in default interrupt table (in case of spurious interrupt
165  * during configuration of kernel, setup interrupt control unit
166  */
167 void
168 isa_defaultirq(void)
169 {
170         int i;
171
172         /* icu vectors */
173         for (i = 0; i < MAX_HARDINTS; i++)
174                 machintr_vector_setdefault(i);
175         init_i8259();
176 }
177
178 static void
179 init_i8259(void)
180 {
181
182         /* initialize 8259's */
183         outb(IO_ICU1, 0x11);            /* reset; program device, four bytes */
184         outb(IO_ICU1+ICU_IMR_OFFSET, IDT_OFFSET);       /* starting at this vector index */
185         outb(IO_ICU1+ICU_IMR_OFFSET, 1 << ICU_IRQ_SLAVE); /* slave on line 2 */
186 #ifdef AUTO_EOI_1
187         outb(IO_ICU1+ICU_IMR_OFFSET, 2 | 1);            /* auto EOI, 8086 mode */
188 #else
189         outb(IO_ICU1+ICU_IMR_OFFSET, 1);                /* 8086 mode */
190 #endif
191         outb(IO_ICU1+ICU_IMR_OFFSET, 0xff);             /* leave interrupts masked */
192         outb(IO_ICU1, 0x0a);            /* default to IRR on read */
193         outb(IO_ICU1, 0xc0 | (3 - 1));  /* pri order 3-7, 0-2 (com2 first) */
194         outb(IO_ICU2, 0x11);            /* reset; program device, four bytes */
195         outb(IO_ICU2+ICU_IMR_OFFSET, IDT_OFFSET+8); /* staring at this vector index */
196         outb(IO_ICU2+ICU_IMR_OFFSET, ICU_IRQ_SLAVE);
197 #ifdef AUTO_EOI_2
198         outb(IO_ICU2+ICU_IMR_OFFSET, 2 | 1);            /* auto EOI, 8086 mode */
199 #else
200         outb(IO_ICU2+ICU_IMR_OFFSET,1);         /* 8086 mode */
201 #endif
202         outb(IO_ICU2+ICU_IMR_OFFSET, 0xff);          /* leave interrupts masked */
203         outb(IO_ICU2, 0x0a);            /* default to IRR on read */
204 }
205
206 #if NISA > 0
207 /*
208  * Return a bitmap of the current interrupt requests.  This is 8259-specific
209  * and is only suitable for use at probe time.
210  */
211 intrmask_t
212 isa_irq_pending(void)
213 {
214         u_char irr1;
215         u_char irr2;
216
217         irr1 = inb(IO_ICU1);
218         irr2 = inb(IO_ICU2);
219         return ((irr2 << 8) | irr1);
220 }
221
222 #endif
223
224 /* The following notice applies beyond this point in the file */
225
226 /*
227  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
228  * All rights reserved.
229  *
230  * Redistribution and use in source and binary forms, with or without
231  * modification, are permitted provided that the following conditions
232  * are met:
233  * 1. Redistributions of source code must retain the above copyright
234  *    notice unmodified, this list of conditions, and the following
235  *    disclaimer.
236  * 2. Redistributions in binary form must reproduce the above copyright
237  *    notice, this list of conditions and the following disclaimer in the
238  *    documentation and/or other materials provided with the distribution.
239  *
240  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
241  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
242  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
243  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
244  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
245  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
246  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
248  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
249  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
250  *
251  * $FreeBSD: src/sys/i386/isa/intr_machdep.c,v 1.29.2.5 2001/10/14 06:54:27 luigi Exp $
252  *
253  */
254
255 #ifdef SMP
256 /*
257  * forward_fast_remote()
258  *
259  *      This function is called from the receiving end of an IPIQ when a
260  *      remote cpu wishes to forward a fast interrupt to us.  All we have to
261  *      do is set the interrupt pending and let the IPI's doreti deal with it.
262  */
263 void
264 forward_fastint_remote(void *arg)
265 {
266     int irq = (int)arg;
267     struct mdglobaldata *gd = mdcpu;
268
269     atomic_set_int_nonlocked(&gd->gd_fpending, 1 << irq);
270     atomic_set_int_nonlocked(&gd->mi.gd_reqflags, RQF_INTPEND);
271 }
272
273 #endif