Deleted Added
sdiff udiff text old ( 119935 ) new ( 121986 )
full compact
1/*-
2 * Copyright (c) 1990 William Jolitz.
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 21 unchanged lines hidden (view full) ---

30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * from: @(#)npx.c 7.2 (Berkeley) 5/12/91
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/i386/isa/npx.c 121986 2003-11-03 21:53:38Z jhb $");
39
40#include "opt_cpu.h"
41#include "opt_debug_npx.h"
42#include "opt_isa.h"
43#include "opt_npx.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/bus.h>
48#include <sys/kernel.h>
49#include <sys/lock.h>
50#include <sys/malloc.h>
51#include <sys/module.h>
52#include <sys/mutex.h>
53#include <sys/mutex.h>
54#include <sys/proc.h>
55#include <sys/smp.h>
56#include <sys/sysctl.h>
57#include <machine/bus.h>
58#include <sys/rman.h>
59#ifdef NPX_DEBUG
60#include <sys/syslog.h>
61#endif
62#include <sys/signalvar.h>
63#include <sys/user.h>
64
65#include <machine/asmacros.h>
66#include <machine/cputypes.h>
67#include <machine/frame.h>
68#include <machine/md_var.h>
69#include <machine/pcb.h>
70#include <machine/psl.h>
71#include <machine/clock.h>
72#include <machine/resource.h>
73#include <machine/specialreg.h>
74#include <machine/segments.h>
75#include <machine/ucontext.h>
76
77#include <i386/isa/icu.h>
78#ifdef PC98
79#include <pc98/pc98/pc98.h>
80#else
81#include <i386/isa/isa.h>
82#endif
83#include <machine/intr_machdep.h>
84#ifdef DEV_ISA
85#include <isa/isavar.h>
86#endif
87
88#if !defined(CPU_ENABLE_SSE) && defined(I686_CPU)
89#define CPU_ENABLE_SSE
90#endif
91#if defined(CPU_DISABLE_SSE)

--- 63 unchanged lines hidden (view full) ---

155#endif /* CPU_ENABLE_SSE */
156
157typedef u_char bool_t;
158
159static void fpusave(union savefpu *);
160static void fpurstor(union savefpu *);
161static int npx_attach(device_t dev);
162static void npx_identify(driver_t *driver, device_t parent);
163static void npx_intr(void *);
164static int npx_probe(device_t dev);
165#ifdef I586_CPU_XXX
166static long timezero(const char *funcname,
167 void (*func)(void *buf, size_t len));
168#endif /* I586_CPU */
169
170int hw_float; /* XXX currently just alias for npx_exists */
171
172SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint,
173 CTLFLAG_RD, &hw_float, 0,
174 "Floatingpoint instructions executed in hardware");
175
176static volatile u_int npx_intrs_while_probing;
177static volatile u_int npx_traps_while_probing;
178
179static union savefpu npx_cleanstate;
180static bool_t npx_cleanstate_ready;
181static bool_t npx_ex16;
182static bool_t npx_exists;
183static bool_t npx_irq13;
184
185alias_for_inthand_t probetrap;
186__asm(" \n\
187 .text \n\
188 .p2align 2,0x90 \n\
189 .type " __XSTRING(CNAME(probetrap)) ",@function \n\
190" __XSTRING(CNAME(probetrap)) ": \n\
191 ss \n\
192 incl " __XSTRING(CNAME(npx_traps_while_probing)) " \n\
193 fnclex \n\
194 iret \n\
195");
196
197/*
198 * Identify routine. Create a connection point on our parent for probing.
199 */
200static void
201npx_identify(driver, parent)
202 driver_t *driver;
203 device_t parent;
204{
205 device_t child;
206
207 child = BUS_ADD_CHILD(parent, 0, "npx", 0);
208 if (child == NULL)
209 panic("npx_identify");
210}
211
212/*
213 * Do minimal handling of npx interrupts to convert them to traps.
214 */
215static void
216npx_intr(dummy)
217 void *dummy;
218{
219 struct thread *td;
220
221 npx_intrs_while_probing++;
222
223 /*
224 * The BUSY# latch must be cleared in all cases so that the next
225 * unmasked npx exception causes an interrupt.
226 */
227#ifdef PC98
228 outb(0xf8, 0);
229#else

--- 15 unchanged lines hidden (view full) ---

245 td = PCPU_GET(fpcurthread);
246 if (td != NULL) {
247 td->td_pcb->pcb_flags |= PCB_NPXTRAP;
248 mtx_lock_spin(&sched_lock);
249 td->td_flags |= TDF_ASTPENDING;
250 mtx_unlock_spin(&sched_lock);
251 }
252}
253
254/*
255 * Probe routine. Initialize cr0 to give correct behaviour for [f]wait
256 * whether the device exists or not (XXX should be elsewhere). Set flags
257 * to tell npxattach() what to do. Modify device struct if npx doesn't
258 * need to use interrupts. Return 0 if device exists.
259 */
260static int
261npx_probe(dev)
262 device_t dev;
263{
264 struct gate_descriptor save_idt_npxtrap;
265 struct resource *ioport_res, *irq_res;
266 void *irq_cookie;
267 int ioport_rid, irq_num, irq_rid;
268 u_short control;
269 u_short status;
270
271 save_idt_npxtrap = idt[IDT_MF];

--- 14 unchanged lines hidden (view full) ---

286 irq_rid = 0;
287 irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, irq_num,
288 irq_num, 1, RF_ACTIVE);
289 if (irq_res == NULL)
290 panic("npx: can't get IRQ");
291 if (bus_setup_intr(dev, irq_res, INTR_TYPE_MISC | INTR_FAST, npx_intr,
292 NULL, &irq_cookie) != 0)
293 panic("npx: can't create intr");
294
295 /*
296 * Partially reset the coprocessor, if any. Some BIOS's don't reset
297 * it after a warm boot.
298 */
299#ifdef PC98
300 outb(0xf8,0);
301#else

--- 24 unchanged lines hidden (view full) ---

326 * pending, then we may get a bogus IRQ13, but npx_intr() will handle
327 * it OK. Bogus halts have never been observed, but we enabled
328 * IRQ13 and cleared the BUSY# latch early to handle them anyway.
329 */
330 fninit();
331
332 device_set_desc(dev, "math processor");
333
334 /*
335 * Don't use fwait here because it might hang.
336 * Don't use fnop here because it usually hangs if there is no FPU.
337 */
338 DELAY(1000); /* wait for any IRQ13 */
339#ifdef DIAGNOSTIC
340 if (npx_intrs_while_probing != 0)
341 printf("fninit caused %u bogus npx interrupt(s)\n",
342 npx_intrs_while_probing);

--- 38 unchanged lines hidden (view full) ---

381 goto no_irq13;
382 }
383 if (npx_intrs_while_probing != 0) {
384 /*
385 * Bad, we are stuck with IRQ13.
386 */
387 npx_irq13 = 1;
388 idt[IDT_MF] = save_idt_npxtrap;
389#ifdef SMP
390 if (mp_ncpus > 1)
391 panic("npx0 cannot use IRQ 13 on an SMP system");
392#endif
393 return (0);
394 }
395 /*
396 * Worse, even IRQ13 is broken. Use emulator.
397 */
398 }
399 }
400 /*
401 * Probe failed, but we want to get to npxattach to initialize the
402 * emulator and say that it has been installed. XXX handle devices
403 * that aren't really devices better.
404 */
405#ifdef SMP
406 if (mp_ncpus > 1)
407 panic("npx0 cannot be emulated on an SMP system");
408#endif
409 /* FALLTHROUGH */
410no_irq13:
411 idt[IDT_MF] = save_idt_npxtrap;
412 bus_teardown_intr(dev, irq_res, irq_cookie);
413
414 /*
415 * XXX hack around brokenness of bus_teardown_intr(). If we left the
416 * irq active then we would get it instead of exception 16.
417 */
418 {
419 struct intsrc *isrc;
420
421 isrc = intr_lookup_source(irq_num);
422 isrc->is_pic->pic_disable_source(isrc);
423 }
424
425 bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res);
426 bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, ioport_res);
427 return (0);
428}
429
430/*
431 * Attach routine - announce which it is, and wire into system
432 */
433static int
434npx_attach(dev)
435 device_t dev;

--- 660 unchanged lines hidden ---