1/* $NetBSD: machdep.c,v 1.172 2011/06/12 03:35:39 rmind Exp $ */ 2 3/* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah $Hdr: machdep.c 1.63 91/04/24$ 37 * 38 * @(#)machdep.c 7.16 (Berkeley) 6/3/91 39 */ 40 41#include <sys/cdefs.h> 42__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.172 2011/06/12 03:35:39 rmind Exp $"); 43 44#include "opt_ddb.h" 45#include "opt_compat_netbsd.h" 46#include "opt_mbtype.h" 47#include "opt_modular.h" 48#include "opt_panicbutton.h" 49 50#include <sys/param.h> 51#include <sys/systm.h> 52#include <sys/signalvar.h> 53#include <sys/kernel.h> 54#include <sys/proc.h> 55#include <sys/buf.h> 56#include <sys/reboot.h> 57#include <sys/conf.h> 58#include <sys/file.h> 59#include <sys/device.h> 60#include <sys/malloc.h> 61#include <sys/mbuf.h> 62#include <sys/msgbuf.h> 63#include <sys/vnode.h> 64#include <sys/queue.h> 65#include <sys/mount.h> 66#include <sys/syscallargs.h> 67#include <sys/ksyms.h> 68#include <sys/module.h> 69#include <sys/intr.h> 70#include <sys/exec.h> 71#include <sys/exec_aout.h> 72#include <sys/cpu.h> 73#if defined(DDB) && defined(__ELF__) 74#include <sys/exec_elf.h> 75#endif 76 77#undef PS /* XXX netccitt/pk.h conflict with machine/reg.h? */ 78 79#define MAXMEM 64*1024 /* XXX - from cmap.h */ 80#include <uvm/uvm_extern.h> 81 82#include <sys/sysctl.h> 83 84#include <machine/db_machdep.h> 85#include <ddb/db_sym.h> 86#include <ddb/db_extern.h> 87 88#include <machine/reg.h> 89#include <machine/psl.h> 90#include <machine/pte.h> 91 92#include <dev/cons.h> 93#include <dev/mm.h> 94 95#include "ksyms.h" 96#include "nvr.h" 97 98#define DEV_NVRAM 11 /* Nvram minor-number */ 99 100static void bootsync(void); 101static void call_sicallbacks(void); 102static void identifycpu(void); 103void straymfpint(int, u_short); 104void straytrap(int, u_short); 105 106#ifdef _MILANHW_ 107void nmihandler(void); 108#endif 109 110struct vm_map *phys_map = NULL; 111 112void * msgbufaddr; 113vaddr_t msgbufpa; 114 115int physmem = MAXMEM; /* max supported memory, changes to actual */ 116/* 117 * safepri is a safe priority for sleep to set for a spin-wait 118 * during autoconfiguration or after a panic. 119 */ 120int safepri = PSL_LOWIPL; 121extern int freebufspace; 122extern u_int lowram; 123 124/* 125 * For the fpu emulation and the fpu driver 126 */ 127int fputype = 0; 128 129/* the following is used externally (sysctl_hw) */ 130char machine[] = MACHINE; /* from <machine/param.h> */ 131 132/* Our exported CPU info; we can have only one. */ 133struct cpu_info cpu_info_store; 134 135 /* 136 * Console initialization: called early on from main, 137 * before vm init or startup. Do enough configuration 138 * to choose and initialize a console. 139 */ 140void 141consinit(void) 142{ 143 int i; 144 145 /* 146 * Initialize error message buffer. pmap_bootstrap() has 147 * positioned this at the end of kernel memory segment - map 148 * and initialize it now. 149 */ 150 for (i = 0; i < btoc(MSGBUFSIZE); i++) 151 pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE, 152 msgbufpa + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0); 153 pmap_update(pmap_kernel()); 154 initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 155 156 /* 157 * Initialize hardware that support various console types like 158 * the grf and PCI busses. 159 */ 160 config_console(); 161 162 /* 163 * Now pick the best console candidate. 164 */ 165 cninit(); 166 167#if NKSYMS || defined(DDB) || defined(MODULAR) 168 { 169 extern int end; 170 extern int *esym; 171 172#ifndef __ELF__ 173 ksyms_addsyms_elf(*(int *)&end, ((int *)&end) + 1, esym); 174#else 175 ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr), 176 (void *)&end, esym); 177#endif 178 } 179#endif 180#if defined (DDB) 181 if (boothowto & RB_KDB) 182 Debugger(); 183#endif 184} 185 186/* 187 * cpu_startup: allocate memory for variable-sized tables, 188 * initialize CPU, and do autoconfiguration. 189 */ 190void 191cpu_startup(void) 192{ 193 extern int iomem_malloc_safe; 194 char pbuf[9]; 195#ifdef DEBUG 196 extern int pmapdebug; 197 int opmapdebug = pmapdebug; 198#endif 199 vaddr_t minaddr, maxaddr; 200 extern vsize_t mem_size; /* from pmap.c */ 201 202#ifdef DEBUG 203 pmapdebug = 0; 204#endif 205 206 if (fputype != FPU_NONE) 207 m68k_make_fpu_idle_frame(); 208 209 /* 210 * Good {morning,afternoon,evening,night}. 211 */ 212 printf("%s%s", copyright, version); 213 identifycpu(); 214 215 format_bytes(pbuf, sizeof(pbuf), mem_size); 216 printf("total memory = %s\n", pbuf); 217 218 minaddr = 0; 219 220 /* 221 * Allocate a submap for physio 222 */ 223 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 224 VM_PHYS_SIZE, 0, false, NULL); 225 226#ifdef DEBUG 227 pmapdebug = opmapdebug; 228#endif 229 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 230 printf("avail memory = %s\n", pbuf); 231 232 /* 233 * Alloc extent allocation to use malloc 234 */ 235 iomem_malloc_safe = 1; 236} 237 238/* 239 * Info for CTL_HW 240 */ 241char cpu_model[120]; 242 243static void 244identifycpu(void) 245{ 246 const char *mach, *mmu, *fpu, *cpu; 247 248 switch (machineid & ATARI_ANYMACH) { 249 case ATARI_TT: 250 mach = "Atari TT"; 251 break; 252 case ATARI_FALCON: 253 mach = "Atari Falcon"; 254 break; 255 case ATARI_HADES: 256 mach = "Atari Hades"; 257 break; 258 case ATARI_MILAN: 259 mach = "Atari Milan"; 260 break; 261 default: 262 mach = "Atari UNKNOWN"; 263 break; 264 } 265 266 cpu = "m68k"; 267 fputype = fpu_probe(); 268 fpu = fpu_describe(fputype); 269 270 switch (cputype) { 271 272 case CPU_68060: 273 { 274 uint32_t pcr; 275 char cputxt[30]; 276 277 __asm(".word 0x4e7a,0x0808;" 278 "movl %%d0,%0" : "=d"(pcr) : : "d0"); 279 sprintf(cputxt, "68%s060 rev.%d", 280 pcr & 0x10000 ? "LC/EC" : "", (pcr >> 8) & 0xff); 281 cpu = cputxt; 282 mmu = "/MMU"; 283 } 284 break; 285 case CPU_68040: 286 cpu = "m68040"; 287 mmu = "/MMU"; 288 break; 289 case CPU_68030: 290 cpu = "m68030"; 291 mmu = "/MMU"; 292 break; 293 default: /* XXX */ 294 cpu = "m68020"; 295 mmu = " m68851 MMU"; 296 } 297 sprintf(cpu_model, "%s (%s CPU%s%sFPU)", mach, cpu, mmu, fpu); 298 printf("%s\n", cpu_model); 299} 300 301/* 302 * machine dependent system variables. 303 */ 304SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 305{ 306 307 sysctl_createv(clog, 0, NULL, NULL, 308 CTLFLAG_PERMANENT, 309 CTLTYPE_NODE, "machdep", NULL, 310 NULL, 0, NULL, 0, 311 CTL_MACHDEP, CTL_EOL); 312 313 sysctl_createv(clog, 0, NULL, NULL, 314 CTLFLAG_PERMANENT, 315 CTLTYPE_STRUCT, "console_device", NULL, 316 sysctl_consdev, 0, NULL, sizeof(dev_t), 317 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 318} 319 320static int waittime = -1; 321 322static void 323bootsync(void) 324{ 325 326 if (waittime < 0) { 327 waittime = 0; 328 329 vfs_shutdown(); 330 331 /* 332 * If we've been adjusting the clock, the todr 333 * will be out of synch; adjust it now. 334 */ 335 resettodr(); 336 } 337} 338 339void 340cpu_reboot(int howto, char *bootstr) 341{ 342 struct pcb *pcb = lwp_getpcb(curlwp); 343 344 /* take a snap shot before clobbering any registers */ 345 if (pcb != NULL) 346 savectx(pcb); 347 348 boothowto = howto; 349 if ((howto & RB_NOSYNC) == 0) 350 bootsync(); 351 352 /* 353 * Call shutdown hooks. Do this _before_ anything might be 354 * asked to the user in case nobody is there.... 355 */ 356 doshutdownhooks(); 357 358 pmf_system_shutdown(boothowto); 359 360 splhigh(); /* extreme priority */ 361 if (howto & RB_HALT) { 362 printf("halted\n\n"); 363 __asm(" stop #0x2700"); 364 } else { 365 if (howto & RB_DUMP) 366 dumpsys(); 367 368 doboot(); 369 /*NOTREACHED*/ 370 } 371 panic("Boot() should never come here"); 372 /*NOTREACHED*/ 373} 374 375#define BYTES_PER_DUMP PAGE_SIZE /* Must be a multiple of PAGE_SIZE */ 376static vaddr_t dumpspace; /* Virt. space to map dumppages */ 377 378/* 379 * Reserve _virtual_ memory to map in the page to be dumped 380 */ 381vaddr_t 382reserve_dumppages(vaddr_t p) 383{ 384 385 dumpspace = p; 386 return p + BYTES_PER_DUMP; 387} 388 389uint32_t dumpmag = 0x8fca0101; /* magic number for savecore */ 390int dumpsize = 0; /* also for savecore (pages) */ 391long dumplo = 0; /* (disk blocks) */ 392 393void 394cpu_dumpconf(void) 395{ 396 int nblks, i; 397 398 for (i = dumpsize = 0; i < NMEM_SEGS; i++) { 399 if (boot_segs[i].start == boot_segs[i].end) 400 break; 401 dumpsize += boot_segs[i].end - boot_segs[i].start; 402 } 403 dumpsize = btoc(dumpsize); 404 405 if (dumpdev != NODEV) { 406 nblks = bdev_size(dumpdev); 407 if (nblks > 0) { 408 if (dumpsize > btoc(dbtob(nblks - dumplo))) 409 dumpsize = btoc(dbtob(nblks - dumplo)); 410 else if (dumplo == 0) 411 dumplo = nblks - btodb(ctob(dumpsize)); 412 } 413 } 414 dumplo -= cpu_dumpsize(); 415 416 /* 417 * Don't dump on the first PAGE_SIZE (why PAGE_SIZE?) 418 * in case the dump device includes a disk label. 419 */ 420 if (dumplo < btodb(PAGE_SIZE)) 421 dumplo = btodb(PAGE_SIZE); 422} 423 424/* 425 * Doadump comes here after turning off memory management and 426 * getting on the dump stack, either when called above, or by 427 * the auto-restart code. 428 */ 429void 430dumpsys(void) 431{ 432 const struct bdevsw *bdev; 433 daddr_t blkno; /* Current block to write */ 434 int (*dump)(dev_t, daddr_t, void *, size_t); 435 /* Dumping function */ 436 u_long maddr; /* PA being dumped */ 437 int segbytes; /* Number of bytes in this seg. */ 438 int segnum; /* Segment we are dumping */ 439 int nbytes; /* Bytes left to dump */ 440 int i, n, error; 441 442 error = segnum = 0; 443 if (dumpdev == NODEV) 444 return; 445 bdev = bdevsw_lookup(dumpdev); 446 if (bdev == NULL) 447 return; 448 /* 449 * For dumps during autoconfiguration, 450 * if dump device has already configured... 451 */ 452 if (dumpsize == 0) 453 cpu_dumpconf(); 454 if (dumplo <= 0) { 455 printf("\ndump to dev %u,%u not possible\n", 456 major(dumpdev), minor(dumpdev)); 457 return; 458 } 459 printf("\ndumping to dev %u,%u offset %ld\n", 460 major(dumpdev), minor(dumpdev), dumplo); 461 462#if defined(DDB) || defined(PANICWAIT) 463 printf("Do you want to dump memory? [y]"); 464 cnputc(i = cngetc()); 465 switch (i) { 466 case 'n': 467 case 'N': 468 return; 469 case '\n': 470 break; 471 default : 472 cnputc('\n'); 473 } 474#endif /* defined(DDB) || defined(PANICWAIT) */ 475 476 maddr = 0; 477 segbytes = boot_segs[0].end; 478 blkno = dumplo; 479 dump = bdev->d_dump; 480 nbytes = dumpsize * PAGE_SIZE; 481 482 printf("dump "); 483 484 error = cpu_dump(dump, &blkno); 485 if (!error) { 486 for (i = 0; i < nbytes; i += n, segbytes -= n) { 487 /* 488 * Skip the hole 489 */ 490 if (segbytes == 0) { 491 segnum++; 492 maddr = boot_segs[segnum].start; 493 segbytes = boot_segs[segnum].end - 494 boot_segs[segnum].start; 495 } 496 /* 497 * Print Mb's to go 498 */ 499 n = nbytes - i; 500 if (n && (n % (1024 * 1024)) == 0) 501 printf_nolog("%d ", n / (1024 * 1024)); 502 503 /* 504 * Limit transfer to BYTES_PER_DUMP 505 */ 506 if (n > BYTES_PER_DUMP) 507 n = BYTES_PER_DUMP; 508 509 /* 510 * Map to a VA and write it 511 */ 512 if (maddr != 0) { /* XXX kvtop chokes on this */ 513 (void)pmap_map(dumpspace, maddr, maddr + n, 514 VM_PROT_READ); 515 error = (*dump)(dumpdev, blkno, 516 (void *)dumpspace, n); 517 if (error) 518 break; 519 } 520 521 maddr += n; 522 blkno += btodb(n); 523 } 524 } 525 switch (error) { 526 527 case ENXIO: 528 printf("device bad\n"); 529 break; 530 531 case EFAULT: 532 printf("device not ready\n"); 533 break; 534 535 case EINVAL: 536 printf("area improper\n"); 537 break; 538 539 case EIO: 540 printf("i/o error\n"); 541 break; 542 543 default: 544 printf("succeeded\n"); 545 break; 546 } 547 printf("\n\n"); 548 delay(5000000); /* 5 seconds */ 549} 550 551void 552straytrap(int pc, u_short evec) 553{ 554 static int prev_evec; 555 556 printf("unexpected trap (vector offset 0x%x) from 0x%x\n", 557 evec & 0xFFF, pc); 558 559 if (prev_evec == evec) { 560 delay(1000000); 561 prev_evec = 0; 562 } else 563 prev_evec = evec; 564} 565 566void 567straymfpint(int pc, u_short evec) 568{ 569 570 printf("unexpected mfp-interrupt (vector offset 0x%x) from 0x%x\n", 571 evec & 0xFFF, pc); 572} 573 574int *nofault; 575 576int 577badbaddr(void *addr, int size) 578{ 579 register int i; 580 label_t faultbuf; 581 582#ifdef lint 583 i = *addr; if (i) return(0); 584#endif 585 nofault = (int *) &faultbuf; 586 if (setjmp((label_t *)nofault)) { 587 nofault = (int *) 0; 588 return 1; 589 } 590 switch (size) { 591 case 1: 592 i = *(volatile uint8_t *)addr; 593 break; 594 case 2: 595 i = *(volatile uint16_t *)addr; 596 break; 597 case 4: 598 i = *(volatile uint32_t *)addr; 599 break; 600 default: 601 panic("badbaddr: unknown size"); 602 } 603 nofault = (int *)0; 604 return 0; 605} 606 607/* 608 * this is a handy package to have asynchronously executed 609 * function calls executed at very low interrupt priority. 610 * Example for use is keyboard repeat, where the repeat 611 * handler running at splclock() triggers such a (hardware 612 * aided) software interrupt. 613 * Note: the installed functions are currently called in a 614 * LIFO fashion, might want to change this to FIFO 615 * later. 616 * 617 * XXX: Some of functions which use this callback should be rewritten 618 * XXX: to use MI softintr(9) directly. 619 */ 620struct si_callback { 621 struct si_callback *next; 622 void (*function)(void *rock1, void *rock2); 623 void *rock1, *rock2; 624}; 625static void *si_callback_cookie; 626static struct si_callback *si_callbacks; 627static struct si_callback *si_free; 628#ifdef DIAGNOSTIC 629static int ncbd; /* number of callback blocks dynamically allocated */ 630#endif 631 632void 633init_sicallback(void) 634{ 635 636 si_callback_cookie = softint_establish(SOFTINT_NET, 637 (void (*)(void *))call_sicallbacks, NULL); 638} 639 640void 641add_sicallback(void (*function)(void *, void *), void *rock1, void *rock2) 642{ 643 struct si_callback *si; 644 int s; 645 646 /* 647 * this function may be called from high-priority interrupt handlers. 648 * We may NOT block for memory-allocation in here!. 649 */ 650 s = splhigh(); 651 if ((si = si_free) != NULL) 652 si_free = si->next; 653 splx(s); 654 655 if (si == NULL) { 656 si = malloc(sizeof(*si), M_TEMP, M_NOWAIT); 657#ifdef DIAGNOSTIC 658 if (si) 659 ++ncbd; /* count # dynamically allocated */ 660#endif 661 if (si == NULL) 662 return; 663 } 664 665 si->function = function; 666 si->rock1 = rock1; 667 si->rock2 = rock2; 668 669 s = splhigh(); 670 si->next = si_callbacks; 671 si_callbacks = si; 672 splx(s); 673 674 /* 675 * and cause a software interrupt (spl1). This interrupt might 676 * happen immediately, or after returning to a safe enough level. 677 * 678 * XXX: 679 * According to <machine/scu.h> and lev1intr() hander in locore.s, 680 * at least _ATARIHW_ machines (ATARITT and HADES?) seem to have 681 * some hardware support which can initiate real hardware interrupt 682 * at ipl 1 for software interrupt. But as per <machine/mtpr.h>, 683 * this feature was not used at all on setsoft*() calls and 684 * traditional hp300 derived ssir (simulated software interrupt 685 * request) on VAX REI emulation in locore.s is used. 686 */ 687 softint_schedule(si_callback_cookie); 688} 689 690void 691rem_sicallback(void (*function)(void *rock1, void *rock2)) 692{ 693 struct si_callback *si, *psi, *nsi; 694 int s; 695 696 s = splhigh(); 697 for (psi = 0, si = si_callbacks; si; ) { 698 nsi = si->next; 699 700 if (si->function != function) 701 psi = si; 702 else { 703 si->next = si_free; 704 si_free = si; 705 if (psi != NULL) 706 psi->next = nsi; 707 else 708 si_callbacks = nsi; 709 } 710 si = nsi; 711 } 712 splx(s); 713} 714 715/* purge the list */ 716static void 717call_sicallbacks(void) 718{ 719 struct si_callback *si; 720 int s; 721 void *rock1, *rock2; 722 void (*function)(void *, void *); 723 724 do { 725 s = splhigh(); 726 if ((si = si_callbacks) != NULL) 727 si_callbacks = si->next; 728 splx(s); 729 730 if (si != NULL) { 731 function = si->function; 732 rock1 = si->rock1; 733 rock2 = si->rock2; 734 s = splhigh(); 735 if (si_callbacks) 736 softint_schedule(si_callback_cookie); 737 si->next = si_free; 738 si_free = si; 739 splx(s); 740 741 /* 742 * Raise spl for BASEPRI() checks to see 743 * nested interrupts in some drivers using callbacks 744 * since modern MI softint(9) doesn't seem to do it 745 * in !__HAVE_FAST_SOFTINTS case. 746 * 747 * XXX: This is just a workaround hack. 748 * Each driver should raise spl in its handler 749 * to avoid nested interrupts if necessary. 750 */ 751 s = splsoftnet(); /* XXX */ 752 function(rock1, rock2); 753 splx(s); 754 } 755 } while (si != NULL); 756#ifdef DIAGNOSTIC 757 if (ncbd) { 758#ifdef DEBUG 759 printf("call_sicallback: %d more dynamic structures\n", ncbd); 760#endif 761 ncbd = 0; 762 } 763#endif 764} 765 766#if defined(DEBUG) && !defined(PANICBUTTON) 767#define PANICBUTTON 768#endif 769 770#ifdef PANICBUTTON 771int panicbutton = 1; /* non-zero if panic buttons are enabled */ 772int crashandburn = 0; 773int candbdelay = 50; /* give em half a second */ 774 775void candbtimer(void); 776 777void 778candbtimer(void) 779{ 780 781 crashandburn = 0; 782} 783#endif 784 785/* 786 * should only get here, if no standard executable. This can currently 787 * only mean, we're reading an old ZMAGIC file without MID, but since Atari 788 * ZMAGIC always worked the `right' way (;-)) just ignore the missing 789 * MID and proceed to new zmagic code ;-) 790 */ 791int 792cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 793{ 794 int error = ENOEXEC; 795#ifdef COMPAT_NOMID 796 struct exec *execp = epp->ep_hdr; 797#endif 798 799#ifdef COMPAT_NOMID 800 if (!((execp->a_midmag >> 16) & 0x0fff) 801 && execp->a_midmag == ZMAGIC) 802 return exec_aout_prep_zmagic(l->l_proc, epp); 803#endif 804 return error; 805} 806 807#ifdef MODULAR 808/* 809 * Push any modules loaded by the bootloader etc. 810 */ 811void 812module_init_md(void) 813{ 814} 815#endif 816 817#ifdef _MILANHW_ 818 819/* 820 * Currently the only source of NMI interrupts on the Milan is the PLX9080. 821 * On access errors to the PCI bus, an NMI is generated. This NMI is shorted 822 * in locore in case of a PCI config cycle to a non-existing address to allow 823 * for probes. On other occaisions, it ShouldNotHappen(TM). 824 * Note: The handler in locore clears the errors, to make further PCI access 825 * possible. 826 */ 827void 828nmihandler(void) 829{ 830 extern unsigned long plx_status; 831 832 printf("nmihandler: plx_status = 0x%08lx\n", plx_status); 833} 834#endif 835 836int 837mm_md_physacc(paddr_t pa, vm_prot_t prot) 838{ 839 struct memseg *ms; 840 841 for (ms = boot_segs; ms->start != ms->end; ms++) { 842 if ((pa >= ms->start) && (pa < ms->end)) 843 return 0; 844 } 845 return EFAULT; 846} 847 848int 849mm_md_readwrite(dev_t dev, struct uio *uio) 850{ 851 switch (minor(dev)) { 852 case DEV_NVRAM: 853#if NNVR > 0 854 return nvram_uio(uio); 855#else 856 return ENXIO; 857#endif 858 default: 859 return ENXIO; 860 } 861} 862