npx.c (119935) | npx.c (121986) |
---|---|
1/*- 2 * Copyright (c) 1990 William Jolitz. 3 * Copyright (c) 1991 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 21 unchanged lines hidden (view full) --- 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 35 */ 36 37#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1990 William Jolitz. 3 * Copyright (c) 1991 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 21 unchanged lines hidden (view full) --- 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 35 */ 36 37#include <sys/cdefs.h> |
38__FBSDID("$FreeBSD: head/sys/i386/isa/npx.c 119935 2003-09-10 01:07:04Z jhb $"); | 38__FBSDID("$FreeBSD: head/sys/i386/isa/npx.c 121986 2003-11-03 21:53:38Z jhb $"); |
39 40#include "opt_cpu.h" 41#include "opt_debug_npx.h" 42#include "opt_isa.h" 43#include "opt_npx.h" 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/bus.h> 48#include <sys/kernel.h> 49#include <sys/lock.h> 50#include <sys/malloc.h> 51#include <sys/module.h> 52#include <sys/mutex.h> 53#include <sys/mutex.h> 54#include <sys/proc.h> | 39 40#include "opt_cpu.h" 41#include "opt_debug_npx.h" 42#include "opt_isa.h" 43#include "opt_npx.h" 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/bus.h> 48#include <sys/kernel.h> 49#include <sys/lock.h> 50#include <sys/malloc.h> 51#include <sys/module.h> 52#include <sys/mutex.h> 53#include <sys/mutex.h> 54#include <sys/proc.h> |
55#include <sys/smp.h> |
|
55#include <sys/sysctl.h> 56#include <machine/bus.h> 57#include <sys/rman.h> 58#ifdef NPX_DEBUG 59#include <sys/syslog.h> 60#endif 61#include <sys/signalvar.h> 62#include <sys/user.h> 63 | 56#include <sys/sysctl.h> 57#include <machine/bus.h> 58#include <sys/rman.h> 59#ifdef NPX_DEBUG 60#include <sys/syslog.h> 61#endif 62#include <sys/signalvar.h> 63#include <sys/user.h> 64 |
64#ifndef SMP | |
65#include <machine/asmacros.h> | 65#include <machine/asmacros.h> |
66#endif | |
67#include <machine/cputypes.h> 68#include <machine/frame.h> 69#include <machine/md_var.h> 70#include <machine/pcb.h> 71#include <machine/psl.h> | 66#include <machine/cputypes.h> 67#include <machine/frame.h> 68#include <machine/md_var.h> 69#include <machine/pcb.h> 70#include <machine/psl.h> |
72#ifndef SMP | |
73#include <machine/clock.h> | 71#include <machine/clock.h> |
74#endif | |
75#include <machine/resource.h> 76#include <machine/specialreg.h> 77#include <machine/segments.h> 78#include <machine/ucontext.h> 79 | 72#include <machine/resource.h> 73#include <machine/specialreg.h> 74#include <machine/segments.h> 75#include <machine/ucontext.h> 76 |
80#ifndef SMP | |
81#include <i386/isa/icu.h> 82#ifdef PC98 83#include <pc98/pc98/pc98.h> 84#else 85#include <i386/isa/isa.h> 86#endif | 77#include <i386/isa/icu.h> 78#ifdef PC98 79#include <pc98/pc98/pc98.h> 80#else 81#include <i386/isa/isa.h> 82#endif |
87#endif 88#include <i386/isa/intr_machdep.h> | 83#include <machine/intr_machdep.h> |
89#ifdef DEV_ISA 90#include <isa/isavar.h> 91#endif 92 93#if !defined(CPU_ENABLE_SSE) && defined(I686_CPU) 94#define CPU_ENABLE_SSE 95#endif 96#if defined(CPU_DISABLE_SSE) --- 63 unchanged lines hidden (view full) --- 160#endif /* CPU_ENABLE_SSE */ 161 162typedef u_char bool_t; 163 164static void fpusave(union savefpu *); 165static void fpurstor(union savefpu *); 166static int npx_attach(device_t dev); 167static void npx_identify(driver_t *driver, device_t parent); | 84#ifdef DEV_ISA 85#include <isa/isavar.h> 86#endif 87 88#if !defined(CPU_ENABLE_SSE) && defined(I686_CPU) 89#define CPU_ENABLE_SSE 90#endif 91#if defined(CPU_DISABLE_SSE) --- 63 unchanged lines hidden (view full) --- 155#endif /* CPU_ENABLE_SSE */ 156 157typedef u_char bool_t; 158 159static void fpusave(union savefpu *); 160static void fpurstor(union savefpu *); 161static int npx_attach(device_t dev); 162static void npx_identify(driver_t *driver, device_t parent); |
168#ifndef SMP | |
169static void npx_intr(void *); | 163static void npx_intr(void *); |
170#endif | |
171static int npx_probe(device_t dev); 172#ifdef I586_CPU_XXX 173static long timezero(const char *funcname, 174 void (*func)(void *buf, size_t len)); 175#endif /* I586_CPU */ 176 177int hw_float; /* XXX currently just alias for npx_exists */ 178 179SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint, 180 CTLFLAG_RD, &hw_float, 0, 181 "Floatingpoint instructions executed in hardware"); 182 | 164static int npx_probe(device_t dev); 165#ifdef I586_CPU_XXX 166static long timezero(const char *funcname, 167 void (*func)(void *buf, size_t len)); 168#endif /* I586_CPU */ 169 170int hw_float; /* XXX currently just alias for npx_exists */ 171 172SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint, 173 CTLFLAG_RD, &hw_float, 0, 174 "Floatingpoint instructions executed in hardware"); 175 |
183#ifndef SMP | |
184static volatile u_int npx_intrs_while_probing; 185static volatile u_int npx_traps_while_probing; | 176static volatile u_int npx_intrs_while_probing; 177static volatile u_int npx_traps_while_probing; |
186#endif | |
187 188static union savefpu npx_cleanstate; 189static bool_t npx_cleanstate_ready; 190static bool_t npx_ex16; 191static bool_t npx_exists; 192static bool_t npx_irq13; 193 | 178 179static union savefpu npx_cleanstate; 180static bool_t npx_cleanstate_ready; 181static bool_t npx_ex16; 182static bool_t npx_exists; 183static bool_t npx_irq13; 184 |
194#ifndef SMP | |
195alias_for_inthand_t probetrap; 196__asm(" \n\ 197 .text \n\ 198 .p2align 2,0x90 \n\ 199 .type " __XSTRING(CNAME(probetrap)) ",@function \n\ 200" __XSTRING(CNAME(probetrap)) ": \n\ 201 ss \n\ 202 incl " __XSTRING(CNAME(npx_traps_while_probing)) " \n\ 203 fnclex \n\ 204 iret \n\ 205"); | 185alias_for_inthand_t probetrap; 186__asm(" \n\ 187 .text \n\ 188 .p2align 2,0x90 \n\ 189 .type " __XSTRING(CNAME(probetrap)) ",@function \n\ 190" __XSTRING(CNAME(probetrap)) ": \n\ 191 ss \n\ 192 incl " __XSTRING(CNAME(npx_traps_while_probing)) " \n\ 193 fnclex \n\ 194 iret \n\ 195"); |
206#endif /* SMP */ | |
207 208/* 209 * Identify routine. Create a connection point on our parent for probing. 210 */ 211static void 212npx_identify(driver, parent) 213 driver_t *driver; 214 device_t parent; 215{ 216 device_t child; 217 218 child = BUS_ADD_CHILD(parent, 0, "npx", 0); 219 if (child == NULL) 220 panic("npx_identify"); 221} 222 | 196 197/* 198 * Identify routine. Create a connection point on our parent for probing. 199 */ 200static void 201npx_identify(driver, parent) 202 driver_t *driver; 203 device_t parent; 204{ 205 device_t child; 206 207 child = BUS_ADD_CHILD(parent, 0, "npx", 0); 208 if (child == NULL) 209 panic("npx_identify"); 210} 211 |
223#ifndef SMP | |
224/* 225 * Do minimal handling of npx interrupts to convert them to traps. 226 */ 227static void 228npx_intr(dummy) 229 void *dummy; 230{ 231 struct thread *td; 232 | 212/* 213 * Do minimal handling of npx interrupts to convert them to traps. 214 */ 215static void 216npx_intr(dummy) 217 void *dummy; 218{ 219 struct thread *td; 220 |
233#ifndef SMP | |
234 npx_intrs_while_probing++; | 221 npx_intrs_while_probing++; |
235#endif | |
236 237 /* 238 * The BUSY# latch must be cleared in all cases so that the next 239 * unmasked npx exception causes an interrupt. 240 */ 241#ifdef PC98 242 outb(0xf8, 0); 243#else --- 15 unchanged lines hidden (view full) --- 259 td = PCPU_GET(fpcurthread); 260 if (td != NULL) { 261 td->td_pcb->pcb_flags |= PCB_NPXTRAP; 262 mtx_lock_spin(&sched_lock); 263 td->td_flags |= TDF_ASTPENDING; 264 mtx_unlock_spin(&sched_lock); 265 } 266} | 222 223 /* 224 * The BUSY# latch must be cleared in all cases so that the next 225 * unmasked npx exception causes an interrupt. 226 */ 227#ifdef PC98 228 outb(0xf8, 0); 229#else --- 15 unchanged lines hidden (view full) --- 245 td = PCPU_GET(fpcurthread); 246 if (td != NULL) { 247 td->td_pcb->pcb_flags |= PCB_NPXTRAP; 248 mtx_lock_spin(&sched_lock); 249 td->td_flags |= TDF_ASTPENDING; 250 mtx_unlock_spin(&sched_lock); 251 } 252} |
267#endif /* !SMP */ | |
268 269/* 270 * Probe routine. Initialize cr0 to give correct behaviour for [f]wait 271 * whether the device exists or not (XXX should be elsewhere). Set flags 272 * to tell npxattach() what to do. Modify device struct if npx doesn't 273 * need to use interrupts. Return 0 if device exists. 274 */ 275static int 276npx_probe(dev) 277 device_t dev; 278{ | 253 254/* 255 * Probe routine. Initialize cr0 to give correct behaviour for [f]wait 256 * whether the device exists or not (XXX should be elsewhere). Set flags 257 * to tell npxattach() what to do. Modify device struct if npx doesn't 258 * need to use interrupts. Return 0 if device exists. 259 */ 260static int 261npx_probe(dev) 262 device_t dev; 263{ |
279#ifndef SMP | |
280 struct gate_descriptor save_idt_npxtrap; 281 struct resource *ioport_res, *irq_res; 282 void *irq_cookie; 283 int ioport_rid, irq_num, irq_rid; 284 u_short control; 285 u_short status; 286 287 save_idt_npxtrap = idt[IDT_MF]; --- 14 unchanged lines hidden (view full) --- 302 irq_rid = 0; 303 irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, irq_num, 304 irq_num, 1, RF_ACTIVE); 305 if (irq_res == NULL) 306 panic("npx: can't get IRQ"); 307 if (bus_setup_intr(dev, irq_res, INTR_TYPE_MISC | INTR_FAST, npx_intr, 308 NULL, &irq_cookie) != 0) 309 panic("npx: can't create intr"); | 264 struct gate_descriptor save_idt_npxtrap; 265 struct resource *ioport_res, *irq_res; 266 void *irq_cookie; 267 int ioport_rid, irq_num, irq_rid; 268 u_short control; 269 u_short status; 270 271 save_idt_npxtrap = idt[IDT_MF]; --- 14 unchanged lines hidden (view full) --- 286 irq_rid = 0; 287 irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, irq_num, 288 irq_num, 1, RF_ACTIVE); 289 if (irq_res == NULL) 290 panic("npx: can't get IRQ"); 291 if (bus_setup_intr(dev, irq_res, INTR_TYPE_MISC | INTR_FAST, npx_intr, 292 NULL, &irq_cookie) != 0) 293 panic("npx: can't create intr"); |
310#endif /* !SMP */ | |
311 312 /* 313 * Partially reset the coprocessor, if any. Some BIOS's don't reset 314 * it after a warm boot. 315 */ 316#ifdef PC98 317 outb(0xf8,0); 318#else --- 24 unchanged lines hidden (view full) --- 343 * pending, then we may get a bogus IRQ13, but npx_intr() will handle 344 * it OK. Bogus halts have never been observed, but we enabled 345 * IRQ13 and cleared the BUSY# latch early to handle them anyway. 346 */ 347 fninit(); 348 349 device_set_desc(dev, "math processor"); 350 | 294 295 /* 296 * Partially reset the coprocessor, if any. Some BIOS's don't reset 297 * it after a warm boot. 298 */ 299#ifdef PC98 300 outb(0xf8,0); 301#else --- 24 unchanged lines hidden (view full) --- 326 * pending, then we may get a bogus IRQ13, but npx_intr() will handle 327 * it OK. Bogus halts have never been observed, but we enabled 328 * IRQ13 and cleared the BUSY# latch early to handle them anyway. 329 */ 330 fninit(); 331 332 device_set_desc(dev, "math processor"); 333 |
351#ifdef SMP 352 | |
353 /* | 334 /* |
354 * Exception 16 MUST work for SMP. 355 */ 356 npx_ex16 = hw_float = npx_exists = 1; 357 return (0); 358 359#else /* !SMP */ 360 361 /* | |
362 * Don't use fwait here because it might hang. 363 * Don't use fnop here because it usually hangs if there is no FPU. 364 */ 365 DELAY(1000); /* wait for any IRQ13 */ 366#ifdef DIAGNOSTIC 367 if (npx_intrs_while_probing != 0) 368 printf("fninit caused %u bogus npx interrupt(s)\n", 369 npx_intrs_while_probing); --- 38 unchanged lines hidden (view full) --- 408 goto no_irq13; 409 } 410 if (npx_intrs_while_probing != 0) { 411 /* 412 * Bad, we are stuck with IRQ13. 413 */ 414 npx_irq13 = 1; 415 idt[IDT_MF] = save_idt_npxtrap; | 335 * Don't use fwait here because it might hang. 336 * Don't use fnop here because it usually hangs if there is no FPU. 337 */ 338 DELAY(1000); /* wait for any IRQ13 */ 339#ifdef DIAGNOSTIC 340 if (npx_intrs_while_probing != 0) 341 printf("fninit caused %u bogus npx interrupt(s)\n", 342 npx_intrs_while_probing); --- 38 unchanged lines hidden (view full) --- 381 goto no_irq13; 382 } 383 if (npx_intrs_while_probing != 0) { 384 /* 385 * Bad, we are stuck with IRQ13. 386 */ 387 npx_irq13 = 1; 388 idt[IDT_MF] = save_idt_npxtrap; |
389#ifdef SMP 390 if (mp_ncpus > 1) 391 panic("npx0 cannot use IRQ 13 on an SMP system"); 392#endif |
|
416 return (0); 417 } 418 /* 419 * Worse, even IRQ13 is broken. Use emulator. 420 */ 421 } 422 } 423 /* 424 * Probe failed, but we want to get to npxattach to initialize the 425 * emulator and say that it has been installed. XXX handle devices 426 * that aren't really devices better. 427 */ | 393 return (0); 394 } 395 /* 396 * Worse, even IRQ13 is broken. Use emulator. 397 */ 398 } 399 } 400 /* 401 * Probe failed, but we want to get to npxattach to initialize the 402 * emulator and say that it has been installed. XXX handle devices 403 * that aren't really devices better. 404 */ |
405#ifdef SMP 406 if (mp_ncpus > 1) 407 panic("npx0 cannot be emulated on an SMP system"); 408#endif |
|
428 /* FALLTHROUGH */ 429no_irq13: 430 idt[IDT_MF] = save_idt_npxtrap; 431 bus_teardown_intr(dev, irq_res, irq_cookie); 432 433 /* 434 * XXX hack around brokenness of bus_teardown_intr(). If we left the 435 * irq active then we would get it instead of exception 16. 436 */ 437 { | 409 /* FALLTHROUGH */ 410no_irq13: 411 idt[IDT_MF] = save_idt_npxtrap; 412 bus_teardown_intr(dev, irq_res, irq_cookie); 413 414 /* 415 * XXX hack around brokenness of bus_teardown_intr(). If we left the 416 * irq active then we would get it instead of exception 16. 417 */ 418 { |
438 register_t crit; | 419 struct intsrc *isrc; |
439 | 420 |
440 crit = intr_disable(); 441 mtx_lock_spin(&icu_lock); 442 INTRDIS(1 << irq_num); 443 mtx_unlock_spin(&icu_lock); 444 intr_restore(crit); | 421 isrc = intr_lookup_source(irq_num); 422 isrc->is_pic->pic_disable_source(isrc); |
445 } 446 447 bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res); 448 bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, ioport_res); 449 return (0); | 423 } 424 425 bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res); 426 bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, ioport_res); 427 return (0); |
450 451#endif /* SMP */ | |
452} 453 454/* 455 * Attach routine - announce which it is, and wire into system 456 */ 457static int 458npx_attach(dev) 459 device_t dev; --- 660 unchanged lines hidden --- | 428} 429 430/* 431 * Attach routine - announce which it is, and wire into system 432 */ 433static int 434npx_attach(dev) 435 device_t dev; --- 660 unchanged lines hidden --- |