1 /* $Id: setup.c,v 1.57 2000/10/14 10:09:00 davem Exp $
2 * linux/arch/sparc64/kernel/setup.c
4 * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8 #include <linux/errno.h>
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
12 #include <linux/stddef.h>
13 #include <linux/unistd.h>
14 #include <linux/ptrace.h>
15 #include <linux/malloc.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>
23 #include <linux/kdev_t.h>
24 #include <linux/major.h>
25 #include <linux/string.h>
26 #include <linux/blk.h>
27 #include <linux/init.h>
28 #include <linux/inet.h>
29 #include <linux/console.h>
31 #include <asm/segment.h>
32 #include <asm/system.h>
34 #include <asm/processor.h>
35 #include <asm/oplib.h>
37 #include <asm/pgtable.h>
38 #include <asm/idprom.h>
40 #include <asm/starfire.h>
43 #include <net/ipconfig.h>
46 #undef PROM_DEBUG_CONSOLE
48 struct screen_info screen_info
= {
49 0, 0, /* orig-x, orig-y */
51 0, /* orig-video-page */
52 0, /* orig-video-mode */
53 128, /* orig-video-cols */
54 0, 0, 0, /* unused, ega_bx, unused */
55 54, /* orig-video-lines */
56 0, /* orig-video-isVGA */
57 16 /* orig-video-points */
60 /* Typing sync at the prom prompt calls the function pointed to by
61 * the sync callback which I set to the following function.
62 * This should sync all filesystems and return, for now it just
63 * prints out pretty messages and returns.
66 #if CONFIG_SUN_CONSOLE
67 void (*prom_palette
)(int);
69 asmlinkage
void sys_sync(void); /* it's really int */
72 prom_console_write(struct console
*con
, const char *s
, unsigned n
)
77 static struct console prom_console
= {
79 write
: prom_console_write
,
80 flags
: CON_CONSDEV
| CON_ENABLED
,
88 int prom_callback(long *args
)
90 struct console
*cons
, *saved_console
= NULL
;
96 if (!(cmd
= (char *)args
[0]))
100 cons
= console_drivers
;
102 unregister_console(cons
);
103 cons
->flags
&= ~(CON_PRINTBUFFER
);
104 cons
->next
= saved_console
;
105 saved_console
= cons
;
106 cons
= console_drivers
;
108 register_console(&prom_console
);
109 if (!strcmp(cmd
, "sync")) {
110 prom_printf("PROM `%s' command...\n", cmd
);
112 if(current
->pid
!= 0) {
118 args
[args
[1] + 3] = -1;
119 prom_printf("Returning to PROM\n");
120 } else if (!strcmp(cmd
, "va>tte-data")) {
121 unsigned long ctx
, va
;
122 unsigned long tte
= 0;
123 long res
= PROM_FALSE
;
129 * Find process owning ctx, lookup mapping.
131 struct task_struct
*p
;
132 struct mm_struct
*mm
= NULL
;
139 if (CTX_HWBITS(mm
->context
) == ctx
)
143 CTX_HWBITS(mm
->context
) != ctx
)
146 pgdp
= pgd_offset(mm
, va
);
149 pmdp
= pmd_offset(pgdp
, va
);
152 ptep
= pte_offset(pmdp
, va
);
153 if (!pte_present(*ptep
))
155 tte
= pte_val(*ptep
);
160 if ((va
>= KERNBASE
) && (va
< (KERNBASE
+ (4 * 1024 * 1024)))) {
161 /* Spitfire Errata #32 workaround */
162 __asm__
__volatile__("stxa %0, [%1] %2\n\t"
166 "r" (PRIMARY_CONTEXT
), "i" (ASI_DMMU
));
169 * Locked down tlb entry 63.
172 tte
= spitfire_get_dtlb_data(63);
177 if (va
< PGDIR_SIZE
) {
179 * vmalloc or prom_inherited mapping.
185 pgdp
= pgd_offset_k(va
);
188 pmdp
= pmd_offset(pgdp
, va
);
191 ptep
= pte_offset(pmdp
, va
);
192 if (!pte_present(*ptep
))
194 tte
= pte_val(*ptep
);
199 if (va
< PAGE_OFFSET
) {
206 if (va
& (1UL << 40)) {
211 tte
= (__pa(va
) & _PAGE_PADDR
) |
212 _PAGE_VALID
| _PAGE_SZ4MB
|
213 _PAGE_E
| _PAGE_P
| _PAGE_W
;
221 tte
= (__pa(va
) & _PAGE_PADDR
) |
222 _PAGE_VALID
| _PAGE_SZ4MB
|
223 _PAGE_CP
| _PAGE_CV
| _PAGE_P
| _PAGE_W
;
227 if (res
== PROM_TRUE
) {
229 args
[args
[1] + 3] = 0;
230 args
[args
[1] + 4] = res
;
231 args
[args
[1] + 5] = tte
;
234 args
[args
[1] + 3] = 0;
235 args
[args
[1] + 4] = res
;
237 } else if (!strcmp(cmd
, ".soft1")) {
241 prom_printf("%lx:\"%s%s%s%s%s\" ",
242 (tte
& _PAGE_SOFT
) >> 7,
243 tte
& _PAGE_MODIFIED
? "M" : "-",
244 tte
& _PAGE_ACCESSED
? "A" : "-",
245 tte
& _PAGE_READ
? "W" : "-",
246 tte
& _PAGE_WRITE
? "R" : "-",
247 tte
& _PAGE_PRESENT
? "P" : "-");
250 args
[args
[1] + 3] = 0;
251 args
[args
[1] + 4] = PROM_TRUE
;
252 } else if (!strcmp(cmd
, ".soft2")) {
256 prom_printf("%lx ", (tte
& _PAGE_SOFT2
) >> 50);
259 args
[args
[1] + 3] = 0;
260 args
[args
[1] + 4] = PROM_TRUE
;
262 prom_printf("unknown PROM `%s' command...\n", cmd
);
264 unregister_console(&prom_console
);
265 while (saved_console
) {
266 cons
= saved_console
;
267 saved_console
= cons
->next
;
268 register_console(cons
);
270 restore_flags(flags
);
274 extern void rs_kgdb_hook(int tty_num
); /* sparc/serial.c */
276 unsigned int boot_flags
= 0;
277 #define BOOTME_DEBUG 0x1
278 #define BOOTME_SINGLE 0x2
279 #define BOOTME_KGDB 0x4
281 #ifdef CONFIG_SUN_CONSOLE
282 static int console_fb __initdata
= 0;
285 /* Exported for mm/init.c:paging_init. */
286 unsigned long cmdline_memory_size
= 0;
288 #ifdef PROM_DEBUG_CONSOLE
289 static struct console prom_debug_console
= {
291 write
: prom_console_write
,
292 flags
: CON_PRINTBUFFER
,
297 /* XXX Implement this at some point... */
298 void kernel_enter_debugger(void)
302 int obp_system_intr(void)
304 if (boot_flags
& BOOTME_DEBUG
) {
305 printk("OBP: system interrupted\n");
313 * Process kernel command line switches that are specific to the
314 * SPARC or that require special low-level processing.
316 static void __init
process_switch(char c
)
320 boot_flags
|= BOOTME_DEBUG
;
323 boot_flags
|= BOOTME_SINGLE
;
326 prom_printf("boot_flags_init: Halt!\n");
330 printk("Unknown boot switch (-%c)\n", c
);
335 static void __init
boot_flags_init(char *commands
)
338 /* Move to the start of the next "argument". */
339 while (*commands
&& *commands
== ' ')
342 /* Process any command switches, otherwise skip it. */
343 if (*commands
== '\0')
345 else if (*commands
== '-') {
347 while (*commands
&& *commands
!= ' ')
348 process_switch(*commands
++);
349 } else if (strlen(commands
) >= 9
350 && !strncmp(commands
, "kgdb=tty", 8)) {
351 boot_flags
|= BOOTME_KGDB
;
352 switch (commands
[8]) {
353 #ifdef CONFIG_SUN_SERIAL
356 prom_printf("KGDB: Using serial line /dev/ttya.\n");
360 prom_printf("KGDB: Using serial line /dev/ttyb.\n");
364 printk("KGDB: Unknown tty line.\n");
365 boot_flags
&= ~BOOTME_KGDB
;
370 #if CONFIG_SUN_CONSOLE
371 if (!strncmp(commands
, "console=", 8)) {
373 if (!strncmp (commands
, "ttya", 4)) {
375 prom_printf ("Using /dev/ttya as console.\n");
376 } else if (!strncmp (commands
, "ttyb", 4)) {
378 prom_printf ("Using /dev/ttyb as console.\n");
379 #if defined(CONFIG_PROM_CONSOLE)
380 } else if (!strncmp (commands
, "prom", 4)) {
383 for (p
= commands
- 8; *p
&& *p
!= ' '; p
++)
385 conswitchp
= &prom_con
;
393 if (!strncmp(commands
, "mem=", 4)) {
395 * "mem=XXX[kKmM]" overrides the PROM-reported
398 cmdline_memory_size
= simple_strtoul(commands
+ 4,
400 if (*commands
== 'K' || *commands
== 'k') {
401 cmdline_memory_size
<<= 10;
403 } else if (*commands
=='M' || *commands
=='m') {
404 cmdline_memory_size
<<= 20;
408 while (*commands
&& *commands
!= ' ')
414 extern int prom_probe_memory(void);
415 extern unsigned long start
, end
;
416 extern void panic_setup(char *, int *);
418 extern unsigned short root_flags
;
419 extern unsigned short root_dev
;
420 extern unsigned short ram_flags
;
421 #define RAMDISK_IMAGE_START_MASK 0x07FF
422 #define RAMDISK_PROMPT_FLAG 0x8000
423 #define RAMDISK_LOAD_FLAG 0x4000
425 extern int root_mountflags
;
427 char saved_command_line
[256];
428 char reboot_command
[256];
430 extern unsigned long phys_base
;
432 static struct pt_regs fake_swapper_regs
= { { 0, }, 0, 0, 0, 0 };
434 void register_prom_callbacks(void)
436 prom_setcallback(prom_callback
);
437 prom_feval(": linux-va>tte-data 2 \" va>tte-data\" $callback drop ; "
438 "' linux-va>tte-data to va>tte-data");
439 prom_feval(": linux-.soft1 1 \" .soft1\" $callback 2drop ; "
440 "' linux-.soft1 to .soft1");
441 prom_feval(": linux-.soft2 1 \" .soft2\" $callback 2drop ; "
442 "' linux-.soft2 to .soft2");
445 extern void paging_init(void);
447 void __init
setup_arch(char **cmdline_p
)
449 extern int serial_console
; /* in console.c, of course */
450 unsigned long highest_paddr
;
453 /* Initialize PROM console and command line. */
454 *cmdline_p
= prom_getbootargs();
455 strcpy(saved_command_line
, *cmdline_p
);
457 #ifdef PROM_DEBUG_CONSOLE
458 register_console(&prom_debug_console
);
461 printk("ARCH: SUN4U\n");
463 #ifdef CONFIG_DUMMY_CONSOLE
464 conswitchp
= &dummy_con
;
465 #elif defined(CONFIG_PROM_CONSOLE)
466 conswitchp
= &prom_con
;
469 /* Work out if we are starfire early on */
472 boot_flags_init(*cmdline_p
);
475 (void) prom_probe_memory();
477 /* In paging_init() we tip off this value to see if we need
478 * to change init_mm.pgd to point to the real alias mapping.
480 phys_base
= 0xffffffffffffffffUL
;
482 for (i
= 0; sp_banks
[i
].num_bytes
!= 0; i
++) {
485 if (sp_banks
[i
].base_addr
< phys_base
)
486 phys_base
= sp_banks
[i
].base_addr
;
487 top
= sp_banks
[i
].base_addr
+
488 sp_banks
[i
].num_bytes
;
489 if (highest_paddr
< top
)
494 root_mountflags
&= ~MS_RDONLY
;
495 ROOT_DEV
= to_kdev_t(root_dev
);
496 #ifdef CONFIG_BLK_DEV_RAM
497 rd_image_start
= ram_flags
& RAMDISK_IMAGE_START_MASK
;
498 rd_prompt
= ((ram_flags
& RAMDISK_PROMPT_FLAG
) != 0);
499 rd_doload
= ((ram_flags
& RAMDISK_LOAD_FLAG
) != 0);
502 /* Due to stack alignment restrictions and assumptions... */
503 init_mm
.mmap
->vm_page_prot
= PAGE_SHARED
;
504 init_mm
.mmap
->vm_start
= PAGE_OFFSET
;
505 init_mm
.mmap
->vm_end
= PAGE_OFFSET
+ highest_paddr
;
506 init_task
.thread
.kregs
= &fake_swapper_regs
;
509 if (!ic_set_manually
) {
510 int chosen
= prom_finddevice ("/chosen");
513 cl
= prom_getintdefault (chosen
, "client-ip", 0);
514 sv
= prom_getintdefault (chosen
, "server-ip", 0);
515 gw
= prom_getintdefault (chosen
, "gateway-ip", 0);
521 #if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
522 ic_proto_enabled
= 0;
528 #ifdef CONFIG_SUN_SERIAL
529 switch (console_fb
) {
530 case 0: /* Let's get our io devices from prom */
532 int idev
= prom_query_input_device();
533 int odev
= prom_query_output_device();
534 if (idev
== PROMDEV_IKBD
&& odev
== PROMDEV_OSCREEN
) {
536 } else if (idev
== PROMDEV_ITTYA
&& odev
== PROMDEV_OTTYA
) {
538 } else if (idev
== PROMDEV_ITTYB
&& odev
== PROMDEV_OTTYB
) {
541 prom_printf("Inconsistent console: "
542 "input %d, output %d\n",
548 case 1: /* Force one of the framebuffers as console */
551 case 2: /* Force ttya as console */
554 case 3: /* Force ttyb as console */
567 asmlinkage
int sys_ioperm(unsigned long from
, unsigned long num
, int on
)
572 /* BUFFER is PAGE_SIZE bytes long. */
574 extern char *sparc_cpu_type
[];
575 extern char *sparc_fpu_type
[];
577 extern int smp_info(char *);
578 extern int smp_bogo(char *);
579 extern int mmu_info(char *);
581 int get_cpuinfo(char *buffer
)
583 int cpuid
=smp_processor_id();
586 len
= sprintf(buffer
,
589 "promlib\t\t: Version 3 Revision %d\n"
590 "prom\t\t: %d.%d.%d\n"
592 "ncpus probed\t: %d\n"
593 "ncpus active\t: %d\n"
595 "BogoMips\t: %lu.%02lu\n"
598 sparc_cpu_type
[cpuid
],
599 sparc_fpu_type
[cpuid
],
600 prom_rev
, prom_prev
>> 16, (prom_prev
>> 8) & 0xff, prom_prev
& 0xff,
601 linux_num_cpus
, smp_num_cpus
603 , loops_per_sec
/500000, (loops_per_sec
/5000) % 100
607 len
+= smp_bogo(buffer
+ len
);
609 len
+= mmu_info(buffer
+ len
);
611 len
+= smp_info(buffer
+ len
);
616 extern int zs_dumplog(char *);
617 len
+= zs_dumplog(buffer
+ len
);