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