linux/arch/sparc/kernel/setup.c
<<
>>
Prefs
   1/*  $Id: setup.c,v 1.126 2001/11/13 00:49:27 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@samba.org)
   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 <linux/initrd.h>
  17#include <asm/smp.h>
  18#include <linux/user.h>
  19#include <linux/a.out.h>
  20#include <linux/screen_info.h>
  21#include <linux/delay.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/interrupt.h>
  30#include <linux/console.h>
  31#include <linux/spinlock.h>
  32#include <linux/root_dev.h>
  33#include <linux/cpu.h>
  34#include <linux/kdebug.h>
  35
  36#include <asm/system.h>
  37#include <asm/io.h>
  38#include <asm/processor.h>
  39#include <asm/oplib.h>
  40#include <asm/page.h>
  41#include <asm/pgtable.h>
  42#include <asm/traps.h>
  43#include <asm/vaddrs.h>
  44#include <asm/mbus.h>
  45#include <asm/idprom.h>
  46#include <asm/machines.h>
  47#include <asm/cpudata.h>
  48#include <asm/setup.h>
  49
  50struct 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 */
  60};
  61
  62/* Typing sync at the prom prompt calls the function pointed to by
  63 * romvec->pv_synchook which I set to the following function.
  64 * This should sync all filesystems and return, for now it just
  65 * prints out pretty messages and returns.
  66 */
  67
  68extern unsigned long trapbase;
  69void (*prom_palette)(int);
  70
  71/* Pretty sick eh? */
  72void prom_sync_me(void)
  73{
  74        unsigned long prom_tbr, flags;
  75
  76        /* XXX Badly broken. FIX! - Anton */
  77        local_irq_save(flags);
  78        __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (prom_tbr));
  79        __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
  80                             "nop\n\t"
  81                             "nop\n\t"
  82                             "nop\n\t" : : "r" (&trapbase));
  83
  84        if (prom_palette)
  85                prom_palette(1);
  86        prom_printf("PROM SYNC COMMAND...\n");
  87        show_free_areas();
  88        if(current->pid != 0) {
  89                local_irq_enable();
  90                sys_sync();
  91                local_irq_disable();
  92        }
  93        prom_printf("Returning to prom\n");
  94
  95        __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
  96                             "nop\n\t"
  97                             "nop\n\t"
  98                             "nop\n\t" : : "r" (prom_tbr));
  99        local_irq_restore(flags);
 100
 101        return;
 102}
 103
 104unsigned int boot_flags __initdata = 0;
 105#define BOOTME_DEBUG  0x1
 106
 107/* Exported for mm/init.c:paging_init. */
 108unsigned long cmdline_memory_size __initdata = 0;
 109
 110static void
 111prom_console_write(struct console *con, const char *s, unsigned n)
 112{
 113        prom_write(s, n);
 114}
 115
 116static struct console prom_debug_console = {
 117        .name =         "debug",
 118        .write =        prom_console_write,
 119        .flags =        CON_PRINTBUFFER,
 120        .index =        -1,
 121};
 122
 123/* 
 124 * Process kernel command line switches that are specific to the
 125 * SPARC or that require special low-level processing.
 126 */
 127static void __init process_switch(char c)
 128{
 129        switch (c) {
 130        case 'd':
 131                boot_flags |= BOOTME_DEBUG;
 132                break;
 133        case 's':
 134                break;
 135        case 'h':
 136                prom_printf("boot_flags_init: Halt!\n");
 137                prom_halt();
 138                break;
 139        case 'p':
 140                /* Use PROM debug console. */
 141                register_console(&prom_debug_console);
 142                break;
 143        default:
 144                printk("Unknown boot switch (-%c)\n", c);
 145                break;
 146        }
 147}
 148
 149static void __init boot_flags_init(char *commands)
 150{
 151        while (*commands) {
 152                /* Move to the start of the next "argument". */
 153                while (*commands && *commands == ' ')
 154                        commands++;
 155
 156                /* Process any command switches, otherwise skip it. */
 157                if (*commands == '\0')
 158                        break;
 159                if (*commands == '-') {
 160                        commands++;
 161                        while (*commands && *commands != ' ')
 162                                process_switch(*commands++);
 163                        continue;
 164                }
 165                if (!strncmp(commands, "mem=", 4)) {
 166                        /*
 167                         * "mem=XXX[kKmM] overrides the PROM-reported
 168                         * memory size.
 169                         */
 170                        cmdline_memory_size = simple_strtoul(commands + 4,
 171                                                     &commands, 0);
 172                        if (*commands == 'K' || *commands == 'k') {
 173                                cmdline_memory_size <<= 10;
 174                                commands++;
 175                        } else if (*commands=='M' || *commands=='m') {
 176                                cmdline_memory_size <<= 20;
 177                                commands++;
 178                        }
 179                }
 180                while (*commands && *commands != ' ')
 181                        commands++;
 182        }
 183}
 184
 185/* This routine will in the future do all the nasty prom stuff
 186 * to probe for the mmu type and its parameters, etc. This will
 187 * also be where SMP things happen plus the Sparc specific memory
 188 * physical memory probe as on the alpha.
 189 */
 190
 191extern int prom_probe_memory(void);
 192extern void sun4c_probe_vac(void);
 193extern char cputypval;
 194extern unsigned long start, end;
 195extern void panic_setup(char *, int *);
 196
 197extern unsigned short root_flags;
 198extern unsigned short root_dev;
 199extern unsigned short ram_flags;
 200#define RAMDISK_IMAGE_START_MASK        0x07FF
 201#define RAMDISK_PROMPT_FLAG             0x8000
 202#define RAMDISK_LOAD_FLAG               0x4000
 203
 204extern int root_mountflags;
 205
 206char reboot_command[COMMAND_LINE_SIZE];
 207enum sparc_cpu sparc_cpu_model;
 208
 209struct tt_entry *sparc_ttable;
 210
 211struct pt_regs fake_swapper_regs;
 212
 213void __init setup_arch(char **cmdline_p)
 214{
 215        int i;
 216        unsigned long highest_paddr;
 217
 218        sparc_ttable = (struct tt_entry *) &start;
 219
 220        /* Initialize PROM console and command line. */
 221        *cmdline_p = prom_getbootargs();
 222        strcpy(boot_command_line, *cmdline_p);
 223
 224        /* Set sparc_cpu_model */
 225        sparc_cpu_model = sun_unknown;
 226        if(!strcmp(&cputypval,"sun4 ")) { sparc_cpu_model=sun4; }
 227        if(!strcmp(&cputypval,"sun4c")) { sparc_cpu_model=sun4c; }
 228        if(!strcmp(&cputypval,"sun4m")) { sparc_cpu_model=sun4m; }
 229        if(!strcmp(&cputypval,"sun4s")) { sparc_cpu_model=sun4m; }  /* CP-1200 with PROM 2.30 -E */
 230        if(!strcmp(&cputypval,"sun4d")) { sparc_cpu_model=sun4d; }
 231        if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; }
 232        if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; }
 233
 234#ifdef CONFIG_SUN4
 235        if (sparc_cpu_model != sun4) {
 236                prom_printf("This kernel is for Sun4 architecture only.\n");
 237                prom_halt();
 238        }
 239#endif
 240        printk("ARCH: ");
 241        switch(sparc_cpu_model) {
 242        case sun4:
 243                printk("SUN4\n");
 244                break;
 245        case sun4c:
 246                printk("SUN4C\n");
 247                break;
 248        case sun4m:
 249                printk("SUN4M\n");
 250                break;
 251        case sun4d:
 252                printk("SUN4D\n");
 253                break;
 254        case sun4e:
 255                printk("SUN4E\n");
 256                break;
 257        case sun4u:
 258                printk("SUN4U\n");
 259                break;
 260        default:
 261                printk("UNKNOWN!\n");
 262                break;
 263        };
 264
 265#ifdef CONFIG_DUMMY_CONSOLE
 266        conswitchp = &dummy_con;
 267#elif defined(CONFIG_PROM_CONSOLE)
 268        conswitchp = &prom_con;
 269#endif
 270        boot_flags_init(*cmdline_p);
 271
 272        idprom_init();
 273        if (ARCH_SUN4C_SUN4)
 274                sun4c_probe_vac();
 275        load_mmu();
 276        (void) prom_probe_memory();
 277
 278        phys_base = 0xffffffffUL;
 279        highest_paddr = 0UL;
 280        for (i = 0; sp_banks[i].num_bytes != 0; i++) {
 281                unsigned long top;
 282
 283                if (sp_banks[i].base_addr < phys_base)
 284                        phys_base = sp_banks[i].base_addr;
 285                top = sp_banks[i].base_addr +
 286                        sp_banks[i].num_bytes;
 287                if (highest_paddr < top)
 288                        highest_paddr = top;
 289        }
 290        pfn_base = phys_base >> PAGE_SHIFT;
 291
 292        if (!root_flags)
 293                root_mountflags &= ~MS_RDONLY;
 294        ROOT_DEV = old_decode_dev(root_dev);
 295#ifdef CONFIG_BLK_DEV_RAM
 296        rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
 297        rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
 298        rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);     
 299#endif
 300
 301        prom_setsync(prom_sync_me);
 302
 303        if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && 
 304           ((*(short *)linux_dbvec) != -1)) {
 305                printk("Booted under KADB. Syncing trap table.\n");
 306                (*(linux_dbvec->teach_debugger))();
 307        }
 308
 309        init_mm.context = (unsigned long) NO_CONTEXT;
 310        init_task.thread.kregs = &fake_swapper_regs;
 311
 312        paging_init();
 313
 314        smp_setup_cpu_possible_map();
 315}
 316
 317extern char *sparc_cpu_type;
 318extern char *sparc_fpu_type;
 319
 320static int ncpus_probed;
 321
 322static int show_cpuinfo(struct seq_file *m, void *__unused)
 323{
 324        seq_printf(m,
 325                   "cpu\t\t: %s\n"
 326                   "fpu\t\t: %s\n"
 327                   "promlib\t\t: Version %d Revision %d\n"
 328                   "prom\t\t: %d.%d\n"
 329                   "type\t\t: %s\n"
 330                   "ncpus probed\t: %d\n"
 331                   "ncpus active\t: %d\n"
 332#ifndef CONFIG_SMP
 333                   "CPU0Bogo\t: %lu.%02lu\n"
 334                   "CPU0ClkTck\t: %ld\n"
 335#endif
 336                   ,
 337                   sparc_cpu_type ? sparc_cpu_type : "undetermined",
 338                   sparc_fpu_type ? sparc_fpu_type : "undetermined",
 339                   romvec->pv_romvers,
 340                   prom_rev,
 341                   romvec->pv_printrev >> 16,
 342                   romvec->pv_printrev & 0xffff,
 343                   &cputypval,
 344                   ncpus_probed,
 345                   num_online_cpus()
 346#ifndef CONFIG_SMP
 347                   , cpu_data(0).udelay_val/(500000/HZ),
 348                   (cpu_data(0).udelay_val/(5000/HZ)) % 100,
 349                   cpu_data(0).clock_tick
 350#endif
 351                );
 352
 353#ifdef CONFIG_SMP
 354        smp_bogo(m);
 355#endif
 356        mmu_info(m);
 357#ifdef CONFIG_SMP
 358        smp_info(m);
 359#endif
 360        return 0;
 361}
 362
 363static void *c_start(struct seq_file *m, loff_t *pos)
 364{
 365        /* The pointer we are returning is arbitrary,
 366         * it just has to be non-NULL and not IS_ERR
 367         * in the success case.
 368         */
 369        return *pos == 0 ? &c_start : NULL;
 370}
 371
 372static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 373{
 374        ++*pos;
 375        return c_start(m, pos);
 376}
 377
 378static void c_stop(struct seq_file *m, void *v)
 379{
 380}
 381
 382const struct seq_operations cpuinfo_op = {
 383        .start =c_start,
 384        .next = c_next,
 385        .stop = c_stop,
 386        .show = show_cpuinfo,
 387};
 388
 389extern int stop_a_enabled;
 390
 391void sun_do_break(void)
 392{
 393        if (!stop_a_enabled)
 394                return;
 395
 396        printk("\n");
 397        flush_user_windows();
 398
 399        prom_cmdline();
 400}
 401
 402int stop_a_enabled = 1;
 403
 404static int __init topology_init(void)
 405{
 406        int i, ncpus, err;
 407
 408        /* Count the number of physically present processors in
 409         * the machine, even on uniprocessor, so that /proc/cpuinfo
 410         * output is consistent with 2.4.x
 411         */
 412        ncpus = 0;
 413        while (!cpu_find_by_instance(ncpus, NULL, NULL))
 414                ncpus++;
 415        ncpus_probed = ncpus;
 416
 417        err = 0;
 418        for_each_online_cpu(i) {
 419                struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
 420                if (!p)
 421                        err = -ENOMEM;
 422                else
 423                        register_cpu(p, i);
 424        }
 425
 426        return err;
 427}
 428
 429subsys_initcall(topology_init);
 430