xref: /csrg-svn/sys/i386/isa/npx.c (revision 49694)
149617Sbostic /*-
249617Sbostic  * Copyright (c) 1990 William Jolitz.
349617Sbostic  * Copyright (c) 1991 The Regents of the University of California.
449617Sbostic  * All rights reserved.
549617Sbostic  *
649617Sbostic  * %sccs.include.redist.c%
749617Sbostic  *
8*49694Swilliam  *	@(#)npx.c	7.2 (Berkeley) 05/12/91
945624Sbill  */
1045624Sbill #include "npx.h"
1149617Sbostic #if NNPX > 0
1245624Sbill 
1345624Sbill #include "param.h"
1445624Sbill #include "systm.h"
1545624Sbill #include "conf.h"
1645624Sbill #include "file.h"
1749573Swilliam #include "proc.h"
18*49694Swilliam #include "machine/cpu.h"
1949573Swilliam #include "machine/pcb.h"
20*49694Swilliam #include "machine/trap.h"
2145624Sbill #include "ioctl.h"
2249573Swilliam #include "machine/specialreg.h"
2349573Swilliam #include "i386/isa/isa_device.h"
2445624Sbill #include "icu.h"
2545624Sbill /*
2645547Sbill  * 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
2745547Sbill  */
2845547Sbill 
2945547Sbill int	npxprobe(), npxattach(), npxintr();
3045624Sbill struct	isa_driver npxdriver = {
3145547Sbill 	npxprobe, npxattach, "npx",
3245547Sbill };
3345547Sbill 
34*49694Swilliam struct proc *npxproc;	/* process who owns device, otherwise zero */
35*49694Swilliam struct pcb *npxpcb;	/* owners context structure */
3649573Swilliam static npxexists;
3749573Swilliam extern long npx0mask;
3845547Sbill 
3945547Sbill /*
4045547Sbill  * Probe routine - look device, otherwise set emulator bit
4145547Sbill  */
4245547Sbill npxprobe(dvp)
4345624Sbill 	struct isa_device *dvp;
4445624Sbill {	static status, control;
4545547Sbill 
4645547Sbill #ifdef lint
4745547Sbill 	npxintr();
4845547Sbill #endif
4945547Sbill 
5045624Sbill 	/* insure EM bit off */
5145624Sbill 	asm("	fninit ");	/* put device in known state */
5245624Sbill 
5345547Sbill 	/* check for a proper status of zero */
5445547Sbill 	status = 0xa5a5;
5545624Sbill 	asm ("	fnstsw	%0 " : "=m" (status) : "m" (status) );
5645547Sbill 
5745547Sbill 	if (status == 0) {
5845547Sbill 
5945547Sbill 		/* good, now check for a proper control word */
6045547Sbill 		control = 0xa5a5;
6145624Sbill 		asm ("	fnstcw %0 " : "=m" (control) : "m" (control));
6245547Sbill 
6345624Sbill 		if ((control&0x103f) == 0x3f) {
6445547Sbill 			/* then we have a numeric coprocessor */
6545547Sbill 		/* XXX should force an exception here to generate an intr */
6645547Sbill 			return (1);
6745547Sbill 		}
6845547Sbill 	}
6945547Sbill 
7045547Sbill /* insure EM bit on */
7145547Sbill 	return (0);
7245547Sbill }
7345547Sbill 
7445547Sbill /*
7545547Sbill  * Attach routine - announce which it is, and wire into system
7645547Sbill  */
7745547Sbill npxattach(dvp)
7845624Sbill 	struct isa_device *dvp;
7945547Sbill {
8045547Sbill 
8145624Sbill 	npxinit(0x262);
8245547Sbill 	/* check for ET bit to decide 387/287 */
8345547Sbill 	/*outb(0xb1,0);		/* reset processor */
8449573Swilliam 	npxexists++;
8549573Swilliam 	npx0mask = dvp->id_irq;
8645547Sbill }
8745547Sbill 
8845547Sbill /*
8945547Sbill  * Initialize floating point unit, usually after an error
9045547Sbill  */
9145624Sbill npxinit(control) {
9245547Sbill 
9349573Swilliam 	if (npxexists == 0) return;
9449573Swilliam 
9549573Swilliam 
9649573Swilliam 	load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
9749573Swilliam #ifdef INTEL_COMPAT
9849573Swilliam 	asm ("	finit");
9945624Sbill 	asm("	fldcw %0" : : "g" (control));
100*49694Swilliam 	asm("	fnsave %0 " : : "g" (curpcb->pcb_savefpu) );
10149573Swilliam #else
10249573Swilliam 	asm("fninit");
103*49694Swilliam 	asm("	fnsave %0 " : : "g" (curpcb->pcb_savefpu) );
10449573Swilliam #endif
10549573Swilliam 	load_cr0(rcr0() | CR0_EM);	/* start emulating */
10645547Sbill 
10745547Sbill }
10845547Sbill 
10945547Sbill /*
11045547Sbill  * Load floating point context and record ownership to suite
11145547Sbill  */
11245547Sbill npxload() {
11345547Sbill 
11445547Sbill 	if (npxproc) panic ("npxload");
11549573Swilliam 	npxproc = curproc;
116*49694Swilliam 	npxpcb = curpcb;
117*49694Swilliam 	asm("	frstor %0 " : : "g" (curpcb->pcb_savefpu) );
11845547Sbill }
11945547Sbill 
12045547Sbill /*
12145547Sbill  * Unload floating point context and relinquish ownership
12245547Sbill  */
12345547Sbill npxunload() {
12445547Sbill 
12545547Sbill 	if (npxproc == 0) panic ("npxunload");
126*49694Swilliam 	asm("	fsave %0 " : : "g" (npxpcb->pcb_savefpu) );
12745547Sbill 	npxproc = 0 ;
12845547Sbill }
12945547Sbill 
13045547Sbill /*
13145547Sbill  * Record information needed in processing an exception and clear status word
13245547Sbill  */
133*49694Swilliam npxintr(frame) struct intrframe frame; {
134*49694Swilliam 	struct trapframe tf;
13545547Sbill 
13649573Swilliam 	outb(0xf0,0);		/* reset processor */
13749573Swilliam 
138*49694Swilliam 	/* sync state in process context structure, in advance of debugger/process looking for it */
13949573Swilliam 	if (npxproc == 0 || npxexists == 0) panic ("npxintr");
140*49694Swilliam 	asm ("	fnsave %0 " : : "g" (npxpcb->pcb_savefpu) );
141*49694Swilliam 
142*49694Swilliam 	/*
143*49694Swilliam 	 * Prepair a trap frame for our generic exception processing routine, trap()
144*49694Swilliam 	 */
145*49694Swilliam 	bcopy(&frame.if_es, &tf, sizeof(tf));
146*49694Swilliam 	tf.tf_trapno = T_ARITHTRAP;
14749573Swilliam #ifdef notyet
148*49694Swilliam 	/* encode the appropriate code for detailed information on this exception */
149*49694Swilliam 	tf.tf_err = ???;
15049573Swilliam #endif
151*49694Swilliam 	trap(tf);
15245547Sbill 
15345547Sbill 	/*
154*49694Swilliam 	 * Restore with any changes to superior frame
15545547Sbill 	 */
156*49694Swilliam 	bcopy(&tf, &frame.if_es, sizeof(tf));
15745547Sbill 
15845547Sbill 	/* clear the exception so we can catch others like it */
15945547Sbill 	asm ("	fnclex");
16045547Sbill }
16145547Sbill 
16245547Sbill /*
16345547Sbill  * Implement device not available (DNA) exception
16445547Sbill  */
16545547Sbill npxdna() {
16649573Swilliam 
16749573Swilliam 	if (npxexists == 0) return(0);
168*49694Swilliam 	if (!(curpcb->pcb_flags & FP_WASUSED)
169*49694Swilliam 	    ||(curpcb->pcb_flags & FP_NEEDSRESTORE)) {
17049573Swilliam 		load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
171*49694Swilliam 		asm("	frstor %0 " : : "g" (curpcb->pcb_savefpu));
172*49694Swilliam 		curpcb->pcb_flags |= FP_WASUSED | FP_NEEDSSAVE;
173*49694Swilliam 		curpcb->pcb_flags &= ~FP_NEEDSRESTORE;
17449573Swilliam 		npxproc = curproc;
175*49694Swilliam 		npxpcb = curpcb;
17649573Swilliam 
17749573Swilliam 		return(1);
17849573Swilliam 	}
17949573Swilliam 	return (0);
18045547Sbill }
18145624Sbill #endif
182