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.4 (Berkeley) 05/20/92 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 load_cr0(rcr0() & ~CR0_EM); 52 53 asm(" fninit "); /* put device in known state */ 54 55 /* check for a proper status of zero */ 56 status = 0xa5a5; 57 asm (" fnstsw %0 " : "=m" (status) : "m" (status) ); 58 59 if (status == 0) { 60 61 /* good, now check for a proper control word */ 62 control = 0xa5a5; 63 asm (" fnstcw %0 " : "=m" (control) : "m" (control)); 64 65 if ((control&0x103f) == 0x3f) { 66 /* then we have a numeric coprocessor */ 67 /* XXX should force an exception here to generate an intr */ 68 return (1); 69 } 70 } 71 72 /* insure EM bit on */ 73 load_cr0(rcr0() | CR0_EM); 74 return (0); 75 } 76 77 /* 78 * Attach routine - announce which it is, and wire into system 79 */ 80 npxattach(dvp) 81 struct isa_device *dvp; 82 { 83 84 npxinit(0x262); 85 /* check for ET bit to decide 387/287 */ 86 npxexists++; 87 npx0mask = dvp->id_irq; 88 } 89 90 /* 91 * Initialize floating point unit, usually after an error 92 */ 93 npxinit(control) { 94 95 if (npxexists == 0) return; 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" (curpcb->pcb_savefpu) ); 102 #else 103 asm("fninit"); 104 asm(" fnsave %0 " : : "g" (curpcb->pcb_savefpu) ); 105 #endif 106 load_cr0(rcr0() | CR0_EM); /* start emulating */ 107 108 } 109 110 /* 111 * Record information needed in processing an exception and clear status word 112 */ 113 npxintr(frame) 114 struct intrframe frame; 115 { 116 if (npxexists == 0) { 117 printf ("stray npxintr\n"); 118 return; 119 } 120 121 outb(0xf0,0); /* reset coprocessor */ 122 123 /* 124 * npxproc may be NULL, if this is a delayed interrupt from 125 * a process that just exited. 126 */ 127 if (npxproc) { 128 /* 129 * sync state in process context structure, in advance 130 * of debugger/process looking for it. 131 */ 132 asm("fnsave %0" :: "g" (npxproc->p_addr->u_pcb.pcb_savefpu)); 133 psignal(npxproc, SIGFPE); 134 135 /* clear the exception so we can catch others like it */ 136 asm (" fnclex"); 137 } 138 } 139 140 /* 141 * Implement device not available (DNA) exception 142 */ 143 npxdna() 144 { 145 if (npxexists == 0) 146 return(0); 147 148 load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 149 if (npxproc != curproc) { 150 if (npxproc) 151 asm(" fnsave %0 "::"g" 152 (npxproc->p_addr->u_pcb.pcb_savefpu)); 153 asm(" frstor %0 " : : "g" (curpcb->pcb_savefpu)); 154 npxproc = curproc; 155 } 156 return (1); 157 } 158 #endif 159