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.3 (Berkeley) 11/16/91 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 asm(" fninit "); /* put device in known state */ 52 53 /* check for a proper status of zero */ 54 status = 0xa5a5; 55 asm (" fnstsw %0 " : "=m" (status) : "m" (status) ); 56 57 if (status == 0) { 58 59 /* good, now check for a proper control word */ 60 control = 0xa5a5; 61 asm (" fnstcw %0 " : "=m" (control) : "m" (control)); 62 63 if ((control&0x103f) == 0x3f) { 64 /* then we have a numeric coprocessor */ 65 /* XXX should force an exception here to generate an intr */ 66 return (1); 67 } 68 } 69 70 /* insure EM bit on */ 71 return (0); 72 } 73 74 /* 75 * Attach routine - announce which it is, and wire into system 76 */ 77 npxattach(dvp) 78 struct isa_device *dvp; 79 { 80 81 npxinit(0x262); 82 /* check for ET bit to decide 387/287 */ 83 /*outb(0xb1,0); /* reset processor */ 84 npxexists++; 85 npx0mask = dvp->id_irq; 86 } 87 88 /* 89 * Initialize floating point unit, usually after an error 90 */ 91 npxinit(control) { 92 93 if (npxexists == 0) return; 94 95 96 load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 97 #ifdef INTEL_COMPAT 98 asm (" finit"); 99 asm(" fldcw %0" : : "g" (control)); 100 asm(" fnsave %0 " : : "g" (curpcb->pcb_savefpu) ); 101 #else 102 asm("fninit"); 103 asm(" fnsave %0 " : : "g" (curpcb->pcb_savefpu) ); 104 #endif 105 load_cr0(rcr0() | CR0_EM); /* start emulating */ 106 107 } 108 109 /* 110 * Load floating point context and record ownership to suite 111 */ 112 npxload() { 113 114 if (npxproc) panic ("npxload"); 115 npxproc = curproc; 116 npxpcb = curpcb; 117 asm(" frstor %0 " : : "g" (curpcb->pcb_savefpu) ); 118 } 119 120 /* 121 * Unload floating point context and relinquish ownership 122 */ 123 npxunload() { 124 125 if (npxproc == 0) panic ("npxunload"); 126 asm(" fsave %0 " : : "g" (npxpcb->pcb_savefpu) ); 127 npxproc = 0 ; 128 } 129 130 /* 131 * Record information needed in processing an exception and clear status word 132 */ 133 npxintr(frame) struct intrframe frame; { 134 struct trapframe tf; 135 136 outb(0xf0,0); /* reset processor */ 137 138 /* sync state in process context structure, in advance of debugger/process looking for it */ 139 if (npxproc == 0 || npxexists == 0) panic ("npxintr"); 140 asm (" fnsave %0 " : : "g" (npxproc->p_addr->u_pcb.pcb_savefpu) ); 141 142 /* 143 * Prepair a trap frame for our generic exception processing routine, trap() 144 */ 145 bcopy(&frame.if_es, &tf, sizeof(tf)); 146 tf.tf_trapno = T_ARITHTRAP; 147 #ifdef notyet 148 /* encode the appropriate code for detailed information on this exception */ 149 tf.tf_err = ???; 150 #endif 151 trap(tf); 152 153 /* 154 * Restore with any changes to superior frame 155 */ 156 bcopy(&tf, &frame.if_es, sizeof(tf)); 157 158 /* clear the exception so we can catch others like it */ 159 asm (" fnclex"); 160 } 161 162 /* 163 * Implement device not available (DNA) exception 164 */ 165 npxdna() { 166 167 if (npxexists == 0) return(0); 168 if (npxproc == curproc) 169 load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 170 else { 171 load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 172 if (npxproc) 173 asm(" fnsave %0 "::"g" (npxproc->p_addr->u_pcb.pcb_savefpu)); 174 asm(" frstor %0 " : : "g" (curpcb->pcb_savefpu)); 175 npxproc = curproc; 176 } 177 #ifdef garbage 178 if (!(curpcb->pcb_flags & FP_WASUSED) 179 ||(curpcb->pcb_flags & FP_NEEDSRESTORE)) { 180 load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 181 asm(" frstor %0 " : : "g" (curpcb->pcb_savefpu)); 182 curpcb->pcb_flags |= FP_WASUSED | FP_NEEDSSAVE; 183 curpcb->pcb_flags &= ~FP_NEEDSRESTORE; 184 npxproc = curproc; 185 npxpcb = curpcb; 186 } 187 load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 188 #endif 189 return (1); 190 } 191 #endif 192