Annotation of sys/arch/macppc/macppc/machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: machdep.c,v 1.93 2007/06/06 17:15:12 deraadt 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: #include <sys/syslog.h>
48: #include <sys/extent.h>
49: #include <sys/systm.h>
50: #include <sys/user.h>
51: #include <sys/conf.h>
52: #include <sys/core.h>
53: #include <sys/kcore.h>
54:
55: #include <uvm/uvm_extern.h>
56:
57: #ifdef SYSVMSG
58: #include <sys/msg.h>
59: #endif
60: #include <net/netisr.h>
61:
62: #include <dev/cons.h>
63:
64: #include <machine/bat.h>
65: #include <machine/pmap.h>
66: #include <machine/powerpc.h>
67: #include <machine/trap.h>
68: #include <machine/autoconf.h>
69: #include <machine/bus.h>
70: #include <machine/pio.h>
71: #include <machine/intr.h>
72:
73: #include <dev/pci/pcivar.h>
74:
75: #include <arch/macppc/macppc/ofw_machdep.h>
76: #include <dev/ofw/openfirm.h>
77:
78: #include "adb.h"
79: #if NADB > 0
80: #include <arch/macppc/dev/adbvar.h>
81: #endif
82:
83: #ifdef DDB
84: #include <machine/db_machdep.h>
85: #include <ddb/db_access.h>
86: #include <ddb/db_sym.h>
87: #include <ddb/db_extern.h>
88: #endif
89:
90: /*
91: * Global variables used here and there
92: */
93: extern struct user *proc0paddr;
94: struct pool ppc_vecpl;
95:
96: /*
97: * Declare these as initialized data so we can patch them.
98: */
99: #ifndef BUFCACHEPERCENT
100: #define BUFCACHEPERCENT 5
101: #endif
102:
103: #ifdef BUFPAGES
104: int bufpages = BUFPAGES;
105: #else
106: int bufpages = 0;
107: #endif
108: int bufcachepercent = BUFCACHEPERCENT;
109:
110: struct bat battable[16];
111:
112: struct vm_map *exec_map = NULL;
113: struct vm_map *phys_map = NULL;
114:
115: int ppc_malloc_ok = 0;
116:
117: #ifndef SYS_TYPE
118: /* XXX Hardwire it for now */
119: #define SYS_TYPE POWER4e
120: #endif
121:
122: int system_type = SYS_TYPE; /* XXX Hardwire it for now */
123:
124: char ofw_eth_addr[6]; /* Save address of first network ifc found */
125: char *bootpath;
126: char bootpathbuf[512];
127:
128: struct firmware *fw = NULL;
129:
130: #ifdef DDB
131: void * startsym, *endsym;
132: #endif
133:
134: #ifdef APERTURE
135: #ifdef INSECURE
136: int allowaperture = 1;
137: #else
138: int allowaperture = 0;
139: #endif
140: #endif
141:
142: void ofw_dbg(char *str);
143:
144: caddr_t allocsys(caddr_t);
145: void dumpsys(void);
146: void systype(char *name);
147: int lcsplx(int ipl); /* called from LCore */
148: int power4e_get_eth_addr(void);
149: void ppc_intr_setup(intr_establish_t *establish,
150: intr_disestablish_t *disestablish);
151: void *ppc_intr_establish(void *lcv, pci_intr_handle_t ih, int type,
152: int level, int (*func)(void *), void *arg, char *name);
153: int bus_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int cacheable,
154: bus_space_handle_t *bshp);
155: bus_addr_t bus_space_unmap_p(bus_space_tag_t t, bus_space_handle_t bsh,
156: bus_size_t size);
157: void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
158: bus_size_t size);
159:
160:
161: /*
162: * Extent maps to manage I/O. Allocate storage for 8 regions in each,
163: * initially. Later devio_malloc_safe will indicate that it's safe to
164: * use malloc() to dynamically allocate region descriptors.
165: */
166: static long devio_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof (long)];
167: struct extent *devio_ex;
168: static int devio_malloc_safe = 0;
169:
170: extern int OF_stdout;
171:
172: /* XXX, called from asm */
173: void initppc(u_int startkernel, u_int endkernel, char *args);
174:
175: void
176: initppc(startkernel, endkernel, args)
177: u_int startkernel, endkernel;
178: char *args;
179: {
180: extern void *trapcode; extern int trapsize;
181: extern void *dsitrap; extern int dsisize;
182: extern void *isitrap; extern int isisize;
183: extern void *alitrap; extern int alisize;
184: extern void *decrint; extern int decrsize;
185: extern void *tlbimiss; extern int tlbimsize;
186: extern void *tlbdlmiss; extern int tlbdlmsize;
187: extern void *tlbdsmiss; extern int tlbdsmsize;
188: #ifdef DDB
189: extern void *ddblow; extern int ddbsize;
190: #endif
191: extern void consinit(void);
192: extern void callback(void *);
193: extern void *msgbuf_addr;
194: int exc, scratch;
195:
196: proc0.p_cpu = &cpu_info[0];
197: proc0.p_addr = proc0paddr;
198: bzero(proc0.p_addr, sizeof *proc0.p_addr);
199:
200: curpcb = &proc0paddr->u_pcb;
201:
202: curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel();
203:
204: ppc_check_procid();
205:
206: /*
207: * Initialize BAT registers to unmapped to not generate
208: * overlapping mappings below.
209: */
210: ppc_mtibat0u(0);
211: ppc_mtibat1u(0);
212: ppc_mtibat2u(0);
213: ppc_mtibat3u(0);
214: ppc_mtdbat0u(0);
215: ppc_mtdbat1u(0);
216: ppc_mtdbat2u(0);
217: ppc_mtdbat3u(0);
218:
219: /*
220: * Set up initial BAT table to only map the lowest 256 MB area
221: */
222: battable[0].batl = BATL(0x00000000, BAT_M);
223: battable[0].batu = BATU(0x00000000);
224:
225: /*
226: * Now setup fixed bat registers
227: *
228: * Note that we still run in real mode, and the BAT
229: * registers were cleared above.
230: */
231: /* IBAT0 used for initial 256 MB segment */
232: ppc_mtibat0l(battable[0].batl);
233: ppc_mtibat0u(battable[0].batu);
234:
235: /* DBAT0 used similar */
236: ppc_mtdbat0l(battable[0].batl);
237: ppc_mtdbat0u(battable[0].batu);
238:
239: /*
240: * Set up trap vectors
241: */
242: for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) {
243: switch (exc) {
244: default:
245: bcopy(&trapcode, (void *)exc, (size_t)&trapsize);
246: break;
247: case EXC_EXI:
248: /*
249: * This one is (potentially) installed during autoconf
250: */
251: break;
252:
253: case EXC_DSI:
254: bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
255: break;
256: case EXC_ISI:
257: bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
258: break;
259: case EXC_ALI:
260: bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
261: break;
262: case EXC_DECR:
263: bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
264: break;
265: case EXC_IMISS:
266: bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize);
267: break;
268: case EXC_DLMISS:
269: bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize);
270: break;
271: case EXC_DSMISS:
272: bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize);
273: break;
274: case EXC_PGM:
275: case EXC_TRC:
276: case EXC_BPT:
277: #if defined(DDB)
278: bcopy(&ddblow, (void *)exc, (size_t)&ddbsize);
279: #endif
280: break;
281: }
282: }
283:
284: /* Grr, ALTIVEC_UNAVAIL is a vector not ~0xff aligned: 0x0f20 */
285: bcopy(&trapcode, (void *)0xf20, (size_t)&trapsize);
286:
287: /*
288: * since trapsize is > 0x20, we just overwrote the EXC_PERF handler
289: * since we do not use it, we will "share" it with the EXC_VEC,
290: * we dont support EXC_VEC either.
291: * should be a 'ba 0xf20 written' at address 0xf00, but we
292: * do not generate EXC_PERF exceptions...
293: */
294:
295: syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
296:
297:
298: uvmexp.pagesize = 4096;
299: uvm_setpagesize();
300:
301: /*
302: * Initialize pmap module.
303: */
304: pmap_bootstrap(startkernel, endkernel);
305:
306: /* now that we know physmem size, map physical memory with BATs */
307: if (physmem > btoc(0x10000000)) {
308: battable[0x1].batl = BATL(0x10000000, BAT_M);
309: battable[0x1].batu = BATU(0x10000000);
310: }
311: if (physmem > btoc(0x20000000)) {
312: battable[0x2].batl = BATL(0x20000000, BAT_M);
313: battable[0x2].batu = BATU(0x20000000);
314: }
315: if (physmem > btoc(0x30000000)) {
316: battable[0x3].batl = BATL(0x30000000, BAT_M);
317: battable[0x3].batu = BATU(0x30000000);
318: }
319: if (physmem > btoc(0x40000000)) {
320: battable[0x4].batl = BATL(0x40000000, BAT_M);
321: battable[0x4].batu = BATU(0x40000000);
322: }
323: if (physmem > btoc(0x50000000)) {
324: battable[0x5].batl = BATL(0x50000000, BAT_M);
325: battable[0x5].batu = BATU(0x50000000);
326: }
327: if (physmem > btoc(0x60000000)) {
328: battable[0x6].batl = BATL(0x60000000, BAT_M);
329: battable[0x6].batu = BATU(0x60000000);
330: }
331: if (physmem > btoc(0x70000000)) {
332: battable[0x7].batl = BATL(0x70000000, BAT_M);
333: battable[0x7].batu = BATU(0x70000000);
334: }
335:
336: /*
337: * Now enable translation (and machine checks/recoverable interrupts).
338: */
339: (fw->vmon)();
340:
341: __asm__ volatile ("eieio; mfmsr %0; ori %0,%0,%1; mtmsr %0; sync;isync"
342: : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
343:
344: /*
345: * use the memory provided by pmap_bootstrap for message buffer
346: */
347: initmsgbuf(msgbuf_addr, MSGBUFSIZE);
348:
349: /*
350: * Look at arguments passed to us and compute boothowto.
351: * Default to SINGLE and ASKNAME if no args or
352: * SINGLE and DFLTROOT if this is a ramdisk kernel.
353: */
354: #ifdef RAMDISK_HOOKS
355: boothowto = RB_SINGLE | RB_DFLTROOT;
356: #else
357: boothowto = RB_AUTOBOOT;
358: #endif /* RAMDISK_HOOKS */
359:
360: /*
361: * Parse arg string.
362: */
363:
364: /* make a copy of the args! */
365: strncpy(bootpathbuf, args, 512);
366: bootpath= &bootpathbuf[0];
367: while ( *++bootpath && *bootpath != ' ');
368: if (*bootpath) {
369: *bootpath++ = 0;
370: while (*bootpath) {
371: switch (*bootpath++) {
372: case 'a':
373: boothowto |= RB_ASKNAME;
374: break;
375: case 's':
376: boothowto |= RB_SINGLE;
377: break;
378: case 'd':
379: boothowto |= RB_KDB;
380: break;
381: case 'c':
382: boothowto |= RB_CONFIG;
383: break;
384: default:
385: break;
386: }
387: }
388: }
389: bootpath= &bootpathbuf[0];
390:
391: #ifdef DDB
392: ddb_init();
393: #endif
394:
395: /*
396: * Set up extents for pci mappings
397: * Is this too late?
398: *
399: * what are good start and end values here??
400: * 0x0 - 0x80000000 mcu bus
401: * MAP A MAP B
402: * 0x80000000 - 0xbfffffff io 0x80000000 - 0xefffffff mem
403: * 0xc0000000 - 0xffffffff mem 0xf0000000 - 0xffffffff io
404: *
405: * of course bsd uses 0xe and 0xf
406: * So the BSD PPC memory map will look like this
407: * 0x0 - 0x80000000 memory (whatever is filled)
408: * 0x80000000 - 0xdfffffff (pci space, memory or io)
409: * 0xe0000000 - kernel vm segment
410: * 0xf0000000 - kernel map segment (user space mapped here)
411: */
412:
413: devio_ex = extent_create("devio", 0x80000000, 0xffffffff, M_DEVBUF,
414: (caddr_t)devio_ex_storage, sizeof(devio_ex_storage),
415: EX_NOCOALESCE|EX_NOWAIT);
416:
417: /*
418: * Now we can set up the console as mapping is enabled.
419: */
420: ofwconsinit();
421: /* while using openfirmware, run userconfig */
422: if (boothowto & RB_CONFIG) {
423: #ifdef BOOT_CONFIG
424: user_config();
425: #else
426: printf("kernel does not support -c; continuing..\n");
427: #endif
428: }
429: /*
430: * Replace with real console.
431: */
432: ofwconprobe();
433: consinit();
434:
435: #ifdef DDB
436: if (boothowto & RB_KDB)
437: Debugger();
438: #endif
439:
440: /*
441: * Figure out ethernet address.
442: */
443: (void)power4e_get_eth_addr();
444:
445: pool_init(&ppc_vecpl, sizeof(struct vreg), 16, 0, 0, "ppcvec", NULL);
446:
447: }
448: void ofw_dbg(char *str)
449: {
450: int i = strlen (str);
451: OF_write(OF_stdout, str, i);
452: }
453:
454:
455: void
456: install_extint(void (*handler)(void))
457: {
458: void extint(void);
459: void extsize(void);
460: extern u_long extint_call;
461: u_long offset = (u_long)handler - (u_long)&extint_call;
462: int omsr, msr;
463:
464: #ifdef DIAGNOSTIC
465: if (offset > 0x1ffffff)
466: panic("install_extint: too far away");
467: #endif
468: omsr = ppc_mfmsr();
469: msr = omsr & ~PSL_EE;
470: ppc_mtmsr(msr);
471: extint_call = (extint_call & 0xfc000003) | offset;
472: bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize);
473: syncicache((void *)&extint_call, sizeof extint_call);
474: syncicache((void *)EXC_EXI, (int)&extsize);
475: ppc_mtmsr(omsr);
476: }
477:
478: /*
479: * Machine dependent startup code.
480: */
481: void
482: cpu_startup()
483: {
484: int sz;
485: caddr_t v;
486: vaddr_t minaddr, maxaddr;
487:
488: v = (caddr_t)proc0paddr + USPACE;
489: proc0.p_addr = proc0paddr;
490:
491: printf("%s", version);
492:
493: printf("real mem = %u (%uMB)\n", ctob(physmem),
494: ctob(physmem)/1024/1024);
495:
496: /*
497: * Find out how much space we need, allocate it,
498: * and then give everything true virtual addresses.
499: */
500: sz = (int)allocsys((caddr_t)0);
501: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
502: panic("startup: no room for tables");
503: if (allocsys(v) - v != sz)
504: panic("startup: table size inconsistency");
505:
506: /*
507: * Determine how many buffers to allocate.
508: * We allocate bufcachepercent% of memory for buffer space.
509: */
510: if (bufpages == 0)
511: bufpages = physmem * bufcachepercent / 100;
512:
513: /* Restrict to at most 25% filled kvm */
514: if (bufpages >
515: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
516: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
517: PAGE_SIZE / 4;
518:
519: /*
520: * Allocate a submap for exec arguments. This map effectively
521: * limits the number of processes exec'ing at any time.
522: */
523: minaddr = vm_map_min(kernel_map);
524: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16 * NCARGS,
525: VM_MAP_PAGEABLE, FALSE, NULL);
526:
527: /*
528: * Allocate a submap for physio
529: */
530: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
531: VM_PHYS_SIZE, 0, FALSE, NULL);
532: ppc_malloc_ok = 1;
533:
534: printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
535: ptoa(uvmexp.free) / 1024 / 1024);
536:
537: /*
538: * Set up the buffers.
539: */
540: bufinit();
541:
542: devio_malloc_safe = 1;
543: }
544:
545: /*
546: * Allocate space for system data structures.
547: */
548: caddr_t
549: allocsys(caddr_t v)
550: {
551: #define valloc(name, type, num) \
552: v = (caddr_t)(((name) = (type *)v) + (num))
553:
554: #ifdef SYSVMSG
555: valloc(msgpool, char, msginfo.msgmax);
556: valloc(msgmaps, struct msgmap, msginfo.msgseg);
557: valloc(msghdrs, struct msg, msginfo.msgtql);
558: valloc(msqids, struct msqid_ds, msginfo.msgmni);
559: #endif
560:
561: return v;
562: }
563:
564: /*
565: * consinit
566: * Initialize system console.
567: */
568: void
569: consinit()
570: {
571: static int cons_initted = 0;
572:
573: if (cons_initted)
574: return;
575: cninit();
576: cons_initted = 1;
577: }
578:
579: /*
580: * Clear registers on exec
581: */
582: void
583: setregs(struct proc *p, struct exec_package *pack, u_long stack,
584: register_t *retval)
585: {
586: u_int32_t newstack;
587: u_int32_t pargs;
588: u_int32_t args[4];
589:
590: struct trapframe *tf = trapframe(p);
591: pargs = -roundup(-stack + 8, 16);
592: newstack = (u_int32_t)(pargs - 32);
593:
594: copyin ((void *)(VM_MAX_ADDRESS-0x10), &args, 0x10);
595:
596: bzero(tf, sizeof *tf);
597: tf->fixreg[1] = newstack;
598: tf->fixreg[3] = retval[0] = args[1]; /* XXX */
599: tf->fixreg[4] = retval[1] = args[0]; /* XXX */
600: tf->fixreg[5] = args[2]; /* XXX */
601: tf->fixreg[6] = args[3]; /* XXX */
602: tf->srr0 = pack->ep_entry;
603: tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
604: p->p_addr->u_pcb.pcb_flags = 0;
605: }
606:
607: /*
608: * Send a signal to process.
609: */
610: void
611: sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
612: union sigval val)
613: {
614: struct proc *p = curproc;
615: struct trapframe *tf;
616: struct sigframe *fp, frame;
617: struct sigacts *psp = p->p_sigacts;
618: int oldonstack;
619:
620: frame.sf_signum = sig;
621:
622: tf = trapframe(p);
623: oldonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
624:
625: /*
626: * Allocate stack space for signal handler.
627: */
628: if ((psp->ps_flags & SAS_ALTSTACK)
629: && !oldonstack
630: && (psp->ps_sigonstack & sigmask(sig))) {
631: fp = (struct sigframe *)(psp->ps_sigstk.ss_sp
632: + psp->ps_sigstk.ss_size);
633: psp->ps_sigstk.ss_flags |= SS_ONSTACK;
634: } else
635: fp = (struct sigframe *)tf->fixreg[1];
636:
637: fp = (struct sigframe *)((int)(fp - 1) & ~0xf);
638:
639: /*
640: * Generate signal context for SYS_sigreturn.
641: */
642: frame.sf_sc.sc_onstack = oldonstack;
643: frame.sf_sc.sc_mask = mask;
644: frame.sf_sip = NULL;
645: bcopy(tf, &frame.sf_sc.sc_frame, sizeof *tf);
646: if (psp->ps_siginfo & sigmask(sig)) {
647: frame.sf_sip = &fp->sf_si;
648: initsiginfo(&frame.sf_si, sig, code, type, val);
649: }
650: if (copyout(&frame, fp, sizeof frame) != 0)
651: sigexit(p, SIGILL);
652:
653:
654: tf->fixreg[1] = (int)fp;
655: tf->lr = (int)catcher;
656: tf->fixreg[3] = (int)sig;
657: tf->fixreg[4] = (psp->ps_siginfo & sigmask(sig)) ? (int)&fp->sf_si : 0;
658: tf->fixreg[5] = (int)&fp->sf_sc;
659: tf->srr0 = p->p_sigcode;
660:
661: #if WHEN_WE_ONLY_FLUSH_DATA_WHEN_DOING_PMAP_ENTER
662: pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),tf->srr0, &pa);
663: syncicache(pa, (p->p_emul->e_esigcode - p->p_emul->e_sigcode));
664: #endif
665: }
666:
667: /*
668: * System call to cleanup state after a signal handler returns.
669: */
670: int
671: sys_sigreturn(struct proc *p, void *v, register_t *retval)
672: {
673: struct sys_sigreturn_args /* {
674: syscallarg(struct sigcontext *) sigcntxp;
675: } */ *uap = v;
676: struct sigcontext sc;
677: struct trapframe *tf;
678: int error;
679:
680: if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)))
681: return error;
682: tf = trapframe(p);
683: if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC))
684: return EINVAL;
685: bcopy(&sc.sc_frame, tf, sizeof *tf);
686: if (sc.sc_onstack & 1)
687: p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
688: else
689: p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
690: p->p_sigmask = sc.sc_mask & ~sigcantmask;
691: return EJUSTRETURN;
692: }
693:
694: /*
695: * Machine dependent system variables.
696: * None for now.
697: */
698: int
699: cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
700: size_t newlen, struct proc *p)
701: {
702: /* all sysctl names at this level are terminal */
703: if (namelen != 1)
704: return ENOTDIR;
705: switch (name[0]) {
706: case CPU_ALLOWAPERTURE:
707: #ifdef APERTURE
708: if (securelevel > 0)
709: return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
710: &allowaperture));
711: else
712: return (sysctl_int(oldp, oldlenp, newp, newlen,
713: &allowaperture));
714: #else
715: return (sysctl_rdint(oldp, oldlenp, newp, 0));
716: #endif
717: case CPU_ALTIVEC:
718: return (sysctl_rdint(oldp, oldlenp, newp, ppc_altivec));
719: default:
720: return EOPNOTSUPP;
721: }
722: }
723:
724:
725: u_long dumpmag = 0x04959fca; /* magic number */
726: int dumpsize = 0; /* size of dump in pages */
727: long dumplo = -1; /* blocks */
728:
729: /*
730: * This is called by configure to set dumplo and dumpsize.
731: * Dumps always skip the first CLBYTES of disk space
732: * in case there might be a disk label stored there.
733: * If there is extra space, put dump at the end to
734: * reduce the chance that swapping trashes it.
735: */
736: void dumpconf(void);
737:
738: void
739: dumpconf(void)
740: {
741: int nblks; /* size of dump area */
742: int i;
743:
744: if (dumpdev == NODEV ||
745: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
746: return;
747: if (nblks <= ctod(1))
748: return;
749:
750: /* Always skip the first block, in case there is a label there. */
751: if (dumplo < ctod(1))
752: dumplo = ctod(1);
753:
754: for (i = 0; i < ndumpmem; i++)
755: dumpsize = max(dumpsize, dumpmem[i].end);
756:
757: /* Put dump at end of partition, and make it fit. */
758: if (dumpsize > dtoc(nblks - dumplo - 1))
759: dumpsize = dtoc(nblks - dumplo - 1);
760: if (dumplo < nblks - ctod(dumpsize) - 1)
761: dumplo = nblks - ctod(dumpsize) - 1;
762:
763: }
764:
765: #define BYTES_PER_DUMP (PAGE_SIZE) /* must be a multiple of pagesize */
766: vaddr_t dumpspace;
767:
768: int
769: reserve_dumppages(caddr_t p)
770: {
771: dumpspace = (vaddr_t)p;
772: return BYTES_PER_DUMP;
773: }
774:
775: /*
776: * cpu_dump: dump machine-dependent kernel core dump headers.
777: */
778: int cpu_dump(void);
779: int
780: cpu_dump()
781: {
782: int (*dump) (dev_t, daddr64_t, caddr_t, size_t);
783: long buf[dbtob(1) / sizeof (long)];
784: kcore_seg_t *segp;
785:
786: dump = bdevsw[major(dumpdev)].d_dump;
787:
788: segp = (kcore_seg_t *)buf;
789:
790: /*
791: * Generate a segment header.
792: */
793: CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
794: segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
795:
796: return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
797: }
798:
799: void
800: dumpsys()
801: {
802: #if 0
803: u_int npg;
804: u_int i, j;
805: daddr64_t blkno;
806: int (*dump) (dev_t, daddr64_t, caddr_t, size_t);
807: char *str;
808: int maddr;
809: extern int msgbufmapped;
810: int error;
811:
812: /* save registers */
813:
814: msgbufmapped = 0; /* don't record dump msgs in msgbuf */
815: if (dumpdev == NODEV)
816: return;
817: /*
818: * For dumps during autoconfiguration,
819: * if dump device has already configured...
820: */
821: if (dumpsize == 0)
822: dumpconf();
823: if (dumplo < 0)
824: return;
825: printf("dumping to dev %x, offset %ld\n", dumpdev, dumplo);
826:
827: error = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
828: if (error == -1) {
829: printf("area unavailable\n");
830: delay (10000000);
831: return;
832: }
833:
834: dump = bdevsw[major(dumpdev)].d_dump;
835: error = cpu_dump();
836: for (i = 0; !error && i < ndumpmem; i++) {
837: npg = dumpmem[i].end - dumpmem[i].start;
838: maddr = ctob(dumpmem[i].start);
839: blkno = dumplo + btodb(maddr) + 1;
840:
841: for (j = npg; j;
842: j--, maddr += PAGE_SIZE, blkno+= btodb(PAGE_SIZE))
843: {
844: /* Print out how many MBs we have to go. */
845: if (dbtob(blkno - dumplo) % (1024 * 1024) < NBPG)
846: printf("%d ",
847: (ctob(dumpsize) - maddr) / (1024 * 1024));
848:
849: pmap_enter(pmap_kernel(), dumpspace, maddr,
850: VM_PROT_READ, PMAP_WIRED);
851: if ((error = (*dump)(dumpdev, blkno,
852: (caddr_t)dumpspace, PAGE_SIZE)) != 0)
853: break;
854: }
855: }
856:
857: switch (error) {
858:
859: case 0: str = "succeeded\n\n"; break;
860: case ENXIO: str = "device bad\n\n"; break;
861: case EFAULT: str = "device not ready\n\n"; break;
862: case EINVAL: str = "area improper\n\n"; break;
863: case EIO: str = "i/o error\n\n"; break;
864: case EINTR: str = "aborted from console\n\n"; break;
865: default: str = "error %d\n\n"; break;
866: }
867: printf(str, error);
868:
869: #else
870: printf("dumpsys() - no yet supported\n");
871:
872: #endif
873: delay(5000000); /* 5 seconds */
874:
875: }
876:
877: int imask[IPL_NUM];
878:
879: /*
880: * this is a hack interface to allow zs to work better until
881: * a true soft interrupt mechanism is created.
882: */
883: #include "zstty.h"
884: #if NZSTTY > 0
885: extern void zssoft(void *);
886: #endif
887: void
888: softtty()
889: {
890: #if NZSTTY > 0
891: zssoft(0);
892: #endif
893: }
894:
895: int netisr;
896:
897: /*
898: * Soft networking interrupts.
899: */
900: void
901: softnet(int isr)
902: {
903: #define DONETISR(flag, func) \
904: if (isr & (1 << flag))\
905: func();
906:
907: #include <net/netisr_dispatch.h>
908: }
909:
910: int
911: lcsplx(int ipl)
912: {
913: return spllower(ipl);
914: }
915:
916: /*
917: * Halt or reboot the machine after syncing/dumping according to howto.
918: */
919: void
920: boot(int howto)
921: {
922: static int syncing;
923:
924: boothowto = howto;
925: if (!cold && !(howto & RB_NOSYNC) && !syncing) {
926: syncing = 1;
927: vfs_shutdown(); /* sync */
928:
929: /*
930: * If we've been adjusting the clock, the todr
931: * will be out of synch; adjust it now unless
932: * the system was sitting in ddb.
933: */
934: if ((howto & RB_TIMEBAD) == 0) {
935: resettodr();
936: } else {
937: printf("WARNING: not updating battery clock\n");
938: }
939: }
940: splhigh();
941: if (howto & RB_HALT) {
942: doshutdownhooks();
943: if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
944: #if NADB > 0
945: delay(1000000);
946: adb_poweroff();
947: printf("WARNING: adb powerdown failed!\n");
948: #endif
949: OF_interpret("shut-down", 0);
950: }
951:
952: printf("halted\n\n");
953: (fw->exit)();
954: }
955: if (!cold && (howto & RB_DUMP))
956: dumpsys();
957: doshutdownhooks();
958: printf("rebooting\n\n");
959:
960: #if NADB > 0
961: adb_restart(); /* not return */
962: #endif
963:
964: OF_interpret("reset-all", 0);
965: OF_exit();
966: printf("boot failed, spinning\n");
967: while(1) /* forever */;
968: }
969:
970: /*
971: * Get Ethernet address for the onboard ethernet chip.
972: */
973: int
974: power4e_get_eth_addr()
975: {
976: int qhandle, phandle;
977: char name[32];
978:
979: for (qhandle = OF_peer(0); qhandle; qhandle = phandle) {
980: if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0
981: && !strcmp(name, "network")
982: && OF_getprop(qhandle, "local-mac-address",
983: &ofw_eth_addr, sizeof ofw_eth_addr) >= 0) {
984: return(0);
985: }
986: if ((phandle = OF_child(qhandle)))
987: continue;
988: while (qhandle) {
989: if ((phandle = OF_peer(qhandle)))
990: break;
991: qhandle = OF_parent(qhandle);
992: }
993: }
994: return(-1);
995: }
996:
997: typedef void (void_f) (void);
998: void_f *pending_int_f = NULL;
999:
1000: /* call the bus/interrupt controller specific pending interrupt handler
1001: * would be nice if the offlevel interrupt code was handled here
1002: * instead of being in each of the specific handler code
1003: */
1004: void
1005: do_pending_int()
1006: {
1007: if (pending_int_f != NULL) {
1008: (*pending_int_f)();
1009: }
1010: }
1011:
1012: /*
1013: * set system type from string
1014: */
1015: void
1016: systype(char *name)
1017: {
1018: /* this table may be order specific if substrings match several
1019: * computers but a longer string matches a specific
1020: */
1021: int i;
1022: struct systyp {
1023: char *name;
1024: char *systypename;
1025: int type;
1026: } systypes[] = {
1027: { "MOT", "(PWRSTK) MCG powerstack family", PWRSTK },
1028: { "V-I Power", "(POWER4e) V-I ppc vme boards ", POWER4e},
1029: { "iMac", "(APPL) Apple iMac ", APPL},
1030: { "PowerMac", "(APPL) Apple PowerMac ", APPL},
1031: { "PowerBook", "(APPL) Apple Powerbook ", APPL},
1032: { NULL,"",0}
1033: };
1034: for (i = 0; systypes[i].name != NULL; i++) {
1035: if (strncmp( name , systypes[i].name,
1036: strlen (systypes[i].name)) == 0)
1037: {
1038: system_type = systypes[i].type;
1039: printf("recognized system type of %s as %s\n",
1040: name, systypes[i].systypename);
1041: break;
1042: }
1043: }
1044: if (system_type == OFWMACH) {
1045: printf("System type %snot recognized, good luck\n",
1046: name);
1047: }
1048: }
1049:
1050: /*
1051: * one attempt at interrupt stuff..
1052: *
1053: */
1054: #include <dev/pci/pcivar.h>
1055:
1056: int ppc_configed_intr_cnt = 0;
1057: struct intrhand ppc_configed_intr[MAX_PRECONF_INTR];
1058:
1059: void *
1060: ppc_intr_establish(void *lcv, pci_intr_handle_t ih, int type, int level,
1061: int (*func)(void *), void *arg, char *name)
1062: {
1063: if (ppc_configed_intr_cnt < MAX_PRECONF_INTR) {
1064: ppc_configed_intr[ppc_configed_intr_cnt].ih_fun = func;
1065: ppc_configed_intr[ppc_configed_intr_cnt].ih_arg = arg;
1066: ppc_configed_intr[ppc_configed_intr_cnt].ih_level = level;
1067: ppc_configed_intr[ppc_configed_intr_cnt].ih_irq = ih;
1068: ppc_configed_intr[ppc_configed_intr_cnt].ih_what = name;
1069: ppc_configed_intr_cnt++;
1070: } else {
1071: panic("ppc_intr_establish called before interrupt controller"
1072: " configured: driver %s too many interrupts", name);
1073: }
1074: /* disestablish is going to be tricky to supported for these :-) */
1075: return (void *)ppc_configed_intr_cnt;
1076: }
1077:
1078: intr_establish_t *intr_establish_func = (intr_establish_t *)ppc_intr_establish;
1079: intr_disestablish_t *intr_disestablish_func;
1080:
1081: void
1082: ppc_intr_setup(intr_establish_t *establish, intr_disestablish_t *disestablish)
1083: {
1084: intr_establish_func = establish;
1085: intr_disestablish_func = disestablish;
1086: }
1087:
1088: /* BUS functions */
1089: int
1090: bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
1091: int cacheable, bus_space_handle_t *bshp)
1092: {
1093: int error;
1094:
1095: if (POWERPC_BUS_TAG_BASE(t) == 0) {
1096: /* if bus has base of 0 fail. */
1097: return 1;
1098: }
1099: bpa |= POWERPC_BUS_TAG_BASE(t);
1100: if ((error = extent_alloc_region(devio_ex, bpa, size, EX_NOWAIT |
1101: (ppc_malloc_ok ? EX_MALLOCOK : 0))))
1102: return error;
1103:
1104: if ((error = bus_mem_add_mapping(bpa, size, cacheable, bshp))) {
1105: if (extent_free(devio_ex, bpa, size, EX_NOWAIT |
1106: (ppc_malloc_ok ? EX_MALLOCOK : 0)))
1107: {
1108: printf("bus_space_map: pa 0x%lx, size 0x%x\n",
1109: bpa, size);
1110: printf("bus_space_map: can't free region\n");
1111: }
1112: }
1113: return 0;
1114: }
1115: bus_addr_t
1116: bus_space_unmap_p(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
1117: {
1118: bus_addr_t paddr;
1119:
1120: pmap_extract(pmap_kernel(), bsh, &paddr);
1121: bus_space_unmap((t), (bsh), (size));
1122: return paddr ;
1123: }
1124: void
1125: bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
1126: {
1127: bus_addr_t sva;
1128: bus_size_t off, len;
1129: bus_addr_t bpa;
1130:
1131: /* should this verify that the proper size is freed? */
1132: sva = trunc_page(bsh);
1133: off = bsh - sva;
1134: len = size+off;
1135:
1136: if (pmap_extract(pmap_kernel(), sva, &bpa) == TRUE) {
1137: if (extent_free(devio_ex, bpa | (bsh & PAGE_MASK), size, EX_NOWAIT |
1138: (ppc_malloc_ok ? EX_MALLOCOK : 0)))
1139: {
1140: printf("bus_space_map: pa 0x%lx, size 0x%x\n",
1141: bpa, size);
1142: printf("bus_space_map: can't free region\n");
1143: }
1144: }
1145: /* do not free memory which was stolen from the vm system */
1146: if (ppc_malloc_ok &&
1147: ((sva >= VM_MIN_KERNEL_ADDRESS) && (sva < VM_MAX_KERNEL_ADDRESS)))
1148: uvm_km_free(phys_map, sva, len);
1149: else {
1150: pmap_remove(vm_map_pmap(phys_map), sva, sva+len);
1151: pmap_update(pmap_kernel());
1152: }
1153: }
1154:
1155: vaddr_t ppc_kvm_stolen = VM_KERN_ADDRESS_SIZE;
1156:
1157: int
1158: bus_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int cacheable,
1159: bus_space_handle_t *bshp)
1160: {
1161: bus_addr_t vaddr;
1162: bus_addr_t spa, epa;
1163: bus_size_t off;
1164: int len;
1165:
1166: spa = trunc_page(bpa);
1167: epa = bpa + size;
1168: off = bpa - spa;
1169: len = size+off;
1170:
1171: #if 0
1172: if (epa <= spa) {
1173: panic("bus_mem_add_mapping: overflow");
1174: }
1175: #endif
1176: if (ppc_malloc_ok == 0) {
1177: bus_size_t alloc_size;
1178:
1179: /* need to steal vm space before kernel vm is initialized */
1180: alloc_size = round_page(len);
1181:
1182: vaddr = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen;
1183: ppc_kvm_stolen += alloc_size;
1184: if (ppc_kvm_stolen > PPC_SEGMENT_LENGTH) {
1185: panic("ppc_kvm_stolen, out of space");
1186: }
1187: } else {
1188: vaddr = uvm_km_kmemalloc(phys_map, NULL, len,
1189: UVM_KMF_NOWAIT|UVM_KMF_VALLOC);
1190: if (vaddr == 0)
1191: panic("bus_mem_add_mapping: kvm alloc of 0x%x failed",
1192: len);
1193: }
1194: *bshp = vaddr + off;
1195: #ifdef DEBUG_BUS_MEM_ADD_MAPPING
1196: printf("mapping %x size %x to %x vbase %x\n",
1197: bpa, size, *bshp, spa);
1198: #endif
1199: for (; len > 0; len -= PAGE_SIZE) {
1200: pmap_kenter_cache(vaddr, spa,
1201: VM_PROT_READ | VM_PROT_WRITE,
1202: cacheable ? PMAP_CACHE_WT : PMAP_CACHE_CI);
1203: spa += PAGE_SIZE;
1204: vaddr += PAGE_SIZE;
1205: }
1206: return 0;
1207: }
1208:
1209: int
1210: bus_space_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
1211: bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable,
1212: bus_addr_t *addrp, bus_space_handle_t *handlep)
1213: {
1214:
1215: panic("bus_space_alloc: unimplemented");
1216: }
1217:
1218: void
1219: bus_space_free(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size)
1220: {
1221:
1222: panic("bus_space_free: unimplemented");
1223: }
1224:
1225: void *
1226: mapiodev(paddr_t pa, psize_t len)
1227: {
1228: paddr_t spa;
1229: vaddr_t vaddr, va;
1230: int off;
1231: int size;
1232:
1233: spa = trunc_page(pa);
1234: off = pa - spa;
1235: size = round_page(off+len);
1236: if (ppc_malloc_ok == 0) {
1237: /* need to steal vm space before kernel vm is initialized */
1238: va = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen;
1239: ppc_kvm_stolen += size;
1240: if (ppc_kvm_stolen > PPC_SEGMENT_LENGTH) {
1241: panic("ppc_kvm_stolen, out of space");
1242: }
1243: } else {
1244: va = uvm_km_kmemalloc(phys_map, NULL, size,
1245: UVM_KMF_NOWAIT|UVM_KMF_VALLOC);
1246: }
1247:
1248: if (va == 0)
1249: return NULL;
1250:
1251: for (vaddr = va; size > 0; size -= PAGE_SIZE) {
1252: pmap_kenter_cache(vaddr, spa,
1253: VM_PROT_READ | VM_PROT_WRITE, PMAP_CACHE_DEFAULT);
1254: spa += PAGE_SIZE;
1255: vaddr += PAGE_SIZE;
1256: }
1257: return (void *) (va+off);
1258: }
1259: void
1260: unmapiodev(void *kva, psize_t p_size)
1261: {
1262: vaddr_t vaddr;
1263: int size;
1264:
1265: size = p_size;
1266:
1267: vaddr = trunc_page((vaddr_t)kva);
1268:
1269: uvm_km_free_wakeup(phys_map, vaddr, size);
1270:
1271: for (; size > 0; size -= PAGE_SIZE) {
1272: #if 0
1273: pmap_remove(vm_map_pmap(phys_map), vaddr, vaddr+PAGE_SIZE-1);
1274: #else
1275: pmap_remove(pmap_kernel(), vaddr, vaddr+PAGE_SIZE-1);
1276: #endif
1277: vaddr += PAGE_SIZE;
1278: }
1279: pmap_update(pmap_kernel());
1280: }
1281:
1282:
1283:
1284: /*
1285: * probably should be ppc_space_copy
1286: */
1287:
1288: #define _CONCAT(A,B) A ## B
1289: #define __C(A,B) _CONCAT(A,B)
1290:
1291: #define BUS_SPACE_COPY_N(BYTES,TYPE) \
1292: void \
1293: __C(bus_space_copy_,BYTES)(void *v, bus_space_handle_t h1, \
1294: bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, \
1295: bus_size_t c) \
1296: { \
1297: TYPE *src, *dst; \
1298: int i; \
1299: \
1300: src = (TYPE *) (h1+o1); \
1301: dst = (TYPE *) (h2+o2); \
1302: \
1303: if (h1 == h2 && o2 > o1) \
1304: for (i = c-1; i >= 0; i--) \
1305: dst[i] = src[i]; \
1306: else \
1307: for (i = 0; i < c; i++) \
1308: dst[i] = src[i]; \
1309: }
1310: BUS_SPACE_COPY_N(1,u_int8_t)
1311: BUS_SPACE_COPY_N(2,u_int16_t)
1312: BUS_SPACE_COPY_N(4,u_int32_t)
1313:
1314: void
1315: bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
1316: u_int8_t val, bus_size_t c)
1317: {
1318: u_int8_t *dst;
1319: int i;
1320:
1321: dst = (u_int8_t *) (h+o);
1322:
1323: for (i = 0; i < c; i++)
1324: dst[i] = val;
1325: }
1326:
1327: void
1328: bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
1329: u_int16_t val, bus_size_t c)
1330: {
1331: u_int16_t *dst;
1332: int i;
1333:
1334: dst = (u_int16_t *) (h+o);
1335: val = swap16(val);
1336:
1337: for (i = 0; i < c; i++)
1338: dst[i] = val;
1339: }
1340: void
1341: bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
1342: u_int32_t val, bus_size_t c)
1343: {
1344: u_int32_t *dst;
1345: int i;
1346:
1347: dst = (u_int32_t *) (h+o);
1348: val = swap32(val);
1349:
1350: for (i = 0; i < c; i++)
1351: dst[i] = val;
1352: }
1353:
1354: #define BUS_SPACE_READ_RAW_MULTI_N(BYTES,SHIFT,TYPE) \
1355: void \
1356: __C(bus_space_read_raw_multi_,BYTES)(bus_space_tag_t bst, \
1357: bus_space_handle_t h, bus_addr_t o, u_int8_t *dst, bus_size_t size) \
1358: { \
1359: TYPE *src; \
1360: TYPE *rdst = (TYPE *)dst; \
1361: int i; \
1362: int count = size >> SHIFT; \
1363: \
1364: src = (TYPE *)(h+o); \
1365: for (i = 0; i < count; i++) { \
1366: rdst[i] = *src; \
1367: __asm__("eieio"); \
1368: } \
1369: }
1370: BUS_SPACE_READ_RAW_MULTI_N(2,1,u_int16_t)
1371: BUS_SPACE_READ_RAW_MULTI_N(4,2,u_int32_t)
1372:
1373: #define BUS_SPACE_WRITE_RAW_MULTI_N(BYTES,SHIFT,TYPE) \
1374: void \
1375: __C(bus_space_write_raw_multi_,BYTES)( bus_space_tag_t bst, \
1376: bus_space_handle_t h, bus_addr_t o, const u_int8_t *src, \
1377: bus_size_t size) \
1378: { \
1379: int i; \
1380: TYPE *dst; \
1381: TYPE *rsrc = (TYPE *)src; \
1382: int count = size >> SHIFT; \
1383: \
1384: dst = (TYPE *)(h+o); \
1385: for (i = 0; i < count; i++) { \
1386: *dst = rsrc[i]; \
1387: __asm__("eieio"); \
1388: } \
1389: }
1390:
1391: BUS_SPACE_WRITE_RAW_MULTI_N(2,1,u_int16_t)
1392: BUS_SPACE_WRITE_RAW_MULTI_N(4,2,u_int32_t)
1393:
1394: int
1395: bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
1396: bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
1397: {
1398: *nbshp = bsh + offset;
1399: return (0);
1400: }
1401:
1402: int
1403: ppc_open_pci_bridge()
1404: {
1405: char *
1406: pci_bridges[] = {
1407: "/pci",
1408: NULL
1409: };
1410: int handle;
1411: int i;
1412:
1413: for (i = 0; pci_bridges[i] != NULL; i++) {
1414: handle = OF_open(pci_bridges[i]);
1415: if ( handle != -1) {
1416: return handle;
1417: }
1418: }
1419: return 0;
1420: }
1421: void
1422: ppc_close_pci_bridge(int handle)
1423: {
1424: OF_close(handle);
1425: }
1426:
1427: /* bcopy(), error on fault */
1428: int
1429: kcopy(const void *from, void *to, size_t size)
1430: {
1431: faultbuf env;
1432: void *oldh = curproc->p_addr->u_pcb.pcb_onfault;
1433:
1434: if (setfault(&env)) {
1435: curproc->p_addr->u_pcb.pcb_onfault = oldh;
1436: return EFAULT;
1437: }
1438: bcopy(from, to, size);
1439: curproc->p_addr->u_pcb.pcb_onfault = oldh;
1440:
1441: return 0;
1442: }
CVSweb