1/* $NetBSD: fpu.c,v 1.12 2011/01/14 02:06:22 rmind Exp $ */ 2 3/*- 4 * Copyright (c) 2000, 2001 Ben Harris 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29/* 30 * fpu.c - Floating point unit support 31 */ 32 33#include <sys/param.h> 34 35__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.12 2011/01/14 02:06:22 rmind Exp $"); 36 37#include <sys/device.h> 38#include <sys/proc.h> 39#include <sys/systm.h> 40#include <arm/undefined.h> 41#include <machine/fpureg.h> 42#include <machine/pcb.h> 43 44 45#include <arch/acorn26/acorn26/fpuvar.h> 46 47#include "opt_fputypes.h" 48 49static int fpu_match(device_t, cfdata_t, void *); 50static void fpu_attach(device_t, device_t, void *); 51static register_t fpu_identify(void); 52 53CFATTACH_DECL(fpu, sizeof(struct fpu_softc), 54 fpu_match, fpu_attach, NULL, NULL); 55 56struct fpu_softc *the_fpu; 57 58static int 59fpu_match(device_t parent, cfdata_t cf, void *aux) 60{ 61 62 return the_fpu == NULL && fpu_identify() != 0; 63} 64 65static void 66fpu_attach(device_t parent, device_t self, void *aux) 67{ 68 int supported; 69 struct fpu_softc *sc = device_private(self); 70 71 the_fpu = sc; 72 printf(": "); 73 sc->sc_fputype = fpu_identify(); 74 supported = 0; 75 switch (sc->sc_fputype) { 76 case FPSR_SYSID_FPPC: 77 printf("FPPC/WE32206"); 78#ifdef FPU_FPPC 79 /* XXX Uncomment when we have minimal support. */ 80 supported = 1; 81 sc->sc_ctxload = fpctx_load_fppc; 82 sc->sc_ctxsave = fpctx_save_fppc; 83 sc->sc_enable = fpu_enable_fppc; 84 sc->sc_disable = fpu_disable_fppc; 85#endif 86 break; 87 case FPSR_SYSID_FPA: 88 printf("FPA"); 89#ifdef FPU_FPA 90 /* XXX Uncomment when we have minimal support. */ 91 supported = 1; 92 sc->sc_ctxload = fpctx_load_fpa; 93 sc->sc_ctxsave = fpctx_save_fpa; 94 sc->sc_enable = fpu_enable_fpa; 95 sc->sc_disable = fpu_disable_fpa; 96#endif 97 break; 98 default: 99 printf("Unknown type, ID=0x%02x", sc->sc_fputype >> 24); 100 break; 101 } 102 printf("\n"); 103 if (!supported) 104 printf("%s: WARNING: FPU type not supported by kernel\n", 105 device_xname(self)); 106} 107 108static label_t undef_jmp; 109 110static int 111fpu_undef_handler(u_int addr, u_int insn, struct trapframe *tf, int fault_code) 112{ 113 114 longjmp(&undef_jmp); 115} 116 117static register_t 118fpu_identify(void) 119{ 120 volatile register_t fpsr; 121 void *uh; 122 123 if (setjmp(&undef_jmp) == 0) { 124 uh = install_coproc_handler(FPA_COPROC, fpu_undef_handler); 125 fpsr = 0; 126 __asm volatile ("rfs %0" : "=r" (fpsr)); 127 } 128 remove_coproc_handler(uh); 129 return fpsr & FPSR_SYSID_MASK; 130} 131