On Mon, 2 Aug 1999, Alex Holden wrote:
> On Fri, 30 Jul 1999, Greg Haerr wrote:
> >     I see.  Does anyone have any code for auto-detection of an
> > 8087/8287/8387?
> >From allegro/src/cpu.c:

I finally figured out where it's hiding in the NetBSD tree (the maths
coprocessor is an ISA device called npx???). It's longer than the other
two, but makes more sense...

>From sys/arch/i386/isa/npx.c:

#define fninit()                __asm("fninit")
#define fnstsw(addr)            __asm("fnstsw %0" : "=m" (*addr))
#define fnstcw(addr)            __asm("fnstcw %0" : "=m" (*addr))
#define fldcw(addr)             __asm("fldcw %0" : : "m" (*addr))
#define fp_divide_by_0()        __asm("fldz; fld1; fdiv %st,%st(1);
fwait")
static inline int
npxprobe1(ia)
        struct isa_attach_args *ia;
{
        int control;
        int status;

        ia->ia_iosize = 16;
        ia->ia_msize = 0;

        /*
         * Finish resetting the coprocessor, if any.  If there is an error
         * pending, then we may get a bogus IRQ13, but probeintr() will
handle
         * it OK.  Bogus halts have never been observed, but we enabled
         * IRQ13 and cleared the BUSY# latch early to handle them anyway.
         */
        fninit();
        delay(1000);            /* wait for any IRQ13 (fwait might hang)
*/

        /*
         * Check for a status of mostly zero.
         */
        status = 0x5a5a;
        fnstsw(&status);
        if ((status & 0xb8ff) == 0) {
                /*
                 * Good, now check for a proper control word.
                 */
                control = 0x5a5a;
                fnstcw(&control);
                if ((control & 0x1f3f) == 0x033f) {
                        /*
                         * We have an npx, now divide by 0 to see if
exception
                         * 16 works.
                         */
                        control &= ~(1 << 2);   /* enable divide by 0 trap
*/
                        fldcw(&control);
                        npx_traps_while_probing = npx_intrs_while_probing
= 0;
                        fp_divide_by_0();
                        if (npx_traps_while_probing != 0) {
                                /*
                                 * Good, exception 16 works.
                                 */
                                npx_type = NPX_EXCEPTION;
                                ia->ia_irq = IRQUNK;    /* zap the
interrupt */
                        } else if (npx_intrs_while_probing != 0) {
                                /*
                                 * Bad, we are stuck with IRQ13.
                                 */
                                npx_type = NPX_INTERRUPT;
                        } else {
                                /*
                                 * Worse, even IRQ13 is broken.  Use
emulator.
                                 */
                                npx_type = NPX_BROKEN;
                                ia->ia_irq = IRQUNK;
                        }
                        return 1;
                }
        }
        /*
         * Probe failed.  There is no usable FPU.
         */
        npx_type = NPX_NONE;
        return 0;
}

--------------- Linux- the choice of a GNU generation. --------------
: Alex Holden (M1CJD)- Caver, Programmer, Land Rover nut, Radio Ham :
-------------------- http://www.linuxhacker.org/ --------------------

Reply via email to