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