xref: /csrg-svn/sys/i386/isa/npx.c (revision 49617)
1*49617Sbostic /*-
2*49617Sbostic  * Copyright (c) 1990 William Jolitz.
3*49617Sbostic  * Copyright (c) 1991 The Regents of the University of California.
4*49617Sbostic  * All rights reserved.
5*49617Sbostic  *
6*49617Sbostic  * %sccs.include.redist.c%
7*49617Sbostic  *
8*49617Sbostic  *	@(#)npx.c	7.1 (Berkeley) 05/09/91
945624Sbill  */
10*49617Sbostic 
1145624Sbill #include "npx.h"
12*49617Sbostic #if NNPX > 0
1345624Sbill 
1445624Sbill #include "param.h"
1545624Sbill #include "systm.h"
1645624Sbill #include "conf.h"
1745624Sbill #include "file.h"
1849573Swilliam #include "proc.h"
1949573Swilliam #include "machine/pcb.h"
2049573Swilliam #include "machine/pte.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 
3449573Swilliam static struct proc *npxproc;	/* process who owns device, otherwise zero */
3545624Sbill extern struct user npxutl;	/* owners user structure */
3645624Sbill extern struct pte Npxmap[];	/* kernel ptes mapping owner's user structure */
3749573Swilliam static npxexists;
3849573Swilliam extern long npx0mask;
3945547Sbill 
4045547Sbill /*
4145547Sbill  * Probe routine - look device, otherwise set emulator bit
4245547Sbill  */
4345547Sbill npxprobe(dvp)
4445624Sbill 	struct isa_device *dvp;
4545624Sbill {	static status, control;
4645547Sbill 
4745547Sbill #ifdef lint
4845547Sbill 	npxintr();
4945547Sbill #endif
5045547Sbill 
5145624Sbill 	/* insure EM bit off */
5245624Sbill 	asm("	fninit ");	/* put device in known state */
5345624Sbill 
5445547Sbill 	/* check for a proper status of zero */
5545547Sbill 	status = 0xa5a5;
5645624Sbill 	asm ("	fnstsw	%0 " : "=m" (status) : "m" (status) );
5745547Sbill 
5845547Sbill 	if (status == 0) {
5945547Sbill 
6045547Sbill 		/* good, now check for a proper control word */
6145547Sbill 		control = 0xa5a5;
6245624Sbill 		asm ("	fnstcw %0 " : "=m" (control) : "m" (control));
6345547Sbill 
6445624Sbill 		if ((control&0x103f) == 0x3f) {
6545547Sbill 			/* then we have a numeric coprocessor */
6645547Sbill 		/* XXX should force an exception here to generate an intr */
6745547Sbill 			return (1);
6845547Sbill 		}
6945547Sbill 	}
7045547Sbill 
7145547Sbill /* insure EM bit on */
7245547Sbill 	return (0);
7345547Sbill }
7445547Sbill 
7545547Sbill /*
7645547Sbill  * Attach routine - announce which it is, and wire into system
7745547Sbill  */
7845547Sbill npxattach(dvp)
7945624Sbill 	struct isa_device *dvp;
8045547Sbill {
8145547Sbill 
8245624Sbill 	npxinit(0x262);
8345547Sbill 	/* check for ET bit to decide 387/287 */
8445547Sbill 	/*outb(0xb1,0);		/* reset processor */
8549573Swilliam 	npxexists++;
8649573Swilliam 	npx0mask = dvp->id_irq;
8745547Sbill }
8845547Sbill 
8945547Sbill /*
9045547Sbill  * Initialize floating point unit, usually after an error
9145547Sbill  */
9245624Sbill npxinit(control) {
9345547Sbill 
9449573Swilliam 	if (npxexists == 0) return;
9549573Swilliam 
9649573Swilliam 
9749573Swilliam 	load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
9849573Swilliam #ifdef INTEL_COMPAT
9949573Swilliam 	asm ("	finit");
10045624Sbill 	asm("	fldcw %0" : : "g" (control));
10149573Swilliam 	asm("	fnsave %0 " : : "g"
10249573Swilliam 		(((struct pcb *)curproc->p_addr)->pcb_savefpu) );
10349573Swilliam #else
10449573Swilliam 	asm("fninit");
10549573Swilliam 	asm("fnsave %0" : : "g"
10649573Swilliam 		(((struct pcb *)curproc->p_addr)->pcb_savefpu) );
10749573Swilliam #endif
10849573Swilliam 	load_cr0(rcr0() | CR0_EM);	/* start emulating */
10945547Sbill 
11045547Sbill }
11145547Sbill 
11249573Swilliam #ifdef notyet
11345547Sbill /*
11445547Sbill  * Load floating point context and record ownership to suite
11545547Sbill  */
11645547Sbill npxload() {
11745547Sbill 
11845547Sbill 	if (npxproc) panic ("npxload");
11949573Swilliam 	npxproc = curproc;
12045547Sbill 	uaccess(npxproc, Npxmap, &npxutl);
12149573Swilliam 	asm("	frstor %0 " : : "g"
12249573Swilliam 		(((struct pcb *)curproc->p_addr)->pcb_savefpu) );
12345547Sbill }
12445547Sbill 
12545547Sbill /*
12645547Sbill  * Unload floating point context and relinquish ownership
12745547Sbill  */
12845547Sbill npxunload() {
12945547Sbill 
13045547Sbill 	if (npxproc == 0) panic ("npxunload");
13145624Sbill 	asm("	fsave %0 " : : "g" (npxutl.u_pcb.pcb_savefpu) );
13245547Sbill 	npxproc = 0 ;
13345547Sbill }
13445547Sbill 
13549573Swilliam #endif
13645547Sbill /*
13745547Sbill  * Record information needed in processing an exception and clear status word
13845547Sbill  */
13949573Swilliam npxintr() {
14045547Sbill 
14149573Swilliam 	outb(0xf0,0);		/* reset processor */
14249573Swilliam 
14345547Sbill 	/* save state in appropriate user structure */
14449573Swilliam 	if (npxproc == 0 || npxexists == 0) panic ("npxintr");
14549573Swilliam #ifdef notyet
14649573Swilliam 	asm ("	fnsave %0 " : : "g" (npxutl.u_pcb.pcb_savefpu) );
14749573Swilliam #endif
14845547Sbill 
14945547Sbill 	/*
15045547Sbill 	 * encode the appropriate u_code for detailed information
15145547Sbill          * on this exception
15245547Sbill 	 */
15345547Sbill 
15445547Sbill 	/* signal appropriate process */
15545547Sbill 	psignal (npxproc, SIGFPE);
15645547Sbill 
15745547Sbill 	/* clear the exception so we can catch others like it */
15845547Sbill 	asm ("	fnclex");
15945547Sbill }
16045547Sbill 
16145547Sbill /*
16245547Sbill  * Implement device not available (DNA) exception
16345547Sbill  */
16445547Sbill npxdna() {
16549573Swilliam 
16649573Swilliam 	if (npxexists == 0) return(0);
16749573Swilliam 	if (!(((struct pcb *) curproc->p_addr)->pcb_flags & FP_WASUSED)
16849573Swilliam 	    ||(((struct pcb *) curproc->p_addr)->pcb_flags & FP_NEEDSRESTORE)) {
16949573Swilliam 		load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
17049573Swilliam 		asm("	frstor %0 " : : "g" (((struct pcb *) curproc->p_addr)->pcb_savefpu) );
17149573Swilliam 		((struct pcb *) curproc->p_addr)->pcb_flags |= FP_WASUSED | FP_NEEDSSAVE;
17249573Swilliam 		((struct pcb *) curproc->p_addr)->pcb_flags &= ~FP_NEEDSRESTORE;
17349573Swilliam 		npxproc = curproc;
17449573Swilliam 
17549573Swilliam 		return(1);
17649573Swilliam 	}
17749573Swilliam 	return (0);
17845547Sbill }
17945624Sbill #endif
180