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