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