Annotation of sys/arch/mvmeppc/mvmeppc/machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: machdep.c,v 1.53 2007/05/26 20:26:51 pedro Exp $ */
2: /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */
3:
4: /*
5: * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6: * Copyright (C) 1995, 1996 TooLs GmbH.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by TooLs GmbH.
20: * 4. The name of TooLs GmbH may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: #include <sys/param.h>
36: #include <sys/buf.h>
37: #include <sys/timeout.h>
38: #include <sys/exec.h>
39: #include <sys/malloc.h>
40: #include <sys/mbuf.h>
41: #include <sys/mount.h>
42: #include <sys/msgbuf.h>
43: #include <sys/proc.h>
44: #include <sys/signalvar.h>
45: #include <sys/reboot.h>
46: #include <sys/syscallargs.h>
47: #ifdef SYSVMSG
48: #include <sys/msg.h>
49: #endif
50: #include <sys/syslog.h>
51: #include <sys/extent.h>
52: #include <sys/systm.h>
53: #include <sys/user.h>
54:
55: #include <net/netisr.h>
56:
57: #include <machine/bat.h>
58: #include <machine/bugio.h>
59: #include <machine/pmap.h>
60: #include <machine/powerpc.h>
61: #include <machine/trap.h>
62: #include <machine/autoconf.h>
63: #include <machine/bus.h>
64: #include <machine/conf.h>
65: #include <machine/pio.h>
66: #include <machine/prom.h>
67:
68: #include <dev/cons.h>
69:
70: #include <uvm/uvm_extern.h>
71:
72: #ifdef DDB
73: #include <machine/db_machdep.h>
74: #include <ddb/db_access.h>
75: #include <ddb/db_sym.h>
76: #include <ddb/db_extern.h>
77: #endif
78:
79: void initppc(u_int, u_int, char *);
80: void dumpsys(void);
81: int lcsplx(int);
82: void myetheraddr(u_char *);
83:
84: /*
85: * Global variables used here and there
86: */
87: struct pcb *curpcb;
88: struct pmap *curpm;
89: struct proc *fpuproc;
90:
91: extern struct user *proc0paddr;
92:
93: /*
94: * This is to fake out the console routines, while booting.
95: */
96: cons_decl(boot);
97: #define bootcnpollc nullcnpollc
98:
99: static struct consdev bootcons = {
100: NULL,
101: NULL,
102: bootcngetc,
103: bootcnputc,
104: bootcnpollc,
105: NULL,
106: makedev(14, 0),
107: CN_NORMAL,
108: };
109:
110: /*
111: * Declare these as initialized data so we can patch them.
112: */
113: #ifndef BUFCACHEPERCENT
114: #define BUFCACHEPERCENT 5
115: #endif
116:
117: #ifdef BUFPAGES
118: int bufpages = BUFPAGES;
119: #else
120: int bufpages = 0;
121: #endif
122: int bufcachepercent = BUFCACHEPERCENT;
123:
124: struct bat battable[16];
125:
126: struct vm_map *exec_map = NULL;
127: struct vm_map *phys_map = NULL;
128:
129: int ppc_malloc_ok;
130:
131: #ifndef SYS_TYPE
132: /* XXX Hardwire it for now */
133: #define SYS_TYPE MVME
134: #endif
135:
136: int system_type = SYS_TYPE; /* XXX Hardwire it for now */
137:
138: struct firmware *fw = NULL;
139: extern struct firmware ppc1_firmware;
140:
141: caddr_t allocsys(caddr_t);
142:
143: /*
144: * Extent maps to manage I/O. Allocate storage for 8 regions in each,
145: * initially. Later devio_malloc_safe will indicate that it's safe to
146: * use malloc() to dynamically allocate region descriptors.
147: */
148: static long devio_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof (long)];
149: struct extent *devio_ex;
150: static int devio_malloc_safe = 0;
151:
152: void
153: initppc(startkernel, endkernel, args)
154: u_int startkernel, endkernel;
155: char *args;
156: {
157: extern void *trapcode; extern int trapsize;
158: extern void *dsitrap; extern int dsisize;
159: extern void *isitrap; extern int isisize;
160: extern void *alitrap; extern int alisize;
161: extern void *decrint; extern int decrsize;
162: extern void *tlbimiss; extern int tlbimsize;
163: extern void *tlbdlmiss; extern int tlbdlmsize;
164: extern void *tlbdsmiss; extern int tlbdsmsize;
165: #ifdef DDB
166: extern void *ddblow; extern int ddbsize;
167: #endif
168: extern void consinit(void);
169: extern void *msgbuf_addr;
170: int exc, scratch;
171:
172: proc0.p_addr = proc0paddr;
173: bzero(proc0.p_addr, sizeof *proc0.p_addr);
174:
175: fw = &ppc1_firmware; /* Just PPC1-Bug for now... */
176: buginit();
177:
178: curpcb = &proc0paddr->u_pcb;
179:
180: curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel();
181:
182: /* startup fake console driver. It will be replaced by consinit() */
183: cn_tab = &bootcons;
184:
185: /*
186: * Initialize BAT registers to unmapped to not generate
187: * overlapping mappings below.
188: */
189: ppc_mtibat0u(0);
190: ppc_mtibat1u(0);
191: ppc_mtibat2u(0);
192: ppc_mtibat3u(0);
193: ppc_mtdbat0u(0);
194: ppc_mtdbat1u(0);
195: ppc_mtdbat2u(0);
196: ppc_mtdbat3u(0);
197:
198: /*
199: * Set up initial BAT table
200: */
201: battable[0].batl = BATL(0x00000000, BAT_M);
202: battable[0].batu = BATU(0x00000000);
203:
204: /*
205: * Now setup fixed bat registers
206: *
207: * Note that we still run in real mode, and the BAT
208: * registers were cleared above.
209: */
210: /* IBAT0 used for initial 256 MB segment */
211: ppc_mtibat0l(battable[0].batl);
212: ppc_mtibat0u(battable[0].batu);
213:
214: /* DBAT0 used similar */
215: ppc_mtdbat0l(battable[0].batl);
216: ppc_mtdbat0u(battable[0].batu);
217:
218: /*
219: * Set up trap vectors
220: */
221: for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) {
222: switch (exc) {
223: default:
224: bcopy(&trapcode, (void *)exc, (size_t)&trapsize);
225: break;
226: case EXC_EXI:
227: /*
228: * This one is (potentially) installed during autoconf
229: */
230: break;
231:
232: case EXC_DSI:
233: bcopy(&dsitrap, (void *)exc, (size_t)&dsisize);
234: break;
235: case EXC_ISI:
236: bcopy(&isitrap, (void *)exc, (size_t)&isisize);
237: break;
238: case EXC_ALI:
239: bcopy(&alitrap, (void *)exc, (size_t)&alisize);
240: break;
241: case EXC_DECR:
242: bcopy(&decrint, (void *)exc, (size_t)&decrsize);
243: break;
244: case EXC_IMISS:
245: bcopy(&tlbimiss, (void *)exc, (size_t)&tlbimsize);
246: break;
247: case EXC_DLMISS:
248: bcopy(&tlbdlmiss, (void *)exc, (size_t)&tlbdlmsize);
249: break;
250: case EXC_DSMISS:
251: bcopy(&tlbdsmiss, (void *)exc, (size_t)&tlbdsmsize);
252: break;
253: #ifdef DDB
254: case EXC_PGM:
255: case EXC_TRC:
256: case EXC_BPT:
257: bcopy(&ddblow, (void *)exc, (size_t)&ddbsize);
258: break;
259: #endif
260: }
261: }
262:
263: /* Grr, ALTIVEC_UNAVAIL is a vector not ~0xff aligned: 0x0f20 */
264: bcopy(&trapcode, (void *)0xf20, (size_t)&trapsize);
265:
266: /*
267: * since trapsize is > 0x20, we just overwrote the EXC_PERF handler
268: * since we do not use it, we will "share" it with the EXC_VEC,
269: * we dont support EXC_VEC either.
270: * should be a 'ba 0xf20 written' at address 0xf00, but we
271: * do not generate EXC_PERF exceptions...
272: */
273:
274: syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
275:
276: /*
277: * Initialize pmap module.
278: */
279: uvmexp.pagesize = 4096;
280: uvm_setpagesize();
281: pmap_bootstrap(startkernel, endkernel);
282:
283: #if 1
284: /* MVME2[67]00 max out at 256MB, and we need BAT2 for now. */
285: #else
286: /* use BATs to map 1GB memory, no pageable BATs now */
287: if (physmem > btoc(0x10000000)) {
288: ppc_mtdbat1l(BATL(0x10000000, BAT_M));
289: ppc_mtdbat1u(BATU(0x10000000));
290: }
291: if (physmem > btoc(0x20000000)) {
292: ppc_mtdbat2l(BATL(0x20000000, BAT_M));
293: ppc_mtdbat2u(BATU(0x20000000));
294: }
295: if (physmem > btoc(0x30000000)) {
296: ppc_mtdbat3l(BATL(0x30000000, BAT_M));
297: ppc_mtdbat3u(BATU(0x30000000));
298: }
299: #endif
300:
301: /*
302: * Now enable translation (and machine checks/recoverable interrupts).
303: * This will also start using the exception vector prefix of 0x000.
304: */
305: (fw->vmon)();
306:
307: __asm__ volatile ("eieio; mfmsr %0; ori %0,%0,%1; mtmsr %0; sync;isync"
308: : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
309:
310: /*
311: * use the memory provided by pmap_bootstrap for message buffer
312: */
313: initmsgbuf(msgbuf_addr, MSGBUFSIZE);
314:
315: #ifdef DDB
316: #ifdef notyet
317: db_machine_init();
318: #endif
319: ddb_init();
320: #endif
321:
322: /*
323: * Set up extents for pci mappings
324: * Is this too late?
325: *
326: * what are good start and end values here??
327: * 0x0 - 0x80000000 mcu bus
328: * MAP A MAP B
329: * 0x80000000 - 0xbfffffff io 0x80000000 - 0xefffffff mem
330: * 0xc0000000 - 0xffffffff mem 0xf0000000 - 0xffffffff io
331: *
332: * of course bsd uses 0xe and 0xf
333: * So the BSD PPC memory map will look like this
334: * 0x0 - 0x80000000 memory (whatever is filled)
335: * 0x80000000 - 0xdfffffff (pci space, memory or io)
336: * 0xe0000000 - kernel vm segment
337: * 0xf0000000 - kernel map segment (user space mapped here)
338: */
339:
340: devio_ex = extent_create("devio", 0x80000000, 0xffffffff, M_DEVBUF,
341: (caddr_t)devio_ex_storage, sizeof(devio_ex_storage),
342: EX_NOCOALESCE|EX_NOWAIT);
343:
344: /*
345: * Now we can set up the console as mapping is enabled.
346: */
347: consinit();
348:
349: if (boothowto & RB_CONFIG) {
350: #ifdef BOOT_CONFIG
351: user_config();
352: #else
353: printf("kernel does not support -c; continuing..\n");
354: #endif
355: }
356:
357: #ifdef DDB
358: if (boothowto & RB_KDB)
359: Debugger();
360: #endif
361: }
362:
363: void
364: install_extint(handler)
365: void (*handler)(void);
366: {
367: extern caddr_t extint, extsize;
368: extern u_long extint_call;
369: u_long offset = (u_long)handler - (u_long)&extint_call;
370: int msr;
371:
372: #ifdef DIAGNOSTIC
373: if (offset > 0x1ffffff)
374: panic("install_extint: too far away");
375: #endif
376: msr = ppc_intr_disable();
377: extint_call = (extint_call & 0xfc000003) | offset;
378: bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize);
379: syncicache((void *)&extint_call, sizeof extint_call);
380: syncicache((void *)EXC_EXI, (int)&extsize);
381: ppc_intr_enable(msr);
382: }
383:
384: /*
385: * Machine dependent startup code.
386: */
387: void
388: cpu_startup()
389: {
390: int sz;
391: caddr_t v;
392: vaddr_t minaddr, maxaddr;
393:
394: proc0.p_addr = proc0paddr;
395:
396: printf("%s", version);
397:
398: printf("real mem = %u (%uMB)\n", ctob(physmem),
399: ctob(physmem)/1024/1024);
400:
401: /*
402: * Find out how much space we need, allocate it,
403: * and then give everything true virtual addresses.
404: */
405: sz = (int)allocsys((caddr_t)0);
406: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
407: panic("startup: no room for tables");
408: if (allocsys(v) - v != sz)
409: panic("startup: table size inconsistency");
410:
411: /*
412: * Determine how many buffers to allocate.
413: * We allocate bufcachepercent% of memory for buffer space.
414: */
415: if (bufpages == 0)
416: bufpages = physmem * bufcachepercent / 100;
417:
418: /* Restrict to at most 25% filled kvm */
419: if (bufpages >
420: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
421: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
422: PAGE_SIZE / 4;
423:
424: /*
425: * Allocate a submap for exec arguments. This map effectively
426: * limits the number of processes exec'ing at any time.
427: */
428: minaddr = vm_map_min(kernel_map);
429: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16 * NCARGS,
430: VM_MAP_PAGEABLE, FALSE, NULL);
431:
432: /*
433: * Allocate a submap for physio
434: */
435: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
436: VM_PHYS_SIZE, 0, FALSE, NULL);
437: ppc_malloc_ok = 1;
438:
439: printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
440: ptoa(uvmexp.free) / 1024 / 1024);
441:
442: /*
443: * Set up the buffers.
444: */
445: bufinit();
446:
447: /*
448: * Set up early mappings
449: */
450: devio_malloc_safe = 1;
451: nvram_map();
452: prep_bus_space_init();
453: }
454:
455: /*
456: * Allocate space for system data structures.
457: */
458: caddr_t
459: allocsys(v)
460: caddr_t v;
461: {
462: #define valloc(name, type, num) \
463: v = (caddr_t)(((name) = (type *)v) + (num))
464:
465: #ifdef SYSVMSG
466: valloc(msgpool, char, msginfo.msgmax);
467: valloc(msgmaps, struct msgmap, msginfo.msgseg);
468: valloc(msghdrs, struct msg, msginfo.msgtql);
469: valloc(msqids, struct msqid_ds, msginfo.msgmni);
470: #endif
471:
472: return v;
473: }
474:
475: /*
476: * consinit
477: * Initialize system console.
478: */
479: void
480: consinit()
481: {
482: static int cons_initted = 0;
483:
484: if (cons_initted)
485: return;
486: cn_tab = NULL;
487: cninit();
488: cons_initted = 1;
489: }
490:
491: /*
492: * Clear registers on exec
493: */
494: void
495: setregs(p, pack, stack, retval)
496: struct proc *p;
497: struct exec_package *pack;
498: u_long stack;
499: register_t *retval;
500: {
501: u_int32_t newstack;
502: u_int32_t pargs;
503: u_int32_t args[4];
504:
505: struct trapframe *tf = trapframe(p);
506: pargs = -roundup(-stack + 8, 16);
507: newstack = (u_int32_t)(pargs - 32);
508:
509: copyin ((void *)(VM_MAX_ADDRESS-0x10), &args, 0x10);
510:
511: bzero(tf, sizeof *tf);
512: tf->fixreg[1] = newstack;
513: tf->fixreg[3] = retval[0] = args[1]; /* XXX */
514: tf->fixreg[4] = retval[1] = args[0]; /* XXX */
515: tf->fixreg[5] = args[2]; /* XXX */
516: tf->fixreg[6] = args[3]; /* XXX */
517: tf->srr0 = pack->ep_entry;
518: tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
519: p->p_addr->u_pcb.pcb_flags = 0;
520: }
521:
522: /*
523: * Send a signal to process.
524: */
525: void
526: sendsig(catcher, sig, mask, code, type, val)
527: sig_t catcher;
528: int sig, mask;
529: u_long code;
530: int type;
531: union sigval val;
532: {
533: struct proc *p = curproc;
534: struct trapframe *tf;
535: struct sigframe *fp, frame;
536: struct sigacts *psp = p->p_sigacts;
537: int oldonstack;
538:
539: frame.sf_signum = sig;
540:
541: tf = trapframe(p);
542: oldonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
543:
544: /*
545: * Allocate stack space for signal handler.
546: */
547: if ((psp->ps_flags & SAS_ALTSTACK)
548: && !oldonstack
549: && (psp->ps_sigonstack & sigmask(sig))) {
550: fp = (struct sigframe *)(psp->ps_sigstk.ss_sp
551: + psp->ps_sigstk.ss_size);
552: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
553: } else
554: fp = (struct sigframe *)tf->fixreg[1];
555:
556: fp = (struct sigframe *)((int)(fp - 1) & ~0xf);
557:
558: /*
559: * Generate signal context for SYS_sigreturn.
560: */
561: frame.sf_sc.sc_onstack = oldonstack;
562: frame.sf_sc.sc_mask = mask;
563: frame.sf_sip = NULL;
564: bcopy(tf, &frame.sf_sc.sc_frame, sizeof *tf);
565: if (psp->ps_siginfo & sigmask(sig)) {
566: frame.sf_sip = &fp->sf_si;
567: initsiginfo(&frame.sf_si, sig, code, type, val);
568: }
569: if (copyout(&frame, fp, sizeof frame) != 0)
570: sigexit(p, SIGILL);
571:
572:
573: tf->fixreg[1] = (int)fp;
574: tf->lr = (int)catcher;
575: tf->fixreg[3] = (int)sig;
576: tf->fixreg[4] = (psp->ps_siginfo & sigmask(sig)) ? (int)&fp->sf_si : 0;
577: tf->fixreg[5] = (int)&fp->sf_sc;
578: tf->srr0 = p->p_sigcode;
579:
580: #if WHEN_WE_ONLY_FLUSH_DATA_WHEN_DOING_PMAP_ENTER
581: pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),tf->srr0, &pa);
582: syncicache(pa, (p->p_emul->e_esigcode - p->p_emul->e_sigcode));
583: #endif
584: }
585:
586: /*
587: * System call to cleanup state after a signal handler returns.
588: */
589: int
590: sys_sigreturn(p, v, retval)
591: struct proc *p;
592: void *v;
593: register_t *retval;
594: {
595: struct sys_sigreturn_args /* {
596: syscallarg(struct sigcontext *) sigcntxp;
597: } */ *uap = v;
598: struct sigcontext sc;
599: struct trapframe *tf;
600: int error;
601:
602: if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)) != 0)
603: return error;
604: tf = trapframe(p);
605: if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC))
606: return EINVAL;
607: bcopy(&sc.sc_frame, tf, sizeof *tf);
608: if (sc.sc_onstack & 1)
609: p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
610: else
611: p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
612: p->p_sigmask = sc.sc_mask & ~sigcantmask;
613: return EJUSTRETURN;
614: }
615:
616: /*
617: * Machine dependent system variables.
618: * None for now.
619: */
620: int
621: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
622: int *name;
623: u_int namelen;
624: void *oldp;
625: size_t *oldlenp;
626: void *newp;
627: size_t newlen;
628: struct proc *p;
629: {
630: /* all sysctl names at this level are terminal */
631: if (namelen != 1)
632: return ENOTDIR;
633: switch (name[0]) {
634: default:
635: return EOPNOTSUPP;
636: }
637: }
638:
639: void
640: dumpsys()
641: {
642: printf("dumpsys: TBD\n");
643: }
644:
645: volatile int cpl, ipending, astpending;
646: int imask[IPL_NUM];
647: int netisr;
648:
649: /*
650: * Soft networking interrupts.
651: */
652: void
653: softnet(isr)
654: int isr;
655: {
656: #define DONETISR(flag, func) \
657: if (isr & (1 << (flag))) \
658: (func)();
659:
660: #include <net/netisr_dispatch.h>
661: #undef DONETISR
662: }
663:
664: int
665: lcsplx(ipl)
666: int ipl;
667: {
668: int oldcpl;
669:
670: oldcpl = cpl;
671: splx(ipl);
672: return oldcpl;
673: }
674:
675: /*
676: * Halt or reboot the machine after syncing/dumping according to howto.
677: */
678: void
679: boot(howto)
680: int howto;
681: {
682: static int syncing;
683: static char str[256];
684:
685: boothowto = howto;
686: if (!cold && !(howto & RB_NOSYNC) && !syncing) {
687: syncing = 1;
688: vfs_shutdown(); /* sync */
689:
690: /*
691: * If we've been adjusting the clock, the todr
692: * will be out of synch; adjust it now unless
693: * the system was sitting in ddb.
694: */
695: if ((howto & RB_TIMEBAD) == 0) {
696: resettodr();
697: } else {
698: printf("WARNING: not updating battery clock\n");
699: }
700: }
701: splhigh();
702: if (howto & RB_HALT) {
703: doshutdownhooks();
704: printf("halted\n\n");
705: (fw->exit)();
706: }
707: if (!cold && (howto & RB_DUMP))
708: dumpsys();
709: doshutdownhooks();
710: printf("rebooting\n\n");
711:
712: (fw->boot)(str);
713: for (;;) ; /* spinning */
714: }
715:
716: /*
717: * Get Ethernet address for the onboard ethernet chip.
718: */
719: void
720: myetheraddr(cp)
721: u_char *cp;
722: {
723: struct mvmeprom_brdid brdid;
724:
725: mvmeprom_brdid(&brdid);
726: bcopy(&brdid.etheraddr, cp, 6);
727: }
728:
729: typedef void (void_f) (void);
730: void_f *pending_int_f = NULL;
731:
732: /* call the bus/interrupt controller specific pending interrupt handler
733: * would be nice if the offlevel interrupt code was handled here
734: * instead of being in each of the specific handler code
735: */
736: void
737: do_pending_int()
738: {
739: if (pending_int_f != NULL) {
740: (*pending_int_f)();
741: }
742: }
743:
744: /*
745: * one attempt at interrupt stuff..
746: *
747: */
748: #include <dev/pci/pcivar.h>
749: typedef void *(intr_establish_t)(void *, pci_intr_handle_t,
750: int, int, int (*func)(void *), void *, char *);
751: typedef void (intr_disestablish_t)(void *, void *);
752:
753: int ppc_configed_intr_cnt = 0;
754: struct intrhand ppc_configed_intr[MAX_PRECONF_INTR];
755:
756: void *ppc_intr_establish(void *, pci_intr_handle_t, int, int, int (*)(void *),
757: void *, char *);
758: void ppc_intr_setup(intr_establish_t *, intr_disestablish_t *);
759: void ppc_intr_enable(int);
760: int ppc_intr_disable(void);
761:
762: void *
763: ppc_intr_establish(lcv, ih, type, level, func, arg, name)
764: void *lcv;
765: pci_intr_handle_t ih;
766: int type;
767: int level;
768: int (*func)(void *);
769: void *arg;
770: char *name;
771: {
772: if (ppc_configed_intr_cnt < MAX_PRECONF_INTR) {
773: ppc_configed_intr[ppc_configed_intr_cnt].ih_fun = func;
774: ppc_configed_intr[ppc_configed_intr_cnt].ih_arg = arg;
775: ppc_configed_intr[ppc_configed_intr_cnt].ih_level = level;
776: ppc_configed_intr[ppc_configed_intr_cnt].ih_irq = ih;
777: ppc_configed_intr[ppc_configed_intr_cnt].ih_what = name;
778: ppc_configed_intr_cnt++;
779: } else {
780: panic("ppc_intr_establish called before interrupt controller"
781: " configured: driver %s has too many interrupts", name);
782: }
783: /* disestablish is going to be tricky to supported for these :-) */
784: return (void *)ppc_configed_intr_cnt;
785: }
786:
787: intr_establish_t *intr_establish_func = ppc_intr_establish;
788: intr_disestablish_t *intr_disestablish_func;
789:
790: void
791: ppc_intr_setup(intr_establish_t *establish, intr_disestablish_t *disestablish)
792: {
793: intr_establish_func = establish;
794: intr_disestablish_func = disestablish;
795: }
796:
797: vaddr_t ppc_kvm_stolen = VM_KERN_ADDRESS_SIZE;
798:
799: void *
800: mapiodev(pa, len)
801: paddr_t pa;
802: psize_t len;
803: {
804: paddr_t spa;
805: vaddr_t vaddr, va;
806: int off;
807: int size;
808:
809: spa = trunc_page(pa);
810: off = pa - spa;
811: size = round_page(off+len);
812:
813: if (ppc_malloc_ok == 0) {
814: /* need to steal vm space before kernel vm is initialized */
815: va = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen;
816: ppc_kvm_stolen += size;
817: if (ppc_kvm_stolen > PPC_SEGMENT_LENGTH) {
818: panic("ppc_kvm_stolen: out of space");
819: }
820: } else {
821: va = uvm_km_valloc_wait(phys_map, size);
822: }
823:
824: if (va == 0)
825: return NULL;
826:
827: for (vaddr = va; size > 0; size -= PAGE_SIZE) {
828: pmap_kenter_cache(vaddr, spa,
829: VM_PROT_READ | VM_PROT_WRITE, PMAP_CACHE_DEFAULT);
830: spa += PAGE_SIZE;
831: vaddr += PAGE_SIZE;
832: }
833: return (void *) (va+off);
834: }
835: void
836: unmapiodev(kva, p_size)
837: void *kva;
838: psize_t p_size;
839: {
840: vaddr_t vaddr;
841: int size;
842:
843: size = p_size;
844:
845: vaddr = trunc_page((vaddr_t)kva);
846:
847: uvm_km_free_wakeup(phys_map, vaddr, size);
848:
849: for (; size > 0; size -= PAGE_SIZE) {
850: pmap_remove(pmap_kernel(), vaddr, vaddr+PAGE_SIZE-1);
851: vaddr += PAGE_SIZE;
852: }
853: pmap_update(pmap_kernel());
854: }
855:
856: /* bcopy(), error on fault */
857: int
858: kcopy(from, to, size)
859: const void *from;
860: void *to;
861: size_t size;
862: {
863: faultbuf env;
864: void *oldh = curproc->p_addr->u_pcb.pcb_onfault;
865:
866: if (setfault(&env)) {
867: curproc->p_addr->u_pcb.pcb_onfault = oldh;
868: return EFAULT;
869: }
870: bcopy(from, to, size);
871: curproc->p_addr->u_pcb.pcb_onfault = oldh;
872:
873: return 0;
874: }
CVSweb