Annotation of sys/arch/luna88k/luna88k/machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: machdep.c,v 1.44 2007/06/06 17:15:12 deraadt Exp $ */
2: /*
3: * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr.
4: * Copyright (c) 1996 Nivas Madhur
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Nivas Madhur.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: *
32: */
33: /*
34: * Mach Operating System
35: * Copyright (c) 1993-1991 Carnegie Mellon University
36: * Copyright (c) 1991 OMRON Corporation
37: * All Rights Reserved.
38: *
39: * Permission to use, copy, modify and distribute this software and its
40: * documentation is hereby granted, provided that both the copyright
41: * notice and this permission notice appear in all copies of the
42: * software, derivative works or modified versions, and any portions
43: * thereof, and that both notices appear in supporting documentation.
44: *
45: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
46: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
47: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48: *
49: * Carnegie Mellon requests users of this software to return to
50: *
51: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
52: * School of Computer Science
53: * Carnegie Mellon University
54: * Pittsburgh PA 15213-3890
55: *
56: * any improvements or extensions that they make and grant Carnegie the
57: * rights to redistribute these changes.
58: */
59:
60: #include <sys/param.h>
61: #include <sys/systm.h>
62: #include <sys/kernel.h>
63: #include <sys/proc.h>
64: #include <sys/user.h>
65: #include <sys/buf.h>
66: #include <sys/reboot.h>
67: #include <sys/conf.h>
68: #include <sys/malloc.h>
69: #include <sys/mount.h>
70: #include <sys/msgbuf.h>
71: #include <sys/syscallargs.h>
72: #ifdef SYSVMSG
73: #include <sys/msg.h>
74: #endif
75: #include <sys/exec.h>
76: #include <sys/sysctl.h>
77: #include <sys/errno.h>
78: #include <sys/extent.h>
79: #include <sys/core.h>
80: #include <sys/kcore.h>
81:
82: #include <machine/asm.h>
83: #include <machine/asm_macro.h>
84: #include <machine/board.h>
85: #include <machine/cmmu.h>
86: #include <machine/cpu.h>
87: #include <machine/kcore.h>
88: #include <machine/reg.h>
89: #include <machine/trap.h>
90: #include <machine/m88100.h>
91:
92: #include <luna88k/luna88k/isr.h>
93:
94: #include <dev/cons.h>
95:
96: #include <uvm/uvm_extern.h>
97:
98: #include "ksyms.h"
99: #if DDB
100: #include <machine/db_machdep.h>
101: #include <ddb/db_extern.h>
102: #include <ddb/db_interface.h>
103: #include <ddb/db_output.h> /* db_printf() */
104: #endif /* DDB */
105:
106: caddr_t allocsys(caddr_t);
107: void consinit(void);
108: void dumpconf(void);
109: void dumpsys(void);
110: int getcpuspeed(void);
111: u_int getipl(void);
112: void identifycpu(void);
113: void luna88k_bootstrap(void);
114: void savectx(struct pcb *);
115: void secondary_main(void);
116: void secondary_pre_main(void);
117: void setlevel(unsigned int);
118:
119: vaddr_t size_memory(void);
120: void powerdown(void);
121: void get_fuse_rom_data(void);
122: void get_nvram_data(void);
123: char *nvram_by_symbol(char *);
124: void get_autoboot_device(void); /* in disksubr.c */
125: int clockintr(void *); /* in clock.c */
126:
127: /*
128: * *int_mask_reg[CPU]
129: * Points to the hardware interrupt status register for each CPU.
130: */
131: unsigned int *volatile int_mask_reg[] = {
132: (unsigned int *)INT_ST_MASK0,
133: (unsigned int *)INT_ST_MASK1,
134: (unsigned int *)INT_ST_MASK2,
135: (unsigned int *)INT_ST_MASK3
136: };
137:
138: unsigned int luna88k_curspl[] = {0, 0, 0, 0};
139:
140: unsigned int int_set_val[INT_LEVEL] = {
141: INT_SET_LV0,
142: INT_SET_LV1,
143: INT_SET_LV2,
144: INT_SET_LV3,
145: INT_SET_LV4,
146: INT_SET_LV5,
147: INT_SET_LV6,
148: INT_SET_LV7
149: };
150:
151: /*
152: * *clock_reg[CPU]
153: */
154: unsigned int *volatile clock_reg[] = {
155: (unsigned int *)OBIO_CLOCK0,
156: (unsigned int *)OBIO_CLOCK1,
157: (unsigned int *)OBIO_CLOCK2,
158: (unsigned int *)OBIO_CLOCK3
159: };
160:
161: /*
162: * FUSE ROM and NVRAM data
163: */
164: struct fuse_rom_byte {
165: u_int32_t h;
166: u_int32_t l;
167: };
168: #define FUSE_ROM_BYTES (FUSE_ROM_SPACE / sizeof(struct fuse_rom_byte))
169: char fuse_rom_data[FUSE_ROM_BYTES];
170:
171: #define NNVSYM 8
172: #define NVSYMLEN 16
173: #define NVVALLEN 16
174: struct nvram_t {
175: char symbol[NVSYMLEN];
176: char value[NVVALLEN];
177: } nvram[NNVSYM];
178:
179: vaddr_t obiova;
180:
181: int physmem; /* available physical memory, in pages */
182:
183: struct vm_map *exec_map = NULL;
184: struct vm_map *phys_map = NULL;
185:
186: /*
187: * Declare these as initialized data so we can patch them.
188: */
189: #ifndef BUFCACHEPERCENT
190: #define BUFCACHEPERCENT 5
191: #endif
192:
193: #ifdef BUFPAGES
194: int bufpages = BUFPAGES;
195: #else
196: int bufpages = 0;
197: #endif
198: int bufcachepercent = BUFCACHEPERCENT;
199:
200: /*
201: * Info for CTL_HW
202: */
203: char machine[] = MACHINE; /* cpu "architecture" */
204: char cpu_model[120];
205:
206: #if defined(DDB) || NKSYMS > 0
207: extern char *esym;
208: #endif
209:
210: int machtype = LUNA_88K; /* may be overwritten in cpu_startup() */
211: int cputyp = CPU_88100; /* XXX: aoyama */
212: int boothowto; /* XXX: should be set in boot loader and locore.S */
213: int bootdev; /* XXX: should be set in boot loader and locore.S */
214: int cpuspeed = 33; /* safe guess */
215: int sysconsole = 1; /* 0 = ttya, 1 = keyboard/mouse, used in dev/sio.c */
216: u_int16_t dipswitch = 0; /* set in locore.S */
217: int hwplanebits; /* set in locore.S */
218:
219: extern struct consdev syscons; /* in dev/siotty.c */
220:
221: extern void syscnattach(int); /* in dev/siotty.c */
222: extern int omfb_cnattach(void); /* in dev/lunafb.c */
223: extern void ws_cnattach(void); /* in dev/lunaws.c */
224:
225: vaddr_t first_addr;
226: vaddr_t last_addr;
227:
228: vaddr_t avail_start, avail_end;
229: vaddr_t virtual_avail, virtual_end;
230:
231: extern struct user *proc0paddr;
232:
233: /*
234: * This is to fake out the console routines, while booting.
235: * We could use directly the romtty console, but we want to be able to
236: * configure a kernel without romtty since we do not necessarily need a
237: * full-blown console driver.
238: */
239: cons_decl(romtty);
240: extern void nullcnpollc(dev_t, int);
241:
242: struct consdev romttycons = {
243: NULL,
244: NULL,
245: romttycngetc,
246: romttycnputc,
247: nullcnpollc,
248: NULL,
249: makedev(14, 0),
250: CN_NORMAL,
251: };
252:
253: /*
254: * Early console initialization: called early on from main, before vm init.
255: */
256: void
257: consinit()
258: {
259: /*
260: * Initialize the console before we print anything out.
261: */
262: if (sysconsole == 0) {
263: syscnattach(0);
264: } else {
265: omfb_cnattach();
266: ws_cnattach();
267: }
268:
269: #if defined(DDB)
270: db_machine_init();
271: ddb_init();
272: if (boothowto & RB_KDB)
273: Debugger();
274: #endif
275: }
276:
277: /*
278: * Figure out how much real memory is available.
279: * Start looking from the megabyte after the end of the kernel data,
280: * until we find non-memory.
281: */
282: vaddr_t
283: size_memory()
284: {
285: unsigned int *volatile look;
286: unsigned int *max;
287: #if 0
288: extern char *end;
289: #endif
290: #define PATTERN 0x5a5a5a5a
291: #define STRIDE (4*1024) /* 4k at a time */
292: #define Roundup(value, stride) (((unsigned)(value) + (stride) - 1) & ~((stride)-1))
293: /*
294: * count it up.
295: */
296: max = (void *)MAXPHYSMEM;
297: #if 0
298: for (look = (void *)Roundup(end, STRIDE); look < max;
299: #else
300: for (look = (void *)first_addr; look < max;
301: #endif
302: look = (int *)((unsigned)look + STRIDE)) {
303: unsigned save;
304:
305: /* if can't access, we've reached the end */
306: if (badaddr((vaddr_t)look, 4)) {
307: #if defined(DEBUG)
308: printf("%x\n", look);
309: #endif
310: look = (int *)((int)look - STRIDE);
311: break;
312: }
313:
314: /*
315: * If we write a value, we expect to read the same value back.
316: * We'll do this twice, the 2nd time with the opposite bit
317: * pattern from the first, to make sure we check all bits.
318: */
319: save = *look;
320: if (*look = PATTERN, *look != PATTERN)
321: break;
322: if (*look = ~PATTERN, *look != ~PATTERN)
323: break;
324: *look = save;
325: }
326:
327: return (trunc_page((unsigned)look));
328: }
329:
330: int
331: getcpuspeed()
332: {
333: switch(machtype) {
334: case LUNA_88K:
335: return 25;
336: case LUNA_88K2:
337: return 33;
338: default:
339: panic("getcpuspeed: can not determine CPU speed");
340: }
341: }
342:
343: void
344: identifycpu()
345: {
346: cpuspeed = getcpuspeed();
347: snprintf(cpu_model, sizeof cpu_model,
348: "OMRON LUNA-88K%s, %dMHz",
349: machtype == LUNA_88K2 ? "2" : "", cpuspeed);
350: }
351:
352: void
353: cpu_startup()
354: {
355: caddr_t v;
356: int sz, i;
357: vaddr_t minaddr, maxaddr;
358:
359: /*
360: * Initialize error message buffer (at end of core).
361: * avail_end was pre-decremented in luna88k_bootstrap() to compensate.
362: */
363: for (i = 0; i < btoc(MSGBUFSIZE); i++)
364: pmap_kenter_pa((paddr_t)msgbufp + i * PAGE_SIZE,
365: avail_end + i * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE);
366: pmap_update(pmap_kernel());
367: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
368:
369: /* Determine the machine type from FUSE ROM data. */
370: get_fuse_rom_data();
371: if (strncmp(fuse_rom_data, "MNAME=LUNA88K+", 14) == 0) {
372: machtype = LUNA_88K2;
373: }
374:
375: /* Determine the 'auto-boot' device from NVRAM data */
376: get_nvram_data();
377: get_autoboot_device();
378:
379: /*
380: * Good {morning,afternoon,evening,night}.
381: */
382: printf(version);
383: identifycpu();
384: printf("real mem = %d\n", ctob(physmem));
385:
386: /*
387: * Check front DIP switch setting
388: */
389: #ifdef DEBUG
390: printf("dipsw = 0x%x\n", dipswitch);
391: #endif
392:
393: /* Check DIP switch 1 - 1 */
394: if ((0x8000 & dipswitch) == 0) {
395: boothowto |= RB_SINGLE;
396: }
397:
398: /* Check DIP switch 1 - 3 */
399: if ((0x2000 & dipswitch) == 0) {
400: boothowto |= RB_ASKNAME;
401: }
402:
403: /* Check DIP switch 1 - 4 */
404: if ((0x1000 & dipswitch) == 0) {
405: boothowto |= RB_CONFIG;
406: }
407:
408: /*
409: * Check frame buffer depth.
410: */
411: switch (hwplanebits) {
412: case 0: /* No frame buffer */
413: case 1:
414: case 4:
415: case 8:
416: break;
417: default:
418: printf("unexpected frame buffer depth = %d\n", hwplanebits);
419: hwplanebits = 0;
420: break;
421: }
422:
423: #if 0 /* just for test */
424: /*
425: * Get boot arguments
426: */
427: {
428: char buf[256];
429: char **p = (volatile char **)0x00001120;
430:
431: strncpy(buf, *p, 256);
432: if (buf[255] != '\0')
433: buf[255] = '\0';
434:
435: printf("boot arg: (0x%x) %s\n", *p, buf);
436: }
437: #endif
438:
439: /*
440: * Find out how much space we need, allocate it,
441: * and then give everything true virtual addresses.
442: */
443: sz = (int)allocsys((caddr_t)0);
444:
445: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
446: panic("startup: no room for tables");
447: if (allocsys(v) - v != sz)
448: panic("startup: table size inconsistency");
449:
450: /*
451: * Grab the OBIO space that we hardwired in pmap_bootstrap
452: */
453: obiova = OBIO_START;
454: uvm_map(kernel_map, (vaddr_t *)&obiova, OBIO_SIZE,
455: NULL, UVM_UNKNOWN_OFFSET, 0,
456: UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
457: UVM_ADV_NORMAL, 0));
458: if (obiova != OBIO_START)
459: panic("obiova %lx: OBIO not free", obiova);
460:
461: /*
462: * Determine how many buffers to allocate.
463: * We allocate bufcachepercent% of memory for buffer space.
464: */
465: if (bufpages == 0)
466: bufpages = physmem * bufcachepercent / 100;
467:
468: /* Restrict to at most 25% filled kvm */
469: if (bufpages >
470: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
471: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
472: PAGE_SIZE / 4;
473:
474: /*
475: * Allocate a submap for exec arguments. This map effectively
476: * limits the number of processes exec'ing at any time.
477: */
478: minaddr = vm_map_min(kernel_map);
479: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
480: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
481:
482: /*
483: * Allocate map for physio.
484: */
485: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
486: VM_PHYS_SIZE, 0, FALSE, NULL);
487:
488: printf("avail mem = %ld (%d pages)\n", ptoa(uvmexp.free), uvmexp.free);
489:
490: /*
491: * Set up buffers, so they can be used to read disk labels.
492: */
493: bufinit();
494:
495: /*
496: * Initialize the autovectored interrupt list.
497: */
498: isrinit();
499:
500: /*
501: * Configure the system.
502: */
503: if (boothowto & RB_CONFIG) {
504: #ifdef BOOT_CONFIG
505: user_config();
506: #else
507: printf("kernel does not support -c; continuing..\n");
508: #endif
509: }
510: }
511:
512: /*
513: * Allocate space for system data structures. We are given
514: * a starting virtual address and we return a final virtual
515: * address; along the way we set each data structure pointer.
516: *
517: * We call allocsys() with 0 to find out how much space we want,
518: * allocate that much and fill it with zeroes, and then call
519: * allocsys() again with the correct base virtual address.
520: */
521: caddr_t
522: allocsys(v)
523: caddr_t v;
524: {
525:
526: #define valloc(name, type, num) \
527: v = (caddr_t)(((name) = (type *)v) + (num))
528:
529: #ifdef SYSVMSG
530: valloc(msgpool, char, msginfo.msgmax);
531: valloc(msgmaps, struct msgmap, msginfo.msgseg);
532: valloc(msghdrs, struct msg, msginfo.msgtql);
533: valloc(msqids, struct msqid_ds, msginfo.msgmni);
534: #endif
535:
536: return v;
537: }
538:
539: __dead void
540: boot(howto)
541: int howto;
542: {
543: /* take a snapshot before clobbering any registers */
544: if (curproc && curproc->p_addr)
545: savectx(curpcb);
546:
547: /* If system is cold, just halt. */
548: if (cold) {
549: /* (Unless the user explicitly asked for reboot.) */
550: if ((howto & RB_USERREQ) == 0)
551: howto |= RB_HALT;
552: goto haltsys;
553: }
554:
555: boothowto = howto;
556: if ((howto & RB_NOSYNC) == 0) {
557: vfs_shutdown();
558: /*
559: * If we've been adjusting the clock, the todr
560: * will be out of synch; adjust it now unless
561: * the system was sitting in ddb.
562: */
563: if ((howto & RB_TIMEBAD) == 0)
564: resettodr();
565: else
566: printf("WARNING: not updating battery clock\n");
567: }
568:
569: /* Disable interrupts. */
570: splhigh();
571:
572: /* If rebooting and a dump is requested, do it. */
573: if (howto & RB_DUMP)
574: dumpsys();
575:
576: haltsys:
577: /* Run any shutdown hooks. */
578: doshutdownhooks();
579:
580: /* Luna88k supports automatic powerdown */
581: if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
582: printf("attempting to power down...\n");
583: powerdown();
584: /* if failed, fall through. */
585: }
586:
587: if (howto & RB_HALT) {
588: printf("halted\n\n");
589: } else {
590: /* Reset all cpus, which causes reboot */
591: *((volatile unsigned *)0x6d000010) = 0;
592: }
593:
594: for (;;); /* to keep compiler happy, and me from going crazy */
595: /*NOTREACHED*/
596: }
597:
598: unsigned dumpmag = 0x8fca0101; /* magic number for savecore */
599: int dumpsize = 0; /* also for savecore */
600: long dumplo = 0;
601: cpu_kcore_hdr_t cpu_kcore_hdr;
602:
603: /*
604: * This is called by configure to set dumplo and dumpsize.
605: * Dumps always skip the first PAGE_SIZE of disk space
606: * in case there might be a disk label stored there.
607: * If there is extra space, put dump at the end to
608: * reduce the chance that swapping trashes it.
609: */
610: void
611: dumpconf(void)
612: {
613: int nblks; /* size of dump area */
614:
615: if (dumpdev == NODEV ||
616: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
617: return;
618: if (nblks <= ctod(1))
619: return;
620:
621: dumpsize = physmem;
622:
623: /* luna88k only uses a single segment. */
624: cpu_kcore_hdr.ram_segs[0].start = 0;
625: cpu_kcore_hdr.ram_segs[0].size = ctob(physmem);
626: cpu_kcore_hdr.cputype = cputyp;
627:
628: /*
629: * Don't dump on the first block
630: * in case the dump device includes a disk label.
631: */
632: if (dumplo < ctod(1))
633: dumplo = ctod(1);
634:
635: /* Put dump at end of partition, and make it fit. */
636: if (dumpsize + 1 > dtoc(nblks - dumplo))
637: dumpsize = dtoc(nblks - dumplo) - 1;
638: if (dumplo < nblks - ctod(dumpsize) - 1)
639: dumplo = nblks - ctod(dumpsize) - 1;
640: }
641:
642: /*
643: * Doadump comes here after turning off memory management and
644: * getting on the dump stack, either when called above, or by
645: * the auto-restart code.
646: */
647: void
648: dumpsys()
649: {
650: int maj;
651: int psize;
652: daddr64_t blkno; /* current block to write */
653: /* dump routine */
654: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
655: int pg; /* page being dumped */
656: paddr_t maddr; /* PA being dumped */
657: int error; /* error code from (*dump)() */
658: kcore_seg_t *kseg_p;
659: cpu_kcore_hdr_t *chdr_p;
660: char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
661:
662: extern int msgbufmapped;
663:
664: msgbufmapped = 0;
665:
666: /* Make sure dump device is valid. */
667: if (dumpdev == NODEV)
668: return;
669: if (dumpsize == 0) {
670: dumpconf();
671: if (dumpsize == 0)
672: return;
673: }
674: maj = major(dumpdev);
675: if (dumplo < 0) {
676: printf("\ndump to dev %u,%u not possible\n", maj,
677: minor(dumpdev));
678: return;
679: }
680: dump = bdevsw[maj].d_dump;
681: blkno = dumplo;
682:
683: printf("\ndumping to dev %u,%u offset %ld\n", maj,
684: minor(dumpdev), dumplo);
685:
686: /* Setup the dump header */
687: kseg_p = (kcore_seg_t *)dump_hdr;
688: chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
689: bzero(dump_hdr, sizeof(dump_hdr));
690:
691: CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
692: kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
693: *chdr_p = cpu_kcore_hdr;
694:
695: printf("dump ");
696: psize = (*bdevsw[maj].d_psize)(dumpdev);
697: if (psize == -1) {
698: printf("area unavailable\n");
699: return;
700: }
701:
702: /* Dump the header. */
703: error = (*dump)(dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
704: if (error != 0)
705: goto abort;
706:
707: maddr = (paddr_t)0;
708: for (pg = 0; pg < dumpsize; pg++) {
709: #define NPGMB (1024 * 1024 / PAGE_SIZE)
710: /* print out how many MBs we have dumped */
711: if (pg != 0 && (pg % NPGMB) == 0)
712: printf("%d ", pg / NPGMB);
713: #undef NPGMB
714: pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
715: VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
716:
717: error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
718: if (error == 0) {
719: maddr += PAGE_SIZE;
720: blkno += btodb(PAGE_SIZE);
721: } else
722: break;
723: }
724: abort:
725: switch (error) {
726: case 0:
727: printf("succeeded\n");
728: break;
729:
730: case ENXIO:
731: printf("device bad\n");
732: break;
733:
734: case EFAULT:
735: printf("device not ready\n");
736: break;
737:
738: case EINVAL:
739: printf("area improper\n");
740: break;
741:
742: case EIO:
743: printf("i/o error\n");
744: break;
745:
746: case EINTR:
747: printf("aborted from console\n");
748: break;
749:
750: default:
751: printf("error %d\n", error);
752: break;
753: }
754: }
755:
756: #ifdef MULTIPROCESSOR
757:
758: /*
759: * Secondary CPU early initialization routine.
760: * Determine CPU number and set it, then allocate the idle pcb (and stack).
761: *
762: * Running on a minimal stack here, with interrupts disabled; do nothing fancy.
763: */
764: void
765: secondary_pre_main()
766: {
767: struct cpu_info *ci;
768:
769: set_cpu_number(cmmu_cpu_number());
770: ci = curcpu();
771:
772: /*
773: * Setup CMMUs and translation tables (shared with the master cpu).
774: */
775: pmap_bootstrap_cpu(ci->ci_cpuid);
776:
777: /*
778: * Allocate UPAGES contiguous pages for the idle PCB and stack.
779: */
780: ci->ci_idle_pcb = (struct pcb *)uvm_km_zalloc(kernel_map, USPACE);
781: if (ci->ci_idle_pcb == NULL) {
782: printf("cpu%d: unable to allocate idle stack\n", ci->ci_cpuid);
783: }
784: }
785:
786: /*
787: * Further secondary CPU initialization.
788: *
789: * We are now running on our idle stack, with proper page tables.
790: * There is nothing to do but display some details about the CPU and its CMMUs.
791: */
792: void
793: secondary_main()
794: {
795: struct cpu_info *ci = curcpu();
796:
797: cpu_configuration_print(0);
798: ncpus++;
799:
800: microuptime(&ci->ci_schedstate.spc_runtime);
801:
802: /*
803: * Upon return, the secondary cpu bootstrap code in locore will
804: * enter the idle loop, waiting for some food to process on this
805: * processor.
806: */
807: }
808:
809: #endif /* MULTIPROCESSOR */
810:
811: /*
812: * Device interrupt handler for LUNA88K
813: */
814:
815: void
816: luna88k_ext_int(u_int v, struct trapframe *eframe)
817: {
818: int cpu = cpu_number();
819: unsigned int cur_mask, cur_int;
820: unsigned int level, old_spl;
821:
822: cur_mask = *int_mask_reg[cpu];
823: old_spl = luna88k_curspl[cpu];
824: eframe->tf_mask = old_spl;
825:
826: cur_int = cur_mask >> 29;
827:
828: if (cur_int == 0) {
829: /*
830: * Spurious interrupts - may be caused by debug output clearing
831: * serial port interrupts.
832: */
833: #ifdef DEBUG
834: printf("luna88k_ext_int(): Spurious interrupts?\n");
835: #endif
836: flush_pipeline();
837: goto out;
838: }
839:
840: uvmexp.intrs++;
841:
842: /*
843: * We want to service all interrupts marked in the IST register
844: * They are all valid because the mask would have prevented them
845: * from being generated otherwise. We will service them in order of
846: * priority.
847: */
848:
849: /* XXX: This is very rough. Should be considered more. (aoyama) */
850: do {
851: level = (cur_int > old_spl ? cur_int : old_spl);
852:
853: #ifdef DEBUG
854: if (level > 7 || (char)level < 0) {
855: panic("int level (%x) is not between 0 and 7", level);
856: }
857: #endif
858:
859: setipl(level);
860:
861: set_psr(get_psr() & ~PSR_IND);
862:
863: switch(cur_int) {
864: case CLOCK_INT_LEVEL:
865: clockintr((void *)eframe);
866: break;
867: case 5:
868: case 4:
869: case 3:
870: isrdispatch_autovec(cur_int);
871: break;
872: default:
873: printf("luna88k_ext_int(): level %d interrupt.\n", cur_int);
874: break;
875: }
876: } while ((cur_int = (*int_mask_reg[cpu]) >> 29) != 0);
877:
878: out:
879: /*
880: * process any remaining data access exceptions before
881: * returning to assembler
882: */
883: if (eframe->tf_dmt0 & DMT_VALID)
884: m88100_trap(T_DATAFLT, eframe);
885:
886: /*
887: * Disable interrupts before returning to assembler, the spl will
888: * be restored later.
889: */
890: set_psr(get_psr() | PSR_IND);
891: }
892:
893: int
894: cpu_exec_aout_makecmds(p, epp)
895: struct proc *p;
896: struct exec_package *epp;
897: {
898:
899: return (ENOEXEC);
900: }
901:
902: int
903: sys_sysarch(p, v, retval)
904: struct proc *p;
905: void *v;
906: register_t *retval;
907: {
908: #if 0
909: struct sys_sysarch_args /* {
910: syscallarg(int) op;
911: syscallarg(char *) parm;
912: } */ *uap = v;
913: #endif
914:
915: return (ENOSYS);
916: }
917:
918: /*
919: * machine dependent system variables.
920: */
921:
922: int
923: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
924: int *name;
925: u_int namelen;
926: void *oldp;
927: size_t *oldlenp;
928: void *newp;
929: size_t newlen;
930: struct proc *p;
931: {
932: dev_t consdev;
933:
934: /* all sysctl names are this level are terminal */
935: if (namelen != 1)
936: return (ENOTDIR); /* overloaded */
937:
938: switch (name[0]) {
939: case CPU_CONSDEV:
940: if (cn_tab != NULL)
941: consdev = cn_tab->cn_dev;
942: else
943: consdev = NODEV;
944: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
945: sizeof consdev));
946: default:
947: return (EOPNOTSUPP);
948: }
949: /*NOTREACHED*/
950: }
951:
952: /*
953: * Called from locore.S during boot,
954: * this is the first C code that's run.
955: */
956: void
957: luna88k_bootstrap()
958: {
959: extern int kernelstart;
960: extern struct consdev *cn_tab;
961: extern struct cmmu_p cmmu8820x;
962: extern char *end;
963: #ifndef MULTIPROCESSOR
964: cpuid_t master_cpu;
965: #endif
966: cpuid_t cpu;
967: extern void m8820x_initialize_cpu(cpuid_t);
968: extern void m8820x_set_sapr(cpuid_t, apr_t);
969: extern void cpu_boot_secondary_processors(void);
970:
971: cmmu = &cmmu8820x;
972:
973: /* clear and disable all interrupts */
974: *int_mask_reg[0] = 0;
975: *int_mask_reg[1] = 0;
976: *int_mask_reg[2] = 0;
977: *int_mask_reg[3] = 0;
978:
979: /* startup fake console driver. It will be replaced by consinit() */
980: cn_tab = &romttycons;
981:
982: uvmexp.pagesize = PAGE_SIZE;
983: uvm_setpagesize();
984:
985: first_addr = round_page((vaddr_t)&end); /* XXX temp until symbols */
986: last_addr = size_memory();
987: physmem = btoc(last_addr);
988:
989: setup_board_config();
990: master_cpu = cmmu_init();
991: set_cpu_number(master_cpu);
992:
993: m88100_apply_patches();
994:
995: /*
996: * Now that set_cpu_number() set us with a valid cpu_info pointer,
997: * we need to initialize p_addr and curpcb before autoconf, for the
998: * fault handler to behave properly [except for badaddr() faults,
999: * which can be taken care of without a valid curcpu()].
1000: */
1001: proc0.p_addr = proc0paddr;
1002: curproc = &proc0;
1003: curpcb = &proc0paddr->u_pcb;
1004:
1005: avail_start = first_addr;
1006: avail_end = last_addr;
1007:
1008: /*
1009: * Steal MSGBUFSIZE at the top of physical memory for msgbuf
1010: */
1011: avail_end -= round_page(MSGBUFSIZE);
1012:
1013: #ifdef DEBUG
1014: printf("LUNA88K boot: memory from 0x%x to 0x%x\n",
1015: avail_start, avail_end);
1016: #endif
1017: pmap_bootstrap((vaddr_t)trunc_page((unsigned)&kernelstart));
1018:
1019: /*
1020: * Tell the VM system about available physical memory.
1021: * luna88k only has one segment.
1022: */
1023: uvm_page_physload(atop(avail_start), atop(avail_end),
1024: atop(avail_start), atop(avail_end),VM_FREELIST_DEFAULT);
1025:
1026: /* Initialize the "u-area" pages. */
1027: bzero((caddr_t)curpcb, USPACE);
1028:
1029: /*
1030: * On the luna88k, secondary processors are not disabled while the
1031: * kernel is initializing. We just initialized the CMMUs tied to the
1032: * currently-running CPU; initialize the others with similar settings
1033: * as well, after calling pmap_bootstrap() above.
1034: */
1035: for (cpu = 0; cpu < max_cpus; cpu++) {
1036: if (cpu == master_cpu)
1037: continue;
1038: if (m88k_cpus[cpu].ci_alive == 0)
1039: continue;
1040: m8820x_initialize_cpu(cpu);
1041: cmmu_set_sapr(cpu, kernel_pmap->pm_apr);
1042: }
1043: /* Release the cpu_mutex */
1044: cpu_boot_secondary_processors();
1045:
1046: #ifdef DEBUG
1047: printf("leaving luna88k_bootstrap()\n");
1048: #endif
1049: }
1050:
1051: /*
1052: * Rom console routines:
1053: * Enables printing of boot messages before consinit().
1054: */
1055:
1056: #define __ROM_FUNC_TABLE ((int **)0x00001100)
1057: #define ROMGETC() (*(int (*)(void))__ROM_FUNC_TABLE[3])()
1058: #define ROMPUTC(x) (*(void (*)(int))__ROM_FUNC_TABLE[4])(x)
1059:
1060: void
1061: romttycnprobe(cp)
1062: struct consdev *cp;
1063: {
1064: cp->cn_dev = makedev(14, 0);
1065: cp->cn_pri = CN_NORMAL;
1066: }
1067:
1068: void
1069: romttycninit(cp)
1070: struct consdev *cp;
1071: {
1072: /* Nothing to do */
1073: }
1074:
1075: int
1076: romttycngetc(dev)
1077: dev_t dev;
1078: {
1079: int s, c;
1080:
1081: do {
1082: s = splhigh();
1083: c = ROMGETC();
1084: splx(s);
1085: } while (c == -1);
1086: return c;
1087: }
1088:
1089: void
1090: romttycnputc(dev, c)
1091: dev_t dev;
1092: int c;
1093: {
1094: int s;
1095:
1096: #if 0
1097: if ((char)c == '\n')
1098: ROMPUTC('\r');
1099: #endif
1100: s = splhigh();
1101: ROMPUTC(c);
1102: splx(s);
1103: }
1104:
1105: /* taken from NetBSD/luna68k */
1106: void
1107: microtime(tvp)
1108: register struct timeval *tvp;
1109: {
1110: int s = splclock();
1111: static struct timeval lasttime;
1112:
1113: *tvp = time;
1114: #ifdef notdef
1115: tvp->tv_usec += clkread();
1116: while (tvp->tv_usec >= 1000000) {
1117: tvp->tv_sec++;
1118: tvp->tv_usec -= 1000000;
1119: }
1120: #endif
1121: if (tvp->tv_sec == lasttime.tv_sec &&
1122: tvp->tv_usec <= lasttime.tv_usec &&
1123: (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
1124: tvp->tv_sec++;
1125: tvp->tv_usec -= 1000000;
1126: }
1127: lasttime = *tvp;
1128: splx(s);
1129: }
1130:
1131: /* powerdown */
1132:
1133: struct pio {
1134: volatile u_int8_t portA;
1135: volatile unsigned : 24;
1136: volatile u_int8_t portB;
1137: volatile unsigned : 24;
1138: volatile u_int8_t portC;
1139: volatile unsigned : 24;
1140: volatile u_int8_t cntrl;
1141: volatile unsigned : 24;
1142: };
1143:
1144: #define PIO1_POWER 0x04
1145:
1146: #define PIO1_ENABLE 0x01
1147: #define PIO1_DISABLE 0x00
1148:
1149: void
1150: powerdown(void)
1151: {
1152: struct pio *p1 = (struct pio *)OBIO_PIO1_BASE;
1153:
1154: DELAY(100000);
1155: p1->cntrl = (PIO1_POWER << 1) | PIO1_DISABLE;
1156: *(volatile u_int8_t *)&p1->portC;
1157: }
1158:
1159: /* Get data from FUSE ROM */
1160:
1161: void
1162: get_fuse_rom_data(void)
1163: {
1164: int i;
1165: struct fuse_rom_byte *p = (struct fuse_rom_byte *)FUSE_ROM_ADDR;
1166:
1167: for (i = 0; i < FUSE_ROM_BYTES; i++) {
1168: fuse_rom_data[i] =
1169: (char)((((p->h) >> 24) & 0x000000f0) |
1170: (((p->l) >> 28) & 0x0000000f));
1171: p++;
1172: }
1173: }
1174:
1175: /* Get data from NVRAM */
1176:
1177: void
1178: get_nvram_data(void)
1179: {
1180: int i, j;
1181: u_int8_t *page;
1182: char buf[NVSYMLEN], *data;
1183:
1184: if (machtype == LUNA_88K) {
1185: data = (char *)(NVRAM_ADDR + 0x80);
1186:
1187: for (i = 0; i < NNVSYM; i++) {
1188: for (j = 0; j < NVSYMLEN; j++) {
1189: buf[j] = *data;
1190: data += 4;
1191: }
1192: strlcpy(nvram[i].symbol, buf, sizeof(nvram[i].symbol));
1193:
1194: for (j = 0; j < NVVALLEN; j++) {
1195: buf[j] = *data;
1196: data += 4;
1197: }
1198: strlcpy(nvram[i].value, buf, sizeof(nvram[i].value));
1199: }
1200: } else if (machtype == LUNA_88K2) {
1201: page = (u_int8_t *)(NVRAM_ADDR_88K2 + 0x20);
1202:
1203: for (i = 0; i < NNVSYM; i++) {
1204: *page = (u_int8_t)i;
1205:
1206: data = (char *)NVRAM_ADDR_88K2;
1207: strlcpy(nvram[i].symbol, data, sizeof(nvram[i].symbol));
1208:
1209: data = (char *)(NVRAM_ADDR_88K2 + 0x10);
1210: strlcpy(nvram[i].value, data, sizeof(nvram[i].value));
1211: }
1212: }
1213: }
1214:
1215: char *
1216: nvram_by_symbol(symbol)
1217: char *symbol;
1218: {
1219: char *value;
1220: int i;
1221:
1222: value = NULL;
1223:
1224: for (i = 0; i < NNVSYM; i++) {
1225: if (strncmp(nvram[i].symbol, symbol, NVSYMLEN) == 0) {
1226: value = nvram[i].value;
1227: break;
1228: }
1229: }
1230:
1231: return value;
1232: }
1233:
1234: void
1235: setlevel(unsigned int level)
1236: {
1237: unsigned int set_value;
1238: int cpu = cpu_number();
1239:
1240: set_value = int_set_val[level];
1241:
1242: #ifdef MULTIPROCESSOR
1243: if (cpu != master_cpu)
1244: set_value &= INT_SLAVE_MASK;
1245: #endif
1246:
1247: *int_mask_reg[cpu] = set_value;
1248: luna88k_curspl[cpu] = level;
1249: }
1250:
1251: u_int
1252: getipl(void)
1253: {
1254: u_int curspl, psr;
1255:
1256: disable_interrupt(psr);
1257: curspl = luna88k_curspl[cpu_number()];
1258: set_psr(psr);
1259: return curspl;
1260: }
1261:
1262: unsigned
1263: setipl(unsigned level)
1264: {
1265: unsigned int curspl, psr;
1266:
1267: disable_interrupt(psr);
1268: curspl = luna88k_curspl[cpu_number()];
1269: setlevel(level);
1270:
1271: /*
1272: * The flush pipeline is required to make sure the above write gets
1273: * through the data pipe and to the hardware; otherwise, the next
1274: * bunch of instructions could execute at the wrong spl protection.
1275: */
1276: flush_pipeline();
1277:
1278: set_psr(psr);
1279: return curspl;
1280: }
1281:
1282: unsigned
1283: raiseipl(unsigned level)
1284: {
1285: unsigned int curspl, psr;
1286:
1287: disable_interrupt(psr);
1288: curspl = luna88k_curspl[cpu_number()];
1289: if (curspl < level)
1290: setlevel(level);
1291:
1292: /*
1293: * The flush pipeline is required to make sure the above write gets
1294: * through the data pipe and to the hardware; otherwise, the next
1295: * bunch of instructions could execute at the wrong spl protection.
1296: */
1297: flush_pipeline();
1298:
1299: set_psr(psr);
1300: return curspl;
1301: }
CVSweb