Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / arch / sparc / kernel / setup.c
blob2a0fe9a2769f972b8aff98660d88bd23469b89e8
1 /* $Id: setup.c,v 1.120 2000/10/14 10:09:00 davem Exp $
2 * linux/arch/sparc/kernel/setup.c
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5 */
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/mm.h>
11 #include <linux/stddef.h>
12 #include <linux/unistd.h>
13 #include <linux/ptrace.h>
14 #include <linux/malloc.h>
15 #include <asm/smp.h>
16 #include <linux/user.h>
17 #include <linux/a.out.h>
18 #include <linux/tty.h>
19 #include <linux/delay.h>
20 #include <linux/config.h>
21 #include <linux/fs.h>
22 #include <linux/kdev_t.h>
23 #include <linux/major.h>
24 #include <linux/string.h>
25 #include <linux/blk.h>
26 #include <linux/init.h>
27 #include <linux/interrupt.h>
28 #include <linux/console.h>
29 #include <linux/spinlock.h>
31 #include <asm/segment.h>
32 #include <asm/system.h>
33 #include <asm/io.h>
34 #include <asm/kgdb.h>
35 #include <asm/processor.h>
36 #include <asm/oplib.h>
37 #include <asm/page.h>
38 #include <asm/pgtable.h>
39 #include <asm/traps.h>
40 #include <asm/vaddrs.h>
41 #include <asm/kdebug.h>
42 #include <asm/mbus.h>
43 #include <asm/idprom.h>
44 #include <asm/softirq.h>
45 #include <asm/hardirq.h>
46 #include <asm/machines.h>
48 #undef PROM_DEBUG_CONSOLE
50 struct screen_info screen_info = {
51 0, 0, /* orig-x, orig-y */
52 0, /* unused */
53 0, /* orig-video-page */
54 0, /* orig-video-mode */
55 128, /* orig-video-cols */
56 0,0,0, /* ega_ax, ega_bx, ega_cx */
57 54, /* orig-video-lines */
58 0, /* orig-video-isVGA */
59 16 /* orig-video-points */
62 unsigned int phys_bytes_of_ram, end_of_phys_memory;
64 /* Typing sync at the prom prompt calls the function pointed to by
65 * romvec->pv_synchook which I set to the following function.
66 * This should sync all filesystems and return, for now it just
67 * prints out pretty messages and returns.
70 extern unsigned long trapbase;
71 extern int serial_console;
72 extern void breakpoint(void);
73 #if CONFIG_SUN_CONSOLE
74 void (*prom_palette)(int);
75 #endif
76 asmlinkage void sys_sync(void); /* it's really int */
78 /* Pretty sick eh? */
79 void prom_sync_me(void)
81 unsigned long prom_tbr, flags;
83 save_and_cli(flags);
84 __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (prom_tbr));
85 __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
86 "nop\n\t"
87 "nop\n\t"
88 "nop\n\t" : : "r" (&trapbase));
90 #ifdef CONFIG_SUN_CONSOLE
91 if (prom_palette)
92 prom_palette(1);
93 #endif
94 prom_printf("PROM SYNC COMMAND...\n");
95 show_free_areas();
96 if(current->pid != 0) {
97 sti();
98 sys_sync();
99 cli();
101 prom_printf("Returning to prom\n");
103 __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
104 "nop\n\t"
105 "nop\n\t"
106 "nop\n\t" : : "r" (prom_tbr));
107 restore_flags(flags);
109 return;
112 extern void rs_kgdb_hook(int tty_num); /* sparc/serial.c */
114 unsigned int boot_flags;
115 #define BOOTME_DEBUG 0x1
116 #define BOOTME_SINGLE 0x2
117 #define BOOTME_KGDBA 0x4
118 #define BOOTME_KGDBB 0x8
119 #define BOOTME_KGDB 0xc
121 #ifdef CONFIG_SUN_CONSOLE
122 static int console_fb = 0;
123 #endif
125 /* Exported for mm/init.c:paging_init. */
126 unsigned long cmdline_memory_size __initdata = 0;
128 void kernel_enter_debugger(void)
130 if (boot_flags & BOOTME_KGDB) {
131 printk("KGDB: Entered\n");
132 breakpoint();
136 int obp_system_intr(void)
138 if (boot_flags & BOOTME_KGDB) {
139 printk("KGDB: system interrupted\n");
140 breakpoint();
141 return 1;
143 if (boot_flags & BOOTME_DEBUG) {
144 printk("OBP: system interrupted\n");
145 prom_halt();
146 return 1;
148 return 0;
152 * Process kernel command line switches that are specific to the
153 * SPARC or that require special low-level processing.
155 static void __init process_switch(char c)
157 switch (c) {
158 case 'd':
159 boot_flags |= BOOTME_DEBUG;
160 break;
161 case 's':
162 boot_flags |= BOOTME_SINGLE;
163 break;
164 case 'h':
165 prom_printf("boot_flags_init: Halt!\n");
166 halt();
167 break;
168 default:
169 printk("Unknown boot switch (-%c)\n", c);
170 break;
174 static void __init boot_flags_init(char *commands)
176 while (*commands) {
177 /* Move to the start of the next "argument". */
178 while (*commands && *commands == ' ')
179 commands++;
181 /* Process any command switches, otherwise skip it. */
182 if (*commands == '\0')
183 break;
184 else if (*commands == '-') {
185 commands++;
186 while (*commands && *commands != ' ')
187 process_switch(*commands++);
188 } else if (strlen(commands) >= 9
189 && !strncmp(commands, "kgdb=tty", 8)) {
190 switch (commands[8]) {
191 #ifdef CONFIG_SUN_SERIAL
192 case 'a':
193 boot_flags |= BOOTME_KGDBA;
194 prom_printf("KGDB: Using serial line /dev/ttya.\n");
195 break;
196 case 'b':
197 boot_flags |= BOOTME_KGDBB;
198 prom_printf("KGDB: Using serial line /dev/ttyb.\n");
199 break;
200 #endif
201 default:
202 printk("KGDB: Unknown tty line.\n");
203 break;
205 commands += 9;
206 } else {
207 #if CONFIG_SUN_CONSOLE
208 if (!strncmp(commands, "console=", 8)) {
209 commands += 8;
210 if (!strncmp (commands, "ttya", 4)) {
211 console_fb = 2;
212 prom_printf ("Using /dev/ttya as console.\n");
213 } else if (!strncmp (commands, "ttyb", 4)) {
214 console_fb = 3;
215 prom_printf ("Using /dev/ttyb as console.\n");
216 #if defined(CONFIG_PROM_CONSOLE)
217 } else if (!strncmp (commands, "prom", 4)) {
218 char *p;
220 for (p = commands - 8; *p && *p != ' '; p++)
221 *p = ' ';
222 conswitchp = &prom_con;
223 console_fb = 1;
224 #endif
225 } else {
226 console_fb = 1;
228 } else
229 #endif
230 if (!strncmp(commands, "mem=", 4)) {
232 * "mem=XXX[kKmM] overrides the PROM-reported
233 * memory size.
235 cmdline_memory_size = simple_strtoul(commands + 4,
236 &commands, 0);
237 if (*commands == 'K' || *commands == 'k') {
238 cmdline_memory_size <<= 10;
239 commands++;
240 } else if (*commands=='M' || *commands=='m') {
241 cmdline_memory_size <<= 20;
242 commands++;
245 while (*commands && *commands != ' ')
246 commands++;
251 /* This routine will in the future do all the nasty prom stuff
252 * to probe for the mmu type and its parameters, etc. This will
253 * also be where SMP things happen plus the Sparc specific memory
254 * physical memory probe as on the alpha.
257 extern int prom_probe_memory(void);
258 extern void sun4c_probe_vac(void);
259 extern char cputypval;
260 extern unsigned long start, end;
261 extern void panic_setup(char *, int *);
262 extern void srmmu_end_memory(unsigned long, unsigned long *);
263 extern void sun_serial_setup(void);
265 extern unsigned short root_flags;
266 extern unsigned short root_dev;
267 extern unsigned short ram_flags;
268 #define RAMDISK_IMAGE_START_MASK 0x07FF
269 #define RAMDISK_PROMPT_FLAG 0x8000
270 #define RAMDISK_LOAD_FLAG 0x4000
272 extern int root_mountflags;
274 char saved_command_line[256];
275 char reboot_command[256];
276 enum sparc_cpu sparc_cpu_model;
278 struct tt_entry *sparc_ttable;
280 struct pt_regs fake_swapper_regs = { 0, 0, 0, 0, { 0, } };
282 #ifdef PROM_DEBUG_CONSOLE
283 static void prom_cons_write(struct console *con, const char *str, unsigned count)
285 while (count--)
286 prom_printf("%c", *str++);
289 static struct console prom_console = {
290 name: "PROM",
291 write: prom_cons_write,
292 flags: CON_PRINTBUFFER,
294 #endif
296 extern void paging_init(void);
298 void __init setup_arch(char **cmdline_p)
300 int i;
301 unsigned long highest_paddr;
303 sparc_ttable = (struct tt_entry *) &start;
305 /* Initialize PROM console and command line. */
306 *cmdline_p = prom_getbootargs();
307 strcpy(saved_command_line, *cmdline_p);
309 /* Set sparc_cpu_model */
310 sparc_cpu_model = sun_unknown;
311 if(!strcmp(&cputypval,"sun4 ")) { sparc_cpu_model=sun4; }
312 if(!strcmp(&cputypval,"sun4c")) { sparc_cpu_model=sun4c; }
313 if(!strcmp(&cputypval,"sun4m")) { sparc_cpu_model=sun4m; }
314 if(!strcmp(&cputypval,"sun4s")) { sparc_cpu_model=sun4m; } /* CP-1200 with PROM 2.30 -E */
315 if(!strcmp(&cputypval,"sun4d")) { sparc_cpu_model=sun4d; }
316 if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; }
317 if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; }
319 #ifdef CONFIG_SUN4
320 if (sparc_cpu_model != sun4) {
321 prom_printf("This kernel is for Sun4 architecture only.\n");
322 prom_halt();
324 #endif
325 printk("ARCH: ");
326 switch(sparc_cpu_model) {
327 case sun4:
328 printk("SUN4\n");
329 break;
330 case sun4c:
331 printk("SUN4C\n");
332 break;
333 case sun4m:
334 printk("SUN4M\n");
335 break;
336 case sun4d:
337 printk("SUN4D\n");
338 break;
339 case sun4e:
340 printk("SUN4E\n");
341 break;
342 case sun4u:
343 printk("SUN4U\n");
344 break;
345 default:
346 printk("UNKNOWN!\n");
347 break;
349 #ifdef PROM_DEBUG_CONSOLE
350 register_console(&prom_console);
351 #endif
353 #ifdef CONFIG_DUMMY_CONSOLE
354 conswitchp = &dummy_con;
355 #elif defined(CONFIG_PROM_CONSOLE)
356 conswitchp = &prom_con;
357 #endif
358 boot_flags_init(*cmdline_p);
360 idprom_init();
361 if (ARCH_SUN4C_SUN4)
362 sun4c_probe_vac();
363 load_mmu();
364 (void) prom_probe_memory();
366 phys_base = 0xffffffffUL;
367 highest_paddr = 0UL;
368 for (i = 0; sp_banks[i].num_bytes != 0; i++) {
369 unsigned long top;
371 if (sp_banks[i].base_addr < phys_base)
372 phys_base = sp_banks[i].base_addr;
373 top = sp_banks[i].base_addr +
374 sp_banks[i].num_bytes;
375 if (highest_paddr < top)
376 highest_paddr = top;
379 if (!root_flags)
380 root_mountflags &= ~MS_RDONLY;
381 ROOT_DEV = to_kdev_t(root_dev);
382 #ifdef CONFIG_BLK_DEV_RAM
383 rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
384 rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
385 rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
386 #endif
388 prom_setsync(prom_sync_me);
391 #if !CONFIG_SUN_SERIAL
392 serial_console = 0;
393 #else
394 switch (console_fb) {
395 case 0: /* Let get our io devices from prom */
397 int idev = prom_query_input_device();
398 int odev = prom_query_output_device();
399 if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
400 serial_console = 0;
401 } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
402 serial_console = 1;
403 } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
404 serial_console = 2;
405 } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) {
406 prom_printf("MrCoffee ttya\n");
407 serial_console = 1;
408 } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) {
409 serial_console = 0;
410 prom_printf("MrCoffee keyboard\n");
411 } else {
412 prom_printf("Inconsistent or unknown console\n");
413 prom_printf("You cannot mix serial and non serial input/output devices\n");
414 prom_halt();
417 break;
418 case 1: serial_console = 0; break; /* Force one of the framebuffers as console */
419 case 2: serial_console = 1; break; /* Force ttya as console */
420 case 3: serial_console = 2; break; /* Force ttyb as console */
422 #endif
425 if ((boot_flags & BOOTME_KGDBA)) {
426 rs_kgdb_hook(0);
428 if ((boot_flags & BOOTME_KGDBB)) {
429 rs_kgdb_hook(1);
432 if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) &&
433 ((*(short *)linux_dbvec) != -1)) {
434 printk("Booted under KADB. Syncing trap table.\n");
435 (*(linux_dbvec->teach_debugger))();
437 if((boot_flags & BOOTME_KGDB)) {
438 set_debug_traps();
439 prom_printf ("Breakpoint!\n");
440 breakpoint();
443 /* Due to stack alignment restrictions and assumptions... */
444 init_mm.mmap->vm_page_prot = PAGE_SHARED;
445 init_mm.mmap->vm_start = PAGE_OFFSET;
446 init_mm.mmap->vm_end = PAGE_OFFSET + highest_paddr;
447 init_mm.context = (unsigned long) NO_CONTEXT;
448 init_task.thread.kregs = &fake_swapper_regs;
450 if (serial_console)
451 conswitchp = NULL;
453 paging_init();
456 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
458 return -EIO;
461 /* BUFFER is PAGE_SIZE bytes long. */
463 extern char *sparc_cpu_type[];
464 extern char *sparc_fpu_type[];
466 int get_cpuinfo(char *buffer)
468 int cpuid=hard_smp_processor_id();
469 int len;
471 len = sprintf(buffer, "cpu\t\t: %s\n"
472 "fpu\t\t: %s\n"
473 "promlib\t\t: Version %d Revision %d\n"
474 "prom\t\t: %d.%d\n"
475 "type\t\t: %s\n"
476 "ncpus probed\t: %d\n"
477 "ncpus active\t: %d\n"
478 #ifndef CONFIG_SMP
479 "BogoMips\t: %lu.%02lu\n"
480 #endif
482 sparc_cpu_type[cpuid] ? : "undetermined",
483 sparc_fpu_type[cpuid] ? : "undetermined",
484 romvec->pv_romvers, prom_rev, romvec->pv_printrev >> 16, (short)romvec->pv_printrev,
485 &cputypval,
486 linux_num_cpus, smp_num_cpus
487 #ifndef CONFIG_SMP
488 , loops_per_sec/500000, (loops_per_sec/5000) % 100
489 #endif
491 #ifdef CONFIG_SMP
492 len += smp_bogo_info(buffer + len);
493 #endif
494 len += mmu_info(buffer + len);
495 #ifdef CONFIG_SMP
496 len += smp_info(buffer + len);
497 #endif
498 return len;