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