* Copyright (c) 1990 William Jolitz.
* Copyright (c) 1991 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)npx.c 7.2 (Berkeley) 5/12/91
static char rcsid
[] = "$Header: /usr/bill/working/sys/i386/isa/RCS/npx.c,v 1.2 92/01/21 14:34:27 william Exp $";
#include "machine/trap.h"
#include "machine/specialreg.h"
#include "i386/isa/isa_device.h"
* 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
int npxprobe(), npxattach(), npxintr();
struct isa_driver npxdriver
= {
npxprobe
, npxattach
, "npx",
struct proc
*npxproc
; /* process who owns device, otherwise zero */
struct pcb
*npxpcb
; /* owners context structure */
* Probe routine - look device, otherwise set emulator bit
{ static status
, control
;
load_cr0(rcr0() & ~CR0_EM
); /* stop emulating */
asm(" fninit "); /* put device in known state */
/* check for a proper status of zero */
asm (" fnstsw %0 " : "=m" (status
) : "m" (status
) );
if ((status
&0xff) == 0) {
/* good, now check for a proper control word */
asm (" fnstcw %0 " : "=m" (status
) : "m" (status
));
if ((status
&0x103f) == 0x3f) {
/* then we have a numeric coprocessor */
/* XXX should force an exception here to generate an intr */
load_cr0(rcr0() | CR0_EM
); /* start emulating */
* Attach routine - announce which it is, and wire into system
npxinit(__INITIAL_NPXCW__
);
* Initialize floating point unit.
if (npxexists
== 0) return;
load_cr0(rcr0() & ~CR0_EM
); /* stop emulating */
asm(" fldcw %0" : : "g" (wd
));
asm(" fnsave %0 " : : "g" (curpcb
->pcb_savefpu
) );
curpcb
->pcb_flags
|= FP_NEEDSRESTORE
;
load_cr0(rcr0() | CR0_EM
); /* start emulating */
outb(0xb1,0); /* reset processor */
* Load floating point context and record ownership to suite
if (npxproc
) panic ("npxload");
asm(" frstor %0 " : : "g" (curpcb
->pcb_savefpu
) );
* Unload floating point context and relinquish ownership
if (npxproc
== 0) panic ("npxunload");
asm(" fsave %0 " : : "g" (npxpcb
->pcb_savefpu
) );
* Record information needed in processing an exception and clear status word
npxintr(frame
) struct intrframe frame
; {
outb(0xf0,0); /* reset processor */
asm (" fnstsw %0 " : "=m" (status
) : "m" (status
) );
/* sync state in process context structure, in advance of debugger/process looking for it */
if (npxproc
== 0 || npxexists
== 0) panic ("npxintr");
asm (" fnsave %0 " : : "g" (npxpcb
->pcb_savefpu
) );
/* encode the appropriate code for detailed information on this exception */
/*if((pg("status %x", status) & 0x7f) == 't') {*/
/* pass exception to process, which may not be the current one */
if (npxproc
== curproc
) {
/* Q: what if in an interrupt, or in trap processing? */
if (ISPL(frame
.if_cs
) == SEL_UPL
) {
curproc
->p_regs
= (int *)&frame
.if_es
;
curpcb
->pcb_flags
|= FM_TRAP
; /* used by sendsig */
trapsignal(curproc
, SIGFPE
, code
);
curpcb
->pcb_flags
&= ~FM_TRAP
; /* used by sendsig */
psignal(npxproc
, SIGFPE
);
/* clear the exception so we can catch others like it */
* Implement device not available (DNA) exception
if (npxexists
== 0) return(0);
load_cr0(rcr0() & ~CR0_EM
); /* stop emulating */
if (curpcb
->pcb_flags
& FP_NEEDSRESTORE
)
asm(" frstor %0 " : : "g" (curpcb
->pcb_savefpu
));
curpcb
->pcb_flags
|= FP_WASUSED
| FP_NEEDSSAVE
;
curpcb
->pcb_flags
&= ~FP_NEEDSRESTORE
;