145547Sbill /* 245624Sbill * Copyright (c) 1990 W. Jolitz 3*49573Swilliam * @(#)npx.c 1.4 (Berkeley) 05/09/91 445624Sbill */ 545624Sbill #include "npx.h" 645624Sbill #if NNPX > 0 745624Sbill 845624Sbill #include "param.h" 945624Sbill #include "systm.h" 1045624Sbill #include "conf.h" 1145624Sbill #include "file.h" 12*49573Swilliam #include "proc.h" 13*49573Swilliam #include "machine/pcb.h" 14*49573Swilliam #include "machine/pte.h" 1545624Sbill #include "ioctl.h" 16*49573Swilliam #include "machine/specialreg.h" 17*49573Swilliam #include "i386/isa/isa_device.h" 1845624Sbill #include "icu.h" 1945624Sbill /* 2045547Sbill * 387 and 287 Numeric Coprocessor Extension (NPX) Driver. 2145547Sbill */ 2245547Sbill 2345547Sbill int npxprobe(), npxattach(), npxintr(); 2445624Sbill struct isa_driver npxdriver = { 2545547Sbill npxprobe, npxattach, "npx", 2645547Sbill }; 2745547Sbill 28*49573Swilliam static struct proc *npxproc; /* process who owns device, otherwise zero */ 2945624Sbill extern struct user npxutl; /* owners user structure */ 3045624Sbill extern struct pte Npxmap[]; /* kernel ptes mapping owner's user structure */ 31*49573Swilliam static npxexists; 32*49573Swilliam extern long npx0mask; 3345547Sbill 3445547Sbill /* 3545547Sbill * Probe routine - look device, otherwise set emulator bit 3645547Sbill */ 3745547Sbill npxprobe(dvp) 3845624Sbill struct isa_device *dvp; 3945624Sbill { static status, control; 4045547Sbill 4145547Sbill #ifdef lint 4245547Sbill npxintr(); 4345547Sbill #endif 4445547Sbill 4545624Sbill /* insure EM bit off */ 4645624Sbill asm(" fninit "); /* put device in known state */ 4745624Sbill 4845547Sbill /* check for a proper status of zero */ 4945547Sbill status = 0xa5a5; 5045624Sbill asm (" fnstsw %0 " : "=m" (status) : "m" (status) ); 5145547Sbill 5245547Sbill if (status == 0) { 5345547Sbill 5445547Sbill /* good, now check for a proper control word */ 5545547Sbill control = 0xa5a5; 5645624Sbill asm (" fnstcw %0 " : "=m" (control) : "m" (control)); 5745547Sbill 5845624Sbill if ((control&0x103f) == 0x3f) { 5945547Sbill /* then we have a numeric coprocessor */ 6045547Sbill /* XXX should force an exception here to generate an intr */ 6145547Sbill return (1); 6245547Sbill } 6345547Sbill } 6445547Sbill 6545547Sbill /* insure EM bit on */ 6645547Sbill return (0); 6745547Sbill } 6845547Sbill 6945547Sbill /* 7045547Sbill * Attach routine - announce which it is, and wire into system 7145547Sbill */ 7245547Sbill npxattach(dvp) 7345624Sbill struct isa_device *dvp; 7445547Sbill { 7545547Sbill 7645624Sbill npxinit(0x262); 7745547Sbill /* check for ET bit to decide 387/287 */ 7845547Sbill /*outb(0xb1,0); /* reset processor */ 79*49573Swilliam npxexists++; 80*49573Swilliam npx0mask = dvp->id_irq; 8145547Sbill } 8245547Sbill 8345547Sbill /* 8445547Sbill * Initialize floating point unit, usually after an error 8545547Sbill */ 8645624Sbill npxinit(control) { 8745547Sbill 88*49573Swilliam if (npxexists == 0) return; 89*49573Swilliam 90*49573Swilliam 91*49573Swilliam load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 92*49573Swilliam #ifdef INTEL_COMPAT 93*49573Swilliam asm (" finit"); 9445624Sbill asm(" fldcw %0" : : "g" (control)); 95*49573Swilliam asm(" fnsave %0 " : : "g" 96*49573Swilliam (((struct pcb *)curproc->p_addr)->pcb_savefpu) ); 97*49573Swilliam #else 98*49573Swilliam asm("fninit"); 99*49573Swilliam asm("fnsave %0" : : "g" 100*49573Swilliam (((struct pcb *)curproc->p_addr)->pcb_savefpu) ); 101*49573Swilliam #endif 102*49573Swilliam load_cr0(rcr0() | CR0_EM); /* start emulating */ 10345547Sbill 10445547Sbill } 10545547Sbill 106*49573Swilliam #ifdef notyet 10745547Sbill /* 10845547Sbill * Load floating point context and record ownership to suite 10945547Sbill */ 11045547Sbill npxload() { 11145547Sbill 11245547Sbill if (npxproc) panic ("npxload"); 113*49573Swilliam npxproc = curproc; 11445547Sbill uaccess(npxproc, Npxmap, &npxutl); 115*49573Swilliam asm(" frstor %0 " : : "g" 116*49573Swilliam (((struct pcb *)curproc->p_addr)->pcb_savefpu) ); 11745547Sbill } 11845547Sbill 11945547Sbill /* 12045547Sbill * Unload floating point context and relinquish ownership 12145547Sbill */ 12245547Sbill npxunload() { 12345547Sbill 12445547Sbill if (npxproc == 0) panic ("npxunload"); 12545624Sbill asm(" fsave %0 " : : "g" (npxutl.u_pcb.pcb_savefpu) ); 12645547Sbill npxproc = 0 ; 12745547Sbill } 12845547Sbill 129*49573Swilliam #endif 13045547Sbill /* 13145547Sbill * Record information needed in processing an exception and clear status word 13245547Sbill */ 133*49573Swilliam npxintr() { 13445547Sbill 135*49573Swilliam outb(0xf0,0); /* reset processor */ 136*49573Swilliam 13745547Sbill /* save state in appropriate user structure */ 138*49573Swilliam if (npxproc == 0 || npxexists == 0) panic ("npxintr"); 139*49573Swilliam #ifdef notyet 140*49573Swilliam asm (" fnsave %0 " : : "g" (npxutl.u_pcb.pcb_savefpu) ); 141*49573Swilliam #endif 14245547Sbill 14345547Sbill /* 14445547Sbill * encode the appropriate u_code for detailed information 14545547Sbill * on this exception 14645547Sbill */ 14745547Sbill 14845547Sbill /* signal appropriate process */ 14945547Sbill psignal (npxproc, SIGFPE); 15045547Sbill 15145547Sbill /* clear the exception so we can catch others like it */ 15245547Sbill asm (" fnclex"); 15345547Sbill } 15445547Sbill 15545547Sbill /* 15645547Sbill * Implement device not available (DNA) exception 15745547Sbill */ 15845547Sbill npxdna() { 159*49573Swilliam 160*49573Swilliam if (npxexists == 0) return(0); 161*49573Swilliam if (!(((struct pcb *) curproc->p_addr)->pcb_flags & FP_WASUSED) 162*49573Swilliam ||(((struct pcb *) curproc->p_addr)->pcb_flags & FP_NEEDSRESTORE)) { 163*49573Swilliam load_cr0(rcr0() & ~CR0_EM); /* stop emulating */ 164*49573Swilliam asm(" frstor %0 " : : "g" (((struct pcb *) curproc->p_addr)->pcb_savefpu) ); 165*49573Swilliam ((struct pcb *) curproc->p_addr)->pcb_flags |= FP_WASUSED | FP_NEEDSSAVE; 166*49573Swilliam ((struct pcb *) curproc->p_addr)->pcb_flags &= ~FP_NEEDSRESTORE; 167*49573Swilliam npxproc = curproc; 168*49573Swilliam 169*49573Swilliam return(1); 170*49573Swilliam } 171*49573Swilliam return (0); 17245547Sbill } 17345624Sbill #endif 174