diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sparc64/kernel/setup.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/sparc64/kernel/setup.c')
-rw-r--r-- | arch/sparc64/kernel/setup.c | 731 |
1 files changed, 731 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c new file mode 100644 index 000000000000..12c3d84b7460 --- /dev/null +++ b/arch/sparc64/kernel/setup.c | |||
@@ -0,0 +1,731 @@ | |||
1 | /* $Id: setup.c,v 1.72 2002/02/09 19:49:30 davem Exp $ | ||
2 | * linux/arch/sparc64/kernel/setup.c | ||
3 | * | ||
4 | * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) | ||
5 | * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | ||
6 | */ | ||
7 | |||
8 | #include <linux/errno.h> | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/unistd.h> | ||
14 | #include <linux/ptrace.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <asm/smp.h> | ||
17 | #include <linux/user.h> | ||
18 | #include <linux/a.out.h> | ||
19 | #include <linux/tty.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/seq_file.h> | ||
24 | #include <linux/syscalls.h> | ||
25 | #include <linux/kdev_t.h> | ||
26 | #include <linux/major.h> | ||
27 | #include <linux/string.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/inet.h> | ||
30 | #include <linux/console.h> | ||
31 | #include <linux/root_dev.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/cpu.h> | ||
34 | #include <linux/initrd.h> | ||
35 | |||
36 | #include <asm/segment.h> | ||
37 | #include <asm/system.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <asm/processor.h> | ||
40 | #include <asm/oplib.h> | ||
41 | #include <asm/page.h> | ||
42 | #include <asm/pgtable.h> | ||
43 | #include <asm/idprom.h> | ||
44 | #include <asm/head.h> | ||
45 | #include <asm/starfire.h> | ||
46 | #include <asm/mmu_context.h> | ||
47 | #include <asm/timer.h> | ||
48 | #include <asm/sections.h> | ||
49 | #include <asm/setup.h> | ||
50 | #include <asm/mmu.h> | ||
51 | |||
52 | #ifdef CONFIG_IP_PNP | ||
53 | #include <net/ipconfig.h> | ||
54 | #endif | ||
55 | |||
56 | struct screen_info screen_info = { | ||
57 | 0, 0, /* orig-x, orig-y */ | ||
58 | 0, /* unused */ | ||
59 | 0, /* orig-video-page */ | ||
60 | 0, /* orig-video-mode */ | ||
61 | 128, /* orig-video-cols */ | ||
62 | 0, 0, 0, /* unused, ega_bx, unused */ | ||
63 | 54, /* orig-video-lines */ | ||
64 | 0, /* orig-video-isVGA */ | ||
65 | 16 /* orig-video-points */ | ||
66 | }; | ||
67 | |||
68 | /* Typing sync at the prom prompt calls the function pointed to by | ||
69 | * the sync callback which I set to the following function. | ||
70 | * This should sync all filesystems and return, for now it just | ||
71 | * prints out pretty messages and returns. | ||
72 | */ | ||
73 | |||
74 | void (*prom_palette)(int); | ||
75 | void (*prom_keyboard)(void); | ||
76 | |||
77 | static void | ||
78 | prom_console_write(struct console *con, const char *s, unsigned n) | ||
79 | { | ||
80 | prom_write(s, n); | ||
81 | } | ||
82 | |||
83 | static struct console prom_console = { | ||
84 | .name = "prom", | ||
85 | .write = prom_console_write, | ||
86 | .flags = CON_CONSDEV | CON_ENABLED, | ||
87 | .index = -1, | ||
88 | }; | ||
89 | |||
90 | #define PROM_TRUE -1 | ||
91 | #define PROM_FALSE 0 | ||
92 | |||
93 | /* Pretty sick eh? */ | ||
94 | int prom_callback(long *args) | ||
95 | { | ||
96 | struct console *cons, *saved_console = NULL; | ||
97 | unsigned long flags; | ||
98 | char *cmd; | ||
99 | extern spinlock_t prom_entry_lock; | ||
100 | |||
101 | if (!args) | ||
102 | return -1; | ||
103 | if (!(cmd = (char *)args[0])) | ||
104 | return -1; | ||
105 | |||
106 | /* | ||
107 | * The callback can be invoked on the cpu that first dropped | ||
108 | * into prom_cmdline after taking the serial interrupt, or on | ||
109 | * a slave processor that was smp_captured() if the | ||
110 | * administrator has done a switch-cpu inside obp. In either | ||
111 | * case, the cpu is marked as in-interrupt. Drop IRQ locks. | ||
112 | */ | ||
113 | irq_exit(); | ||
114 | |||
115 | /* XXX Revisit the locking here someday. This is a debugging | ||
116 | * XXX feature so it isnt all that critical. -DaveM | ||
117 | */ | ||
118 | local_irq_save(flags); | ||
119 | |||
120 | spin_unlock(&prom_entry_lock); | ||
121 | cons = console_drivers; | ||
122 | while (cons) { | ||
123 | unregister_console(cons); | ||
124 | cons->flags &= ~(CON_PRINTBUFFER); | ||
125 | cons->next = saved_console; | ||
126 | saved_console = cons; | ||
127 | cons = console_drivers; | ||
128 | } | ||
129 | register_console(&prom_console); | ||
130 | if (!strcmp(cmd, "sync")) { | ||
131 | prom_printf("PROM `%s' command...\n", cmd); | ||
132 | show_free_areas(); | ||
133 | if (current->pid != 0) { | ||
134 | local_irq_enable(); | ||
135 | sys_sync(); | ||
136 | local_irq_disable(); | ||
137 | } | ||
138 | args[2] = 0; | ||
139 | args[args[1] + 3] = -1; | ||
140 | prom_printf("Returning to PROM\n"); | ||
141 | } else if (!strcmp(cmd, "va>tte-data")) { | ||
142 | unsigned long ctx, va; | ||
143 | unsigned long tte = 0; | ||
144 | long res = PROM_FALSE; | ||
145 | |||
146 | ctx = args[3]; | ||
147 | va = args[4]; | ||
148 | if (ctx) { | ||
149 | /* | ||
150 | * Find process owning ctx, lookup mapping. | ||
151 | */ | ||
152 | struct task_struct *p; | ||
153 | struct mm_struct *mm = NULL; | ||
154 | pgd_t *pgdp; | ||
155 | pud_t *pudp; | ||
156 | pmd_t *pmdp; | ||
157 | pte_t *ptep; | ||
158 | |||
159 | for_each_process(p) { | ||
160 | mm = p->mm; | ||
161 | if (CTX_NRBITS(mm->context) == ctx) | ||
162 | break; | ||
163 | } | ||
164 | if (!mm || | ||
165 | CTX_NRBITS(mm->context) != ctx) | ||
166 | goto done; | ||
167 | |||
168 | pgdp = pgd_offset(mm, va); | ||
169 | if (pgd_none(*pgdp)) | ||
170 | goto done; | ||
171 | pudp = pud_offset(pgdp, va); | ||
172 | if (pud_none(*pudp)) | ||
173 | goto done; | ||
174 | pmdp = pmd_offset(pudp, va); | ||
175 | if (pmd_none(*pmdp)) | ||
176 | goto done; | ||
177 | |||
178 | /* Preemption implicitly disabled by virtue of | ||
179 | * being called from inside OBP. | ||
180 | */ | ||
181 | ptep = pte_offset_map(pmdp, va); | ||
182 | if (pte_present(*ptep)) { | ||
183 | tte = pte_val(*ptep); | ||
184 | res = PROM_TRUE; | ||
185 | } | ||
186 | pte_unmap(ptep); | ||
187 | goto done; | ||
188 | } | ||
189 | |||
190 | if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) { | ||
191 | unsigned long kernel_pctx = 0; | ||
192 | |||
193 | if (tlb_type == cheetah_plus) | ||
194 | kernel_pctx |= (CTX_CHEETAH_PLUS_NUC | | ||
195 | CTX_CHEETAH_PLUS_CTX0); | ||
196 | |||
197 | /* Spitfire Errata #32 workaround */ | ||
198 | __asm__ __volatile__("stxa %0, [%1] %2\n\t" | ||
199 | "flush %%g6" | ||
200 | : /* No outputs */ | ||
201 | : "r" (kernel_pctx), | ||
202 | "r" (PRIMARY_CONTEXT), | ||
203 | "i" (ASI_DMMU)); | ||
204 | |||
205 | /* | ||
206 | * Locked down tlb entry. | ||
207 | */ | ||
208 | |||
209 | if (tlb_type == spitfire) | ||
210 | tte = spitfire_get_dtlb_data(SPITFIRE_HIGHEST_LOCKED_TLBENT); | ||
211 | else if (tlb_type == cheetah || tlb_type == cheetah_plus) | ||
212 | tte = cheetah_get_ldtlb_data(CHEETAH_HIGHEST_LOCKED_TLBENT); | ||
213 | |||
214 | res = PROM_TRUE; | ||
215 | goto done; | ||
216 | } | ||
217 | |||
218 | if (va < PGDIR_SIZE) { | ||
219 | /* | ||
220 | * vmalloc or prom_inherited mapping. | ||
221 | */ | ||
222 | pgd_t *pgdp; | ||
223 | pud_t *pudp; | ||
224 | pmd_t *pmdp; | ||
225 | pte_t *ptep; | ||
226 | int error; | ||
227 | |||
228 | if ((va >= LOW_OBP_ADDRESS) && (va < HI_OBP_ADDRESS)) { | ||
229 | tte = prom_virt_to_phys(va, &error); | ||
230 | if (!error) | ||
231 | res = PROM_TRUE; | ||
232 | goto done; | ||
233 | } | ||
234 | pgdp = pgd_offset_k(va); | ||
235 | if (pgd_none(*pgdp)) | ||
236 | goto done; | ||
237 | pudp = pud_offset(pgdp, va); | ||
238 | if (pud_none(*pudp)) | ||
239 | goto done; | ||
240 | pmdp = pmd_offset(pudp, va); | ||
241 | if (pmd_none(*pmdp)) | ||
242 | goto done; | ||
243 | |||
244 | /* Preemption implicitly disabled by virtue of | ||
245 | * being called from inside OBP. | ||
246 | */ | ||
247 | ptep = pte_offset_kernel(pmdp, va); | ||
248 | if (pte_present(*ptep)) { | ||
249 | tte = pte_val(*ptep); | ||
250 | res = PROM_TRUE; | ||
251 | } | ||
252 | goto done; | ||
253 | } | ||
254 | |||
255 | if (va < PAGE_OFFSET) { | ||
256 | /* | ||
257 | * No mappings here. | ||
258 | */ | ||
259 | goto done; | ||
260 | } | ||
261 | |||
262 | if (va & (1UL << 40)) { | ||
263 | /* | ||
264 | * I/O page. | ||
265 | */ | ||
266 | |||
267 | tte = (__pa(va) & _PAGE_PADDR) | | ||
268 | _PAGE_VALID | _PAGE_SZ4MB | | ||
269 | _PAGE_E | _PAGE_P | _PAGE_W; | ||
270 | res = PROM_TRUE; | ||
271 | goto done; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Normal page. | ||
276 | */ | ||
277 | tte = (__pa(va) & _PAGE_PADDR) | | ||
278 | _PAGE_VALID | _PAGE_SZ4MB | | ||
279 | _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W; | ||
280 | res = PROM_TRUE; | ||
281 | |||
282 | done: | ||
283 | if (res == PROM_TRUE) { | ||
284 | args[2] = 3; | ||
285 | args[args[1] + 3] = 0; | ||
286 | args[args[1] + 4] = res; | ||
287 | args[args[1] + 5] = tte; | ||
288 | } else { | ||
289 | args[2] = 2; | ||
290 | args[args[1] + 3] = 0; | ||
291 | args[args[1] + 4] = res; | ||
292 | } | ||
293 | } else if (!strcmp(cmd, ".soft1")) { | ||
294 | unsigned long tte; | ||
295 | |||
296 | tte = args[3]; | ||
297 | prom_printf("%lx:\"%s%s%s%s%s\" ", | ||
298 | (tte & _PAGE_SOFT) >> 7, | ||
299 | tte & _PAGE_MODIFIED ? "M" : "-", | ||
300 | tte & _PAGE_ACCESSED ? "A" : "-", | ||
301 | tte & _PAGE_READ ? "W" : "-", | ||
302 | tte & _PAGE_WRITE ? "R" : "-", | ||
303 | tte & _PAGE_PRESENT ? "P" : "-"); | ||
304 | |||
305 | args[2] = 2; | ||
306 | args[args[1] + 3] = 0; | ||
307 | args[args[1] + 4] = PROM_TRUE; | ||
308 | } else if (!strcmp(cmd, ".soft2")) { | ||
309 | unsigned long tte; | ||
310 | |||
311 | tte = args[3]; | ||
312 | prom_printf("%lx ", (tte & 0x07FC000000000000UL) >> 50); | ||
313 | |||
314 | args[2] = 2; | ||
315 | args[args[1] + 3] = 0; | ||
316 | args[args[1] + 4] = PROM_TRUE; | ||
317 | } else { | ||
318 | prom_printf("unknown PROM `%s' command...\n", cmd); | ||
319 | } | ||
320 | unregister_console(&prom_console); | ||
321 | while (saved_console) { | ||
322 | cons = saved_console; | ||
323 | saved_console = cons->next; | ||
324 | register_console(cons); | ||
325 | } | ||
326 | spin_lock(&prom_entry_lock); | ||
327 | local_irq_restore(flags); | ||
328 | |||
329 | /* | ||
330 | * Restore in-interrupt status for a resume from obp. | ||
331 | */ | ||
332 | irq_enter(); | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | unsigned int boot_flags = 0; | ||
337 | #define BOOTME_DEBUG 0x1 | ||
338 | #define BOOTME_SINGLE 0x2 | ||
339 | |||
340 | /* Exported for mm/init.c:paging_init. */ | ||
341 | unsigned long cmdline_memory_size = 0; | ||
342 | |||
343 | static struct console prom_debug_console = { | ||
344 | .name = "debug", | ||
345 | .write = prom_console_write, | ||
346 | .flags = CON_PRINTBUFFER, | ||
347 | .index = -1, | ||
348 | }; | ||
349 | |||
350 | /* XXX Implement this at some point... */ | ||
351 | void kernel_enter_debugger(void) | ||
352 | { | ||
353 | } | ||
354 | |||
355 | int obp_system_intr(void) | ||
356 | { | ||
357 | if (boot_flags & BOOTME_DEBUG) { | ||
358 | printk("OBP: system interrupted\n"); | ||
359 | prom_halt(); | ||
360 | return 1; | ||
361 | } | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * Process kernel command line switches that are specific to the | ||
367 | * SPARC or that require special low-level processing. | ||
368 | */ | ||
369 | static void __init process_switch(char c) | ||
370 | { | ||
371 | switch (c) { | ||
372 | case 'd': | ||
373 | boot_flags |= BOOTME_DEBUG; | ||
374 | break; | ||
375 | case 's': | ||
376 | boot_flags |= BOOTME_SINGLE; | ||
377 | break; | ||
378 | case 'h': | ||
379 | prom_printf("boot_flags_init: Halt!\n"); | ||
380 | prom_halt(); | ||
381 | break; | ||
382 | case 'p': | ||
383 | /* Use PROM debug console. */ | ||
384 | register_console(&prom_debug_console); | ||
385 | break; | ||
386 | default: | ||
387 | printk("Unknown boot switch (-%c)\n", c); | ||
388 | break; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | static void __init process_console(char *commands) | ||
393 | { | ||
394 | serial_console = 0; | ||
395 | commands += 8; | ||
396 | /* Linux-style serial */ | ||
397 | if (!strncmp(commands, "ttyS", 4)) | ||
398 | serial_console = simple_strtoul(commands + 4, NULL, 10) + 1; | ||
399 | else if (!strncmp(commands, "tty", 3)) { | ||
400 | char c = *(commands + 3); | ||
401 | /* Solaris-style serial */ | ||
402 | if (c == 'a' || c == 'b') { | ||
403 | serial_console = c - 'a' + 1; | ||
404 | prom_printf ("Using /dev/tty%c as console.\n", c); | ||
405 | } | ||
406 | /* else Linux-style fbcon, not serial */ | ||
407 | } | ||
408 | #if defined(CONFIG_PROM_CONSOLE) | ||
409 | if (!strncmp(commands, "prom", 4)) { | ||
410 | char *p; | ||
411 | |||
412 | for (p = commands - 8; *p && *p != ' '; p++) | ||
413 | *p = ' '; | ||
414 | conswitchp = &prom_con; | ||
415 | } | ||
416 | #endif | ||
417 | } | ||
418 | |||
419 | static void __init boot_flags_init(char *commands) | ||
420 | { | ||
421 | while (*commands) { | ||
422 | /* Move to the start of the next "argument". */ | ||
423 | while (*commands && *commands == ' ') | ||
424 | commands++; | ||
425 | |||
426 | /* Process any command switches, otherwise skip it. */ | ||
427 | if (*commands == '\0') | ||
428 | break; | ||
429 | if (*commands == '-') { | ||
430 | commands++; | ||
431 | while (*commands && *commands != ' ') | ||
432 | process_switch(*commands++); | ||
433 | continue; | ||
434 | } | ||
435 | if (!strncmp(commands, "console=", 8)) { | ||
436 | process_console(commands); | ||
437 | } else if (!strncmp(commands, "mem=", 4)) { | ||
438 | /* | ||
439 | * "mem=XXX[kKmM]" overrides the PROM-reported | ||
440 | * memory size. | ||
441 | */ | ||
442 | cmdline_memory_size = simple_strtoul(commands + 4, | ||
443 | &commands, 0); | ||
444 | if (*commands == 'K' || *commands == 'k') { | ||
445 | cmdline_memory_size <<= 10; | ||
446 | commands++; | ||
447 | } else if (*commands=='M' || *commands=='m') { | ||
448 | cmdline_memory_size <<= 20; | ||
449 | commands++; | ||
450 | } | ||
451 | } | ||
452 | while (*commands && *commands != ' ') | ||
453 | commands++; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | extern int prom_probe_memory(void); | ||
458 | extern unsigned long start, end; | ||
459 | extern void panic_setup(char *, int *); | ||
460 | |||
461 | extern unsigned short root_flags; | ||
462 | extern unsigned short root_dev; | ||
463 | extern unsigned short ram_flags; | ||
464 | #define RAMDISK_IMAGE_START_MASK 0x07FF | ||
465 | #define RAMDISK_PROMPT_FLAG 0x8000 | ||
466 | #define RAMDISK_LOAD_FLAG 0x4000 | ||
467 | |||
468 | extern int root_mountflags; | ||
469 | |||
470 | char reboot_command[COMMAND_LINE_SIZE]; | ||
471 | |||
472 | static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 }; | ||
473 | |||
474 | void register_prom_callbacks(void) | ||
475 | { | ||
476 | prom_setcallback(prom_callback); | ||
477 | prom_feval(": linux-va>tte-data 2 \" va>tte-data\" $callback drop ; " | ||
478 | "' linux-va>tte-data to va>tte-data"); | ||
479 | prom_feval(": linux-.soft1 1 \" .soft1\" $callback 2drop ; " | ||
480 | "' linux-.soft1 to .soft1"); | ||
481 | prom_feval(": linux-.soft2 1 \" .soft2\" $callback 2drop ; " | ||
482 | "' linux-.soft2 to .soft2"); | ||
483 | } | ||
484 | |||
485 | extern void paging_init(void); | ||
486 | |||
487 | void __init setup_arch(char **cmdline_p) | ||
488 | { | ||
489 | unsigned long highest_paddr; | ||
490 | int i; | ||
491 | |||
492 | /* Initialize PROM console and command line. */ | ||
493 | *cmdline_p = prom_getbootargs(); | ||
494 | strcpy(saved_command_line, *cmdline_p); | ||
495 | |||
496 | printk("ARCH: SUN4U\n"); | ||
497 | |||
498 | #ifdef CONFIG_DUMMY_CONSOLE | ||
499 | conswitchp = &dummy_con; | ||
500 | #elif defined(CONFIG_PROM_CONSOLE) | ||
501 | conswitchp = &prom_con; | ||
502 | #endif | ||
503 | |||
504 | #ifdef CONFIG_SMP | ||
505 | i = (unsigned long)&irq_stat[1] - (unsigned long)&irq_stat[0]; | ||
506 | if ((i == SMP_CACHE_BYTES) || (i == (2 * SMP_CACHE_BYTES))) { | ||
507 | extern unsigned int irqsz_patchme[1]; | ||
508 | irqsz_patchme[0] |= ((i == SMP_CACHE_BYTES) ? SMP_CACHE_BYTES_SHIFT : \ | ||
509 | SMP_CACHE_BYTES_SHIFT + 1); | ||
510 | flushi((long)&irqsz_patchme[0]); | ||
511 | } else { | ||
512 | prom_printf("Unexpected size of irq_stat[] elements\n"); | ||
513 | prom_halt(); | ||
514 | } | ||
515 | #endif | ||
516 | /* Work out if we are starfire early on */ | ||
517 | check_if_starfire(); | ||
518 | |||
519 | boot_flags_init(*cmdline_p); | ||
520 | |||
521 | idprom_init(); | ||
522 | (void) prom_probe_memory(); | ||
523 | |||
524 | /* In paging_init() we tip off this value to see if we need | ||
525 | * to change init_mm.pgd to point to the real alias mapping. | ||
526 | */ | ||
527 | phys_base = 0xffffffffffffffffUL; | ||
528 | highest_paddr = 0UL; | ||
529 | for (i = 0; sp_banks[i].num_bytes != 0; i++) { | ||
530 | unsigned long top; | ||
531 | |||
532 | if (sp_banks[i].base_addr < phys_base) | ||
533 | phys_base = sp_banks[i].base_addr; | ||
534 | top = sp_banks[i].base_addr + | ||
535 | sp_banks[i].num_bytes; | ||
536 | if (highest_paddr < top) | ||
537 | highest_paddr = top; | ||
538 | } | ||
539 | pfn_base = phys_base >> PAGE_SHIFT; | ||
540 | |||
541 | switch (tlb_type) { | ||
542 | default: | ||
543 | case spitfire: | ||
544 | kern_base = spitfire_get_itlb_data(sparc64_highest_locked_tlbent()); | ||
545 | kern_base &= _PAGE_PADDR_SF; | ||
546 | break; | ||
547 | |||
548 | case cheetah: | ||
549 | case cheetah_plus: | ||
550 | kern_base = cheetah_get_litlb_data(sparc64_highest_locked_tlbent()); | ||
551 | kern_base &= _PAGE_PADDR; | ||
552 | break; | ||
553 | }; | ||
554 | |||
555 | kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; | ||
556 | |||
557 | if (!root_flags) | ||
558 | root_mountflags &= ~MS_RDONLY; | ||
559 | ROOT_DEV = old_decode_dev(root_dev); | ||
560 | #ifdef CONFIG_BLK_DEV_INITRD | ||
561 | rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; | ||
562 | rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0); | ||
563 | rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); | ||
564 | #endif | ||
565 | |||
566 | init_task.thread_info->kregs = &fake_swapper_regs; | ||
567 | |||
568 | #ifdef CONFIG_IP_PNP | ||
569 | if (!ic_set_manually) { | ||
570 | int chosen = prom_finddevice ("/chosen"); | ||
571 | u32 cl, sv, gw; | ||
572 | |||
573 | cl = prom_getintdefault (chosen, "client-ip", 0); | ||
574 | sv = prom_getintdefault (chosen, "server-ip", 0); | ||
575 | gw = prom_getintdefault (chosen, "gateway-ip", 0); | ||
576 | if (cl && sv) { | ||
577 | ic_myaddr = cl; | ||
578 | ic_servaddr = sv; | ||
579 | if (gw) | ||
580 | ic_gateway = gw; | ||
581 | #if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP) | ||
582 | ic_proto_enabled = 0; | ||
583 | #endif | ||
584 | } | ||
585 | } | ||
586 | #endif | ||
587 | |||
588 | paging_init(); | ||
589 | } | ||
590 | |||
591 | static int __init set_preferred_console(void) | ||
592 | { | ||
593 | int idev, odev; | ||
594 | |||
595 | /* The user has requested a console so this is already set up. */ | ||
596 | if (serial_console >= 0) | ||
597 | return -EBUSY; | ||
598 | |||
599 | idev = prom_query_input_device(); | ||
600 | odev = prom_query_output_device(); | ||
601 | if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { | ||
602 | serial_console = 0; | ||
603 | } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { | ||
604 | serial_console = 1; | ||
605 | } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { | ||
606 | serial_console = 2; | ||
607 | } else { | ||
608 | prom_printf("Inconsistent console: " | ||
609 | "input %d, output %d\n", | ||
610 | idev, odev); | ||
611 | prom_halt(); | ||
612 | } | ||
613 | |||
614 | if (serial_console) | ||
615 | return add_preferred_console("ttyS", serial_console - 1, NULL); | ||
616 | |||
617 | return -ENODEV; | ||
618 | } | ||
619 | console_initcall(set_preferred_console); | ||
620 | |||
621 | /* BUFFER is PAGE_SIZE bytes long. */ | ||
622 | |||
623 | extern char *sparc_cpu_type; | ||
624 | extern char *sparc_fpu_type; | ||
625 | |||
626 | extern void smp_info(struct seq_file *); | ||
627 | extern void smp_bogo(struct seq_file *); | ||
628 | extern void mmu_info(struct seq_file *); | ||
629 | |||
630 | static int show_cpuinfo(struct seq_file *m, void *__unused) | ||
631 | { | ||
632 | seq_printf(m, | ||
633 | "cpu\t\t: %s\n" | ||
634 | "fpu\t\t: %s\n" | ||
635 | "promlib\t\t: Version 3 Revision %d\n" | ||
636 | "prom\t\t: %d.%d.%d\n" | ||
637 | "type\t\t: sun4u\n" | ||
638 | "ncpus probed\t: %ld\n" | ||
639 | "ncpus active\t: %ld\n" | ||
640 | #ifndef CONFIG_SMP | ||
641 | "Cpu0Bogo\t: %lu.%02lu\n" | ||
642 | "Cpu0ClkTck\t: %016lx\n" | ||
643 | #endif | ||
644 | , | ||
645 | sparc_cpu_type, | ||
646 | sparc_fpu_type, | ||
647 | prom_rev, | ||
648 | prom_prev >> 16, | ||
649 | (prom_prev >> 8) & 0xff, | ||
650 | prom_prev & 0xff, | ||
651 | (long)num_possible_cpus(), | ||
652 | (long)num_online_cpus() | ||
653 | #ifndef CONFIG_SMP | ||
654 | , cpu_data(0).udelay_val/(500000/HZ), | ||
655 | (cpu_data(0).udelay_val/(5000/HZ)) % 100, | ||
656 | cpu_data(0).clock_tick | ||
657 | #endif | ||
658 | ); | ||
659 | #ifdef CONFIG_SMP | ||
660 | smp_bogo(m); | ||
661 | #endif | ||
662 | mmu_info(m); | ||
663 | #ifdef CONFIG_SMP | ||
664 | smp_info(m); | ||
665 | #endif | ||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
670 | { | ||
671 | /* The pointer we are returning is arbitrary, | ||
672 | * it just has to be non-NULL and not IS_ERR | ||
673 | * in the success case. | ||
674 | */ | ||
675 | return *pos == 0 ? &c_start : NULL; | ||
676 | } | ||
677 | |||
678 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
679 | { | ||
680 | ++*pos; | ||
681 | return c_start(m, pos); | ||
682 | } | ||
683 | |||
684 | static void c_stop(struct seq_file *m, void *v) | ||
685 | { | ||
686 | } | ||
687 | |||
688 | struct seq_operations cpuinfo_op = { | ||
689 | .start =c_start, | ||
690 | .next = c_next, | ||
691 | .stop = c_stop, | ||
692 | .show = show_cpuinfo, | ||
693 | }; | ||
694 | |||
695 | extern int stop_a_enabled; | ||
696 | |||
697 | void sun_do_break(void) | ||
698 | { | ||
699 | if (!stop_a_enabled) | ||
700 | return; | ||
701 | |||
702 | prom_printf("\n"); | ||
703 | flush_user_windows(); | ||
704 | |||
705 | prom_cmdline(); | ||
706 | } | ||
707 | |||
708 | int serial_console = -1; | ||
709 | int stop_a_enabled = 1; | ||
710 | |||
711 | static int __init topology_init(void) | ||
712 | { | ||
713 | int i, err; | ||
714 | |||
715 | err = -ENOMEM; | ||
716 | for (i = 0; i < NR_CPUS; i++) { | ||
717 | if (cpu_possible(i)) { | ||
718 | struct cpu *p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
719 | |||
720 | if (p) { | ||
721 | memset(p, 0, sizeof(*p)); | ||
722 | register_cpu(p, i, NULL); | ||
723 | err = 0; | ||
724 | } | ||
725 | } | ||
726 | } | ||
727 | |||
728 | return err; | ||
729 | } | ||
730 | |||
731 | subsys_initcall(topology_init); | ||