xref: /csrg-svn/sys/i386/isa/npx.c (revision 49573)
145547Sbill /*
245624Sbill  * Copyright (c) 1990 W. Jolitz
3*49573Swilliam  * @(#)npx.c	1.4 (Berkeley) 05/09/91
445624Sbill  */
545624Sbill #include "npx.h"
645624Sbill #if	NNPX > 0
745624Sbill 
845624Sbill #include "param.h"
945624Sbill #include "systm.h"
1045624Sbill #include "conf.h"
1145624Sbill #include "file.h"
12*49573Swilliam #include "proc.h"
13*49573Swilliam #include "machine/pcb.h"
14*49573Swilliam #include "machine/pte.h"
1545624Sbill #include "ioctl.h"
16*49573Swilliam #include "machine/specialreg.h"
17*49573Swilliam #include "i386/isa/isa_device.h"
1845624Sbill #include "icu.h"
1945624Sbill /*
2045547Sbill  * 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
2145547Sbill  */
2245547Sbill 
2345547Sbill int	npxprobe(), npxattach(), npxintr();
2445624Sbill struct	isa_driver npxdriver = {
2545547Sbill 	npxprobe, npxattach, "npx",
2645547Sbill };
2745547Sbill 
28*49573Swilliam static struct proc *npxproc;	/* process who owns device, otherwise zero */
2945624Sbill extern struct user npxutl;	/* owners user structure */
3045624Sbill extern struct pte Npxmap[];	/* kernel ptes mapping owner's user structure */
31*49573Swilliam static npxexists;
32*49573Swilliam extern long npx0mask;
3345547Sbill 
3445547Sbill /*
3545547Sbill  * Probe routine - look device, otherwise set emulator bit
3645547Sbill  */
3745547Sbill npxprobe(dvp)
3845624Sbill 	struct isa_device *dvp;
3945624Sbill {	static status, control;
4045547Sbill 
4145547Sbill #ifdef lint
4245547Sbill 	npxintr();
4345547Sbill #endif
4445547Sbill 
4545624Sbill 	/* insure EM bit off */
4645624Sbill 	asm("	fninit ");	/* put device in known state */
4745624Sbill 
4845547Sbill 	/* check for a proper status of zero */
4945547Sbill 	status = 0xa5a5;
5045624Sbill 	asm ("	fnstsw	%0 " : "=m" (status) : "m" (status) );
5145547Sbill 
5245547Sbill 	if (status == 0) {
5345547Sbill 
5445547Sbill 		/* good, now check for a proper control word */
5545547Sbill 		control = 0xa5a5;
5645624Sbill 		asm ("	fnstcw %0 " : "=m" (control) : "m" (control));
5745547Sbill 
5845624Sbill 		if ((control&0x103f) == 0x3f) {
5945547Sbill 			/* then we have a numeric coprocessor */
6045547Sbill 		/* XXX should force an exception here to generate an intr */
6145547Sbill 			return (1);
6245547Sbill 		}
6345547Sbill 	}
6445547Sbill 
6545547Sbill /* insure EM bit on */
6645547Sbill 	return (0);
6745547Sbill }
6845547Sbill 
6945547Sbill /*
7045547Sbill  * Attach routine - announce which it is, and wire into system
7145547Sbill  */
7245547Sbill npxattach(dvp)
7345624Sbill 	struct isa_device *dvp;
7445547Sbill {
7545547Sbill 
7645624Sbill 	npxinit(0x262);
7745547Sbill 	/* check for ET bit to decide 387/287 */
7845547Sbill 	/*outb(0xb1,0);		/* reset processor */
79*49573Swilliam 	npxexists++;
80*49573Swilliam 	npx0mask = dvp->id_irq;
8145547Sbill }
8245547Sbill 
8345547Sbill /*
8445547Sbill  * Initialize floating point unit, usually after an error
8545547Sbill  */
8645624Sbill npxinit(control) {
8745547Sbill 
88*49573Swilliam 	if (npxexists == 0) return;
89*49573Swilliam 
90*49573Swilliam 
91*49573Swilliam 	load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
92*49573Swilliam #ifdef INTEL_COMPAT
93*49573Swilliam 	asm ("	finit");
9445624Sbill 	asm("	fldcw %0" : : "g" (control));
95*49573Swilliam 	asm("	fnsave %0 " : : "g"
96*49573Swilliam 		(((struct pcb *)curproc->p_addr)->pcb_savefpu) );
97*49573Swilliam #else
98*49573Swilliam 	asm("fninit");
99*49573Swilliam 	asm("fnsave %0" : : "g"
100*49573Swilliam 		(((struct pcb *)curproc->p_addr)->pcb_savefpu) );
101*49573Swilliam #endif
102*49573Swilliam 	load_cr0(rcr0() | CR0_EM);	/* start emulating */
10345547Sbill 
10445547Sbill }
10545547Sbill 
106*49573Swilliam #ifdef notyet
10745547Sbill /*
10845547Sbill  * Load floating point context and record ownership to suite
10945547Sbill  */
11045547Sbill npxload() {
11145547Sbill 
11245547Sbill 	if (npxproc) panic ("npxload");
113*49573Swilliam 	npxproc = curproc;
11445547Sbill 	uaccess(npxproc, Npxmap, &npxutl);
115*49573Swilliam 	asm("	frstor %0 " : : "g"
116*49573Swilliam 		(((struct pcb *)curproc->p_addr)->pcb_savefpu) );
11745547Sbill }
11845547Sbill 
11945547Sbill /*
12045547Sbill  * Unload floating point context and relinquish ownership
12145547Sbill  */
12245547Sbill npxunload() {
12345547Sbill 
12445547Sbill 	if (npxproc == 0) panic ("npxunload");
12545624Sbill 	asm("	fsave %0 " : : "g" (npxutl.u_pcb.pcb_savefpu) );
12645547Sbill 	npxproc = 0 ;
12745547Sbill }
12845547Sbill 
129*49573Swilliam #endif
13045547Sbill /*
13145547Sbill  * Record information needed in processing an exception and clear status word
13245547Sbill  */
133*49573Swilliam npxintr() {
13445547Sbill 
135*49573Swilliam 	outb(0xf0,0);		/* reset processor */
136*49573Swilliam 
13745547Sbill 	/* save state in appropriate user structure */
138*49573Swilliam 	if (npxproc == 0 || npxexists == 0) panic ("npxintr");
139*49573Swilliam #ifdef notyet
140*49573Swilliam 	asm ("	fnsave %0 " : : "g" (npxutl.u_pcb.pcb_savefpu) );
141*49573Swilliam #endif
14245547Sbill 
14345547Sbill 	/*
14445547Sbill 	 * encode the appropriate u_code for detailed information
14545547Sbill          * on this exception
14645547Sbill 	 */
14745547Sbill 
14845547Sbill 	/* signal appropriate process */
14945547Sbill 	psignal (npxproc, SIGFPE);
15045547Sbill 
15145547Sbill 	/* clear the exception so we can catch others like it */
15245547Sbill 	asm ("	fnclex");
15345547Sbill }
15445547Sbill 
15545547Sbill /*
15645547Sbill  * Implement device not available (DNA) exception
15745547Sbill  */
15845547Sbill npxdna() {
159*49573Swilliam 
160*49573Swilliam 	if (npxexists == 0) return(0);
161*49573Swilliam 	if (!(((struct pcb *) curproc->p_addr)->pcb_flags & FP_WASUSED)
162*49573Swilliam 	    ||(((struct pcb *) curproc->p_addr)->pcb_flags & FP_NEEDSRESTORE)) {
163*49573Swilliam 		load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
164*49573Swilliam 		asm("	frstor %0 " : : "g" (((struct pcb *) curproc->p_addr)->pcb_savefpu) );
165*49573Swilliam 		((struct pcb *) curproc->p_addr)->pcb_flags |= FP_WASUSED | FP_NEEDSSAVE;
166*49573Swilliam 		((struct pcb *) curproc->p_addr)->pcb_flags &= ~FP_NEEDSRESTORE;
167*49573Swilliam 		npxproc = curproc;
168*49573Swilliam 
169*49573Swilliam 		return(1);
170*49573Swilliam 	}
171*49573Swilliam 	return (0);
17245547Sbill }
17345624Sbill #endif
174