~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/arch/sparc/kernel/setup.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*  $Id: setup.c,v 1.122 2001/01/01 01:46:15 davem Exp $
  2  *  linux/arch/sparc/kernel/setup.c
  3  *
  4  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
  5  *  Copyright (C) 2000  Anton Blanchard (anton@linuxcare.com)
  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/malloc.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/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/interrupt.h>
 29 #include <linux/console.h>
 30 #include <linux/spinlock.h>
 31 
 32 #include <asm/segment.h>
 33 #include <asm/system.h>
 34 #include <asm/io.h>
 35 #include <asm/kgdb.h>
 36 #include <asm/processor.h>
 37 #include <asm/oplib.h>
 38 #include <asm/page.h>
 39 #include <asm/pgtable.h>
 40 #include <asm/traps.h>
 41 #include <asm/vaddrs.h>
 42 #include <asm/kdebug.h>
 43 #include <asm/mbus.h>
 44 #include <asm/idprom.h>
 45 #include <asm/softirq.h>
 46 #include <asm/hardirq.h>
 47 #include <asm/machines.h>
 48 
 49 #undef PROM_DEBUG_CONSOLE
 50 
 51 struct screen_info screen_info = {
 52         0, 0,                   /* orig-x, orig-y */
 53         0,                      /* unused */
 54         0,                      /* orig-video-page */
 55         0,                      /* orig-video-mode */
 56         128,                    /* orig-video-cols */
 57         0,0,0,                  /* ega_ax, ega_bx, ega_cx */
 58         54,                     /* orig-video-lines */
 59         0,                      /* orig-video-isVGA */
 60         16                      /* orig-video-points */
 61 };
 62 
 63 /* Typing sync at the prom prompt calls the function pointed to by
 64  * romvec->pv_synchook which I set to the following function.
 65  * This should sync all filesystems and return, for now it just
 66  * prints out pretty messages and returns.
 67  */
 68 
 69 extern unsigned long trapbase;
 70 extern int serial_console;
 71 extern void breakpoint(void);
 72 #if CONFIG_SUN_CONSOLE
 73 void (*prom_palette)(int);
 74 #endif
 75 asmlinkage void sys_sync(void); /* it's really int */
 76 
 77 /* Pretty sick eh? */
 78 void prom_sync_me(void)
 79 {
 80         unsigned long prom_tbr, flags;
 81 
 82         /* XXX Badly broken. FIX! - Anton */
 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));
 89 
 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();
100         }
101         prom_printf("Returning to prom\n");
102 
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);
108 
109         return;
110 }
111 
112 extern void rs_kgdb_hook(int tty_num); /* sparc/serial.c */
113 
114 unsigned int boot_flags __initdata = 0;
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
120 
121 #ifdef CONFIG_SUN_CONSOLE
122 static int console_fb __initdata = 0;
123 #endif
124 
125 /* Exported for mm/init.c:paging_init. */
126 unsigned long cmdline_memory_size __initdata = 0;
127 
128 void kernel_enter_debugger(void)
129 {
130         if (boot_flags & BOOTME_KGDB) {
131                 printk("KGDB: Entered\n");
132                 breakpoint();
133         }
134 }
135 
136 int obp_system_intr(void)
137 {
138         if (boot_flags & BOOTME_KGDB) {
139                 printk("KGDB: system interrupted\n");
140                 breakpoint();
141                 return 1;
142         }
143         if (boot_flags & BOOTME_DEBUG) {
144                 printk("OBP: system interrupted\n");
145                 prom_halt();
146                 return 1;
147         }
148         return 0;
149 }
150 
151 /* 
152  * Process kernel command line switches that are specific to the
153  * SPARC or that require special low-level processing.
154  */
155 static void __init process_switch(char c)
156 {
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                 prom_halt();
167                 break;
168         default:
169                 printk("Unknown boot switch (-%c)\n", c);
170                 break;
171         }
172 }
173 
174 static void __init boot_flags_init(char *commands)
175 {
176         while (*commands) {
177                 /* Move to the start of the next "argument". */
178                 while (*commands && *commands == ' ')
179                         commands++;
180 
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;
204                         }
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;
219                                         
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;
227                                 }
228                         } else
229 #endif
230                         if (!strncmp(commands, "mem=", 4)) {
231                                 /*
232                                  * "mem=XXX[kKmM] overrides the PROM-reported
233                                  * memory size.
234                                  */
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++;
243                                 }
244                         }
245                         while (*commands && *commands != ' ')
246                                 commands++;
247                 }
248         }
249 }
250 
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.
255  */
256 
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);
264 
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
271 
272 extern int root_mountflags;
273 
274 char saved_command_line[256];
275 char reboot_command[256];
276 enum sparc_cpu sparc_cpu_model;
277 
278 struct tt_entry *sparc_ttable;
279 
280 struct pt_regs fake_swapper_regs;
281 
282 #ifdef PROM_DEBUG_CONSOLE
283 static void
284 prom_console_write(struct console *con, const char *s, unsigned n)
285 {
286         prom_printf("%s", s);
287 }
288 
289 static struct console prom_console = {
290         name:           "debug",
291         write:          prom_console_write,
292         flags:          CON_PRINTBUFFER,
293         index:          -1,
294 };
295 #endif
296 
297 extern void paging_init(void);
298 
299 void __init setup_arch(char **cmdline_p)
300 {
301         int i;
302         unsigned long highest_paddr;
303 
304         sparc_ttable = (struct tt_entry *) &start;
305 
306         /* Initialize PROM console and command line. */
307         *cmdline_p = prom_getbootargs();
308         strcpy(saved_command_line, *cmdline_p);
309 
310         /* Set sparc_cpu_model */
311         sparc_cpu_model = sun_unknown;
312         if(!strcmp(&cputypval,"sun4 ")) { sparc_cpu_model=sun4; }
313         if(!strcmp(&cputypval,"sun4c")) { sparc_cpu_model=sun4c; }
314         if(!strcmp(&cputypval,"sun4m")) { sparc_cpu_model=sun4m; }
315         if(!strcmp(&cputypval,"sun4s")) { sparc_cpu_model=sun4m; }  /* CP-1200 with PROM 2.30 -E */
316         if(!strcmp(&cputypval,"sun4d")) { sparc_cpu_model=sun4d; }
317         if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; }
318         if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; }
319 
320 #ifdef CONFIG_SUN4
321         if (sparc_cpu_model != sun4) {
322                 prom_printf("This kernel is for Sun4 architecture only.\n");
323                 prom_halt();
324         }
325 #endif
326         printk("ARCH: ");
327         switch(sparc_cpu_model) {
328         case sun4:
329                 printk("SUN4\n");
330                 break;
331         case sun4c:
332                 printk("SUN4C\n");
333                 break;
334         case sun4m:
335                 printk("SUN4M\n");
336                 break;
337         case sun4d:
338                 printk("SUN4D\n");
339                 break;
340         case sun4e:
341                 printk("SUN4E\n");
342                 break;
343         case sun4u:
344                 printk("SUN4U\n");
345                 break;
346         default:
347                 printk("UNKNOWN!\n");
348                 break;
349         };
350 #ifdef PROM_DEBUG_CONSOLE
351         register_console(&prom_console);
352 #endif
353 
354 #ifdef CONFIG_DUMMY_CONSOLE
355         conswitchp = &dummy_con;
356 #elif defined(CONFIG_PROM_CONSOLE)
357         conswitchp = &prom_con;
358 #endif
359         boot_flags_init(*cmdline_p);
360 
361         idprom_init();
362         if (ARCH_SUN4C_SUN4)
363                 sun4c_probe_vac();
364         load_mmu();
365         (void) prom_probe_memory();
366 
367         phys_base = 0xffffffffUL;
368         highest_paddr = 0UL;
369         for (i = 0; sp_banks[i].num_bytes != 0; i++) {
370                 unsigned long top;
371 
372                 if (sp_banks[i].base_addr < phys_base)
373                         phys_base = sp_banks[i].base_addr;
374                 top = sp_banks[i].base_addr +
375                         sp_banks[i].num_bytes;
376                 if (highest_paddr < top)
377                         highest_paddr = top;
378         }
379 
380         if (!root_flags)
381                 root_mountflags &= ~MS_RDONLY;
382         ROOT_DEV = to_kdev_t(root_dev);
383 #ifdef CONFIG_BLK_DEV_RAM
384         rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
385         rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
386         rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);     
387 #endif
388 
389         prom_setsync(prom_sync_me);
390 
391         {
392 #if !CONFIG_SUN_SERIAL
393                 serial_console = 0;
394 #else
395                 switch (console_fb) {
396                 case 0: /* Let get our io devices from prom */
397                         {
398                                 int idev = prom_query_input_device();
399                                 int odev = prom_query_output_device();
400                                 if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
401                                         serial_console = 0;
402                                 } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
403                                         serial_console = 1;
404                                 } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
405                                         serial_console = 2;
406                                 } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) {
407                                         prom_printf("MrCoffee ttya\n");
408                                         serial_console = 1;
409                                 } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) {
410                                         serial_console = 0;
411                                         prom_printf("MrCoffee keyboard\n");
412                                 } else {
413                                         prom_printf("Inconsistent or unknown console\n");
414                                         prom_printf("You cannot mix serial and non serial input/output devices\n");
415                                         prom_halt();
416                                 }
417                         }
418                         break;
419                 case 1: serial_console = 0; break; /* Force one of the framebuffers as console */
420                 case 2: serial_console = 1; break; /* Force ttya as console */
421                 case 3: serial_console = 2; break; /* Force ttyb as console */
422                 }
423 #endif
424         }
425 
426         if ((boot_flags & BOOTME_KGDBA)) {
427                 rs_kgdb_hook(0);
428         }
429         if ((boot_flags & BOOTME_KGDBB)) {
430                 rs_kgdb_hook(1);
431         }
432 
433         if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && 
434            ((*(short *)linux_dbvec) != -1)) {
435                 printk("Booted under KADB. Syncing trap table.\n");
436                 (*(linux_dbvec->teach_debugger))();
437         }
438         if((boot_flags & BOOTME_KGDB)) {
439                 set_debug_traps();
440                 prom_printf ("Breakpoint!\n");
441                 breakpoint();
442         }
443 
444         /* Due to stack alignment restrictions and assumptions... */
445         init_mm.mmap->vm_page_prot = PAGE_SHARED;
446         init_mm.mmap->vm_start = PAGE_OFFSET;
447         init_mm.mmap->vm_end = PAGE_OFFSET + highest_paddr;
448         init_mm.context = (unsigned long) NO_CONTEXT;
449         init_task.thread.kregs = &fake_swapper_regs;
450 
451         if (serial_console)
452                 conswitchp = NULL;
453 
454         paging_init();
455 }
456 
457 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
458 {
459         return -EIO;
460 }
461 
462 /* BUFFER is PAGE_SIZE bytes long. */
463 
464 extern char *sparc_cpu_type[];
465 extern char *sparc_fpu_type[];
466 
467 int get_cpuinfo(char *buffer)
468 {
469         int cpuid=hard_smp_processor_id();
470         int len;
471 
472         len = sprintf(buffer, "cpu\t\t: %s\n"
473             "fpu\t\t: %s\n"
474             "promlib\t\t: Version %d Revision %d\n"
475             "prom\t\t: %d.%d\n"
476             "type\t\t: %s\n"
477             "ncpus probed\t: %d\n"
478             "ncpus active\t: %d\n"
479 #ifndef CONFIG_SMP
480             "BogoMips\t: %lu.%02lu\n"
481 #endif
482             ,
483             sparc_cpu_type[cpuid] ? : "undetermined",
484             sparc_fpu_type[cpuid] ? : "undetermined",
485             romvec->pv_romvers, prom_rev, romvec->pv_printrev >> 16, (short)romvec->pv_printrev,
486             &cputypval,
487             linux_num_cpus, smp_num_cpus
488 #ifndef CONFIG_SMP
489             , loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ)) % 100
490 #endif
491             );
492 #ifdef CONFIG_SMP
493         len += smp_bogo_info(buffer + len);
494 #endif
495         len += mmu_info(buffer + len);
496 #ifdef CONFIG_SMP
497         len += smp_info(buffer + len);
498 #endif
499         return len;
500 }
501 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.