xref: /csrg-svn/sys/i386/isa/npx.c (revision 45547)
1*45547Sbill /*
2*45547Sbill  * 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
3*45547Sbill  * @(#)npx.c	1.1 (Berkeley) 11/08/90
4*45547Sbill  */
5*45547Sbill 
6*45547Sbill int	npxprobe(), npxattach(), npxintr();
7*45547Sbill struct	driver npxdriver = {
8*45547Sbill 	npxprobe, npxattach, "npx",
9*45547Sbill };
10*45547Sbill 
11*45547Sbill struct proc	*npxproc;	/* process who owns device, otherwise zero */
12*45547Sbill struct user	*npxutl;	/* owners user structure */
13*45547Sbill struct pte	*Npxmap;	/* kernel ptes mapping owner's user structure */
14*45547Sbill 
15*45547Sbill /*
16*45547Sbill  * Probe routine - look device, otherwise set emulator bit
17*45547Sbill  */
18*45547Sbill npxprobe(dvp)
19*45547Sbill 	struct device *dvp;
20*45547Sbill {
21*45547Sbill 	register status;
22*45547Sbill 
23*45547Sbill #ifdef lint
24*45547Sbill 	npxintr();
25*45547Sbill #endif
26*45547Sbill /* insure EM bit off */
27*45547Sbill 	asm("	fninit");	/* put device in known state */
28*45547Sbill 
29*45547Sbill 	/* check for a proper status of zero */
30*45547Sbill 	status = 0xa5a5;
31*45547Sbill 	asm("	movw	%1,%%ax ; fnstsw %%ax ;  movw %%ax, %0"
32*45547Sbill 		: "=g" (status) : "g" (status) : "ax");
33*45547Sbill 
34*45547Sbill 	if (status == 0) {
35*45547Sbill 		register control;
36*45547Sbill 
37*45547Sbill 		/* good, now check for a proper control word */
38*45547Sbill 		control = 0xa5a5;
39*45547Sbill 		asm("	movw	%1,%%ax ; fnstcw %%ax ;  movw %%ax, %0"
40*45547Sbill 			: "=g" (control) : "g" (control) : "ax");
41*45547Sbill 
42*45547Sbill 		if (control&0x103f == 0x3f) {
43*45547Sbill 			/* then we have a numeric coprocessor */
44*45547Sbill 		/* XXX should force an exception here to generate an intr */
45*45547Sbill 			return (1);
46*45547Sbill 		}
47*45547Sbill 	}
48*45547Sbill 
49*45547Sbill /* insure EM bit on */
50*45547Sbill 	return (0);
51*45547Sbill }
52*45547Sbill 
53*45547Sbill /*
54*45547Sbill  * Attach routine - announce which it is, and wire into system
55*45547Sbill  */
56*45547Sbill npxattach(dvp)
57*45547Sbill 	struct device *dvp;
58*45547Sbill {
59*45547Sbill 	int unit = dvp->unit;
60*45547Sbill 
61*45547Sbill 	npxinit();
62*45547Sbill 	/* check for ET bit to decide 387/287 */
63*45547Sbill 	INTREN(IRQ13);
64*45547Sbill 	/*outb(0xb1,0);		/* reset processor */
65*45547Sbill }
66*45547Sbill 
67*45547Sbill /*
68*45547Sbill  * Initialize floating point unit, usually after an error
69*45547Sbill  */
70*45547Sbill npxinit() {
71*45547Sbill 	register control;
72*45547Sbill 
73*45547Sbill 	asm ("	fninit");
74*45547Sbill 	control = XXX;
75*45547Sbill 	asm("	movw	%0,%%ax ; fldcw %%ax "
76*45547Sbill 			: "g" (control) : "ax");
77*45547Sbill 
78*45547Sbill }
79*45547Sbill 
80*45547Sbill /*
81*45547Sbill  * Load floating point context and record ownership to suite
82*45547Sbill  */
83*45547Sbill npxload() {
84*45547Sbill 
85*45547Sbill 	if (npxproc) panic ("npxload");
86*45547Sbill 	npxproc = u.u_procp;
87*45547Sbill 	uaccess(npxproc, Npxmap, &npxutl);
88*45547Sbill 	asm("	frstor %0 " : "g" (u.u_pcb.pcb_savefpu) );
89*45547Sbill }
90*45547Sbill 
91*45547Sbill /*
92*45547Sbill  * Unload floating point context and relinquish ownership
93*45547Sbill  */
94*45547Sbill npxunload() {
95*45547Sbill 
96*45547Sbill 	if (npxproc == 0) panic ("npxunload");
97*45547Sbill 	asm("	fsave %0 " : "g" (npxutl.u_pcb.pcb_savefpu) );
98*45547Sbill 	npxproc = 0 ;
99*45547Sbill }
100*45547Sbill 
101*45547Sbill /*
102*45547Sbill  * Record information needed in processing an exception and clear status word
103*45547Sbill  */
104*45547Sbill npxexcept() {
105*45547Sbill 
106*45547Sbill 	/* save state in appropriate user structure */
107*45547Sbill 	if (npxproc == 0) panic ("npxexcept");
108*45547Sbill 	asm ("	fsave %0 " : "g" (npxutl.u_pcb.pcb_savefpu) );
109*45547Sbill 
110*45547Sbill 	/*
111*45547Sbill 	 * encode the appropriate u_code for detailed information
112*45547Sbill          * on this exception
113*45547Sbill 	 */
114*45547Sbill 
115*45547Sbill 	/* signal appropriate process */
116*45547Sbill 	psignal (npxproc, SIGFPE);
117*45547Sbill 
118*45547Sbill 	/* clear the exception so we can catch others like it */
119*45547Sbill 	asm ("	fnclex");
120*45547Sbill }
121*45547Sbill 
122*45547Sbill /*
123*45547Sbill  * Catch AT/386 interrupt used to signal exception, and simulate trap()
124*45547Sbill  */
125*45547Sbill npxintr() {
126*45547Sbill 	outb(0xf0,0);
127*45547Sbill 	pg("npxintr");
128*45547Sbill }
129*45547Sbill 
130*45547Sbill /*
131*45547Sbill  * Implement device not available (DNA) exception
132*45547Sbill  */
133*45547Sbill npxdna() {
134*45547Sbill }
135