xref: /original-bsd/sys/i386/isa/npx.c (revision f6a299d4)
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.3 (Berkeley) 11/16/91
9  */
10 #include "npx.h"
11 #if NNPX > 0
12 
13 #include "param.h"
14 #include "systm.h"
15 #include "conf.h"
16 #include "file.h"
17 #include "proc.h"
18 #include "machine/cpu.h"
19 #include "user.h"
20 #include "machine/trap.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 struct proc *npxproc;	/* process who owns device, otherwise zero */
35 struct pcb *npxpcb;	/* owners context structure */
36 static npxexists;
37 extern long npx0mask;
38 
39 /*
40  * Probe routine - look device, otherwise set emulator bit
41  */
42 npxprobe(dvp)
43 	struct isa_device *dvp;
44 {	static status, control;
45 
46 #ifdef lint
47 	npxintr();
48 #endif
49 
50 	/* insure EM bit off */
51 	asm("	fninit ");	/* put device in known state */
52 
53 	/* check for a proper status of zero */
54 	status = 0xa5a5;
55 	asm ("	fnstsw	%0 " : "=m" (status) : "m" (status) );
56 
57 	if (status == 0) {
58 
59 		/* good, now check for a proper control word */
60 		control = 0xa5a5;
61 		asm ("	fnstcw %0 " : "=m" (control) : "m" (control));
62 
63 		if ((control&0x103f) == 0x3f) {
64 			/* then we have a numeric coprocessor */
65 		/* XXX should force an exception here to generate an intr */
66 			return (1);
67 		}
68 	}
69 
70 /* insure EM bit on */
71 	return (0);
72 }
73 
74 /*
75  * Attach routine - announce which it is, and wire into system
76  */
77 npxattach(dvp)
78 	struct isa_device *dvp;
79 {
80 
81 	npxinit(0x262);
82 	/* check for ET bit to decide 387/287 */
83 	/*outb(0xb1,0);		/* reset processor */
84 	npxexists++;
85 	npx0mask = dvp->id_irq;
86 }
87 
88 /*
89  * Initialize floating point unit, usually after an error
90  */
91 npxinit(control) {
92 
93 	if (npxexists == 0) return;
94 
95 
96 	load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
97 #ifdef INTEL_COMPAT
98 	asm ("	finit");
99 	asm("	fldcw %0" : : "g" (control));
100 	asm("	fnsave %0 " : : "g" (curpcb->pcb_savefpu) );
101 #else
102 	asm("fninit");
103 	asm("	fnsave %0 " : : "g" (curpcb->pcb_savefpu) );
104 #endif
105 	load_cr0(rcr0() | CR0_EM);	/* start emulating */
106 
107 }
108 
109 /*
110  * Load floating point context and record ownership to suite
111  */
112 npxload() {
113 
114 	if (npxproc) panic ("npxload");
115 	npxproc = curproc;
116 	npxpcb = curpcb;
117 	asm("	frstor %0 " : : "g" (curpcb->pcb_savefpu) );
118 }
119 
120 /*
121  * Unload floating point context and relinquish ownership
122  */
123 npxunload() {
124 
125 	if (npxproc == 0) panic ("npxunload");
126 	asm("	fsave %0 " : : "g" (npxpcb->pcb_savefpu) );
127 	npxproc = 0 ;
128 }
129 
130 /*
131  * Record information needed in processing an exception and clear status word
132  */
133 npxintr(frame) struct intrframe frame; {
134 	struct trapframe tf;
135 
136 	outb(0xf0,0);		/* reset processor */
137 
138 	/* sync state in process context structure, in advance of debugger/process looking for it */
139 	if (npxproc == 0 || npxexists == 0) panic ("npxintr");
140 	asm ("	fnsave %0 " : : "g" (npxproc->p_addr->u_pcb.pcb_savefpu) );
141 
142 	/*
143 	 * Prepair a trap frame for our generic exception processing routine, trap()
144 	 */
145 	bcopy(&frame.if_es, &tf, sizeof(tf));
146 	tf.tf_trapno = T_ARITHTRAP;
147 #ifdef notyet
148 	/* encode the appropriate code for detailed information on this exception */
149 	tf.tf_err = ???;
150 #endif
151 	trap(tf);
152 
153 	/*
154 	 * Restore with any changes to superior frame
155 	 */
156 	bcopy(&tf, &frame.if_es, sizeof(tf));
157 
158 	/* clear the exception so we can catch others like it */
159 	asm ("	fnclex");
160 }
161 
162 /*
163  * Implement device not available (DNA) exception
164  */
165 npxdna() {
166 
167 	if (npxexists == 0) return(0);
168 	if (npxproc == curproc)
169 		load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
170 	else {
171 		load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
172 		if (npxproc)
173 			asm(" fnsave %0 "::"g" (npxproc->p_addr->u_pcb.pcb_savefpu));
174 		asm("	frstor %0 " : : "g" (curpcb->pcb_savefpu));
175 		npxproc = curproc;
176 	}
177 #ifdef garbage
178 	if (!(curpcb->pcb_flags & FP_WASUSED)
179 	    ||(curpcb->pcb_flags & FP_NEEDSRESTORE)) {
180 		load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
181 		asm("	frstor %0 " : : "g" (curpcb->pcb_savefpu));
182 		curpcb->pcb_flags |= FP_WASUSED | FP_NEEDSSAVE;
183 		curpcb->pcb_flags &= ~FP_NEEDSRESTORE;
184 		npxproc = curproc;
185 		npxpcb = curpcb;
186 	}
187 	load_cr0(rcr0() & ~CR0_EM);	/* stop emulating */
188 #endif
189 	return (1);
190 }
191 #endif
192