Deleted Added
full compact
npx.c (119935) npx.c (121986)
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>
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 119935 2003-09-10 01:07:04Z jhb $");
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>
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>
55#include <sys/sysctl.h>
56#include <machine/bus.h>
57#include <sys/rman.h>
58#ifdef NPX_DEBUG
59#include <sys/syslog.h>
60#endif
61#include <sys/signalvar.h>
62#include <sys/user.h>
63
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
64#ifndef SMP
65#include <machine/asmacros.h>
65#include <machine/asmacros.h>
66#endif
67#include <machine/cputypes.h>
68#include <machine/frame.h>
69#include <machine/md_var.h>
70#include <machine/pcb.h>
71#include <machine/psl.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>
72#ifndef SMP
73#include <machine/clock.h>
71#include <machine/clock.h>
74#endif
75#include <machine/resource.h>
76#include <machine/specialreg.h>
77#include <machine/segments.h>
78#include <machine/ucontext.h>
79
72#include <machine/resource.h>
73#include <machine/specialreg.h>
74#include <machine/segments.h>
75#include <machine/ucontext.h>
76
80#ifndef SMP
81#include <i386/isa/icu.h>
82#ifdef PC98
83#include <pc98/pc98/pc98.h>
84#else
85#include <i386/isa/isa.h>
86#endif
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
87#endif
88#include <i386/isa/intr_machdep.h>
83#include <machine/intr_machdep.h>
89#ifdef DEV_ISA
90#include <isa/isavar.h>
91#endif
92
93#if !defined(CPU_ENABLE_SSE) && defined(I686_CPU)
94#define CPU_ENABLE_SSE
95#endif
96#if defined(CPU_DISABLE_SSE)

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

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

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

259 td = PCPU_GET(fpcurthread);
260 if (td != NULL) {
261 td->td_pcb->pcb_flags |= PCB_NPXTRAP;
262 mtx_lock_spin(&sched_lock);
263 td->td_flags |= TDF_ASTPENDING;
264 mtx_unlock_spin(&sched_lock);
265 }
266}
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}
267#endif /* !SMP */
268
269/*
270 * Probe routine. Initialize cr0 to give correct behaviour for [f]wait
271 * whether the device exists or not (XXX should be elsewhere). Set flags
272 * to tell npxattach() what to do. Modify device struct if npx doesn't
273 * need to use interrupts. Return 0 if device exists.
274 */
275static int
276npx_probe(dev)
277 device_t dev;
278{
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{
279#ifndef SMP
280 struct gate_descriptor save_idt_npxtrap;
281 struct resource *ioport_res, *irq_res;
282 void *irq_cookie;
283 int ioport_rid, irq_num, irq_rid;
284 u_short control;
285 u_short status;
286
287 save_idt_npxtrap = idt[IDT_MF];

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

302 irq_rid = 0;
303 irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, irq_num,
304 irq_num, 1, RF_ACTIVE);
305 if (irq_res == NULL)
306 panic("npx: can't get IRQ");
307 if (bus_setup_intr(dev, irq_res, INTR_TYPE_MISC | INTR_FAST, npx_intr,
308 NULL, &irq_cookie) != 0)
309 panic("npx: can't create intr");
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");
310#endif /* !SMP */
311
312 /*
313 * Partially reset the coprocessor, if any. Some BIOS's don't reset
314 * it after a warm boot.
315 */
316#ifdef PC98
317 outb(0xf8,0);
318#else

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

343 * pending, then we may get a bogus IRQ13, but npx_intr() will handle
344 * it OK. Bogus halts have never been observed, but we enabled
345 * IRQ13 and cleared the BUSY# latch early to handle them anyway.
346 */
347 fninit();
348
349 device_set_desc(dev, "math processor");
350
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
351#ifdef SMP
352
353 /*
334 /*
354 * Exception 16 MUST work for SMP.
355 */
356 npx_ex16 = hw_float = npx_exists = 1;
357 return (0);
358
359#else /* !SMP */
360
361 /*
362 * Don't use fwait here because it might hang.
363 * Don't use fnop here because it usually hangs if there is no FPU.
364 */
365 DELAY(1000); /* wait for any IRQ13 */
366#ifdef DIAGNOSTIC
367 if (npx_intrs_while_probing != 0)
368 printf("fninit caused %u bogus npx interrupt(s)\n",
369 npx_intrs_while_probing);

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

408 goto no_irq13;
409 }
410 if (npx_intrs_while_probing != 0) {
411 /*
412 * Bad, we are stuck with IRQ13.
413 */
414 npx_irq13 = 1;
415 idt[IDT_MF] = save_idt_npxtrap;
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
416 return (0);
417 }
418 /*
419 * Worse, even IRQ13 is broken. Use emulator.
420 */
421 }
422 }
423 /*
424 * Probe failed, but we want to get to npxattach to initialize the
425 * emulator and say that it has been installed. XXX handle devices
426 * that aren't really devices better.
427 */
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
428 /* FALLTHROUGH */
429no_irq13:
430 idt[IDT_MF] = save_idt_npxtrap;
431 bus_teardown_intr(dev, irq_res, irq_cookie);
432
433 /*
434 * XXX hack around brokenness of bus_teardown_intr(). If we left the
435 * irq active then we would get it instead of exception 16.
436 */
437 {
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 {
438 register_t crit;
419 struct intsrc *isrc;
439
420
440 crit = intr_disable();
441 mtx_lock_spin(&icu_lock);
442 INTRDIS(1 << irq_num);
443 mtx_unlock_spin(&icu_lock);
444 intr_restore(crit);
421 isrc = intr_lookup_source(irq_num);
422 isrc->is_pic->pic_disable_source(isrc);
445 }
446
447 bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res);
448 bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, ioport_res);
449 return (0);
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);
450
451#endif /* SMP */
452}
453
454/*
455 * Attach routine - announce which it is, and wire into system
456 */
457static int
458npx_attach(dev)
459 device_t dev;

--- 660 unchanged lines hidden ---
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 ---