1 /*- 2 * Copyright (c) 1990 William Jolitz. 3 * Copyright (c) 1991, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 * 8 * @(#)npx.c 8.1 (Berkeley) 06/11/93 9 */ 10 #include "npx.h" 11 #if NNPX > 0 12 13 #include <sys/param.h> 14 #include <sys/systm.h> 15 #include <sys/conf.h> 16 #include <sys/file.h> 17 #include <sys/proc.h> 18 #include <sys/user.h> 19 #include <sys/ioctl.h> 20 21 #include <machine/cpu.h> 22 #include <machine/trap.h> 23 #include <machine/specialreg.h> 24 #include <i386/isa/isa_device.h> 25 #include <i386/isa/icu.h> 26 /* 27 * 387 and 287 Numeric Coprocessor Extension (NPX) Driver. 28 */ 29 30 int npxprobe(), npxattach(), npxintr(); 31 struct isa_driver npxdriver = { 32 npxprobe, npxattach, "npx", 33 }; 34 35 struct proc *npxproc; /* process who owns device, otherwise zero */ 36 struct pcb *npxpcb; /* owners context 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 load_cr0(rcr0() & ~CR0_EM); 53 54 asm(" fninit "); /* put device in known state */ 55 56 /* check for a proper status of zero */ 57 status = 0xa5a5; 58 asm (" fnstsw %0 " : "=m" (status) : "m" (status) ); 59 60 if (status == 0) { 61 62 /* good, now check for a proper control word */ 63 control = 0xa5a5; 64 asm (" fnstcw %0 " : "=m" (control) : "m" (control)); 65 66 if ((control&0x103f) == 0x3f) { 67 /* then we have a numeric coprocessor */ 68 /* XXX should force an exception here to generate an intr */ 69 return (1); 70 } 71 } 72 73 /* insure EM bit on */ 74 load_cr0(rcr0() | CR0_EM); 75 return (0); 76 } 77 78 /* 79 * Attach routine - announce which it is, and wire into system 80 */ 81 npxattach(dvp) 82 struct isa_device *dvp; 83 { 84 85 npxinit(0x262); 86 /* check for ET bit to decide 387/287 */ 87 npxexists++; 88 npx0mask = dvp->id_irq; 89 } 90 91 /* 92 * Initialize floating point unit, usually after an error 93 */ 94 npxinit(control) { 95 96 if (npxexists == 0) return; 97 98 load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 99 #ifdef INTEL_COMPAT 100 asm (" finit"); 101 asm(" fldcw %0" : : "g" (control)); 102 asm(" fnsave %0 " : : "g" (curpcb->pcb_savefpu) ); 103 #else 104 asm("fninit"); 105 asm(" fnsave %0 " : : "g" (curpcb->pcb_savefpu) ); 106 #endif 107 load_cr0(rcr0() | CR0_EM); /* start emulating */ 108 109 } 110 111 /* 112 * Record information needed in processing an exception and clear status word 113 */ 114 npxintr(frame) 115 struct intrframe frame; 116 { 117 if (npxexists == 0) { 118 printf ("stray npxintr\n"); 119 return; 120 } 121 122 outb(0xf0,0); /* reset coprocessor */ 123 124 /* 125 * npxproc may be NULL, if this is a delayed interrupt from 126 * a process that just exited. 127 */ 128 if (npxproc) { 129 /* 130 * sync state in process context structure, in advance 131 * of debugger/process looking for it. 132 */ 133 asm("fnsave %0" :: "g" (npxproc->p_addr->u_pcb.pcb_savefpu)); 134 psignal(npxproc, SIGFPE); 135 136 /* clear the exception so we can catch others like it */ 137 asm (" fnclex"); 138 } 139 } 140 141 /* 142 * Implement device not available (DNA) exception 143 */ 144 npxdna() 145 { 146 if (npxexists == 0) 147 return(0); 148 149 load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 150 if (npxproc != curproc) { 151 if (npxproc) 152 asm(" fnsave %0 "::"g" 153 (npxproc->p_addr->u_pcb.pcb_savefpu)); 154 asm(" frstor %0 " : : "g" (curpcb->pcb_savefpu)); 155 npxproc = curproc; 156 } 157 return (1); 158 } 159 #endif 160