xref: /original-bsd/sys/i386/isa/npx.c (revision 963f8367)
1 /*-
2  * Copyright (c) 1990 William Jolitz.
3  * Copyright (c) 1991 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  *
8  *	@(#)npx.c	7.1 (Berkeley) 05/09/91
9  */
10 
11 #include "npx.h"
12 #if NNPX > 0
13 
14 #include "param.h"
15 #include "systm.h"
16 #include "conf.h"
17 #include "file.h"
18 #include "proc.h"
19 #include "machine/pcb.h"
20 #include "machine/pte.h"
21 #include "ioctl.h"
22 #include "machine/specialreg.h"
23 #include "i386/isa/isa_device.h"
24 #include "icu.h"
25 /*
26  * 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
27  */
28 
29 int	npxprobe(), npxattach(), npxintr();
30 struct	isa_driver npxdriver = {
31 	npxprobe, npxattach, "npx",
32 };
33 
34 static struct proc *npxproc;	/* process who owns device, otherwise zero */
35 extern struct user npxutl;	/* owners user structure */
36 extern struct pte Npxmap[];	/* kernel ptes mapping owner's user structure */
37 static npxexists;
38 extern long npx0mask;
39 
40 /*
41  * Probe routine - look device, otherwise set emulator bit
42  */
43 npxprobe(dvp)
44 	struct isa_device *dvp;
45 {	static status, control;
46 
47 #ifdef lint
48 	npxintr();
49 #endif
50 
51 	/* insure EM bit off */
52 	asm("	fninit ");	/* put device in known state */
53 
54 	/* check for a proper status of zero */
55 	status = 0xa5a5;
56 	asm ("	fnstsw	%0 " : "=m" (status) : "m" (status) );
57 
58 	if (status == 0) {
59 
60 		/* good, now check for a proper control word */
61 		control = 0xa5a5;
62 		asm ("	fnstcw %0 " : "=m" (control) : "m" (control));
63 
64 		if ((control&0x103f) == 0x3f) {
65 			/* then we have a numeric coprocessor */
66 		/* XXX should force an exception here to generate an intr */
67 			return (1);
68 		}
69 	}
70 
71 /* insure EM bit on */
72 	return (0);
73 }
74 
75 /*
76  * Attach routine - announce which it is, and wire into system
77  */
78 npxattach(dvp)
79 	struct isa_device *dvp;
80 {
81 
82 	npxinit(0x262);
83 	/* check for ET bit to decide 387/287 */
84 	/*outb(0xb1,0);		/* reset processor */
85 	npxexists++;
86 	npx0mask = dvp->id_irq;
87 }
88 
89 /*
90  * Initialize floating point unit, usually after an error
91  */
92 npxinit(control) {
93 
94 	if (npxexists == 0) return;
95 
96 
97 	load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
98 #ifdef INTEL_COMPAT
99 	asm ("	finit");
100 	asm("	fldcw %0" : : "g" (control));
101 	asm("	fnsave %0 " : : "g"
102 		(((struct pcb *)curproc->p_addr)->pcb_savefpu) );
103 #else
104 	asm("fninit");
105 	asm("fnsave %0" : : "g"
106 		(((struct pcb *)curproc->p_addr)->pcb_savefpu) );
107 #endif
108 	load_cr0(rcr0() | CR0_EM);	/* start emulating */
109 
110 }
111 
112 #ifdef notyet
113 /*
114  * Load floating point context and record ownership to suite
115  */
116 npxload() {
117 
118 	if (npxproc) panic ("npxload");
119 	npxproc = curproc;
120 	uaccess(npxproc, Npxmap, &npxutl);
121 	asm("	frstor %0 " : : "g"
122 		(((struct pcb *)curproc->p_addr)->pcb_savefpu) );
123 }
124 
125 /*
126  * Unload floating point context and relinquish ownership
127  */
128 npxunload() {
129 
130 	if (npxproc == 0) panic ("npxunload");
131 	asm("	fsave %0 " : : "g" (npxutl.u_pcb.pcb_savefpu) );
132 	npxproc = 0 ;
133 }
134 
135 #endif
136 /*
137  * Record information needed in processing an exception and clear status word
138  */
139 npxintr() {
140 
141 	outb(0xf0,0);		/* reset processor */
142 
143 	/* save state in appropriate user structure */
144 	if (npxproc == 0 || npxexists == 0) panic ("npxintr");
145 #ifdef notyet
146 	asm ("	fnsave %0 " : : "g" (npxutl.u_pcb.pcb_savefpu) );
147 #endif
148 
149 	/*
150 	 * encode the appropriate u_code for detailed information
151          * on this exception
152 	 */
153 
154 	/* signal appropriate process */
155 	psignal (npxproc, SIGFPE);
156 
157 	/* clear the exception so we can catch others like it */
158 	asm ("	fnclex");
159 }
160 
161 /*
162  * Implement device not available (DNA) exception
163  */
164 npxdna() {
165 
166 	if (npxexists == 0) return(0);
167 	if (!(((struct pcb *) curproc->p_addr)->pcb_flags & FP_WASUSED)
168 	    ||(((struct pcb *) curproc->p_addr)->pcb_flags & FP_NEEDSRESTORE)) {
169 		load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
170 		asm("	frstor %0 " : : "g" (((struct pcb *) curproc->p_addr)->pcb_savefpu) );
171 		((struct pcb *) curproc->p_addr)->pcb_flags |= FP_WASUSED | FP_NEEDSSAVE;
172 		((struct pcb *) curproc->p_addr)->pcb_flags &= ~FP_NEEDSRESTORE;
173 		npxproc = curproc;
174 
175 		return(1);
176 	}
177 	return (0);
178 }
179 #endif
180